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