1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_CIRCULATION_H
20 #define LEMON_CIRCULATION_H
24 #include <lemon/tolerance.h>
25 #include <lemon/elevator.h>
29 ///\brief Push-prelabel algorithm for finding a feasible circulation.
33 /// \brief Default traits class of Circulation class.
35 /// Default traits class of Circulation class.
36 /// \param _Graph Digraph type.
37 /// \param _CapacityMap Type of capacity map.
38 template <typename _Graph, typename _LCapMap,
39 typename _UCapMap, typename _DeltaMap>
40 struct CirculationDefaultTraits {
42 /// \brief The digraph type the algorithm runs on.
43 typedef _Graph Digraph;
45 /// \brief The type of the map that stores the circulation lower
48 /// The type of the map that stores the circulation lower bound.
49 /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
50 typedef _LCapMap LCapMap;
52 /// \brief The type of the map that stores the circulation upper
55 /// The type of the map that stores the circulation upper bound.
56 /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
57 typedef _UCapMap UCapMap;
59 /// \brief The type of the map that stores the upper bound of
62 /// The type of the map that stores the lower bound of node
63 /// excess. It must meet the \ref concepts::ReadMap "ReadMap"
65 typedef _DeltaMap DeltaMap;
67 /// \brief The type of the length of the arcs.
68 typedef typename DeltaMap::Value Value;
70 /// \brief The map type that stores the flow values.
72 /// The map type that stores the flow values.
73 /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
74 typedef typename Digraph::template ArcMap<Value> FlowMap;
76 /// \brief Instantiates a FlowMap.
78 /// This function instantiates a \ref FlowMap.
79 /// \param digraph The digraph, to which we would like to define
81 static FlowMap* createFlowMap(const Digraph& digraph) {
82 return new FlowMap(digraph);
85 /// \brief The eleavator type used by Circulation algorithm.
87 /// The elevator type used by Circulation algorithm.
90 /// \sa LinkedElevator
91 typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
93 /// \brief Instantiates an Elevator.
95 /// This function instantiates a \ref Elevator.
96 /// \param digraph The digraph, to which we would like to define
98 /// \param max_level The maximum level of the elevator.
99 static Elevator* createElevator(const Digraph& digraph, int max_level) {
100 return new Elevator(digraph, max_level);
103 /// \brief The tolerance used by the algorithm
105 /// The tolerance used by the algorithm to handle inexact computation.
106 typedef lemon::Tolerance<Value> Tolerance;
110 ///Push-relabel algorithm for the Network Circulation Problem.
114 This class implements a push-relabel algorithm
115 or the Network Circulation Problem.
116 The exact formulation of this problem is the following.
117 \f[\sum_{e\in\rho(v)}x(e)-\sum_{e\in\delta(v)}x(e)\leq
118 -delta(v)\quad \forall v\in V \f]
119 \f[ lo(e)\leq x(e) \leq up(e) \quad \forall e\in E \f]
121 template<class _Graph,
122 class _LCapMap=typename _Graph::template ArcMap<int>,
123 class _UCapMap=_LCapMap,
124 class _DeltaMap=typename _Graph::template NodeMap<
125 typename _UCapMap::Value>,
126 class _Traits=CirculationDefaultTraits<_Graph, _LCapMap,
127 _UCapMap, _DeltaMap> >
130 typedef _Traits Traits;
131 typedef typename Traits::Digraph Digraph;
132 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
134 typedef typename Traits::Value Value;
136 typedef typename Traits::LCapMap LCapMap;
137 typedef typename Traits::UCapMap UCapMap;
138 typedef typename Traits::DeltaMap DeltaMap;
139 typedef typename Traits::FlowMap FlowMap;
140 typedef typename Traits::Elevator Elevator;
141 typedef typename Traits::Tolerance Tolerance;
143 typedef typename Digraph::template NodeMap<Value> ExcessMap;
150 const DeltaMap *_delta;
165 typedef Circulation Create;
167 ///\name Named template parameters
171 template <typename _FlowMap>
172 struct DefFlowMapTraits : public Traits {
173 typedef _FlowMap FlowMap;
174 static FlowMap *createFlowMap(const Digraph&) {
175 LEMON_ASSERT(false, "FlowMap is not initialized");
176 return 0; // ignore warnings
180 /// \brief \ref named-templ-param "Named parameter" for setting
183 /// \ref named-templ-param "Named parameter" for setting FlowMap
185 template <typename _FlowMap>
187 : public Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
188 DefFlowMapTraits<_FlowMap> > {
189 typedef Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
190 DefFlowMapTraits<_FlowMap> > Create;
193 template <typename _Elevator>
194 struct DefElevatorTraits : public Traits {
195 typedef _Elevator Elevator;
196 static Elevator *createElevator(const Digraph&, int) {
197 LEMON_ASSERT(false, "Elevator is not initialized");
198 return 0; // ignore warnings
202 /// \brief \ref named-templ-param "Named parameter" for setting
205 /// \ref named-templ-param "Named parameter" for setting Elevator
207 template <typename _Elevator>
209 : public Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
210 DefElevatorTraits<_Elevator> > {
211 typedef Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
212 DefElevatorTraits<_Elevator> > Create;
215 template <typename _Elevator>
216 struct DefStandardElevatorTraits : public Traits {
217 typedef _Elevator Elevator;
218 static Elevator *createElevator(const Digraph& digraph, int max_level) {
219 return new Elevator(digraph, max_level);
223 /// \brief \ref named-templ-param "Named parameter" for setting
226 /// \ref named-templ-param "Named parameter" for setting Elevator
227 /// type. The Elevator should be standard constructor interface, ie.
228 /// the digraph and the maximum level should be passed to it.
229 template <typename _Elevator>
230 struct DefStandardElevator
231 : public Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
232 DefStandardElevatorTraits<_Elevator> > {
233 typedef Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
234 DefStandardElevatorTraits<_Elevator> > Create;
245 /// The constructor of the class.
247 /// The constructor of the class.
248 /// \param g The digraph the algorithm runs on.
249 /// \param lo The lower bound capacity of the arcs.
250 /// \param up The upper bound capacity of the arcs.
251 /// \param delta The lower bound on node excess.
252 Circulation(const Digraph &g,const LCapMap &lo,
253 const UCapMap &up,const DeltaMap &delta)
254 : _g(g), _node_num(),
255 _lo(&lo),_up(&up),_delta(&delta),_flow(0),_local_flow(false),
256 _level(0), _local_level(false), _excess(0), _el() {}
265 void createStructures() {
266 _node_num = _el = countNodes(_g);
269 _flow = Traits::createFlowMap(_g);
273 _level = Traits::createElevator(_g, _node_num);
277 _excess = new ExcessMap(_g);
281 void destroyStructures() {
295 /// Sets the lower bound capacity map.
297 /// Sets the lower bound capacity map.
298 /// \return \c (*this)
299 Circulation& lowerCapMap(const LCapMap& map) {
304 /// Sets the upper bound capacity map.
306 /// Sets the upper bound capacity map.
307 /// \return \c (*this)
308 Circulation& upperCapMap(const LCapMap& map) {
313 /// Sets the lower bound map on excess.
315 /// Sets the lower bound map on excess.
316 /// \return \c (*this)
317 Circulation& deltaMap(const DeltaMap& map) {
322 /// Sets the flow map.
324 /// Sets the flow map.
325 /// \return \c (*this)
326 Circulation& flowMap(FlowMap& map) {
335 /// Returns the flow map.
337 /// \return The flow map.
339 const FlowMap& flowMap() {
343 /// Sets the elevator.
345 /// Sets the elevator.
346 /// \return \c (*this)
347 Circulation& elevator(Elevator& elevator) {
350 _local_level = false;
356 /// Returns the elevator.
358 /// \return The elevator.
360 const Elevator& elevator() {
364 /// Sets the tolerance used by algorithm.
366 /// Sets the tolerance used by algorithm.
368 Circulation& tolerance(const Tolerance& tolerance) const {
373 /// Returns the tolerance used by algorithm.
375 /// Returns the tolerance used by algorithm.
377 const Tolerance& tolerance() const {
381 /// \name Execution control
382 /// The simplest way to execute the algorithm is to use one of the
383 /// member functions called \c run().
385 /// If you need more control on initial solution or execution then
386 /// you have to call one \ref init() function and then the start()
391 /// Initializes the internal data structures.
393 /// Initializes the internal data structures. This function sets
394 /// all flow values to the lower bound.
395 /// \return This function returns false if the initialization
396 /// process found a barrier.
401 for(NodeIt n(_g);n!=INVALID;++n) {
402 _excess->set(n, (*_delta)[n]);
405 for (ArcIt e(_g);e!=INVALID;++e) {
406 _flow->set(e, (*_lo)[e]);
407 _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_flow)[e]);
408 _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_flow)[e]);
411 // global relabeling tested, but in general case it provides
412 // worse performance for random digraphs
414 for(NodeIt n(_g);n!=INVALID;++n)
415 _level->initAddItem(n);
416 _level->initFinish();
417 for(NodeIt n(_g);n!=INVALID;++n)
418 if(_tol.positive((*_excess)[n]))
422 /// Initializes the internal data structures.
424 /// Initializes the internal data structures. This functions uses
425 /// greedy approach to construct the initial solution.
430 for(NodeIt n(_g);n!=INVALID;++n) {
431 _excess->set(n, (*_delta)[n]);
434 for (ArcIt e(_g);e!=INVALID;++e) {
435 if (!_tol.positive((*_excess)[_g.target(e)] + (*_up)[e])) {
436 _flow->set(e, (*_up)[e]);
437 _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_up)[e]);
438 _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_up)[e]);
439 } else if (_tol.positive((*_excess)[_g.target(e)] + (*_lo)[e])) {
440 _flow->set(e, (*_lo)[e]);
441 _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_lo)[e]);
442 _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_lo)[e]);
444 Value fc = -(*_excess)[_g.target(e)];
446 _excess->set(_g.target(e), 0);
447 _excess->set(_g.source(e), (*_excess)[_g.source(e)] - fc);
452 for(NodeIt n(_g);n!=INVALID;++n)
453 _level->initAddItem(n);
454 _level->initFinish();
455 for(NodeIt n(_g);n!=INVALID;++n)
456 if(_tol.positive((*_excess)[n]))
460 ///Starts the algorithm
462 ///This function starts the algorithm.
463 ///\return This function returns true if it found a feasible circulation.
471 Node last_activated=INVALID;
472 while((act=_level->highestActive())!=INVALID) {
473 int actlevel=(*_level)[act];
474 int mlevel=_node_num;
475 Value exc=(*_excess)[act];
477 for(OutArcIt e(_g,act);e!=INVALID; ++e) {
478 Node v = _g.target(e);
479 Value fc=(*_up)[e]-(*_flow)[e];
480 if(!_tol.positive(fc)) continue;
481 if((*_level)[v]<actlevel) {
482 if(!_tol.less(fc, exc)) {
483 _flow->set(e, (*_flow)[e] + exc);
484 _excess->set(v, (*_excess)[v] + exc);
485 if(!_level->active(v) && _tol.positive((*_excess)[v]))
488 _level->deactivate(act);
492 _flow->set(e, (*_up)[e]);
493 _excess->set(v, (*_excess)[v] + fc);
494 if(!_level->active(v) && _tol.positive((*_excess)[v]))
499 else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
501 for(InArcIt e(_g,act);e!=INVALID; ++e) {
502 Node v = _g.source(e);
503 Value fc=(*_flow)[e]-(*_lo)[e];
504 if(!_tol.positive(fc)) continue;
505 if((*_level)[v]<actlevel) {
506 if(!_tol.less(fc, exc)) {
507 _flow->set(e, (*_flow)[e] - exc);
508 _excess->set(v, (*_excess)[v] + exc);
509 if(!_level->active(v) && _tol.positive((*_excess)[v]))
512 _level->deactivate(act);
516 _flow->set(e, (*_lo)[e]);
517 _excess->set(v, (*_excess)[v] + fc);
518 if(!_level->active(v) && _tol.positive((*_excess)[v]))
523 else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
526 _excess->set(act, exc);
527 if(!_tol.positive(exc)) _level->deactivate(act);
528 else if(mlevel==_node_num) {
529 _level->liftHighestActiveToTop();
534 _level->liftHighestActive(mlevel+1);
535 if(_level->onLevel(actlevel)==0) {
546 /// Runs the circulation algorithm.
548 /// Runs the circulation algorithm.
549 /// \note fc.run() is just a shortcut of the following code.
552 /// return fc.start();
561 /// \name Query Functions
562 /// The result of the %Circulation algorithm can be obtained using
565 /// Before the use of these functions,
566 /// either run() or start() must be called.
571 \brief Returns a barrier
573 Barrier is a set \e B of nodes for which
574 \f[ \sum_{v\in B}-delta(v)<
575 \sum_{e\in\rho(B)}lo(e)-\sum_{e\in\delta(B)}up(e) \f]
576 holds. The existence of a set with this property prooves that a feasible
582 void barrierMap(GT &bar)
584 for(NodeIt n(_g);n!=INVALID;++n)
585 bar.set(n, (*_level)[n] >= _el);
588 ///Returns true if the node is in the barrier
590 ///Returns true if the node is in the barrier
592 bool barrier(const Node& node)
594 return (*_level)[node] >= _el;
597 /// \brief Returns the flow on the arc.
599 /// Sets the \c flowMap to the flow on the arcs. This method can
600 /// be called after the second phase of algorithm.
601 Value flow(const Arc& arc) const {
602 return (*_flow)[arc];
607 /// \name Checker Functions
608 /// The feasibility of the results can be checked using
611 /// Before the use of these functions,
612 /// either run() or start() must be called.
616 ///Check if the \c flow is a feasible circulation
618 for(ArcIt e(_g);e!=INVALID;++e)
619 if((*_flow)[e]<(*_lo)[e]||(*_flow)[e]>(*_up)[e]) return false;
620 for(NodeIt n(_g);n!=INVALID;++n)
622 Value dif=-(*_delta)[n];
623 for(InArcIt e(_g,n);e!=INVALID;++e) dif-=(*_flow)[e];
624 for(OutArcIt e(_g,n);e!=INVALID;++e) dif+=(*_flow)[e];
625 if(_tol.negative(dif)) return false;
630 ///Check whether or not the last execution provides a barrier
632 ///Check whether or not the last execution provides a barrier
637 for(NodeIt n(_g);n!=INVALID;++n)
640 for(ArcIt e(_g);e!=INVALID;++e)
644 if(barrier(s)&&!barrier(t)) delta+=(*_up)[e];
645 else if(barrier(t)&&!barrier(s)) delta-=(*_lo)[e];
647 return _tol.negative(delta);