src/work/peter/path/path.h
changeset 838 51dcd224455c
child 921 818510fa3d99
equal deleted inserted replaced
-1:000000000000 0:992e8c93f9be
       
     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 <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