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