src/work/athos/mincostflow.h
author marci
Tue, 25 May 2004 13:13:52 +0000
changeset 660 edb42cb9d352
parent 657 531fc5f575ef
child 661 d306e777117e
permissions -rw-r--r--
ResCap, a map for the residual capacity in ResGraphWrapper
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@657
    13
#include <list>
athos@610
    14
#include <for_each_macros.h>
athos@657
    15
#include <hugo/union_find.h>
athos@610
    16
athos@610
    17
namespace hugo {
athos@610
    18
athos@610
    19
/// \addtogroup galgs
athos@610
    20
/// @{
athos@610
    21
athos@645
    22
  ///\brief Implementation of an algorithm for finding the minimum cost flow 
athos@645
    23
  /// of given value in an uncapacitated network
athos@610
    24
  /// 
athos@610
    25
  ///
athos@633
    26
  /// The class \ref hugo::MinCostFlow "MinCostFlow" implements
athos@633
    27
  /// an algorithm for solving the following general minimum cost flow problem>
athos@633
    28
  /// 
athos@633
    29
  ///
athos@633
    30
  ///
athos@633
    31
  /// \warning It is assumed here that the problem has a feasible solution
athos@633
    32
  ///
athos@610
    33
  /// The range of the length (weight) function is nonnegative reals but 
athos@610
    34
  /// the range of capacity function is the set of nonnegative integers. 
athos@610
    35
  /// It is not a polinomial time algorithm for counting the minimum cost
athos@610
    36
  /// maximal flow, since it counts the minimum cost flow for every value 0..M
athos@610
    37
  /// where \c M is the value of the maximal flow.
athos@610
    38
  ///
athos@610
    39
  ///\author Attila Bernath
athos@635
    40
  template <typename Graph, typename LengthMap, typename SupplyDemandMap>
athos@633
    41
  class MinCostFlow {
athos@610
    42
athos@610
    43
    typedef typename LengthMap::ValueType Length;
athos@610
    44
athos@633
    45
athos@635
    46
    typedef typename SupplyDemandMap::ValueType SupplyDemand;
athos@610
    47
    
athos@610
    48
    typedef typename Graph::Node Node;
athos@610
    49
    typedef typename Graph::NodeIt NodeIt;
athos@610
    50
    typedef typename Graph::Edge Edge;
athos@610
    51
    typedef typename Graph::OutEdgeIt OutEdgeIt;
athos@610
    52
    typedef typename Graph::template EdgeMap<int> EdgeIntMap;
athos@610
    53
athos@610
    54
    //    typedef ConstMap<Edge,int> ConstMap;
athos@610
    55
athos@610
    56
    typedef ResGraphWrapper<const Graph,int,CapacityMap,EdgeIntMap> ResGraphType;
athos@610
    57
    typedef typename ResGraphType::Edge ResGraphEdge;
athos@610
    58
athos@610
    59
    class ModLengthMap {   
athos@610
    60
      //typedef typename ResGraphType::template NodeMap<Length> NodeMap;
athos@610
    61
      typedef typename Graph::template NodeMap<Length> NodeMap;
athos@659
    62
      const ResGraphType& res_graph;
athos@610
    63
      //      const EdgeIntMap& rev;
athos@610
    64
      const LengthMap &ol;
athos@610
    65
      const NodeMap &pot;
athos@610
    66
    public :
athos@610
    67
      typedef typename LengthMap::KeyType KeyType;
athos@610
    68
      typedef typename LengthMap::ValueType ValueType;
athos@610
    69
	
athos@610
    70
      ValueType operator[](typename ResGraphType::Edge e) const {     
athos@659
    71
	if (res_graph.forward(e))
athos@659
    72
	  return  ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
athos@610
    73
	else
athos@659
    74
	  return -ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
athos@610
    75
      }     
athos@610
    76
	
athos@659
    77
      ModLengthMap(const ResGraphType& _res_graph,
athos@610
    78
		   const LengthMap &o,  const NodeMap &p) : 
athos@659
    79
	res_graph(_res_graph), /*rev(_rev),*/ ol(o), pot(p){}; 
athos@610
    80
    };//ModLengthMap
athos@610
    81
athos@610
    82
athos@610
    83
  protected:
athos@610
    84
    
athos@610
    85
    //Input
athos@659
    86
    const Graph& graph;
athos@610
    87
    const LengthMap& length;
athos@635
    88
    const SupplyDemandMap& supply_demand;//supply or demand of nodes
athos@610
    89
athos@610
    90
athos@610
    91
    //auxiliary variables
athos@610
    92
athos@610
    93
    //To store the flow
athos@610
    94
    EdgeIntMap flow; 
athos@610
    95
    //To store the potentila (dual variables)
athos@610
    96
    typename Graph::template NodeMap<Length> potential;
athos@633
    97
    //To store excess-deficit values
athos@635
    98
    SupplyDemandMap excess_deficit;
athos@610
    99
    
athos@610
   100
athos@610
   101
    Length total_length;
athos@610
   102
athos@610
   103
athos@610
   104
  public :
athos@610
   105
athos@610
   106
athos@659
   107
    MinCostFlow(Graph& _graph, LengthMap& _length, SupplyDemandMap& _supply_demand) : graph(_graph), 
athos@659
   108
      length(_length), supply_demand(_supply_demand), flow(_graph), potential(_graph){ }
athos@610
   109
athos@610
   110
    
athos@610
   111
    ///Runs the algorithm.
athos@610
   112
athos@610
   113
    ///Runs the algorithm.
athos@635
   114
athos@610
   115
    ///\todo May be it does make sense to be able to start with a nonzero 
athos@610
   116
    /// feasible primal-dual solution pair as well.
athos@659
   117
    void run() {
athos@610
   118
athos@610
   119
      //Resetting variables from previous runs
athos@635
   120
      //total_length = 0;
athos@635
   121
athos@635
   122
      typedef typename Graph::template NodeMap<int> HeapMap;
athos@657
   123
      typedef Heap< Node, SupplyDemand, typename Graph::template NodeMap<int>,
athos@635
   124
	std::greater<SupplyDemand> > 	HeapType;
athos@635
   125
athos@635
   126
      //A heap for the excess nodes
athos@659
   127
      HeapMap excess_nodes_map(graph,-1);
athos@635
   128
      HeapType excess_nodes(excess_nodes_map);
athos@635
   129
athos@635
   130
      //A heap for the deficit nodes
athos@659
   131
      HeapMap deficit_nodes_map(graph,-1);
athos@635
   132
      HeapType deficit_nodes(deficit_nodes_map);
athos@635
   133
athos@657
   134
      //A container to store nonabundant arcs
athos@657
   135
      list<Edge> nonabundant_arcs;
athos@659
   136
athos@659
   137
	
athos@659
   138
      FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@610
   139
	flow.set(e,0);
athos@657
   140
	nonabundant_arcs.push_back(e);
athos@610
   141
      }
athos@633
   142
athos@633
   143
      //Initial value for delta
athos@635
   144
      SupplyDemand delta = 0;
athos@635
   145
athos@657
   146
      typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
athos@657
   147
athos@657
   148
      //A union-find structure to store the abundant components
athos@659
   149
      UFE::MapType abund_comp_map(graph);
athos@657
   150
      UFE abundant_components(abund_comp_map);
athos@657
   151
athos@657
   152
athos@657
   153
athos@659
   154
      FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@635
   155
       	excess_deficit.set(n,supply_demand[n]);
athos@635
   156
	//A supply node
athos@635
   157
	if (excess_deficit[n] > 0){
athos@635
   158
	  excess_nodes.push(n,excess_deficit[n]);
athos@633
   159
	}
athos@635
   160
	//A demand node
athos@635
   161
	if (excess_deficit[n] < 0){
athos@635
   162
	  deficit_nodes.push(n, - excess_deficit[n]);
athos@635
   163
	}
athos@635
   164
	//Finding out starting value of delta
athos@635
   165
	if (delta < abs(excess_deficit[n])){
athos@635
   166
	  delta = abs(excess_deficit[n]);
athos@635
   167
	}
athos@633
   168
	//Initialize the copy of the Dijkstra potential to zero
athos@610
   169
	potential.set(n,0);
athos@657
   170
	//Every single point is an abundant component initially 
athos@657
   171
	abundant_components.insert(n);
athos@610
   172
      }
athos@610
   173
athos@635
   174
      //It'll be allright as an initial value, though this value 
athos@635
   175
      //can be the maximum deficit here
athos@635
   176
      SupplyDemand max_excess = delta;
athos@610
   177
      
athos@659
   178
      //ConstMap<Edge,SupplyDemand> ConstEdgeMap;
athos@659
   179
athos@633
   180
      //We need a residual graph which is uncapacitated
athos@659
   181
      ResGraphType res_graph(graph, flow);
athos@659
   182
      
athos@659
   183
      //An EdgeMap to tell which arcs are abundant
athos@659
   184
      template typename Graph::EdgeMap<bool> abundant_arcs(graph);
athos@610
   185
athos@659
   186
      //Let's construct the sugraph consisting only of the abundant edges
athos@659
   187
      typedef ConstMap< typename Graph::Node, bool > ConstNodeMap;
athos@659
   188
      ConstNodeMap const_true_map(true);
athos@659
   189
      typedef SubGraphWrapper< Graph, ConstNodeMap, 
athos@659
   190
	 template typename Graph::EdgeMap<bool> > 
athos@659
   191
	AbundantGraph;
athos@659
   192
      AbundantGraph abundant_graph(graph, const_true_map, abundant_arcs );
athos@659
   193
      
athos@659
   194
      //Let's construct the residual graph for the abundant graph
athos@659
   195
      typedef ResGraphWrapper<const AbundantGraph,int,CapacityMap,EdgeIntMap> 
athos@659
   196
	ResAbGraph;
athos@659
   197
      //Again uncapacitated
athos@659
   198
      ResAbGraph res_ab_graph(abundant_graph, flow);
athos@659
   199
      
athos@659
   200
      //We need things for the bfs
athos@659
   201
      typename ResAbGraph::NodeMap<bool> bfs_reached(res_ab_graph);
athos@659
   202
      typename ResAbGraph::NodeMap<typename ResAbGraph::Edge> 
athos@659
   203
	bfs_pred(res_ab_graph); 
athos@659
   204
      NullMap<typename ResAbGraph::Node, int> bfs_dist_dummy(res_ab_graph);
athos@659
   205
      //We want to run bfs-es (more) on this graph 'res_ab_graph'
athos@659
   206
      Bfs < ResAbGraph , 
athos@659
   207
	typename ResAbGraph::NodeMap<bool>, 
athos@659
   208
	typename ResAbGraph::NodeMap<typename ResAbGraph::Edge>,
athos@659
   209
	NullMap<typename ResAbGraph::Node, int> > 
athos@659
   210
	bfs(res_ab_graph, bfs_reached, bfs_pred, bfs_dist_dummy);
athos@610
   211
      
athos@610
   212
      ModLengthMap mod_length(res_graph, length, potential);
athos@610
   213
athos@610
   214
      Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length);
athos@610
   215
athos@633
   216
athos@635
   217
      while (max_excess > 0){
athos@635
   218
athos@657
   219
	//Reset delta if still too big
athos@657
   220
	if (8*number_of_nodes*max_excess <= delta){
athos@657
   221
	  delta = max_excess;
athos@657
   222
	  
athos@657
   223
	}
athos@657
   224
athos@645
   225
	/*
athos@645
   226
	 * Beginning of the delta scaling phase 
athos@645
   227
	*/
athos@635
   228
	//Merge and stuff
athos@657
   229
	{
athos@657
   230
	  SupplyDemand buf=8*number_of_nodes*delta;
athos@657
   231
	  list<Edge>::iterator i = nonabundant_arcs.begin();
athos@657
   232
	  while ( i != nonabundant_arcs.end() ){
athos@657
   233
	    if (flow[i]>=buf){
athos@657
   234
	      Node a = abundant_components.find(res_graph.head(i));
athos@657
   235
	      Node b = abundant_components.find(res_graph.tail(i));
athos@657
   236
	      //Merge
athos@657
   237
	      if (a != b){
athos@657
   238
		abundant_components.join(a,b);
athos@659
   239
		//We want to push the smaller
athos@659
   240
		//Which has greater absolut value excess/deficit
athos@659
   241
		Node root=(abs(excess_deficit[a])>abs(excess_deficit[b]))?a:b;
athos@659
   242
		//Which is the other
athos@659
   243
		Node non_root = ( a == root ) ? b : a ;
athos@659
   244
		abundant_components.makeRep(root);
athos@659
   245
		SupplyDemand qty_to_augment = abs(excess_deficit[non_root]); 
athos@659
   246
		//Push the positive value
athos@659
   247
		if (excess_deficit[non_root] < 0)
athos@659
   248
		  swap(root, non_root);
athos@659
   249
		//If the non_root node has excess/deficit at all
athos@659
   250
		if (qty_to_augment>0){
athos@659
   251
		  //Find path and augment
athos@659
   252
		  bfs.run(non_root);
athos@659
   253
		  //root should be reached
athos@659
   254
		  
athos@659
   255
		  //Augmenting on the found path
athos@659
   256
		  Node n=root;
athos@659
   257
		  ResGraphEdge e;
athos@659
   258
		  while (n!=non_root){
athos@659
   259
		    e = bfs_pred(n);
athos@659
   260
		    n = res_graph.tail(e);
athos@659
   261
		    res_graph.augment(e,qty_to_augment);
athos@659
   262
		  }
athos@659
   263
	  
athos@659
   264
		  //We know that non_root had positive excess
athos@659
   265
		  excess_nodes[non_root] -= qty_to_augment;
athos@659
   266
		  //But what about root node
athos@659
   267
		  //It might have been positive and so became larger
athos@659
   268
		  if (excess_deficit[root]>0){
athos@659
   269
		    excess_nodes[root] += qty_to_augment;
athos@659
   270
		  }
athos@659
   271
		  else{
athos@659
   272
		    //Or negative but not turned into positive
athos@659
   273
		    deficit_nodes[root] -= qty_to_augment;
athos@659
   274
		  }
athos@659
   275
athos@659
   276
		  //Update the excess_deficit map
athos@659
   277
		  excess_deficit[non_root] -= qty_to_augment;
athos@659
   278
		  excess_deficit[root] += qty_to_augment;
athos@659
   279
athos@659
   280
		  
athos@659
   281
		}
athos@657
   282
	      }
athos@657
   283
	      //What happens to i?
athos@659
   284
	      //Marci and Zsolt says I shouldn't do such things
athos@659
   285
	      nonabundant_arcs.erase(i++);
athos@659
   286
	      abundant_arcs[i] = true;
athos@657
   287
	    }
athos@657
   288
	    else
athos@657
   289
	      ++i;
athos@657
   290
	  }
athos@657
   291
	}
athos@657
   292
athos@635
   293
athos@635
   294
	Node s = excess_nodes.top(); 
athos@635
   295
	SupplyDemand max_excess = excess_nodes[s];
athos@635
   296
	Node t = deficit_nodes.top(); 
athos@659
   297
	if (max_excess < deficit_nodes[t]){
athos@659
   298
	  max_excess = deficit_nodes[t];
athos@635
   299
	}
athos@635
   300
athos@635
   301
athos@659
   302
	while(max_excess > (n-1)*delta/n){
athos@659
   303
	  
athos@635
   304
	  
athos@635
   305
	  //s es t valasztasa
athos@659
   306
	  
athos@635
   307
	  //Dijkstra part	
athos@635
   308
	  dijkstra.run(s);
athos@659
   309
	  
athos@635
   310
	  /*We know from theory that t can be reached
athos@635
   311
	  if (!dijkstra.reached(t)){
athos@635
   312
	    //There are no k paths from s to t
athos@635
   313
	    break;
athos@635
   314
	  };
athos@635
   315
	  */
athos@635
   316
	  
athos@635
   317
	  //We have to change the potential
athos@635
   318
	  FOR_EACH_LOC(typename ResGraphType::NodeIt, n, res_graph){
athos@635
   319
	    potential[n] += dijkstra.distMap()[n];
athos@635
   320
	  }
athos@635
   321
athos@635
   322
athos@635
   323
	  //Augmenting on the sortest path
athos@635
   324
	  Node n=t;
athos@635
   325
	  ResGraphEdge e;
athos@635
   326
	  while (n!=s){
athos@635
   327
	    e = dijkstra.pred(n);
athos@635
   328
	    n = dijkstra.predNode(n);
athos@635
   329
	    res_graph.augment(e,delta);
athos@635
   330
	    /*
athos@635
   331
	    //Let's update the total length
athos@635
   332
	    if (res_graph.forward(e))
athos@635
   333
	      total_length += length[e];
athos@635
   334
	    else 
athos@635
   335
	      total_length -= length[e];	    
athos@635
   336
	    */
athos@635
   337
	  }
athos@659
   338
	  
athos@659
   339
	  //Update the excess_deficit map
athos@659
   340
	  excess_deficit[s] -= delta;
athos@659
   341
	  excess_deficit[t] += delta;
athos@659
   342
	  
athos@635
   343
athos@635
   344
	  //Update the excess_nodes heap
athos@635
   345
	  if (delta >= excess_nodes[s]){
athos@635
   346
	    if (delta > excess_nodes[s])
athos@635
   347
	      deficit_nodes.push(s,delta - excess_nodes[s]);
athos@635
   348
	    excess_nodes.pop();
athos@635
   349
	    
athos@635
   350
	  } 
athos@635
   351
	  else{
athos@635
   352
	    excess_nodes[s] -= delta;
athos@635
   353
	  }
athos@635
   354
	  //Update the deficit_nodes heap
athos@635
   355
	  if (delta >= deficit_nodes[t]){
athos@635
   356
	    if (delta > deficit_nodes[t])
athos@635
   357
	      excess_nodes.push(t,delta - deficit_nodes[t]);
athos@635
   358
	    deficit_nodes.pop();
athos@635
   359
	    
athos@635
   360
	  } 
athos@635
   361
	  else{
athos@635
   362
	    deficit_nodes[t] -= delta;
athos@635
   363
	  }
athos@635
   364
	  //Dijkstra part ends here
athos@659
   365
	  
athos@659
   366
	  //Choose s and t again
athos@659
   367
	  s = excess_nodes.top(); 
athos@659
   368
	  max_excess = excess_nodes[s];
athos@659
   369
	  t = deficit_nodes.top(); 
athos@659
   370
	  if (max_excess < deficit_nodes[t]){
athos@659
   371
	    max_excess = deficit_nodes[t];
athos@659
   372
	  }
athos@659
   373
athos@633
   374
	}
athos@633
   375
athos@633
   376
	/*
athos@635
   377
	 * End of the delta scaling phase 
athos@635
   378
	*/
athos@633
   379
athos@635
   380
	//Whatever this means
athos@635
   381
	delta = delta / 2;
athos@635
   382
athos@635
   383
	/*This is not necessary here
athos@635
   384
	//Update the max_excess
athos@635
   385
	max_excess = 0;
athos@659
   386
	FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@635
   387
	  if (max_excess < excess_deficit[n]){
athos@635
   388
	    max_excess = excess_deficit[n];
athos@610
   389
	  }
athos@610
   390
	}
athos@633
   391
	*/
athos@657
   392
athos@610
   393
	  
athos@635
   394
      }//while(max_excess > 0)
athos@610
   395
      
athos@610
   396
athos@610
   397
      return i;
athos@610
   398
    }
athos@610
   399
athos@610
   400
athos@610
   401
athos@610
   402
athos@610
   403
    ///This function gives back the total length of the found paths.
athos@610
   404
    ///Assumes that \c run() has been run and nothing changed since then.
athos@610
   405
    Length totalLength(){
athos@610
   406
      return total_length;
athos@610
   407
    }
athos@610
   408
athos@610
   409
    ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
athos@610
   410
    ///be called before using this function.
athos@610
   411
    const EdgeIntMap &getFlow() const { return flow;}
athos@610
   412
athos@610
   413
  ///Returns a const reference to the NodeMap \c potential (the dual solution).
athos@610
   414
    /// \pre \ref run() must be called before using this function.
athos@610
   415
    const EdgeIntMap &getPotential() const { return potential;}
athos@610
   416
athos@610
   417
    ///This function checks, whether the given solution is optimal
athos@610
   418
    ///Running after a \c run() should return with true
athos@610
   419
    ///In this "state of the art" this only check optimality, doesn't bother with feasibility
athos@610
   420
    ///
athos@610
   421
    ///\todo Is this OK here?
athos@610
   422
    bool checkComplementarySlackness(){
athos@610
   423
      Length mod_pot;
athos@610
   424
      Length fl_e;
athos@659
   425
      FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@610
   426
	//C^{\Pi}_{i,j}
athos@659
   427
	mod_pot = length[e]-potential[graph.head(e)]+potential[graph.tail(e)];
athos@610
   428
	fl_e = flow[e];
athos@610
   429
	//	std::cout << fl_e << std::endl;
athos@610
   430
	if (0<fl_e && fl_e<capacity[e]){
athos@610
   431
	  if (mod_pot != 0)
athos@610
   432
	    return false;
athos@610
   433
	}
athos@610
   434
	else{
athos@610
   435
	  if (mod_pot > 0 && fl_e != 0)
athos@610
   436
	    return false;
athos@610
   437
	  if (mod_pot < 0 && fl_e != capacity[e])
athos@610
   438
	    return false;
athos@610
   439
	}
athos@610
   440
      }
athos@610
   441
      return true;
athos@610
   442
    }
athos@610
   443
    
athos@610
   444
athos@633
   445
  }; //class MinCostFlow
athos@610
   446
athos@610
   447
  ///@}
athos@610
   448
athos@610
   449
} //namespace hugo
athos@610
   450
athos@610
   451
#endif //HUGO_MINCOSTFLOW_H