src/work/athos/mincostflow.h
author marci
Fri, 21 May 2004 10:57:30 +0000
changeset 655 a9878222d5c8
parent 635 933f593824c2
child 657 531fc5f575ef
permissions -rw-r--r--
bug correction in BidirGraphWrapper<Graph> default constructor
athos@610
     1
// -*- c++ -*-
athos@633
     2
#ifndef HUGO_MINCOSTFLOW_H
athos@633
     3
#define HUGO_MINCOSTFLOW_H
athos@610
     4
athos@610
     5
///\ingroup galgs
athos@610
     6
///\file
athos@645
     7
///\brief An algorithm for finding the minimum cost flow of given value in an uncapacitated network
athos@611
     8
athos@610
     9
#include <hugo/dijkstra.h>
athos@610
    10
#include <hugo/graph_wrapper.h>
athos@610
    11
#include <hugo/maps.h>
athos@610
    12
#include <vector>
athos@610
    13
#include <for_each_macros.h>
athos@610
    14
athos@610
    15
namespace hugo {
athos@610
    16
athos@610
    17
/// \addtogroup galgs
athos@610
    18
/// @{
athos@610
    19
athos@645
    20
  ///\brief Implementation of an algorithm for finding the minimum cost flow 
athos@645
    21
  /// of given value in an uncapacitated network
athos@610
    22
  /// 
athos@610
    23
  ///
athos@633
    24
  /// The class \ref hugo::MinCostFlow "MinCostFlow" implements
athos@633
    25
  /// an algorithm for solving the following general minimum cost flow problem>
athos@633
    26
  /// 
athos@633
    27
  ///
athos@633
    28
  ///
athos@633
    29
  /// \warning It is assumed here that the problem has a feasible solution
athos@633
    30
  ///
athos@610
    31
  /// The range of the length (weight) function is nonnegative reals but 
athos@610
    32
  /// the range of capacity function is the set of nonnegative integers. 
athos@610
    33
  /// It is not a polinomial time algorithm for counting the minimum cost
athos@610
    34
  /// maximal flow, since it counts the minimum cost flow for every value 0..M
athos@610
    35
  /// where \c M is the value of the maximal flow.
athos@610
    36
  ///
athos@610
    37
  ///\author Attila Bernath
athos@635
    38
  template <typename Graph, typename LengthMap, typename SupplyDemandMap>
athos@633
    39
  class MinCostFlow {
athos@610
    40
athos@610
    41
    typedef typename LengthMap::ValueType Length;
athos@610
    42
athos@633
    43
athos@635
    44
    typedef typename SupplyDemandMap::ValueType SupplyDemand;
athos@610
    45
    
athos@610
    46
    typedef typename Graph::Node Node;
athos@610
    47
    typedef typename Graph::NodeIt NodeIt;
athos@610
    48
    typedef typename Graph::Edge Edge;
athos@610
    49
    typedef typename Graph::OutEdgeIt OutEdgeIt;
athos@610
    50
    typedef typename Graph::template EdgeMap<int> EdgeIntMap;
athos@610
    51
athos@610
    52
    //    typedef ConstMap<Edge,int> ConstMap;
athos@610
    53
athos@610
    54
    typedef ResGraphWrapper<const Graph,int,CapacityMap,EdgeIntMap> ResGraphType;
athos@610
    55
    typedef typename ResGraphType::Edge ResGraphEdge;
athos@610
    56
athos@610
    57
    class ModLengthMap {   
athos@610
    58
      //typedef typename ResGraphType::template NodeMap<Length> NodeMap;
athos@610
    59
      typedef typename Graph::template NodeMap<Length> NodeMap;
athos@610
    60
      const ResGraphType& G;
athos@610
    61
      //      const EdgeIntMap& rev;
athos@610
    62
      const LengthMap &ol;
athos@610
    63
      const NodeMap &pot;
athos@610
    64
    public :
athos@610
    65
      typedef typename LengthMap::KeyType KeyType;
athos@610
    66
      typedef typename LengthMap::ValueType ValueType;
athos@610
    67
	
athos@610
    68
      ValueType operator[](typename ResGraphType::Edge e) const {     
athos@610
    69
	if (G.forward(e))
athos@610
    70
	  return  ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
athos@610
    71
	else
athos@610
    72
	  return -ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
athos@610
    73
      }     
athos@610
    74
	
athos@610
    75
      ModLengthMap(const ResGraphType& _G,
athos@610
    76
		   const LengthMap &o,  const NodeMap &p) : 
athos@610
    77
	G(_G), /*rev(_rev),*/ ol(o), pot(p){}; 
athos@610
    78
    };//ModLengthMap
athos@610
    79
athos@610
    80
athos@610
    81
  protected:
athos@610
    82
    
athos@610
    83
    //Input
athos@610
    84
    const Graph& G;
athos@610
    85
    const LengthMap& length;
athos@635
    86
    const SupplyDemandMap& supply_demand;//supply or demand of nodes
athos@610
    87
athos@610
    88
athos@610
    89
    //auxiliary variables
athos@610
    90
athos@610
    91
    //To store the flow
athos@610
    92
    EdgeIntMap flow; 
athos@610
    93
    //To store the potentila (dual variables)
athos@610
    94
    typename Graph::template NodeMap<Length> potential;
athos@633
    95
    //To store excess-deficit values
athos@635
    96
    SupplyDemandMap excess_deficit;
athos@610
    97
    
athos@610
    98
athos@610
    99
    Length total_length;
athos@610
   100
athos@610
   101
athos@610
   102
  public :
athos@610
   103
athos@610
   104
athos@635
   105
    MinCostFlow(Graph& _G, LengthMap& _length, SupplyDemandMap& _supply_demand) : G(_G), 
athos@635
   106
      length(_length), supply_demand(_supply_demand), flow(_G), potential(_G){ }
athos@610
   107
athos@610
   108
    
athos@610
   109
    ///Runs the algorithm.
athos@610
   110
athos@610
   111
    ///Runs the algorithm.
athos@635
   112
athos@610
   113
    ///\todo May be it does make sense to be able to start with a nonzero 
athos@610
   114
    /// feasible primal-dual solution pair as well.
athos@633
   115
    int run() {
athos@610
   116
athos@610
   117
      //Resetting variables from previous runs
athos@635
   118
      //total_length = 0;
athos@635
   119
athos@635
   120
      typedef typename Graph::template NodeMap<int> HeapMap;
athos@635
   121
      typedef Heap<Node, SupplyDemand, typename Graph::template NodeMap<int>,
athos@635
   122
	std::greater<SupplyDemand> > 	HeapType;
athos@635
   123
athos@635
   124
      //A heap for the excess nodes
athos@635
   125
      HeapMap excess_nodes_map(G,-1);
athos@635
   126
      HeapType excess_nodes(excess_nodes_map);
athos@635
   127
athos@635
   128
      //A heap for the deficit nodes
athos@635
   129
      HeapMap deficit_nodes_map(G,-1);
athos@635
   130
      HeapType deficit_nodes(deficit_nodes_map);
athos@635
   131
athos@610
   132
      
athos@610
   133
      FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
athos@610
   134
	flow.set(e,0);
athos@610
   135
      }
athos@633
   136
athos@633
   137
      //Initial value for delta
athos@635
   138
      SupplyDemand delta = 0;
athos@635
   139
athos@610
   140
      FOR_EACH_LOC(typename Graph::NodeIt, n, G){
athos@635
   141
       	excess_deficit.set(n,supply_demand[n]);
athos@635
   142
	//A supply node
athos@635
   143
	if (excess_deficit[n] > 0){
athos@635
   144
	  excess_nodes.push(n,excess_deficit[n]);
athos@633
   145
	}
athos@635
   146
	//A demand node
athos@635
   147
	if (excess_deficit[n] < 0){
athos@635
   148
	  deficit_nodes.push(n, - excess_deficit[n]);
athos@635
   149
	}
athos@635
   150
	//Finding out starting value of delta
athos@635
   151
	if (delta < abs(excess_deficit[n])){
athos@635
   152
	  delta = abs(excess_deficit[n]);
athos@635
   153
	}
athos@633
   154
	//Initialize the copy of the Dijkstra potential to zero
athos@610
   155
	potential.set(n,0);
athos@610
   156
      }
athos@610
   157
athos@635
   158
      //It'll be allright as an initial value, though this value 
athos@635
   159
      //can be the maximum deficit here
athos@635
   160
      SupplyDemand max_excess = delta;
athos@610
   161
      
athos@633
   162
      //We need a residual graph which is uncapacitated
athos@633
   163
      ResGraphType res_graph(G, flow);
athos@610
   164
athos@633
   165
athos@610
   166
      
athos@610
   167
      ModLengthMap mod_length(res_graph, length, potential);
athos@610
   168
athos@610
   169
      Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length);
athos@610
   170
athos@633
   171
athos@635
   172
      while (max_excess > 0){
athos@635
   173
athos@645
   174
	/*
athos@645
   175
	 * Beginning of the delta scaling phase 
athos@645
   176
	*/
athos@610
   177
	
athos@635
   178
	//Merge and stuff
athos@635
   179
athos@635
   180
	Node s = excess_nodes.top(); 
athos@635
   181
	SupplyDemand max_excess = excess_nodes[s];
athos@635
   182
	Node t = deficit_nodes.top(); 
athos@635
   183
	if (max_excess < dificit_nodes[t]){
athos@635
   184
	  max_excess = dificit_nodes[t];
athos@635
   185
	}
athos@635
   186
athos@635
   187
athos@645
   188
	while(max_excess > 0){
athos@635
   189
athos@635
   190
	  
athos@635
   191
	  //s es t valasztasa
athos@635
   192
athos@635
   193
	  //Dijkstra part	
athos@635
   194
	  dijkstra.run(s);
athos@635
   195
athos@635
   196
	  /*We know from theory that t can be reached
athos@635
   197
	  if (!dijkstra.reached(t)){
athos@635
   198
	    //There are no k paths from s to t
athos@635
   199
	    break;
athos@635
   200
	  };
athos@635
   201
	  */
athos@635
   202
	  
athos@635
   203
	  //We have to change the potential
athos@635
   204
	  FOR_EACH_LOC(typename ResGraphType::NodeIt, n, res_graph){
athos@635
   205
	    potential[n] += dijkstra.distMap()[n];
athos@635
   206
	  }
athos@635
   207
athos@635
   208
athos@635
   209
	  //Augmenting on the sortest path
athos@635
   210
	  Node n=t;
athos@635
   211
	  ResGraphEdge e;
athos@635
   212
	  while (n!=s){
athos@635
   213
	    e = dijkstra.pred(n);
athos@635
   214
	    n = dijkstra.predNode(n);
athos@635
   215
	    res_graph.augment(e,delta);
athos@635
   216
	    /*
athos@635
   217
	    //Let's update the total length
athos@635
   218
	    if (res_graph.forward(e))
athos@635
   219
	      total_length += length[e];
athos@635
   220
	    else 
athos@635
   221
	      total_length -= length[e];	    
athos@635
   222
	    */
athos@635
   223
	  }
athos@635
   224
athos@635
   225
	  //Update the excess_nodes heap
athos@635
   226
	  if (delta >= excess_nodes[s]){
athos@635
   227
	    if (delta > excess_nodes[s])
athos@635
   228
	      deficit_nodes.push(s,delta - excess_nodes[s]);
athos@635
   229
	    excess_nodes.pop();
athos@635
   230
	    
athos@635
   231
	  } 
athos@635
   232
	  else{
athos@635
   233
	    excess_nodes[s] -= delta;
athos@635
   234
	  }
athos@635
   235
	  //Update the deficit_nodes heap
athos@635
   236
	  if (delta >= deficit_nodes[t]){
athos@635
   237
	    if (delta > deficit_nodes[t])
athos@635
   238
	      excess_nodes.push(t,delta - deficit_nodes[t]);
athos@635
   239
	    deficit_nodes.pop();
athos@635
   240
	    
athos@635
   241
	  } 
athos@635
   242
	  else{
athos@635
   243
	    deficit_nodes[t] -= delta;
athos@635
   244
	  }
athos@635
   245
	  //Dijkstra part ends here
athos@633
   246
	}
athos@633
   247
athos@633
   248
	/*
athos@635
   249
	 * End of the delta scaling phase 
athos@635
   250
	*/
athos@633
   251
athos@635
   252
	//Whatever this means
athos@635
   253
	delta = delta / 2;
athos@635
   254
athos@635
   255
	/*This is not necessary here
athos@635
   256
	//Update the max_excess
athos@635
   257
	max_excess = 0;
athos@635
   258
	FOR_EACH_LOC(typename Graph::NodeIt, n, G){
athos@635
   259
	  if (max_excess < excess_deficit[n]){
athos@635
   260
	    max_excess = excess_deficit[n];
athos@610
   261
	  }
athos@610
   262
	}
athos@633
   263
	*/
athos@635
   264
	//Reset delta if still too big
athos@635
   265
	if (8*number_of_nodes*max_excess <= delta){
athos@635
   266
	  delta = max_excess;
athos@635
   267
	  
athos@610
   268
	}
athos@610
   269
	  
athos@635
   270
      }//while(max_excess > 0)
athos@610
   271
      
athos@610
   272
athos@610
   273
      return i;
athos@610
   274
    }
athos@610
   275
athos@610
   276
athos@610
   277
athos@610
   278
athos@610
   279
    ///This function gives back the total length of the found paths.
athos@610
   280
    ///Assumes that \c run() has been run and nothing changed since then.
athos@610
   281
    Length totalLength(){
athos@610
   282
      return total_length;
athos@610
   283
    }
athos@610
   284
athos@610
   285
    ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
athos@610
   286
    ///be called before using this function.
athos@610
   287
    const EdgeIntMap &getFlow() const { return flow;}
athos@610
   288
athos@610
   289
  ///Returns a const reference to the NodeMap \c potential (the dual solution).
athos@610
   290
    /// \pre \ref run() must be called before using this function.
athos@610
   291
    const EdgeIntMap &getPotential() const { return potential;}
athos@610
   292
athos@610
   293
    ///This function checks, whether the given solution is optimal
athos@610
   294
    ///Running after a \c run() should return with true
athos@610
   295
    ///In this "state of the art" this only check optimality, doesn't bother with feasibility
athos@610
   296
    ///
athos@610
   297
    ///\todo Is this OK here?
athos@610
   298
    bool checkComplementarySlackness(){
athos@610
   299
      Length mod_pot;
athos@610
   300
      Length fl_e;
athos@610
   301
      FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
athos@610
   302
	//C^{\Pi}_{i,j}
athos@610
   303
	mod_pot = length[e]-potential[G.head(e)]+potential[G.tail(e)];
athos@610
   304
	fl_e = flow[e];
athos@610
   305
	//	std::cout << fl_e << std::endl;
athos@610
   306
	if (0<fl_e && fl_e<capacity[e]){
athos@610
   307
	  if (mod_pot != 0)
athos@610
   308
	    return false;
athos@610
   309
	}
athos@610
   310
	else{
athos@610
   311
	  if (mod_pot > 0 && fl_e != 0)
athos@610
   312
	    return false;
athos@610
   313
	  if (mod_pot < 0 && fl_e != capacity[e])
athos@610
   314
	    return false;
athos@610
   315
	}
athos@610
   316
      }
athos@610
   317
      return true;
athos@610
   318
    }
athos@610
   319
    
athos@610
   320
athos@633
   321
  }; //class MinCostFlow
athos@610
   322
athos@610
   323
  ///@}
athos@610
   324
athos@610
   325
} //namespace hugo
athos@610
   326
athos@610
   327
#endif //HUGO_MINCOSTFLOW_H