[Lemon-commits] deba: r3403 - in lemon/trunk: demo lemon
Lemon SVN
svn at lemon.cs.elte.hu
Wed Nov 28 18:51:03 CET 2007
Author: deba
Date: Wed Nov 28 18:51:02 2007
New Revision: 3403
Modified:
lemon/trunk/demo/circulation_demo.cc
lemon/trunk/lemon/circulation.h
lemon/trunk/lemon/cycle_canceling.h
Log:
Redesign Circulation interface according to new flow interface
New greedy approach initialization
Modified: lemon/trunk/demo/circulation_demo.cc
==============================================================================
--- lemon/trunk/demo/circulation_demo.cc (original)
+++ lemon/trunk/demo/circulation_demo.cc Wed Nov 28 18:51:02 2007
@@ -52,7 +52,6 @@
Graph g;
EdgeMap lo(g);
EdgeMap up(g);
- EdgeMap x(g);
NodeMap delta(g);
NodeMap nid(g);
EdgeMap eid(g);
@@ -69,16 +68,16 @@
readNodeMap("coordinates_y", cy).
run();
- Circulation<Graph,int> gen(g,lo,up,delta,x);
- int ret=gen.run();
- if(ret==-1)
+ Circulation<Graph> gen(g,lo,up,delta);
+ bool ret=gen.run();
+ if(ret)
{
std::cout << "\nA feasible flow has been found.\n";
- if(!gen.checkX(x)) std::cerr << "Oops!!!\n";
+ if(!gen.checkFlow()) std::cerr << "Oops!!!\n";
GraphWriter<Graph>("circulation-output.lgf", g).
writeEdgeMap("lo_cap", lo).
writeEdgeMap("up_cap", up).
- writeEdgeMap("flow", x).
+ writeEdgeMap("flow", gen.flowMap()).
writeNodeMap("delta", delta).
writeEdgeMap("label", eid).
writeNodeMap("label", nid).
@@ -89,8 +88,8 @@
else {
std::cout << "\nThere is no such a flow\n";
Graph::NodeMap<int> bar(g);
- gen.barrier(bar,ret);
- if(!gen.checkBarrier(bar)) std::cerr << "Dual Oops!!!\n";
+ gen.barrierMap(bar);
+ if(!gen.checkBarrier()) std::cerr << "Dual Oops!!!\n";
GraphWriter<Graph>("circulation-output.lgf", g).
writeEdgeMap("lo_cap", lo).
Modified: lemon/trunk/lemon/circulation.h
==============================================================================
--- lemon/trunk/lemon/circulation.h (original)
+++ lemon/trunk/lemon/circulation.h Wed Nov 28 18:51:02 2007
@@ -31,269 +31,613 @@
///
namespace lemon {
- ///Preflow algorithm for the Network Circulation Problem.
+ /// \brief Default traits class of Circulation class.
+ ///
+ /// Default traits class of Circulation class.
+ /// \param _Graph Graph type.
+ /// \param _CapacityMap Type of capacity map.
+ template <typename _Graph, typename _LCapMap,
+ typename _UCapMap, typename _DeltaMap>
+ struct CirculationDefaultTraits {
+
+ /// \brief The graph type the algorithm runs on.
+ typedef _Graph Graph;
+
+ /// \brief The type of the map that stores the circulation lower
+ /// bound.
+ ///
+ /// The type of the map that stores the circulation lower bound.
+ /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
+ typedef _LCapMap LCapMap;
+
+ /// \brief The type of the map that stores the circulation upper
+ /// bound.
+ ///
+ /// The type of the map that stores the circulation upper bound.
+ /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
+ typedef _UCapMap UCapMap;
+
+ /// \brief The type of the map that stores the upper bound of
+ /// node excess.
+ ///
+ /// The type of the map that stores the lower bound of node
+ /// excess. It must meet the \ref concepts::ReadMap "ReadMap"
+ /// concept.
+ typedef _DeltaMap DeltaMap;
+
+ /// \brief The type of the length of the edges.
+ typedef typename DeltaMap::Value Value;
+
+ /// \brief The map type that stores the flow values.
+ ///
+ /// The map type that stores the flow values.
+ /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Graph::template EdgeMap<Value> FlowMap;
+
+ /// \brief Instantiates a FlowMap.
+ ///
+ /// This function instantiates a \ref FlowMap.
+ /// \param graph The graph, to which we would like to define the flow map.
+ static FlowMap* createFlowMap(const Graph& graph) {
+ return new FlowMap(graph);
+ }
+
+ /// \brief The eleavator type used by Circulation algorithm.
+ ///
+ /// The elevator type used by Circulation algorithm.
+ ///
+ /// \sa Elevator
+ /// \sa LinkedElevator
+ typedef Elevator<Graph, typename Graph::Node> Elevator;
+
+ /// \brief Instantiates an Elevator.
+ ///
+ /// This function instantiates a \ref Elevator.
+ /// \param graph The graph, to which we would like to define the elevator.
+ /// \param max_level The maximum level of the elevator.
+ static Elevator* createElevator(const Graph& graph, int max_level) {
+ return new Elevator(graph, max_level);
+ }
+
+ /// \brief The tolerance used by the algorithm
+ ///
+ /// The tolerance used by the algorithm to handle inexact computation.
+ typedef Tolerance<Value> Tolerance;
+
+ };
+
+ ///Push-relabel algorithm for the Network Circulation Problem.
///\ingroup max_flow
- ///This class implements a preflow algorithm
+ ///This class implements a push-relabel algorithm
///for the Network Circulation Problem.
///The exact formulation of this problem is the following.
/// \f[\sum_{e\in\rho(v)}x(e)-\sum_{e\in\delta(v)}x(e)\leq -delta(v)\quad \forall v\in V \f]
/// \f[ lo(e)\leq x(e) \leq up(e) \quad \forall e\in E \f]
///
- template<class Graph,
- class Value,
- class FlowMap=typename Graph::template EdgeMap<Value>,
- class LCapMap=typename Graph::template EdgeMap<Value>,
- class UCapMap=LCapMap,
- class DeltaMap=typename Graph::template NodeMap<Value>
- >
+ template<class _Graph,
+ class _LCapMap=typename _Graph::template EdgeMap<int>,
+ class _UCapMap=_LCapMap,
+ class _DeltaMap=typename _Graph::template NodeMap<
+ typename _UCapMap::Value>,
+ class _Traits=CirculationDefaultTraits<_Graph, _LCapMap,
+ _UCapMap, _DeltaMap> >
class Circulation {
- typedef typename Graph::Node Node;
- typedef typename Graph::NodeIt NodeIt;
- typedef typename Graph::Edge Edge;
- typedef typename Graph::EdgeIt EdgeIt;
- typedef typename Graph::InEdgeIt InEdgeIt;
- typedef typename Graph::OutEdgeIt OutEdgeIt;
-
+
+ typedef _Traits Traits;
+ typedef typename Traits::Graph Graph;
+ GRAPH_TYPEDEFS(typename Graph);
+
+ typedef typename Traits::Value Value;
+
+ typedef typename Traits::LCapMap LCapMap;
+ typedef typename Traits::UCapMap UCapMap;
+ typedef typename Traits::DeltaMap DeltaMap;
+ typedef typename Traits::FlowMap FlowMap;
+ typedef typename Traits::Elevator Elevator;
+ typedef typename Traits::Tolerance Tolerance;
+
+ typedef typename Graph::template NodeMap<Value> ExcessMap;
const Graph &_g;
int _node_num;
- const LCapMap &_lo;
- const UCapMap &_up;
- const DeltaMap &_delta;
- FlowMap &_x;
- Tolerance<Value> _tol;
- Elevator<Graph,typename Graph::Node> _levels;
- typename Graph::template NodeMap<Value> _excess;
+ const LCapMap *_lo;
+ const UCapMap *_up;
+ const DeltaMap *_delta;
+
+ FlowMap *_flow;
+ bool _local_flow;
+
+ Elevator* _level;
+ bool _local_level;
+
+ ExcessMap* _excess;
+
+ Tolerance _tol;
+ int _el;
public:
- ///\e
- Circulation(const Graph &g,const LCapMap &lo,const UCapMap &up,
- const DeltaMap &delta,FlowMap &x) :
- _g(g),
- _node_num(countNodes(g)),
- _lo(lo),_up(up),_delta(delta),_x(x),
- _levels(g,_node_num),
- _excess(g)
- {
+
+ typedef Circulation Create;
+
+ ///\name Named template parameters
+
+ ///@{
+
+ template <typename _FlowMap>
+ struct DefFlowMapTraits : public Traits {
+ typedef _FlowMap FlowMap;
+ static FlowMap *createFlowMap(const Graph&) {
+ throw UninitializedParameter();
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// FlowMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting FlowMap
+ /// type
+ template <typename _FlowMap>
+ struct DefFlowMap
+ : public Circulation<Graph, LCapMap, UCapMap, DeltaMap,
+ DefFlowMapTraits<_FlowMap> > {
+ typedef Circulation<Graph, LCapMap, UCapMap, DeltaMap,
+ DefFlowMapTraits<_FlowMap> > Create;
+ };
+
+ template <typename _Elevator>
+ struct DefElevatorTraits : public Traits {
+ typedef _Elevator Elevator;
+ static Elevator *createElevator(const Graph&, int) {
+ throw UninitializedParameter();
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type
+ template <typename _Elevator>
+ struct DefElevator
+ : public Circulation<Graph, LCapMap, UCapMap, DeltaMap,
+ DefElevatorTraits<_Elevator> > {
+ typedef Circulation<Graph, LCapMap, UCapMap, DeltaMap,
+ DefElevatorTraits<_Elevator> > Create;
+ };
+
+ template <typename _Elevator>
+ struct DefStandardElevatorTraits : public Traits {
+ typedef _Elevator Elevator;
+ static Elevator *createElevator(const Graph& graph, int max_level) {
+ return new Elevator(graph, max_level);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type. The Elevator should be standard constructor interface, ie.
+ /// the graph and the maximum level should be passed to it.
+ template <typename _Elevator>
+ struct DefStandardElevator
+ : public Circulation<Graph, LCapMap, UCapMap, DeltaMap,
+ DefStandardElevatorTraits<_Elevator> > {
+ typedef Circulation<Graph, LCapMap, UCapMap, DeltaMap,
+ DefStandardElevatorTraits<_Elevator> > Create;
+ };
+
+ /// @}
+
+ /// The constructor of the class.
+
+ /// The constructor of the class.
+ /// \param g The directed graph the algorithm runs on.
+ /// \param lo The lower bound capacity of the edges.
+ /// \param up The upper bound capacity of the edges.
+ /// \param delta The lower bound on node excess.
+ Circulation(const Graph &g,const LCapMap &lo,
+ const UCapMap &up,const DeltaMap &delta)
+ : _g(g), _node_num(),
+ _lo(&lo),_up(&up),_delta(&delta),_flow(0),_local_flow(false),
+ _level(0), _local_level(false), _excess(0), _el() {}
+
+ /// Destrcutor.
+ ~Circulation() {
+ destroyStructures();
}
-
+
private:
- void addExcess(Node n,Value v)
- {
- if(_tol.positive(_excess[n]+=v))
- {
- if(!_levels.active(n)) _levels.activate(n);
- }
- else if(_levels.active(n)) _levels.deactivate(n);
+ void createStructures() {
+ _node_num = _el = countNodes(_g);
+
+ if (!_flow) {
+ _flow = Traits::createFlowMap(_g);
+ _local_flow = true;
+ }
+ if (!_level) {
+ _level = Traits::createElevator(_g, _node_num);
+ _local_level = true;
+ }
+ if (!_excess) {
+ _excess = new ExcessMap(_g);
+ }
}
+
+ void destroyStructures() {
+ if (_local_flow) {
+ delete _flow;
+ }
+ if (_local_level) {
+ delete _level;
+ }
+ if (_excess) {
+ delete _excess;
+ }
+ }
+
+ public:
+
+ /// Sets the lower bound capacity map.
+
+ /// Sets the lower bound capacity map.
+ /// \return \c (*this)
+ Circulation& lowerCapMap(const LCapMap& map) {
+ _lo = ↦
+ return *this;
+ }
+
+ /// Sets the upper bound capacity map.
+
+ /// Sets the upper bound capacity map.
+ /// \return \c (*this)
+ Circulation& upperCapMap(const LCapMap& map) {
+ _up = ↦
+ return *this;
+ }
+
+ /// Sets the lower bound map on excess.
+
+ /// Sets the lower bound map on excess.
+ /// \return \c (*this)
+ Circulation& deltaMap(const DeltaMap& map) {
+ _delta = ↦
+ return *this;
+ }
+
+ /// Sets the flow map.
+
+ /// Sets the flow map.
+ /// \return \c (*this)
+ Circulation& flowMap(FlowMap& map) {
+ if (_local_flow) {
+ delete _flow;
+ _local_flow = false;
+ }
+ _flow = ↦
+ return *this;
+ }
+
+ /// Returns the flow map.
+
+ /// \return The flow map.
+ ///
+ const FlowMap& flowMap() {
+ return *_flow;
+ }
+
+ /// Sets the elevator.
+
+ /// Sets the elevator.
+ /// \return \c (*this)
+ Circulation& elevator(Elevator& elevator) {
+ if (_local_level) {
+ delete _level;
+ _local_level = false;
+ }
+ _level = &elevator;
+ return *this;
+ }
+
+ /// Returns the elevator.
+
+ /// \return The elevator.
+ ///
+ const Elevator& elevator() {
+ return *_level;
+ }
+
+ /// Sets the tolerance used by algorithm.
+
+ /// Sets the tolerance used by algorithm.
+ ///
+ Circulation& tolerance(const Tolerance& tolerance) const {
+ _tol = tolerance;
+ return *this;
+ }
+
+ /// Returns the tolerance used by algorithm.
+
+ /// Returns the tolerance used by algorithm.
+ ///
+ const Tolerance& tolerance() const {
+ return tolerance;
+ }
+ /// \name Execution control The simplest way to execute the
+ /// algorithm is to use one of the member functions called \c
+ /// run().
+ /// \n
+ /// If you need more control on initial solution or execution then
+ /// you have to call one \ref init() function and then the start()
+ /// function.
+
+ ///@{
+
+ /// Initializes the internal data structures.
+
+ /// Initializes the internal data structures. This function sets
+ /// all flow values to the lower bound.
+ /// \return This function returns false if the initialization
+ /// process found a barrier.
void init()
{
+ createStructures();
+
+ for(NodeIt n(_g);n!=INVALID;++n) {
+ _excess->set(n, (*_delta)[n]);
+ }
- _x=_lo;
+ for (EdgeIt e(_g);e!=INVALID;++e) {
+ _flow->set(e, (*_lo)[e]);
+ _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_flow)[e]);
+ _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_flow)[e]);
+ }
- for(NodeIt n(_g);n!=INVALID;++n) _excess[n]=_delta[n];
+ typename Graph::template NodeMap<bool> reached(_g, false);
- for(EdgeIt e(_g);e!=INVALID;++e)
- {
- _excess[_g.target(e)]+=_x[e];
- _excess[_g.source(e)]-=_x[e];
- }
-
- _levels.initStart();
+
+ // global relabeling tested, but in general case it provides
+ // worse performance for random graphs
+ _level->initStart();
for(NodeIt n(_g);n!=INVALID;++n)
- _levels.initAddItem(n);
- _levels.initFinish();
+ _level->initAddItem(n);
+ _level->initFinish();
for(NodeIt n(_g);n!=INVALID;++n)
- if(_tol.positive(_excess[n]))
- _levels.activate(n);
+ if(_tol.positive((*_excess)[n]))
+ _level->activate(n);
}
- public:
- ///Check if \c x is a feasible circulation
- template<class FT>
- bool checkX(FT &x) {
- for(EdgeIt e(_g);e!=INVALID;++e)
- if(x[e]<_lo[e]||x[e]>_up[e]) return false;
- for(NodeIt n(_g);n!=INVALID;++n)
- {
- Value dif=-_delta[n];
- for(InEdgeIt e(_g,n);e!=INVALID;++e) dif-=x[e];
- for(OutEdgeIt e(_g,n);e!=INVALID;++e) dif+=x[e];
- if(_tol.negative(dif)) return false;
- }
- return true;
- };
- ///Check if the default \c x is a feasible circulation
- bool checkX() { return checkX(_x); }
+ /// Initializes the internal data structures.
- ///Check if \c bar is a real barrier
-
- ///Check if \c bar is a real barrier
- ///\sa barrier()
- template<class GT>
- bool checkBarrier(GT &bar)
+ /// Initializes the internal data structures. This functions uses
+ /// greedy approach to construct the initial solution.
+ void greedyInit()
{
- Value delta=0;
- for(NodeIt n(_g);n!=INVALID;++n)
- if(bar[n])
- delta-=_delta[n];
- for(EdgeIt e(_g);e!=INVALID;++e)
- {
- Node s=_g.source(e);
- Node t=_g.target(e);
- if(bar[s]&&!bar[t]) delta+=_up[e];
- else if(bar[t]&&!bar[s]) delta-=_lo[e];
+ createStructures();
+
+ for(NodeIt n(_g);n!=INVALID;++n) {
+ _excess->set(n, (*_delta)[n]);
+ }
+
+ for (EdgeIt e(_g);e!=INVALID;++e) {
+ if (!_tol.positive((*_excess)[_g.target(e)] + (*_up)[e])) {
+ _flow->set(e, (*_up)[e]);
+ _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_up)[e]);
+ _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_up)[e]);
+ } else if (_tol.positive((*_excess)[_g.target(e)] + (*_lo)[e])) {
+ _flow->set(e, (*_lo)[e]);
+ _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_up)[e]);
+ _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_up)[e]);
+ } else {
+ Value fc = -(*_excess)[_g.target(e)];
+ _flow->set(e, fc);
+ _excess->set(_g.target(e), 0);
+ _excess->set(_g.source(e), (*_excess)[_g.source(e)] - fc);
}
- return _tol.negative(delta);
- }
- ///Check whether or not the last execution provides a barrier
+ }
+
+ _level->initStart();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ _level->initAddItem(n);
+ _level->initFinish();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ if(_tol.positive((*_excess)[n]))
+ _level->activate(n);
+ }
- ///Check whether or not the last execution provides a barrier
- ///\sa barrier()
- bool checkBarrier()
- {
- typename Graph:: template NodeMap<bool> bar(_g);
- barrier(bar);
- return checkBarrier(bar);
- }
- ///Run the algorithm
-
- ///This function runs the algorithm.
- ///\return This function returns -1 if it found a feasible circulation.
- /// nonnegative values (including 0) mean that no feasible solution is
- /// found. In this case the return value means an "empty level".
+ ///Starts the algorithm
+
+ ///This function starts the algorithm.
+ ///\return This function returns true if it found a feasible circulation.
///
///\sa barrier()
- int run()
+ bool start()
{
- init();
-#ifdef LEMON_CIRCULATION_DEBUG
- for(NodeIt n(_g);n!=INVALID;++n)
- std::cerr<< _levels[n] << ' ';
- std::cerr << std::endl;
-#endif
Node act;
Node bact=INVALID;
Node last_activated=INVALID;
- while((act=_levels.highestActive())!=INVALID) {
- int actlevel=_levels[act];
- int tlevel;
+ while((act=_level->highestActive())!=INVALID) {
+ int actlevel=(*_level)[act];
int mlevel=_node_num;
- Value exc=_excess[act];
- Value fc;
-
-#ifdef LEMON_CIRCULATION_DEBUG
- for(NodeIt n(_g);n!=INVALID;++n)
- std::cerr<< _levels[n] << ' ';
- std::cerr << std::endl;
- std::cerr << "Process node " << _g.id(act)
- << " on level " << actlevel
- << " with excess " << exc
- << std::endl;
-#endif
- for(OutEdgeIt e(_g,act);e!=INVALID; ++e)
- if((fc=_up[e]-_x[e])>0)
- if((tlevel=_levels[_g.target(e)])<actlevel)
- if(fc<=exc) {
- _x[e]=_up[e];
- addExcess(_g.target(e),fc);
- exc-=fc;
-#ifdef LEMON_CIRCULATION_DEBUG
- std::cerr << " Push " << fc
- << " toward " << _g.id(_g.target(e)) << std::endl;
-#endif
- }
- else {
- _x[e]+=exc;
- addExcess(_g.target(e),exc);
- //exc=0;
- _excess[act]=0;
- _levels.deactivate(act);
-#ifdef LEMON_CIRCULATION_DEBUG
- std::cerr << " Push " << exc
- << " toward " << _g.id(_g.target(e)) << std::endl;
- std::cerr << " Deactivate\n";
-#endif
- goto next_l;
- }
- else if(tlevel<mlevel) mlevel=tlevel;
+ Value exc=(*_excess)[act];
- for(InEdgeIt e(_g,act);e!=INVALID; ++e)
- if((fc=_x[e]-_lo[e])>0)
- if((tlevel=_levels[_g.source(e)])<actlevel)
- if(fc<=exc) {
- _x[e]=_lo[e];
- addExcess(_g.source(e),fc);
- exc-=fc;
-#ifdef LEMON_CIRCULATION_DEBUG
- std::cerr << " Push " << fc
- << " toward " << _g.id(_g.source(e)) << std::endl;
-#endif
- }
- else {
- _x[e]-=exc;
- addExcess(_g.source(e),exc);
- //exc=0;
- _excess[act]=0;
- _levels.deactivate(act);
-#ifdef LEMON_CIRCULATION_DEBUG
- std::cerr << " Push " << exc
- << " toward " << _g.id(_g.source(e)) << std::endl;
- std::cerr << " Deactivate\n";
-#endif
- goto next_l;
- }
- else if(tlevel<mlevel) mlevel=tlevel;
+ for(OutEdgeIt e(_g,act);e!=INVALID; ++e) {
+ Node v = _g.target(e);
+ Value fc=(*_up)[e]-(*_flow)[e];
+ if(!_tol.positive(fc)) continue;
+ if((*_level)[v]<actlevel) {
+ if(!_tol.less(fc, exc)) {
+ _flow->set(e, (*_flow)[e] + exc);
+ _excess->set(v, (*_excess)[v] + exc);
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ _excess->set(act,0);
+ _level->deactivate(act);
+ goto next_l;
+ }
+ else {
+ _flow->set(e, (*_up)[e]);
+ _excess->set(v, (*_excess)[v] + exc);
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ exc-=fc;
+ }
+ }
+ else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
+ }
+ for(InEdgeIt e(_g,act);e!=INVALID; ++e) {
+ Node v = _g.source(e);
+ Value fc=(*_flow)[e]-(*_lo)[e];
+ if(!_tol.positive(fc)) continue;
+ if((*_level)[v]<actlevel) {
+ if(!_tol.less(fc, exc)) {
+ _flow->set(e, (*_flow)[e] - exc);
+ _excess->set(v, (*_excess)[v] + exc);
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ _excess->set(act,0);
+ _level->deactivate(act);
+ goto next_l;
+ }
+ else {
+ _flow->set(e, (*_lo)[e]);
+ _excess->set(v, (*_excess)[v] + fc);
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ exc-=fc;
+ }
+ }
+ else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
+ }
- _excess[act]=exc;
- if(!_tol.positive(exc)) _levels.deactivate(act);
+ _excess->set(act, exc);
+ if(!_tol.positive(exc)) _level->deactivate(act);
else if(mlevel==_node_num) {
- _levels.liftHighestActiveToTop();
-#ifdef LEMON_CIRCULATION_DEBUG
- std::cerr << " Lift to level " << _node_num << std::endl;
-#endif
- return _levels.onLevel(_node_num-1)==0?_node_num-1:actlevel;
+ _level->liftHighestActiveToTop();
+ _el = _node_num;
+ return false;
}
else {
- _levels.liftHighestActive(mlevel+1);
-#ifdef LEMON_CIRCULATION_DEBUG
- std::cerr << " Lift to level " << mlevel+1 << std::endl;
-#endif
- if(_levels.onLevel(actlevel)==0)
- return actlevel;
+ _level->liftHighestActive(mlevel+1);
+ if(_level->onLevel(actlevel)==0) {
+ _el = actlevel;
+ return false;
+ }
}
next_l:
;
}
-#ifdef LEMON_CIRCULATION_DEBUG
- std::cerr << "Feasible flow found.\n";
-#endif
- return -1;
+ return true;
+ }
+
+ /// Runs the circulation algorithm.
+
+ /// Runs the circulation algorithm.
+ /// \note fc.run() is just a shortcut of the following code.
+ /// \code
+ /// fc.greedyInit();
+ /// return fc.start();
+ /// \endcode
+ bool run() {
+ greedyInit();
+ return start();
}
+
+ /// @}
+
+ /// \name Query Functions
+ /// The result of the %Circulation algorithm can be obtained using
+ /// these functions.
+ /// \n
+ /// Before the use of these functions,
+ /// either run() or start() must be called.
- ///Return a barrier
+ ///@{
+
+ ///Returns a barrier
///Barrier is a set \e B of nodes for which
/// \f[ \sum_{v\in B}-delta(v)<\sum_{e\in\rho(B)}lo(e)-\sum_{e\in\delta(B)}up(e) \f]
///holds. The existence of a set with this property prooves that a feasible
///flow cannot exists.
- ///\pre The run() must have been executed, and its return value was -1.
///\sa checkBarrier()
///\sa run()
template<class GT>
- void barrier(GT &bar,int empty_level=-1)
+ void barrierMap(GT &bar)
{
- if(empty_level==-1)
- for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
for(NodeIt n(_g);n!=INVALID;++n)
- bar[n] = _levels[n]>empty_level;
+ bar.set(n, (*_level)[n] >= _el);
+ }
+
+ ///Returns true if the node is in the barrier
+
+ ///Returns true if the node is in the barrier
+ ///\sa barrierMap()
+ bool barrier(const Node& node)
+ {
+ return (*_level)[node] >= _el;
}
+ /// \brief Returns the flow on the edge.
+ ///
+ /// Sets the \c flowMap to the flow on the edges. This method can
+ /// be called after the second phase of algorithm.
+ Value flow(const Edge& edge) const {
+ return (*_flow)[edge];
+ }
+
+ /// @}
+
+ /// \name Checker Functions
+ /// The feasibility of the results can be checked using
+ /// these functions.
+ /// \n
+ /// Before the use of these functions,
+ /// either run() or start() must be called.
+
+ ///@{
+
+ ///Check if the \c flow is a feasible circulation
+ bool checkFlow() {
+ for(EdgeIt e(_g);e!=INVALID;++e)
+ if((*_flow)[e]<(*_lo)[e]||(*_flow)[e]>(*_up)[e]) return false;
+ for(NodeIt n(_g);n!=INVALID;++n)
+ {
+ Value dif=-(*_delta)[n];
+ for(InEdgeIt e(_g,n);e!=INVALID;++e) dif-=(*_flow)[e];
+ for(OutEdgeIt e(_g,n);e!=INVALID;++e) dif+=(*_flow)[e];
+ if(_tol.negative(dif)) return false;
+ }
+ return true;
+ }
+
+ ///Check whether or not the last execution provides a barrier
+
+ ///Check whether or not the last execution provides a barrier
+ ///\sa barrier()
+ bool checkBarrier()
+ {
+ Value delta=0;
+ for(NodeIt n(_g);n!=INVALID;++n)
+ if(barrier(n))
+ delta-=(*_delta)[n];
+ for(EdgeIt e(_g);e!=INVALID;++e)
+ {
+ Node s=_g.source(e);
+ Node t=_g.target(e);
+ if(barrier(s)&&!barrier(t)) delta+=(*_up)[e];
+ else if(barrier(t)&&!barrier(s)) delta-=(*_lo)[e];
+ }
+ return _tol.negative(delta);
+ }
+
+ /// @}
+
};
}
Modified: lemon/trunk/lemon/cycle_canceling.h
==============================================================================
--- lemon/trunk/lemon/cycle_canceling.h (original)
+++ lemon/trunk/lemon/cycle_canceling.h Wed Nov 28 18:51:02 2007
@@ -323,11 +323,12 @@
if (sum != 0) return false;
// Finding a feasible flow
- Circulation< Graph, Capacity, FlowMap, ConstMap<Edge, Capacity>,
- CapacityRefMap, SupplyMap >
+ Circulation< Graph, Capacity, ConstMap<Edge, Capacity>,
+ CapacityRefMap, SupplyMap >::DefFlowMap<FlowMap>::Create
circulation( graph, constMap<Edge>((Capacity)0),
- capacity, supply, flow );
- return circulation.run() == -1;
+ capacity, supply);
+ circulation.flowMap(flowMap);
+ return circulation.run();
}
#ifdef LIMITED_CYCLE_CANCELING
More information about the Lemon-commits
mailing list