diff --git a/lemon/Makefile.am b/lemon/Makefile.am --- a/lemon/Makefile.am +++ b/lemon/Makefile.am @@ -15,9 +15,13 @@ lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_LIBS) lemon_HEADERS += \ - lemon/concept_check.h \ + lemon/bfs.h \ + lemon/bin_heap.h \ + lemon/dfs.h \ + lemon/dijkstra.h \ lemon/dim2.h \ lemon/error.h \ + lemon/graph_utils.h \ lemon/list_graph.h \ lemon/maps.h \ lemon/path.h \ @@ -32,6 +36,7 @@ lemon/bits/graph_extender.h \ lemon/bits/invalid.h \ lemon/bits/map_extender.h \ + lemon/bits/path_dump.h \ lemon/bits/traits.h \ lemon/bits/utility.h \ lemon/bits/vector_map.h @@ -40,6 +45,7 @@ lemon/concept_check.h \ lemon/concepts/digraph.h \ lemon/concepts/graph.h \ + lemon/concepts/heap.h \ lemon/concepts/maps.h \ lemon/concepts/path.h \ lemon/concepts/graph_components.h diff --git a/lemon/bfs.h b/lemon/bfs.h new file mode 100644 --- /dev/null +++ b/lemon/bfs.h @@ -0,0 +1,1597 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_BFS_H +#define LEMON_BFS_H + +///\ingroup search +///\file +///\brief Bfs algorithm. + +#include +#include +#include +#include +#include +#include + +namespace lemon { + + + + ///Default traits class of Bfs class. + + ///Default traits class of Bfs class. + ///\param GR Digraph type. + template + struct BfsDefaultTraits + { + ///The digraph type the algorithm runs on. + typedef GR Digraph; + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + /// + ///The type of the map that stores the last + ///arcs of the shortest paths. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef typename Digraph::template NodeMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the digraph, to which we would like to define the PredMap. + ///\todo The digraph alone may be insufficient to initialize + static PredMap *createPredMap(const GR &G) + { + return new PredMap(G); + } + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param g is the digraph, to which + ///we would like to define the \ref ProcessedMap +#ifdef DOXYGEN + static ProcessedMap *createProcessedMap(const GR &g) +#else + static ProcessedMap *createProcessedMap(const GR &) +#endif + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Digraph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the digraph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef typename Digraph::template NodeMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the digraph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &G) + { + return new DistMap(G); + } + }; + + ///%BFS algorithm class. + + ///\ingroup search + ///This class provides an efficient implementation of the %BFS algorithm. + /// + ///\param GR The digraph type the algorithm runs on. The default value is + ///\ref ListDigraph. The value of GR is not used directly by Bfs, it + ///is only passed to \ref BfsDefaultTraits. + ///\param TR Traits class to set various data types used by the algorithm. + ///The default traits class is + ///\ref BfsDefaultTraits "BfsDefaultTraits". + ///See \ref BfsDefaultTraits for the documentation of + ///a Bfs traits class. + /// + ///\author Alpar Juttner + +#ifdef DOXYGEN + template +#else + template > +#endif + class Bfs { + public: + /** + * \brief \ref Exception for uninitialized parameters. + * + * This error represents problems in the initialization + * of the parameters of the algorithms. + */ + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* what() const throw() { + return "lemon::Bfs::UninitializedParameter"; + } + }; + + typedef TR Traits; + ///The type of the underlying digraph. + typedef typename TR::Digraph Digraph; + + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + typedef typename TR::PredMap PredMap; + ///The type of the map indicating which nodes are reached. + typedef typename TR::ReachedMap ReachedMap; + ///The type of the map indicating which nodes are processed. + typedef typename TR::ProcessedMap ProcessedMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + private: + + typedef typename Digraph::Node Node; + typedef typename Digraph::NodeIt NodeIt; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::OutArcIt OutArcIt; + + /// Pointer to the underlying digraph. + const Digraph *G; + ///Pointer to the map of predecessors arcs. + PredMap *_pred; + ///Indicates if \ref _pred is locally allocated (\c true) or not. + bool local_pred; + ///Pointer to the map of distances. + DistMap *_dist; + ///Indicates if \ref _dist is locally allocated (\c true) or not. + bool local_dist; + ///Pointer to the map of reached status of the nodes. + ReachedMap *_reached; + ///Indicates if \ref _reached is locally allocated (\c true) or not. + bool local_reached; + ///Pointer to the map of processed status of the nodes. + ProcessedMap *_processed; + ///Indicates if \ref _processed is locally allocated (\c true) or not. + bool local_processed; + + std::vector _queue; + int _queue_head,_queue_tail,_queue_next_dist; + int _curr_dist; + + ///Creates the maps if necessary. + + ///\todo Better memory allocation (instead of new). + void create_maps() + { + if(!_pred) { + local_pred = true; + _pred = Traits::createPredMap(*G); + } + if(!_dist) { + local_dist = true; + _dist = Traits::createDistMap(*G); + } + if(!_reached) { + local_reached = true; + _reached = Traits::createReachedMap(*G); + } + if(!_processed) { + local_processed = true; + _processed = Traits::createProcessedMap(*G); + } + } + + protected: + + Bfs() {} + + public: + + typedef Bfs Create; + + ///\name Named template parameters + + ///@{ + + template + struct DefPredMapTraits : public Traits { + typedef T PredMap; + static PredMap *createPredMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///PredMap type + /// + ///\ref named-templ-param "Named parameter" for setting PredMap type + /// + template + struct DefPredMap : public Bfs< Digraph, DefPredMapTraits > { + typedef Bfs< Digraph, DefPredMapTraits > Create; + }; + + template + struct DefDistMapTraits : public Traits { + typedef T DistMap; + static DistMap *createDistMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///DistMap type + /// + ///\ref named-templ-param "Named parameter" for setting DistMap type + /// + template + struct DefDistMap : public Bfs< Digraph, DefDistMapTraits > { + typedef Bfs< Digraph, DefDistMapTraits > Create; + }; + + template + struct DefReachedMapTraits : public Traits { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///ReachedMap type + /// + ///\ref named-templ-param "Named parameter" for setting ReachedMap type + /// + template + struct DefReachedMap : public Bfs< Digraph, DefReachedMapTraits > { + typedef Bfs< Digraph, DefReachedMapTraits > Create; + }; + + template + struct DefProcessedMapTraits : public Traits { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///ProcessedMap type + /// + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + /// + template + struct DefProcessedMap : public Bfs< Digraph, DefProcessedMapTraits > { + typedef Bfs< Digraph, DefProcessedMapTraits > Create; + }; + + struct DefDigraphProcessedMapTraits : public Traits { + typedef typename Digraph::template NodeMap ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &G) + { + return new ProcessedMap(G); + } + }; + ///\brief \ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Digraph::NodeMap. + /// + ///\ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Digraph::NodeMap. + ///If you don't set it explicitly, it will be automatically allocated. + template + struct DefProcessedMapToBeDefaultMap : + public Bfs< Digraph, DefDigraphProcessedMapTraits> { + typedef Bfs< Digraph, DefDigraphProcessedMapTraits> Create; + }; + + ///@} + + public: + + ///Constructor. + + ///\param _G the digraph the algorithm will run on. + /// + Bfs(const Digraph& _G) : + G(&_G), + _pred(NULL), local_pred(false), + _dist(NULL), local_dist(false), + _reached(NULL), local_reached(false), + _processed(NULL), local_processed(false) + { } + + ///Destructor. + ~Bfs() + { + if(local_pred) delete _pred; + if(local_dist) delete _dist; + if(local_reached) delete _reached; + if(local_processed) delete _processed; + } + + ///Sets the map storing the predecessor arcs. + + ///Sets the map storing the predecessor arcs. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &predMap(PredMap &m) + { + if(local_pred) { + delete _pred; + local_pred=false; + } + _pred = &m; + return *this; + } + + ///Sets the map indicating the reached nodes. + + ///Sets the map indicating the reached nodes. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &reachedMap(ReachedMap &m) + { + if(local_reached) { + delete _reached; + local_reached=false; + } + _reached = &m; + return *this; + } + + ///Sets the map indicating the processed nodes. + + ///Sets the map indicating the processed nodes. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &processedMap(ProcessedMap &m) + { + if(local_processed) { + delete _processed; + local_processed=false; + } + _processed = &m; + return *this; + } + + ///Sets the map storing the distances calculated by the algorithm. + + ///Sets the map storing the distances calculated by the algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &distMap(DistMap &m) + { + if(local_dist) { + delete _dist; + local_dist=false; + } + _dist = &m; + return *this; + } + + public: + ///\name Execution control + ///The simplest way to execute the algorithm is to use + ///one of the member functions called \c run(...). + ///\n + ///If you need more control on the execution, + ///first you must call \ref init(), then you can add several source nodes + ///with \ref addSource(). + ///Finally \ref start() will perform the actual path + ///computation. + + ///@{ + + ///\brief Initializes the internal data structures. + /// + ///Initializes the internal data structures. + /// + void init() + { + create_maps(); + _queue.resize(countNodes(*G)); + _queue_head=_queue_tail=0; + _curr_dist=1; + for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { + _pred->set(u,INVALID); + _reached->set(u,false); + _processed->set(u,false); + } + } + + ///Adds a new source node. + + ///Adds a new source node to the set of nodes to be processed. + /// + void addSource(Node s) + { + if(!(*_reached)[s]) + { + _reached->set(s,true); + _pred->set(s,INVALID); + _dist->set(s,0); + _queue[_queue_head++]=s; + _queue_next_dist=_queue_head; + } + } + + ///Processes the next node. + + ///Processes the next node. + /// + ///\return The processed node. + /// + ///\warning The queue must not be empty! + Node processNextNode() + { + if(_queue_tail==_queue_next_dist) { + _curr_dist++; + _queue_next_dist=_queue_head; + } + Node n=_queue[_queue_tail++]; + _processed->set(n,true); + Node m; + for(OutArcIt e(*G,n);e!=INVALID;++e) + if(!(*_reached)[m=G->target(e)]) { + _queue[_queue_head++]=m; + _reached->set(m,true); + _pred->set(m,e); + _dist->set(m,_curr_dist); + } + return n; + } + + ///Processes the next node. + + ///Processes the next node. And checks that the given target node + ///is reached. If the target node is reachable from the processed + ///node then the reached parameter will be set true. The reached + ///parameter should be initially false. + /// + ///\param target The target node. + ///\retval reach Indicates that the target node is reached. + ///\return The processed node. + /// + ///\warning The queue must not be empty! + Node processNextNode(Node target, bool& reach) + { + if(_queue_tail==_queue_next_dist) { + _curr_dist++; + _queue_next_dist=_queue_head; + } + Node n=_queue[_queue_tail++]; + _processed->set(n,true); + Node m; + for(OutArcIt e(*G,n);e!=INVALID;++e) + if(!(*_reached)[m=G->target(e)]) { + _queue[_queue_head++]=m; + _reached->set(m,true); + _pred->set(m,e); + _dist->set(m,_curr_dist); + reach = reach || (target == m); + } + return n; + } + + ///Processes the next node. + + ///Processes the next node. And checks that at least one of + ///reached node has true value in the \c nm node map. If one node + ///with true value is reachable from the processed node then the + ///rnode parameter will be set to the first of such nodes. + /// + ///\param nm The node map of possible targets. + ///\retval rnode The reached target node. + ///\return The processed node. + /// + ///\warning The queue must not be empty! + template + Node processNextNode(const NM& nm, Node& rnode) + { + if(_queue_tail==_queue_next_dist) { + _curr_dist++; + _queue_next_dist=_queue_head; + } + Node n=_queue[_queue_tail++]; + _processed->set(n,true); + Node m; + for(OutArcIt e(*G,n);e!=INVALID;++e) + if(!(*_reached)[m=G->target(e)]) { + _queue[_queue_head++]=m; + _reached->set(m,true); + _pred->set(m,e); + _dist->set(m,_curr_dist); + if (nm[m] && rnode == INVALID) rnode = m; + } + return n; + } + + ///Next node to be processed. + + ///Next node to be processed. + /// + ///\return The next node to be processed or INVALID if the queue is + /// empty. + Node nextNode() + { + return _queue_tail<_queue_head?_queue[_queue_tail]:INVALID; + } + + ///\brief Returns \c false if there are nodes + ///to be processed in the queue + /// + ///Returns \c false if there are nodes + ///to be processed in the queue + bool emptyQueue() { return _queue_tail==_queue_head; } + ///Returns the number of the nodes to be processed. + + ///Returns the number of the nodes to be processed in the queue. + int queueSize() { return _queue_head-_queue_tail; } + + ///Executes the algorithm. + + ///Executes the algorithm. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %BFS algorithm from the root node(s) + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root(s). + void start() + { + while ( !emptyQueue() ) processNextNode(); + } + + ///Executes the algorithm until \c dest is reached. + + ///Executes the algorithm until \c dest is reached. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %BFS algorithm from the root node(s) + ///in order to compute the shortest path to \c dest. + ///The algorithm computes + ///- The shortest path to \c dest. + ///- The distance of \c dest from the root(s). + void start(Node dest) + { + bool reach = false; + while ( !emptyQueue() && !reach ) processNextNode(dest, reach); + } + + ///Executes the algorithm until a condition is met. + + ///Executes the algorithm until a condition is met. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///\param nm must be a bool (or convertible) node map. The + ///algorithm will stop when it reaches a node \c v with + /// nm[v] true. + /// + ///\return The reached node \c v with nm[v] true or + ///\c INVALID if no such node was found. + template + Node start(const NM &nm) + { + Node rnode = INVALID; + while ( !emptyQueue() && rnode == INVALID ) { + processNextNode(nm, rnode); + } + return rnode; + } + + ///Runs %BFS algorithm from node \c s. + + ///This method runs the %BFS algorithm from a root node \c s + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root. + /// + ///\note b.run(s) is just a shortcut of the following code. + ///\code + /// b.init(); + /// b.addSource(s); + /// b.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + ///Finds the shortest path between \c s and \c t. + + ///Finds the shortest path between \c s and \c t. + /// + ///\return The length of the shortest s---t path if there exists one, + ///0 otherwise. + ///\note Apart from the return value, b.run(s) is + ///just a shortcut of the following code. + ///\code + /// b.init(); + /// b.addSource(s); + /// b.start(t); + ///\endcode + int run(Node s,Node t) { + init(); + addSource(s); + start(t); + return reached(t) ? _curr_dist : 0; + } + + ///@} + + ///\name Query Functions + ///The result of the %BFS algorithm can be obtained using these + ///functions.\n + ///Before the use of these functions, + ///either run() or start() must be calleb. + + ///@{ + + typedef PredMapPath Path; + + ///Gives back the shortest path. + + ///Gives back the shortest path. + ///\pre The \c t should be reachable from the source. + Path path(Node t) + { + return Path(*G, *_pred, t); + } + + ///The distance of a node from the root(s). + + ///Returns the distance of a node from the root(s). + ///\pre \ref run() must be called before using this function. + ///\warning If node \c v in unreachable from the root(s) the return value + ///of this function is undefined. + int dist(Node v) const { return (*_dist)[v]; } + + ///Returns the 'previous arc' of the shortest path tree. + + ///For a node \c v it returns the 'previous arc' + ///of the shortest path tree, + ///i.e. it returns the last arc of a shortest path from the root(s) to \c + ///v. It is \ref INVALID + ///if \c v is unreachable from the root(s) or \c v is a root. The + ///shortest path tree used here is equal to the shortest path tree used in + ///\ref predNode(). + ///\pre Either \ref run() or \ref start() must be called before using + ///this function. + Arc predArc(Node v) const { return (*_pred)[v];} + + ///Returns the 'previous node' of the shortest path tree. + + ///For a node \c v it returns the 'previous node' + ///of the shortest path tree, + ///i.e. it returns the last but one node from a shortest path from the + ///root(a) to \c /v. + ///It is INVALID if \c v is unreachable from the root(s) or + ///if \c v itself a root. + ///The shortest path tree used here is equal to the shortest path + ///tree used in \ref predArc(). + ///\pre Either \ref run() or \ref start() must be called before + ///using this function. + Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: + G->source((*_pred)[v]); } + + ///Returns a reference to the NodeMap of distances. + + ///Returns a reference to the NodeMap of distances. + ///\pre Either \ref run() or \ref init() must + ///be called before using this function. + const DistMap &distMap() const { return *_dist;} + + ///Returns a reference to the shortest path tree map. + + ///Returns a reference to the NodeMap of the arcs of the + ///shortest path tree. + ///\pre Either \ref run() or \ref init() + ///must be called before using this function. + const PredMap &predMap() const { return *_pred;} + + ///Checks if a node is reachable from the root. + + ///Returns \c true if \c v is reachable from the root. + ///\warning The source nodes are indicated as unreached. + ///\pre Either \ref run() or \ref start() + ///must be called before using this function. + /// + bool reached(Node v) { return (*_reached)[v]; } + + ///@} + }; + + ///Default traits class of Bfs function. + + ///Default traits class of Bfs function. + ///\param GR Digraph type. + template + struct BfsWizardDefaultTraits + { + ///The digraph type the algorithm runs on. + typedef GR Digraph; + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + /// + ///The type of the map that stores the last + ///arcs of the shortest paths. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef NullMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param g is the digraph, to which we would like to define the PredMap. + ///\todo The digraph alone may be insufficient to initialize +#ifdef DOXYGEN + static PredMap *createPredMap(const GR &g) +#else + static PredMap *createPredMap(const GR &) +#endif + { + return new PredMap(); + } + + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param g is the digraph, to which + ///we would like to define the \ref ProcessedMap +#ifdef DOXYGEN + static ProcessedMap *createProcessedMap(const GR &g) +#else + static ProcessedMap *createProcessedMap(const GR &) +#endif + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Digraph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the digraph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef NullMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param g is the digraph, to which we would like to define the \ref DistMap +#ifdef DOXYGEN + static DistMap *createDistMap(const GR &g) +#else + static DistMap *createDistMap(const GR &) +#endif + { + return new DistMap(); + } + }; + + /// Default traits used by \ref BfsWizard + + /// To make it easier to use Bfs algorithm + ///we have created a wizard class. + /// This \ref BfsWizard class needs default traits, + ///as well as the \ref Bfs class. + /// The \ref BfsWizardBase is a class to be the default traits of the + /// \ref BfsWizard class. + template + class BfsWizardBase : public BfsWizardDefaultTraits + { + + typedef BfsWizardDefaultTraits Base; + protected: + /// Type of the nodes in the digraph. + typedef typename Base::Digraph::Node Node; + + /// Pointer to the underlying digraph. + void *_g; + ///Pointer to the map of reached nodes. + void *_reached; + ///Pointer to the map of processed nodes. + void *_processed; + ///Pointer to the map of predecessors arcs. + void *_pred; + ///Pointer to the map of distances. + void *_dist; + ///Pointer to the source node. + Node _source; + + public: + /// Constructor. + + /// This constructor does not require parameters, therefore it initiates + /// all of the attributes to default values (0, INVALID). + BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), + _dist(0), _source(INVALID) {} + + /// Constructor. + + /// This constructor requires some parameters, + /// listed in the parameters list. + /// Others are initiated to 0. + /// \param g is the initial value of \ref _g + /// \param s is the initial value of \ref _source + BfsWizardBase(const GR &g, Node s=INVALID) : + _g(reinterpret_cast(const_cast(&g))), + _reached(0), _processed(0), _pred(0), _dist(0), _source(s) {} + + }; + + /// A class to make the usage of Bfs algorithm easier + + /// This class is created to make it easier to use Bfs algorithm. + /// It uses the functions and features of the plain \ref Bfs, + /// but it is much simpler to use it. + /// + /// Simplicity means that the way to change the types defined + /// in the traits class is based on functions that returns the new class + /// and not on templatable built-in classes. + /// When using the plain \ref Bfs + /// the new class with the modified type comes from + /// the original class by using the :: + /// operator. In the case of \ref BfsWizard only + /// a function have to be called and it will + /// return the needed class. + /// + /// It does not have own \ref run method. When its \ref run method is called + /// it initiates a plain \ref Bfs class, and calls the \ref Bfs::run + /// method of it. + template + class BfsWizard : public TR + { + typedef TR Base; + + ///The type of the underlying digraph. + typedef typename TR::Digraph Digraph; + //\e + typedef typename Digraph::Node Node; + //\e + typedef typename Digraph::NodeIt NodeIt; + //\e + typedef typename Digraph::Arc Arc; + //\e + typedef typename Digraph::OutArcIt OutArcIt; + + ///\brief The type of the map that stores + ///the reached nodes + typedef typename TR::ReachedMap ReachedMap; + ///\brief The type of the map that stores + ///the processed nodes + typedef typename TR::ProcessedMap ProcessedMap; + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + typedef typename TR::PredMap PredMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + + public: + /// Constructor. + BfsWizard() : TR() {} + + /// Constructor that requires parameters. + + /// Constructor that requires parameters. + /// These parameters will be the default values for the traits class. + BfsWizard(const Digraph &g, Node s=INVALID) : + TR(g,s) {} + + ///Copy constructor + BfsWizard(const TR &b) : TR(b) {} + + ~BfsWizard() {} + + ///Runs Bfs algorithm from a given node. + + ///Runs Bfs algorithm from a given node. + ///The node can be given by the \ref source function. + void run() + { + if(Base::_source==INVALID) throw UninitializedParameter(); + Bfs alg(*reinterpret_cast(Base::_g)); + if(Base::_reached) + alg.reachedMap(*reinterpret_cast(Base::_reached)); + if(Base::_processed) + alg.processedMap(*reinterpret_cast(Base::_processed)); + if(Base::_pred) + alg.predMap(*reinterpret_cast(Base::_pred)); + if(Base::_dist) + alg.distMap(*reinterpret_cast(Base::_dist)); + alg.run(Base::_source); + } + + ///Runs Bfs algorithm from the given node. + + ///Runs Bfs algorithm from the given node. + ///\param s is the given source. + void run(Node s) + { + Base::_source=s; + run(); + } + + template + struct DefPredMapBase : public Base { + typedef T PredMap; + static PredMap *createPredMap(const Digraph &) { return 0; }; + DefPredMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting PredMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting PredMap + /// + template + BfsWizard > predMap(const T &t) + { + Base::_pred=reinterpret_cast(const_cast(&t)); + return BfsWizard >(*this); + } + + + template + struct DefReachedMapBase : public Base { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Digraph &) { return 0; }; + DefReachedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + template + BfsWizard > reachedMap(const T &t) + { + Base::_pred=reinterpret_cast(const_cast(&t)); + return BfsWizard >(*this); + } + + + template + struct DefProcessedMapBase : public Base { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &) { return 0; }; + DefProcessedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + template + BfsWizard > processedMap(const T &t) + { + Base::_pred=reinterpret_cast(const_cast(&t)); + return BfsWizard >(*this); + } + + + template + struct DefDistMapBase : public Base { + typedef T DistMap; + static DistMap *createDistMap(const Digraph &) { return 0; }; + DefDistMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + template + BfsWizard > distMap(const T &t) + { + Base::_dist=reinterpret_cast(const_cast(&t)); + return BfsWizard >(*this); + } + + /// Sets the source node, from which the Bfs algorithm runs. + + /// Sets the source node, from which the Bfs algorithm runs. + /// \param s is the source node. + BfsWizard &source(Node s) + { + Base::_source=s; + return *this; + } + + }; + + ///Function type interface for Bfs algorithm. + + /// \ingroup search + ///Function type interface for Bfs algorithm. + /// + ///This function also has several + ///\ref named-templ-func-param "named parameters", + ///they are declared as the members of class \ref BfsWizard. + ///The following + ///example shows how to use these parameters. + ///\code + /// bfs(g,source).predMap(preds).run(); + ///\endcode + ///\warning Don't forget to put the \ref BfsWizard::run() "run()" + ///to the end of the parameter list. + ///\sa BfsWizard + ///\sa Bfs + template + BfsWizard > + bfs(const GR &g,typename GR::Node s=INVALID) + { + return BfsWizard >(g,s); + } + +#ifdef DOXYGEN + /// \brief Visitor class for bfs. + /// + /// This class defines the interface of the BfsVisit events, and + /// it could be the base of a real Visitor class. + template + struct BfsVisitor { + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::Node Node; + /// \brief Called when the arc reach a node. + /// + /// It is called when the bfs find an arc which target is not + /// reached yet. + void discover(const Arc& arc) {} + /// \brief Called when the node reached first time. + /// + /// It is Called when the node reached first time. + void reach(const Node& node) {} + /// \brief Called when the arc examined but target of the arc + /// already discovered. + /// + /// It called when the arc examined but the target of the arc + /// already discovered. + void examine(const Arc& arc) {} + /// \brief Called for the source node of the bfs. + /// + /// It is called for the source node of the bfs. + void start(const Node& node) {} + /// \brief Called when the node processed. + /// + /// It is Called when the node processed. + void process(const Node& node) {} + }; +#else + template + struct BfsVisitor { + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::Node Node; + void discover(const Arc&) {} + void reach(const Node&) {} + void examine(const Arc&) {} + void start(const Node&) {} + void process(const Node&) {} + + template + struct Constraints { + void constraints() { + Arc arc; + Node node; + visitor.discover(arc); + visitor.reach(node); + visitor.examine(arc); + visitor.start(node); + visitor.process(node); + } + _Visitor& visitor; + }; + }; +#endif + + /// \brief Default traits class of BfsVisit class. + /// + /// Default traits class of BfsVisit class. + /// \param _Digraph Digraph type. + template + struct BfsVisitDefaultTraits { + + /// \brief The digraph type the algorithm runs on. + typedef _Digraph Digraph; + + /// \brief The type of the map that indicates which nodes are reached. + /// + /// The type of the map that indicates which nodes are reached. + /// It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// \todo named parameter to set this type, function to read and write. + typedef typename Digraph::template NodeMap ReachedMap; + + /// \brief Instantiates a ReachedMap. + /// + /// This function instantiates a \ref ReachedMap. + /// \param digraph is the digraph, to which + /// we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const Digraph &digraph) { + return new ReachedMap(digraph); + } + + }; + + /// \ingroup search + /// + /// \brief %BFS Visit algorithm class. + /// + /// This class provides an efficient implementation of the %BFS algorithm + /// with visitor interface. + /// + /// The %BfsVisit class provides an alternative interface to the Bfs + /// class. It works with callback mechanism, the BfsVisit object calls + /// on every bfs event the \c Visitor class member functions. + /// + /// \param _Digraph The digraph type the algorithm runs on. The default value is + /// \ref ListDigraph. The value of _Digraph is not used directly by Bfs, it + /// is only passed to \ref BfsDefaultTraits. + /// \param _Visitor The Visitor object for the algorithm. The + /// \ref BfsVisitor "BfsVisitor<_Digraph>" is an empty Visitor which + /// does not observe the Bfs events. If you want to observe the bfs + /// events you should implement your own Visitor class. + /// \param _Traits Traits class to set various data types used by the + /// algorithm. The default traits class is + /// \ref BfsVisitDefaultTraits "BfsVisitDefaultTraits<_Digraph>". + /// See \ref BfsVisitDefaultTraits for the documentation of + /// a Bfs visit traits class. + /// + /// \author Jacint Szabo, Alpar Juttner and Balazs Dezso +#ifdef DOXYGEN + template +#else + template , + typename _Traits = BfsDefaultTraits<_Digraph> > +#endif + class BfsVisit { + public: + + /// \brief \ref Exception for uninitialized parameters. + /// + /// This error represents problems in the initialization + /// of the parameters of the algorithms. + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* what() const throw() + { + return "lemon::BfsVisit::UninitializedParameter"; + } + }; + + typedef _Traits Traits; + + typedef typename Traits::Digraph Digraph; + + typedef _Visitor Visitor; + + ///The type of the map indicating which nodes are reached. + typedef typename Traits::ReachedMap ReachedMap; + + private: + + typedef typename Digraph::Node Node; + typedef typename Digraph::NodeIt NodeIt; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::OutArcIt OutArcIt; + + /// Pointer to the underlying digraph. + const Digraph *_digraph; + /// Pointer to the visitor object. + Visitor *_visitor; + ///Pointer to the map of reached status of the nodes. + ReachedMap *_reached; + ///Indicates if \ref _reached is locally allocated (\c true) or not. + bool local_reached; + + std::vector _list; + int _list_front, _list_back; + + /// \brief Creates the maps if necessary. + /// + /// Creates the maps if necessary. + void create_maps() { + if(!_reached) { + local_reached = true; + _reached = Traits::createReachedMap(*_digraph); + } + } + + protected: + + BfsVisit() {} + + public: + + typedef BfsVisit Create; + + /// \name Named template parameters + + ///@{ + template + struct DefReachedMapTraits : public Traits { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Digraph &digraph) { + throw UninitializedParameter(); + } + }; + /// \brief \ref named-templ-param "Named parameter" for setting + /// ReachedMap type + /// + /// \ref named-templ-param "Named parameter" for setting ReachedMap type + template + struct DefReachedMap : public BfsVisit< Digraph, Visitor, + DefReachedMapTraits > { + typedef BfsVisit< Digraph, Visitor, DefReachedMapTraits > Create; + }; + ///@} + + public: + + /// \brief Constructor. + /// + /// Constructor. + /// + /// \param digraph the digraph the algorithm will run on. + /// \param visitor The visitor of the algorithm. + /// + BfsVisit(const Digraph& digraph, Visitor& visitor) + : _digraph(&digraph), _visitor(&visitor), + _reached(0), local_reached(false) {} + + /// \brief Destructor. + /// + /// Destructor. + ~BfsVisit() { + if(local_reached) delete _reached; + } + + /// \brief Sets the map indicating if a node is reached. + /// + /// Sets the map indicating if a node is reached. + /// If you don't use this function before calling \ref run(), + /// it will allocate one. The destuctor deallocates this + /// automatically allocated map, of course. + /// \return (*this) + BfsVisit &reachedMap(ReachedMap &m) { + if(local_reached) { + delete _reached; + local_reached = false; + } + _reached = &m; + return *this; + } + + public: + /// \name Execution control + /// The simplest way to execute the algorithm is to use + /// one of the member functions called \c run(...). + /// \n + /// If you need more control on the execution, + /// first you must call \ref init(), then you can adda source node + /// with \ref addSource(). + /// Finally \ref start() will perform the actual path + /// computation. + + /// @{ + /// \brief Initializes the internal data structures. + /// + /// Initializes the internal data structures. + /// + void init() { + create_maps(); + _list.resize(countNodes(*_digraph)); + _list_front = _list_back = -1; + for (NodeIt u(*_digraph) ; u != INVALID ; ++u) { + _reached->set(u, false); + } + } + + /// \brief Adds a new source node. + /// + /// Adds a new source node to the set of nodes to be processed. + void addSource(Node s) { + if(!(*_reached)[s]) { + _reached->set(s,true); + _visitor->start(s); + _visitor->reach(s); + _list[++_list_back] = s; + } + } + + /// \brief Processes the next node. + /// + /// Processes the next node. + /// + /// \return The processed node. + /// + /// \pre The queue must not be empty! + Node processNextNode() { + Node n = _list[++_list_front]; + _visitor->process(n); + Arc e; + for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) { + Node m = _digraph->target(e); + if (!(*_reached)[m]) { + _visitor->discover(e); + _visitor->reach(m); + _reached->set(m, true); + _list[++_list_back] = m; + } else { + _visitor->examine(e); + } + } + return n; + } + + /// \brief Processes the next node. + /// + /// Processes the next node. And checks that the given target node + /// is reached. If the target node is reachable from the processed + /// node then the reached parameter will be set true. The reached + /// parameter should be initially false. + /// + /// \param target The target node. + /// \retval reach Indicates that the target node is reached. + /// \return The processed node. + /// + /// \warning The queue must not be empty! + Node processNextNode(Node target, bool& reach) { + Node n = _list[++_list_front]; + _visitor->process(n); + Arc e; + for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) { + Node m = _digraph->target(e); + if (!(*_reached)[m]) { + _visitor->discover(e); + _visitor->reach(m); + _reached->set(m, true); + _list[++_list_back] = m; + reach = reach || (target == m); + } else { + _visitor->examine(e); + } + } + return n; + } + + /// \brief Processes the next node. + /// + /// Processes the next node. And checks that at least one of + /// reached node has true value in the \c nm node map. If one node + /// with true value is reachable from the processed node then the + /// rnode parameter will be set to the first of such nodes. + /// + /// \param nm The node map of possible targets. + /// \retval rnode The reached target node. + /// \return The processed node. + /// + /// \warning The queue must not be empty! + template + Node processNextNode(const NM& nm, Node& rnode) { + Node n = _list[++_list_front]; + _visitor->process(n); + Arc e; + for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) { + Node m = _digraph->target(e); + if (!(*_reached)[m]) { + _visitor->discover(e); + _visitor->reach(m); + _reached->set(m, true); + _list[++_list_back] = m; + if (nm[m] && rnode == INVALID) rnode = m; + } else { + _visitor->examine(e); + } + } + return n; + } + + /// \brief Next node to be processed. + /// + /// Next node to be processed. + /// + /// \return The next node to be processed or INVALID if the stack is + /// empty. + Node nextNode() { + return _list_front != _list_back ? _list[_list_front + 1] : INVALID; + } + + /// \brief Returns \c false if there are nodes + /// to be processed in the queue + /// + /// Returns \c false if there are nodes + /// to be processed in the queue + bool emptyQueue() { return _list_front == _list_back; } + + /// \brief Returns the number of the nodes to be processed. + /// + /// Returns the number of the nodes to be processed in the queue. + int queueSize() { return _list_back - _list_front; } + + /// \brief Executes the algorithm. + /// + /// Executes the algorithm. + /// + /// \pre init() must be called and at least one node should be added + /// with addSource() before using this function. + void start() { + while ( !emptyQueue() ) processNextNode(); + } + + /// \brief Executes the algorithm until \c dest is reached. + /// + /// Executes the algorithm until \c dest is reached. + /// + /// \pre init() must be called and at least one node should be added + /// with addSource() before using this function. + void start(Node dest) { + bool reach = false; + while ( !emptyQueue() && !reach ) processNextNode(dest, reach); + } + + /// \brief Executes the algorithm until a condition is met. + /// + /// Executes the algorithm until a condition is met. + /// + /// \pre init() must be called and at least one node should be added + /// with addSource() before using this function. + /// + ///\param nm must be a bool (or convertible) node map. The + ///algorithm will stop when it reaches a node \c v with + /// nm[v] true. + /// + ///\return The reached node \c v with nm[v] true or + ///\c INVALID if no such node was found. + template + Node start(const NM &nm) { + Node rnode = INVALID; + while ( !emptyQueue() && rnode == INVALID ) { + processNextNode(nm, rnode); + } + return rnode; + } + + /// \brief Runs %BFSVisit algorithm from node \c s. + /// + /// This method runs the %BFS algorithm from a root node \c s. + /// \note b.run(s) is just a shortcut of the following code. + ///\code + /// b.init(); + /// b.addSource(s); + /// b.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + /// \brief Runs %BFSVisit algorithm to visit all nodes in the digraph. + /// + /// This method runs the %BFS algorithm in order to + /// compute the %BFS path to each node. The algorithm computes + /// - The %BFS tree. + /// - The distance of each node from the root in the %BFS tree. + /// + ///\note b.run() is just a shortcut of the following code. + ///\code + /// b.init(); + /// for (NodeIt it(digraph); it != INVALID; ++it) { + /// if (!b.reached(it)) { + /// b.addSource(it); + /// b.start(); + /// } + /// } + ///\endcode + void run() { + init(); + for (NodeIt it(*_digraph); it != INVALID; ++it) { + if (!reached(it)) { + addSource(it); + start(); + } + } + } + ///@} + + /// \name Query Functions + /// The result of the %BFS algorithm can be obtained using these + /// functions.\n + /// Before the use of these functions, + /// either run() or start() must be called. + ///@{ + + /// \brief Checks if a node is reachable from the root. + /// + /// Returns \c true if \c v is reachable from the root(s). + /// \warning The source nodes are inditated as unreachable. + /// \pre Either \ref run() or \ref start() + /// must be called before using this function. + /// + bool reached(Node v) { return (*_reached)[v]; } + ///@} + }; + +} //END OF NAMESPACE LEMON + +#endif + diff --git a/lemon/bin_heap.h b/lemon/bin_heap.h new file mode 100644 --- /dev/null +++ b/lemon/bin_heap.h @@ -0,0 +1,346 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_BIN_HEAP_H +#define LEMON_BIN_HEAP_H + +///\ingroup auxdat +///\file +///\brief Binary Heap implementation. + +#include +#include +#include + +namespace lemon { + + ///\ingroup auxdat + /// + ///\brief A Binary Heap implementation. + /// + ///This class implements the \e binary \e heap data structure. A \e heap + ///is a data structure for storing items with specified values called \e + ///priorities in such a way that finding the item with minimum priority is + ///efficient. \c Compare specifies the ordering of the priorities. In a heap + ///one can change the priority of an item, add or erase an item, etc. + /// + ///\param _Prio Type of the priority of the items. + ///\param _ItemIntMap A read and writable Item int map, used internally + ///to handle the cross references. + ///\param _Compare A class for the ordering of the priorities. The + ///default is \c std::less<_Prio>. + /// + ///\sa FibHeap + ///\sa Dijkstra + template > + class BinHeap { + + public: + ///\e + typedef _ItemIntMap ItemIntMap; + ///\e + typedef _Prio Prio; + ///\e + typedef typename ItemIntMap::Key Item; + ///\e + typedef std::pair Pair; + ///\e + typedef _Compare Compare; + + /// \brief Type to represent the items states. + /// + /// Each Item element have a state associated to it. It may be "in heap", + /// "pre heap" or "post heap". The latter two are indifferent from the + /// heap's point of view, but may be useful to the user. + /// + /// The ItemIntMap \e should be initialized in such way that it maps + /// PRE_HEAP (-1) to any element to be put in the heap... + enum State { + IN_HEAP = 0, + PRE_HEAP = -1, + POST_HEAP = -2 + }; + + private: + std::vector data; + Compare comp; + ItemIntMap &iim; + + public: + /// \brief The constructor. + /// + /// The constructor. + /// \param _iim should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {} + + /// \brief The constructor. + /// + /// The constructor. + /// \param _iim should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + /// + /// \param _comp The comparator function object. + BinHeap(ItemIntMap &_iim, const Compare &_comp) + : iim(_iim), comp(_comp) {} + + + /// The number of items stored in the heap. + /// + /// \brief Returns the number of items stored in the heap. + int size() const { return data.size(); } + + /// \brief Checks if the heap stores no items. + /// + /// Returns \c true if and only if the heap stores no items. + bool empty() const { return data.empty(); } + + /// \brief Make empty this heap. + /// + /// Make empty this heap. It does not change the cross reference map. + /// If you want to reuse what is not surely empty you should first clear + /// the heap and after that you should set the cross reference map for + /// each item to \c PRE_HEAP. + void clear() { + data.clear(); + } + + private: + static int parent(int i) { return (i-1)/2; } + + static int second_child(int i) { return 2*i+2; } + bool less(const Pair &p1, const Pair &p2) const { + return comp(p1.second, p2.second); + } + + int bubble_up(int hole, Pair p) { + int par = parent(hole); + while( hole>0 && less(p,data[par]) ) { + move(data[par],hole); + hole = par; + par = parent(hole); + } + move(p, hole); + return hole; + } + + int bubble_down(int hole, Pair p, int length) { + int child = second_child(hole); + while(child < length) { + if( less(data[child-1], data[child]) ) { + --child; + } + if( !less(data[child], p) ) + goto ok; + move(data[child], hole); + hole = child; + child = second_child(hole); + } + child--; + if( child 0) { + bubble_down(0, data[n], n); + } + data.pop_back(); + } + + /// \brief Deletes \c i from the heap. + /// + /// This method deletes item \c i from the heap. + /// \param i The item to erase. + /// \pre The item should be in the heap. + void erase(const Item &i) { + int h = iim[i]; + int n = data.size()-1; + iim.set(data[h].first, POST_HEAP); + if( h < n ) { + if ( bubble_up(h, data[n]) == h) { + bubble_down(h, data[n], n); + } + } + data.pop_back(); + } + + + /// \brief Returns the priority of \c i. + /// + /// This function returns the priority of item \c i. + /// \pre \c i must be in the heap. + /// \param i The item. + Prio operator[](const Item &i) const { + int idx = iim[i]; + return data[idx].second; + } + + /// \brief \c i gets to the heap with priority \c p independently + /// if \c i was already there. + /// + /// This method calls \ref push(\c i, \c p) if \c i is not stored + /// in the heap and sets the priority of \c i to \c p otherwise. + /// \param i The item. + /// \param p The priority. + void set(const Item &i, const Prio &p) { + int idx = iim[i]; + if( idx < 0 ) { + push(i,p); + } + else if( comp(p, data[idx].second) ) { + bubble_up(idx, Pair(i,p)); + } + else { + bubble_down(idx, Pair(i,p), data.size()); + } + } + + /// \brief Decreases the priority of \c i to \c p. + /// + /// This method decreases the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at least \c + /// p relative to \c Compare. + /// \param i The item. + /// \param p The priority. + void decrease(const Item &i, const Prio &p) { + int idx = iim[i]; + bubble_up(idx, Pair(i,p)); + } + + /// \brief Increases the priority of \c i to \c p. + /// + /// This method sets the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at most \c + /// p relative to \c Compare. + /// \param i The item. + /// \param p The priority. + void increase(const Item &i, const Prio &p) { + int idx = iim[i]; + bubble_down(idx, Pair(i,p), data.size()); + } + + /// \brief Returns if \c item is in, has already been in, or has + /// never been in the heap. + /// + /// This method returns PRE_HEAP if \c item has never been in the + /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP + /// otherwise. In the latter case it is possible that \c item will + /// get back to the heap again. + /// \param i The item. + State state(const Item &i) const { + int s = iim[i]; + if( s>=0 ) + s=0; + return State(s); + } + + /// \brief Sets the state of the \c item in the heap. + /// + /// Sets the state of the \c item in the heap. It can be used to + /// manually clear the heap when it is important to achive the + /// better time complexity. + /// \param i The item. + /// \param st The state. It should not be \c IN_HEAP. + void state(const Item& i, State st) { + switch (st) { + case POST_HEAP: + case PRE_HEAP: + if (state(i) == IN_HEAP) { + erase(i); + } + iim[i] = st; + break; + case IN_HEAP: + break; + } + } + + /// \brief Replaces an item in the heap. + /// + /// The \c i item is replaced with \c j item. The \c i item should + /// be in the heap, while the \c j should be out of the heap. The + /// \c i item will out of the heap and \c j will be in the heap + /// with the same prioriority as prevoiusly the \c i item. + void replace(const Item& i, const Item& j) { + int idx = iim[i]; + iim.set(i, iim[j]); + iim.set(j, idx); + data[idx].first = j; + } + + }; // class BinHeap + +} // namespace lemon + +#endif // LEMON_BIN_HEAP_H diff --git a/lemon/bits/path_dump.h b/lemon/bits/path_dump.h new file mode 100644 --- /dev/null +++ b/lemon/bits/path_dump.h @@ -0,0 +1,174 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_BITS_PRED_MAP_PATH_H +#define LEMON_BITS_PRED_MAP_PATH_H + +namespace lemon { + + template + class PredMapPath { + public: + typedef True RevPathTag; + + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + typedef _PredMap PredMap; + + PredMapPath(const Digraph& _digraph, const PredMap& _predMap, + typename Digraph::Node _target) + : digraph(_digraph), predMap(_predMap), target(_target) {} + + int length() const { + int len = 0; + typename Digraph::Node node = target; + typename Digraph::Arc arc; + while ((arc = predMap[node]) != INVALID) { + node = digraph.source(arc); + ++len; + } + return len; + } + + bool empty() const { + return predMap[target] != INVALID; + } + + class RevArcIt { + public: + RevArcIt() {} + RevArcIt(Invalid) : path(0), current(INVALID) {} + RevArcIt(const PredMapPath& _path) + : path(&_path), current(_path.target) { + if (path->predMap[current] == INVALID) current = INVALID; + } + + operator const typename Digraph::Arc() const { + return path->predMap[current]; + } + + RevArcIt& operator++() { + current = path->digraph.source(path->predMap[current]); + if (path->predMap[current] == INVALID) current = INVALID; + return *this; + } + + bool operator==(const RevArcIt& e) const { + return current == e.current; + } + + bool operator!=(const RevArcIt& e) const { + return current != e.current; + } + + bool operator<(const RevArcIt& e) const { + return current < e.current; + } + + private: + const PredMapPath* path; + typename Digraph::Node current; + }; + + private: + const Digraph& digraph; + const PredMap& predMap; + typename Digraph::Node target; + }; + + + template + class PredMatrixMapPath { + public: + typedef True RevPathTag; + + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + typedef _PredMatrixMap PredMatrixMap; + + PredMatrixMapPath(const Digraph& _digraph, + const PredMatrixMap& _predMatrixMap, + typename Digraph::Node _source, + typename Digraph::Node _target) + : digraph(_digraph), predMatrixMap(_predMatrixMap), + source(_source), target(_target) {} + + int length() const { + int len = 0; + typename Digraph::Node node = target; + typename Digraph::Arc arc; + while ((arc = predMatrixMap(source, node)) != INVALID) { + node = digraph.source(arc); + ++len; + } + return len; + } + + bool empty() const { + return source != target; + } + + class RevArcIt { + public: + RevArcIt() {} + RevArcIt(Invalid) : path(0), current(INVALID) {} + RevArcIt(const PredMatrixMapPath& _path) + : path(&_path), current(_path.target) { + if (path->predMatrixMap(path->source, current) == INVALID) + current = INVALID; + } + + operator const typename Digraph::Arc() const { + return path->predMatrixMap(path->source, current); + } + + RevArcIt& operator++() { + current = + path->digraph.source(path->predMatrixMap(path->source, current)); + if (path->predMatrixMap(path->source, current) == INVALID) + current = INVALID; + return *this; + } + + bool operator==(const RevArcIt& e) const { + return current == e.current; + } + + bool operator!=(const RevArcIt& e) const { + return current != e.current; + } + + bool operator<(const RevArcIt& e) const { + return current < e.current; + } + + private: + const PredMatrixMapPath* path; + typename Digraph::Node current; + }; + + private: + const Digraph& digraph; + const PredMatrixMap& predMatrixMap; + typename Digraph::Node source; + typename Digraph::Node target; + }; + +} + +#endif diff --git a/lemon/concepts/heap.h b/lemon/concepts/heap.h new file mode 100644 --- /dev/null +++ b/lemon/concepts/heap.h @@ -0,0 +1,226 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup concept +///\file +///\brief Classes for representing heaps. +/// + +#ifndef LEMON_CONCEPT_HEAP_H +#define LEMON_CONCEPT_HEAP_H + +#include + +namespace lemon { + namespace concepts { + /// \addtogroup concept + /// @{ + + + /// \brief A concept structure describes the main interface of heaps. + /// + /// A concept structure describes the main interface of heaps. + /// + template + class Heap { + public: + + ///\brief Type of the items stored in the heap. + typedef typename ItemIntMap::Key Item; + + + /// \brief Type to represent the items states. + /// + /// Each Item element have a state associated to it. It may be "in heap", + /// "pre heap" or "post heap". The later two are indifferent from the + /// heap's point of view, but may be useful to the user. + /// + /// The ItemIntMap _should_ be initialized in such way, that it maps + /// PRE_HEAP (-1) to any element to be put in the heap... + enum State { + IN_HEAP = 0, + PRE_HEAP = -1, + POST_HEAP = -2 + }; + + /// \brief The constructor. + /// + /// The constructor. + /// \param _iim should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + explicit Heap(ItemIntMap &_iim) {} + + /// \brief The number of items stored in the heap. + /// + /// Returns the number of items stored in the heap. + int size() const { return 0; } + + /// \brief Checks if the heap stores no items. + /// + /// Returns \c true if and only if the heap stores no items. + bool empty() const { return false; } + + /// \brief Makes empty this heap. + /// + /// Makes this heap empty. + void clear(); + + /// \brief Insert an item into the heap with the given heap. + /// + /// Adds \c i to the heap with priority \c p. + /// \param i The item to insert. + /// \param p The priority of the item. + void push(const Item &i, const Prio &p) {} + + /// \brief Returns the item with minimum priority. + /// + /// This method returns the item with minimum priority. + /// \pre The heap must be nonempty. + Item top() const {} + + /// \brief Returns the minimum priority. + /// + /// It returns the minimum priority. + /// \pre The heap must be nonempty. + Prio prio() const {} + + /// \brief Deletes the item with minimum priority. + /// + /// This method deletes the item with minimum priority. + /// \pre The heap must be non-empty. + void pop() {} + + /// \brief Deletes \c i from the heap. + /// + /// This method deletes item \c i from the heap, if \c i was + /// already stored in the heap. + /// \param i The item to erase. + void erase(const Item &i) {} + + /// \brief Returns the priority of \c i. + /// + /// This function returns the priority of item \c i. + /// \pre \c i must be in the heap. + /// \param i The item. + Prio operator[](const Item &i) const {} + + /// \brief \c i gets to the heap with priority \c p independently + /// if \c i was already there. + /// + /// This method calls \ref push(\c i, \c p) if \c i is not stored + /// in the heap and sets the priority of \c i to \c p otherwise. + /// It may throw an \e UnderFlowPriorityException. + /// \param i The item. + /// \param p The priority. + void set(const Item &i, const Prio &p) {} + + /// \brief Decreases the priority of \c i to \c p. + /// + /// This method decreases the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at least \c p. + /// \param i The item. + /// \param p The priority. + void decrease(const Item &i, const Prio &p) {} + + /// \brief Increases the priority of \c i to \c p. + /// + /// This method sets the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at most \c + /// p relative to \c Compare. + /// \param i The item. + /// \param p The priority. + void increase(const Item &i, const Prio &p) {} + + /// \brief Returns if \c item is in, has already been in, or has + /// never been in the heap. + /// + /// This method returns PRE_HEAP if \c item has never been in the + /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP + /// otherwise. In the latter case it is possible that \c item will + /// get back to the heap again. + /// \param i The item. + State state(const Item &i) const {} + + /// \brief Sets the state of the \c item in the heap. + /// + /// Sets the state of the \c item in the heap. It can be used to + /// manually clear the heap when it is important to achive the + /// better time complexity. + /// \param i The item. + /// \param st The state. It should not be \c IN_HEAP. + void state(const Item& i, State st) {} + + + template + struct Constraints { + public: + + void constraints() { + Item item; + Prio prio; + + item=Item(); + prio=Prio(); + + ignore_unused_variable_warning(item); + ignore_unused_variable_warning(prio); + + typedef typename _Heap::State State; + State state; + + ignore_unused_variable_warning(state); + + _Heap heap1 = _Heap(map); + + ignore_unused_variable_warning(heap1); + + heap.push(item, prio); + + prio = heap.prio(); + item = heap.top(); + + heap.pop(); + + heap.set(item, prio); + heap.decrease(item, prio); + heap.increase(item, prio); + prio = heap[item]; + + heap.erase(item); + + state = heap.state(item); + + state = _Heap::PRE_HEAP; + state = _Heap::IN_HEAP; + state = _Heap::POST_HEAP; + + heap.clear(); + } + + _Heap& heap; + ItemIntMap& map; + + Constraints() : heap(0), map(0) {} + }; + }; + + /// @} + } // namespace lemon +} +#endif // LEMON_CONCEPT_PATH_H diff --git a/lemon/dfs.h b/lemon/dfs.h new file mode 100644 --- /dev/null +++ b/lemon/dfs.h @@ -0,0 +1,1543 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_DFS_H +#define LEMON_DFS_H + +///\ingroup search +///\file +///\brief Dfs algorithm. + +#include +#include +#include +#include +#include +#include + +#include + +namespace lemon { + + + ///Default traits class of Dfs class. + + ///Default traits class of Dfs class. + ///\param GR Digraph type. + template + struct DfsDefaultTraits + { + ///The digraph type the algorithm runs on. + typedef GR Digraph; + ///\brief The type of the map that stores the last + ///arcs of the %DFS paths. + /// + ///The type of the map that stores the last + ///arcs of the %DFS paths. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef typename Digraph::template NodeMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the digraph, to which we would like to define the PredMap. + ///\todo The digraph alone may be insufficient to initialize + static PredMap *createPredMap(const GR &G) + { + return new PredMap(G); + } + + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param g is the digraph, to which + ///we would like to define the \ref ProcessedMap +#ifdef DOXYGEN + static ProcessedMap *createProcessedMap(const GR &g) +#else + static ProcessedMap *createProcessedMap(const GR &) +#endif + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Digraph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the digraph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef typename Digraph::template NodeMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the digraph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &G) + { + return new DistMap(G); + } + }; + + ///%DFS algorithm class. + + ///\ingroup search + ///This class provides an efficient implementation of the %DFS algorithm. + /// + ///\param GR The digraph type the algorithm runs on. The default value is + ///\ref ListDigraph. The value of GR is not used directly by Dfs, it + ///is only passed to \ref DfsDefaultTraits. + ///\param TR Traits class to set various data types used by the algorithm. + ///The default traits class is + ///\ref DfsDefaultTraits "DfsDefaultTraits". + ///See \ref DfsDefaultTraits for the documentation of + ///a Dfs traits class. + /// + ///\author Jacint Szabo and Alpar Juttner +#ifdef DOXYGEN + template +#else + template > +#endif + class Dfs { + public: + /** + * \brief \ref Exception for uninitialized parameters. + * + * This error represents problems in the initialization + * of the parameters of the algorithms. + */ + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* what() const throw() { + return "lemon::Dfs::UninitializedParameter"; + } + }; + + typedef TR Traits; + ///The type of the underlying digraph. + typedef typename TR::Digraph Digraph; + ///\e + typedef typename Digraph::Node Node; + ///\e + typedef typename Digraph::NodeIt NodeIt; + ///\e + typedef typename Digraph::Arc Arc; + ///\e + typedef typename Digraph::OutArcIt OutArcIt; + + ///\brief The type of the map that stores the last + ///arcs of the %DFS paths. + typedef typename TR::PredMap PredMap; + ///The type of the map indicating which nodes are reached. + typedef typename TR::ReachedMap ReachedMap; + ///The type of the map indicating which nodes are processed. + typedef typename TR::ProcessedMap ProcessedMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + private: + /// Pointer to the underlying digraph. + const Digraph *G; + ///Pointer to the map of predecessors arcs. + PredMap *_pred; + ///Indicates if \ref _pred is locally allocated (\c true) or not. + bool local_pred; + ///Pointer to the map of distances. + DistMap *_dist; + ///Indicates if \ref _dist is locally allocated (\c true) or not. + bool local_dist; + ///Pointer to the map of reached status of the nodes. + ReachedMap *_reached; + ///Indicates if \ref _reached is locally allocated (\c true) or not. + bool local_reached; + ///Pointer to the map of processed status of the nodes. + ProcessedMap *_processed; + ///Indicates if \ref _processed is locally allocated (\c true) or not. + bool local_processed; + + std::vector _stack; + int _stack_head; + + ///Creates the maps if necessary. + + ///\todo Better memory allocation (instead of new). + void create_maps() + { + if(!_pred) { + local_pred = true; + _pred = Traits::createPredMap(*G); + } + if(!_dist) { + local_dist = true; + _dist = Traits::createDistMap(*G); + } + if(!_reached) { + local_reached = true; + _reached = Traits::createReachedMap(*G); + } + if(!_processed) { + local_processed = true; + _processed = Traits::createProcessedMap(*G); + } + } + + protected: + + Dfs() {} + + public: + + typedef Dfs Create; + + ///\name Named template parameters + + ///@{ + + template + struct DefPredMapTraits : public Traits { + typedef T PredMap; + static PredMap *createPredMap(const Digraph &G) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///PredMap type + /// + ///\ref named-templ-param "Named parameter" for setting PredMap type + /// + template + struct DefPredMap : public Dfs > { + typedef Dfs > Create; + }; + + + template + struct DefDistMapTraits : public Traits { + typedef T DistMap; + static DistMap *createDistMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///DistMap type + /// + ///\ref named-templ-param "Named parameter" for setting DistMap + ///type + template + struct DefDistMap { + typedef Dfs > Create; + }; + + template + struct DefReachedMapTraits : public Traits { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///ReachedMap type + /// + ///\ref named-templ-param "Named parameter" for setting ReachedMap type + /// + template + struct DefReachedMap : public Dfs< Digraph, DefReachedMapTraits > { + typedef Dfs< Digraph, DefReachedMapTraits > Create; + }; + + template + struct DefProcessedMapTraits : public Traits { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///ProcessedMap type + /// + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + /// + template + struct DefProcessedMap : public Dfs< Digraph, DefProcessedMapTraits > { + typedef Dfs< Digraph, DefProcessedMapTraits > Create; + }; + + struct DefDigraphProcessedMapTraits : public Traits { + typedef typename Digraph::template NodeMap ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &G) + { + return new ProcessedMap(G); + } + }; + ///\brief \ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Digraph::NodeMap. + /// + ///\ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Digraph::NodeMap. + ///If you don't set it explicitely, it will be automatically allocated. + template + class DefProcessedMapToBeDefaultMap : + public Dfs< Digraph, DefDigraphProcessedMapTraits> { + typedef Dfs< Digraph, DefDigraphProcessedMapTraits> Create; + }; + + ///@} + + public: + + ///Constructor. + + ///\param _G the digraph the algorithm will run on. + /// + Dfs(const Digraph& _G) : + G(&_G), + _pred(NULL), local_pred(false), + _dist(NULL), local_dist(false), + _reached(NULL), local_reached(false), + _processed(NULL), local_processed(false) + { } + + ///Destructor. + ~Dfs() + { + if(local_pred) delete _pred; + if(local_dist) delete _dist; + if(local_reached) delete _reached; + if(local_processed) delete _processed; + } + + ///Sets the map storing the predecessor arcs. + + ///Sets the map storing the predecessor arcs. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &predMap(PredMap &m) + { + if(local_pred) { + delete _pred; + local_pred=false; + } + _pred = &m; + return *this; + } + + ///Sets the map storing the distances calculated by the algorithm. + + ///Sets the map storing the distances calculated by the algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &distMap(DistMap &m) + { + if(local_dist) { + delete _dist; + local_dist=false; + } + _dist = &m; + return *this; + } + + ///Sets the map indicating if a node is reached. + + ///Sets the map indicating if a node is reached. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &reachedMap(ReachedMap &m) + { + if(local_reached) { + delete _reached; + local_reached=false; + } + _reached = &m; + return *this; + } + + ///Sets the map indicating if a node is processed. + + ///Sets the map indicating if a node is processed. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &processedMap(ProcessedMap &m) + { + if(local_processed) { + delete _processed; + local_processed=false; + } + _processed = &m; + return *this; + } + + public: + ///\name Execution control + ///The simplest way to execute the algorithm is to use + ///one of the member functions called \c run(...). + ///\n + ///If you need more control on the execution, + ///first you must call \ref init(), then you can add a source node + ///with \ref addSource(). + ///Finally \ref start() will perform the actual path + ///computation. + + ///@{ + + ///Initializes the internal data structures. + + ///Initializes the internal data structures. + /// + void init() + { + create_maps(); + _stack.resize(countNodes(*G)); + _stack_head=-1; + for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { + _pred->set(u,INVALID); + // _predNode->set(u,INVALID); + _reached->set(u,false); + _processed->set(u,false); + } + } + + ///Adds a new source node. + + ///Adds a new source node to the set of nodes to be processed. + /// + ///\warning dists are wrong (or at least strange) + ///in case of multiple sources. + void addSource(Node s) + { + if(!(*_reached)[s]) + { + _reached->set(s,true); + _pred->set(s,INVALID); + OutArcIt e(*G,s); + if(e!=INVALID) { + _stack[++_stack_head]=e; + _dist->set(s,_stack_head); + } + else { + _processed->set(s,true); + _dist->set(s,0); + } + } + } + + ///Processes the next arc. + + ///Processes the next arc. + /// + ///\return The processed arc. + /// + ///\pre The stack must not be empty! + Arc processNextArc() + { + Node m; + Arc e=_stack[_stack_head]; + if(!(*_reached)[m=G->target(e)]) { + _pred->set(m,e); + _reached->set(m,true); + ++_stack_head; + _stack[_stack_head] = OutArcIt(*G, m); + _dist->set(m,_stack_head); + } + else { + m=G->source(e); + ++_stack[_stack_head]; + } + while(_stack_head>=0 && _stack[_stack_head]==INVALID) { + _processed->set(m,true); + --_stack_head; + if(_stack_head>=0) { + m=G->source(_stack[_stack_head]); + ++_stack[_stack_head]; + } + } + return e; + } + ///Next arc to be processed. + + ///Next arc to be processed. + /// + ///\return The next arc to be processed or INVALID if the stack is + /// empty. + OutArcIt nextArc() + { + return _stack_head>=0?_stack[_stack_head]:INVALID; + } + + ///\brief Returns \c false if there are nodes + ///to be processed in the queue + /// + ///Returns \c false if there are nodes + ///to be processed in the queue + bool emptyQueue() { return _stack_head<0; } + ///Returns the number of the nodes to be processed. + + ///Returns the number of the nodes to be processed in the queue. + int queueSize() { return _stack_head+1; } + + ///Executes the algorithm. + + ///Executes the algorithm. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %DFS algorithm from the root node(s) + ///in order to + ///compute the + ///%DFS path to each node. The algorithm computes + ///- The %DFS tree. + ///- The distance of each node from the root(s) in the %DFS tree. + /// + void start() + { + while ( !emptyQueue() ) processNextArc(); + } + + ///Executes the algorithm until \c dest is reached. + + ///Executes the algorithm until \c dest is reached. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %DFS algorithm from the root node(s) + ///in order to + ///compute the + ///%DFS path to \c dest. The algorithm computes + ///- The %DFS path to \c dest. + ///- The distance of \c dest from the root(s) in the %DFS tree. + /// + void start(Node dest) + { + while ( !emptyQueue() && G->target(_stack[_stack_head])!=dest ) + processNextArc(); + } + + ///Executes the algorithm until a condition is met. + + ///Executes the algorithm until a condition is met. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///\param em must be a bool (or convertible) arc map. The algorithm + ///will stop when it reaches an arc \c e with em[e] true. + /// + ///\return The reached arc \c e with em[e] true or + ///\c INVALID if no such arc was found. + /// + ///\warning Contrary to \ref Bfs and \ref Dijkstra, \c em is an arc map, + ///not a node map. + template + Arc start(const EM &em) + { + while ( !emptyQueue() && !em[_stack[_stack_head]] ) + processNextArc(); + return emptyQueue() ? INVALID : _stack[_stack_head]; + } + + ///Runs %DFS algorithm to visit all nodes in the digraph. + + ///This method runs the %DFS algorithm in order to + ///compute the + ///%DFS path to each node. The algorithm computes + ///- The %DFS tree. + ///- The distance of each node from the root in the %DFS tree. + /// + ///\note d.run() is just a shortcut of the following code. + ///\code + /// d.init(); + /// for (NodeIt it(digraph); it != INVALID; ++it) { + /// if (!d.reached(it)) { + /// d.addSource(it); + /// d.start(); + /// } + /// } + ///\endcode + void run() { + init(); + for (NodeIt it(*G); it != INVALID; ++it) { + if (!reached(it)) { + addSource(it); + start(); + } + } + } + + ///Runs %DFS algorithm from node \c s. + + ///This method runs the %DFS algorithm from a root node \c s + ///in order to + ///compute the + ///%DFS path to each node. The algorithm computes + ///- The %DFS tree. + ///- The distance of each node from the root in the %DFS tree. + /// + ///\note d.run(s) is just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + ///Finds the %DFS path between \c s and \c t. + + ///Finds the %DFS path between \c s and \c t. + /// + ///\return The length of the %DFS s---t path if there exists one, + ///0 otherwise. + ///\note Apart from the return value, d.run(s,t) is + ///just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(t); + ///\endcode + int run(Node s,Node t) { + init(); + addSource(s); + start(t); + return reached(t)?_stack_head+1:0; + } + + ///@} + + ///\name Query Functions + ///The result of the %DFS algorithm can be obtained using these + ///functions.\n + ///Before the use of these functions, + ///either run() or start() must be called. + + ///@{ + + typedef PredMapPath Path; + + ///Gives back the shortest path. + + ///Gives back the shortest path. + ///\pre The \c t should be reachable from the source. + Path path(Node t) + { + return Path(*G, *_pred, t); + } + + ///The distance of a node from the root(s). + + ///Returns the distance of a node from the root(s). + ///\pre \ref run() must be called before using this function. + ///\warning If node \c v is unreachable from the root(s) then the return + ///value of this funcion is undefined. + int dist(Node v) const { return (*_dist)[v]; } + + ///Returns the 'previous arc' of the %DFS tree. + + ///For a node \c v it returns the 'previous arc' + ///of the %DFS path, + ///i.e. it returns the last arc of a %DFS path from the root(s) to \c + ///v. It is \ref INVALID + ///if \c v is unreachable from the root(s) or \c v is a root. The + ///%DFS tree used here is equal to the %DFS tree used in + ///\ref predNode(). + ///\pre Either \ref run() or \ref start() must be called before using + ///this function. + Arc predArc(Node v) const { return (*_pred)[v];} + + ///Returns the 'previous node' of the %DFS tree. + + ///For a node \c v it returns the 'previous node' + ///of the %DFS tree, + ///i.e. it returns the last but one node from a %DFS path from the + ///root(s) to \c v. + ///It is INVALID if \c v is unreachable from the root(s) or + ///if \c v itself a root. + ///The %DFS tree used here is equal to the %DFS + ///tree used in \ref predArc(). + ///\pre Either \ref run() or \ref start() must be called before + ///using this function. + Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: + G->source((*_pred)[v]); } + + ///Returns a reference to the NodeMap of distances. + + ///Returns a reference to the NodeMap of distances. + ///\pre Either \ref run() or \ref init() must + ///be called before using this function. + const DistMap &distMap() const { return *_dist;} + + ///Returns a reference to the %DFS arc-tree map. + + ///Returns a reference to the NodeMap of the arcs of the + ///%DFS tree. + ///\pre Either \ref run() or \ref init() + ///must be called before using this function. + const PredMap &predMap() const { return *_pred;} + + ///Checks if a node is reachable from the root. + + ///Returns \c true if \c v is reachable from the root(s). + ///\warning The source nodes are inditated as unreachable. + ///\pre Either \ref run() or \ref start() + ///must be called before using this function. + /// + bool reached(Node v) { return (*_reached)[v]; } + + ///@} + }; + + ///Default traits class of Dfs function. + + ///Default traits class of Dfs function. + ///\param GR Digraph type. + template + struct DfsWizardDefaultTraits + { + ///The digraph type the algorithm runs on. + typedef GR Digraph; + ///\brief The type of the map that stores the last + ///arcs of the %DFS paths. + /// + ///The type of the map that stores the last + ///arcs of the %DFS paths. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef NullMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param g is the digraph, to which we would like to define the PredMap. + ///\todo The digraph alone may be insufficient to initialize +#ifdef DOXYGEN + static PredMap *createPredMap(const GR &g) +#else + static PredMap *createPredMap(const GR &) +#endif + { + return new PredMap(); + } + + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param g is the digraph, to which + ///we would like to define the \ref ProcessedMap +#ifdef DOXYGEN + static ProcessedMap *createProcessedMap(const GR &g) +#else + static ProcessedMap *createProcessedMap(const GR &) +#endif + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Digraph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the digraph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef NullMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param g is the digraph, to which we would like to define the \ref DistMap +#ifdef DOXYGEN + static DistMap *createDistMap(const GR &g) +#else + static DistMap *createDistMap(const GR &) +#endif + { + return new DistMap(); + } + }; + + /// Default traits used by \ref DfsWizard + + /// To make it easier to use Dfs algorithm + ///we have created a wizard class. + /// This \ref DfsWizard class needs default traits, + ///as well as the \ref Dfs class. + /// The \ref DfsWizardBase is a class to be the default traits of the + /// \ref DfsWizard class. + template + class DfsWizardBase : public DfsWizardDefaultTraits + { + + typedef DfsWizardDefaultTraits Base; + protected: + /// Type of the nodes in the digraph. + typedef typename Base::Digraph::Node Node; + + /// Pointer to the underlying digraph. + void *_g; + ///Pointer to the map of reached nodes. + void *_reached; + ///Pointer to the map of processed nodes. + void *_processed; + ///Pointer to the map of predecessors arcs. + void *_pred; + ///Pointer to the map of distances. + void *_dist; + ///Pointer to the source node. + Node _source; + + public: + /// Constructor. + + /// This constructor does not require parameters, therefore it initiates + /// all of the attributes to default values (0, INVALID). + DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), + _dist(0), _source(INVALID) {} + + /// Constructor. + + /// This constructor requires some parameters, + /// listed in the parameters list. + /// Others are initiated to 0. + /// \param g is the initial value of \ref _g + /// \param s is the initial value of \ref _source + DfsWizardBase(const GR &g, Node s=INVALID) : + _g(reinterpret_cast(const_cast(&g))), + _reached(0), _processed(0), _pred(0), _dist(0), _source(s) {} + + }; + + /// A class to make the usage of the Dfs algorithm easier + + /// This class is created to make it easier to use the Dfs algorithm. + /// It uses the functions and features of the plain \ref Dfs, + /// but it is much simpler to use it. + /// + /// Simplicity means that the way to change the types defined + /// in the traits class is based on functions that returns the new class + /// and not on templatable built-in classes. + /// When using the plain \ref Dfs + /// the new class with the modified type comes from + /// the original class by using the :: + /// operator. In the case of \ref DfsWizard only + /// a function have to be called and it will + /// return the needed class. + /// + /// It does not have own \ref run method. When its \ref run method is called + /// it initiates a plain \ref Dfs object, and calls the \ref Dfs::run + /// method of it. + template + class DfsWizard : public TR + { + typedef TR Base; + + ///The type of the underlying digraph. + typedef typename TR::Digraph Digraph; + //\e + typedef typename Digraph::Node Node; + //\e + typedef typename Digraph::NodeIt NodeIt; + //\e + typedef typename Digraph::Arc Arc; + //\e + typedef typename Digraph::OutArcIt OutArcIt; + + ///\brief The type of the map that stores + ///the reached nodes + typedef typename TR::ReachedMap ReachedMap; + ///\brief The type of the map that stores + ///the processed nodes + typedef typename TR::ProcessedMap ProcessedMap; + ///\brief The type of the map that stores the last + ///arcs of the %DFS paths. + typedef typename TR::PredMap PredMap; + ///The type of the map that stores the distances of the nodes. + typedef typename TR::DistMap DistMap; + + public: + /// Constructor. + DfsWizard() : TR() {} + + /// Constructor that requires parameters. + + /// Constructor that requires parameters. + /// These parameters will be the default values for the traits class. + DfsWizard(const Digraph &g, Node s=INVALID) : + TR(g,s) {} + + ///Copy constructor + DfsWizard(const TR &b) : TR(b) {} + + ~DfsWizard() {} + + ///Runs Dfs algorithm from a given node. + + ///Runs Dfs algorithm from a given node. + ///The node can be given by the \ref source function. + void run() + { + if(Base::_source==INVALID) throw UninitializedParameter(); + Dfs alg(*reinterpret_cast(Base::_g)); + if(Base::_reached) + alg.reachedMap(*reinterpret_cast(Base::_reached)); + if(Base::_processed) + alg.processedMap(*reinterpret_cast(Base::_processed)); + if(Base::_pred) + alg.predMap(*reinterpret_cast(Base::_pred)); + if(Base::_dist) + alg.distMap(*reinterpret_cast(Base::_dist)); + alg.run(Base::_source); + } + + ///Runs Dfs algorithm from the given node. + + ///Runs Dfs algorithm from the given node. + ///\param s is the given source. + void run(Node s) + { + Base::_source=s; + run(); + } + + template + struct DefPredMapBase : public Base { + typedef T PredMap; + static PredMap *createPredMap(const Digraph &) { return 0; }; + DefPredMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + template + DfsWizard > predMap(const T &t) + { + Base::_pred=reinterpret_cast(const_cast(&t)); + return DfsWizard >(*this); + } + + + template + struct DefReachedMapBase : public Base { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Digraph &) { return 0; }; + DefReachedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + template + DfsWizard > reachedMap(const T &t) + { + Base::_pred=reinterpret_cast(const_cast(&t)); + return DfsWizard >(*this); + } + + + template + struct DefProcessedMapBase : public Base { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &) { return 0; }; + DefProcessedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + template + DfsWizard > processedMap(const T &t) + { + Base::_pred=reinterpret_cast(const_cast(&t)); + return DfsWizard >(*this); + } + + template + struct DefDistMapBase : public Base { + typedef T DistMap; + static DistMap *createDistMap(const Digraph &) { return 0; }; + DefDistMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + template + DfsWizard > distMap(const T &t) + { + Base::_dist=reinterpret_cast(const_cast(&t)); + return DfsWizard >(*this); + } + + /// Sets the source node, from which the Dfs algorithm runs. + + /// Sets the source node, from which the Dfs algorithm runs. + /// \param s is the source node. + DfsWizard &source(Node s) + { + Base::_source=s; + return *this; + } + + }; + + ///Function type interface for Dfs algorithm. + + ///\ingroup search + ///Function type interface for Dfs algorithm. + /// + ///This function also has several + ///\ref named-templ-func-param "named parameters", + ///they are declared as the members of class \ref DfsWizard. + ///The following + ///example shows how to use these parameters. + ///\code + /// dfs(g,source).predMap(preds).run(); + ///\endcode + ///\warning Don't forget to put the \ref DfsWizard::run() "run()" + ///to the end of the parameter list. + ///\sa DfsWizard + ///\sa Dfs + template + DfsWizard > + dfs(const GR &g,typename GR::Node s=INVALID) + { + return DfsWizard >(g,s); + } + +#ifdef DOXYGEN + /// \brief Visitor class for dfs. + /// + /// It gives a simple interface for a functional interface for dfs + /// traversal. The traversal on a linear data structure. + template + struct DfsVisitor { + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::Node Node; + /// \brief Called when the arc reach a node. + /// + /// It is called when the dfs find an arc which target is not + /// reached yet. + void discover(const Arc& arc) {} + /// \brief Called when the node reached first time. + /// + /// It is Called when the node reached first time. + void reach(const Node& node) {} + /// \brief Called when we step back on an arc. + /// + /// It is called when the dfs should step back on the arc. + void backtrack(const Arc& arc) {} + /// \brief Called when we step back from the node. + /// + /// It is called when we step back from the node. + void leave(const Node& node) {} + /// \brief Called when the arc examined but target of the arc + /// already discovered. + /// + /// It called when the arc examined but the target of the arc + /// already discovered. + void examine(const Arc& arc) {} + /// \brief Called for the source node of the dfs. + /// + /// It is called for the source node of the dfs. + void start(const Node& node) {} + /// \brief Called when we leave the source node of the dfs. + /// + /// It is called when we leave the source node of the dfs. + void stop(const Node& node) {} + + }; +#else + template + struct DfsVisitor { + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::Node Node; + void discover(const Arc&) {} + void reach(const Node&) {} + void backtrack(const Arc&) {} + void leave(const Node&) {} + void examine(const Arc&) {} + void start(const Node&) {} + void stop(const Node&) {} + + template + struct Constraints { + void constraints() { + Arc arc; + Node node; + visitor.discover(arc); + visitor.reach(node); + visitor.backtrack(arc); + visitor.leave(node); + visitor.examine(arc); + visitor.start(node); + visitor.stop(arc); + } + _Visitor& visitor; + }; + }; +#endif + + /// \brief Default traits class of DfsVisit class. + /// + /// Default traits class of DfsVisit class. + /// \param _Digraph Digraph type. + template + struct DfsVisitDefaultTraits { + + /// \brief The digraph type the algorithm runs on. + typedef _Digraph Digraph; + + /// \brief The type of the map that indicates which nodes are reached. + /// + /// The type of the map that indicates which nodes are reached. + /// It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// \todo named parameter to set this type, function to read and write. + typedef typename Digraph::template NodeMap ReachedMap; + + /// \brief Instantiates a ReachedMap. + /// + /// This function instantiates a \ref ReachedMap. + /// \param digraph is the digraph, to which + /// we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const Digraph &digraph) { + return new ReachedMap(digraph); + } + + }; + + /// %DFS Visit algorithm class. + + /// \ingroup search + /// This class provides an efficient implementation of the %DFS algorithm + /// with visitor interface. + /// + /// The %DfsVisit class provides an alternative interface to the Dfs + /// class. It works with callback mechanism, the DfsVisit object calls + /// on every dfs event the \c Visitor class member functions. + /// + /// \param _Digraph The digraph type the algorithm runs on. The default value is + /// \ref ListDigraph. The value of _Digraph is not used directly by Dfs, it + /// is only passed to \ref DfsDefaultTraits. + /// \param _Visitor The Visitor object for the algorithm. The + /// \ref DfsVisitor "DfsVisitor<_Digraph>" is an empty Visitor which + /// does not observe the Dfs events. If you want to observe the dfs + /// events you should implement your own Visitor class. + /// \param _Traits Traits class to set various data types used by the + /// algorithm. The default traits class is + /// \ref DfsVisitDefaultTraits "DfsVisitDefaultTraits<_Digraph>". + /// See \ref DfsVisitDefaultTraits for the documentation of + /// a Dfs visit traits class. + /// + /// \author Jacint Szabo, Alpar Juttner and Balazs Dezso +#ifdef DOXYGEN + template +#else + template , + typename _Traits = DfsDefaultTraits<_Digraph> > +#endif + class DfsVisit { + public: + + /// \brief \ref Exception for uninitialized parameters. + /// + /// This error represents problems in the initialization + /// of the parameters of the algorithms. + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* what() const throw() + { + return "lemon::DfsVisit::UninitializedParameter"; + } + }; + + typedef _Traits Traits; + + typedef typename Traits::Digraph Digraph; + + typedef _Visitor Visitor; + + ///The type of the map indicating which nodes are reached. + typedef typename Traits::ReachedMap ReachedMap; + + private: + + typedef typename Digraph::Node Node; + typedef typename Digraph::NodeIt NodeIt; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::OutArcIt OutArcIt; + + /// Pointer to the underlying digraph. + const Digraph *_digraph; + /// Pointer to the visitor object. + Visitor *_visitor; + ///Pointer to the map of reached status of the nodes. + ReachedMap *_reached; + ///Indicates if \ref _reached is locally allocated (\c true) or not. + bool local_reached; + + std::vector _stack; + int _stack_head; + + /// \brief Creates the maps if necessary. + /// + /// Creates the maps if necessary. + void create_maps() { + if(!_reached) { + local_reached = true; + _reached = Traits::createReachedMap(*_digraph); + } + } + + protected: + + DfsVisit() {} + + public: + + typedef DfsVisit Create; + + /// \name Named template parameters + + ///@{ + template + struct DefReachedMapTraits : public Traits { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Digraph &digraph) { + throw UninitializedParameter(); + } + }; + /// \brief \ref named-templ-param "Named parameter" for setting + /// ReachedMap type + /// + /// \ref named-templ-param "Named parameter" for setting ReachedMap type + template + struct DefReachedMap : public DfsVisit< Digraph, Visitor, + DefReachedMapTraits > { + typedef DfsVisit< Digraph, Visitor, DefReachedMapTraits > Create; + }; + ///@} + + public: + + /// \brief Constructor. + /// + /// Constructor. + /// + /// \param digraph the digraph the algorithm will run on. + /// \param visitor The visitor of the algorithm. + /// + DfsVisit(const Digraph& digraph, Visitor& visitor) + : _digraph(&digraph), _visitor(&visitor), + _reached(0), local_reached(false) {} + + /// \brief Destructor. + /// + /// Destructor. + ~DfsVisit() { + if(local_reached) delete _reached; + } + + /// \brief Sets the map indicating if a node is reached. + /// + /// Sets the map indicating if a node is reached. + /// If you don't use this function before calling \ref run(), + /// it will allocate one. The destuctor deallocates this + /// automatically allocated map, of course. + /// \return (*this) + DfsVisit &reachedMap(ReachedMap &m) { + if(local_reached) { + delete _reached; + local_reached=false; + } + _reached = &m; + return *this; + } + + public: + /// \name Execution control + /// The simplest way to execute the algorithm is to use + /// one of the member functions called \c run(...). + /// \n + /// If you need more control on the execution, + /// first you must call \ref init(), then you can adda source node + /// with \ref addSource(). + /// Finally \ref start() will perform the actual path + /// computation. + + /// @{ + /// \brief Initializes the internal data structures. + /// + /// Initializes the internal data structures. + /// + void init() { + create_maps(); + _stack.resize(countNodes(*_digraph)); + _stack_head = -1; + for (NodeIt u(*_digraph) ; u != INVALID ; ++u) { + _reached->set(u, false); + } + } + + /// \brief Adds a new source node. + /// + /// Adds a new source node to the set of nodes to be processed. + void addSource(Node s) { + if(!(*_reached)[s]) { + _reached->set(s,true); + _visitor->start(s); + _visitor->reach(s); + Arc e; + _digraph->firstOut(e, s); + if (e != INVALID) { + _stack[++_stack_head] = e; + } else { + _visitor->leave(s); + } + } + } + + /// \brief Processes the next arc. + /// + /// Processes the next arc. + /// + /// \return The processed arc. + /// + /// \pre The stack must not be empty! + Arc processNextArc() { + Arc e = _stack[_stack_head]; + Node m = _digraph->target(e); + if(!(*_reached)[m]) { + _visitor->discover(e); + _visitor->reach(m); + _reached->set(m, true); + _digraph->firstOut(_stack[++_stack_head], m); + } else { + _visitor->examine(e); + m = _digraph->source(e); + _digraph->nextOut(_stack[_stack_head]); + } + while (_stack_head>=0 && _stack[_stack_head] == INVALID) { + _visitor->leave(m); + --_stack_head; + if (_stack_head >= 0) { + _visitor->backtrack(_stack[_stack_head]); + m = _digraph->source(_stack[_stack_head]); + _digraph->nextOut(_stack[_stack_head]); + } else { + _visitor->stop(m); + } + } + return e; + } + + /// \brief Next arc to be processed. + /// + /// Next arc to be processed. + /// + /// \return The next arc to be processed or INVALID if the stack is + /// empty. + Arc nextArc() { + return _stack_head >= 0 ? _stack[_stack_head] : INVALID; + } + + /// \brief Returns \c false if there are nodes + /// to be processed in the queue + /// + /// Returns \c false if there are nodes + /// to be processed in the queue + bool emptyQueue() { return _stack_head < 0; } + + /// \brief Returns the number of the nodes to be processed. + /// + /// Returns the number of the nodes to be processed in the queue. + int queueSize() { return _stack_head + 1; } + + /// \brief Executes the algorithm. + /// + /// Executes the algorithm. + /// + /// \pre init() must be called and at least one node should be added + /// with addSource() before using this function. + void start() { + while ( !emptyQueue() ) processNextArc(); + } + + /// \brief Executes the algorithm until \c dest is reached. + /// + /// Executes the algorithm until \c dest is reached. + /// + /// \pre init() must be called and at least one node should be added + /// with addSource() before using this function. + void start(Node dest) { + while ( !emptyQueue() && _digraph->target(_stack[_stack_head]) != dest ) + processNextArc(); + } + + /// \brief Executes the algorithm until a condition is met. + /// + /// Executes the algorithm until a condition is met. + /// + /// \pre init() must be called and at least one node should be added + /// with addSource() before using this function. + /// + /// \param em must be a bool (or convertible) arc map. The algorithm + /// will stop when it reaches an arc \c e with em[e] true. + /// + ///\return The reached arc \c e with em[e] true or + ///\c INVALID if no such arc was found. + /// + /// \warning Contrary to \ref Bfs and \ref Dijkstra, \c em is an arc map, + /// not a node map. + template + Arc start(const EM &em) { + while ( !emptyQueue() && !em[_stack[_stack_head]] ) + processNextArc(); + return emptyQueue() ? INVALID : _stack[_stack_head]; + } + + /// \brief Runs %DFSVisit algorithm from node \c s. + /// + /// This method runs the %DFS algorithm from a root node \c s. + /// \note d.run(s) is just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + /// \brief Runs %DFSVisit algorithm to visit all nodes in the digraph. + + /// This method runs the %DFS algorithm in order to + /// compute the %DFS path to each node. The algorithm computes + /// - The %DFS tree. + /// - The distance of each node from the root in the %DFS tree. + /// + ///\note d.run() is just a shortcut of the following code. + ///\code + /// d.init(); + /// for (NodeIt it(digraph); it != INVALID; ++it) { + /// if (!d.reached(it)) { + /// d.addSource(it); + /// d.start(); + /// } + /// } + ///\endcode + void run() { + init(); + for (NodeIt it(*_digraph); it != INVALID; ++it) { + if (!reached(it)) { + addSource(it); + start(); + } + } + } + ///@} + + /// \name Query Functions + /// The result of the %DFS algorithm can be obtained using these + /// functions.\n + /// Before the use of these functions, + /// either run() or start() must be called. + ///@{ + /// \brief Checks if a node is reachable from the root. + /// + /// Returns \c true if \c v is reachable from the root(s). + /// \warning The source nodes are inditated as unreachable. + /// \pre Either \ref run() or \ref start() + /// must be called before using this function. + /// + bool reached(Node v) { return (*_reached)[v]; } + ///@} + }; + + +} //END OF NAMESPACE LEMON + +#endif + diff --git a/lemon/dijkstra.h b/lemon/dijkstra.h new file mode 100644 --- /dev/null +++ b/lemon/dijkstra.h @@ -0,0 +1,1209 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_DIJKSTRA_H +#define LEMON_DIJKSTRA_H + +///\ingroup shortest_path +///\file +///\brief Dijkstra algorithm. +/// + +#include +#include +#include +#include +#include +#include + + +namespace lemon { + + /// \brief Default OperationTraits for the Dijkstra algorithm class. + /// + /// It defines all computational operations and constants which are + /// used in the Dijkstra algorithm. + template + struct DijkstraDefaultOperationTraits { + /// \brief Gives back the zero value of the type. + static Value zero() { + return static_cast(0); + } + /// \brief Gives back the sum of the given two elements. + static Value plus(const Value& left, const Value& right) { + return left + right; + } + /// \brief Gives back true only if the first value less than the second. + static bool less(const Value& left, const Value& right) { + return left < right; + } + }; + + /// \brief Widest path OperationTraits for the Dijkstra algorithm class. + /// + /// It defines all computational operations and constants which are + /// used in the Dijkstra algorithm for widest path computation. + template + struct DijkstraWidestPathOperationTraits { + /// \brief Gives back the maximum value of the type. + static Value zero() { + return std::numeric_limits::max(); + } + /// \brief Gives back the minimum of the given two elements. + static Value plus(const Value& left, const Value& right) { + return std::min(left, right); + } + /// \brief Gives back true only if the first value less than the second. + static bool less(const Value& left, const Value& right) { + return left < right; + } + }; + + ///Default traits class of Dijkstra class. + + ///Default traits class of Dijkstra class. + ///\param GR Digraph type. + ///\param LM Type of length map. + template + struct DijkstraDefaultTraits + { + ///The digraph type the algorithm runs on. + typedef GR Digraph; + ///The type of the map that stores the arc lengths. + + ///The type of the map that stores the arc lengths. + ///It must meet the \ref concepts::ReadMap "ReadMap" concept. + typedef LM LengthMap; + //The type of the length of the arcs. + typedef typename LM::Value Value; + /// Operation traits for Dijkstra algorithm. + + /// It defines the used operation by the algorithm. + /// \see DijkstraDefaultOperationTraits + typedef DijkstraDefaultOperationTraits OperationTraits; + /// The cross reference type used by heap. + + + /// The cross reference type used by heap. + /// Usually it is \c Digraph::NodeMap. + typedef typename Digraph::template NodeMap HeapCrossRef; + ///Instantiates a HeapCrossRef. + + ///This function instantiates a \c HeapCrossRef. + /// \param G is the digraph, to which we would like to define the + /// HeapCrossRef. + static HeapCrossRef *createHeapCrossRef(const GR &G) + { + return new HeapCrossRef(G); + } + + ///The heap type used by Dijkstra algorithm. + + ///The heap type used by Dijkstra algorithm. + /// + ///\sa BinHeap + ///\sa Dijkstra + typedef BinHeap > Heap; + + static Heap *createHeap(HeapCrossRef& R) + { + return new Heap(R); + } + + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + /// + ///The type of the map that stores the last + ///arcs of the shortest paths. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef typename Digraph::template NodeMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \c PredMap. + ///\param G is the digraph, to which we would like to define the PredMap. + ///\todo The digraph alone may be insufficient for the initialization + static PredMap *createPredMap(const GR &G) + { + return new PredMap(G); + } + + ///The type of the map that stores whether a nodes is processed. + + ///The type of the map that stores whether a nodes is processed. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///By default it is a NullMap. + ///\todo If it is set to a real map, + ///Dijkstra::processed() should read this. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \c ProcessedMap. + ///\param g is the digraph, to which + ///we would like to define the \c ProcessedMap +#ifdef DOXYGEN + static ProcessedMap *createProcessedMap(const GR &g) +#else + static ProcessedMap *createProcessedMap(const GR &) +#endif + { + return new ProcessedMap(); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef typename Digraph::template NodeMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the digraph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &G) + { + return new DistMap(G); + } + }; + + ///%Dijkstra algorithm class. + + /// \ingroup shortest_path + ///This class provides an efficient implementation of %Dijkstra algorithm. + ///The arc lengths are passed to the algorithm using a + ///\ref concepts::ReadMap "ReadMap", + ///so it is easy to change it to any kind of length. + /// + ///The type of the length is determined by the + ///\ref concepts::ReadMap::Value "Value" of the length map. + /// + ///It is also possible to change the underlying priority heap. + /// + ///\param GR The digraph type the algorithm runs on. The default value + ///is \ref ListDigraph. The value of GR is not used directly by + ///Dijkstra, it is only passed to \ref DijkstraDefaultTraits. + ///\param LM This read-only ArcMap determines the lengths of the + ///arcs. It is read once for each arc, so the map may involve in + ///relatively time consuming process to compute the arc length if + ///it is necessary. The default map type is \ref + ///concepts::Digraph::ArcMap "Digraph::ArcMap". The value + ///of LM is not used directly by Dijkstra, it is only passed to \ref + ///DijkstraDefaultTraits. \param TR Traits class to set + ///various data types used by the algorithm. The default traits + ///class is \ref DijkstraDefaultTraits + ///"DijkstraDefaultTraits". See \ref + ///DijkstraDefaultTraits for the documentation of a Dijkstra traits + ///class. + /// + ///\author Jacint Szabo and Alpar Juttner + +#ifdef DOXYGEN + template +#else + template , + typename TR=DijkstraDefaultTraits > +#endif + class Dijkstra { + public: + /** + * \brief \ref Exception for uninitialized parameters. + * + * This error represents problems in the initialization + * of the parameters of the algorithms. + */ + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* what() const throw() { + return "lemon::Dijkstra::UninitializedParameter"; + } + }; + + typedef TR Traits; + ///The type of the underlying digraph. + typedef typename TR::Digraph Digraph; + ///\e + typedef typename Digraph::Node Node; + ///\e + typedef typename Digraph::NodeIt NodeIt; + ///\e + typedef typename Digraph::Arc Arc; + ///\e + typedef typename Digraph::OutArcIt OutArcIt; + + ///The type of the length of the arcs. + typedef typename TR::LengthMap::Value Value; + ///The type of the map that stores the arc lengths. + typedef typename TR::LengthMap LengthMap; + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + typedef typename TR::PredMap PredMap; + ///The type of the map indicating if a node is processed. + typedef typename TR::ProcessedMap ProcessedMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + ///The cross reference type used for the current heap. + typedef typename TR::HeapCrossRef HeapCrossRef; + ///The heap type used by the dijkstra algorithm. + typedef typename TR::Heap Heap; + ///The operation traits. + typedef typename TR::OperationTraits OperationTraits; + private: + /// Pointer to the underlying digraph. + const Digraph *G; + /// Pointer to the length map + const LengthMap *length; + ///Pointer to the map of predecessors arcs. + PredMap *_pred; + ///Indicates if \ref _pred is locally allocated (\c true) or not. + bool local_pred; + ///Pointer to the map of distances. + DistMap *_dist; + ///Indicates if \ref _dist is locally allocated (\c true) or not. + bool local_dist; + ///Pointer to the map of processed status of the nodes. + ProcessedMap *_processed; + ///Indicates if \ref _processed is locally allocated (\c true) or not. + bool local_processed; + ///Pointer to the heap cross references. + HeapCrossRef *_heap_cross_ref; + ///Indicates if \ref _heap_cross_ref is locally allocated (\c true) or not. + bool local_heap_cross_ref; + ///Pointer to the heap. + Heap *_heap; + ///Indicates if \ref _heap is locally allocated (\c true) or not. + bool local_heap; + + ///Creates the maps if necessary. + + ///\todo Better memory allocation (instead of new). + void create_maps() + { + if(!_pred) { + local_pred = true; + _pred = Traits::createPredMap(*G); + } + if(!_dist) { + local_dist = true; + _dist = Traits::createDistMap(*G); + } + if(!_processed) { + local_processed = true; + _processed = Traits::createProcessedMap(*G); + } + if (!_heap_cross_ref) { + local_heap_cross_ref = true; + _heap_cross_ref = Traits::createHeapCrossRef(*G); + } + if (!_heap) { + local_heap = true; + _heap = Traits::createHeap(*_heap_cross_ref); + } + } + + public : + + typedef Dijkstra Create; + + ///\name Named template parameters + + ///@{ + + template + struct DefPredMapTraits : public Traits { + typedef T PredMap; + static PredMap *createPredMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting PredMap type + + ///\ref named-templ-param "Named parameter" for setting PredMap type + /// + template + struct DefPredMap + : public Dijkstra< Digraph, LengthMap, DefPredMapTraits > { + typedef Dijkstra< Digraph, LengthMap, DefPredMapTraits > Create; + }; + + template + struct DefDistMapTraits : public Traits { + typedef T DistMap; + static DistMap *createDistMap(const Digraph &) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting DistMap type + + ///\ref named-templ-param "Named parameter" for setting DistMap type + /// + template + struct DefDistMap + : public Dijkstra< Digraph, LengthMap, DefDistMapTraits > { + typedef Dijkstra< Digraph, LengthMap, DefDistMapTraits > Create; + }; + + template + struct DefProcessedMapTraits : public Traits { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + /// + template + struct DefProcessedMap + : public Dijkstra< Digraph, LengthMap, DefProcessedMapTraits > { + typedef Dijkstra< Digraph, LengthMap, DefProcessedMapTraits > Create; + }; + + struct DefDigraphProcessedMapTraits : public Traits { + typedef typename Digraph::template NodeMap ProcessedMap; + static ProcessedMap *createProcessedMap(const Digraph &G) + { + return new ProcessedMap(G); + } + }; + ///\brief \ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Digraph::NodeMap. + /// + ///\ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Digraph::NodeMap. + ///If you don't set it explicitely, it will be automatically allocated. + template + struct DefProcessedMapToBeDefaultMap + : public Dijkstra< Digraph, LengthMap, DefDigraphProcessedMapTraits> { + typedef Dijkstra< Digraph, LengthMap, DefDigraphProcessedMapTraits> Create; + }; + + template + struct DefHeapTraits : public Traits { + typedef CR HeapCrossRef; + typedef H Heap; + static HeapCrossRef *createHeapCrossRef(const Digraph &) { + throw UninitializedParameter(); + } + static Heap *createHeap(HeapCrossRef &) + { + throw UninitializedParameter(); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///heap and cross reference type + /// + ///\ref named-templ-param "Named parameter" for setting heap and cross + ///reference type + /// + template > + struct DefHeap + : public Dijkstra< Digraph, LengthMap, DefHeapTraits > { + typedef Dijkstra< Digraph, LengthMap, DefHeapTraits > Create; + }; + + template + struct DefStandardHeapTraits : public Traits { + typedef CR HeapCrossRef; + typedef H Heap; + static HeapCrossRef *createHeapCrossRef(const Digraph &G) { + return new HeapCrossRef(G); + } + static Heap *createHeap(HeapCrossRef &R) + { + return new Heap(R); + } + }; + ///\brief \ref named-templ-param "Named parameter" for setting + ///heap and cross reference type with automatic allocation + /// + ///\ref named-templ-param "Named parameter" for setting heap and cross + ///reference type. It can allocate the heap and the cross reference + ///object if the cross reference's constructor waits for the digraph as + ///parameter and the heap's constructor waits for the cross reference. + template > + struct DefStandardHeap + : public Dijkstra< Digraph, LengthMap, DefStandardHeapTraits > { + typedef Dijkstra< Digraph, LengthMap, DefStandardHeapTraits > + Create; + }; + + template + struct DefOperationTraitsTraits : public Traits { + typedef T OperationTraits; + }; + + /// \brief \ref named-templ-param "Named parameter" for setting + /// OperationTraits type + /// + /// \ref named-templ-param "Named parameter" for setting OperationTraits + /// type + template + struct DefOperationTraits + : public Dijkstra > { + typedef Dijkstra > + Create; + }; + + ///@} + + + protected: + + Dijkstra() {} + + public: + + ///Constructor. + + ///\param _G the digraph the algorithm will run on. + ///\param _length the length map used by the algorithm. + Dijkstra(const Digraph& _G, const LengthMap& _length) : + G(&_G), length(&_length), + _pred(NULL), local_pred(false), + _dist(NULL), local_dist(false), + _processed(NULL), local_processed(false), + _heap_cross_ref(NULL), local_heap_cross_ref(false), + _heap(NULL), local_heap(false) + { } + + ///Destructor. + ~Dijkstra() + { + if(local_pred) delete _pred; + if(local_dist) delete _dist; + if(local_processed) delete _processed; + if(local_heap_cross_ref) delete _heap_cross_ref; + if(local_heap) delete _heap; + } + + ///Sets the length map. + + ///Sets the length map. + ///\return (*this) + Dijkstra &lengthMap(const LengthMap &m) + { + length = &m; + return *this; + } + + ///Sets the map storing the predecessor arcs. + + ///Sets the map storing the predecessor arcs. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dijkstra &predMap(PredMap &m) + { + if(local_pred) { + delete _pred; + local_pred=false; + } + _pred = &m; + return *this; + } + + ///Sets the map storing the distances calculated by the algorithm. + + ///Sets the map storing the distances calculated by the algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dijkstra &distMap(DistMap &m) + { + if(local_dist) { + delete _dist; + local_dist=false; + } + _dist = &m; + return *this; + } + + ///Sets the heap and the cross reference used by algorithm. + + ///Sets the heap and the cross reference used by algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated heap and cross reference, of course. + ///\return (*this) + Dijkstra &heap(Heap& hp, HeapCrossRef &cr) + { + if(local_heap_cross_ref) { + delete _heap_cross_ref; + local_heap_cross_ref=false; + } + _heap_cross_ref = &cr; + if(local_heap) { + delete _heap; + local_heap=false; + } + _heap = &hp; + return *this; + } + + private: + void finalizeNodeData(Node v,Value dst) + { + _processed->set(v,true); + _dist->set(v, dst); + } + + public: + + typedef PredMapPath Path; + + ///\name Execution control + ///The simplest way to execute the algorithm is to use + ///one of the member functions called \c run(...). + ///\n + ///If you need more control on the execution, + ///first you must call \ref init(), then you can add several source nodes + ///with \ref addSource(). + ///Finally \ref start() will perform the actual path + ///computation. + + ///@{ + + ///Initializes the internal data structures. + + ///Initializes the internal data structures. + /// + void init() + { + create_maps(); + _heap->clear(); + for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { + _pred->set(u,INVALID); + _processed->set(u,false); + _heap_cross_ref->set(u,Heap::PRE_HEAP); + } + } + + ///Adds a new source node. + + ///Adds a new source node to the priority heap. + /// + ///The optional second parameter is the initial distance of the node. + /// + ///It checks if the node has already been added to the heap and + ///it is pushed to the heap only if either it was not in the heap + ///or the shortest path found till then is shorter than \c dst. + void addSource(Node s,Value dst=OperationTraits::zero()) + { + if(_heap->state(s) != Heap::IN_HEAP) { + _heap->push(s,dst); + } else if(OperationTraits::less((*_heap)[s], dst)) { + _heap->set(s,dst); + _pred->set(s,INVALID); + } + } + + ///Processes the next node in the priority heap + + ///Processes the next node in the priority heap. + /// + ///\return The processed node. + /// + ///\warning The priority heap must not be empty! + Node processNextNode() + { + Node v=_heap->top(); + Value oldvalue=_heap->prio(); + _heap->pop(); + finalizeNodeData(v,oldvalue); + + for(OutArcIt e(*G,v); e!=INVALID; ++e) { + Node w=G->target(e); + switch(_heap->state(w)) { + case Heap::PRE_HEAP: + _heap->push(w,OperationTraits::plus(oldvalue, (*length)[e])); + _pred->set(w,e); + break; + case Heap::IN_HEAP: + { + Value newvalue = OperationTraits::plus(oldvalue, (*length)[e]); + if ( OperationTraits::less(newvalue, (*_heap)[w]) ) { + _heap->decrease(w, newvalue); + _pred->set(w,e); + } + } + break; + case Heap::POST_HEAP: + break; + } + } + return v; + } + + ///Next node to be processed. + + ///Next node to be processed. + /// + ///\return The next node to be processed or INVALID if the priority heap + /// is empty. + Node nextNode() + { + return !_heap->empty()?_heap->top():INVALID; + } + + ///\brief Returns \c false if there are nodes + ///to be processed in the priority heap + /// + ///Returns \c false if there are nodes + ///to be processed in the priority heap + bool emptyQueue() { return _heap->empty(); } + ///Returns the number of the nodes to be processed in the priority heap + + ///Returns the number of the nodes to be processed in the priority heap + /// + int queueSize() { return _heap->size(); } + + ///Executes the algorithm. + + ///Executes the algorithm. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %Dijkstra algorithm from the root node(s) + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root(s). + /// + void start() + { + while ( !_heap->empty() ) processNextNode(); + } + + ///Executes the algorithm until \c dest is reached. + + ///Executes the algorithm until \c dest is reached. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %Dijkstra algorithm from the root node(s) + ///in order to + ///compute the + ///shortest path to \c dest. The algorithm computes + ///- The shortest path to \c dest. + ///- The distance of \c dest from the root(s). + /// + void start(Node dest) + { + while ( !_heap->empty() && _heap->top()!=dest ) processNextNode(); + if ( !_heap->empty() ) finalizeNodeData(_heap->top(),_heap->prio()); + } + + ///Executes the algorithm until a condition is met. + + ///Executes the algorithm until a condition is met. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///\param nm must be a bool (or convertible) node map. The algorithm + ///will stop when it reaches a node \c v with nm[v] true. + /// + ///\return The reached node \c v with nm[v] true or + ///\c INVALID if no such node was found. + template + Node start(const NodeBoolMap &nm) + { + while ( !_heap->empty() && !nm[_heap->top()] ) processNextNode(); + if ( _heap->empty() ) return INVALID; + finalizeNodeData(_heap->top(),_heap->prio()); + return _heap->top(); + } + + ///Runs %Dijkstra algorithm from node \c s. + + ///This method runs the %Dijkstra algorithm from a root node \c s + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root. + /// + ///\note d.run(s) is just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + ///Finds the shortest path between \c s and \c t. + + ///Finds the shortest path between \c s and \c t. + /// + ///\return The length of the shortest s---t path if there exists one, + ///0 otherwise. + ///\note Apart from the return value, d.run(s) is + ///just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(t); + ///\endcode + Value run(Node s,Node t) { + init(); + addSource(s); + start(t); + return (*_pred)[t]==INVALID?OperationTraits::zero():(*_dist)[t]; + } + + ///@} + + ///\name Query Functions + ///The result of the %Dijkstra algorithm can be obtained using these + ///functions.\n + ///Before the use of these functions, + ///either run() or start() must be called. + + ///@{ + + ///Gives back the shortest path. + + ///Gives back the shortest path. + ///\pre The \c t should be reachable from the source. + Path path(Node t) + { + return Path(*G, *_pred, t); + } + + ///The distance of a node from the root. + + ///Returns the distance of a node from the root. + ///\pre \ref run() must be called before using this function. + ///\warning If node \c v in unreachable from the root the return value + ///of this funcion is undefined. + Value dist(Node v) const { return (*_dist)[v]; } + + ///The current distance of a node from the root. + + ///Returns the current distance of a node from the root. + ///It may be decreased in the following processes. + ///\pre \c node should be reached but not processed + Value currentDist(Node v) const { return (*_heap)[v]; } + + ///Returns the 'previous arc' of the shortest path tree. + + ///For a node \c v it returns the 'previous arc' of the shortest path tree, + ///i.e. it returns the last arc of a shortest path from the root to \c + ///v. It is \ref INVALID + ///if \c v is unreachable from the root or if \c v=s. The + ///shortest path tree used here is equal to the shortest path tree used in + ///\ref predNode(). \pre \ref run() must be called before using + ///this function. + Arc predArc(Node v) const { return (*_pred)[v]; } + + ///Returns the 'previous node' of the shortest path tree. + + ///For a node \c v it returns the 'previous node' of the shortest path tree, + ///i.e. it returns the last but one node from a shortest path from the + ///root to \c /v. It is INVALID if \c v is unreachable from the root or if + ///\c v=s. The shortest path tree used here is equal to the shortest path + ///tree used in \ref predArc(). \pre \ref run() must be called before + ///using this function. + Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: + G->source((*_pred)[v]); } + + ///Returns a reference to the NodeMap of distances. + + ///Returns a reference to the NodeMap of distances. \pre \ref run() must + ///be called before using this function. + const DistMap &distMap() const { return *_dist;} + + ///Returns a reference to the shortest path tree map. + + ///Returns a reference to the NodeMap of the arcs of the + ///shortest path tree. + ///\pre \ref run() must be called before using this function. + const PredMap &predMap() const { return *_pred;} + + ///Checks if a node is reachable from the root. + + ///Returns \c true if \c v is reachable from the root. + ///\warning The source nodes are inditated as unreached. + ///\pre \ref run() must be called before using this function. + /// + bool reached(Node v) { return (*_heap_cross_ref)[v] != Heap::PRE_HEAP; } + + ///Checks if a node is processed. + + ///Returns \c true if \c v is processed, i.e. the shortest + ///path to \c v has already found. + ///\pre \ref run() must be called before using this function. + /// + bool processed(Node v) { return (*_heap_cross_ref)[v] == Heap::POST_HEAP; } + + ///@} + }; + + + + + + ///Default traits class of Dijkstra function. + + ///Default traits class of Dijkstra function. + ///\param GR Digraph type. + ///\param LM Type of length map. + template + struct DijkstraWizardDefaultTraits + { + ///The digraph type the algorithm runs on. + typedef GR Digraph; + ///The type of the map that stores the arc lengths. + + ///The type of the map that stores the arc lengths. + ///It must meet the \ref concepts::ReadMap "ReadMap" concept. + typedef LM LengthMap; + //The type of the length of the arcs. + typedef typename LM::Value Value; + /// Operation traits for Dijkstra algorithm. + + /// It defines the used operation by the algorithm. + /// \see DijkstraDefaultOperationTraits + typedef DijkstraDefaultOperationTraits OperationTraits; + ///The heap type used by Dijkstra algorithm. + + /// The cross reference type used by heap. + + /// The cross reference type used by heap. + /// Usually it is \c Digraph::NodeMap. + typedef typename Digraph::template NodeMap HeapCrossRef; + ///Instantiates a HeapCrossRef. + + ///This function instantiates a \ref HeapCrossRef. + /// \param G is the digraph, to which we would like to define the + /// HeapCrossRef. + /// \todo The digraph alone may be insufficient for the initialization + static HeapCrossRef *createHeapCrossRef(const GR &G) + { + return new HeapCrossRef(G); + } + + ///The heap type used by Dijkstra algorithm. + + ///The heap type used by Dijkstra algorithm. + /// + ///\sa BinHeap + ///\sa Dijkstra + typedef BinHeap, + std::less > Heap; + + static Heap *createHeap(HeapCrossRef& R) + { + return new Heap(R); + } + + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + /// + ///The type of the map that stores the last + ///arcs of the shortest paths. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef NullMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param g is the digraph, to which we would like to define the PredMap. + ///\todo The digraph alone may be insufficient for the initialization +#ifdef DOXYGEN + static PredMap *createPredMap(const GR &g) +#else + static PredMap *createPredMap(const GR &) +#endif + { + return new PredMap(); + } + ///The type of the map that stores whether a nodes is processed. + + ///The type of the map that stores whether a nodes is processed. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///By default it is a NullMap. + ///\todo If it is set to a real map, + ///Dijkstra::processed() should read this. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param g is the digraph, to which + ///we would like to define the \ref ProcessedMap +#ifdef DOXYGEN + static ProcessedMap *createProcessedMap(const GR &g) +#else + static ProcessedMap *createProcessedMap(const GR &) +#endif + { + return new ProcessedMap(); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + /// + typedef NullMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param g is the digraph, to which we would like to define the \ref DistMap +#ifdef DOXYGEN + static DistMap *createDistMap(const GR &g) +#else + static DistMap *createDistMap(const GR &) +#endif + { + return new DistMap(); + } + }; + + /// Default traits used by \ref DijkstraWizard + + /// To make it easier to use Dijkstra algorithm + ///we have created a wizard class. + /// This \ref DijkstraWizard class needs default traits, + ///as well as the \ref Dijkstra class. + /// The \ref DijkstraWizardBase is a class to be the default traits of the + /// \ref DijkstraWizard class. + /// \todo More named parameters are required... + template + class DijkstraWizardBase : public DijkstraWizardDefaultTraits + { + + typedef DijkstraWizardDefaultTraits Base; + protected: + /// Type of the nodes in the digraph. + typedef typename Base::Digraph::Node Node; + + /// Pointer to the underlying digraph. + void *_g; + /// Pointer to the length map + void *_length; + ///Pointer to the map of predecessors arcs. + void *_pred; + ///Pointer to the map of distances. + void *_dist; + ///Pointer to the source node. + Node _source; + + public: + /// Constructor. + + /// This constructor does not require parameters, therefore it initiates + /// all of the attributes to default values (0, INVALID). + DijkstraWizardBase() : _g(0), _length(0), _pred(0), + _dist(0), _source(INVALID) {} + + /// Constructor. + + /// This constructor requires some parameters, + /// listed in the parameters list. + /// Others are initiated to 0. + /// \param g is the initial value of \ref _g + /// \param l is the initial value of \ref _length + /// \param s is the initial value of \ref _source + DijkstraWizardBase(const GR &g,const LM &l, Node s=INVALID) : + _g(reinterpret_cast(const_cast(&g))), + _length(reinterpret_cast(const_cast(&l))), + _pred(0), _dist(0), _source(s) {} + + }; + + /// A class to make the usage of Dijkstra algorithm easier + + /// This class is created to make it easier to use Dijkstra algorithm. + /// It uses the functions and features of the plain \ref Dijkstra, + /// but it is much simpler to use it. + /// + /// Simplicity means that the way to change the types defined + /// in the traits class is based on functions that returns the new class + /// and not on templatable built-in classes. + /// When using the plain \ref Dijkstra + /// the new class with the modified type comes from + /// the original class by using the :: + /// operator. In the case of \ref DijkstraWizard only + /// a function have to be called and it will + /// return the needed class. + /// + /// It does not have own \ref run method. When its \ref run method is called + /// it initiates a plain \ref Dijkstra class, and calls the \ref + /// Dijkstra::run method of it. + template + class DijkstraWizard : public TR + { + typedef TR Base; + + ///The type of the underlying digraph. + typedef typename TR::Digraph Digraph; + //\e + typedef typename Digraph::Node Node; + //\e + typedef typename Digraph::NodeIt NodeIt; + //\e + typedef typename Digraph::Arc Arc; + //\e + typedef typename Digraph::OutArcIt OutArcIt; + + ///The type of the map that stores the arc lengths. + typedef typename TR::LengthMap LengthMap; + ///The type of the length of the arcs. + typedef typename LengthMap::Value Value; + ///\brief The type of the map that stores the last + ///arcs of the shortest paths. + typedef typename TR::PredMap PredMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + ///The heap type used by the dijkstra algorithm. + typedef typename TR::Heap Heap; + public: + /// Constructor. + DijkstraWizard() : TR() {} + + /// Constructor that requires parameters. + + /// Constructor that requires parameters. + /// These parameters will be the default values for the traits class. + DijkstraWizard(const Digraph &g,const LengthMap &l, Node s=INVALID) : + TR(g,l,s) {} + + ///Copy constructor + DijkstraWizard(const TR &b) : TR(b) {} + + ~DijkstraWizard() {} + + ///Runs Dijkstra algorithm from a given node. + + ///Runs Dijkstra algorithm from a given node. + ///The node can be given by the \ref source function. + void run() + { + if(Base::_source==INVALID) throw UninitializedParameter(); + Dijkstra + dij(*reinterpret_cast(Base::_g), + *reinterpret_cast(Base::_length)); + if(Base::_pred) dij.predMap(*reinterpret_cast(Base::_pred)); + if(Base::_dist) dij.distMap(*reinterpret_cast(Base::_dist)); + dij.run(Base::_source); + } + + ///Runs Dijkstra algorithm from the given node. + + ///Runs Dijkstra algorithm from the given node. + ///\param s is the given source. + void run(Node s) + { + Base::_source=s; + run(); + } + + template + struct DefPredMapBase : public Base { + typedef T PredMap; + static PredMap *createPredMap(const Digraph &) { return 0; }; + DefPredMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + template + DijkstraWizard > predMap(const T &t) + { + Base::_pred=reinterpret_cast(const_cast(&t)); + return DijkstraWizard >(*this); + } + + template + struct DefDistMapBase : public Base { + typedef T DistMap; + static DistMap *createDistMap(const Digraph &) { return 0; }; + DefDistMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + template + DijkstraWizard > distMap(const T &t) + { + Base::_dist=reinterpret_cast(const_cast(&t)); + return DijkstraWizard >(*this); + } + + /// Sets the source node, from which the Dijkstra algorithm runs. + + /// Sets the source node, from which the Dijkstra algorithm runs. + /// \param s is the source node. + DijkstraWizard &source(Node s) + { + Base::_source=s; + return *this; + } + + }; + + ///Function type interface for Dijkstra algorithm. + + /// \ingroup shortest_path + ///Function type interface for Dijkstra algorithm. + /// + ///This function also has several + ///\ref named-templ-func-param "named parameters", + ///they are declared as the members of class \ref DijkstraWizard. + ///The following + ///example shows how to use these parameters. + ///\code + /// dijkstra(g,length,source).predMap(preds).run(); + ///\endcode + ///\warning Don't forget to put the \ref DijkstraWizard::run() "run()" + ///to the end of the parameter list. + ///\sa DijkstraWizard + ///\sa Dijkstra + template + DijkstraWizard > + dijkstra(const GR &g,const LM &l,typename GR::Node s=INVALID) + { + return DijkstraWizard >(g,l,s); + } + +} //END OF NAMESPACE LEMON + +#endif diff --git a/lemon/graph_utils.h b/lemon/graph_utils.h new file mode 100644 --- /dev/null +++ b/lemon/graph_utils.h @@ -0,0 +1,3179 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_GRAPH_UTILS_H +#define LEMON_GRAPH_UTILS_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +///\ingroup gutils +///\file +///\brief Digraph utilities. + +namespace lemon { + + /// \addtogroup gutils + /// @{ + + ///Creates convenience typedefs for the digraph types and iterators + + ///This \c \#define creates convenience typedefs for the following types + ///of \c Digraph: \c Node, \c NodeIt, \c Arc, \c ArcIt, \c InArcIt, + ///\c OutArcIt + ///\note If \c G it a template parameter, it should be used in this way. + ///\code + /// GRAPH_TYPEDEFS(typename G); + ///\endcode + /// + ///\warning There are no typedefs for the digraph maps because of the lack of + ///template typedefs in C++. +#define GRAPH_TYPEDEFS(Digraph) \ + typedef Digraph:: Node Node; \ + typedef Digraph:: NodeIt NodeIt; \ + typedef Digraph:: Arc Arc; \ + typedef Digraph:: ArcIt ArcIt; \ + typedef Digraph:: InArcIt InArcIt; \ + typedef Digraph::OutArcIt OutArcIt + + ///Creates convenience typedefs for the graph types and iterators + + ///This \c \#define creates the same convenience typedefs as defined by + ///\ref GRAPH_TYPEDEFS(Digraph) and three more, namely it creates + ///\c Edge, \c EdgeIt, \c IncArcIt, + /// + ///\note If \c G it a template parameter, it should be used in this way. + ///\code + /// UGRAPH_TYPEDEFS(typename G); + ///\endcode + /// + ///\warning There are no typedefs for the digraph maps because of the lack of + ///template typedefs in C++. +#define UGRAPH_TYPEDEFS(Digraph) \ + GRAPH_TYPEDEFS(Digraph); \ + typedef Digraph:: Edge Edge; \ + typedef Digraph:: EdgeIt EdgeIt; \ + typedef Digraph:: IncArcIt IncArcIt + + ///\brief Creates convenience typedefs for the bipartite digraph + ///types and iterators + + ///This \c \#define creates the same convenience typedefs as defined by + ///\ref UGRAPH_TYPEDEFS(Digraph) and two more, namely it creates + ///\c RedIt, \c BlueIt, + /// + ///\note If \c G it a template parameter, it should be used in this way. + ///\code + /// BPUGRAPH_TYPEDEFS(typename G); + ///\endcode + /// + ///\warning There are no typedefs for the digraph maps because of the lack of + ///template typedefs in C++. +#define BPUGRAPH_TYPEDEFS(Digraph) \ + UGRAPH_TYPEDEFS(Digraph); \ + typedef Digraph::Red Red; \ + typedef Digraph::Blue Blue; \ + typedef Digraph::RedIt RedIt; \ + typedef Digraph::BlueIt BlueIt + + /// \brief Function to count the items in the digraph. + /// + /// This function counts the items (nodes, arcs etc) in the digraph. + /// The complexity of the function is O(n) because + /// it iterates on all of the items. + + template + inline int countItems(const Digraph& g) { + typedef typename ItemSetTraits::ItemIt ItemIt; + int num = 0; + for (ItemIt it(g); it != INVALID; ++it) { + ++num; + } + return num; + } + + // Node counting: + + namespace _digraph_utils_bits { + + template + struct CountNodesSelector { + static int count(const Digraph &g) { + return countItems(g); + } + }; + + template + struct CountNodesSelector< + Digraph, typename + enable_if::type> + { + static int count(const Digraph &g) { + return g.nodeNum(); + } + }; + } + + /// \brief Function to count the nodes in the digraph. + /// + /// This function counts the nodes in the digraph. + /// The complexity of the function is O(n) but for some + /// digraph structures it is specialized to run in O(1). + /// + /// If the digraph contains a \e nodeNum() member function and a + /// \e NodeNumTag tag then this function calls directly the member + /// function to query the cardinality of the node set. + template + inline int countNodes(const Digraph& g) { + return _digraph_utils_bits::CountNodesSelector::count(g); + } + + namespace _digraph_utils_bits { + + template + struct CountRedsSelector { + static int count(const Digraph &g) { + return countItems(g); + } + }; + + template + struct CountRedsSelector< + Digraph, typename + enable_if::type> + { + static int count(const Digraph &g) { + return g.redNum(); + } + }; + } + + /// \brief Function to count the reds in the digraph. + /// + /// This function counts the reds in the digraph. + /// The complexity of the function is O(an) but for some + /// digraph structures it is specialized to run in O(1). + /// + /// If the digraph contains an \e redNum() member function and a + /// \e NodeNumTag tag then this function calls directly the member + /// function to query the cardinality of the A-node set. + template + inline int countReds(const Digraph& g) { + return _digraph_utils_bits::CountRedsSelector::count(g); + } + + namespace _digraph_utils_bits { + + template + struct CountBluesSelector { + static int count(const Digraph &g) { + return countItems(g); + } + }; + + template + struct CountBluesSelector< + Digraph, typename + enable_if::type> + { + static int count(const Digraph &g) { + return g.blueNum(); + } + }; + } + + /// \brief Function to count the blues in the digraph. + /// + /// This function counts the blues in the digraph. + /// The complexity of the function is O(bn) but for some + /// digraph structures it is specialized to run in O(1). + /// + /// If the digraph contains a \e blueNum() member function and a + /// \e NodeNumTag tag then this function calls directly the member + /// function to query the cardinality of the B-node set. + template + inline int countBlues(const Digraph& g) { + return _digraph_utils_bits::CountBluesSelector::count(g); + } + + + // Arc counting: + + namespace _digraph_utils_bits { + + template + struct CountArcsSelector { + static int count(const Digraph &g) { + return countItems(g); + } + }; + + template + struct CountArcsSelector< + Digraph, + typename enable_if::type> + { + static int count(const Digraph &g) { + return g.arcNum(); + } + }; + } + + /// \brief Function to count the arcs in the digraph. + /// + /// This function counts the arcs in the digraph. + /// The complexity of the function is O(e) but for some + /// digraph structures it is specialized to run in O(1). + /// + /// If the digraph contains a \e arcNum() member function and a + /// \e ArcNumTag tag then this function calls directly the member + /// function to query the cardinality of the arc set. + template + inline int countArcs(const Digraph& g) { + return _digraph_utils_bits::CountArcsSelector::count(g); + } + + // Undirected arc counting: + namespace _digraph_utils_bits { + + template + struct CountEdgesSelector { + static int count(const Digraph &g) { + return countItems(g); + } + }; + + template + struct CountEdgesSelector< + Digraph, + typename enable_if::type> + { + static int count(const Digraph &g) { + return g.edgeNum(); + } + }; + } + + /// \brief Function to count the edges in the digraph. + /// + /// This function counts the edges in the digraph. + /// The complexity of the function is O(e) but for some + /// digraph structures it is specialized to run in O(1). + /// + /// If the digraph contains a \e edgeNum() member function and a + /// \e ArcNumTag tag then this function calls directly the member + /// function to query the cardinality of the edge set. + template + inline int countEdges(const Digraph& g) { + return _digraph_utils_bits::CountEdgesSelector::count(g); + + } + + + template + inline int countNodeDegree(const Digraph& _g, const typename Digraph::Node& _n) { + int num = 0; + for (DegIt it(_g, _n); it != INVALID; ++it) { + ++num; + } + return num; + } + + /// \brief Function to count the number of the out-arcs from node \c n. + /// + /// This function counts the number of the out-arcs from node \c n + /// in the digraph. + template + inline int countOutArcs(const Digraph& _g, const typename Digraph::Node& _n) { + return countNodeDegree(_g, _n); + } + + /// \brief Function to count the number of the in-arcs to node \c n. + /// + /// This function counts the number of the in-arcs to node \c n + /// in the digraph. + template + inline int countInArcs(const Digraph& _g, const typename Digraph::Node& _n) { + return countNodeDegree(_g, _n); + } + + /// \brief Function to count the number of the inc-arcs to node \c n. + /// + /// This function counts the number of the inc-arcs to node \c n + /// in the digraph. + template + inline int countIncArcs(const Digraph& _g, const typename Digraph::Node& _n) { + return countNodeDegree(_g, _n); + } + + namespace _digraph_utils_bits { + + template + struct FindArcSelector { + typedef typename Digraph::Node Node; + typedef typename Digraph::Arc Arc; + static Arc find(const Digraph &g, Node u, Node v, Arc e) { + if (e == INVALID) { + g.firstOut(e, u); + } else { + g.nextOut(e); + } + while (e != INVALID && g.target(e) != v) { + g.nextOut(e); + } + return e; + } + }; + + template + struct FindArcSelector< + Digraph, + typename enable_if::type> + { + typedef typename Digraph::Node Node; + typedef typename Digraph::Arc Arc; + static Arc find(const Digraph &g, Node u, Node v, Arc prev) { + return g.findArc(u, v, prev); + } + }; + } + + /// \brief Finds an arc between two nodes of a digraph. + /// + /// Finds an arc from node \c u to node \c v in digraph \c g. + /// + /// If \c prev is \ref INVALID (this is the default value), then + /// it finds the first arc from \c u to \c v. Otherwise it looks for + /// the next arc from \c u to \c v after \c prev. + /// \return The found arc or \ref INVALID if there is no such an arc. + /// + /// Thus you can iterate through each arc from \c u to \c v as it follows. + ///\code + /// for(Arc e=findArc(g,u,v);e!=INVALID;e=findArc(g,u,v,e)) { + /// ... + /// } + ///\endcode + /// + ///\sa ArcLookUp + ///\sa AllArcLookUp + ///\sa DynArcLookUp + ///\sa ConArcIt + template + inline typename Digraph::Arc + findArc(const Digraph &g, typename Digraph::Node u, typename Digraph::Node v, + typename Digraph::Arc prev = INVALID) { + return _digraph_utils_bits::FindArcSelector::find(g, u, v, prev); + } + + /// \brief Iterator for iterating on arcs connected the same nodes. + /// + /// Iterator for iterating on arcs connected the same nodes. It is + /// higher level interface for the findArc() function. You can + /// use it the following way: + ///\code + /// for (ConArcIt it(g, src, trg); it != INVALID; ++it) { + /// ... + /// } + ///\endcode + /// + ///\sa findArc() + ///\sa ArcLookUp + ///\sa AllArcLookUp + ///\sa DynArcLookUp + /// + /// \author Balazs Dezso + template + class ConArcIt : public _Digraph::Arc { + public: + + typedef _Digraph Digraph; + typedef typename Digraph::Arc Parent; + + typedef typename Digraph::Arc Arc; + typedef typename Digraph::Node Node; + + /// \brief Constructor. + /// + /// Construct a new ConArcIt iterating on the arcs which + /// connects the \c u and \c v node. + ConArcIt(const Digraph& g, Node u, Node v) : digraph(g) { + Parent::operator=(findArc(digraph, u, v)); + } + + /// \brief Constructor. + /// + /// Construct a new ConArcIt which continues the iterating from + /// the \c e arc. + ConArcIt(const Digraph& g, Arc e) : Parent(e), digraph(g) {} + + /// \brief Increment operator. + /// + /// It increments the iterator and gives back the next arc. + ConArcIt& operator++() { + Parent::operator=(findArc(digraph, digraph.source(*this), + digraph.target(*this), *this)); + return *this; + } + private: + const Digraph& digraph; + }; + + namespace _digraph_utils_bits { + + template + struct FindEdgeSelector { + typedef typename Digraph::Node Node; + typedef typename Digraph::Edge Edge; + static Edge find(const Digraph &g, Node u, Node v, Edge e) { + bool b; + if (u != v) { + if (e == INVALID) { + g.firstInc(e, b, u); + } else { + b = g.source(e) == u; + g.nextInc(e, b); + } + while (e != INVALID && (b ? g.target(e) : g.source(e)) != v) { + g.nextInc(e, b); + } + } else { + if (e == INVALID) { + g.firstInc(e, b, u); + } else { + b = true; + g.nextInc(e, b); + } + while (e != INVALID && (!b || g.target(e) != v)) { + g.nextInc(e, b); + } + } + return e; + } + }; + + template + struct FindEdgeSelector< + Digraph, + typename enable_if::type> + { + typedef typename Digraph::Node Node; + typedef typename Digraph::Edge Edge; + static Edge find(const Digraph &g, Node u, Node v, Edge prev) { + return g.findEdge(u, v, prev); + } + }; + } + + /// \brief Finds an edge between two nodes of a digraph. + /// + /// Finds an edge from node \c u to node \c v in digraph \c g. + /// If the node \c u and node \c v is equal then each loop arc + /// will be enumerated. + /// + /// If \c prev is \ref INVALID (this is the default value), then + /// it finds the first arc from \c u to \c v. Otherwise it looks for + /// the next arc from \c u to \c v after \c prev. + /// \return The found arc or \ref INVALID if there is no such an arc. + /// + /// Thus you can iterate through each arc from \c u to \c v as it follows. + ///\code + /// for(Edge e = findEdge(g,u,v); e != INVALID; + /// e = findEdge(g,u,v,e)) { + /// ... + /// } + ///\endcode + /// + ///\sa ConArcIt + + template + inline typename Digraph::Edge + findEdge(const Digraph &g, typename Digraph::Node u, typename Digraph::Node v, + typename Digraph::Edge p = INVALID) { + return _digraph_utils_bits::FindEdgeSelector::find(g, u, v, p); + } + + /// \brief Iterator for iterating on edges connected the same nodes. + /// + /// Iterator for iterating on edges connected the same nodes. It is + /// higher level interface for the findEdge() function. You can + /// use it the following way: + ///\code + /// for (ConEdgeIt it(g, src, trg); it != INVALID; ++it) { + /// ... + /// } + ///\endcode + /// + ///\sa findEdge() + /// + /// \author Balazs Dezso + template + class ConEdgeIt : public _Digraph::Edge { + public: + + typedef _Digraph Digraph; + typedef typename Digraph::Edge Parent; + + typedef typename Digraph::Edge Edge; + typedef typename Digraph::Node Node; + + /// \brief Constructor. + /// + /// Construct a new ConEdgeIt iterating on the arcs which + /// connects the \c u and \c v node. + ConEdgeIt(const Digraph& g, Node u, Node v) : digraph(g) { + Parent::operator=(findEdge(digraph, u, v)); + } + + /// \brief Constructor. + /// + /// Construct a new ConEdgeIt which continues the iterating from + /// the \c e arc. + ConEdgeIt(const Digraph& g, Edge e) : Parent(e), digraph(g) {} + + /// \brief Increment operator. + /// + /// It increments the iterator and gives back the next arc. + ConEdgeIt& operator++() { + Parent::operator=(findEdge(digraph, digraph.source(*this), + digraph.target(*this), *this)); + return *this; + } + private: + const Digraph& digraph; + }; + + /// \brief Copy a map. + /// + /// This function copies the \c from map to the \c to map. It uses the + /// given iterator to iterate on the data structure and it uses the \c ref + /// mapping to convert the from's keys to the to's keys. + template + void copyMap(To& to, const From& from, + ItemIt it, const Ref& ref) { + for (; it != INVALID; ++it) { + to[ref[it]] = from[it]; + } + } + + /// \brief Copy the from map to the to map. + /// + /// Copy the \c from map to the \c to map. It uses the given iterator + /// to iterate on the data structure. + template + void copyMap(To& to, const From& from, ItemIt it) { + for (; it != INVALID; ++it) { + to[it] = from[it]; + } + } + + namespace _digraph_utils_bits { + + template + class MapCopyBase { + public: + virtual void copy(const Digraph& from, const RefMap& refMap) = 0; + + virtual ~MapCopyBase() {} + }; + + template + class MapCopy : public MapCopyBase { + public: + + MapCopy(ToMap& tmap, const FromMap& map) + : _tmap(tmap), _map(map) {} + + virtual void copy(const Digraph& digraph, const RefMap& refMap) { + typedef typename ItemSetTraits::ItemIt ItemIt; + for (ItemIt it(digraph); it != INVALID; ++it) { + _tmap.set(refMap[it], _map[it]); + } + } + + private: + ToMap& _tmap; + const FromMap& _map; + }; + + template + class ItemCopy : public MapCopyBase { + public: + + ItemCopy(It& it, const Item& item) : _it(it), _item(item) {} + + virtual void copy(const Digraph&, const RefMap& refMap) { + _it = refMap[_item]; + } + + private: + It& _it; + Item _item; + }; + + template + class RefCopy : public MapCopyBase { + public: + + RefCopy(Ref& map) : _map(map) {} + + virtual void copy(const Digraph& digraph, const RefMap& refMap) { + typedef typename ItemSetTraits::ItemIt ItemIt; + for (ItemIt it(digraph); it != INVALID; ++it) { + _map.set(it, refMap[it]); + } + } + + private: + Ref& _map; + }; + + template + class CrossRefCopy : public MapCopyBase { + public: + + CrossRefCopy(CrossRef& cmap) : _cmap(cmap) {} + + virtual void copy(const Digraph& digraph, const RefMap& refMap) { + typedef typename ItemSetTraits::ItemIt ItemIt; + for (ItemIt it(digraph); it != INVALID; ++it) { + _cmap.set(refMap[it], it); + } + } + + private: + CrossRef& _cmap; + }; + + template + struct DigraphCopySelector { + template + static void copy(Digraph &to, const From& from, + NodeRefMap& nodeRefMap, ArcRefMap& arcRefMap) { + for (typename From::NodeIt it(from); it != INVALID; ++it) { + nodeRefMap[it] = to.addNode(); + } + for (typename From::ArcIt it(from); it != INVALID; ++it) { + arcRefMap[it] = to.addArc(nodeRefMap[from.source(it)], + nodeRefMap[from.target(it)]); + } + } + }; + + template + struct DigraphCopySelector< + Digraph, + typename enable_if::type> + { + template + static void copy(Digraph &to, const From& from, + NodeRefMap& nodeRefMap, ArcRefMap& arcRefMap) { + to.build(from, nodeRefMap, arcRefMap); + } + }; + + template + struct GraphCopySelector { + template + static void copy(Graph &to, const From& from, + NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) { + for (typename From::NodeIt it(from); it != INVALID; ++it) { + nodeRefMap[it] = to.addNode(); + } + for (typename From::EdgeIt it(from); it != INVALID; ++it) { + edgeRefMap[it] = to.addArc(nodeRefMap[from.source(it)], + nodeRefMap[from.target(it)]); + } + } + }; + + template + struct GraphCopySelector< + Graph, + typename enable_if::type> + { + template + static void copy(Graph &to, const From& from, + NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) { + to.build(from, nodeRefMap, edgeRefMap); + } + }; + + template + struct BpGraphCopySelector { + template + static void copy(BpGraph &to, const From& from, + RedRefMap& redRefMap, BlueRefMap& blueRefMap, + EdgeRefMap& edgeRefMap) { + for (typename From::RedIt it(from); it != INVALID; ++it) { + redRefMap[it] = to.addRed(); + } + for (typename From::BlueIt it(from); it != INVALID; ++it) { + blueRefMap[it] = to.addBlue(); + } + for (typename From::EdgeIt it(from); it != INVALID; ++it) { + edgeRefMap[it] = to.addArc(redRefMap[from.red(it)], + blueRefMap[from.blue(it)]); + } + } + }; + + template + struct BpGraphCopySelector< + BpGraph, + typename enable_if::type> + { + template + static void copy(BpGraph &to, const From& from, + RedRefMap& redRefMap, BlueRefMap& blueRefMap, + EdgeRefMap& edgeRefMap) { + to.build(from, redRefMap, blueRefMap, edgeRefMap); + } + }; + + + } + + /// \brief Class to copy a digraph. + /// + /// Class to copy a digraph to another digraph (duplicate a digraph). The + /// simplest way of using it is through the \c copyDigraph() function. + template + class DigraphCopy { + private: + + typedef typename From::Node Node; + typedef typename From::NodeIt NodeIt; + typedef typename From::Arc Arc; + typedef typename From::ArcIt ArcIt; + + typedef typename To::Node TNode; + typedef typename To::Arc TArc; + + typedef typename From::template NodeMap NodeRefMap; + typedef typename From::template ArcMap ArcRefMap; + + + public: + + + /// \brief Constructor for the DigraphCopy. + /// + /// It copies the content of the \c _from digraph into the + /// \c _to digraph. + DigraphCopy(To& _to, const From& _from) + : from(_from), to(_to) {} + + /// \brief Destructor of the DigraphCopy + /// + /// Destructor of the DigraphCopy + ~DigraphCopy() { + for (int i = 0; i < int(nodeMapCopies.size()); ++i) { + delete nodeMapCopies[i]; + } + for (int i = 0; i < int(arcMapCopies.size()); ++i) { + delete arcMapCopies[i]; + } + + } + + /// \brief Copies the node references into the given map. + /// + /// Copies the node references into the given map. + template + DigraphCopy& nodeRef(NodeRef& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the node cross references into the given map. + /// + /// Copies the node cross references (reverse references) into + /// the given map. + template + DigraphCopy& nodeCrossRef(NodeCrossRef& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's node type, + /// and the copied map's key type is the from digraph's node + /// type. + template + DigraphCopy& nodeMap(ToMap& tmap, const FromMap& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given node. + /// + /// Make a copy of the given node. + DigraphCopy& node(TNode& tnode, const Node& snode) { + nodeMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tnode, snode)); + return *this; + } + + /// \brief Copies the arc references into the given map. + /// + /// Copies the arc references into the given map. + template + DigraphCopy& arcRef(ArcRef& map) { + arcMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the arc cross references into the given map. + /// + /// Copies the arc cross references (reverse references) into + /// the given map. + template + DigraphCopy& arcCrossRef(ArcCrossRef& map) { + arcMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's arc type, + /// and the copied map's key type is the from digraph's arc + /// type. + template + DigraphCopy& arcMap(ToMap& tmap, const FromMap& map) { + arcMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given arc. + /// + /// Make a copy of the given arc. + DigraphCopy& arc(TArc& tarc, const Arc& sarc) { + arcMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tarc, sarc)); + return *this; + } + + /// \brief Executes the copies. + /// + /// Executes the copies. + void run() { + NodeRefMap nodeRefMap(from); + ArcRefMap arcRefMap(from); + _digraph_utils_bits::DigraphCopySelector:: + copy(to, from, nodeRefMap, arcRefMap); + for (int i = 0; i < int(nodeMapCopies.size()); ++i) { + nodeMapCopies[i]->copy(from, nodeRefMap); + } + for (int i = 0; i < int(arcMapCopies.size()); ++i) { + arcMapCopies[i]->copy(from, arcRefMap); + } + } + + protected: + + + const From& from; + To& to; + + std::vector<_digraph_utils_bits::MapCopyBase* > + nodeMapCopies; + + std::vector<_digraph_utils_bits::MapCopyBase* > + arcMapCopies; + + }; + + /// \brief Copy a digraph to another digraph. + /// + /// Copy a digraph to another digraph. + /// The usage of the function: + /// + ///\code + /// copyDigraph(trg, src).nodeRef(nr).arcCrossRef(ecr).run(); + ///\endcode + /// + /// After the copy the \c nr map will contain the mapping from the + /// nodes of the \c from digraph to the nodes of the \c to digraph and + /// \c ecr will contain the mapping from the arcs of the \c to digraph + /// to the arcs of the \c from digraph. + /// + /// \see DigraphCopy + template + DigraphCopy copyDigraph(To& to, const From& from) { + return DigraphCopy(to, from); + } + + /// \brief Class to copy an graph. + /// + /// Class to copy an graph to another digraph (duplicate a digraph). + /// The simplest way of using it is through the \c copyGraph() function. + template + class GraphCopy { + private: + + typedef typename From::Node Node; + typedef typename From::NodeIt NodeIt; + typedef typename From::Arc Arc; + typedef typename From::ArcIt ArcIt; + typedef typename From::Edge Edge; + typedef typename From::EdgeIt EdgeIt; + + typedef typename To::Node TNode; + typedef typename To::Arc TArc; + typedef typename To::Edge TEdge; + + typedef typename From::template NodeMap NodeRefMap; + typedef typename From::template EdgeMap EdgeRefMap; + + struct ArcRefMap { + ArcRefMap(const To& _to, const From& _from, + const EdgeRefMap& _edge_ref, const NodeRefMap& _node_ref) + : to(_to), from(_from), + edge_ref(_edge_ref), node_ref(_node_ref) {} + + typedef typename From::Arc Key; + typedef typename To::Arc Value; + + Value operator[](const Key& key) const { + bool forward = + (from.direction(key) == + (node_ref[from.source(static_cast(key))] == + to.source(edge_ref[static_cast(key)]))); + return to.direct(edge_ref[key], forward); + } + + const To& to; + const From& from; + const EdgeRefMap& edge_ref; + const NodeRefMap& node_ref; + }; + + + public: + + + /// \brief Constructor for the DigraphCopy. + /// + /// It copies the content of the \c _from digraph into the + /// \c _to digraph. + GraphCopy(To& _to, const From& _from) + : from(_from), to(_to) {} + + /// \brief Destructor of the DigraphCopy + /// + /// Destructor of the DigraphCopy + ~GraphCopy() { + for (int i = 0; i < int(nodeMapCopies.size()); ++i) { + delete nodeMapCopies[i]; + } + for (int i = 0; i < int(arcMapCopies.size()); ++i) { + delete arcMapCopies[i]; + } + for (int i = 0; i < int(edgeMapCopies.size()); ++i) { + delete edgeMapCopies[i]; + } + + } + + /// \brief Copies the node references into the given map. + /// + /// Copies the node references into the given map. + template + GraphCopy& nodeRef(NodeRef& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the node cross references into the given map. + /// + /// Copies the node cross references (reverse references) into + /// the given map. + template + GraphCopy& nodeCrossRef(NodeCrossRef& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's node type, + /// and the copied map's key type is the from digraph's node + /// type. + template + GraphCopy& nodeMap(ToMap& tmap, const FromMap& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given node. + /// + /// Make a copy of the given node. + GraphCopy& node(TNode& tnode, const Node& snode) { + nodeMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tnode, snode)); + return *this; + } + + /// \brief Copies the arc references into the given map. + /// + /// Copies the arc references into the given map. + template + GraphCopy& arcRef(ArcRef& map) { + arcMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the arc cross references into the given map. + /// + /// Copies the arc cross references (reverse references) into + /// the given map. + template + GraphCopy& arcCrossRef(ArcCrossRef& map) { + arcMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's arc type, + /// and the copied map's key type is the from digraph's arc + /// type. + template + GraphCopy& arcMap(ToMap& tmap, const FromMap& map) { + arcMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given arc. + /// + /// Make a copy of the given arc. + GraphCopy& arc(TArc& tarc, const Arc& sarc) { + arcMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tarc, sarc)); + return *this; + } + + /// \brief Copies the edge references into the given map. + /// + /// Copies the edge references into the given map. + template + GraphCopy& edgeRef(EdgeRef& map) { + edgeMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the edge cross references into the given map. + /// + /// Copies the edge cross references (reverse + /// references) into the given map. + template + GraphCopy& edgeCrossRef(EdgeCrossRef& map) { + edgeMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's edge type, + /// and the copied map's key type is the from digraph's edge + /// type. + template + GraphCopy& edgeMap(ToMap& tmap, const FromMap& map) { + edgeMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given edge. + /// + /// Make a copy of the given edge. + GraphCopy& edge(TEdge& tedge, const Edge& sedge) { + edgeMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tedge, sedge)); + return *this; + } + + /// \brief Executes the copies. + /// + /// Executes the copies. + void run() { + NodeRefMap nodeRefMap(from); + EdgeRefMap edgeRefMap(from); + ArcRefMap arcRefMap(to, from, edgeRefMap, nodeRefMap); + _digraph_utils_bits::GraphCopySelector:: + copy(to, from, nodeRefMap, edgeRefMap); + for (int i = 0; i < int(nodeMapCopies.size()); ++i) { + nodeMapCopies[i]->copy(from, nodeRefMap); + } + for (int i = 0; i < int(edgeMapCopies.size()); ++i) { + edgeMapCopies[i]->copy(from, edgeRefMap); + } + for (int i = 0; i < int(arcMapCopies.size()); ++i) { + arcMapCopies[i]->copy(from, arcRefMap); + } + } + + private: + + const From& from; + To& to; + + std::vector<_digraph_utils_bits::MapCopyBase* > + nodeMapCopies; + + std::vector<_digraph_utils_bits::MapCopyBase* > + arcMapCopies; + + std::vector<_digraph_utils_bits::MapCopyBase* > + edgeMapCopies; + + }; + + /// \brief Copy an graph to another digraph. + /// + /// Copy an graph to another digraph. + /// The usage of the function: + /// + ///\code + /// copyGraph(trg, src).nodeRef(nr).arcCrossRef(ecr).run(); + ///\endcode + /// + /// After the copy the \c nr map will contain the mapping from the + /// nodes of the \c from digraph to the nodes of the \c to digraph and + /// \c ecr will contain the mapping from the arcs of the \c to digraph + /// to the arcs of the \c from digraph. + /// + /// \see GraphCopy + template + GraphCopy + copyGraph(To& to, const From& from) { + return GraphCopy(to, from); + } + + /// \brief Class to copy a bipartite digraph. + /// + /// Class to copy a bipartite digraph to another digraph + /// (duplicate a digraph). The simplest way of using it is through + /// the \c copyBpGraph() function. + template + class BpGraphCopy { + private: + + typedef typename From::Node Node; + typedef typename From::Red Red; + typedef typename From::Blue Blue; + typedef typename From::NodeIt NodeIt; + typedef typename From::Arc Arc; + typedef typename From::ArcIt ArcIt; + typedef typename From::Edge Edge; + typedef typename From::EdgeIt EdgeIt; + + typedef typename To::Node TNode; + typedef typename To::Arc TArc; + typedef typename To::Edge TEdge; + + typedef typename From::template RedMap RedRefMap; + typedef typename From::template BlueMap BlueRefMap; + typedef typename From::template EdgeMap EdgeRefMap; + + struct NodeRefMap { + NodeRefMap(const From& _from, const RedRefMap& _red_ref, + const BlueRefMap& _blue_ref) + : from(_from), red_ref(_red_ref), blue_ref(_blue_ref) {} + + typedef typename From::Node Key; + typedef typename To::Node Value; + + Value operator[](const Key& key) const { + return from.red(key) ? red_ref[key] : blue_ref[key]; + } + + const From& from; + const RedRefMap& red_ref; + const BlueRefMap& blue_ref; + }; + + struct ArcRefMap { + ArcRefMap(const To& _to, const From& _from, + const EdgeRefMap& _edge_ref, const NodeRefMap& _node_ref) + : to(_to), from(_from), + edge_ref(_edge_ref), node_ref(_node_ref) {} + + typedef typename From::Arc Key; + typedef typename To::Arc Value; + + Value operator[](const Key& key) const { + bool forward = + (from.direction(key) == + (node_ref[from.source(static_cast(key))] == + to.source(edge_ref[static_cast(key)]))); + return to.direct(edge_ref[key], forward); + } + + const To& to; + const From& from; + const EdgeRefMap& edge_ref; + const NodeRefMap& node_ref; + }; + + public: + + + /// \brief Constructor for the DigraphCopy. + /// + /// It copies the content of the \c _from digraph into the + /// \c _to digraph. + BpGraphCopy(To& _to, const From& _from) + : from(_from), to(_to) {} + + /// \brief Destructor of the DigraphCopy + /// + /// Destructor of the DigraphCopy + ~BpGraphCopy() { + for (int i = 0; i < int(redMapCopies.size()); ++i) { + delete redMapCopies[i]; + } + for (int i = 0; i < int(blueMapCopies.size()); ++i) { + delete blueMapCopies[i]; + } + for (int i = 0; i < int(nodeMapCopies.size()); ++i) { + delete nodeMapCopies[i]; + } + for (int i = 0; i < int(arcMapCopies.size()); ++i) { + delete arcMapCopies[i]; + } + for (int i = 0; i < int(edgeMapCopies.size()); ++i) { + delete edgeMapCopies[i]; + } + + } + + /// \brief Copies the A-node references into the given map. + /// + /// Copies the A-node references into the given map. + template + BpGraphCopy& redRef(RedRef& map) { + redMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the A-node cross references into the given map. + /// + /// Copies the A-node cross references (reverse references) into + /// the given map. + template + BpGraphCopy& redCrossRef(RedCrossRef& map) { + redMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given A-node map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's node type, + /// and the copied map's key type is the from digraph's node + /// type. + template + BpGraphCopy& redMap(ToMap& tmap, const FromMap& map) { + redMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Copies the B-node references into the given map. + /// + /// Copies the B-node references into the given map. + template + BpGraphCopy& blueRef(BlueRef& map) { + blueMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the B-node cross references into the given map. + /// + /// Copies the B-node cross references (reverse references) into + /// the given map. + template + BpGraphCopy& blueCrossRef(BlueCrossRef& map) { + blueMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given B-node map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's node type, + /// and the copied map's key type is the from digraph's node + /// type. + template + BpGraphCopy& blueMap(ToMap& tmap, const FromMap& map) { + blueMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + /// \brief Copies the node references into the given map. + /// + /// Copies the node references into the given map. + template + BpGraphCopy& nodeRef(NodeRef& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the node cross references into the given map. + /// + /// Copies the node cross references (reverse references) into + /// the given map. + template + BpGraphCopy& nodeCrossRef(NodeCrossRef& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's node type, + /// and the copied map's key type is the from digraph's node + /// type. + template + BpGraphCopy& nodeMap(ToMap& tmap, const FromMap& map) { + nodeMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given node. + /// + /// Make a copy of the given node. + BpGraphCopy& node(TNode& tnode, const Node& snode) { + nodeMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tnode, snode)); + return *this; + } + + /// \brief Copies the arc references into the given map. + /// + /// Copies the arc references into the given map. + template + BpGraphCopy& arcRef(ArcRef& map) { + arcMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the arc cross references into the given map. + /// + /// Copies the arc cross references (reverse references) into + /// the given map. + template + BpGraphCopy& arcCrossRef(ArcCrossRef& map) { + arcMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's arc type, + /// and the copied map's key type is the from digraph's arc + /// type. + template + BpGraphCopy& arcMap(ToMap& tmap, const FromMap& map) { + arcMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given arc. + /// + /// Make a copy of the given arc. + BpGraphCopy& arc(TArc& tarc, const Arc& sarc) { + arcMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tarc, sarc)); + return *this; + } + + /// \brief Copies the edge references into the given map. + /// + /// Copies the edge references into the given map. + template + BpGraphCopy& edgeRef(EdgeRef& map) { + edgeMapCopies.push_back(new _digraph_utils_bits::RefCopy(map)); + return *this; + } + + /// \brief Copies the edge cross references into the given map. + /// + /// Copies the edge cross references (reverse + /// references) into the given map. + template + BpGraphCopy& edgeCrossRef(EdgeCrossRef& map) { + edgeMapCopies.push_back(new _digraph_utils_bits::CrossRefCopy(map)); + return *this; + } + + /// \brief Make copy of the given map. + /// + /// Makes copy of the given map for the newly created digraph. + /// The new map's key type is the to digraph's edge type, + /// and the copied map's key type is the from digraph's edge + /// type. + template + BpGraphCopy& edgeMap(ToMap& tmap, const FromMap& map) { + edgeMapCopies.push_back(new _digraph_utils_bits::MapCopy(tmap, map)); + return *this; + } + + /// \brief Make a copy of the given edge. + /// + /// Make a copy of the given edge. + BpGraphCopy& edge(TEdge& tedge, const Edge& sedge) { + edgeMapCopies.push_back(new _digraph_utils_bits::ItemCopy(tedge, sedge)); + return *this; + } + + /// \brief Executes the copies. + /// + /// Executes the copies. + void run() { + RedRefMap redRefMap(from); + BlueRefMap blueRefMap(from); + NodeRefMap nodeRefMap(from, redRefMap, blueRefMap); + EdgeRefMap edgeRefMap(from); + ArcRefMap arcRefMap(to, from, edgeRefMap, nodeRefMap); + _digraph_utils_bits::BpGraphCopySelector:: + copy(to, from, redRefMap, blueRefMap, edgeRefMap); + for (int i = 0; i < int(redMapCopies.size()); ++i) { + redMapCopies[i]->copy(from, redRefMap); + } + for (int i = 0; i < int(blueMapCopies.size()); ++i) { + blueMapCopies[i]->copy(from, blueRefMap); + } + for (int i = 0; i < int(nodeMapCopies.size()); ++i) { + nodeMapCopies[i]->copy(from, nodeRefMap); + } + for (int i = 0; i < int(edgeMapCopies.size()); ++i) { + edgeMapCopies[i]->copy(from, edgeRefMap); + } + for (int i = 0; i < int(arcMapCopies.size()); ++i) { + arcMapCopies[i]->copy(from, arcRefMap); + } + } + + private: + + const From& from; + To& to; + + std::vector<_digraph_utils_bits::MapCopyBase* > + redMapCopies; + + std::vector<_digraph_utils_bits::MapCopyBase* > + blueMapCopies; + + std::vector<_digraph_utils_bits::MapCopyBase* > + nodeMapCopies; + + std::vector<_digraph_utils_bits::MapCopyBase* > + arcMapCopies; + + std::vector<_digraph_utils_bits::MapCopyBase* > + edgeMapCopies; + + }; + + /// \brief Copy a bipartite digraph to another digraph. + /// + /// Copy a bipartite digraph to another digraph. + /// The usage of the function: + /// + ///\code + /// copyBpGraph(trg, src).redRef(anr).arcCrossRef(ecr).run(); + ///\endcode + /// + /// After the copy the \c nr map will contain the mapping from the + /// nodes of the \c from digraph to the nodes of the \c to digraph and + /// \c ecr will contain the mapping from the arcs of the \c to digraph + /// to the arcs of the \c from digraph. + /// + /// \see BpGraphCopy + template + BpGraphCopy + copyBpGraph(To& to, const From& from) { + return BpGraphCopy(to, from); + } + + + /// @} + + /// \addtogroup digraph_maps + /// @{ + + /// Provides an immutable and unique id for each item in the digraph. + + /// The IdMap class provides a unique and immutable id for each item of the + /// same type (e.g. node) in the digraph. This id is
  • \b unique: + /// different items (nodes) get different ids
  • \b immutable: the id of an + /// item (node) does not change (even if you delete other nodes).
+ /// Through this map you get access (i.e. can read) the inner id values of + /// the items stored in the digraph. This map can be inverted with its member + /// class \c InverseMap. + /// + template + class IdMap { + public: + typedef _Digraph Digraph; + typedef int Value; + typedef _Item Item; + typedef _Item Key; + + /// \brief Constructor. + /// + /// Constructor of the map. + explicit IdMap(const Digraph& _digraph) : digraph(&_digraph) {} + + /// \brief Gives back the \e id of the item. + /// + /// Gives back the immutable and unique \e id of the item. + int operator[](const Item& item) const { return digraph->id(item);} + + /// \brief Gives back the item by its id. + /// + /// Gives back the item by its id. + Item operator()(int id) { return digraph->fromId(id, Item()); } + + private: + const Digraph* digraph; + + public: + + /// \brief The class represents the inverse of its owner (IdMap). + /// + /// The class represents the inverse of its owner (IdMap). + /// \see inverse() + class InverseMap { + public: + + /// \brief Constructor. + /// + /// Constructor for creating an id-to-item map. + explicit InverseMap(const Digraph& _digraph) : digraph(&_digraph) {} + + /// \brief Constructor. + /// + /// Constructor for creating an id-to-item map. + explicit InverseMap(const IdMap& idMap) : digraph(idMap.digraph) {} + + /// \brief Gives back the given item from its id. + /// + /// Gives back the given item from its id. + /// + Item operator[](int id) const { return digraph->fromId(id, Item());} + + private: + const Digraph* digraph; + }; + + /// \brief Gives back the inverse of the map. + /// + /// Gives back the inverse of the IdMap. + InverseMap inverse() const { return InverseMap(*digraph);} + + }; + + + /// \brief General invertable digraph-map type. + + /// This type provides simple invertable digraph-maps. + /// The InvertableMap wraps an arbitrary ReadWriteMap + /// and if a key is set to a new value then store it + /// in the inverse map. + /// + /// The values of the map can be accessed + /// with stl compatible forward iterator. + /// + /// \param _Digraph The digraph type. + /// \param _Item The item type of the digraph. + /// \param _Value The value type of the map. + /// + /// \see IterableValueMap + template + class InvertableMap : protected DefaultMap<_Digraph, _Item, _Value> { + private: + + typedef DefaultMap<_Digraph, _Item, _Value> Map; + typedef _Digraph Digraph; + + typedef std::map<_Value, _Item> Container; + Container invMap; + + public: + + /// The key type of InvertableMap (Node, Arc, Edge). + typedef typename Map::Key Key; + /// The value type of the InvertableMap. + typedef typename Map::Value Value; + + + + /// \brief Constructor. + /// + /// Construct a new InvertableMap for the digraph. + /// + explicit InvertableMap(const Digraph& digraph) : Map(digraph) {} + + /// \brief Forward iterator for values. + /// + /// This iterator is an stl compatible forward + /// iterator on the values of the map. The values can + /// be accessed in the [beginValue, endValue) range. + /// + class ValueIterator + : public std::iterator { + friend class InvertableMap; + private: + ValueIterator(typename Container::const_iterator _it) + : it(_it) {} + public: + + ValueIterator() {} + + ValueIterator& operator++() { ++it; return *this; } + ValueIterator operator++(int) { + ValueIterator tmp(*this); + operator++(); + return tmp; + } + + const Value& operator*() const { return it->first; } + const Value* operator->() const { return &(it->first); } + + bool operator==(ValueIterator jt) const { return it == jt.it; } + bool operator!=(ValueIterator jt) const { return it != jt.it; } + + private: + typename Container::const_iterator it; + }; + + /// \brief Returns an iterator to the first value. + /// + /// Returns an stl compatible iterator to the + /// first value of the map. The values of the + /// map can be accessed in the [beginValue, endValue) + /// range. + ValueIterator beginValue() const { + return ValueIterator(invMap.begin()); + } + + /// \brief Returns an iterator after the last value. + /// + /// Returns an stl compatible iterator after the + /// last value of the map. The values of the + /// map can be accessed in the [beginValue, endValue) + /// range. + ValueIterator endValue() const { + return ValueIterator(invMap.end()); + } + + /// \brief The setter function of the map. + /// + /// Sets the mapped value. + void set(const Key& key, const Value& val) { + Value oldval = Map::operator[](key); + typename Container::iterator it = invMap.find(oldval); + if (it != invMap.end() && it->second == key) { + invMap.erase(it); + } + invMap.insert(make_pair(val, key)); + Map::set(key, val); + } + + /// \brief The getter function of the map. + /// + /// It gives back the value associated with the key. + typename MapTraits::ConstReturnValue + operator[](const Key& key) const { + return Map::operator[](key); + } + + /// \brief Gives back the item by its value. + /// + /// Gives back the item by its value. + Key operator()(const Value& key) const { + typename Container::const_iterator it = invMap.find(key); + return it != invMap.end() ? it->second : INVALID; + } + + protected: + + /// \brief Erase the key from the map. + /// + /// Erase the key to the map. It is called by the + /// \c AlterationNotifier. + virtual void erase(const Key& key) { + Value val = Map::operator[](key); + typename Container::iterator it = invMap.find(val); + if (it != invMap.end() && it->second == key) { + invMap.erase(it); + } + Map::erase(key); + } + + /// \brief Erase more keys from the map. + /// + /// Erase more keys from the map. It is called by the + /// \c AlterationNotifier. + virtual void erase(const std::vector& keys) { + for (int i = 0; i < int(keys.size()); ++i) { + Value val = Map::operator[](keys[i]); + typename Container::iterator it = invMap.find(val); + if (it != invMap.end() && it->second == keys[i]) { + invMap.erase(it); + } + } + Map::erase(keys); + } + + /// \brief Clear the keys from the map and inverse map. + /// + /// Clear the keys from the map and inverse map. It is called by the + /// \c AlterationNotifier. + virtual void clear() { + invMap.clear(); + Map::clear(); + } + + public: + + /// \brief The inverse map type. + /// + /// The inverse of this map. The subscript operator of the map + /// gives back always the item what was last assigned to the value. + class InverseMap { + public: + /// \brief Constructor of the InverseMap. + /// + /// Constructor of the InverseMap. + explicit InverseMap(const InvertableMap& _inverted) + : inverted(_inverted) {} + + /// The value type of the InverseMap. + typedef typename InvertableMap::Key Value; + /// The key type of the InverseMap. + typedef typename InvertableMap::Value Key; + + /// \brief Subscript operator. + /// + /// Subscript operator. It gives back always the item + /// what was last assigned to the value. + Value operator[](const Key& key) const { + return inverted(key); + } + + private: + const InvertableMap& inverted; + }; + + /// \brief It gives back the just readable inverse map. + /// + /// It gives back the just readable inverse map. + InverseMap inverse() const { + return InverseMap(*this); + } + + + + }; + + /// \brief Provides a mutable, continuous and unique descriptor for each + /// item in the digraph. + /// + /// The DescriptorMap class provides a unique and continuous (but mutable) + /// descriptor (id) for each item of the same type (e.g. node) in the + /// digraph. This id is
  • \b unique: different items (nodes) get + /// different ids
  • \b continuous: the range of the ids is the set of + /// integers between 0 and \c n-1, where \c n is the number of the items of + /// this type (e.g. nodes) (so the id of a node can change if you delete an + /// other node, i.e. this id is mutable).
This map can be inverted + /// with its member class \c InverseMap. + /// + /// \param _Digraph The digraph class the \c DescriptorMap belongs to. + /// \param _Item The Item is the Key of the Map. It may be Node, Arc or + /// Edge. + template + class DescriptorMap : protected DefaultMap<_Digraph, _Item, int> { + + typedef _Item Item; + typedef DefaultMap<_Digraph, _Item, int> Map; + + public: + /// The digraph class of DescriptorMap. + typedef _Digraph Digraph; + + /// The key type of DescriptorMap (Node, Arc, Edge). + typedef typename Map::Key Key; + /// The value type of DescriptorMap. + typedef typename Map::Value Value; + + /// \brief Constructor. + /// + /// Constructor for descriptor map. + explicit DescriptorMap(const Digraph& _digraph) : Map(_digraph) { + Item it; + const typename Map::Notifier* nf = Map::notifier(); + for (nf->first(it); it != INVALID; nf->next(it)) { + Map::set(it, invMap.size()); + invMap.push_back(it); + } + } + + protected: + + /// \brief Add a new key to the map. + /// + /// Add a new key to the map. It is called by the + /// \c AlterationNotifier. + virtual void add(const Item& item) { + Map::add(item); + Map::set(item, invMap.size()); + invMap.push_back(item); + } + + /// \brief Add more new keys to the map. + /// + /// Add more new keys to the map. It is called by the + /// \c AlterationNotifier. + virtual void add(const std::vector& items) { + Map::add(items); + for (int i = 0; i < int(items.size()); ++i) { + Map::set(items[i], invMap.size()); + invMap.push_back(items[i]); + } + } + + /// \brief Erase the key from the map. + /// + /// Erase the key from the map. It is called by the + /// \c AlterationNotifier. + virtual void erase(const Item& item) { + Map::set(invMap.back(), Map::operator[](item)); + invMap[Map::operator[](item)] = invMap.back(); + invMap.pop_back(); + Map::erase(item); + } + + /// \brief Erase more keys from the map. + /// + /// Erase more keys from the map. It is called by the + /// \c AlterationNotifier. + virtual void erase(const std::vector& items) { + for (int i = 0; i < int(items.size()); ++i) { + Map::set(invMap.back(), Map::operator[](items[i])); + invMap[Map::operator[](items[i])] = invMap.back(); + invMap.pop_back(); + } + Map::erase(items); + } + + /// \brief Build the unique map. + /// + /// Build the unique map. It is called by the + /// \c AlterationNotifier. + virtual void build() { + Map::build(); + Item it; + const typename Map::Notifier* nf = Map::notifier(); + for (nf->first(it); it != INVALID; nf->next(it)) { + Map::set(it, invMap.size()); + invMap.push_back(it); + } + } + + /// \brief Clear the keys from the map. + /// + /// Clear the keys from the map. It is called by the + /// \c AlterationNotifier. + virtual void clear() { + invMap.clear(); + Map::clear(); + } + + public: + + /// \brief Returns the maximal value plus one. + /// + /// Returns the maximal value plus one in the map. + unsigned int size() const { + return invMap.size(); + } + + /// \brief Swaps the position of the two items in the map. + /// + /// Swaps the position of the two items in the map. + void swap(const Item& p, const Item& q) { + int pi = Map::operator[](p); + int qi = Map::operator[](q); + Map::set(p, qi); + invMap[qi] = p; + Map::set(q, pi); + invMap[pi] = q; + } + + /// \brief Gives back the \e descriptor of the item. + /// + /// Gives back the mutable and unique \e descriptor of the map. + int operator[](const Item& item) const { + return Map::operator[](item); + } + + /// \brief Gives back the item by its descriptor. + /// + /// Gives back th item by its descriptor. + Item operator()(int id) const { + return invMap[id]; + } + + private: + + typedef std::vector Container; + Container invMap; + + public: + /// \brief The inverse map type of DescriptorMap. + /// + /// The inverse map type of DescriptorMap. + class InverseMap { + public: + /// \brief Constructor of the InverseMap. + /// + /// Constructor of the InverseMap. + explicit InverseMap(const DescriptorMap& _inverted) + : inverted(_inverted) {} + + + /// The value type of the InverseMap. + typedef typename DescriptorMap::Key Value; + /// The key type of the InverseMap. + typedef typename DescriptorMap::Value Key; + + /// \brief Subscript operator. + /// + /// Subscript operator. It gives back the item + /// that the descriptor belongs to currently. + Value operator[](const Key& key) const { + return inverted(key); + } + + /// \brief Size of the map. + /// + /// Returns the size of the map. + unsigned int size() const { + return inverted.size(); + } + + private: + const DescriptorMap& inverted; + }; + + /// \brief Gives back the inverse of the map. + /// + /// Gives back the inverse of the map. + const InverseMap inverse() const { + return InverseMap(*this); + } + }; + + /// \brief Returns the source of the given arc. + /// + /// The SourceMap gives back the source Node of the given arc. + /// \see TargetMap + /// \author Balazs Dezso + template + class SourceMap { + public: + + typedef typename Digraph::Node Value; + typedef typename Digraph::Arc Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _digraph The digraph that the map belongs to. + explicit SourceMap(const Digraph& _digraph) : digraph(_digraph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param arc The arc + /// \return The source of the arc + Value operator[](const Key& arc) const { + return digraph.source(arc); + } + + private: + const Digraph& digraph; + }; + + /// \brief Returns a \ref SourceMap class. + /// + /// This function just returns an \ref SourceMap class. + /// \relates SourceMap + template + inline SourceMap sourceMap(const Digraph& digraph) { + return SourceMap(digraph); + } + + /// \brief Returns the target of the given arc. + /// + /// The TargetMap gives back the target Node of the given arc. + /// \see SourceMap + /// \author Balazs Dezso + template + class TargetMap { + public: + + typedef typename Digraph::Node Value; + typedef typename Digraph::Arc Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _digraph The digraph that the map belongs to. + explicit TargetMap(const Digraph& _digraph) : digraph(_digraph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param e The arc + /// \return The target of the arc + Value operator[](const Key& e) const { + return digraph.target(e); + } + + private: + const Digraph& digraph; + }; + + /// \brief Returns a \ref TargetMap class. + /// + /// This function just returns a \ref TargetMap class. + /// \relates TargetMap + template + inline TargetMap targetMap(const Digraph& digraph) { + return TargetMap(digraph); + } + + /// \brief Returns the "forward" directed arc view of an edge. + /// + /// Returns the "forward" directed arc view of an edge. + /// \see BackwardMap + /// \author Balazs Dezso + template + class ForwardMap { + public: + + typedef typename Digraph::Arc Value; + typedef typename Digraph::Edge Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _digraph The digraph that the map belongs to. + explicit ForwardMap(const Digraph& _digraph) : digraph(_digraph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param key An edge + /// \return The "forward" directed arc view of edge + Value operator[](const Key& key) const { + return digraph.direct(key, true); + } + + private: + const Digraph& digraph; + }; + + /// \brief Returns a \ref ForwardMap class. + /// + /// This function just returns an \ref ForwardMap class. + /// \relates ForwardMap + template + inline ForwardMap forwardMap(const Digraph& digraph) { + return ForwardMap(digraph); + } + + /// \brief Returns the "backward" directed arc view of an edge. + /// + /// Returns the "backward" directed arc view of an edge. + /// \see ForwardMap + /// \author Balazs Dezso + template + class BackwardMap { + public: + + typedef typename Digraph::Arc Value; + typedef typename Digraph::Edge Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _digraph The digraph that the map belongs to. + explicit BackwardMap(const Digraph& _digraph) : digraph(_digraph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param key An edge + /// \return The "backward" directed arc view of edge + Value operator[](const Key& key) const { + return digraph.direct(key, false); + } + + private: + const Digraph& digraph; + }; + + /// \brief Returns a \ref BackwardMap class + + /// This function just returns a \ref BackwardMap class. + /// \relates BackwardMap + template + inline BackwardMap backwardMap(const Digraph& digraph) { + return BackwardMap(digraph); + } + + /// \brief Potential difference map + /// + /// If there is an potential map on the nodes then we + /// can get an arc map as we get the substraction of the + /// values of the target and source. + template + class PotentialDifferenceMap { + public: + typedef typename Digraph::Arc Key; + typedef typename NodeMap::Value Value; + + /// \brief Constructor + /// + /// Contructor of the map + explicit PotentialDifferenceMap(const Digraph& _digraph, + const NodeMap& _potential) + : digraph(_digraph), potential(_potential) {} + + /// \brief Const subscription operator + /// + /// Const subscription operator + Value operator[](const Key& arc) const { + return potential[digraph.target(arc)] - potential[digraph.source(arc)]; + } + + private: + const Digraph& digraph; + const NodeMap& potential; + }; + + /// \brief Returns a PotentialDifferenceMap. + /// + /// This function just returns a PotentialDifferenceMap. + /// \relates PotentialDifferenceMap + template + PotentialDifferenceMap + potentialDifferenceMap(const Digraph& digraph, const NodeMap& potential) { + return PotentialDifferenceMap(digraph, potential); + } + + /// \brief Map of the node in-degrees. + /// + /// This map returns the in-degree of a node. Once it is constructed, + /// the degrees are stored in a standard NodeMap, so each query is done + /// in constant time. On the other hand, the values are updated automatically + /// whenever the digraph changes. + /// + /// \warning Besides addNode() and addArc(), a digraph structure may provide + /// alternative ways to modify the digraph. The correct behavior of InDegMap + /// is not guarantied if these additional features are used. For example + /// the functions \ref ListDigraph::changeSource() "changeSource()", + /// \ref ListDigraph::changeTarget() "changeTarget()" and + /// \ref ListDigraph::reverseArc() "reverseArc()" + /// of \ref ListDigraph will \e not update the degree values correctly. + /// + /// \sa OutDegMap + + template + class InDegMap + : protected ItemSetTraits<_Digraph, typename _Digraph::Arc> + ::ItemNotifier::ObserverBase { + + public: + + typedef _Digraph Digraph; + typedef int Value; + typedef typename Digraph::Node Key; + + typedef typename ItemSetTraits<_Digraph, typename _Digraph::Arc> + ::ItemNotifier::ObserverBase Parent; + + private: + + class AutoNodeMap : public DefaultMap<_Digraph, Key, int> { + public: + + typedef DefaultMap<_Digraph, Key, int> Parent; + typedef typename Parent::Digraph Digraph; + + AutoNodeMap(const Digraph& digraph) : Parent(digraph, 0) {} + + virtual void add(const Key& key) { + Parent::add(key); + Parent::set(key, 0); + } + + virtual void add(const std::vector& keys) { + Parent::add(keys); + for (int i = 0; i < int(keys.size()); ++i) { + Parent::set(keys[i], 0); + } + } + + virtual void build() { + Parent::build(); + Key it; + typename Parent::Notifier* nf = Parent::notifier(); + for (nf->first(it); it != INVALID; nf->next(it)) { + Parent::set(it, 0); + } + } + }; + + public: + + /// \brief Constructor. + /// + /// Constructor for creating in-degree map. + explicit InDegMap(const Digraph& _digraph) : digraph(_digraph), deg(_digraph) { + Parent::attach(digraph.notifier(typename _Digraph::Arc())); + + for(typename _Digraph::NodeIt it(digraph); it != INVALID; ++it) { + deg[it] = countInArcs(digraph, it); + } + } + + /// Gives back the in-degree of a Node. + int operator[](const Key& key) const { + return deg[key]; + } + + protected: + + typedef typename Digraph::Arc Arc; + + virtual void add(const Arc& arc) { + ++deg[digraph.target(arc)]; + } + + virtual void add(const std::vector& arcs) { + for (int i = 0; i < int(arcs.size()); ++i) { + ++deg[digraph.target(arcs[i])]; + } + } + + virtual void erase(const Arc& arc) { + --deg[digraph.target(arc)]; + } + + virtual void erase(const std::vector& arcs) { + for (int i = 0; i < int(arcs.size()); ++i) { + --deg[digraph.target(arcs[i])]; + } + } + + virtual void build() { + for(typename _Digraph::NodeIt it(digraph); it != INVALID; ++it) { + deg[it] = countInArcs(digraph, it); + } + } + + virtual void clear() { + for(typename _Digraph::NodeIt it(digraph); it != INVALID; ++it) { + deg[it] = 0; + } + } + private: + + const _Digraph& digraph; + AutoNodeMap deg; + }; + + /// \brief Map of the node out-degrees. + /// + /// This map returns the out-degree of a node. Once it is constructed, + /// the degrees are stored in a standard NodeMap, so each query is done + /// in constant time. On the other hand, the values are updated automatically + /// whenever the digraph changes. + /// + /// \warning Besides addNode() and addArc(), a digraph structure may provide + /// alternative ways to modify the digraph. The correct behavior of OutDegMap + /// is not guarantied if these additional features are used. For example + /// the functions \ref ListDigraph::changeSource() "changeSource()", + /// \ref ListDigraph::changeTarget() "changeTarget()" and + /// \ref ListDigraph::reverseArc() "reverseArc()" + /// of \ref ListDigraph will \e not update the degree values correctly. + /// + /// \sa InDegMap + + template + class OutDegMap + : protected ItemSetTraits<_Digraph, typename _Digraph::Arc> + ::ItemNotifier::ObserverBase { + + public: + + typedef typename ItemSetTraits<_Digraph, typename _Digraph::Arc> + ::ItemNotifier::ObserverBase Parent; + + typedef _Digraph Digraph; + typedef int Value; + typedef typename Digraph::Node Key; + + private: + + class AutoNodeMap : public DefaultMap<_Digraph, Key, int> { + public: + + typedef DefaultMap<_Digraph, Key, int> Parent; + typedef typename Parent::Digraph Digraph; + + AutoNodeMap(const Digraph& digraph) : Parent(digraph, 0) {} + + virtual void add(const Key& key) { + Parent::add(key); + Parent::set(key, 0); + } + virtual void add(const std::vector& keys) { + Parent::add(keys); + for (int i = 0; i < int(keys.size()); ++i) { + Parent::set(keys[i], 0); + } + } + virtual void build() { + Parent::build(); + Key it; + typename Parent::Notifier* nf = Parent::notifier(); + for (nf->first(it); it != INVALID; nf->next(it)) { + Parent::set(it, 0); + } + } + }; + + public: + + /// \brief Constructor. + /// + /// Constructor for creating out-degree map. + explicit OutDegMap(const Digraph& _digraph) : digraph(_digraph), deg(_digraph) { + Parent::attach(digraph.notifier(typename _Digraph::Arc())); + + for(typename _Digraph::NodeIt it(digraph); it != INVALID; ++it) { + deg[it] = countOutArcs(digraph, it); + } + } + + /// Gives back the out-degree of a Node. + int operator[](const Key& key) const { + return deg[key]; + } + + protected: + + typedef typename Digraph::Arc Arc; + + virtual void add(const Arc& arc) { + ++deg[digraph.source(arc)]; + } + + virtual void add(const std::vector& arcs) { + for (int i = 0; i < int(arcs.size()); ++i) { + ++deg[digraph.source(arcs[i])]; + } + } + + virtual void erase(const Arc& arc) { + --deg[digraph.source(arc)]; + } + + virtual void erase(const std::vector& arcs) { + for (int i = 0; i < int(arcs.size()); ++i) { + --deg[digraph.source(arcs[i])]; + } + } + + virtual void build() { + for(typename _Digraph::NodeIt it(digraph); it != INVALID; ++it) { + deg[it] = countOutArcs(digraph, it); + } + } + + virtual void clear() { + for(typename _Digraph::NodeIt it(digraph); it != INVALID; ++it) { + deg[it] = 0; + } + } + private: + + const _Digraph& digraph; + AutoNodeMap deg; + }; + + + ///Dynamic arc look up between given endpoints. + + ///\ingroup gutils + ///Using this class, you can find an arc in a digraph from a given + ///source to a given target in amortized time O(log d), + ///where d is the out-degree of the source node. + /// + ///It is possible to find \e all parallel arcs between two nodes with + ///the \c findFirst() and \c findNext() members. + /// + ///See the \ref ArcLookUp and \ref AllArcLookUp classes if your + ///digraph do not changed so frequently. + /// + ///This class uses a self-adjusting binary search tree, Sleator's + ///and Tarjan's Splay tree for guarantee the logarithmic amortized + ///time bound for arc lookups. This class also guarantees the + ///optimal time bound in a constant factor for any distribution of + ///queries. + /// + ///\param G The type of the underlying digraph. + /// + ///\sa ArcLookUp + ///\sa AllArcLookUp + template + class DynArcLookUp + : protected ItemSetTraits::ItemNotifier::ObserverBase + { + public: + typedef typename ItemSetTraits + ::ItemNotifier::ObserverBase Parent; + + GRAPH_TYPEDEFS(typename G); + typedef G Digraph; + + protected: + + class AutoNodeMap : public DefaultMap { + public: + + typedef DefaultMap Parent; + + AutoNodeMap(const G& digraph) : Parent(digraph, INVALID) {} + + virtual void add(const Node& node) { + Parent::add(node); + Parent::set(node, INVALID); + } + + virtual void add(const std::vector& nodes) { + Parent::add(nodes); + for (int i = 0; i < int(nodes.size()); ++i) { + Parent::set(nodes[i], INVALID); + } + } + + virtual void build() { + Parent::build(); + Node it; + typename Parent::Notifier* nf = Parent::notifier(); + for (nf->first(it); it != INVALID; nf->next(it)) { + Parent::set(it, INVALID); + } + } + }; + + const Digraph &_g; + AutoNodeMap _head; + typename Digraph::template ArcMap _parent; + typename Digraph::template ArcMap _left; + typename Digraph::template ArcMap _right; + + class ArcLess { + const Digraph &g; + public: + ArcLess(const Digraph &_g) : g(_g) {} + bool operator()(Arc a,Arc b) const + { + return g.target(a)& arcs) { + for (int i = 0; i < int(arcs.size()); ++i) { + insert(arcs[i]); + } + } + + virtual void erase(const Arc& arc) { + remove(arc); + } + + virtual void erase(const std::vector& arcs) { + for (int i = 0; i < int(arcs.size()); ++i) { + remove(arcs[i]); + } + } + + virtual void build() { + refresh(); + } + + virtual void clear() { + for(NodeIt n(_g);n!=INVALID;++n) { + _head.set(n, INVALID); + } + } + + void insert(Arc arc) { + Node s = _g.source(arc); + Node t = _g.target(arc); + _left.set(arc, INVALID); + _right.set(arc, INVALID); + + Arc e = _head[s]; + if (e == INVALID) { + _head.set(s, arc); + _parent.set(arc, INVALID); + return; + } + while (true) { + if (t < _g.target(e)) { + if (_left[e] == INVALID) { + _left.set(e, arc); + _parent.set(arc, e); + splay(arc); + return; + } else { + e = _left[e]; + } + } else { + if (_right[e] == INVALID) { + _right.set(e, arc); + _parent.set(arc, e); + splay(arc); + return; + } else { + e = _right[e]; + } + } + } + } + + void remove(Arc arc) { + if (_left[arc] == INVALID) { + if (_right[arc] != INVALID) { + _parent.set(_right[arc], _parent[arc]); + } + if (_parent[arc] != INVALID) { + if (_left[_parent[arc]] == arc) { + _left.set(_parent[arc], _right[arc]); + } else { + _right.set(_parent[arc], _right[arc]); + } + } else { + _head.set(_g.source(arc), _right[arc]); + } + } else if (_right[arc] == INVALID) { + _parent.set(_left[arc], _parent[arc]); + if (_parent[arc] != INVALID) { + if (_left[_parent[arc]] == arc) { + _left.set(_parent[arc], _left[arc]); + } else { + _right.set(_parent[arc], _left[arc]); + } + } else { + _head.set(_g.source(arc), _left[arc]); + } + } else { + Arc e = _left[arc]; + if (_right[e] != INVALID) { + e = _right[e]; + while (_right[e] != INVALID) { + e = _right[e]; + } + Arc s = _parent[e]; + _right.set(_parent[e], _left[e]); + if (_left[e] != INVALID) { + _parent.set(_left[e], _parent[e]); + } + + _left.set(e, _left[arc]); + _parent.set(_left[arc], e); + _right.set(e, _right[arc]); + _parent.set(_right[arc], e); + + _parent.set(e, _parent[arc]); + if (_parent[arc] != INVALID) { + if (_left[_parent[arc]] == arc) { + _left.set(_parent[arc], e); + } else { + _right.set(_parent[arc], e); + } + } + splay(s); + } else { + _right.set(e, _right[arc]); + _parent.set(_right[arc], e); + + if (_parent[arc] != INVALID) { + if (_left[_parent[arc]] == arc) { + _left.set(_parent[arc], e); + } else { + _right.set(_parent[arc], e); + } + } else { + _head.set(_g.source(arc), e); + } + } + } + } + + Arc refreshRec(std::vector &v,int a,int b) + { + int m=(a+b)/2; + Arc me=v[m]; + if (a < m) { + Arc left = refreshRec(v,a,m-1); + _left.set(me, left); + _parent.set(left, me); + } else { + _left.set(me, INVALID); + } + if (m < b) { + Arc right = refreshRec(v,m+1,b); + _right.set(me, right); + _parent.set(right, me); + } else { + _right.set(me, INVALID); + } + return me; + } + + void refresh() { + for(NodeIt n(_g);n!=INVALID;++n) { + std::vector v; + for(OutArcIt e(_g,n);e!=INVALID;++e) v.push_back(e); + if(v.size()) { + std::sort(v.begin(),v.end(),ArcLess(_g)); + Arc head = refreshRec(v,0,v.size()-1); + _head.set(n, head); + _parent.set(head, INVALID); + } + else _head.set(n, INVALID); + } + } + + void zig(Arc v) { + Arc w = _parent[v]; + _parent.set(v, _parent[w]); + _parent.set(w, v); + _left.set(w, _right[v]); + _right.set(v, w); + if (_parent[v] != INVALID) { + if (_right[_parent[v]] == w) { + _right.set(_parent[v], v); + } else { + _left.set(_parent[v], v); + } + } + if (_left[w] != INVALID){ + _parent.set(_left[w], w); + } + } + + void zag(Arc v) { + Arc w = _parent[v]; + _parent.set(v, _parent[w]); + _parent.set(w, v); + _right.set(w, _left[v]); + _left.set(v, w); + if (_parent[v] != INVALID){ + if (_left[_parent[v]] == w) { + _left.set(_parent[v], v); + } else { + _right.set(_parent[v], v); + } + } + if (_right[w] != INVALID){ + _parent.set(_right[w], w); + } + } + + void splay(Arc v) { + while (_parent[v] != INVALID) { + if (v == _left[_parent[v]]) { + if (_parent[_parent[v]] == INVALID) { + zig(v); + } else { + if (_parent[v] == _left[_parent[_parent[v]]]) { + zig(_parent[v]); + zig(v); + } else { + zig(v); + zag(v); + } + } + } else { + if (_parent[_parent[v]] == INVALID) { + zag(v); + } else { + if (_parent[v] == _left[_parent[_parent[v]]]) { + zag(v); + zig(v); + } else { + zag(_parent[v]); + zag(v); + } + } + } + } + _head[_g.source(v)] = v; + } + + + public: + + ///Find an arc between two nodes. + + ///Find an arc between two nodes in time O(logd), where + /// d is the number of outgoing arcs of \c s. + ///\param s The source node + ///\param t The target node + ///\return An arc from \c s to \c t if there exists, + ///\ref INVALID otherwise. + Arc operator()(Node s, Node t) const + { + Arc e = _head[s]; + while (true) { + if (_g.target(e) == t) { + const_cast(*this).splay(e); + return e; + } else if (t < _g.target(e)) { + if (_left[e] == INVALID) { + const_cast(*this).splay(e); + return INVALID; + } else { + e = _left[e]; + } + } else { + if (_right[e] == INVALID) { + const_cast(*this).splay(e); + return INVALID; + } else { + e = _right[e]; + } + } + } + } + + ///Find the first arc between two nodes. + + ///Find the first arc between two nodes in time + /// O(logd), where d is the number of + /// outgoing arcs of \c s. + ///\param s The source node + ///\param t The target node + ///\return An arc from \c s to \c t if there exists, \ref INVALID + /// otherwise. + Arc findFirst(Node s, Node t) const + { + Arc e = _head[s]; + Arc r = INVALID; + while (true) { + if (_g.target(e) < t) { + if (_right[e] == INVALID) { + const_cast(*this).splay(e); + return r; + } else { + e = _right[e]; + } + } else { + if (_g.target(e) == t) { + r = e; + } + if (_left[e] == INVALID) { + const_cast(*this).splay(e); + return r; + } else { + e = _left[e]; + } + } + } + } + + ///Find the next arc between two nodes. + + ///Find the next arc between two nodes in time + /// O(logd), where d is the number of + /// outgoing arcs of \c s. + ///\param s The source node + ///\param t The target node + ///\return An arc from \c s to \c t if there exists, \ref INVALID + /// otherwise. + + ///\note If \c e is not the result of the previous \c findFirst() + ///operation then the amorized time bound can not be guaranteed. +#ifdef DOXYGEN + Arc findNext(Node s, Node t, Arc e) const +#else + Arc findNext(Node, Node t, Arc e) const +#endif + { + if (_right[e] != INVALID) { + e = _right[e]; + while (_left[e] != INVALID) { + e = _left[e]; + } + const_cast(*this).splay(e); + } else { + while (_parent[e] != INVALID && _right[_parent[e]] == e) { + e = _parent[e]; + } + if (_parent[e] == INVALID) { + return INVALID; + } else { + e = _parent[e]; + const_cast(*this).splay(e); + } + } + if (_g.target(e) == t) return e; + else return INVALID; + } + + }; + + ///Fast arc look up between given endpoints. + + ///\ingroup gutils + ///Using this class, you can find an arc in a digraph from a given + ///source to a given target in time O(log d), + ///where d is the out-degree of the source node. + /// + ///It is not possible to find \e all parallel arcs between two nodes. + ///Use \ref AllArcLookUp for this purpose. + /// + ///\warning This class is static, so you should refresh() (or at least + ///refresh(Node)) this data structure + ///whenever the digraph changes. This is a time consuming (superlinearly + ///proportional (O(mlogm)) to the number of arcs). + /// + ///\param G The type of the underlying digraph. + /// + ///\sa DynArcLookUp + ///\sa AllArcLookUp + template + class ArcLookUp + { + public: + GRAPH_TYPEDEFS(typename G); + typedef G Digraph; + + protected: + const Digraph &_g; + typename Digraph::template NodeMap _head; + typename Digraph::template ArcMap _left; + typename Digraph::template ArcMap _right; + + class ArcLess { + const Digraph &g; + public: + ArcLess(const Digraph &_g) : g(_g) {} + bool operator()(Arc a,Arc b) const + { + return g.target(a) &v,int a,int b) + { + int m=(a+b)/2; + Arc me=v[m]; + _left[me] = aO(dlogd), where d is + ///the number of the outgoing arcs of \c n. + void refresh(Node n) + { + std::vector v; + for(OutArcIt e(_g,n);e!=INVALID;++e) v.push_back(e); + if(v.size()) { + std::sort(v.begin(),v.end(),ArcLess(_g)); + _head[n]=refreshRec(v,0,v.size()-1); + } + else _head[n]=INVALID; + } + ///Refresh the full data structure. + + ///Build up the full search database. In fact, it simply calls + ///\ref refresh(Node) "refresh(n)" for each node \c n. + /// + ///It runs in time O(mlogD), where m is + ///the number of the arcs of \c n and D is the maximum + ///out-degree of the digraph. + + void refresh() + { + for(NodeIt n(_g);n!=INVALID;++n) refresh(n); + } + + ///Find an arc between two nodes. + + ///Find an arc between two nodes in time O(logd), where + /// d is the number of outgoing arcs of \c s. + ///\param s The source node + ///\param t The target node + ///\return An arc from \c s to \c t if there exists, + ///\ref INVALID otherwise. + /// + ///\warning If you change the digraph, refresh() must be called before using + ///this operator. If you change the outgoing arcs of + ///a single node \c n, then + ///\ref refresh(Node) "refresh(n)" is enough. + /// + Arc operator()(Node s, Node t) const + { + Arc e; + for(e=_head[s]; + e!=INVALID&&_g.target(e)!=t; + e = t < _g.target(e)?_left[e]:_right[e]) ; + return e; + } + + }; + + ///Fast look up of all arcs between given endpoints. + + ///\ingroup gutils + ///This class is the same as \ref ArcLookUp, with the addition + ///that it makes it possible to find all arcs between given endpoints. + /// + ///\warning This class is static, so you should refresh() (or at least + ///refresh(Node)) this data structure + ///whenever the digraph changes. This is a time consuming (superlinearly + ///proportional (O(mlogm)) to the number of arcs). + /// + ///\param G The type of the underlying digraph. + /// + ///\sa DynArcLookUp + ///\sa ArcLookUp + template + class AllArcLookUp : public ArcLookUp + { + using ArcLookUp::_g; + using ArcLookUp::_right; + using ArcLookUp::_left; + using ArcLookUp::_head; + + GRAPH_TYPEDEFS(typename G); + typedef G Digraph; + + typename Digraph::template ArcMap _next; + + Arc refreshNext(Arc head,Arc next=INVALID) + { + if(head==INVALID) return next; + else { + next=refreshNext(_right[head],next); +// _next[head]=next; + _next[head]=( next!=INVALID && _g.target(next)==_g.target(head)) + ? next : INVALID; + return refreshNext(_left[head],head); + } + } + + void refreshNext() + { + for(NodeIt n(_g);n!=INVALID;++n) refreshNext(_head[n]); + } + + public: + ///Constructor + + ///Constructor. + /// + ///It builds up the search database, which remains valid until the digraph + ///changes. + AllArcLookUp(const Digraph &g) : ArcLookUp(g), _next(g) {refreshNext();} + + ///Refresh the data structure at a node. + + ///Build up the search database of node \c n. + /// + ///It runs in time O(dlogd), where d is + ///the number of the outgoing arcs of \c n. + + void refresh(Node n) + { + ArcLookUp::refresh(n); + refreshNext(_head[n]); + } + + ///Refresh the full data structure. + + ///Build up the full search database. In fact, it simply calls + ///\ref refresh(Node) "refresh(n)" for each node \c n. + /// + ///It runs in time O(mlogD), where m is + ///the number of the arcs of \c n and D is the maximum + ///out-degree of the digraph. + + void refresh() + { + for(NodeIt n(_g);n!=INVALID;++n) refresh(_head[n]); + } + + ///Find an arc between two nodes. + + ///Find an arc between two nodes. + ///\param s The source node + ///\param t The target node + ///\param prev The previous arc between \c s and \c t. It it is INVALID or + ///not given, the operator finds the first appropriate arc. + ///\return An arc from \c s to \c t after \c prev or + ///\ref INVALID if there is no more. + /// + ///For example, you can count the number of arcs from \c u to \c v in the + ///following way. + ///\code + ///AllArcLookUp ae(g); + ///... + ///int n=0; + ///for(Arc e=ae(u,v);e!=INVALID;e=ae(u,v,e)) n++; + ///\endcode + /// + ///Finding the first arc take O(logd) time, where + /// d is the number of outgoing arcs of \c s. Then, the + ///consecutive arcs are found in constant time. + /// + ///\warning If you change the digraph, refresh() must be called before using + ///this operator. If you change the outgoing arcs of + ///a single node \c n, then + ///\ref refresh(Node) "refresh(n)" is enough. + /// +#ifdef DOXYGEN + Arc operator()(Node s, Node t, Arc prev=INVALID) const {} +#else + using ArcLookUp::operator() ; + Arc operator()(Node s, Node t, Arc prev) const + { + return prev==INVALID?(*this)(s,t):_next[prev]; + } +#endif + + }; + + /// @} + +} //END OF NAMESPACE LEMON + +#endif diff --git a/lemon/path.h b/lemon/path.h --- a/lemon/path.h +++ b/lemon/path.h @@ -29,6 +29,7 @@ #include #include +#include namespace lemon { diff --git a/test/Makefile.am b/test/Makefile.am --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,10 +3,13 @@ noinst_HEADERS += \ test/digraph_test.h \ + test/heap_test.h \ test/map_test.h \ test/test_tools.h check_PROGRAMS += \ + test/bfs_test \ + test/dfs_test \ test/digraph_test \ test/dim_test \ test/graph_test \ @@ -19,10 +22,13 @@ TESTS += $(check_PROGRAMS) XFAIL_TESTS += test/test_tools_fail$(EXEEXT) +test_bfs_test_SOURCES = test/bfs_test.cc +test_dfs_test_SOURCES = test/dfs_test.cc test_digraph_test_SOURCES = test/digraph_test.cc test_dim_test_SOURCES = test/dim_test.cc #test_error_test_SOURCES = test/error_test.cc test_graph_test_SOURCES = test/graph_test.cc +# test_heap_test_SOURCES = test/heap_test.cc test_maps_test_SOURCES = test/maps_test.cc test_path_test_SOURCES = test/path_test.cc test_random_test_SOURCES = test/random_test.cc diff --git a/test/bfs_test.cc b/test/bfs_test.cc new file mode 100644 --- /dev/null +++ b/test/bfs_test.cc @@ -0,0 +1,141 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include "test_tools.h" +//#include +#include +#include +#include +#include + +using namespace lemon; + +const int PET_SIZE =5; + + +void check_Bfs_Compile() +{ + typedef concepts::Digraph Digraph; + + typedef Digraph::Arc Arc; + typedef Digraph::Node Node; + typedef Digraph::ArcIt ArcIt; + typedef Digraph::NodeIt NodeIt; + + typedef Bfs BType; + + Digraph G; + Node n; + Arc e; + int l; + bool b; + BType::DistMap d(G); + BType::PredMap p(G); + // BType::PredNodeMap pn(G); + + BType bfs_test(G); + + bfs_test.run(n); + + l = bfs_test.dist(n); + e = bfs_test.predArc(n); + n = bfs_test.predNode(n); + d = bfs_test.distMap(); + p = bfs_test.predMap(); + // pn = bfs_test.predNodeMap(); + b = bfs_test.reached(n); + + Path pp = bfs_test.path(n); +} + +void check_Bfs_Function_Compile() +{ + typedef int VType; + typedef concepts::Digraph Digraph; + + typedef Digraph::Arc Arc; + typedef Digraph::Node Node; + typedef Digraph::ArcIt ArcIt; + typedef Digraph::NodeIt NodeIt; + typedef concepts::ReadMap LengthMap; + + Digraph g; + bfs(g,Node()).run(); + bfs(g).source(Node()).run(); + bfs(g) + .predMap(concepts::WriteMap()) + .distMap(concepts::WriteMap()) + .reachedMap(concepts::ReadWriteMap()) + .processedMap(concepts::WriteMap()) + .run(Node()); + +} + +int main() +{ + + // typedef SmartDigraph Digraph; + typedef ListDigraph Digraph; + + typedef Digraph::Arc Arc; + typedef Digraph::Node Node; + typedef Digraph::ArcIt ArcIt; + typedef Digraph::NodeIt NodeIt; + typedef Digraph::ArcMap LengthMap; + + Digraph G; + Node s, t; + PetStruct ps = addPetersen(G,PET_SIZE); + + s=ps.outer[2]; + t=ps.inner[0]; + + Bfs bfs_test(G); + bfs_test.run(s); + + check(bfs_test.dist(t)==3,"Bfs found a wrong path. " << bfs_test.dist(t)); + + Path p = bfs_test.path(t); + check(p.length()==3,"getPath() found a wrong path."); + check(checkPath(G, p),"path() found a wrong path."); + check(pathSource(G, p) == s,"path() found a wrong path."); + check(pathTarget(G, p) == t,"path() found a wrong path."); + + + for(ArcIt e(G); e==INVALID; ++e) { + Node u=G.source(e); + Node v=G.target(e); + check( !bfs_test.reached(u) || + (bfs_test.dist(v) > bfs_test.dist(u)+1), + "Wrong output."); + } + + for(NodeIt v(G); v==INVALID; ++v) { + check(bfs_test.reached(v),"Each node should be reached."); + if ( bfs_test.predArc(v)!=INVALID ) { + Arc e=bfs_test.predArc(v); + Node u=G.source(e); + check(u==bfs_test.predNode(v),"Wrong tree."); + check(bfs_test.dist(v) - bfs_test.dist(u) == 1, + "Wrong distance. Difference: " + << std::abs(bfs_test.dist(v) - bfs_test.dist(u) + - 1)); + } + } +} + diff --git a/test/dfs_test.cc b/test/dfs_test.cc new file mode 100644 --- /dev/null +++ b/test/dfs_test.cc @@ -0,0 +1,130 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include "test_tools.h" +// #include +#include +#include +#include +#include + +using namespace lemon; + +const int PET_SIZE =5; + + +void check_Dfs_SmartDigraph_Compile() +{ + typedef concepts::Digraph Digraph; + + typedef Digraph::Arc Arc; + typedef Digraph::Node Node; + typedef Digraph::ArcIt ArcIt; + typedef Digraph::NodeIt NodeIt; + + typedef Dfs DType; + + Digraph G; + Node n; + Arc e; + int l; + bool b; + DType::DistMap d(G); + DType::PredMap p(G); + // DType::PredNodeMap pn(G); + + DType dfs_test(G); + + dfs_test.run(n); + + l = dfs_test.dist(n); + e = dfs_test.predArc(n); + n = dfs_test.predNode(n); + d = dfs_test.distMap(); + p = dfs_test.predMap(); + // pn = dfs_test.predNodeMap(); + b = dfs_test.reached(n); + + Path pp = dfs_test.path(n); +} + + +void check_Dfs_Function_Compile() +{ + typedef int VType; + typedef concepts::Digraph Digraph; + + typedef Digraph::Arc Arc; + typedef Digraph::Node Node; + typedef Digraph::ArcIt ArcIt; + typedef Digraph::NodeIt NodeIt; + typedef concepts::ReadMap LengthMap; + + Digraph g; + dfs(g,Node()).run(); + dfs(g).source(Node()).run(); + dfs(g) + .predMap(concepts::WriteMap()) + .distMap(concepts::WriteMap()) + .reachedMap(concepts::ReadWriteMap()) + .processedMap(concepts::WriteMap()) + .run(Node()); + +} + +int main() +{ + + // typedef SmartDigraph Digraph; + typedef ListDigraph Digraph; + + typedef Digraph::Arc Arc; + typedef Digraph::Node Node; + typedef Digraph::ArcIt ArcIt; + typedef Digraph::NodeIt NodeIt; + typedef Digraph::ArcMap LengthMap; + + Digraph G; + Node s, t; + PetStruct ps = addPetersen(G,PET_SIZE); + + s=ps.outer[2]; + t=ps.inner[0]; + + Dfs dfs_test(G); + dfs_test.run(s); + + Path p = dfs_test.path(t); + check(p.length()==dfs_test.dist(t),"path() found a wrong path."); + check(checkPath(G, p),"path() found a wrong path."); + check(pathSource(G, p) == s,"path() found a wrong path."); + check(pathTarget(G, p) == t,"path() found a wrong path."); + + for(NodeIt v(G); v!=INVALID; ++v) { + check(dfs_test.reached(v),"Each node should be reached."); + if ( dfs_test.predArc(v)!=INVALID ) { + Arc e=dfs_test.predArc(v); + Node u=G.source(e); + check(u==dfs_test.predNode(v),"Wrong tree."); + check(dfs_test.dist(v) - dfs_test.dist(u) == 1, + "Wrong distance. (" << dfs_test.dist(u) << "->" + < +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include "test_tools.h" + +#include "heap_test.h" + +#include + +using namespace lemon; +using namespace lemon::concepts; + + +int main() { + + typedef int Item; + typedef int Prio; + typedef IntIntMap ItemIntMap; + + typedef ListDigraph Digraph; + + typedef Digraph::Arc Arc; + typedef Digraph::Node Node; + typedef Digraph::ArcIt ArcIt; + typedef Digraph::NodeIt NodeIt; + typedef Digraph::ArcMap LengthMap; + + Digraph digraph; + LengthMap length(digraph); + Node start; + + /// \todo create own test digraph + + std::string f_name; + if( getenv("srcdir") ) + f_name = std::string(getenv("srcdir")); + else f_name = "."; + f_name += "/test/dijkstra_test.lgf"; + + std::ifstream input(f_name.c_str()); + check(input, "Input file '" << f_name << "' not found."); + DigraphReader(input, digraph). + readArcMap("capacity", length). + readNode("source", start). + run(); + + { + std::cerr << "Checking Bin Heap" << std::endl; + + typedef BinHeap IntHeap; + checkConcept, IntHeap>(); + heapSortTest(100); + heapIncreaseTest(100); + + typedef FibHeap > NodeHeap; + checkConcept >, NodeHeap>(); + Timer timer; + dijkstraHeapTest(digraph, length, start); + std::cout << timer << std::endl; + } + { + std::cerr << "Checking Fib Heap" << std::endl; + + typedef FibHeap IntHeap; + checkConcept, IntHeap>(); + heapSortTest(100); + heapIncreaseTest(100); + + typedef FibHeap > NodeHeap; + checkConcept >, NodeHeap>(); + Timer timer; + dijkstraHeapTest(digraph, length, start); + std::cout << timer << std::endl; + } + { + std::cerr << "Checking Radix Heap" << std::endl; + + typedef RadixHeap IntHeap; + checkConcept, IntHeap>(); + heapSortTest(100); + heapIncreaseTest(100); + + typedef RadixHeap > NodeHeap; + checkConcept >, NodeHeap>(); + Timer timer; + dijkstraHeapTest(digraph, length, start); + std::cout << timer << std::endl; + } + + { + std::cerr << "Checking Bucket Heap" << std::endl; + + typedef BucketHeap IntHeap; + checkConcept, IntHeap>(); + heapSortTest(100); + heapIncreaseTest(100); + + typedef BucketHeap > NodeHeap; + checkConcept >, NodeHeap>(); + Timer timer; + dijkstraHeapTest(digraph, length, start); + std::cout << timer << std::endl; + } + + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff --git a/test/heap_test.h b/test/heap_test.h new file mode 100644 --- /dev/null +++ b/test/heap_test.h @@ -0,0 +1,123 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include + +#include + +class IntIntMap : public std::vector { +public: + typedef std::vector Parent; + + typedef int Key; + typedef int Value; + + IntIntMap() : Parent() {} + IntIntMap(int n) : Parent(n) {} + IntIntMap(int n, int v) : Parent(n, v) {} + + void set(int key, int value) { + Parent::operator[](key) = value; + } +}; + + +template +void heapSortTest(int n) { + typedef _Heap Heap; + IntIntMap map(n, -1); + + Heap heap(map); + + std::vector v(n); + + for (int i = 0; i < n; ++i) { + v[i] = rnd[1000]; + heap.push(i, v[i]); + } + std::sort(v.begin(), v.end()); + for (int i = 0; i < n; ++i) { + check(v[i] == heap.prio() ,"Wrong order in heap sort."); + heap.pop(); + } +} + +template +void heapIncreaseTest(int n) { + typedef _Heap Heap; + IntIntMap map(n, -1); + + Heap heap(map); + + std::vector v(n); + + for (int i = 0; i < n; ++i) { + v[i] = rnd[1000]; + heap.push(i, v[i]); + } + for (int i = 0; i < n; ++i) { + v[i] += rnd[1000]; + heap.increase(i, v[i]); + } + std::sort(v.begin(), v.end()); + for (int i = 0; i < n; ++i) { + check(v[i] == heap.prio() ,"Wrong order in heap increase test."); + heap.pop(); + } +} + + + +template +void dijkstraHeapTest(_Digraph& digraph, _LengthMap& length, + typename _Digraph::Node& start) { + + typedef _Heap Heap; + typedef _Digraph Digraph; + typedef _LengthMap LengthMap; + + typedef typename Digraph::Node Node; + typedef typename Digraph::Arc Arc; + typedef typename Digraph::NodeIt NodeIt; + typedef typename Digraph::ArcIt ArcIt; + + typename Dijkstra::template DefStandardHeap:: + Create dijkstra(digraph, length); + + dijkstra.run(start); + + for(ArcIt e(digraph); e!=INVALID; ++e) { + Node u=digraph.source(e); + Node v=digraph.target(e); + if (dijkstra.reached(u)) { + check( dijkstra.dist(v) - dijkstra.dist(u) <= length[e], + "Error in a shortest path tree arc!"); + } + } + + for(NodeIt v(digraph); v!=INVALID; ++v) { + if ( dijkstra.reached(v) && dijkstra.predArc(v) != INVALID ) { + Arc e=dijkstra.predArc(v); + Node u=digraph.source(e); + check( dijkstra.dist(v) - dijkstra .dist(u) == length[e], + "Error in a shortest path tree arc!"); + } + } + +} diff --git a/test/test_tools.h b/test/test_tools.h --- a/test/test_tools.h +++ b/test/test_tools.h @@ -20,6 +20,17 @@ #define LEMON_TEST_TEST_TOOLS_H #include +#include + +#include +#include + +#include +#include + +#include + +using namespace lemon; //! \ingroup misc //! \file @@ -36,7 +47,7 @@ ///For example ///\code check(0==1,"This is obviously false.");\endcode will ///print this (and then exits). -///\verbatim graph_test.cc:123: error: This is obviously false. \endverbatim +///\verbatim digraph_test.cc:123: error: This is obviously false. \endverbatim /// ///\todo It should be in \c error.h #define check(rc, msg) \ @@ -45,4 +56,126 @@ abort(); \ } else { } \ +///Structure returned by \ref addPetersen(). + +///Structure returned by \ref addPetersen(). +/// +template struct PetStruct +{ + ///Vector containing the outer nodes. + std::vector outer; + ///Vector containing the inner nodes. + std::vector inner; + ///Vector containing the arcs of the inner circle. + std::vector incir; + ///Vector containing the arcs of the outer circle. + std::vector outcir; + ///Vector containing the chord arcs. + std::vector chords; +}; + + + +///Adds a Petersen digraph to \c G. + +///Adds a Petersen digraph to \c G. +///\return The nodes and arcs of the generated digraph. + +template +PetStruct addPetersen(Digraph &G,int num = 5) +{ + PetStruct n; + + for(int i=0;i void bidirDigraph(Digraph &G) +{ + typedef typename Digraph::Arc Arc; + typedef typename Digraph::ArcIt ArcIt; + + std::vector ee; + + for(ArcIt e(G);e!=INVALID;++e) ee.push_back(e); + + for(typename std::vector::iterator p=ee.begin();p!=ee.end();p++) + G.addArc(G.target(*p),G.source(*p)); +} + + +/// \brief Checks the bidirectioned Petersen digraph. +/// +/// Checks the bidirectioned Petersen digraph. +/// +template void checkBidirPetersen(Digraph &G, int num = 5) +{ + typedef typename Digraph::Node Node; + + typedef typename Digraph::ArcIt ArcIt; + typedef typename Digraph::NodeIt NodeIt; + + checkDigraphNodeList(G, 2 * num); + checkDigraphArcList(G, 6 * num); + + for(NodeIt n(G);n!=INVALID;++n) { + checkDigraphInArcList(G, n, 3); + checkDigraphOutArcList(G, n, 3); + } +} + +///Structure returned by \ref addUPetersen(). + +///Structure returned by \ref addUPetersen(). +/// +template struct UPetStruct +{ + ///Vector containing the outer nodes. + std::vector outer; + ///Vector containing the inner nodes. + std::vector inner; + ///Vector containing the arcs of the inner circle. + std::vector incir; + ///Vector containing the arcs of the outer circle. + std::vector outcir; + ///Vector containing the chord arcs. + std::vector chords; +}; + +///Adds a Petersen digraph to the undirected \c G. + +///Adds a Petersen digraph to the undirected \c G. +///\return The nodes and arcs of the generated digraph. + +template +UPetStruct addUPetersen(Digraph &G,int num=5) +{ + UPetStruct n; + + for(int i=0;i