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