/* -*- mode: C++; indent-tabs-mode: nil; -*- * * This file is a part of LEMON, a generic C++ optimization library. * * Copyright (C) 2003-2008 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_BFS_H #define LEMON_BFS_H ///\ingroup search ///\file ///\brief BFS algorithm. #include #include #include #include #include namespace lemon { ///Default traits class of Bfs class. ///Default traits class of Bfs class. ///\tparam GR Digraph type. template struct BfsDefaultTraits { ///The type of the digraph the algorithm runs on. typedef GR Digraph; ///\brief The type of the map that stores the predecessor ///arcs of the shortest paths. /// ///The type of the map that stores the predecessor ///arcs of the shortest paths. ///It must meet the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap PredMap; ///Instantiates a \ref PredMap. ///This function instantiates a \ref PredMap. ///\param g is the digraph, to which we would like to define the ///\ref PredMap. ///\todo The digraph alone may be insufficient to initialize static PredMap *createPredMap(const Digraph &g) { return new PredMap(g); } ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. ///It must meet the \ref concepts::WriteMap "WriteMap" concept. ///By default it is a NullMap. typedef NullMap ProcessedMap; ///Instantiates a \ref ProcessedMap. ///This function instantiates a \ref ProcessedMap. ///\param g is the digraph, to which ///we would like to define the \ref ProcessedMap #ifdef DOXYGEN static ProcessedMap *createProcessedMap(const Digraph &g) #else static ProcessedMap *createProcessedMap(const Digraph &) #endif { return new ProcessedMap(); } ///The type of the map that indicates which nodes are reached. ///The type of the map that indicates which nodes are reached. ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; ///Instantiates a \ref ReachedMap. ///This function instantiates a \ref ReachedMap. ///\param g is the digraph, to which ///we would like to define the \ref ReachedMap. static ReachedMap *createReachedMap(const Digraph &g) { return new ReachedMap(g); } ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. ///It must meet the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap DistMap; ///Instantiates a \ref DistMap. ///This function instantiates a \ref DistMap. ///\param g is the digraph, to which we would like to define the ///\ref DistMap. static DistMap *createDistMap(const Digraph &g) { return new DistMap(g); } }; ///%BFS algorithm class. ///\ingroup search ///This class provides an efficient implementation of the %BFS algorithm. /// ///There is also a \ref bfs() "function type interface" for the BFS ///algorithm, which is convenient in the simplier cases and it can be ///used easier. /// ///\tparam GR The type of the digraph the algorithm runs on. ///The default value is \ref ListDigraph. The value of GR is not used ///directly by \ref Bfs, it is only passed to \ref BfsDefaultTraits. ///\tparam TR Traits class to set various data types used by the algorithm. ///The default traits class is ///\ref BfsDefaultTraits "BfsDefaultTraits". ///See \ref BfsDefaultTraits for the documentation of ///a Bfs traits class. #ifdef DOXYGEN template #else template > #endif class Bfs { public: ///\ref Exception for uninitialized parameters. ///This error represents problems in the initialization of the ///parameters of the algorithm. class UninitializedParameter : public lemon::UninitializedParameter { public: virtual const char* what() const throw() { return "lemon::Bfs::UninitializedParameter"; } }; ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; ///\brief The type of the map that stores the predecessor arcs of the ///shortest paths. typedef typename TR::PredMap PredMap; ///The type of the map that stores the distances of the nodes. typedef typename TR::DistMap DistMap; ///The type of the map that indicates which nodes are reached. typedef typename TR::ReachedMap ReachedMap; ///The type of the map that indicates which nodes are processed. typedef typename TR::ProcessedMap ProcessedMap; ///The type of the paths. typedef PredMapPath Path; ///The traits class. typedef TR Traits; private: typedef typename Digraph::Node Node; typedef typename Digraph::NodeIt NodeIt; typedef typename Digraph::Arc Arc; typedef typename Digraph::OutArcIt OutArcIt; //Pointer to the underlying digraph. const Digraph *G; //Pointer to the map of predecessor arcs. PredMap *_pred; //Indicates if _pred is locally allocated (true) or not. bool local_pred; //Pointer to the map of distances. DistMap *_dist; //Indicates if _dist is locally allocated (true) or not. bool local_dist; //Pointer to the map of reached status of the nodes. ReachedMap *_reached; //Indicates if _reached is locally allocated (true) or not. bool local_reached; //Pointer to the map of processed status of the nodes. ProcessedMap *_processed; //Indicates if _processed is locally allocated (true) or not. bool local_processed; std::vector _queue; int _queue_head,_queue_tail,_queue_next_dist; int _curr_dist; ///Creates the maps if necessary. ///\todo Better memory allocation (instead of new). void create_maps() { if(!_pred) { local_pred = true; _pred = Traits::createPredMap(*G); } if(!_dist) { local_dist = true; _dist = Traits::createDistMap(*G); } if(!_reached) { local_reached = true; _reached = Traits::createReachedMap(*G); } if(!_processed) { local_processed = true; _processed = Traits::createProcessedMap(*G); } } protected: Bfs() {} public: typedef Bfs Create; ///\name Named template parameters ///@{ template struct DefPredMapTraits : public Traits { typedef T PredMap; static PredMap *createPredMap(const Digraph &) { throw UninitializedParameter(); } }; ///\brief \ref named-templ-param "Named parameter" for setting ///\ref PredMap type. /// ///\ref named-templ-param "Named parameter" for setting ///\ref PredMap type. template struct DefPredMap : public Bfs< Digraph, DefPredMapTraits > { typedef Bfs< Digraph, DefPredMapTraits > Create; }; template struct DefDistMapTraits : public Traits { typedef T DistMap; static DistMap *createDistMap(const Digraph &) { throw UninitializedParameter(); } }; ///\brief \ref named-templ-param "Named parameter" for setting ///\ref DistMap type. /// ///\ref named-templ-param "Named parameter" for setting ///\ref DistMap type. template struct DefDistMap : public Bfs< Digraph, DefDistMapTraits > { typedef Bfs< Digraph, DefDistMapTraits > Create; }; template struct DefReachedMapTraits : public Traits { typedef T ReachedMap; static ReachedMap *createReachedMap(const Digraph &) { throw UninitializedParameter(); } }; ///\brief \ref named-templ-param "Named parameter" for setting ///\ref ReachedMap type. /// ///\ref named-templ-param "Named parameter" for setting ///\ref ReachedMap type. template struct DefReachedMap : public Bfs< Digraph, DefReachedMapTraits > { typedef Bfs< Digraph, DefReachedMapTraits > Create; }; template struct DefProcessedMapTraits : public Traits { typedef T ProcessedMap; static ProcessedMap *createProcessedMap(const Digraph &) { throw UninitializedParameter(); } }; ///\brief \ref named-templ-param "Named parameter" for setting ///\ref ProcessedMap type. /// ///\ref named-templ-param "Named parameter" for setting ///\ref ProcessedMap type. template struct DefProcessedMap : public Bfs< Digraph, DefProcessedMapTraits > { typedef Bfs< Digraph, DefProcessedMapTraits > Create; }; struct DefDigraphProcessedMapTraits : public Traits { typedef typename Digraph::template NodeMap ProcessedMap; static ProcessedMap *createProcessedMap(const Digraph &g) { return new ProcessedMap(g); } }; ///\brief \ref named-templ-param "Named parameter" for setting ///\ref ProcessedMap type to be Digraph::NodeMap. /// ///\ref named-templ-param "Named parameter" for setting ///\ref ProcessedMap type to be Digraph::NodeMap. ///If you don't set it explicitly, it will be automatically allocated. template struct DefProcessedMapToBeDefaultMap : public Bfs< Digraph, DefDigraphProcessedMapTraits> { typedef Bfs< Digraph, DefDigraphProcessedMapTraits> Create; }; ///@} public: ///Constructor. ///Constructor. ///\param g The digraph the algorithm runs on. Bfs(const Digraph &g) : G(&g), _pred(NULL), local_pred(false), _dist(NULL), local_dist(false), _reached(NULL), local_reached(false), _processed(NULL), local_processed(false) { } ///Destructor. ~Bfs() { if(local_pred) delete _pred; if(local_dist) delete _dist; if(local_reached) delete _reached; if(local_processed) delete _processed; } ///Sets the map that stores the predecessor arcs. ///Sets the map that stores the predecessor arcs. ///If you don't use this function before calling \ref run(), ///it will allocate one. The destructor deallocates this ///automatically allocated map, of course. ///\return (*this) Bfs &predMap(PredMap &m) { if(local_pred) { delete _pred; local_pred=false; } _pred = &m; return *this; } ///Sets the map that indicates which nodes are reached. ///Sets the map that indicates which nodes are reached. ///If you don't use this function before calling \ref run(), ///it will allocate one. The destructor deallocates this ///automatically allocated map, of course. ///\return (*this) Bfs &reachedMap(ReachedMap &m) { if(local_reached) { delete _reached; local_reached=false; } _reached = &m; return *this; } ///Sets the map that indicates which nodes are processed. ///Sets the map that indicates which nodes are processed. ///If you don't use this function before calling \ref run(), ///it will allocate one. The destructor deallocates this ///automatically allocated map, of course. ///\return (*this) Bfs &processedMap(ProcessedMap &m) { if(local_processed) { delete _processed; local_processed=false; } _processed = &m; return *this; } ///Sets the map that stores the distances of the nodes. ///Sets the map that stores the distances of the nodes calculated by ///the algorithm. ///If you don't use this function before calling \ref run(), ///it will allocate one. The destructor deallocates this ///automatically allocated map, of course. ///\return (*this) Bfs &distMap(DistMap &m) { if(local_dist) { delete _dist; local_dist=false; } _dist = &m; return *this; } public: ///\name Execution control ///The simplest way to execute the algorithm is to use ///one of the member functions called \ref lemon::Bfs::run() "run()". ///\n ///If you need more control on the execution, first you must call ///\ref lemon::Bfs::init() "init()", then you can add several source ///nodes with \ref lemon::Bfs::addSource() "addSource()". ///Finally \ref lemon::Bfs::start() "start()" will perform the ///actual path computation. ///@{ ///Initializes the internal data structures. ///Initializes the internal data structures. /// void init() { create_maps(); _queue.resize(countNodes(*G)); _queue_head=_queue_tail=0; _curr_dist=1; for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { _pred->set(u,INVALID); _reached->set(u,false); _processed->set(u,false); } } ///Adds a new source node. ///Adds a new source node to the set of nodes to be processed. /// void addSource(Node s) { if(!(*_reached)[s]) { _reached->set(s,true); _pred->set(s,INVALID); _dist->set(s,0); _queue[_queue_head++]=s; _queue_next_dist=_queue_head; } } ///Processes the next node. ///Processes the next node. /// ///\return The processed node. /// ///\pre The queue must not be empty. Node processNextNode() { if(_queue_tail==_queue_next_dist) { _curr_dist++; _queue_next_dist=_queue_head; } Node n=_queue[_queue_tail++]; _processed->set(n,true); Node m; for(OutArcIt e(*G,n);e!=INVALID;++e) if(!(*_reached)[m=G->target(e)]) { _queue[_queue_head++]=m; _reached->set(m,true); _pred->set(m,e); _dist->set(m,_curr_dist); } return n; } ///Processes the next node. ///Processes the next node and checks if the given target node ///is reached. If the target node is reachable from the processed ///node, then the \c reach parameter will be set to \c true. /// ///\param target The target node. ///\retval reach Indicates if the target node is reached. ///It should be initially \c false. /// ///\return The processed node. /// ///\pre The queue must not be empty. Node processNextNode(Node target, bool& reach) { if(_queue_tail==_queue_next_dist) { _curr_dist++; _queue_next_dist=_queue_head; } Node n=_queue[_queue_tail++]; _processed->set(n,true); Node m; for(OutArcIt e(*G,n);e!=INVALID;++e) if(!(*_reached)[m=G->target(e)]) { _queue[_queue_head++]=m; _reached->set(m,true); _pred->set(m,e); _dist->set(m,_curr_dist); reach = reach || (target == m); } return n; } ///Processes the next node. ///Processes the next node and checks if at least one of reached ///nodes has \c true value in the \c nm node map. If one node ///with \c true value is reachable from the processed node, then the ///\c rnode parameter will be set to the first of such nodes. /// ///\param nm A \c bool (or convertible) node map that indicates the ///possible targets. ///\retval rnode The reached target node. ///It should be initially \c INVALID. /// ///\return The processed node. /// ///\pre The queue must not be empty. template Node processNextNode(const NM& nm, Node& rnode) { if(_queue_tail==_queue_next_dist) { _curr_dist++; _queue_next_dist=_queue_head; } Node n=_queue[_queue_tail++]; _processed->set(n,true); Node m; for(OutArcIt e(*G,n);e!=INVALID;++e) if(!(*_reached)[m=G->target(e)]) { _queue[_queue_head++]=m; _reached->set(m,true); _pred->set(m,e); _dist->set(m,_curr_dist); if (nm[m] && rnode == INVALID) rnode = m; } return n; } ///The next node to be processed. ///Returns the next node to be processed or \c INVALID if the queue ///is empty. Node nextNode() const { return _queue_tail<_queue_head?_queue[_queue_tail]:INVALID; } ///\brief Returns \c false if there are nodes ///to be processed. /// ///Returns \c false if there are nodes ///to be processed in the queue. bool emptyQueue() const { return _queue_tail==_queue_head; } ///Returns the number of the nodes to be processed. ///Returns the number of the nodes to be processed in the queue. int queueSize() const { return _queue_head-_queue_tail; } ///Executes the algorithm. ///Executes the algorithm. /// ///This method runs the %BFS algorithm from the root node(s) ///in order to compute the shortest path to each node. /// ///The algorithm computes ///- the shortest path tree (forest), ///- the distance of each node from the root(s). /// ///\pre init() must be called and at least one root node should be ///added with addSource() before using this function. /// ///\note b.start() is just a shortcut of the following code. ///\code /// while ( !b.emptyQueue() ) { /// b.processNextNode(); /// } ///\endcode void start() { while ( !emptyQueue() ) processNextNode(); } ///Executes the algorithm until the given target node is reached. ///Executes the algorithm until the given target node is reached. /// ///This method runs the %BFS algorithm from the root node(s) ///in order to compute the shortest path to \c dest. /// ///The algorithm computes ///- the shortest path to \c dest, ///- the distance of \c dest from the root(s). /// ///\pre init() must be called and at least one root node should be ///added with addSource() before using this function. /// ///\note b.start(t) is just a shortcut of the following code. ///\code /// bool reach = false; /// while ( !b.emptyQueue() && !reach ) { /// b.processNextNode(t, reach); /// } ///\endcode void start(Node dest) { bool reach = false; while ( !emptyQueue() && !reach ) processNextNode(dest, reach); } ///Executes the algorithm until a condition is met. ///Executes the algorithm until a condition is met. /// ///This method runs the %BFS algorithm from the root node(s) in ///order to compute the shortest path to a node \c v with /// nm[v] true, if such a node can be found. /// ///\param nm A \c bool (or convertible) node map. The algorithm ///will stop when it reaches a node \c v with nm[v] true. /// ///\return The reached node \c v with nm[v] true or ///\c INVALID if no such node was found. /// ///\pre init() must be called and at least one root node should be ///added with addSource() before using this function. /// ///\note b.start(nm) is just a shortcut of the following code. ///\code /// Node rnode = INVALID; /// while ( !b.emptyQueue() && rnode == INVALID ) { /// b.processNextNode(nm, rnode); /// } /// return rnode; ///\endcode template Node start(const NodeBoolMap &nm) { Node rnode = INVALID; while ( !emptyQueue() && rnode == INVALID ) { processNextNode(nm, rnode); } return rnode; } ///Runs the algorithm from the given node. ///This method runs the %BFS algorithm from node \c s ///in order to compute the shortest path to each node. /// ///The algorithm computes ///- the shortest path tree, ///- the distance of each node from the root. /// ///\note b.run(s) is just a shortcut of the following code. ///\code /// b.init(); /// b.addSource(s); /// b.start(); ///\endcode void run(Node s) { init(); addSource(s); start(); } ///Finds the shortest path between \c s and \c t. ///This method runs the %BFS algorithm from node \c s ///in order to compute the shortest path to \c t. /// ///\return The length of the shortest s--t path, ///if \c t is reachable form \c s, \c 0 otherwise. /// ///\note Apart from the return value, b.run(s,t) is just a ///shortcut of the following code. ///\code /// b.init(); /// b.addSource(s); /// b.start(t); ///\endcode int run(Node s,Node t) { init(); addSource(s); start(t); return reached(t) ? _curr_dist : 0; } ///Runs the algorithm to visit all nodes in the digraph. ///This method runs the %BFS algorithm in order to ///compute the shortest path to each node. /// ///The algorithm computes ///- the shortest path tree (forest), ///- the distance of each node from the root(s). /// ///\note b.run(s) is just a shortcut of the following code. ///\code /// b.init(); /// for (NodeIt n(gr); n != INVALID; ++n) { /// if (!b.reached(n)) { /// b.addSource(n); /// b.start(); /// } /// } ///\endcode void run() { init(); for (NodeIt n(*G); n != INVALID; ++n) { if (!reached(n)) { addSource(n); start(); } } } ///@} ///\name Query Functions ///The result of the %BFS algorithm can be obtained using these ///functions.\n ///Either \ref lemon::Bfs::run() "run()" or \ref lemon::Bfs::start() ///"start()" must be called before using them. ///@{ ///The shortest path to a node. ///Returns the shortest path to a node. /// ///\warning \c t should be reachable from the root(s). /// ///\pre Either \ref run() or \ref start() must be called before ///using this function. Path path(Node t) const { return Path(*G, *_pred, t); } ///The distance of a node from the root(s). ///Returns the distance of a node from the root(s). /// ///\warning If node \c v is not reachable from the root(s), then ///the return value of this function is undefined. /// ///\pre Either \ref run() or \ref start() must be called before ///using this function. int dist(Node v) const { return (*_dist)[v]; } ///Returns the 'previous arc' of the shortest path tree for a node. ///This function returns the 'previous arc' of the shortest path ///tree for the node \c v, i.e. it returns the last arc of a ///shortest path from the root(s) to \c v. It is \c INVALID if \c v ///is not reachable from the root(s) or if \c v is a root. /// ///The shortest path tree used here is equal to the shortest path ///tree used in \ref predNode(). /// ///\pre Either \ref run() or \ref start() must be called before ///using this function. Arc predArc(Node v) const { return (*_pred)[v];} ///Returns the 'previous node' of the shortest path tree for a node. ///This function returns the 'previous node' of the shortest path ///tree for the node \c v, i.e. it returns the last but one node ///from a shortest path from the root(s) to \c v. It is \c INVALID ///if \c v is not reachable from the root(s) or if \c v is a root. /// ///The shortest path tree used here is equal to the shortest path ///tree used in \ref predArc(). /// ///\pre Either \ref run() or \ref start() must be called before ///using this function. Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: G->source((*_pred)[v]); } ///\brief Returns a const reference to the node map that stores the /// distances of the nodes. /// ///Returns a const reference to the node map that stores the distances ///of the nodes calculated by the algorithm. /// ///\pre Either \ref run() or \ref init() ///must be called before using this function. const DistMap &distMap() const { return *_dist;} ///\brief Returns a const reference to the node map that stores the ///predecessor arcs. /// ///Returns a const reference to the node map that stores the predecessor ///arcs, which form the shortest path tree. /// ///\pre Either \ref run() or \ref init() ///must be called before using this function. const PredMap &predMap() const { return *_pred;} ///Checks if a node is reachable from the root(s). ///Returns \c true if \c v is reachable from the root(s). ///\pre Either \ref run() or \ref start() ///must be called before using this function. bool reached(Node v) const { return (*_reached)[v]; } ///@} }; ///Default traits class of bfs() function. ///Default traits class of bfs() function. ///\tparam GR Digraph type. template struct BfsWizardDefaultTraits { ///The type of the digraph the algorithm runs on. typedef GR Digraph; ///\brief The type of the map that stores the predecessor ///arcs of the shortest paths. /// ///The type of the map that stores the predecessor ///arcs of the shortest paths. ///It must meet the \ref concepts::WriteMap "WriteMap" concept. typedef NullMap PredMap; ///Instantiates a \ref PredMap. ///This function instantiates a \ref PredMap. ///\param g is the digraph, to which we would like to define the ///\ref PredMap. ///\todo The digraph alone may be insufficient to initialize #ifdef DOXYGEN static PredMap *createPredMap(const Digraph &g) #else static PredMap *createPredMap(const Digraph &) #endif { return new PredMap(); } ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. ///It must meet the \ref concepts::WriteMap "WriteMap" concept. typedef NullMap ProcessedMap; ///Instantiates a \ref ProcessedMap. ///This function instantiates a \ref ProcessedMap. ///\param g is the digraph, to which ///we would like to define the \ref ProcessedMap. #ifdef DOXYGEN static ProcessedMap *createProcessedMap(const Digraph &g) #else static ProcessedMap *createProcessedMap(const Digraph &) #endif { return new ProcessedMap(); } ///The type of the map that indicates which nodes are reached. ///The type of the map that indicates which nodes are reached. ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; ///Instantiates a \ref ReachedMap. ///This function instantiates a \ref ReachedMap. ///\param g is the digraph, to which ///we would like to define the \ref ReachedMap. static ReachedMap *createReachedMap(const Digraph &g) { return new ReachedMap(g); } ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. ///It must meet the \ref concepts::WriteMap "WriteMap" concept. /// typedef NullMap DistMap; ///Instantiates a \ref DistMap. ///This function instantiates a \ref DistMap. ///\param g is the digraph, to which we would like to define ///the \ref DistMap #ifdef DOXYGEN static DistMap *createDistMap(const Digraph &g) #else static DistMap *createDistMap(const Digraph &) #endif { return new DistMap(); } }; /// Default traits class used by \ref BfsWizard /// To make it easier to use Bfs algorithm /// we have created a wizard class. /// This \ref BfsWizard class needs default traits, /// as well as the \ref Bfs class. /// The \ref BfsWizardBase is a class to be the default traits of the /// \ref BfsWizard class. template class BfsWizardBase : public BfsWizardDefaultTraits { typedef BfsWizardDefaultTraits Base; protected: //The type of the nodes in the digraph. typedef typename Base::Digraph::Node Node; //Pointer to the digraph the algorithm runs on. void *_g; //Pointer to the map of reached nodes. void *_reached; //Pointer to the map of processed nodes. void *_processed; //Pointer to the map of predecessors arcs. void *_pred; //Pointer to the map of distances. void *_dist; //Pointer to the source node. Node _source; public: /// Constructor. /// This constructor does not require parameters, therefore it initiates /// all of the attributes to default values (0, INVALID). BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), _dist(0), _source(INVALID) {} /// Constructor. /// This constructor requires some parameters, /// listed in the parameters list. /// Others are initiated to 0. /// \param g The digraph the algorithm runs on. /// \param s The source node. BfsWizardBase(const GR &g, Node s=INVALID) : _g(reinterpret_cast(const_cast(&g))), _reached(0), _processed(0), _pred(0), _dist(0), _source(s) {} }; /// Auxiliary class for the function type interface of BFS algorithm. /// This auxiliary class is created to implement the function type /// interface of \ref Bfs algorithm. It uses the functions and features /// of the plain \ref Bfs, but it is much simpler to use it. /// It should only be used through the \ref bfs() function, which makes /// it easier to use the algorithm. /// /// Simplicity means that the way to change the types defined /// in the traits class is based on functions that returns the new class /// and not on templatable built-in classes. /// When using the plain \ref Bfs /// the new class with the modified type comes from /// the original class by using the :: /// operator. In the case of \ref BfsWizard only /// a function have to be called, and it will /// return the needed class. /// /// It does not have own \ref run() method. When its \ref run() method /// is called, it initiates a plain \ref Bfs object, and calls the /// \ref Bfs::run() method of it. template class BfsWizard : public TR { typedef TR Base; ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; typedef typename Digraph::Node Node; typedef typename Digraph::NodeIt NodeIt; typedef typename Digraph::Arc Arc; typedef typename Digraph::OutArcIt OutArcIt; ///\brief The type of the map that stores the predecessor ///arcs of the shortest paths. typedef typename TR::PredMap PredMap; ///\brief The type of the map that stores the distances of the nodes. typedef typename TR::DistMap DistMap; ///\brief The type of the map that indicates which nodes are reached. typedef typename TR::ReachedMap ReachedMap; ///\brief The type of the map that indicates which nodes are processed. typedef typename TR::ProcessedMap ProcessedMap; public: /// Constructor. BfsWizard() : TR() {} /// Constructor that requires parameters. /// Constructor that requires parameters. /// These parameters will be the default values for the traits class. BfsWizard(const Digraph &g, Node s=INVALID) : TR(g,s) {} ///Copy constructor BfsWizard(const TR &b) : TR(b) {} ~BfsWizard() {} ///Runs BFS algorithm from a source node. ///Runs BFS algorithm from a source node. ///The node can be given with the \ref source() function. void run() { if(Base::_source==INVALID) throw UninitializedParameter(); Bfs alg(*reinterpret_cast(Base::_g)); if(Base::_reached) alg.reachedMap(*reinterpret_cast(Base::_reached)); if(Base::_processed) alg.processedMap(*reinterpret_cast(Base::_processed)); if(Base::_pred) alg.predMap(*reinterpret_cast(Base::_pred)); if(Base::_dist) alg.distMap(*reinterpret_cast(Base::_dist)); alg.run(Base::_source); } ///Runs BFS algorithm from the given node. ///Runs BFS algorithm from the given node. ///\param s is the given source. void run(Node s) { Base::_source=s; run(); } /// Sets the source node, from which the Bfs algorithm runs. /// Sets the source node, from which the Bfs algorithm runs. /// \param s is the source node. BfsWizard &source(Node s) { Base::_source=s; return *this; } template struct DefPredMapBase : public Base { typedef T PredMap; static PredMap *createPredMap(const Digraph &) { return 0; }; DefPredMapBase(const TR &b) : TR(b) {} }; ///\brief \ref named-templ-param "Named parameter" ///for setting \ref PredMap object. /// /// \ref named-templ-param "Named parameter" ///for setting \ref PredMap object. template BfsWizard > predMap(const T &t) { Base::_pred=reinterpret_cast(const_cast(&t)); return BfsWizard >(*this); } template struct DefReachedMapBase : public Base { typedef T ReachedMap; static ReachedMap *createReachedMap(const Digraph &) { return 0; }; DefReachedMapBase(const TR &b) : TR(b) {} }; ///\brief \ref named-templ-param "Named parameter" ///for setting \ref ReachedMap object. /// /// \ref named-templ-param "Named parameter" ///for setting \ref ReachedMap object. template BfsWizard > reachedMap(const T &t) { Base::_reached=reinterpret_cast(const_cast(&t)); return BfsWizard >(*this); } template struct DefProcessedMapBase : public Base { typedef T ProcessedMap; static ProcessedMap *createProcessedMap(const Digraph &) { return 0; }; DefProcessedMapBase(const TR &b) : TR(b) {} }; ///\brief \ref named-templ-param "Named parameter" ///for setting \ref ProcessedMap object. /// /// \ref named-templ-param "Named parameter" ///for setting \ref ProcessedMap object. template BfsWizard > processedMap(const T &t) { Base::_processed=reinterpret_cast(const_cast(&t)); return BfsWizard >(*this); } template struct DefDistMapBase : public Base { typedef T DistMap; static DistMap *createDistMap(const Digraph &) { return 0; }; DefDistMapBase(const TR &b) : TR(b) {} }; ///\brief \ref named-templ-param "Named parameter" ///for setting \ref DistMap object. /// /// \ref named-templ-param "Named parameter" ///for setting \ref DistMap object. template BfsWizard > distMap(const T &t) { Base::_dist=reinterpret_cast(const_cast(&t)); return BfsWizard >(*this); } }; ///Function type interface for Bfs algorithm. /// \ingroup search ///Function type interface for Bfs algorithm. /// ///This function also has several ///\ref named-templ-func-param "named parameters", ///they are declared as the members of class \ref BfsWizard. ///The following ///example shows how to use these parameters. ///\code /// bfs(g,source).predMap(preds).run(); ///\endcode ///\warning Don't forget to put the \ref BfsWizard::run() "run()" ///to the end of the parameter list. ///\sa BfsWizard ///\sa Bfs template BfsWizard > bfs(const GR &g,typename GR::Node s=INVALID) { return BfsWizard >(g,s); } #ifdef DOXYGEN /// \brief Visitor class for BFS. /// /// This class defines the interface of the BfsVisit events, and /// it could be the base of a real visitor class. template struct BfsVisitor { typedef _Digraph Digraph; typedef typename Digraph::Arc Arc; typedef typename Digraph::Node Node; /// \brief Called for the source node(s) of the BFS. /// /// This function is called for the source node(s) of the BFS. void start(const Node& node) {} /// \brief Called when a node is reached first time. /// /// This function is called when a node is reached first time. void reach(const Node& node) {} /// \brief Called when a node is processed. /// /// This function is called when a node is processed. void process(const Node& node) {} /// \brief Called when an arc reaches a new node. /// /// This function is called when the BFS finds an arc whose target node /// is not reached yet. void discover(const Arc& arc) {} /// \brief Called when an arc is examined but its target node is /// already discovered. /// /// This function is called when an arc is examined but its target node is /// already discovered. void examine(const Arc& arc) {} }; #else template struct BfsVisitor { typedef _Digraph Digraph; typedef typename Digraph::Arc Arc; typedef typename Digraph::Node Node; void start(const Node&) {} void reach(const Node&) {} void process(const Node&) {} void discover(const Arc&) {} void examine(const Arc&) {} template struct Constraints { void constraints() { Arc arc; Node node; visitor.start(node); visitor.reach(node); visitor.process(node); visitor.discover(arc); visitor.examine(arc); } _Visitor& visitor; }; }; #endif /// \brief Default traits class of BfsVisit class. /// /// Default traits class of BfsVisit class. /// \tparam _Digraph The type of the digraph the algorithm runs on. template struct BfsVisitDefaultTraits { /// \brief The type of the digraph the algorithm runs on. typedef _Digraph Digraph; /// \brief The type of the map that indicates which nodes are reached. /// /// The type of the map that indicates which nodes are reached. /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; /// \brief Instantiates a \ref ReachedMap. /// /// This function instantiates a \ref ReachedMap. /// \param digraph is the digraph, to which /// we would like to define the \ref ReachedMap. static ReachedMap *createReachedMap(const Digraph &digraph) { return new ReachedMap(digraph); } }; /// \ingroup search /// /// \brief %BFS algorithm class with visitor interface. /// /// This class provides an efficient implementation of the %BFS algorithm /// with visitor interface. /// /// The %BfsVisit class provides an alternative interface to the Bfs /// class. It works with callback mechanism, the BfsVisit object calls /// the member functions of the \c Visitor class on every BFS event. /// /// This interface of the BFS algorithm should be used in special cases /// when extra actions have to be performed in connection with certain /// events of the BFS algorithm. Otherwise consider to use Bfs or bfs() /// instead. /// /// \tparam _Digraph The type of the digraph the algorithm runs on. /// The default value is /// \ref ListDigraph. The value of _Digraph is not used directly by /// \ref BfsVisit, it is only passed to \ref BfsVisitDefaultTraits. /// \tparam _Visitor The Visitor type that is used by the algorithm. /// \ref BfsVisitor "BfsVisitor<_Digraph>" is an empty visitor, which /// does not observe the BFS events. If you want to observe the BFS /// events, you should implement your own visitor class. /// \tparam _Traits Traits class to set various data types used by the /// algorithm. The default traits class is /// \ref BfsVisitDefaultTraits "BfsVisitDefaultTraits<_Digraph>". /// See \ref BfsVisitDefaultTraits for the documentation of /// a BFS visit traits class. #ifdef DOXYGEN template #else template , typename _Traits = BfsDefaultTraits<_Digraph> > #endif class BfsVisit { public: /// \brief \ref Exception for uninitialized parameters. /// /// This error represents problems in the initialization /// of the parameters of the algorithm. class UninitializedParameter : public lemon::UninitializedParameter { public: virtual const char* what() const throw() { return "lemon::BfsVisit::UninitializedParameter"; } }; ///The traits class. typedef _Traits Traits; ///The type of the digraph the algorithm runs on. typedef typename Traits::Digraph Digraph; ///The visitor type used by the algorithm. typedef _Visitor Visitor; ///The type of the map that indicates which nodes are reached. typedef typename Traits::ReachedMap ReachedMap; private: typedef typename Digraph::Node Node; typedef typename Digraph::NodeIt NodeIt; typedef typename Digraph::Arc Arc; typedef typename Digraph::OutArcIt OutArcIt; //Pointer to the underlying digraph. const Digraph *_digraph; //Pointer to the visitor object. Visitor *_visitor; //Pointer to the map of reached status of the nodes. ReachedMap *_reached; //Indicates if _reached is locally allocated (true) or not. bool local_reached; std::vector _list; int _list_front, _list_back; ///Creates the maps if necessary. ///\todo Better memory allocation (instead of new). void create_maps() { if(!_reached) { local_reached = true; _reached = Traits::createReachedMap(*_digraph); } } protected: BfsVisit() {} public: typedef BfsVisit Create; /// \name Named template parameters ///@{ template struct DefReachedMapTraits : public Traits { typedef T ReachedMap; static ReachedMap *createReachedMap(const Digraph &digraph) { throw UninitializedParameter(); } }; /// \brief \ref named-templ-param "Named parameter" for setting /// ReachedMap type. /// /// \ref named-templ-param "Named parameter" for setting ReachedMap type. template struct DefReachedMap : public BfsVisit< Digraph, Visitor, DefReachedMapTraits > { typedef BfsVisit< Digraph, Visitor, DefReachedMapTraits > Create; }; ///@} public: /// \brief Constructor. /// /// Constructor. /// /// \param digraph The digraph the algorithm runs on. /// \param visitor The visitor object of the algorithm. BfsVisit(const Digraph& digraph, Visitor& visitor) : _digraph(&digraph), _visitor(&visitor), _reached(0), local_reached(false) {} /// \brief Destructor. ~BfsVisit() { if(local_reached) delete _reached; } /// \brief Sets the map that indicates which nodes are reached. /// /// Sets the map that indicates which nodes are reached. /// If you don't use this function before calling \ref run(), /// it will allocate one. The destructor deallocates this /// automatically allocated map, of course. /// \return (*this) BfsVisit &reachedMap(ReachedMap &m) { if(local_reached) { delete _reached; local_reached = false; } _reached = &m; return *this; } public: /// \name Execution control /// The simplest way to execute the algorithm is to use /// one of the member functions called \ref lemon::BfsVisit::run() /// "run()". /// \n /// If you need more control on the execution, first you must call /// \ref lemon::BfsVisit::init() "init()", then you can add several /// source nodes with \ref lemon::BfsVisit::addSource() "addSource()". /// Finally \ref lemon::BfsVisit::start() "start()" will perform the /// actual path computation. /// @{ /// \brief Initializes the internal data structures. /// /// Initializes the internal data structures. void init() { create_maps(); _list.resize(countNodes(*_digraph)); _list_front = _list_back = -1; for (NodeIt u(*_digraph) ; u != INVALID ; ++u) { _reached->set(u, false); } } /// \brief Adds a new source node. /// /// Adds a new source node to the set of nodes to be processed. void addSource(Node s) { if(!(*_reached)[s]) { _reached->set(s,true); _visitor->start(s); _visitor->reach(s); _list[++_list_back] = s; } } /// \brief Processes the next node. /// /// Processes the next node. /// /// \return The processed node. /// /// \pre The queue must not be empty. Node processNextNode() { Node n = _list[++_list_front]; _visitor->process(n); Arc e; for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) { Node m = _digraph->target(e); if (!(*_reached)[m]) { _visitor->discover(e); _visitor->reach(m); _reached->set(m, true); _list[++_list_back] = m; } else { _visitor->examine(e); } } return n; } /// \brief Processes the next node. /// /// Processes the next node and checks if the given target node /// is reached. If the target node is reachable from the processed /// node, then the \c reach parameter will be set to \c true. /// /// \param target The target node. /// \retval reach Indicates if the target node is reached. /// It should be initially \c false. /// /// \return The processed node. /// /// \pre The queue must not be empty. Node processNextNode(Node target, bool& reach) { Node n = _list[++_list_front]; _visitor->process(n); Arc e; for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) { Node m = _digraph->target(e); if (!(*_reached)[m]) { _visitor->discover(e); _visitor->reach(m); _reached->set(m, true); _list[++_list_back] = m; reach = reach || (target == m); } else { _visitor->examine(e); } } return n; } /// \brief Processes the next node. /// /// Processes the next node and checks if at least one of reached /// nodes has \c true value in the \c nm node map. If one node /// with \c true value is reachable from the processed node, then the /// \c rnode parameter will be set to the first of such nodes. /// /// \param nm A \c bool (or convertible) node map that indicates the /// possible targets. /// \retval rnode The reached target node. /// It should be initially \c INVALID. /// /// \return The processed node. /// /// \pre The queue must not be empty. template Node processNextNode(const NM& nm, Node& rnode) { Node n = _list[++_list_front]; _visitor->process(n); Arc e; for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) { Node m = _digraph->target(e); if (!(*_reached)[m]) { _visitor->discover(e); _visitor->reach(m); _reached->set(m, true); _list[++_list_back] = m; if (nm[m] && rnode == INVALID) rnode = m; } else { _visitor->examine(e); } } return n; } /// \brief The next node to be processed. /// /// Returns the next node to be processed or \c INVALID if the queue /// is empty. Node nextNode() const { return _list_front != _list_back ? _list[_list_front + 1] : INVALID; } /// \brief Returns \c false if there are nodes /// to be processed. /// /// Returns \c false if there are nodes /// to be processed in the queue. bool emptyQueue() const { return _list_front == _list_back; } /// \brief Returns the number of the nodes to be processed. /// /// Returns the number of the nodes to be processed in the queue. int queueSize() const { return _list_back - _list_front; } /// \brief Executes the algorithm. /// /// Executes the algorithm. /// /// This method runs the %BFS algorithm from the root node(s) /// in order to compute the shortest path to each node. /// /// The algorithm computes /// - the shortest path tree (forest), /// - the distance of each node from the root(s). /// /// \pre init() must be called and at least one root node should be added /// with addSource() before using this function. /// /// \note b.start() is just a shortcut of the following code. /// \code /// while ( !b.emptyQueue() ) { /// b.processNextNode(); /// } /// \endcode void start() { while ( !emptyQueue() ) processNextNode(); } /// \brief Executes the algorithm until the given target node is reached. /// /// Executes the algorithm until the given target node is reached. /// /// This method runs the %BFS algorithm from the root node(s) /// in order to compute the shortest path to \c dest. /// /// The algorithm computes /// - the shortest path to \c dest, /// - the distance of \c dest from the root(s). /// /// \pre init() must be called and at least one root node should be /// added with addSource() before using this function. /// /// \note b.start(t) is just a shortcut of the following code. /// \code /// bool reach = false; /// while ( !b.emptyQueue() && !reach ) { /// b.processNextNode(t, reach); /// } /// \endcode void start(Node dest) { bool reach = false; while ( !emptyQueue() && !reach ) processNextNode(dest, reach); } /// \brief Executes the algorithm until a condition is met. /// /// Executes the algorithm until a condition is met. /// /// This method runs the %BFS algorithm from the root node(s) in /// order to compute the shortest path to a node \c v with /// nm[v] true, if such a node can be found. /// /// \param nm must be a bool (or convertible) node map. The /// algorithm will stop when it reaches a node \c v with /// nm[v] true. /// /// \return The reached node \c v with nm[v] true or /// \c INVALID if no such node was found. /// /// \pre init() must be called and at least one root node should be /// added with addSource() before using this function. /// /// \note b.start(nm) is just a shortcut of the following code. /// \code /// Node rnode = INVALID; /// while ( !b.emptyQueue() && rnode == INVALID ) { /// b.processNextNode(nm, rnode); /// } /// return rnode; /// \endcode template Node start(const NM &nm) { Node rnode = INVALID; while ( !emptyQueue() && rnode == INVALID ) { processNextNode(nm, rnode); } return rnode; } /// \brief Runs the algorithm from the given node. /// /// This method runs the %BFS algorithm from node \c s /// in order to compute the shortest path to each node. /// /// The algorithm computes /// - the shortest path tree, /// - the distance of each node from the root. /// /// \note b.run(s) is just a shortcut of the following code. ///\code /// b.init(); /// b.addSource(s); /// b.start(); ///\endcode void run(Node s) { init(); addSource(s); start(); } /// \brief Runs the algorithm to visit all nodes in the digraph. /// /// This method runs the %BFS algorithm in order to /// compute the shortest path to each node. /// /// The algorithm computes /// - the shortest path tree (forest), /// - the distance of each node from the root(s). /// /// \note b.run(s) is just a shortcut of the following code. ///\code /// b.init(); /// for (NodeIt n(gr); n != INVALID; ++n) { /// if (!b.reached(n)) { /// b.addSource(n); /// b.start(); /// } /// } ///\endcode void run() { init(); for (NodeIt it(*_digraph); it != INVALID; ++it) { if (!reached(it)) { addSource(it); start(); } } } ///@} /// \name Query Functions /// The result of the %BFS algorithm can be obtained using these /// functions.\n /// Either \ref lemon::BfsVisit::run() "run()" or /// \ref lemon::BfsVisit::start() "start()" must be called before /// using them. ///@{ /// \brief Checks if a node is reachable from the root(s). /// /// Returns \c true if \c v is reachable from the root(s). /// \pre Either \ref run() or \ref start() /// must be called before using this function. bool reached(Node v) { return (*_reached)[v]; } ///@} }; } //END OF NAMESPACE LEMON #endif