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