src/work/athos/preflow_push.hh
author alpar
Tue, 20 Jul 2004 09:52:03 +0000
changeset 712 6f1abe741fb6
parent 331 f5461f8bc59b
permissions -rw-r--r--
src/becnhmark gets in the distro.
I hope it works well.
athos@331
     1
#ifndef HUGO_PREFLOW_PUSH_HH
athos@331
     2
#define HUGO_PREFLOW_PUSH_HH
athos@36
     3
athos@331
     4
//#include <algorithm>
athos@36
     5
#include <list>
athos@36
     6
#include <vector>
athos@331
     7
#include <queue>
athos@36
     8
//#include "pf_hiba.hh"
athos@36
     9
//#include <marci_list_graph.hh>
athos@77
    10
//#include <marci_graph_traits.hh>
athos@331
    11
#include <invalid.h>
athos@331
    12
#include <graph_wrapper.h>
athos@331
    13
//#include <reverse_bfs.hh>
athos@36
    14
athos@36
    15
using namespace std;
athos@36
    16
alpar@105
    17
namespace hugo {
athos@36
    18
athos@331
    19
  template <typename Graph, typename T>
athos@36
    20
  class preflow_push {
athos@36
    21
athos@331
    22
    //Useful typedefs
athos@331
    23
    typedef typename Graph::Node Node;
athos@331
    24
    typedef typename Graph::NodeIt NodeIt;
athos@331
    25
    typedef typename Graph::Edge Edge;
athos@331
    26
    typedef typename Graph::OutEdgeIt OutEdgeIt;
athos@331
    27
    typedef typename Graph::InEdgeIt InEdgeIt;
athos@505
    28
    typedef typename Graph::EdgeMap<T> CapacityType;
athos@505
    29
athos@505
    30
    typedef ResGraphWrapper<const Graph,int,CapacityType,CapacityType> ResGraphType;
athos@77
    31
athos@77
    32
athos@36
    33
    //---------------------------------------------
athos@36
    34
    //Parameters of the algorithm
athos@36
    35
    //---------------------------------------------
athos@36
    36
    //Fully examine an active node until excess becomes 0
athos@36
    37
    enum node_examination_t {examine_full, examine_to_relabel};
athos@36
    38
    //No more implemented yet:, examine_only_one_edge};
athos@36
    39
    node_examination_t node_examination;
athos@36
    40
    //Which implementation to be used
athos@36
    41
    enum implementation_t {impl_fifo, impl_highest_label};
athos@36
    42
    //No more implemented yet:};
athos@36
    43
    implementation_t implementation;
athos@36
    44
    //---------------------------------------------
athos@36
    45
    //Parameters of the algorithm
athos@36
    46
    //---------------------------------------------
athos@36
    47
 
athos@36
    48
  private:
athos@36
    49
    //input
athos@331
    50
    Graph& G;
athos@331
    51
    Node s;
athos@331
    52
    Node t;
athos@505
    53
    CapacityType &capacity;
athos@331
    54
athos@36
    55
    //output
athos@505
    56
    CapacityType preflow;
athos@36
    57
    T maxflow_value;
athos@36
    58
  
athos@36
    59
    //auxiliary variables for computation
athos@331
    60
    //The number of the nodes
athos@36
    61
    int number_of_nodes;
athos@331
    62
    //A nodemap for the level
athos@331
    63
    typename Graph::NodeMap<int> level;
athos@331
    64
    //A nodemap for the excess
athos@331
    65
    typename Graph::NodeMap<T> excess;
athos@36
    66
    
athos@36
    67
    //Number of nodes on each level
athos@36
    68
    vector<int> num_of_nodes_on_level;
athos@36
    69
    
athos@36
    70
    //For the FIFO implementation
athos@331
    71
    list<Node> fifo_nodes;
athos@36
    72
    //For 'highest label' implementation
athos@36
    73
    int highest_active;
athos@36
    74
    //int second_highest_active;
athos@331
    75
    vector< list<Node> > active_nodes;
athos@36
    76
athos@36
    77
  public:
athos@36
    78
  
athos@36
    79
    //Constructing the object using the graph, source, sink and capacity vector
athos@36
    80
    preflow_push(
athos@331
    81
		      Graph& _G, 
athos@331
    82
		      Node _s, 
athos@331
    83
		      Node _t, 
athos@331
    84
		      typename Graph::EdgeMap<T> & _capacity)
athos@36
    85
      : G(_G), s(_s), t(_t), 
athos@36
    86
	capacity(_capacity), 
athos@36
    87
	preflow(_G),
athos@36
    88
	//Counting the number of nodes
athos@77
    89
	//number_of_nodes(count(G.first<EachNodeIt>())),
athos@77
    90
	number_of_nodes(G.nodeNum()),
athos@77
    91
athos@36
    92
	level(_G),
athos@36
    93
	excess(_G)//,
athos@36
    94
        // Default constructor: active_nodes()
athos@36
    95
    { 
athos@36
    96
      //Simplest parameter settings
athos@36
    97
      node_examination = examine_full;//examine_to_relabel;//
athos@36
    98
      //Which implementation to be usedexamine_full
athos@36
    99
      implementation = impl_highest_label;//impl_fifo;
athos@36
   100
 
athos@36
   101
      //
athos@36
   102
      num_of_nodes_on_level.resize(2*number_of_nodes-1);
athos@36
   103
      num_of_nodes_on_level.clear();
athos@36
   104
athos@36
   105
      switch(implementation){
athos@36
   106
      case impl_highest_label :{
athos@331
   107
	active_nodes.clear();
athos@36
   108
	active_nodes.resize(2*number_of_nodes-1);
athos@331
   109
	
athos@36
   110
	break;
athos@36
   111
      }
athos@36
   112
      default:
athos@36
   113
	break;
athos@36
   114
      }
athos@36
   115
athos@36
   116
    }
athos@36
   117
athos@36
   118
    //Returns the value of a maximal flow 
athos@36
   119
    T run();
athos@36
   120
  
athos@331
   121
    typename Graph::EdgeMap<T>  getmaxflow(){
athos@36
   122
      return preflow;
athos@36
   123
    }
athos@36
   124
athos@36
   125
athos@36
   126
  private:
athos@36
   127
    //For testing purposes only
athos@36
   128
    //Lists the node_properties
athos@331
   129
    void write_property_vector(typename Graph::NodeMap<T> a,
athos@331
   130
			       //node_property_vector<Graph, T> a, 
athos@36
   131
			       char* prop_name="property"){
athos@331
   132
      for(NodeIt i=G.template first<NodeIt>(); G.valid(i); G.next(i)) {
athos@331
   133
	cout<<"Node id.: "<<G.id(i)<<", "<<prop_name<<" value: "<<a[i]<<endl;
athos@36
   134
      }
athos@36
   135
      cout<<endl;
athos@36
   136
    }
athos@505
   137
    /*
athos@36
   138
    //Modifies the excess of the node and makes sufficient changes
athos@331
   139
    void modify_excess(const Node& a ,T v){
athos@331
   140
      //T old_value=excess[a];
athos@331
   141
      excess[a] += v;
athos@36
   142
    }
athos@36
   143
  
athos@36
   144
    //This private procedure is supposed to modify the preflow on edge j
athos@36
   145
    //by value v (which can be positive or negative as well) 
athos@36
   146
    //and maintain the excess on the head and tail
athos@36
   147
    //Here we do not check whether this is possible or not
athos@331
   148
    void modify_preflow(Edge j, const T& v){
athos@36
   149
athos@36
   150
      //Modifiyng the edge
athos@331
   151
      preflow[j] += v;
athos@36
   152
athos@36
   153
athos@36
   154
      //Modifiyng the head
athos@36
   155
      modify_excess(G.head(j),v);
athos@36
   156
	
athos@36
   157
      //Modifiyng the tail
athos@36
   158
      modify_excess(G.tail(j),-v);
athos@36
   159
athos@36
   160
    }
athos@505
   161
    */
athos@36
   162
    //Gives the active node to work with 
athos@36
   163
    //(depending on the implementation to be used)
athos@331
   164
    Node get_active_node(){
athos@119
   165
      
athos@36
   166
athos@36
   167
      switch(implementation) {
athos@36
   168
      case impl_highest_label : {
athos@36
   169
athos@331
   170
	//First need to find the highest label for which there's an active node
athos@36
   171
	while( highest_active>=0 && active_nodes[highest_active].empty() ){ 
athos@36
   172
	  --highest_active;
athos@36
   173
	}
athos@36
   174
athos@36
   175
	if( highest_active>=0) {
athos@119
   176
	  
athos@119
   177
athos@331
   178
	  Node a=active_nodes[highest_active].front();
athos@36
   179
	  active_nodes[highest_active].pop_front();
athos@119
   180
	  
athos@36
   181
	  return a;
athos@36
   182
	}
athos@36
   183
	else {
athos@331
   184
	  return INVALID;
athos@36
   185
	}
athos@36
   186
	
athos@36
   187
	break;
athos@36
   188
	
athos@36
   189
      }
athos@36
   190
      case impl_fifo : {
athos@36
   191
athos@36
   192
	if( ! fifo_nodes.empty() ) {
athos@331
   193
	  Node a=fifo_nodes.front();
athos@36
   194
	  fifo_nodes.pop_front();
athos@36
   195
	  return a;
athos@36
   196
	}
athos@36
   197
	else {
athos@331
   198
	  return INVALID;
athos@36
   199
	}
athos@36
   200
	break;
athos@36
   201
      }
athos@36
   202
      }
athos@36
   203
      //
athos@331
   204
      return INVALID;
athos@36
   205
    }
athos@36
   206
athos@36
   207
    //Puts node 'a' among the active nodes
athos@331
   208
    void make_active(const Node& a){
athos@36
   209
      //s and t never become active
athos@36
   210
      if (a!=s && a!= t){
athos@36
   211
	switch(implementation){
athos@36
   212
	case impl_highest_label :
athos@331
   213
	  active_nodes[level[a]].push_back(a);
athos@36
   214
	  break;
athos@36
   215
	case impl_fifo :
athos@36
   216
	  fifo_nodes.push_back(a);
athos@36
   217
	  break;
athos@36
   218
	}
athos@36
   219
athos@36
   220
      }
athos@36
   221
athos@36
   222
      //Update highest_active label
athos@331
   223
      if (highest_active<level[a]){
athos@331
   224
	highest_active=level[a];
athos@36
   225
      }
athos@36
   226
athos@36
   227
    }
athos@36
   228
athos@36
   229
    //Changes the level of node a and make sufficent changes
athos@331
   230
    void change_level_to(Node a, int new_value){
athos@331
   231
      int seged = level[a];
athos@77
   232
      level.set(a,new_value);
athos@36
   233
      --num_of_nodes_on_level[seged];
athos@36
   234
      ++num_of_nodes_on_level[new_value];
athos@36
   235
    }
athos@36
   236
athos@36
   237
    //Collection of things useful (or necessary) to do before running
athos@77
   238
athos@36
   239
    void preprocess(){
athos@36
   240
athos@36
   241
      //---------------------------------------
athos@36
   242
      //Initialize parameters
athos@36
   243
      //---------------------------------------
athos@36
   244
athos@36
   245
      //Setting starting preflow, level and excess values to zero
athos@36
   246
      //This can be important, if the algorithm is run more then once
athos@331
   247
      for(NodeIt i=G.template first<NodeIt>(); G.valid(i); G.next(i)) {
athos@77
   248
        level.set(i,0);
athos@77
   249
        excess.set(i,0);
athos@331
   250
	for(OutEdgeIt j=G.template first<OutEdgeIt>(i); G.valid(j); G.next(j)) 
athos@77
   251
	  preflow.set(j, 0);
athos@36
   252
      }
athos@36
   253
      num_of_nodes_on_level[0]=number_of_nodes;
athos@36
   254
      highest_active=0;
athos@36
   255
      //---------------------------------------
athos@36
   256
      //Initialize parameters
athos@36
   257
      //---------------------------------------
athos@36
   258
athos@36
   259
      
athos@36
   260
      //------------------------------------
athos@36
   261
      //This is the only part that uses BFS
athos@36
   262
      //------------------------------------
athos@331
   263
athos@331
   264
      /*Reverse_bfs from t, to find the starting level.*/
athos@331
   265
      //Copyright: Jacint
athos@331
   266
      change_level_to(t,0);
athos@331
   267
athos@331
   268
      std::queue<Node> bfs_queue;
athos@331
   269
      bfs_queue.push(t);
athos@331
   270
athos@331
   271
      while (!bfs_queue.empty()) {
athos@331
   272
athos@331
   273
	Node v=bfs_queue.front();	
athos@331
   274
	bfs_queue.pop();
athos@331
   275
	int l=level[v]+1;
athos@331
   276
athos@331
   277
	InEdgeIt e;
athos@331
   278
	for(G.first(e,v); G.valid(e); G.next(e)) {
athos@331
   279
	  Node w=G.tail(e);
athos@331
   280
	  if ( level[w] == number_of_nodes && w != s ) {
athos@331
   281
	    bfs_queue.push(w);
athos@331
   282
	    //Node first=level_list[l];
athos@331
   283
	    //if ( G.valid(first) ) left.set(first,w);
athos@331
   284
	    //right.set(w,first);
athos@331
   285
	    //level_list[l]=w;
athos@331
   286
	    change_level_to(w, l);
athos@331
   287
	    //level.set(w, l);
athos@331
   288
	  }
athos@331
   289
	}
athos@331
   290
      }
athos@331
   291
      change_level_to(s,number_of_nodes);
athos@331
   292
      //level.set(s,number_of_nodes);
athos@331
   293
athos@331
   294
      /*
athos@36
   295
      //Setting starting level values using reverse bfs
athos@331
   296
      reverse_bfs<Graph> rev_bfs(G,t);
athos@36
   297
      rev_bfs.run();
athos@36
   298
      //write_property_vector(rev_bfs.dist,"rev_bfs");
athos@331
   299
      for(NodeIt i=G.template first<NodeIt>(); G.valid(i); G.next(i)) {
athos@36
   300
        change_level_to(i,rev_bfs.dist(i));
athos@36
   301
	//level.put(i,rev_bfs.dist.get(i));
athos@36
   302
      }
athos@331
   303
      */
athos@36
   304
      //------------------------------------
athos@36
   305
      //This is the only part that uses BFS
athos@36
   306
      //------------------------------------
athos@36
   307
      
athos@36
   308
      
athos@36
   309
      //Starting level of s
athos@36
   310
      change_level_to(s,number_of_nodes);
athos@36
   311
      //level.put(s,number_of_nodes);
athos@36
   312
      
athos@36
   313
      
athos@36
   314
      //we push as much preflow from s as possible to start with
athos@331
   315
      for(OutEdgeIt j=G.template first<OutEdgeIt>(s); G.valid(j); G.next(j)){ 
athos@331
   316
	modify_preflow(j,capacity[j] );
athos@36
   317
	make_active(G.head(j));
athos@331
   318
	int lev=level[G.head(j)];
athos@36
   319
	if(highest_active<lev){
athos@36
   320
	  highest_active=lev;
athos@36
   321
	}
athos@36
   322
      }
athos@36
   323
      //cout<<highest_active<<endl;
athos@36
   324
    } 
athos@36
   325
athos@36
   326
    
athos@36
   327
    //If the preflow is less than the capacity on the given edge
athos@36
   328
    //then it is an edge in the residual graph
athos@331
   329
    bool is_admissible_forward_edge(Edge j, int& new_level){
athos@119
   330
athos@331
   331
      if (capacity[j]>preflow[j]){
athos@331
   332
	if(level[G.tail(j)]==level[G.head(j)]+1){
athos@36
   333
	  return true;
athos@36
   334
	}
athos@36
   335
	else{
athos@331
   336
	  if (level[G.head(j)] < new_level)
athos@331
   337
	    new_level=level[G.head(j)];
athos@36
   338
	}
athos@36
   339
      }
athos@36
   340
      return false;
athos@36
   341
    }
athos@36
   342
athos@36
   343
    //If the preflow is greater than 0 on the given edge
athos@36
   344
    //then the edge reversd is an edge in the residual graph
athos@331
   345
    bool is_admissible_backward_edge(Edge j, int& new_level){
athos@119
   346
      
athos@331
   347
      if (0<preflow[j]){
athos@331
   348
	if(level[G.tail(j)]==level[G.head(j)]-1){
athos@119
   349
	 
athos@36
   350
	  return true;
athos@36
   351
	}
athos@36
   352
	else{
athos@331
   353
	  if (level[G.tail(j)] < new_level)
athos@331
   354
	    new_level=level[G.tail(j)];
athos@36
   355
	}
athos@36
   356
	
athos@36
   357
      }
athos@36
   358
      return false;
athos@36
   359
    }
athos@36
   360
athos@36
   361
 
athos@36
   362
  };  //class preflow_push  
athos@36
   363
athos@331
   364
  template<typename Graph, typename T>
athos@331
   365
    T preflow_push<Graph, T>::run() {
athos@331
   366
    
athos@331
   367
    //We need a residual graph
athos@331
   368
    ResGraphType res_graph(G, preflow, capacity);
athos@36
   369
    
athos@36
   370
    preprocess();
athos@119
   371
    //write_property_vector(level,"level");
athos@36
   372
    T e,v;
athos@331
   373
    Node a;
athos@331
   374
    while (a=get_active_node(), G.valid(a)){
athos@119
   375
      
athos@331
   376
      bool go_to_next_node=false;
athos@331
   377
      e = excess[a];
athos@331
   378
      while (!go_to_next_node){
athos@36
   379
athos@77
   380
	//Initial value for the new level for the active node we are dealing with
athos@77
   381
	int new_level=2*number_of_nodes;
athos@331
   382
athos@331
   383
athos@36
   384
	//Out edges from node a
athos@36
   385
	{
athos@505
   386
	  ResGraphType::OutEdgeIt j=res_graph.first(j,a);
athos@505
   387
	  while (res_graph.valid(j) && e){
athos@505
   388
	    if (is_admissible_forward_edge(j,new_level)){
athos@505
   389
	      v=min(e,res_graph.resCap(j));
athos@505
   390
	      e -= v;
athos@505
   391
	      //New node might become active
athos@505
   392
	      if (excess[res_graph.head(j)]==0){
athos@505
   393
		make_active(res_graph.head(j));
athos@505
   394
	      }
athos@505
   395
	      res_graph.augment(j,v);
athos@505
   396
	      excess[res_graph.tail(j)] -= v;
athos@505
   397
	      excess[res_graph.head(j)] += v;
athos@505
   398
	    }
athos@505
   399
	    res_graph.next(j);
athos@505
   400
	  }
athos@505
   401
	}
athos@505
   402
athos@505
   403
	/*
athos@505
   404
	//Out edges from node a
athos@505
   405
	{
athos@77
   406
	  OutEdgeIt j=G.template first<OutEdgeIt>(a);
athos@331
   407
	  while (G.valid(j) && e){
athos@36
   408
athos@36
   409
	    if (is_admissible_forward_edge(j,new_level)){
athos@331
   410
	      v=min(e,capacity[j] - preflow[j]);
athos@36
   411
	      e -= v;
athos@36
   412
	      //New node might become active
athos@331
   413
	      if (excess[G.head(j)]==0){
athos@36
   414
		make_active(G.head(j));
athos@36
   415
	      }
athos@36
   416
	      modify_preflow(j,v);
athos@36
   417
	    }
athos@331
   418
	    G.next(j);
athos@36
   419
	  }
athos@36
   420
	}
athos@36
   421
	//In edges to node a
athos@36
   422
	{
athos@77
   423
	  InEdgeIt j=G.template first<InEdgeIt>(a);
athos@331
   424
	  while (G.valid(j) && e){
athos@36
   425
	    if (is_admissible_backward_edge(j,new_level)){
athos@331
   426
	      v=min(e,preflow[j]);
athos@36
   427
	      e -= v;
athos@36
   428
	      //New node might become active
athos@331
   429
	      if (excess[G.tail(j)]==0){
athos@36
   430
		make_active(G.tail(j));
athos@36
   431
	      }
athos@36
   432
	      modify_preflow(j,-v);
athos@36
   433
	    }
athos@331
   434
	    G.next(j);
athos@36
   435
	  }
athos@36
   436
	}
athos@505
   437
	*/
athos@36
   438
athos@119
   439
	//if (G.id(a)==999)
athos@119
   440
	//cout<<new_level<<" e: "<<e<<endl;
athos@36
   441
	//cout<<G.id(a)<<" "<<new_level<<endl;
athos@36
   442
athos@36
   443
	if (0==e){
athos@36
   444
	  //Saturating push
athos@36
   445
	  go_to_next_node=true;
athos@36
   446
	}
athos@36
   447
	else{//If there is still excess in node a
athos@77
   448
	  
athos@77
   449
	  //change_level_to(a,new_level+1);
athos@77
   450
	  
athos@36
   451
	  //Level remains empty
athos@331
   452
	  if (num_of_nodes_on_level[level[a]]==1){
athos@36
   453
	    change_level_to(a,number_of_nodes);
athos@36
   454
	    //go_to_next_node=True;
athos@36
   455
	  }
athos@36
   456
	  else{
athos@36
   457
	    change_level_to(a,new_level+1);
athos@36
   458
	    //increase_level(a);
athos@36
   459
	  }
athos@77
   460
	  
athos@36
   461
    
athos@36
   462
	  
athos@36
   463
athos@36
   464
	  switch(node_examination){
athos@36
   465
	  case examine_to_relabel:
athos@36
   466
	    make_active(a);
athos@36
   467
athos@36
   468
	    go_to_next_node = true;
athos@36
   469
	    break;
athos@36
   470
	  default:
athos@36
   471
	    break;
athos@36
   472
	  }
athos@36
   473
	  
athos@36
   474
    
athos@36
   475
	
athos@36
   476
	}//if (0==e)
athos@36
   477
      }
athos@36
   478
    }
athos@331
   479
    maxflow_value = excess[t];
athos@36
   480
    return maxflow_value;
athos@36
   481
  }//run
athos@36
   482
athos@36
   483
alpar@105
   484
}//namespace hugo
athos@36
   485
athos@36
   486
#endif //PREFLOW_PUSH_HH