alpar@906: /* -*- C++ -*- ladanyi@1435: * lemon/dfs.h - Part of LEMON, a generic C++ optimization library alpar@906: * alpar@1164: * Copyright (C) 2005 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_DFS_H alpar@921: #define LEMON_DFS_H alpar@780: alpar@780: ///\ingroup flowalgs alpar@780: ///\file alpar@1218: ///\brief Dfs algorithm. alpar@780: alpar@1218: #include klao@946: #include alpar@921: #include alpar@1218: #include alpar@1218: #include alpar@780: alpar@921: namespace lemon { alpar@780: alpar@780: alpar@1218: alpar@1218: ///Default traits class of Dfs class. alpar@1218: alpar@1218: ///Default traits class of Dfs class. alpar@1218: ///\param GR Graph type. alpar@1218: template alpar@1218: struct DfsDefaultTraits 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 %DFS paths. alpar@1218: /// alpar@1218: ///The type of the map that stores the last alpar@1218: ///edges of the %DFS paths. alpar@1218: ///It must meet the \ref concept::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: // ///\brief The type of the map that stores the last but one alpar@1218: // ///nodes of the %DFS paths. alpar@1218: // /// alpar@1218: // ///The type of the map that stores the last but one alpar@1218: // ///nodes of the %DFS paths. alpar@1218: // ///It must meet the \ref concept::WriteMap "WriteMap" concept. alpar@1218: // /// alpar@1218: // typedef NullMap PredNodeMap; alpar@1218: // ///Instantiates a PredNodeMap. alpar@1218: alpar@1218: // ///This function instantiates a \ref PredNodeMap. alpar@1218: // ///\param G is the graph, to which alpar@1218: // ///we would like to define the \ref PredNodeMap alpar@1218: // static PredNodeMap *createPredNodeMap(const GR &G) alpar@1218: // { alpar@1218: // return new PredNodeMap(); 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@1218: ///It must meet the \ref concept::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@1218: ///It must meet the \ref concept::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@1218: ///It must meet the \ref concept::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: ///%DFS algorithm class. alpar@1218: alpar@1218: ///\ingroup flowalgs alpar@1218: ///This class provides an efficient implementation of the %DFS algorithm. alpar@780: /// 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 Dfs, it alpar@1218: ///is only passed to \ref DfsDefaultTraits. 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 DfsDefaultTraits "DfsDefaultTraits". alpar@1218: ///See \ref DfsDefaultTraits for the documentation of alpar@1218: ///a Dfs traits class. alpar@780: /// alpar@1218: ///\author Jacint Szabo and Alpar Juttner alpar@1218: ///\todo A compare object would be nice. alpar@780: alpar@780: #ifdef DOXYGEN alpar@1218: template alpar@780: #else alpar@1218: template > alpar@780: #endif alpar@1218: class Dfs { alpar@780: 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@1218: virtual const char* exceptionName() const { alpar@1218: return "lemon::Dfs::UninitializedParameter"; alpar@1218: } alpar@1218: }; alpar@1218: alpar@1218: typedef TR Traits; alpar@780: ///The type of the underlying graph. alpar@1218: typedef typename TR::Graph Graph; alpar@911: ///\e alpar@780: typedef typename Graph::Node Node; alpar@911: ///\e alpar@780: typedef typename Graph::NodeIt NodeIt; alpar@911: ///\e alpar@780: typedef typename Graph::Edge Edge; alpar@911: ///\e alpar@780: typedef typename Graph::OutEdgeIt OutEdgeIt; alpar@780: alpar@780: ///\brief The type of the map that stores the last alpar@1218: ///edges of the %DFS paths. alpar@1218: typedef typename TR::PredMap PredMap; alpar@1218: // ///\brief The type of the map that stores the last but one alpar@1218: // ///nodes of the %DFS paths. alpar@1218: // typedef typename TR::PredNodeMap PredNodeMap; 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@1218: ///The type of the map that stores the dists of the nodes. alpar@1218: typedef typename TR::DistMap DistMap; alpar@780: private: alpar@802: /// Pointer to the underlying graph. alpar@780: 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@1218: // ///Pointer to the map of predecessors nodes. alpar@1218: // PredNodeMap *_predNode; alpar@1218: // ///Indicates if \ref _predNode is locally allocated (\c true) or not. alpar@1218: // bool local_predNode; 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@780: alpar@1218: std::vector _stack; alpar@1218: int _stack_head; alpar@1218: // ///The source node of the last execution. alpar@1218: // Node source; alpar@780: alpar@1218: ///Creates the maps if necessary. alpar@1218: alpar@1218: ///\todo Error if \c G are \c NULL. alpar@1218: ///\todo Better memory allocation (instead of new). alpar@1218: void create_maps() alpar@780: { alpar@1218: if(!_pred) { alpar@1218: local_pred = true; alpar@1218: _pred = Traits::createPredMap(*G); alpar@780: } alpar@1218: // if(!_predNode) { alpar@1218: // local_predNode = true; alpar@1218: // _predNode = Traits::createPredNodeMap(*G); alpar@1218: // } alpar@1218: if(!_dist) { alpar@1218: local_dist = true; alpar@1218: _dist = Traits::createDistMap(*G); alpar@780: } 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@780: } alpar@780: } alpar@780: alpar@1218: public : alpar@1218: 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; alpar@1218: static PredMap *createPredMap(const Graph &G) alpar@1218: { alpar@1218: throw UninitializedParameter(); alpar@1218: } alpar@1218: }; alpar@1218: ///\ref named-templ-param "Named parameter" for setting PredMap type alpar@1218: alpar@1218: ///\ref named-templ-param "Named parameter" for setting PredMap type alpar@1218: /// alpar@1218: template alpar@1218: class DefPredMap : public Dfs< Graph, alpar@1218: DefPredMapTraits > { }; alpar@1218: alpar@1218: // template alpar@1218: // struct DefPredNodeMapTraits : public Traits { alpar@1218: // typedef T PredNodeMap; alpar@1218: // static PredNodeMap *createPredNodeMap(const Graph &G) alpar@1218: // { alpar@1218: // throw UninitializedParameter(); alpar@1218: // } alpar@1218: // }; alpar@1218: // ///\ref named-templ-param "Named parameter" for setting PredNodeMap type alpar@1218: alpar@1218: // ///\ref named-templ-param "Named parameter" for setting PredNodeMap type alpar@1218: // /// alpar@1218: // template alpar@1218: // class DefPredNodeMap : public Dfs< Graph, alpar@1218: // LengthMap, alpar@1218: // DefPredNodeMapTraits > { }; alpar@1218: alpar@1218: template alpar@1218: struct DefDistMapTraits : public Traits { alpar@1218: typedef T DistMap; alpar@1218: static DistMap *createDistMap(const Graph &G) alpar@1218: { alpar@1218: throw UninitializedParameter(); alpar@1218: } alpar@1218: }; alpar@1218: ///\ref named-templ-param "Named parameter" for setting DistMap type alpar@1218: alpar@1218: ///\ref named-templ-param "Named parameter" for setting DistMap type alpar@1218: /// alpar@1218: template alpar@1218: class DefDistMap : public Dfs< Graph, alpar@1218: DefDistMapTraits > { }; alpar@1218: alpar@1218: template alpar@1218: struct DefReachedMapTraits : public Traits { alpar@1218: typedef T ReachedMap; alpar@1218: static ReachedMap *createReachedMap(const Graph &G) alpar@1218: { alpar@1218: throw UninitializedParameter(); alpar@1218: } alpar@1218: }; alpar@1218: ///\ref named-templ-param "Named parameter" for setting ReachedMap type alpar@1218: alpar@1218: ///\ref named-templ-param "Named parameter" for setting ReachedMap type alpar@1218: /// alpar@1218: template alpar@1218: class DefReachedMap : public Dfs< Graph, alpar@1218: DefReachedMapTraits > { }; alpar@1218: alpar@1218: struct DefGraphReachedMapTraits : public Traits { alpar@1218: typedef typename Graph::template NodeMap ReachedMap; alpar@1218: static ReachedMap *createReachedMap(const Graph &G) alpar@1218: { alpar@1218: return new ReachedMap(G); alpar@1218: } alpar@1218: }; alpar@1218: template alpar@1218: struct DefProcessedMapTraits : public Traits { alpar@1218: typedef T ProcessedMap; alpar@1218: static ProcessedMap *createProcessedMap(const Graph &G) alpar@1218: { alpar@1218: throw UninitializedParameter(); alpar@1218: } alpar@1218: }; alpar@1218: ///\ref named-templ-param "Named parameter" for setting ProcessedMap type alpar@1218: alpar@1218: ///\ref named-templ-param "Named parameter" for setting ProcessedMap type alpar@1218: /// alpar@1218: template alpar@1218: class DefProcessedMap : public Dfs< Graph, alpar@1218: DefProcessedMapTraits > { }; 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. alpar@1218: ///If you don't set it explicitely, it will be automatically allocated. alpar@1218: template alpar@1218: class DefProcessedMapToBeDefaultMap : alpar@1218: public Dfs< Graph, alpar@1218: DefGraphProcessedMapTraits> { }; 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@780: Dfs(const Graph& _G) : alpar@780: G(&_G), alpar@1218: _pred(NULL), local_pred(false), alpar@1218: // _predNode(NULL), local_predNode(false), alpar@1218: _dist(NULL), local_dist(false), alpar@1218: _reached(NULL), local_reached(false), alpar@1218: _processed(NULL), local_processed(false) alpar@780: { } alpar@780: alpar@802: ///Destructor. alpar@780: ~Dfs() alpar@780: { alpar@1218: if(local_pred) delete _pred; alpar@1218: // if(local_predNode) delete _predNode; alpar@1218: if(local_dist) delete _dist; alpar@1218: if(local_reached) delete _reached; alpar@1218: if(local_processed) delete _processed; alpar@780: } alpar@780: alpar@780: ///Sets the map storing the predecessor edges. alpar@780: alpar@780: ///Sets the map storing the predecessor edges. alpar@780: ///If you don't use this function before calling \ref run(), alpar@780: ///it will allocate one. The destuctor deallocates this alpar@780: ///automatically allocated map, of course. alpar@780: ///\return (*this) alpar@1218: Dfs &predMap(PredMap &m) alpar@780: { alpar@1218: if(local_pred) { alpar@1218: delete _pred; alpar@1218: local_pred=false; alpar@780: } alpar@1218: _pred = &m; alpar@780: return *this; alpar@780: } alpar@780: alpar@1218: // ///Sets the map storing the predecessor nodes. alpar@780: alpar@1218: // ///Sets the map storing the predecessor nodes. alpar@1218: // ///If you don't use this function before calling \ref run(), alpar@1218: // ///it will allocate one. The destuctor deallocates this alpar@1218: // ///automatically allocated map, of course. alpar@1218: // ///\return (*this) alpar@1218: // Dfs &predNodeMap(PredNodeMap &m) alpar@1218: // { alpar@1218: // if(local_predNode) { alpar@1218: // delete _predNode; alpar@1218: // local_predNode=false; alpar@1218: // } alpar@1218: // _predNode = &m; alpar@1218: // return *this; alpar@1218: // } alpar@780: alpar@780: ///Sets the map storing the distances calculated by the algorithm. alpar@780: alpar@780: ///Sets the map storing the distances calculated by the algorithm. alpar@780: ///If you don't use this function before calling \ref run(), alpar@780: ///it will allocate one. The destuctor deallocates this alpar@780: ///automatically allocated map, of course. alpar@780: ///\return (*this) alpar@1218: Dfs &distMap(DistMap &m) alpar@780: { alpar@1218: if(local_dist) { alpar@1218: delete _dist; alpar@1218: local_dist=false; alpar@780: } alpar@1218: _dist = &m; alpar@780: return *this; alpar@780: } alpar@780: alpar@1220: ///Sets the map indicating if a node is reached. alpar@1220: alpar@1220: ///Sets the map indicating if a node is reached. alpar@1220: ///If you don't use this function before calling \ref run(), alpar@1220: ///it will allocate one. The destuctor deallocates this alpar@1220: ///automatically allocated map, of course. alpar@1220: ///\return (*this) alpar@1220: Dfs &reachedMap(ReachedMap &m) alpar@1220: { alpar@1220: if(local_reached) { alpar@1220: delete _reached; alpar@1220: local_reached=false; alpar@1220: } alpar@1220: _reached = &m; alpar@1220: return *this; alpar@1220: } alpar@1220: alpar@1220: ///Sets the map indicating if a node is processed. alpar@1220: alpar@1220: ///Sets the map indicating if a node is processed. alpar@1220: ///If you don't use this function before calling \ref run(), alpar@1220: ///it will allocate one. The destuctor deallocates this alpar@1220: ///automatically allocated map, of course. alpar@1220: ///\return (*this) alpar@1220: Dfs &processedMap(ProcessedMap &m) alpar@1220: { alpar@1220: if(local_processed) { alpar@1220: delete _processed; alpar@1220: local_processed=false; alpar@1220: } alpar@1220: _processed = &m; alpar@1220: return *this; alpar@1220: } alpar@1220: 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: alpar@1218: ///Initializes the internal data structures. alpar@1218: alpar@1218: ///Initializes the internal data structures. alpar@1218: /// alpar@1218: void init() alpar@1218: { alpar@1218: create_maps(); alpar@1218: _stack.resize(countNodes(*G)); alpar@1218: _stack_head=-1; alpar@780: for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { alpar@1218: _pred->set(u,INVALID); alpar@1218: // _predNode->set(u,INVALID); alpar@1218: _reached->set(u,false); alpar@1218: _processed->set(u,false); alpar@780: } alpar@780: } alpar@780: alpar@1218: ///Adds a new source node. alpar@780: alpar@1218: ///Adds a new source node to the set of nodes to be processed. alpar@1218: /// athos@1443: ///\bug dists are wrong (or at least strange) in case of multiple sources. 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: // _predNode->set(u,INVALID); alpar@1218: _stack[++_stack_head]=OutEdgeIt(*G,s); alpar@1218: _dist->set(s,_stack_head); alpar@1218: } alpar@1218: } alpar@1218: deba@1529: ///Processes the next edge. alpar@1218: deba@1529: ///Processes the next edge. alpar@1218: /// alpar@1516: ///\return The processed edge. alpar@1516: /// athos@1443: ///\pre The stack must not be empty! alpar@1516: Edge processNextEdge() alpar@1218: { alpar@1218: Node m; alpar@1218: Edge e=_stack[_stack_head]; alpar@1218: if(!(*_reached)[m=G->target(e)]) { alpar@1218: _pred->set(m,e); alpar@1218: _reached->set(m,true); alpar@1218: // _pred_node->set(m,G->source(e)); alpar@1233: ++_stack_head; alpar@1233: _stack[_stack_head] = OutEdgeIt(*G, m); alpar@1218: _dist->set(m,_stack_head); alpar@1218: } alpar@1218: else { alpar@1218: Node n; alpar@1218: while(_stack_head>=0 && alpar@1218: (n=G->source(_stack[_stack_head]), alpar@1218: ++_stack[_stack_head]==INVALID)) alpar@1218: { alpar@1218: _processed->set(n,true); alpar@1218: --_stack_head; alpar@1218: } alpar@1218: } alpar@1516: return e; alpar@1218: } alpar@1218: 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 _stack_head<0; } 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: /// alpar@1218: int queueSize() { return _stack_head+1; } 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 %DFS algorithm from the root node(s) alpar@1218: ///in order to alpar@1218: ///compute the alpar@1218: ///%DFS path to each node. The algorithm computes alpar@1218: ///- The %DFS tree. athos@1443: ///- The distance of each node from the root(s) in the %DFS tree. alpar@1218: /// alpar@1218: void start() alpar@1218: { alpar@1218: while ( !emptyQueue() ) processNextEdge(); alpar@1218: } alpar@1218: alpar@1218: ///Executes the algorithm until \c dest is reached. alpar@1218: alpar@1218: ///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 %DFS algorithm from the root node(s) alpar@1218: ///in order to alpar@1218: ///compute the alpar@1218: ///%DFS path to \c dest. The algorithm computes alpar@1218: ///- The %DFS path to \c dest. athos@1443: ///- The distance of \c dest from the root(s) in the %DFS tree. alpar@1218: /// alpar@1218: void start(Node dest) alpar@1218: { alpar@1233: while ( !emptyQueue() && G->target(_stack[_stack_head])!=dest ) alpar@1233: processNextEdge(); 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: /// alpar@1233: ///\param nm must be a bool (or convertible) edge map. The algorithm athos@1438: ///will stop when it reaches an edge \c e with nm[e]==true. athos@1443: /// athos@1438: ///\warning Contrary to \ref Dfs and \ref Dijkstra, \c nm is an edge map, alpar@1233: ///not a node map. alpar@1218: template alpar@1218: void start(const NM &nm) alpar@1218: { alpar@1233: while ( !emptyQueue() && !nm[_stack[_stack_head]] ) processNextEdge(); alpar@1218: } alpar@1218: alpar@1218: ///Runs %DFS algorithm from node \c s. alpar@1218: alpar@1218: ///This method runs the %DFS algorithm from a root node \c s alpar@1218: ///in order to alpar@1218: ///compute the alpar@1218: ///%DFS path to each node. The algorithm computes alpar@1218: ///- The %DFS tree. athos@1443: ///- The distance of each node from the root in the %DFS tree. alpar@1218: /// alpar@1218: ///\note d.run(s) is just a shortcut of the following code. alpar@1218: ///\code alpar@1218: /// d.init(); alpar@1218: /// d.addSource(s); alpar@1218: /// d.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 %DFS path between \c s and \c t. alpar@1218: alpar@1218: ///Finds the %DFS path between \c s and \c t. alpar@1218: /// alpar@1218: ///\return The length of the %DFS s---t path if there exists one, alpar@1218: ///0 otherwise. athos@1540: ///\note Apart from the return value, d.run(s,t) is alpar@1218: ///just a shortcut of the following code. alpar@1218: ///\code alpar@1218: /// d.init(); alpar@1218: /// d.addSource(s); alpar@1218: /// d.start(t); alpar@1218: ///\endcode alpar@1218: int run(Node s,Node t) { alpar@1218: init(); alpar@1218: addSource(s); alpar@1218: start(t); alpar@1233: return reached(t)?_stack_head+1:0; alpar@1218: } alpar@1218: alpar@1218: ///@} alpar@1218: alpar@1218: ///\name Query Functions alpar@1218: ///The result of the %DFS algorithm can be obtained using these alpar@1218: ///functions.\n alpar@1218: ///Before the use of these functions, alpar@1218: ///either run() or start() must be called. alpar@1218: alpar@1218: ///@{ alpar@1218: alpar@1283: ///Copies the path to \c t on the DFS tree into \c p alpar@1283: athos@1443: ///This function copies the path to \c t on the DFS tree into \c p. athos@1438: ///If \c t is a source itself or unreachable, then it does not alpar@1283: ///alter \c p. athos@1438: ///\todo Is this the right way to handle unreachable nodes? athos@1438: /// alpar@1283: ///\return Returns \c true if a path to \c t was actually copied to \c p, alpar@1283: ///\c false otherwise. alpar@1283: ///\sa DirPath alpar@1283: template alpar@1283: bool getPath(P &p,Node t) alpar@1283: { alpar@1283: if(reached(t)) { alpar@1283: p.clear(); alpar@1283: typename P::Builder b(p); alpar@1283: for(b.setStartNode(t);pred(t)!=INVALID;t=predNode(t)) alpar@1283: b.pushFront(pred(t)); alpar@1283: b.commit(); alpar@1283: return true; alpar@1283: } alpar@1283: return false; 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@780: ///\pre \ref run() must be called before using this function. athos@1438: ///\warning If node \c v is unreachable from the root(s) then the return value alpar@780: ///of this funcion is undefined. alpar@1218: int dist(Node v) const { return (*_dist)[v]; } alpar@780: alpar@1218: ///Returns the 'previous edge' of the %DFS tree. alpar@780: alpar@1218: ///For a node \c v it returns the 'previous edge' alpar@1218: ///of the %DFS path, alpar@1218: ///i.e. it returns the last edge of a %DFS path from the root(s) to \c alpar@780: ///v. It is \ref INVALID alpar@1218: ///if \c v is unreachable from the root(s) or \c v is a root. The alpar@781: ///%DFS tree used here is equal to the %DFS tree used in alpar@1218: ///\ref predNode(Node v). alpar@1218: ///\pre Either \ref run() or \ref start() must be called before using alpar@780: ///this function. alpar@1218: ///\todo predEdge could be a better name. alpar@1218: Edge pred(Node v) const { return (*_pred)[v];} alpar@780: alpar@781: ///Returns the 'previous node' of the %DFS tree. alpar@780: alpar@1218: ///For a node \c v it returns the 'previous node' alpar@1218: ///of the %DFS tree, alpar@1218: ///i.e. it returns the last but one node from a %DFS 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 %DFS tree used here is equal to the %DFS alpar@1218: ///tree used in \ref pred(Node v). alpar@1218: ///\pre Either \ref run() or \ref start() must be called before alpar@780: ///using this function. alpar@1218: Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: alpar@1218: G->source((*_pred)[v]); } alpar@780: alpar@1218: ///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@780: ///be called before using this function. alpar@1218: const DistMap &distMap() const { return *_dist;} alpar@780: alpar@1218: ///Returns a reference to the %DFS edge-tree map. alpar@780: alpar@780: ///Returns a reference to the NodeMap of the edges of the alpar@781: ///%DFS 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@780: alpar@1218: // ///Returns a reference to the map of nodes of %DFS paths. alpar@780: alpar@1218: // ///Returns a reference to the NodeMap of the last but one nodes of the alpar@1218: // ///%DFS tree. alpar@1218: // ///\pre \ref run() must be called before using this function. alpar@1218: // const PredNodeMap &predNodeMap() const { return *_predNode;} alpar@780: alpar@780: ///Checks if a node is reachable from the root. alpar@780: athos@1438: ///Returns \c true if \c v is reachable from the root(s). athos@1438: ///\warning The source nodes are inditated as unreachable. alpar@1218: ///\pre Either \ref run() or \ref start() alpar@1218: ///must be called before using this function. alpar@780: /// alpar@1218: bool reached(Node v) { return (*_reached)[v]; } alpar@1218: alpar@1218: ///@} alpar@1218: }; alpar@1218: alpar@1218: ///Default traits class of Dfs function. alpar@1218: alpar@1218: ///Default traits class of Dfs function. alpar@1218: ///\param GR Graph type. alpar@1218: template alpar@1218: struct DfsWizardDefaultTraits 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 %DFS paths. alpar@1218: /// alpar@1218: ///The type of the map that stores the last alpar@1218: ///edges of the %DFS paths. alpar@1218: ///It must meet the \ref concept::WriteMap "WriteMap" concept. alpar@780: /// 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: // ///\brief The type of the map that stores the last but one alpar@1218: // ///nodes of the %DFS paths. alpar@1218: // /// alpar@1218: // ///The type of the map that stores the last but one alpar@1218: // ///nodes of the %DFS paths. alpar@1218: // ///It must meet the \ref concept::WriteMap "WriteMap" concept. alpar@1218: // /// alpar@1218: // typedef NullMap PredNodeMap; alpar@1218: // ///Instantiates a PredNodeMap. alpar@1218: alpar@1218: // ///This function instantiates a \ref PredNodeMap. alpar@1218: // ///\param G is the graph, to which alpar@1218: // ///we would like to define the \ref PredNodeMap alpar@1218: // static PredNodeMap *createPredNodeMap(const GR &G) alpar@1218: // { alpar@1218: // return new PredNodeMap(); 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@1218: ///It must meet the \ref concept::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@1218: ///It must meet the \ref concept::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@1218: ///It must meet the \ref concept::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 DfsWizard alpar@1218: alpar@1218: /// To make it easier to use Dfs algorithm alpar@1218: ///we have created a wizard class. alpar@1218: /// This \ref DfsWizard class needs default traits, alpar@1218: ///as well as the \ref Dfs class. alpar@1218: /// The \ref DfsWizardBase is a class to be the default traits of the alpar@1218: /// \ref DfsWizard class. alpar@1218: template alpar@1218: class DfsWizardBase : public DfsWizardDefaultTraits alpar@1218: { alpar@1218: alpar@1218: typedef DfsWizardDefaultTraits 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 predecessors nodes. alpar@1218: // void *_predNode; 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: DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), alpar@1218: // _predNode(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: DfsWizardBase(const GR &g, Node s=INVALID) : alpar@1218: _g((void *)&g), _reached(0), _processed(0), _pred(0), alpar@1218: // _predNode(0), alpar@1218: _dist(0), _source(s) {} alpar@1218: alpar@1218: }; alpar@1218: athos@1443: /// A class to make the usage of the Dfs algorithm easier alpar@1218: athos@1443: /// This class is created to make it easier to use the Dfs algorithm. alpar@1218: /// It uses the functions and features of the plain \ref Dfs, 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 Dfs 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 DfsWizard 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 athos@1438: /// it initiates a plain \ref Dfs object, and calls the \ref Dfs::run alpar@1218: /// method of it. alpar@1218: template alpar@1218: class DfsWizard : 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 %DFS paths. alpar@1218: typedef typename TR::PredMap PredMap; alpar@1218: // ///\brief The type of the map that stores the last but one alpar@1218: // ///nodes of the %DFS paths. alpar@1218: // typedef typename TR::PredNodeMap PredNodeMap; athos@1443: ///The type of the map that stores the distances of the nodes. alpar@1218: typedef typename TR::DistMap DistMap; alpar@1218: alpar@1218: public: alpar@1218: /// Constructor. alpar@1218: DfsWizard() : 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: DfsWizard(const Graph &g, Node s=INVALID) : alpar@1218: TR(g,s) {} alpar@1218: alpar@1218: ///Copy constructor alpar@1218: DfsWizard(const TR &b) : TR(b) {} alpar@1218: alpar@1218: ~DfsWizard() {} alpar@1218: alpar@1218: ///Runs Dfs algorithm from a given node. alpar@1218: alpar@1218: ///Runs Dfs 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(); alpar@1218: Dfs alg(*(Graph*)Base::_g); alpar@1218: if(Base::_reached) alg.reachedMap(*(ReachedMap*)Base::_reached); alpar@1218: if(Base::_processed) alg.processedMap(*(ProcessedMap*)Base::_processed); alpar@1218: if(Base::_pred) alg.predMap(*(PredMap*)Base::_pred); alpar@1218: // if(Base::_predNode) alg.predNodeMap(*(PredNodeMap*)Base::_predNode); alpar@1218: if(Base::_dist) alg.distMap(*(DistMap*)Base::_dist); alpar@1218: alg.run(Base::_source); alpar@1218: } alpar@1218: alpar@1218: ///Runs Dfs algorithm from the given node. alpar@1218: alpar@1218: ///Runs Dfs 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 type alpar@1218: /// alpar@1218: /// \ref named-templ-param "Named parameter" alpar@1218: ///function for setting PredMap type alpar@1218: /// alpar@1218: template alpar@1218: DfsWizard > predMap(const T &t) alpar@1218: { alpar@1218: Base::_pred=(void *)&t; alpar@1218: return DfsWizard >(*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: DfsWizard > reachedMap(const T &t) alpar@1218: { alpar@1218: Base::_pred=(void *)&t; alpar@1218: return DfsWizard >(*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: DfsWizard > processedMap(const T &t) alpar@1218: { alpar@1218: Base::_pred=(void *)&t; alpar@1218: return DfsWizard >(*this); alpar@1218: } alpar@1218: alpar@1218: alpar@1218: // template alpar@1218: // struct DefPredNodeMapBase : public Base { alpar@1218: // typedef T PredNodeMap; alpar@1218: // static PredNodeMap *createPredNodeMap(const Graph &G) { return 0; }; alpar@1236: // DefPredNodeMapBase(const TR &b) : TR(b) {} alpar@1218: // }; alpar@1218: alpar@1218: // ///\brief \ref named-templ-param "Named parameter" alpar@1218: // ///function for setting PredNodeMap type alpar@1218: // /// alpar@1218: // /// \ref named-templ-param "Named parameter" alpar@1218: // ///function for setting PredNodeMap type alpar@1218: // /// alpar@1218: // template alpar@1218: // DfsWizard > predNodeMap(const T &t) alpar@1218: // { alpar@1218: // Base::_predNode=(void *)&t; alpar@1218: // return DfsWizard >(*this); 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: DfsWizard > distMap(const T &t) alpar@1218: { alpar@1218: Base::_dist=(void *)&t; alpar@1218: return DfsWizard >(*this); alpar@1218: } alpar@1218: alpar@1218: /// Sets the source node, from which the Dfs algorithm runs. alpar@1218: alpar@1218: /// Sets the source node, from which the Dfs algorithm runs. alpar@1218: /// \param s is the source node. alpar@1218: DfsWizard &source(Node s) alpar@1218: { alpar@1218: Base::_source=s; alpar@1218: return *this; alpar@1218: } alpar@780: alpar@780: }; alpar@780: alpar@1218: ///Function type interface for Dfs algorithm. alpar@1218: alpar@1218: /// \ingroup flowalgs alpar@1218: ///Function type interface for Dfs 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 DfsWizard. alpar@1218: ///The following alpar@1218: ///example shows how to use these parameters. alpar@1218: ///\code alpar@1218: /// dfs(g,source).predMap(preds).run(); alpar@1218: ///\endcode alpar@1218: ///\warning Don't forget to put the \ref DfsWizard::run() "run()" alpar@1218: ///to the end of the parameter list. alpar@1218: ///\sa DfsWizard alpar@1218: ///\sa Dfs alpar@1218: template alpar@1218: DfsWizard > alpar@1218: dfs(const GR &g,typename GR::Node s=INVALID) alpar@1218: { alpar@1218: return DfsWizard >(g,s); alpar@1218: } alpar@1218: alpar@921: } //END OF NAMESPACE LEMON alpar@780: alpar@780: #endif alpar@780: