src/hugo/path.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
child 831 b6ae3446098a
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
     1 // -*- c++ -*- //
     2 
     3 /**
     4 @defgroup paths Path Structures
     5 @ingroup datas
     6 \brief Path structures implemented in Hugo.
     7 
     8 Hugolib provides flexible data structures
     9 to work with paths.
    10 
    11 All of them have the same interface, especially they can be built or extended
    12 using a standard Builder subclass. This make is easy to have e.g. the Dijkstra
    13 algorithm to store its result in any kind of path structure.
    14 
    15 \sa hugo::skeleton::Path
    16 
    17 */
    18 
    19 ///\ingroup paths
    20 ///\file
    21 ///\brief Classes for representing paths in graphs.
    22 
    23 #ifndef HUGO_PATH_H
    24 #define HUGO_PATH_H
    25 
    26 #include <deque>
    27 #include <vector>
    28 #include <algorithm>
    29 
    30 #include <hugo/invalid.h>
    31 #include <hugo/error.h>
    32 #include <hugo/debug.h>
    33 
    34 namespace hugo {
    35 
    36   /// \addtogroup paths
    37   /// @{
    38 
    39 
    40   //! \brief A structure for representing directed paths in a graph.
    41   //!
    42   //! A structure for representing directed path in a graph.
    43   //! \param Graph The graph type in which the path is.
    44   //! \param DM DebugMode, defaults to DefaultDebugMode.
    45   //! 
    46   //! In a sense, the path can be treated as a graph, for is has \c NodeIt
    47   //! and \c EdgeIt with the same usage. These types converts to the \c Node
    48   //! and \c Edge of the original graph.
    49   //!
    50   //! \todo Thoroughfully check all the range and consistency tests.
    51   template<typename Graph, typename DM = DefaultDebugMode>
    52   class DirPath {
    53   public:
    54     /// Edge type of the underlying graph.
    55     typedef typename Graph::Edge GraphEdge; 
    56     /// Node type of the underlying graph.
    57     typedef typename Graph::Node GraphNode;
    58     class NodeIt;
    59     class EdgeIt;
    60 
    61   protected:
    62     const Graph *gr;
    63     typedef std::vector<GraphEdge> Container;
    64     Container edges;
    65 
    66   public:
    67 
    68     /// \param _G The graph in which the path is.
    69     ///
    70     DirPath(const Graph &_G) : gr(&_G) {}
    71 
    72     /// \brief Subpath constructor.
    73     ///
    74     /// Subpath defined by two nodes.
    75     /// \warning It is an error if the two edges are not in order!
    76     DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) {
    77       if( DM::range_check && (!a.valid() || !b.valid) ) {
    78 	// FIXME: this check should be more elaborate...
    79 	fault("DirPath, subpath ctor: invalid bounding nodes");
    80       }
    81       gr = P.gr;
    82       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
    83     }
    84 
    85     /// \brief Subpath constructor.
    86     ///
    87     /// Subpath defined by two edges. Contains edges in [a,b)
    88     /// \warning It is an error if the two edges are not in order!
    89     DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) {
    90       if( DM::range_check && (!a.valid() || !b.valid) ) {
    91 	// FIXME: this check should be more elaborate...
    92 	fault("DirPath, subpath ctor: invalid bounding nodes");
    93       }
    94       gr = P.gr;
    95       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
    96     }
    97 
    98     /// Length of the path.
    99     size_t length() const { return edges.size(); }
   100     /// Returns whether the path is empty.
   101     bool empty() const { return edges.empty(); }
   102 
   103     /// Resets the path to an empty path.
   104     void clear() { edges.clear(); }
   105 
   106     /// \brief Starting point of the path.
   107     ///
   108     /// Starting point of the path.
   109     /// Returns INVALID if the path is empty.
   110     GraphNode from() const {
   111       return empty() ? INVALID : gr->tail(edges[0]);
   112     }
   113     /// \brief End point of the path.
   114     ///
   115     /// End point of the path.
   116     /// Returns INVALID if the path is empty.
   117     GraphNode to() const {
   118       return empty() ? INVALID : gr->head(edges[length()-1]);
   119     }
   120 
   121     /// \brief Initializes node or edge iterator to point to the first
   122     /// node or edge.
   123     ///
   124     /// \sa nth
   125     template<typename It>
   126     It& first(It &i) const { return i=It(*this); }
   127 
   128     /// \brief Initializes node iterator to point to the node of a given index.
   129     NodeIt& nth(NodeIt &i, int n) const {
   130       if( DM::range_check && (n<0 || n>int(length())) )
   131 	fault("DirPath::nth: index out of range");
   132       return i=NodeIt(*this, n);
   133     }
   134 
   135     /// \brief Initializes edge iterator to point to the edge of a given index.
   136     EdgeIt& nth(EdgeIt &i, int n) const {
   137       if( DM::range_check && (n<0 || n>=int(length())) )
   138 	fault("DirPath::nth: index out of range");
   139       return i=EdgeIt(*this, n);
   140     }
   141 
   142     /// Checks validity of a node or edge iterator.
   143     template<typename It>
   144     static
   145     bool valid(const It &i) { return i.valid(); }
   146 
   147     /// Steps the given node or edge iterator.
   148     template<typename It>
   149     static
   150     It& next(It &e) {
   151       if( DM::range_check && !e.valid() )
   152 	fault("DirPath::next() on invalid iterator");
   153       return ++e;
   154     }
   155 
   156     /// \brief Returns node iterator pointing to the head node of the
   157     /// given edge iterator.
   158     NodeIt head(const EdgeIt& e) const {
   159       if( DM::range_check && !e.valid() )
   160 	fault("DirPath::head() on invalid iterator");
   161       return NodeIt(*this, e.idx+1);
   162     }
   163 
   164     /// \brief Returns node iterator pointing to the tail node of the
   165     /// given edge iterator.
   166     NodeIt tail(const EdgeIt& e) const {
   167       if( DM::range_check && !e.valid() )
   168 	fault("DirPath::tail() on invalid iterator");
   169       return NodeIt(*this, e.idx);
   170     }
   171 
   172 
   173     /* Iterator classes */
   174 
   175     /**
   176      * \brief Iterator class to iterate on the edges of the paths
   177      * 
   178      * \ingroup paths
   179      * This class is used to iterate on the edges of the paths
   180      *
   181      * Of course it converts to Graph::Edge
   182      * 
   183      * \todo Its interface differs from the standard edge iterator.
   184      * Yes, it shouldn't.
   185      */
   186     class EdgeIt {
   187       friend class DirPath;
   188 
   189       int idx;
   190       const DirPath *p;
   191     public:
   192       /// Default constructor
   193       EdgeIt() {}
   194       /// Invalid constructor
   195       EdgeIt(Invalid) : idx(-1), p(0) {}
   196       /// Constructor with starting point
   197       EdgeIt(const DirPath &_p, int _idx = 0) :
   198 	idx(_idx), p(&_p) { validate(); }
   199 
   200       ///Validity check
   201       bool valid() const { return idx!=-1; }
   202 
   203       ///Conversion to Graph::Edge
   204       operator GraphEdge () const {
   205 	return valid() ? p->edges[idx] : INVALID;
   206       }
   207 
   208       /// Next edge
   209       EdgeIt& operator++() { ++idx; validate(); return *this; }
   210 
   211       /// Comparison operator
   212       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
   213       /// Comparison operator
   214       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
   215       /// Comparison operator
   216       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
   217 
   218     private:
   219       // FIXME: comparison between signed and unsigned...
   220       // Jo ez igy? Vagy esetleg legyen a length() int?
   221       void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
   222     };
   223 
   224     /**
   225      * \brief Iterator class to iterate on the nodes of the paths
   226      * 
   227      * \ingroup paths
   228      * This class is used to iterate on the nodes of the paths
   229      *
   230      * Of course it converts to Graph::Node
   231      * 
   232      * \todo Its interface differs from the standard node iterator.
   233      * Yes, it shouldn't.
   234      */
   235     class NodeIt {
   236       friend class DirPath;
   237 
   238       int idx;
   239       const DirPath *p;
   240     public:
   241       /// Default constructor
   242       NodeIt() {}
   243       /// Invalid constructor
   244       NodeIt(Invalid) : idx(-1), p(0) {}
   245       /// Constructor with starting point
   246       NodeIt(const DirPath &_p, int _idx = 0) :
   247 	idx(_idx), p(&_p) { validate(); }
   248 
   249       ///Validity check
   250       bool valid() const { return idx!=-1; }
   251 
   252       ///Conversion to Graph::Node
   253       operator const GraphNode& () const {
   254 	if(idx >= p->length())
   255 	  return p->to();
   256 	else if(idx >= 0)
   257 	  return p->gr->tail(p->edges[idx]);
   258 	else
   259 	  return INVALID;
   260       }
   261       /// Next node
   262       NodeIt& operator++() { ++idx; validate(); return *this; }
   263 
   264       /// Comparison operator
   265       bool operator==(const NodeIt& e) const { return idx==e.idx; }
   266       /// Comparison operator
   267       bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
   268       /// Comparison operator
   269       bool operator<(const NodeIt& e) const { return idx<e.idx; }
   270 
   271     private:
   272       void validate() { if( size_t(idx) > p->length() ) idx=-1; }
   273     };
   274 
   275     friend class Builder;    
   276 
   277     /**
   278      * \brief Class to build paths
   279      * 
   280      * \ingroup paths
   281      * This class is used to fill a path with edges.
   282      *
   283      * You can push new edges to the front and to the back of the path in
   284      * arbitrary order then you should commit these changes to the graph.
   285      *
   286      * Fundamentally, for most "Paths" (classes fulfilling the
   287      * PathConcept) while the builder is active (after the first modifying
   288      * operation and until the commit()) the original Path is in a
   289      * "transitional" state (operations on it have undefined result). But
   290      * in the case of DirPath the original path remains unchanged until the
   291      * commit. However we don't recomend that you use this feature.
   292      */
   293     class Builder {
   294       DirPath &P;
   295       Container front, back;
   296 
   297     public:
   298       ///\param _P the path you want to fill in.
   299       ///
   300       Builder(DirPath &_P) : P(_P) {}
   301 
   302       /// Sets the starting node of the path.
   303       
   304       /// Sets the starting node of the path. Edge added to the path
   305       /// afterwards have to be incident to this node.
   306       /// It should be called iff the path is empty and before any call to
   307       /// \ref pushFront() or \ref pushBack()
   308       void setStartNode(const GraphNode &) {}
   309 
   310       ///Push a new edge to the front of the path
   311 
   312       ///Push a new edge to the front of the path.
   313       ///\sa setStartNode
   314       void pushFront(const GraphEdge& e) {
   315 	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
   316 	  fault("DirPath::Builder::pushFront: nonincident edge");
   317 	}
   318 	front.push_back(e);
   319       }
   320 
   321       ///Push a new edge to the back of the path
   322 
   323       ///Push a new edge to the back of the path.
   324       ///\sa setStartNode
   325       void pushBack(const GraphEdge& e) {
   326 	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
   327 	  fault("DirPath::Builder::pushBack: nonincident edge");
   328 	}
   329 	back.push_back(e);
   330       }
   331 
   332       ///Commit the changes to the path.
   333       void commit() {
   334 	if( !(front.empty() && back.empty()) ) {
   335 	  Container tmp;
   336 	  tmp.reserve(front.size()+back.size()+P.length());
   337 	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
   338 	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
   339 	  tmp.insert(tmp.end(), back.begin(), back.end());
   340 	  P.edges.swap(tmp);
   341 	  front.clear();
   342 	  back.clear();
   343 	}
   344       }
   345 
   346       // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
   347       // Hogy kenyelmes egy ilyet hasznalni?
   348   
   349       ///Reserve storage for the builder in advance.
   350 
   351       ///If you know an reasonable upper bound of the number of the edges
   352       ///to add, using this function you can speed up the building.
   353       void reserve(size_t r) {
   354 	front.reserve(r);
   355 	back.reserve(r);
   356       }
   357 
   358     private:
   359       bool empty() {
   360 	return front.empty() && back.empty() && P.empty();
   361       }
   362 
   363       GraphNode from() const {
   364 	if( ! front.empty() )
   365 	  return P.gr->tail(front[front.size()-1]);
   366 	else if( ! P.empty() )
   367 	  return P.gr->tail(P.edges[0]);
   368 	else if( ! back.empty() )
   369 	  return P.gr->tail(back[0]);
   370 	else
   371 	  return INVALID;
   372       }
   373       GraphNode to() const {
   374 	if( ! back.empty() )
   375 	  return P.gr->head(back[back.size()-1]);
   376 	else if( ! P.empty() )
   377 	  return P.gr->head(P.edges[P.length()-1]);
   378 	else if( ! front.empty() )
   379 	  return P.gr->head(front[0]);
   380 	else
   381 	  return INVALID;
   382       }
   383 
   384     };
   385 
   386   };
   387 
   388 
   389 
   390 
   391 
   392 
   393 
   394 
   395 
   396 
   397   /**********************************************************************/
   398 
   399 
   400   //! \brief A structure for representing undirected path in a graph.
   401   //!
   402   //! A structure for representing undirected path in a graph. Ie. this is
   403   //! a path in a \e directed graph but the edges should not be directed
   404   //! forward.
   405   //!
   406   //! \param Graph The graph type in which the path is.
   407   //! \param DM DebugMode, defaults to DefaultDebugMode.
   408   //! 
   409   //! In a sense, the path can be treated as a graph, for is has \c NodeIt
   410   //! and \c EdgeIt with the same usage. These types converts to the \c Node
   411   //! and \c Edge of the original graph.
   412   //!
   413   //! \todo Thoroughfully check all the range and consistency tests.
   414   template<typename Graph, typename DM = DefaultDebugMode>
   415   class UndirPath {
   416   public:
   417     /// Edge type of the underlying graph.
   418     typedef typename Graph::Edge GraphEdge;
   419      /// Node type of the underlying graph.
   420    typedef typename Graph::Node GraphNode;
   421     class NodeIt;
   422     class EdgeIt;
   423 
   424   protected:
   425     const Graph *gr;
   426     typedef std::vector<GraphEdge> Container;
   427     Container edges;
   428 
   429   public:
   430 
   431     /// \param _G The graph in which the path is.
   432     ///
   433     UndirPath(const Graph &_G) : gr(&_G) {}
   434 
   435     /// \brief Subpath constructor.
   436     ///
   437     /// Subpath defined by two nodes.
   438     /// \warning It is an error if the two edges are not in order!
   439     UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) {
   440       if( DM::range_check && (!a.valid() || !b.valid) ) {
   441 	// FIXME: this check should be more elaborate...
   442 	fault("UndirPath, subpath ctor: invalid bounding nodes");
   443       }
   444       gr = P.gr;
   445       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
   446     }
   447 
   448     /// \brief Subpath constructor.
   449     ///
   450     /// Subpath defined by two edges. Contains edges in [a,b)
   451     /// \warning It is an error if the two edges are not in order!
   452     UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) {
   453       if( DM::range_check && (!a.valid() || !b.valid) ) {
   454 	// FIXME: this check should be more elaborate...
   455 	fault("UndirPath, subpath ctor: invalid bounding nodes");
   456       }
   457       gr = P.gr;
   458       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
   459     }
   460 
   461     /// Length of the path.
   462     size_t length() const { return edges.size(); }
   463     /// Returns whether the path is empty.
   464     bool empty() const { return edges.empty(); }
   465 
   466     /// Resets the path to an empty path.
   467     void clear() { edges.clear(); }
   468 
   469     /// \brief Starting point of the path.
   470     ///
   471     /// Starting point of the path.
   472     /// Returns INVALID if the path is empty.
   473     GraphNode from() const {
   474       return empty() ? INVALID : gr->tail(edges[0]);
   475     }
   476     /// \brief End point of the path.
   477     ///
   478     /// End point of the path.
   479     /// Returns INVALID if the path is empty.
   480     GraphNode to() const {
   481       return empty() ? INVALID : gr->head(edges[length()-1]);
   482     }
   483 
   484     /// \brief Initializes node or edge iterator to point to the first
   485     /// node or edge.
   486     ///
   487     /// \sa nth
   488     template<typename It>
   489     It& first(It &i) const { return i=It(*this); }
   490 
   491     /// \brief Initializes node iterator to point to the node of a given index.
   492     NodeIt& nth(NodeIt &i, int n) const {
   493       if( DM::range_check && (n<0 || n>int(length())) )
   494 	fault("UndirPath::nth: index out of range");
   495       return i=NodeIt(*this, n);
   496     }
   497 
   498     /// \brief Initializes edge iterator to point to the edge of a given index.
   499     EdgeIt& nth(EdgeIt &i, int n) const {
   500       if( DM::range_check && (n<0 || n>=int(length())) )
   501 	fault("UndirPath::nth: index out of range");
   502       return i=EdgeIt(*this, n);
   503     }
   504 
   505     /// Checks validity of a node or edge iterator.
   506     template<typename It>
   507     static
   508     bool valid(const It &i) { return i.valid(); }
   509 
   510     /// Steps the given node or edge iterator.
   511     template<typename It>
   512     static
   513     It& next(It &e) {
   514       if( DM::range_check && !e.valid() )
   515 	fault("UndirPath::next() on invalid iterator");
   516       return ++e;
   517     }
   518 
   519     /// \brief Returns node iterator pointing to the head node of the
   520     /// given edge iterator.
   521     NodeIt head(const EdgeIt& e) const {
   522       if( DM::range_check && !e.valid() )
   523 	fault("UndirPath::head() on invalid iterator");
   524       return NodeIt(*this, e.idx+1);
   525     }
   526 
   527     /// \brief Returns node iterator pointing to the tail node of the
   528     /// given edge iterator.
   529     NodeIt tail(const EdgeIt& e) const {
   530       if( DM::range_check && !e.valid() )
   531 	fault("UndirPath::tail() on invalid iterator");
   532       return NodeIt(*this, e.idx);
   533     }
   534 
   535 
   536 
   537     /**
   538      * \brief Iterator class to iterate on the edges of the paths
   539      * 
   540      * \ingroup paths
   541      * This class is used to iterate on the edges of the paths
   542      *
   543      * Of course it converts to Graph::Edge
   544      * 
   545      * \todo Its interface differs from the standard edge iterator.
   546      * Yes, it shouldn't.
   547      */
   548     class EdgeIt {
   549       friend class UndirPath;
   550 
   551       int idx;
   552       const UndirPath *p;
   553     public:
   554       /// Default constructor
   555       EdgeIt() {}
   556       /// Invalid constructor
   557       EdgeIt(Invalid) : idx(-1), p(0) {}
   558       /// Constructor with starting point
   559       EdgeIt(const UndirPath &_p, int _idx = 0) :
   560 	idx(_idx), p(&_p) { validate(); }
   561 
   562       ///Validity check
   563       bool valid() const { return idx!=-1; }
   564 
   565       ///Conversion to Graph::Edge
   566       operator GraphEdge () const {
   567 	return valid() ? p->edges[idx] : INVALID;
   568       }
   569       /// Next edge
   570      EdgeIt& operator++() { ++idx; validate(); return *this; }
   571 
   572       /// Comparison operator
   573       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
   574       /// Comparison operator
   575       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
   576       /// Comparison operator
   577       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
   578 
   579     private:
   580       // FIXME: comparison between signed and unsigned...
   581       // Jo ez igy? Vagy esetleg legyen a length() int?
   582       void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
   583     };
   584 
   585     /**
   586      * \brief Iterator class to iterate on the nodes of the paths
   587      * 
   588      * \ingroup paths
   589      * This class is used to iterate on the nodes of the paths
   590      *
   591      * Of course it converts to Graph::Node
   592      * 
   593      * \todo Its interface differs from the standard node iterator.
   594      * Yes, it shouldn't.
   595      */
   596     class NodeIt {
   597       friend class UndirPath;
   598 
   599       int idx;
   600       const UndirPath *p;
   601     public:
   602       /// Default constructor
   603       NodeIt() {}
   604       /// Invalid constructor
   605       NodeIt(Invalid) : idx(-1), p(0) {}
   606       /// Constructor with starting point
   607       NodeIt(const UndirPath &_p, int _idx = 0) :
   608 	idx(_idx), p(&_p) { validate(); }
   609 
   610       ///Validity check
   611       bool valid() const { return idx!=-1; }
   612 
   613       ///Conversion to Graph::Node
   614       operator const GraphNode& () const {
   615 	if(idx >= p->length())
   616 	  return p->to();
   617 	else if(idx >= 0)
   618 	  return p->gr->tail(p->edges[idx]);
   619 	else
   620 	  return INVALID;
   621       }
   622       /// Next node
   623       NodeIt& operator++() { ++idx; validate(); return *this; }
   624 
   625       /// Comparison operator
   626       bool operator==(const NodeIt& e) const { return idx==e.idx; }
   627       /// Comparison operator
   628       bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
   629        /// Comparison operator
   630      bool operator<(const NodeIt& e) const { return idx<e.idx; }
   631 
   632     private:
   633       void validate() { if( size_t(idx) > p->length() ) idx=-1; }
   634     };
   635 
   636     friend class Builder;    
   637 
   638     /**
   639      * \brief Class to build paths
   640      * 
   641      * \ingroup paths
   642      * This class is used to fill a path with edges.
   643      *
   644      * You can push new edges to the front and to the back of the path in
   645      * arbitrary order then you should commit these changes to the graph.
   646      *
   647      * Fundamentally, for most "Paths" (classes fulfilling the
   648      * PathConcept) while the builder is active (after the first modifying
   649      * operation and until the commit()) the original Path is in a
   650      * "transitional" state (operations ot it have undefined result). But
   651      * in the case of UndirPath the original path is unchanged until the
   652      * commit. However we don't recomend that you use this feature.
   653      */
   654     class Builder {
   655       UndirPath &P;
   656       Container front, back;
   657 
   658     public:
   659       ///\param _P the path you want to fill in.
   660       ///
   661       Builder(UndirPath &_P) : P(_P) {}
   662 
   663       /// Sets the starting node of the path.
   664       
   665       /// Sets the starting node of the path. Edge added to the path
   666       /// afterwards have to be incident to this node.
   667       /// It should be called iff the path is empty and before any call to
   668       /// \ref pushFront() or \ref pushBack()
   669       void setStartNode(const GraphNode &) {}
   670 
   671       ///Push a new edge to the front of the path
   672 
   673       ///Push a new edge to the front of the path.
   674       ///\sa setStartNode
   675       void pushFront(const GraphEdge& e) {
   676 	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
   677 	  fault("UndirPath::Builder::pushFront: nonincident edge");
   678 	}
   679 	front.push_back(e);
   680       }
   681 
   682       ///Push a new edge to the back of the path
   683 
   684       ///Push a new edge to the back of the path.
   685       ///\sa setStartNode
   686       void pushBack(const GraphEdge& e) {
   687 	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
   688 	  fault("UndirPath::Builder::pushBack: nonincident edge");
   689 	}
   690 	back.push_back(e);
   691       }
   692 
   693       ///Commit the changes to the path.
   694       void commit() {
   695 	if( !(front.empty() && back.empty()) ) {
   696 	  Container tmp;
   697 	  tmp.reserve(front.size()+back.size()+P.length());
   698 	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
   699 	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
   700 	  tmp.insert(tmp.end(), back.begin(), back.end());
   701 	  P.edges.swap(tmp);
   702 	  front.clear();
   703 	  back.clear();
   704 	}
   705       }
   706 
   707       // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
   708       // Hogy kenyelmes egy ilyet hasznalni?
   709 
   710       ///Reserve storage for the builder in advance.
   711 
   712       ///If you know an reasonable upper bound of the number of the edges
   713       ///to add, using this function you can speed up the building.
   714        void reserve(size_t r) {
   715 	front.reserve(r);
   716 	back.reserve(r);
   717       }
   718 
   719     private:
   720       bool empty() {
   721 	return front.empty() && back.empty() && P.empty();
   722       }
   723 
   724       GraphNode from() const {
   725 	if( ! front.empty() )
   726 	  return P.gr->tail(front[front.size()-1]);
   727 	else if( ! P.empty() )
   728 	  return P.gr->tail(P.edges[0]);
   729 	else if( ! back.empty() )
   730 	  return P.gr->tail(back[0]);
   731 	else
   732 	  return INVALID;
   733       }
   734       GraphNode to() const {
   735 	if( ! back.empty() )
   736 	  return P.gr->head(back[back.size()-1]);
   737 	else if( ! P.empty() )
   738 	  return P.gr->head(P.edges[P.length()-1]);
   739 	else if( ! front.empty() )
   740 	  return P.gr->head(front[0]);
   741 	else
   742 	  return INVALID;
   743       }
   744 
   745     };
   746 
   747   };
   748 
   749 
   750 
   751 
   752 
   753 
   754 
   755 
   756 
   757 
   758   /**********************************************************************/
   759 
   760 
   761   /* Ennek az allocatorosdinak sokkal jobban utana kene nezni a hasznalata
   762      elott. Eleg bonyinak nez ki, ahogyan azokat az STL-ben hasznaljak. */
   763 
   764   template<typename Graph>
   765   class DynamicPath {
   766 
   767   public:
   768     typedef typename Graph::Edge GraphEdge;
   769     typedef typename Graph::Node GraphNode;
   770     class NodeIt;
   771     class EdgeIt;
   772 
   773   protected:
   774     Graph& G;
   775     // FIXME: ehelyett eleg lenne tarolni ket boolt: a ket szelso el
   776     // iranyitasat:
   777     GraphNode _first, _last;
   778     typedef std::deque<GraphEdge> Container;
   779     Container edges;
   780 
   781   public:
   782 
   783     DynamicPath(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {}
   784 
   785     /// Subpath defined by two nodes.
   786     /// Nodes may be in reversed order, then
   787     /// we contstruct the reversed path.
   788     DynamicPath(const DynamicPath &P, const NodeIt &a, const NodeIt &b);
   789     /// Subpath defined by two edges. Contains edges in [a,b)
   790     /// It is an error if the two edges are not in order!
   791     DynamicPath(const DynamicPath &P, const EdgeIt &a, const EdgeIt &b);
   792     
   793     size_t length() const { return edges.size(); }
   794     GraphNode from() const { return _first; }
   795     GraphNode to() const { return _last; }
   796 
   797     NodeIt& first(NodeIt &n) const { return nth(n, 0); }
   798     EdgeIt& first(EdgeIt &e) const { return nth(e, 0); }
   799     template<typename It>
   800     It first() const { 
   801       It e;
   802       first(e);
   803       return e; 
   804     }
   805 
   806     NodeIt& nth(NodeIt &, size_t) const;
   807     EdgeIt& nth(EdgeIt &, size_t) const;
   808     template<typename It>
   809     It nth(size_t n) const { 
   810       It e;
   811       nth(e, n);
   812       return e; 
   813     }
   814 
   815     bool valid(const NodeIt &n) const { return n.idx <= length(); }
   816     bool valid(const EdgeIt &e) const { return e.it < edges.end(); }
   817 
   818     bool isForward(const EdgeIt &e) const { return e.forw; }
   819 
   820     /// index of a node on the path. Returns length+2 for the invalid NodeIt
   821     int index(const NodeIt &n) const { return n.idx; }
   822     /// index of an edge on the path. Returns length+1 for the invalid EdgeIt
   823     int index(const EdgeIt &e) const { return e.it - edges.begin(); }
   824 
   825     EdgeIt& next(EdgeIt &e) const;
   826     NodeIt& next(NodeIt &n) const;
   827     template <typename It>
   828     It getNext(It it) const {
   829       It tmp(it); return next(tmp);
   830     }
   831 
   832     // A path is constructed using the following four functions.
   833     // They return false if the requested operation is inconsistent
   834     // with the path constructed so far.
   835     // If your path has only one edge you MUST set either "from" or "to"!
   836     // So you probably SHOULD call it in any case to be safe (and check the
   837     // returned value to check if your path is consistent with your idea).
   838     bool pushFront(const GraphEdge &e);
   839     bool pushBack(const GraphEdge &e);
   840     bool setFrom(const GraphNode &n);
   841     bool setTo(const GraphNode &n);
   842 
   843     // WARNING: these two functions return the head/tail of an edge with
   844     // respect to the direction of the path!
   845     // So G.head(P.graphEdge(e)) == P.graphNode(P.head(e)) holds only if 
   846     // P.forward(e) is true (or the edge is a loop)!
   847     NodeIt head(const EdgeIt& e) const;
   848     NodeIt tail(const EdgeIt& e) const;
   849 
   850     // FIXME: ezeknek valami jobb nev kellene!!!
   851     GraphEdge graphEdge(const EdgeIt& e) const;
   852     GraphNode graphNode(const NodeIt& n) const;
   853 
   854 
   855     /*** Iterator classes ***/
   856     class EdgeIt {
   857       friend class DynamicPath;
   858 
   859       typename Container::const_iterator it;
   860       bool forw;
   861     public:
   862       // FIXME: jarna neki ilyen is...
   863       // EdgeIt(Invalid);
   864 
   865       bool forward() const { return forw; }
   866 
   867       bool operator==(const EdgeIt& e) const { return it==e.it; }
   868       bool operator!=(const EdgeIt& e) const { return it!=e.it; }
   869       bool operator<(const EdgeIt& e) const { return it<e.it; }
   870     };
   871 
   872     class NodeIt {
   873       friend class DynamicPath;
   874 
   875       size_t idx;
   876       bool tail;  // Is this node the tail of the edge with same idx?
   877 
   878     public:
   879       // FIXME: jarna neki ilyen is...
   880       // NodeIt(Invalid);
   881 
   882       bool operator==(const NodeIt& n) const { return idx==n.idx; }
   883       bool operator!=(const NodeIt& n) const { return idx!=n.idx; }
   884       bool operator<(const NodeIt& n) const { return idx<n.idx; }
   885     };
   886 
   887   private:
   888     bool edgeIncident(const GraphEdge &e, const GraphNode &a,
   889 		      GraphNode &b);
   890     bool connectTwoEdges(const GraphEdge &e, const GraphEdge &f);
   891   };
   892 
   893   template<typename Gr>
   894   typename DynamicPath<Gr>::EdgeIt&
   895   DynamicPath<Gr>::next(DynamicPath::EdgeIt &e) const {
   896     if( e.it == edges.end() ) 
   897       return e;
   898 
   899     GraphNode common_node = ( e.forw ? G.head(*e.it) : G.tail(*e.it) );
   900     ++e.it;
   901 
   902     // Invalid edgeit is always forward :)
   903     if( e.it == edges.end() ) {
   904       e.forw = true;
   905       return e;
   906     }
   907 
   908     e.forw = ( G.tail(*e.it) == common_node );
   909     return e;
   910   }
   911 
   912   template<typename Gr>
   913   typename DynamicPath<Gr>::NodeIt& DynamicPath<Gr>::next(NodeIt &n) const {
   914     if( n.idx >= length() ) {
   915       // FIXME: invalid
   916       n.idx = length()+1;
   917       return n;
   918     }
   919 
   920     
   921     GraphNode next_node = ( n.tail ? G.head(edges[n.idx]) :
   922 			      G.tail(edges[n.idx]) );
   923     ++n.idx;
   924     if( n.idx < length() ) {
   925       n.tail = ( next_node == G.tail(edges[n.idx]) );
   926     }
   927     else {
   928       n.tail = true;
   929     }
   930 
   931     return n;
   932   }
   933 
   934   template<typename Gr>
   935   bool DynamicPath<Gr>::edgeIncident(const GraphEdge &e, const GraphNode &a,
   936 			  GraphNode &b) {
   937     if( G.tail(e) == a ) {
   938       b=G.head(e);
   939       return true;
   940     }
   941     if( G.head(e) == a ) {
   942       b=G.tail(e);
   943       return true;
   944     }
   945     return false;
   946   }
   947 
   948   template<typename Gr>
   949   bool DynamicPath<Gr>::connectTwoEdges(const GraphEdge &e,
   950 			     const GraphEdge &f) {
   951     if( edgeIncident(f, G.tail(e), _last) ) {
   952       _first = G.head(e);
   953       return true;
   954     }
   955     if( edgeIncident(f, G.head(e), _last) ) {
   956       _first = G.tail(e);
   957       return true;
   958     }
   959     return false;
   960   }
   961 
   962   template<typename Gr>
   963   bool DynamicPath<Gr>::pushFront(const GraphEdge &e) {
   964     if( G.valid(_first) ) {
   965 	if( edgeIncident(e, _first, _first) ) {
   966 	  edges.push_front(e);
   967 	  return true;
   968 	}
   969 	else
   970 	  return false;
   971     }
   972     else if( length() < 1 || connectTwoEdges(e, edges[0]) ) {
   973       edges.push_front(e);
   974       return true;
   975     }
   976     else
   977       return false;
   978   }
   979 
   980   template<typename Gr>
   981   bool DynamicPath<Gr>::pushBack(const GraphEdge &e) {
   982     if( G.valid(_last) ) {
   983 	if( edgeIncident(e, _last, _last) ) {
   984 	  edges.push_back(e);
   985 	  return true;
   986 	}
   987 	else
   988 	  return false;
   989     }
   990     else if( length() < 1 || connectTwoEdges(edges[0], e) ) {
   991       edges.push_back(e);
   992       return true;
   993     }
   994     else
   995       return false;
   996   }
   997 
   998 
   999   template<typename Gr>
  1000   bool DynamicPath<Gr>::setFrom(const GraphNode &n) {
  1001     if( G.valid(_first) ) {
  1002       return _first == n;
  1003     }
  1004     else {
  1005       if( length() > 0) {
  1006 	if( edgeIncident(edges[0], n, _last) ) {
  1007 	  _first = n;
  1008 	  return true;
  1009 	}
  1010 	else return false;
  1011       }
  1012       else {
  1013 	_first = _last = n;
  1014 	return true;
  1015       }
  1016     }
  1017   }
  1018 
  1019   template<typename Gr>
  1020   bool DynamicPath<Gr>::setTo(const GraphNode &n) {
  1021     if( G.valid(_last) ) {
  1022       return _last == n;
  1023     }
  1024     else {
  1025       if( length() > 0) {
  1026 	if( edgeIncident(edges[0], n, _first) ) {
  1027 	  _last = n;
  1028 	  return true;
  1029 	}
  1030 	else return false;
  1031       }
  1032       else {
  1033 	_first = _last = n;
  1034 	return true;
  1035       }
  1036     }
  1037   }
  1038 
  1039 
  1040   template<typename Gr>
  1041   typename DynamicPath<Gr>::NodeIt
  1042   DynamicPath<Gr>::tail(const EdgeIt& e) const {
  1043     NodeIt n;
  1044 
  1045     if( e.it == edges.end() ) {
  1046       // FIXME: invalid-> invalid
  1047       n.idx = length() + 1;
  1048       n.tail = true;
  1049       return n;
  1050     }
  1051 
  1052     n.idx = e.it-edges.begin();
  1053     n.tail = e.forw;
  1054     return n;
  1055   }
  1056 
  1057   template<typename Gr>
  1058   typename DynamicPath<Gr>::NodeIt
  1059   DynamicPath<Gr>::head(const EdgeIt& e) const {
  1060     if( e.it == edges.end()-1 ) {
  1061       return _last;
  1062     }
  1063 
  1064     EdgeIt next_edge = e;
  1065     next(next_edge);
  1066     return tail(next_edge);
  1067   }
  1068       
  1069   template<typename Gr>
  1070   typename DynamicPath<Gr>::GraphEdge
  1071   DynamicPath<Gr>::graphEdge(const EdgeIt& e) const {
  1072     if( e.it != edges.end() ) {
  1073       return *e.it;
  1074     }
  1075     else {
  1076       return INVALID;
  1077     }
  1078   }
  1079   
  1080   template<typename Gr>
  1081   typename DynamicPath<Gr>::GraphNode
  1082   DynamicPath<Gr>::graphNode(const NodeIt& n) const {
  1083     if( n.idx < length() ) {
  1084       return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]);
  1085     }
  1086     else if( n.idx == length() ) {
  1087       return _last;
  1088     }
  1089     else {
  1090       return INVALID;
  1091     }
  1092   }
  1093 
  1094   template<typename Gr>
  1095   typename DynamicPath<Gr>::EdgeIt&
  1096   DynamicPath<Gr>::nth(EdgeIt &e, size_t k) const {
  1097     if( k>=length() ) {
  1098       // FIXME: invalid EdgeIt
  1099       e.it = edges.end();
  1100       e.forw = true;
  1101       return e;
  1102     }
  1103 
  1104     e.it = edges.begin()+k;
  1105     if(k==0) {
  1106       e.forw = ( G.tail(*e.it) == _first );
  1107     }
  1108     else {
  1109       e.forw = ( G.tail(*e.it) == G.tail(edges[k-1]) ||
  1110 		 G.tail(*e.it) == G.head(edges[k-1]) );
  1111     }
  1112     return e;
  1113   }
  1114     
  1115   template<typename Gr>
  1116   typename DynamicPath<Gr>::NodeIt&
  1117   DynamicPath<Gr>::nth(NodeIt &n, size_t k) const {
  1118     if( k>length() ) {
  1119       // FIXME: invalid NodeIt
  1120       n.idx = length()+1;
  1121       n.tail = true;
  1122       return n;
  1123     }
  1124     if( k==length() ) {
  1125       n.idx = length();
  1126       n.tail = true;
  1127       return n;
  1128     }
  1129     n = tail(nth<EdgeIt>(k));
  1130     return n;
  1131   }
  1132 
  1133   // Reszut konstruktorok:
  1134 
  1135 
  1136   template<typename Gr>
  1137   DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const EdgeIt &a,
  1138 			       const EdgeIt &b) :
  1139     G(P.G), edges(a.it, b.it)    // WARNING: if b.it < a.it this will blow up! 
  1140   {
  1141     if( G.valid(P._first) && a.it < P.edges.end() ) {
  1142       _first = ( a.forw ? G.tail(*a.it) : G.head(*a.it) );
  1143       if( b.it < P.edges.end() ) {
  1144 	_last = ( b.forw ? G.tail(*b.it) : G.head(*b.it) );
  1145       }
  1146       else {
  1147 	_last = P._last;
  1148       }
  1149     }
  1150   }
  1151 
  1152   template<typename Gr>
  1153   DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const NodeIt &a,
  1154 			       const NodeIt &b) : G(P.G)
  1155   {
  1156     if( !P.valid(a) || !P.valid(b) )
  1157       return;
  1158 
  1159     int ai = a.idx, bi = b.idx;
  1160     if( bi<ai )
  1161       std::swap(ai,bi);
  1162     
  1163     edges.resize(bi-ai);
  1164     copy(P.edges.begin()+ai, P.edges.begin()+bi, edges.begin());
  1165 
  1166     _first = P.graphNode(a);
  1167     _last = P.graphNode(b);
  1168   }
  1169 
  1170   ///@}
  1171 
  1172 } // namespace hugo
  1173 
  1174 #endif // HUGO_PATH_H