lemon/circulation.h
author alpar
Thu, 01 Mar 2007 16:03:36 +0000
changeset 2379 248152674a9e
parent 2376 0ed45a6c74b1
child 2391 14a343be7a5a
permissions -rw-r--r--
Prescaling can be turned off
alpar@2375
     1
/* -*- C++ -*-
alpar@2375
     2
 * lemon/preflow_matching.h - Part of LEMON, a generic C++ optimization library
alpar@2375
     3
 *
alpar@2375
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@2375
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@2375
     6
 *
alpar@2375
     7
 * Permission to use, modify and distribute this software is granted
alpar@2375
     8
 * provided that this copyright notice appears in all copies. For
alpar@2375
     9
 * precise terms see the accompanying LICENSE file.
alpar@2375
    10
 *
alpar@2375
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@2375
    12
 * express or implied, and with no claim as to its suitability for any
alpar@2375
    13
 * purpose.
alpar@2375
    14
 *
alpar@2375
    15
 */
alpar@2375
    16
alpar@2375
    17
#ifndef LEMON_CIRCULATION_H
alpar@2375
    18
#define LEMON_CIRCULATION_H
alpar@2375
    19
alpar@2375
    20
#include <lemon/graph_utils.h>
alpar@2375
    21
#include <iostream>
alpar@2375
    22
#include <queue>
alpar@2375
    23
#include <lemon/tolerance.h>
alpar@2375
    24
#include <lemon/elevator.h>
alpar@2375
    25
deba@2376
    26
///\ingroup max_flow
alpar@2375
    27
///\file
alpar@2375
    28
///\brief Push-prelabel algorithm for finding a feasible circulation.
alpar@2375
    29
///
alpar@2375
    30
namespace lemon {
alpar@2375
    31
alpar@2375
    32
  ///Preflow algorithm for the Network Circulation Problem.
alpar@2375
    33
  
deba@2378
    34
  ///\ingroup max_flow
alpar@2375
    35
  ///This class implements a preflow algorithm
alpar@2375
    36
  ///for the Network Circulation Problem.
alpar@2375
    37
  ///The exact formulation of this problem is the following.
alpar@2375
    38
  /// \f[\sum_{e\in\rho(v)}x(e)-\sum_{e\in\delta(v)}x(e)\leq delta(v)\quad \forall v\in V \f]
alpar@2375
    39
  /// \f[ lo(e)\leq x(e) \leq up(e) \quad \forall e\in E \f]
alpar@2375
    40
  ///
alpar@2375
    41
  template<class Graph,
alpar@2375
    42
	   class Value,
alpar@2375
    43
	   class FlowMap=typename Graph::template EdgeMap<Value>,
alpar@2375
    44
	   class LCapMap=typename Graph::template EdgeMap<Value>,
alpar@2375
    45
	   class UCapMap=LCapMap,
alpar@2375
    46
	   class DeltaMap=typename Graph::template NodeMap<Value>
alpar@2375
    47
	    >
alpar@2375
    48
  class Circulation {
alpar@2375
    49
    typedef typename Graph::Node Node;
alpar@2375
    50
    typedef typename Graph::NodeIt NodeIt;
alpar@2375
    51
    typedef typename Graph::Edge Edge;
alpar@2375
    52
    typedef typename Graph::EdgeIt EdgeIt;
alpar@2375
    53
    typedef typename Graph::InEdgeIt InEdgeIt;
alpar@2375
    54
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@2375
    55
    
alpar@2375
    56
alpar@2375
    57
    const Graph &_g;
alpar@2375
    58
    int _node_num;
alpar@2375
    59
alpar@2375
    60
    const LCapMap &_lo;
alpar@2375
    61
    const UCapMap &_up;
alpar@2375
    62
    const DeltaMap &_delta;
alpar@2375
    63
    FlowMap &_x;
alpar@2375
    64
    Tolerance<Value> _tol;
alpar@2375
    65
    Elevator<Graph,typename Graph::Node> _levels;
alpar@2375
    66
    typename Graph::template NodeMap<Value> _excess;
alpar@2375
    67
alpar@2375
    68
  public:
alpar@2375
    69
    ///\e
alpar@2375
    70
    Circulation(const Graph &g,const LCapMap &lo,const UCapMap &up,
alpar@2375
    71
		const DeltaMap &delta,FlowMap &x) :
alpar@2375
    72
      _g(g),
alpar@2375
    73
      _node_num(countNodes(g)),
alpar@2375
    74
      _lo(lo),_up(up),_delta(delta),_x(x),
alpar@2375
    75
      _levels(g,_node_num),
alpar@2375
    76
      _excess(g)
alpar@2375
    77
    {
alpar@2375
    78
    }
alpar@2375
    79
    
alpar@2375
    80
  private:
alpar@2375
    81
alpar@2375
    82
    void addExcess(Node n,Value v)
alpar@2375
    83
    {
alpar@2375
    84
      if(_tol.positive(_excess[n]+=v))
alpar@2375
    85
	{
alpar@2375
    86
	  if(!_levels.active(n)) _levels.activate(n);
alpar@2375
    87
	}
alpar@2375
    88
      else if(_levels.active(n)) _levels.deactivate(n);
alpar@2375
    89
    }
alpar@2375
    90
    
alpar@2375
    91
    void init() 
alpar@2375
    92
    {
alpar@2375
    93
     
alpar@2375
    94
      _x=_lo;
alpar@2375
    95
alpar@2375
    96
      for(NodeIt n(_g);n!=INVALID;++n) _excess[n]=-_delta[n];
alpar@2375
    97
alpar@2375
    98
      for(EdgeIt e(_g);e!=INVALID;++e)
alpar@2375
    99
	{
alpar@2375
   100
	  _excess[_g.target(e)]+=_x[e];
alpar@2375
   101
	  _excess[_g.source(e)]-=_x[e];
alpar@2375
   102
	}
alpar@2375
   103
     
alpar@2375
   104
      _levels.initStart();
alpar@2375
   105
      for(NodeIt n(_g);n!=INVALID;++n)
alpar@2375
   106
	_levels.initAddItem(n);
alpar@2375
   107
      _levels.initFinish();
alpar@2375
   108
      for(NodeIt n(_g);n!=INVALID;++n)
alpar@2375
   109
	if(_tol.positive(_excess[n]))
alpar@2375
   110
	  _levels.activate(n);
alpar@2375
   111
    }
alpar@2375
   112
alpar@2375
   113
  public:
alpar@2375
   114
    ///Check if \c x is a feasible circulation
alpar@2375
   115
    template<class FT>
alpar@2375
   116
    bool checkX(FT &x) {
alpar@2375
   117
      for(EdgeIt e(_g);e!=INVALID;++e)
alpar@2375
   118
	if(x[e]<_lo[e]||x[e]>_up[e]) return false;
alpar@2375
   119
      for(NodeIt n(_g);n!=INVALID;++n)
alpar@2375
   120
	{
alpar@2375
   121
	  Value dif=_delta[n];
alpar@2375
   122
	  for(InEdgeIt e(_g,n);e!=INVALID;++e) dif-=x[e];
alpar@2375
   123
	  for(OutEdgeIt e(_g,n);e!=INVALID;++e) dif+=x[e];
alpar@2375
   124
	  if(_tol.negative(dif)) return false;
alpar@2375
   125
	}
alpar@2375
   126
      return true;
alpar@2375
   127
    };
alpar@2375
   128
    ///Check if the default \c x is a feasible circulation
alpar@2375
   129
    bool checkX() { return checkX(_x); }
alpar@2375
   130
alpar@2375
   131
    ///Chech if \c bar is a real barrier
alpar@2375
   132
alpar@2375
   133
    ///Chech if \c bar is a real barrier
alpar@2375
   134
    ///\sa barrier()
alpar@2375
   135
    template<class GT>
alpar@2375
   136
    bool checkBarrier(GT &bar) 
alpar@2375
   137
    {
alpar@2375
   138
      Value delta=0;
alpar@2375
   139
      for(NodeIt n(_g);n!=INVALID;++n)
alpar@2375
   140
	if(bar[n])
alpar@2375
   141
	  delta+=_delta[n];
alpar@2375
   142
      for(EdgeIt e(_g);e!=INVALID;++e)
alpar@2375
   143
	{
alpar@2375
   144
	  Node s=_g.source(e);
alpar@2375
   145
	  Node t=_g.target(e);
alpar@2375
   146
	  if(bar[s]&&!bar[t]) delta+=_up[e];
alpar@2375
   147
	  else if(bar[t]&&!bar[s]) delta-=_lo[e];
alpar@2375
   148
	}
alpar@2375
   149
      return _tol.negative(delta);
alpar@2375
   150
    }  
alpar@2375
   151
    ///Chech whether or not the last execution provides a barrier
alpar@2375
   152
alpar@2375
   153
    ///Chech whether or not the last execution provides a barrier
alpar@2375
   154
    ///\sa barrier()
alpar@2375
   155
    bool checkBarrier() 
alpar@2375
   156
    {
alpar@2375
   157
      typename Graph:: template NodeMap<bool> bar(_g);
alpar@2375
   158
      barrier(bar);
alpar@2375
   159
      return checkBarrier(bar);
alpar@2375
   160
    }
alpar@2375
   161
    ///Run the algorithm
alpar@2375
   162
alpar@2375
   163
    ///This function runs the algorithm.
alpar@2375
   164
    ///\return This function returns -1 if it found a feasible circulation.
alpar@2375
   165
    /// nonnegative values (including 0) mean that no feasible solution is
alpar@2375
   166
    /// found. In this case the return value means an "empty level".
alpar@2375
   167
    ///
alpar@2375
   168
    ///\sa barrier()
alpar@2375
   169
    int run() 
alpar@2375
   170
    {
alpar@2375
   171
      init();
alpar@2375
   172
      
alpar@2375
   173
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   174
      for(NodeIt n(_g);n!=INVALID;++n)
alpar@2375
   175
	std::cerr<< _levels[n] << ' ';
alpar@2375
   176
      std::cerr << std::endl;
alpar@2375
   177
#endif      
alpar@2375
   178
      Node act;
alpar@2375
   179
      Node bact=INVALID;
alpar@2375
   180
      Node last_activated=INVALID;
alpar@2375
   181
      while((act=_levels.highestActive())!=INVALID) {
alpar@2375
   182
	int actlevel=_levels[act];
alpar@2375
   183
	int tlevel;
alpar@2375
   184
	int mlevel=_node_num;
alpar@2375
   185
	Value exc=_excess[act];
alpar@2375
   186
	Value fc;
alpar@2375
   187
	
alpar@2375
   188
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   189
	for(NodeIt n(_g);n!=INVALID;++n)
alpar@2375
   190
	  std::cerr<< _levels[n] << ' ';
alpar@2375
   191
	std::cerr << std::endl;
alpar@2375
   192
	std::cerr << "Process node " << _g.id(act)
alpar@2375
   193
		  << " on level " << actlevel
alpar@2375
   194
		  << " with excess " << exc
alpar@2375
   195
		  << std::endl;
alpar@2375
   196
#endif
alpar@2375
   197
	for(OutEdgeIt e(_g,act);e!=INVALID; ++e)
alpar@2375
   198
	  if((fc=_up[e]-_x[e])>0)
alpar@2375
   199
	    if((tlevel=_levels[_g.target(e)])<actlevel)
alpar@2375
   200
	      if(fc<=exc) {
alpar@2375
   201
		_x[e]=_up[e];
alpar@2375
   202
		addExcess(_g.target(e),fc);
alpar@2375
   203
		exc-=fc;
alpar@2375
   204
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   205
		std::cerr << "  Push " << fc
alpar@2375
   206
			  << " toward " << _g.id(_g.target(e)) << std::endl;
alpar@2375
   207
#endif
alpar@2375
   208
	      }
alpar@2375
   209
	      else {
alpar@2375
   210
		_x[e]+=exc;
alpar@2375
   211
		addExcess(_g.target(e),exc);
alpar@2375
   212
		//exc=0;
alpar@2375
   213
		_excess[act]=0;
alpar@2375
   214
		_levels.deactivate(act);
alpar@2375
   215
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   216
		std::cerr << "  Push " << exc
alpar@2375
   217
			  << " toward " << _g.id(_g.target(e)) << std::endl;
alpar@2375
   218
		std::cerr << "  Deactivate\n";
alpar@2375
   219
#endif
alpar@2375
   220
		goto next_l;
alpar@2375
   221
	      }
alpar@2375
   222
	    else if(tlevel<mlevel) mlevel=tlevel;
alpar@2375
   223
	
alpar@2375
   224
	for(InEdgeIt e(_g,act);e!=INVALID; ++e)
alpar@2375
   225
	  if((fc=_x[e]-_lo[e])>0)
alpar@2375
   226
	    if((tlevel=_levels[_g.source(e)])<actlevel)
alpar@2375
   227
	      if(fc<=exc) {
alpar@2375
   228
		_x[e]=_lo[e];
alpar@2375
   229
		addExcess(_g.source(e),fc);
alpar@2375
   230
		exc-=fc;
alpar@2375
   231
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   232
		std::cerr << "  Push " << fc
alpar@2375
   233
			  << " toward " << _g.id(_g.source(e)) << std::endl;
alpar@2375
   234
#endif
alpar@2375
   235
	      }
alpar@2375
   236
	      else {
alpar@2375
   237
		_x[e]-=exc;
alpar@2375
   238
		addExcess(_g.source(e),exc);
alpar@2375
   239
		//exc=0;
alpar@2375
   240
		_excess[act]=0;
alpar@2375
   241
		_levels.deactivate(act);
alpar@2375
   242
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   243
		std::cerr << "  Push " << exc
alpar@2375
   244
			  << " toward " << _g.id(_g.source(e)) << std::endl;
alpar@2375
   245
		std::cerr << "  Deactivate\n";
alpar@2375
   246
#endif
alpar@2375
   247
		goto next_l;
alpar@2375
   248
              }
alpar@2375
   249
	    else if(tlevel<mlevel) mlevel=tlevel;
alpar@2375
   250
   
alpar@2375
   251
	_excess[act]=exc;
alpar@2375
   252
	if(!_tol.positive(exc)) _levels.deactivate(act);
alpar@2375
   253
	else if(mlevel==_node_num) {
alpar@2375
   254
	  _levels.liftHighestActiveTo(_node_num);
alpar@2375
   255
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   256
	  std::cerr << "  Lift to level " << _node_num << std::endl;
alpar@2375
   257
#endif
alpar@2375
   258
	  return _levels.onLevel(_node_num-1)==0?_node_num-1:actlevel;
alpar@2375
   259
	}
alpar@2375
   260
	else {
alpar@2375
   261
	  _levels.liftHighestActiveTo(mlevel+1);
alpar@2375
   262
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   263
	  std::cerr << "  Lift to level " << mlevel+1 << std::endl;
alpar@2375
   264
#endif
alpar@2375
   265
	  if(_levels.onLevel(actlevel)==0)
alpar@2375
   266
	    return actlevel;
alpar@2375
   267
	}
alpar@2375
   268
      next_l:
alpar@2375
   269
	;
alpar@2375
   270
      }
alpar@2375
   271
#ifdef LEMON_CIRCULATION_DEBUG
alpar@2375
   272
      std::cerr << "Feasible flow found.\n";
alpar@2375
   273
#endif
alpar@2375
   274
      return -1;
alpar@2375
   275
    }
alpar@2375
   276
    
alpar@2375
   277
    ///Return a barrier
alpar@2375
   278
    
alpar@2375
   279
    ///Barrier is a set \e B of nodes for which
alpar@2375
   280
    /// \f[ \sum_{v\in B}delta(v)<\sum_{e\in\rho(B)}lo(e)-\sum_{e\in\delta(B)}up(e) \f]
alpar@2375
   281
    ///holds. The existence of a set with this property prooves that a feasible
alpar@2375
   282
    ///flow cannot exists.
alpar@2375
   283
    ///\pre The run() must have been executed, and its return value was -1.
alpar@2375
   284
    ///\sa checkBarrier()
alpar@2375
   285
    ///\sa run()
alpar@2375
   286
    template<class GT>
alpar@2375
   287
    void barrier(GT &bar,int empty_level=-1) 
alpar@2375
   288
    {
alpar@2375
   289
      if(empty_level==-1)
alpar@2375
   290
	for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
alpar@2375
   291
      for(NodeIt n(_g);n!=INVALID;++n)
alpar@2375
   292
	bar[n] = _levels[n]>empty_level;
alpar@2375
   293
    }  
alpar@2375
   294
alpar@2375
   295
  };
alpar@2375
   296
  
alpar@2375
   297
}
alpar@2375
   298
alpar@2375
   299
#endif