2 * lemon/preflow_matching.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #ifndef LEMON_CIRCULATION_H
18 #define LEMON_CIRCULATION_H
20 #include <lemon/graph_utils.h>
23 #include <lemon/tolerance.h>
24 #include <lemon/elevator.h>
28 ///\brief Push-prelabel algorithm for finding a feasible circulation.
32 ///Preflow algorithm for the Network Circulation Problem.
35 ///This class implements a preflow algorithm
36 ///for the Network Circulation Problem.
37 ///The exact formulation of this problem is the following.
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]
39 /// \f[ lo(e)\leq x(e) \leq up(e) \quad \forall e\in E \f]
43 class FlowMap=typename Graph::template EdgeMap<Value>,
44 class LCapMap=typename Graph::template EdgeMap<Value>,
45 class UCapMap=LCapMap,
46 class DeltaMap=typename Graph::template NodeMap<Value>
49 typedef typename Graph::Node Node;
50 typedef typename Graph::NodeIt NodeIt;
51 typedef typename Graph::Edge Edge;
52 typedef typename Graph::EdgeIt EdgeIt;
53 typedef typename Graph::InEdgeIt InEdgeIt;
54 typedef typename Graph::OutEdgeIt OutEdgeIt;
62 const DeltaMap &_delta;
64 Tolerance<Value> _tol;
65 Elevator<Graph,typename Graph::Node> _levels;
66 typename Graph::template NodeMap<Value> _excess;
70 Circulation(const Graph &g,const LCapMap &lo,const UCapMap &up,
71 const DeltaMap &delta,FlowMap &x) :
73 _node_num(countNodes(g)),
74 _lo(lo),_up(up),_delta(delta),_x(x),
82 void addExcess(Node n,Value v)
84 if(_tol.positive(_excess[n]+=v))
86 if(!_levels.active(n)) _levels.activate(n);
88 else if(_levels.active(n)) _levels.deactivate(n);
96 for(NodeIt n(_g);n!=INVALID;++n) _excess[n]=-_delta[n];
98 for(EdgeIt e(_g);e!=INVALID;++e)
100 _excess[_g.target(e)]+=_x[e];
101 _excess[_g.source(e)]-=_x[e];
105 for(NodeIt n(_g);n!=INVALID;++n)
106 _levels.initAddItem(n);
107 _levels.initFinish();
108 for(NodeIt n(_g);n!=INVALID;++n)
109 if(_tol.positive(_excess[n]))
114 ///Check if \c x is a feasible circulation
117 for(EdgeIt e(_g);e!=INVALID;++e)
118 if(x[e]<_lo[e]||x[e]>_up[e]) return false;
119 for(NodeIt n(_g);n!=INVALID;++n)
122 for(InEdgeIt e(_g,n);e!=INVALID;++e) dif-=x[e];
123 for(OutEdgeIt e(_g,n);e!=INVALID;++e) dif+=x[e];
124 if(_tol.negative(dif)) return false;
128 ///Check if the default \c x is a feasible circulation
129 bool checkX() { return checkX(_x); }
131 ///Chech if \c bar is a real barrier
133 ///Chech if \c bar is a real barrier
136 bool checkBarrier(GT &bar)
139 for(NodeIt n(_g);n!=INVALID;++n)
142 for(EdgeIt e(_g);e!=INVALID;++e)
146 if(bar[s]&&!bar[t]) delta+=_up[e];
147 else if(bar[t]&&!bar[s]) delta-=_lo[e];
149 return _tol.negative(delta);
151 ///Chech whether or not the last execution provides a barrier
153 ///Chech whether or not the last execution provides a barrier
157 typename Graph:: template NodeMap<bool> bar(_g);
159 return checkBarrier(bar);
163 ///This function runs the algorithm.
164 ///\return This function returns -1 if it found a feasible circulation.
165 /// nonnegative values (including 0) mean that no feasible solution is
166 /// found. In this case the return value means an "empty level".
173 #ifdef LEMON_CIRCULATION_DEBUG
174 for(NodeIt n(_g);n!=INVALID;++n)
175 std::cerr<< _levels[n] << ' ';
176 std::cerr << std::endl;
180 Node last_activated=INVALID;
181 while((act=_levels.highestActive())!=INVALID) {
182 int actlevel=_levels[act];
184 int mlevel=_node_num;
185 Value exc=_excess[act];
188 #ifdef LEMON_CIRCULATION_DEBUG
189 for(NodeIt n(_g);n!=INVALID;++n)
190 std::cerr<< _levels[n] << ' ';
191 std::cerr << std::endl;
192 std::cerr << "Process node " << _g.id(act)
193 << " on level " << actlevel
194 << " with excess " << exc
197 for(OutEdgeIt e(_g,act);e!=INVALID; ++e)
198 if((fc=_up[e]-_x[e])>0)
199 if((tlevel=_levels[_g.target(e)])<actlevel)
202 addExcess(_g.target(e),fc);
204 #ifdef LEMON_CIRCULATION_DEBUG
205 std::cerr << " Push " << fc
206 << " toward " << _g.id(_g.target(e)) << std::endl;
211 addExcess(_g.target(e),exc);
214 _levels.deactivate(act);
215 #ifdef LEMON_CIRCULATION_DEBUG
216 std::cerr << " Push " << exc
217 << " toward " << _g.id(_g.target(e)) << std::endl;
218 std::cerr << " Deactivate\n";
222 else if(tlevel<mlevel) mlevel=tlevel;
224 for(InEdgeIt e(_g,act);e!=INVALID; ++e)
225 if((fc=_x[e]-_lo[e])>0)
226 if((tlevel=_levels[_g.source(e)])<actlevel)
229 addExcess(_g.source(e),fc);
231 #ifdef LEMON_CIRCULATION_DEBUG
232 std::cerr << " Push " << fc
233 << " toward " << _g.id(_g.source(e)) << std::endl;
238 addExcess(_g.source(e),exc);
241 _levels.deactivate(act);
242 #ifdef LEMON_CIRCULATION_DEBUG
243 std::cerr << " Push " << exc
244 << " toward " << _g.id(_g.source(e)) << std::endl;
245 std::cerr << " Deactivate\n";
249 else if(tlevel<mlevel) mlevel=tlevel;
252 if(!_tol.positive(exc)) _levels.deactivate(act);
253 else if(mlevel==_node_num) {
254 _levels.liftHighestActiveTo(_node_num);
255 #ifdef LEMON_CIRCULATION_DEBUG
256 std::cerr << " Lift to level " << _node_num << std::endl;
258 return _levels.onLevel(_node_num-1)==0?_node_num-1:actlevel;
261 _levels.liftHighestActiveTo(mlevel+1);
262 #ifdef LEMON_CIRCULATION_DEBUG
263 std::cerr << " Lift to level " << mlevel+1 << std::endl;
265 if(_levels.onLevel(actlevel)==0)
271 #ifdef LEMON_CIRCULATION_DEBUG
272 std::cerr << "Feasible flow found.\n";
279 ///Barrier is a set \e B of nodes for which
280 /// \f[ \sum_{v\in B}delta(v)<\sum_{e\in\rho(B)}lo(e)-\sum_{e\in\delta(B)}up(e) \f]
281 ///holds. The existence of a set with this property prooves that a feasible
282 ///flow cannot exists.
283 ///\pre The run() must have been executed, and its return value was -1.
284 ///\sa checkBarrier()
287 void barrier(GT &bar,int empty_level=-1)
290 for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
291 for(NodeIt n(_g);n!=INVALID;++n)
292 bar[n] = _levels[n]>empty_level;