src/work/klao/path.h
author marci
Mon, 10 May 2004 16:31:48 +0000
changeset 597 a6e2b02f496a
parent 450 5caac2f7829b
child 607 327f7cf13843
permissions -rw-r--r--
bfs, dfs docs
klao@225
     1
// -*- c++ -*- //
klao@225
     2
klao@493
     3
///\ingroup datas
alpar@434
     4
///\file
klao@493
     5
///\brief Classes for representing paths in graphs.
klao@225
     6
klao@225
     7
#ifndef HUGO_PATH_H
klao@225
     8
#define HUGO_PATH_H
klao@225
     9
klao@225
    10
#include <deque>
klao@369
    11
#include <vector>
klao@226
    12
#include <algorithm>
klao@225
    13
klao@225
    14
#include <invalid.h>
klao@493
    15
#include <error.h>
klao@493
    16
#include <debug.h>
klao@225
    17
klao@225
    18
namespace hugo {
klao@225
    19
alpar@434
    20
  /// \addtogroup datas
alpar@434
    21
  /// @{
alpar@434
    22
alpar@434
    23
klao@493
    24
  //! \brief A structure for representing directed path in a graph.
klao@493
    25
  //!
klao@493
    26
  //! \param Graph The graph type in which the path is.
klao@493
    27
  //! \param DM DebugMode, defaults to DefaultDebugMode.
klao@493
    28
  //! 
klao@493
    29
  //! In a sense, the path can be treated as a graph, for is has \c NodeIt
klao@493
    30
  //! and \c EdgeIt with the same usage. These types converts to the \c Node
klao@493
    31
  //! and \c Edge of the original graph.
klao@493
    32
  //!
klao@493
    33
  //! \todo Thoroughfully check all the range and consistency tests.
klao@493
    34
  template<typename Graph, typename DM = DefaultDebugMode>
klao@369
    35
  class DirPath {
klao@369
    36
  public:
klao@369
    37
    typedef typename Graph::Edge GraphEdge;
klao@369
    38
    typedef typename Graph::Node GraphNode;
klao@369
    39
    class NodeIt;
klao@369
    40
    class EdgeIt;
klao@369
    41
klao@369
    42
  protected:
klao@369
    43
    const Graph *gr;
klao@369
    44
    typedef std::vector<GraphEdge> Container;
klao@369
    45
    Container edges;
klao@369
    46
klao@369
    47
  public:
klao@369
    48
alpar@434
    49
    /// \param _G The graph in which the path is.
alpar@434
    50
    ///
klao@369
    51
    DirPath(const Graph &_G) : gr(&_G) {}
klao@369
    52
klao@493
    53
    /// \brief Subpath constructor.
klao@493
    54
    ///
klao@369
    55
    /// Subpath defined by two nodes.
alpar@434
    56
    /// \warning It is an error if the two edges are not in order!
klao@493
    57
    /// \todo Implement!
klao@369
    58
    DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b);
klao@493
    59
    /// \brief Subpath constructor.
klao@493
    60
    ///
klao@369
    61
    /// Subpath defined by two edges. Contains edges in [a,b)
alpar@434
    62
    /// \warning It is an error if the two edges are not in order!
klao@493
    63
    /// \todo Implement!
klao@369
    64
    DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b);
klao@369
    65
klao@493
    66
    /// Length of the path.
klao@369
    67
    size_t length() const { return edges.size(); }
klao@493
    68
    /// Returns whether the path is empty.
klao@369
    69
    bool empty() const { return edges.empty(); }
klao@493
    70
klao@493
    71
    /// Resets the path to an empty path.
klao@493
    72
    void clear() { edges.clear(); }
klao@493
    73
klao@493
    74
    /// \brief Starting point of the path.
klao@493
    75
    ///
klao@493
    76
    /// Starting point of the path.
klao@493
    77
    /// Returns INVALID if the path is empty.
klao@369
    78
    GraphNode from() const {
klao@369
    79
      return empty() ? INVALID : gr->tail(edges[0]);
klao@369
    80
    }
klao@493
    81
    /// \brief End point of the path.
klao@493
    82
    ///
klao@493
    83
    /// End point of the path.
klao@493
    84
    /// Returns INVALID if the path is empty.
klao@369
    85
    GraphNode to() const {
klao@369
    86
      return empty() ? INVALID : gr->head(edges[length()-1]);
klao@369
    87
    }
klao@369
    88
klao@493
    89
    /// \brief Initializes node or edge iterator to point to the first
klao@493
    90
    /// node or edge.
klao@493
    91
    ///
klao@493
    92
    /// \sa nth
klao@369
    93
    template<typename It>
klao@369
    94
    It& first(It &i) const { return i=It(*this); }
klao@369
    95
klao@493
    96
    /// \brief Initializes node or edge iterator to point to the node or edge
klao@493
    97
    /// of a given index.
klao@369
    98
    template<typename It>
klao@493
    99
    It& nth(It &i, int n) const {
klao@493
   100
      // FIXME: this test should be different for NodeIt and EdgeIt:
klao@493
   101
      if( DM::range_check && (n<0 || n>int(length())) )
klao@493
   102
	fault("DirPath::nth: index out of range");
klao@493
   103
      return i=It(*this, n);
klao@493
   104
    }
klao@369
   105
klao@493
   106
    /// Checks validity of a node or edge iterator.
klao@369
   107
    template<typename It>
klao@369
   108
    bool valid(const It &i) const { return i.valid(); }
klao@369
   109
klao@493
   110
    /// Steps the given node or edge iterator.
klao@369
   111
    template<typename It>
klao@493
   112
    It& next(It &e) const {
klao@493
   113
      if( DM::range_check && !e.valid() )
klao@493
   114
	fault("DirPath::next() on invalid iterator");
klao@493
   115
      return ++e;
klao@493
   116
    }
klao@369
   117
klao@493
   118
    /// \brief Returns node iterator pointing to the head node of the
klao@493
   119
    /// given edge iterator.
klao@493
   120
    NodeIt head(const EdgeIt& e) const {
klao@493
   121
      return NodeIt(*this, e.idx+1);
klao@493
   122
    }
klao@493
   123
klao@493
   124
    /// \brief Returns node iterator pointing to the tail node of the
klao@493
   125
    /// given edge iterator.
klao@493
   126
    NodeIt tail(const EdgeIt& e) const {
klao@493
   127
      return NodeIt(*this, e.idx);
klao@493
   128
    }
klao@369
   129
klao@369
   130
klao@369
   131
    /*** Iterator classes ***/
klao@369
   132
    class EdgeIt {
klao@369
   133
      friend class DirPath;
klao@369
   134
klao@369
   135
      int idx;
klao@369
   136
      const DirPath *p;
klao@369
   137
    public:
klao@369
   138
      EdgeIt() {}
klao@369
   139
      EdgeIt(Invalid) : idx(-1), p(0) {}
klao@369
   140
      EdgeIt(const DirPath &_p, int _idx = 0) :
klao@369
   141
	idx(_idx), p(&_p) { validate(); }
klao@369
   142
klao@369
   143
      bool valid() const { return idx!=-1; }
klao@369
   144
klao@369
   145
      operator GraphEdge () const {
klao@369
   146
	return valid() ? p->edges[idx] : INVALID;
klao@369
   147
      }
klao@369
   148
      EdgeIt& operator++() { ++idx; validate(); return *this; }
klao@369
   149
klao@369
   150
      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
klao@369
   151
      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
klao@369
   152
      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
klao@369
   153
klao@369
   154
    private:
klao@369
   155
      // FIXME: comparison between signed and unsigned...
klao@369
   156
      // Jo ez igy? Vagy esetleg legyen a length() int?
klao@369
   157
      void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
klao@369
   158
    };
klao@369
   159
klao@369
   160
    class NodeIt {
klao@369
   161
      friend class DirPath;
klao@369
   162
klao@369
   163
      int idx;
klao@369
   164
      const DirPath *p;
klao@369
   165
    public:
klao@369
   166
      NodeIt() {}
klao@369
   167
      NodeIt(Invalid) : idx(-1), p(0) {}
klao@369
   168
      NodeIt(const DirPath &_p, int _idx = 0) :
klao@369
   169
	idx(_idx), p(&_p) { validate(); }
klao@369
   170
klao@369
   171
      bool valid() const { return idx!=-1; }
klao@369
   172
klao@369
   173
      operator const GraphEdge& () const {
klao@369
   174
	if(idx >= p->length())
klao@369
   175
	  return p->to();
klao@369
   176
	else if(idx >= 0)
klao@369
   177
	  return p->gr->tail(p->edges[idx]);
klao@369
   178
	else
klao@369
   179
	  return INVALID;
klao@369
   180
      }
klao@369
   181
      NodeIt& operator++() { ++idx; validate(); return *this; }
klao@369
   182
klao@369
   183
      bool operator==(const NodeIt& e) const { return idx==e.idx; }
klao@369
   184
      bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
klao@369
   185
      bool operator<(const NodeIt& e) const { return idx<e.idx; }
klao@369
   186
klao@369
   187
    private:
klao@369
   188
      void validate() { if( size_t(idx) > p->length() ) idx=-1; }
klao@369
   189
    };
klao@369
   190
klao@369
   191
    friend class Builder;    
alpar@434
   192
klao@493
   193
    /**
klao@493
   194
     * \brief Class to build paths
klao@493
   195
     * 
klao@493
   196
     * \ingroup datas
klao@493
   197
     * This class is used to fill a path with edges.
klao@493
   198
     *
klao@493
   199
     * You can push new edges to the front and to the back of the path in
klao@493
   200
     * arbitrary order the you can commit these changes to the graph.
klao@493
   201
     *
klao@493
   202
     * Fundamentally, for most "Paths" (classes fulfilling the
klao@493
   203
     * PathConcept) while the builder is active (after the first modifying
klao@493
   204
     * operation and until the commit()) the original Path is in a
klao@493
   205
     * "transitional" state (operations ot it have undefined result). But
klao@493
   206
     * in the case of DirPath the original path is unchanged until the
klao@493
   207
     * commit. However we don't recomend that you use this feature.
klao@493
   208
     */
klao@369
   209
    class Builder {
klao@369
   210
      DirPath &P;
klao@493
   211
      Container front, back;
klao@369
   212
klao@369
   213
    public:
klao@493
   214
      ///\param _P the path you want to fill in.
alpar@434
   215
      ///
klao@369
   216
      Builder(DirPath &_P) : P(_P) {}
klao@369
   217
klao@493
   218
      ///Sets the first node of the path.
alpar@434
   219
      
klao@493
   220
      ///Sets the first node of the path. If the path is empty, this
klao@493
   221
      ///function or setTo() have to be called before any call to \ref
klao@493
   222
      ///pushFront() or \ref pushBack()
klao@493
   223
      void setFrom(const GraphNode &) {}
klao@493
   224
      
klao@493
   225
      ///Sets the last node of the path.
klao@493
   226
      
klao@493
   227
      ///Sets the last node of the path. If the path is empty, this
klao@493
   228
      ///function or setFrom() have to be called before any call of \ref
klao@493
   229
      ///pushFront() or \ref pushBack()
klao@493
   230
      void setTo(const GraphNode &) {}
alpar@434
   231
      
alpar@434
   232
      ///Push a new edge to the front of the path
alpar@434
   233
alpar@434
   234
      ///Push a new edge to the front of the path.
klao@493
   235
      ///\sa setTo
klao@493
   236
      void pushFront(const GraphEdge& e) {
klao@493
   237
	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
klao@493
   238
	  fault("DirPath::Builder::pushFront: nonincident edge");
klao@369
   239
	}
klao@493
   240
	front.push_back(e);
klao@369
   241
      }
klao@493
   242
alpar@434
   243
      ///Push a new edge to the back of the path
alpar@434
   244
alpar@434
   245
      ///Push a new edge to the back of the path.
klao@493
   246
      ///\sa setFrom
klao@493
   247
      void pushBack(const GraphEdge& e) {
klao@493
   248
	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
klao@493
   249
	  fault("DirPath::Builder::pushBack: nonincident edge");
klao@369
   250
	}
klao@493
   251
	back.push_back(e);
klao@369
   252
      }
klao@369
   253
alpar@434
   254
      ///Commit the changes to the path.
klao@369
   255
      void commit() {
klao@493
   256
	if( !(front.empty() && back.empty()) ) {
klao@493
   257
	  Container tmp;
klao@493
   258
	  tmp.reserve(front.size()+back.size()+P.length());
klao@493
   259
	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
klao@493
   260
	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
klao@493
   261
	  tmp.insert(tmp.end(), back.begin(), back.end());
klao@493
   262
	  P.edges.swap(tmp);
klao@493
   263
	  front.clear();
klao@493
   264
	  back.clear();
klao@369
   265
	}
klao@369
   266
      }
klao@369
   267
klao@493
   268
//       ///Desctuctor
alpar@434
   269
klao@493
   270
//       ///The desctuctor.
klao@493
   271
//       ///It commit also commit the changes.
klao@493
   272
//       ///\todo Is this what we want?
klao@493
   273
//  Nope. Let's use commit() explicitly.
klao@493
   274
//       ~Builder() { commit(); }
klao@369
   275
klao@369
   276
      // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
klao@369
   277
      // Hogy kenyelmes egy ilyet hasznalni?
klao@369
   278
      void reserve(size_t r) {
klao@493
   279
	front.reserve(r);
klao@493
   280
	back.reserve(r);
klao@369
   281
      }
klao@369
   282
klao@369
   283
    private:
klao@493
   284
      bool empty() {
klao@493
   285
	return front.empty() && back.empty() && P.empty();
klao@493
   286
      }
klao@369
   287
klao@369
   288
      GraphNode from() const {
klao@493
   289
	if( ! front.empty() )
klao@493
   290
	  return P.gr->tail(front[front.size()-1]);
klao@369
   291
	else if( ! P.empty() )
klao@369
   292
	  return P.gr->tail(P.edges[0]);
klao@493
   293
	else if( ! back.empty() )
klao@493
   294
	  return P.gr->tail(back[0]);
klao@369
   295
	else
klao@369
   296
	  return INVALID;
klao@369
   297
      }
klao@369
   298
      GraphNode to() const {
klao@493
   299
	if( ! back.empty() )
klao@493
   300
	  return P.gr->head(back[back.size()-1]);
klao@493
   301
	else if( ! P.empty() )
klao@369
   302
	  return P.gr->head(P.edges[P.length()-1]);
klao@493
   303
	else if( ! front.empty() )
klao@493
   304
	  return P.gr->head(front[0]);
klao@369
   305
	else
klao@369
   306
	  return INVALID;
klao@369
   307
      }
klao@369
   308
klao@369
   309
    };
klao@369
   310
klao@369
   311
  };
klao@369
   312
klao@369
   313
klao@369
   314
klao@369
   315
klao@369
   316
klao@369
   317
klao@369
   318
klao@369
   319
klao@369
   320
klao@369
   321
klao@369
   322
  /**********************************************************************/
klao@369
   323
klao@369
   324
klao@225
   325
  /* Ennek az allocatorosdinak sokkal jobban utana kene nezni a hasznalata
klao@225
   326
     elott. Eleg bonyinak nez ki, ahogyan azokat az STL-ben hasznaljak. */
klao@225
   327
klao@225
   328
  template<typename Graph>
klao@369
   329
  class DynamicPath {
klao@225
   330
klao@225
   331
  public:
klao@225
   332
    typedef typename Graph::Edge GraphEdge;
klao@225
   333
    typedef typename Graph::Node GraphNode;
klao@225
   334
    class NodeIt;
klao@225
   335
    class EdgeIt;
klao@225
   336
klao@225
   337
  protected:
klao@225
   338
    Graph& G;
klao@225
   339
    // FIXME: ehelyett eleg lenne tarolni ket boolt: a ket szelso el
klao@225
   340
    // iranyitasat:
klao@225
   341
    GraphNode _first, _last;
klao@225
   342
    typedef std::deque<GraphEdge> Container;
klao@225
   343
    Container edges;
klao@225
   344
klao@225
   345
  public:
klao@225
   346
klao@369
   347
    DynamicPath(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {}
klao@225
   348
klao@226
   349
    /// Subpath defined by two nodes.
klao@226
   350
    /// Nodes may be in reversed order, then
klao@226
   351
    /// we contstruct the reversed path.
klao@369
   352
    DynamicPath(const DynamicPath &P, const NodeIt &a, const NodeIt &b);
klao@226
   353
    /// Subpath defined by two edges. Contains edges in [a,b)
klao@226
   354
    /// It is an error if the two edges are not in order!
klao@369
   355
    DynamicPath(const DynamicPath &P, const EdgeIt &a, const EdgeIt &b);
klao@225
   356
    
klao@225
   357
    size_t length() const { return edges.size(); }
klao@225
   358
    GraphNode from() const { return _first; }
klao@225
   359
    GraphNode to() const { return _last; }
klao@225
   360
klao@225
   361
    NodeIt& first(NodeIt &n) const { return nth(n, 0); }
klao@225
   362
    EdgeIt& first(EdgeIt &e) const { return nth(e, 0); }
klao@225
   363
    template<typename It>
klao@225
   364
    It first() const { 
klao@225
   365
      It e;
klao@225
   366
      first(e);
klao@225
   367
      return e; 
klao@225
   368
    }
klao@225
   369
klao@225
   370
    NodeIt& nth(NodeIt &, size_t) const;
klao@225
   371
    EdgeIt& nth(EdgeIt &, size_t) const;
klao@225
   372
    template<typename It>
klao@225
   373
    It nth(size_t n) const { 
klao@225
   374
      It e;
klao@225
   375
      nth(e, n);
klao@225
   376
      return e; 
klao@225
   377
    }
klao@225
   378
klao@225
   379
    bool valid(const NodeIt &n) const { return n.idx <= length(); }
klao@225
   380
    bool valid(const EdgeIt &e) const { return e.it < edges.end(); }
klao@225
   381
klao@225
   382
    bool isForward(const EdgeIt &e) const { return e.forw; }
klao@225
   383
klao@226
   384
    /// index of a node on the path. Returns length+2 for the invalid NodeIt
klao@226
   385
    int index(const NodeIt &n) const { return n.idx; }
klao@226
   386
    /// index of an edge on the path. Returns length+1 for the invalid EdgeIt
klao@226
   387
    int index(const EdgeIt &e) const { return e.it - edges.begin(); }
klao@226
   388
klao@225
   389
    EdgeIt& next(EdgeIt &e) const;
klao@225
   390
    NodeIt& next(NodeIt &n) const;
klao@225
   391
    template <typename It>
klao@225
   392
    It getNext(It it) const {
klao@225
   393
      It tmp(it); return next(tmp);
klao@225
   394
    }
klao@225
   395
klao@225
   396
    // A path is constructed using the following four functions.
klao@225
   397
    // They return false if the requested operation is inconsistent
klao@225
   398
    // with the path constructed so far.
klao@225
   399
    // If your path has only one edge you MUST set either "from" or "to"!
klao@225
   400
    // So you probably SHOULD call it in any case to be safe (and check the
klao@225
   401
    // returned value to check if your path is consistent with your idea).
klao@225
   402
    bool pushFront(const GraphEdge &e);
klao@225
   403
    bool pushBack(const GraphEdge &e);
klao@225
   404
    bool setFrom(const GraphNode &n);
klao@225
   405
    bool setTo(const GraphNode &n);
klao@225
   406
klao@225
   407
    // WARNING: these two functions return the head/tail of an edge with
klao@225
   408
    // respect to the direction of the path!
klao@225
   409
    // So G.head(P.graphEdge(e)) == P.graphNode(P.head(e)) holds only if 
klao@225
   410
    // P.forward(e) is true (or the edge is a loop)!
klao@225
   411
    NodeIt head(const EdgeIt& e) const;
klao@225
   412
    NodeIt tail(const EdgeIt& e) const;
klao@225
   413
klao@225
   414
    // FIXME: ezeknek valami jobb nev kellene!!!
klao@225
   415
    GraphEdge graphEdge(const EdgeIt& e) const;
klao@225
   416
    GraphNode graphNode(const NodeIt& n) const;
klao@225
   417
klao@225
   418
klao@225
   419
    /*** Iterator classes ***/
klao@225
   420
    class EdgeIt {
klao@369
   421
      friend class DynamicPath;
klao@225
   422
klao@225
   423
      typename Container::const_iterator it;
klao@225
   424
      bool forw;
klao@225
   425
    public:
klao@225
   426
      // FIXME: jarna neki ilyen is...
klao@225
   427
      // EdgeIt(Invalid);
klao@225
   428
klao@225
   429
      bool forward() const { return forw; }
klao@225
   430
klao@225
   431
      bool operator==(const EdgeIt& e) const { return it==e.it; }
klao@225
   432
      bool operator!=(const EdgeIt& e) const { return it!=e.it; }
klao@225
   433
      bool operator<(const EdgeIt& e) const { return it<e.it; }
klao@225
   434
    };
klao@225
   435
klao@225
   436
    class NodeIt {
klao@369
   437
      friend class DynamicPath;
klao@225
   438
klao@226
   439
      size_t idx;
klao@225
   440
      bool tail;  // Is this node the tail of the edge with same idx?
klao@225
   441
klao@225
   442
    public:
klao@225
   443
      // FIXME: jarna neki ilyen is...
klao@225
   444
      // NodeIt(Invalid);
klao@225
   445
klao@225
   446
      bool operator==(const NodeIt& n) const { return idx==n.idx; }
klao@225
   447
      bool operator!=(const NodeIt& n) const { return idx!=n.idx; }
klao@225
   448
      bool operator<(const NodeIt& n) const { return idx<n.idx; }
klao@225
   449
    };
klao@225
   450
klao@225
   451
  private:
klao@225
   452
    bool edgeIncident(const GraphEdge &e, const GraphNode &a,
klao@225
   453
		      GraphNode &b);
klao@225
   454
    bool connectTwoEdges(const GraphEdge &e, const GraphEdge &f);
klao@225
   455
  };
klao@225
   456
klao@225
   457
  template<typename Gr>
klao@369
   458
  typename DynamicPath<Gr>::EdgeIt&
klao@369
   459
  DynamicPath<Gr>::next(DynamicPath::EdgeIt &e) const {
klao@225
   460
    if( e.it == edges.end() ) 
klao@225
   461
      return e;
klao@225
   462
klao@225
   463
    GraphNode common_node = ( e.forw ? G.head(*e.it) : G.tail(*e.it) );
klao@225
   464
    ++e.it;
klao@225
   465
klao@225
   466
    // Invalid edgeit is always forward :)
klao@225
   467
    if( e.it == edges.end() ) {
klao@225
   468
      e.forw = true;
klao@225
   469
      return e;
klao@225
   470
    }
klao@225
   471
klao@225
   472
    e.forw = ( G.tail(*e.it) == common_node );
klao@225
   473
    return e;
klao@225
   474
  }
klao@225
   475
klao@225
   476
  template<typename Gr>
klao@369
   477
  typename DynamicPath<Gr>::NodeIt& DynamicPath<Gr>::next(NodeIt &n) const {
klao@225
   478
    if( n.idx >= length() ) {
klao@225
   479
      // FIXME: invalid
klao@225
   480
      n.idx = length()+1;
klao@225
   481
      return n;
klao@225
   482
    }
klao@225
   483
klao@225
   484
    
klao@225
   485
    GraphNode next_node = ( n.tail ? G.head(edges[n.idx]) :
klao@225
   486
			      G.tail(edges[n.idx]) );
klao@225
   487
    ++n.idx;
klao@225
   488
    if( n.idx < length() ) {
klao@225
   489
      n.tail = ( next_node == G.tail(edges[n.idx]) );
klao@225
   490
    }
klao@225
   491
    else {
klao@225
   492
      n.tail = true;
klao@225
   493
    }
klao@225
   494
klao@225
   495
    return n;
klao@225
   496
  }
klao@225
   497
klao@225
   498
  template<typename Gr>
klao@369
   499
  bool DynamicPath<Gr>::edgeIncident(const GraphEdge &e, const GraphNode &a,
klao@225
   500
			  GraphNode &b) {
klao@225
   501
    if( G.tail(e) == a ) {
klao@225
   502
      b=G.head(e);
klao@225
   503
      return true;
klao@225
   504
    }
klao@225
   505
    if( G.head(e) == a ) {
klao@225
   506
      b=G.tail(e);
klao@225
   507
      return true;
klao@225
   508
    }
klao@225
   509
    return false;
klao@225
   510
  }
klao@225
   511
klao@225
   512
  template<typename Gr>
klao@369
   513
  bool DynamicPath<Gr>::connectTwoEdges(const GraphEdge &e,
klao@225
   514
			     const GraphEdge &f) {
klao@225
   515
    if( edgeIncident(f, G.tail(e), _last) ) {
klao@225
   516
      _first = G.head(e);
klao@225
   517
      return true;
klao@225
   518
    }
klao@225
   519
    if( edgeIncident(f, G.head(e), _last) ) {
klao@225
   520
      _first = G.tail(e);
klao@225
   521
      return true;
klao@225
   522
    }
klao@225
   523
    return false;
klao@225
   524
  }
klao@225
   525
klao@225
   526
  template<typename Gr>
klao@369
   527
  bool DynamicPath<Gr>::pushFront(const GraphEdge &e) {
klao@225
   528
    if( G.valid(_first) ) {
klao@225
   529
	if( edgeIncident(e, _first, _first) ) {
klao@225
   530
	  edges.push_front(e);
klao@225
   531
	  return true;
klao@225
   532
	}
klao@225
   533
	else
klao@225
   534
	  return false;
klao@225
   535
    }
klao@225
   536
    else if( length() < 1 || connectTwoEdges(e, edges[0]) ) {
klao@225
   537
      edges.push_front(e);
klao@225
   538
      return true;
klao@225
   539
    }
klao@225
   540
    else
klao@225
   541
      return false;
klao@225
   542
  }
klao@225
   543
klao@225
   544
  template<typename Gr>
klao@369
   545
  bool DynamicPath<Gr>::pushBack(const GraphEdge &e) {
klao@225
   546
    if( G.valid(_last) ) {
klao@225
   547
	if( edgeIncident(e, _last, _last) ) {
klao@225
   548
	  edges.push_back(e);
klao@225
   549
	  return true;
klao@225
   550
	}
klao@225
   551
	else
klao@225
   552
	  return false;
klao@225
   553
    }
klao@225
   554
    else if( length() < 1 || connectTwoEdges(edges[0], e) ) {
klao@225
   555
      edges.push_back(e);
klao@225
   556
      return true;
klao@225
   557
    }
klao@225
   558
    else
klao@225
   559
      return false;
klao@225
   560
  }
klao@225
   561
klao@225
   562
klao@225
   563
  template<typename Gr>
klao@369
   564
  bool DynamicPath<Gr>::setFrom(const GraphNode &n) {
klao@225
   565
    if( G.valid(_first) ) {
klao@225
   566
      return _first == n;
klao@225
   567
    }
klao@225
   568
    else {
klao@225
   569
      if( length() > 0) {
klao@225
   570
	if( edgeIncident(edges[0], n, _last) ) {
klao@225
   571
	  _first = n;
klao@225
   572
	  return true;
klao@225
   573
	}
klao@225
   574
	else return false;
klao@225
   575
      }
klao@225
   576
      else {
klao@225
   577
	_first = _last = n;
klao@225
   578
	return true;
klao@225
   579
      }
klao@225
   580
    }
klao@225
   581
  }
klao@225
   582
klao@225
   583
  template<typename Gr>
klao@369
   584
  bool DynamicPath<Gr>::setTo(const GraphNode &n) {
klao@225
   585
    if( G.valid(_last) ) {
klao@225
   586
      return _last == n;
klao@225
   587
    }
klao@225
   588
    else {
klao@225
   589
      if( length() > 0) {
klao@225
   590
	if( edgeIncident(edges[0], n, _first) ) {
klao@225
   591
	  _last = n;
klao@225
   592
	  return true;
klao@225
   593
	}
klao@225
   594
	else return false;
klao@225
   595
      }
klao@225
   596
      else {
klao@225
   597
	_first = _last = n;
klao@225
   598
	return true;
klao@225
   599
      }
klao@225
   600
    }
klao@225
   601
  }
klao@225
   602
klao@225
   603
klao@225
   604
  template<typename Gr>
klao@369
   605
  typename DynamicPath<Gr>::NodeIt
klao@369
   606
  DynamicPath<Gr>::tail(const EdgeIt& e) const {
klao@225
   607
    NodeIt n;
klao@225
   608
klao@225
   609
    if( e.it == edges.end() ) {
klao@225
   610
      // FIXME: invalid-> invalid
klao@225
   611
      n.idx = length() + 1;
klao@225
   612
      n.tail = true;
klao@225
   613
      return n;
klao@225
   614
    }
klao@225
   615
klao@225
   616
    n.idx = e.it-edges.begin();
klao@225
   617
    n.tail = e.forw;
klao@226
   618
    return n;
klao@225
   619
  }
klao@225
   620
klao@225
   621
  template<typename Gr>
klao@369
   622
  typename DynamicPath<Gr>::NodeIt
klao@369
   623
  DynamicPath<Gr>::head(const EdgeIt& e) const {
klao@225
   624
    if( e.it == edges.end()-1 ) {
klao@225
   625
      return _last;
klao@225
   626
    }
klao@225
   627
klao@225
   628
    EdgeIt next_edge = e;
klao@225
   629
    next(next_edge);
klao@225
   630
    return tail(next_edge);
klao@225
   631
  }
klao@225
   632
      
klao@225
   633
  template<typename Gr>
klao@369
   634
  typename DynamicPath<Gr>::GraphEdge
klao@369
   635
  DynamicPath<Gr>::graphEdge(const EdgeIt& e) const {
klao@225
   636
    if( e.it != edges.end() ) {
klao@225
   637
      return *e.it;
klao@225
   638
    }
klao@225
   639
    else {
klao@225
   640
      return INVALID;
klao@225
   641
    }
klao@225
   642
  }
klao@225
   643
  
klao@225
   644
  template<typename Gr>
klao@369
   645
  typename DynamicPath<Gr>::GraphNode
klao@369
   646
  DynamicPath<Gr>::graphNode(const NodeIt& n) const {
klao@225
   647
    if( n.idx < length() ) {
klao@225
   648
      return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]);
klao@225
   649
    }
klao@225
   650
    else if( n.idx == length() ) {
klao@225
   651
      return _last;
klao@225
   652
    }
klao@225
   653
    else {
klao@225
   654
      return INVALID;
klao@225
   655
    }
klao@225
   656
  }
klao@225
   657
klao@225
   658
  template<typename Gr>
klao@369
   659
  typename DynamicPath<Gr>::EdgeIt&
klao@369
   660
  DynamicPath<Gr>::nth(EdgeIt &e, size_t k) const {
klao@450
   661
    if( k>=length() ) {
klao@225
   662
      // FIXME: invalid EdgeIt
klao@225
   663
      e.it = edges.end();
klao@225
   664
      e.forw = true;
klao@225
   665
      return e;
klao@225
   666
    }
klao@225
   667
klao@225
   668
    e.it = edges.begin()+k;
klao@225
   669
    if(k==0) {
klao@225
   670
      e.forw = ( G.tail(*e.it) == _first );
klao@225
   671
    }
klao@225
   672
    else {
klao@225
   673
      e.forw = ( G.tail(*e.it) == G.tail(edges[k-1]) ||
klao@225
   674
		 G.tail(*e.it) == G.head(edges[k-1]) );
klao@225
   675
    }
klao@225
   676
    return e;
klao@225
   677
  }
klao@225
   678
    
klao@225
   679
  template<typename Gr>
klao@369
   680
  typename DynamicPath<Gr>::NodeIt&
klao@369
   681
  DynamicPath<Gr>::nth(NodeIt &n, size_t k) const {
klao@450
   682
    if( k>length() ) {
klao@225
   683
      // FIXME: invalid NodeIt
klao@225
   684
      n.idx = length()+1;
klao@225
   685
      n.tail = true;
klao@225
   686
      return n;
klao@225
   687
    }
klao@225
   688
    if( k==length() ) {
klao@225
   689
      n.idx = length();
klao@225
   690
      n.tail = true;
klao@225
   691
      return n;
klao@225
   692
    }
klao@225
   693
    n = tail(nth<EdgeIt>(k));
klao@225
   694
    return n;
klao@225
   695
  }
klao@225
   696
klao@226
   697
  // Reszut konstruktorok:
klao@226
   698
klao@226
   699
klao@226
   700
  template<typename Gr>
klao@369
   701
  DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const EdgeIt &a,
klao@369
   702
			       const EdgeIt &b) :
klao@226
   703
    G(P.G), edges(a.it, b.it)    // WARNING: if b.it < a.it this will blow up! 
klao@226
   704
  {
klao@226
   705
    if( G.valid(P._first) && a.it < P.edges.end() ) {
klao@226
   706
      _first = ( a.forw ? G.tail(*a.it) : G.head(*a.it) );
klao@226
   707
      if( b.it < P.edges.end() ) {
klao@226
   708
	_last = ( b.forw ? G.tail(*b.it) : G.head(*b.it) );
klao@226
   709
      }
klao@226
   710
      else {
klao@226
   711
	_last = P._last;
klao@226
   712
      }
klao@226
   713
    }
klao@226
   714
  }
klao@226
   715
klao@226
   716
  template<typename Gr>
klao@369
   717
  DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const NodeIt &a,
klao@369
   718
			       const NodeIt &b) : G(P.G)
klao@226
   719
  {
klao@226
   720
    if( !P.valid(a) || !P.valid(b) )
klao@226
   721
      return;
klao@226
   722
klao@226
   723
    int ai = a.idx, bi = b.idx;
klao@226
   724
    if( bi<ai )
klao@450
   725
      std::swap(ai,bi);
klao@226
   726
    
klao@226
   727
    edges.resize(bi-ai);
klao@226
   728
    copy(P.edges.begin()+ai, P.edges.begin()+bi, edges.begin());
klao@226
   729
klao@226
   730
    _first = P.graphNode(a);
klao@226
   731
    _last = P.graphNode(b);
klao@226
   732
  }
klao@226
   733
alpar@434
   734
  ///@}
klao@225
   735
klao@225
   736
} // namespace hugo
klao@225
   737
klao@225
   738
#endif // HUGO_PATH_H