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