lemon/path.h
author deba
Wed, 09 Nov 2005 12:54:59 +0000
changeset 1782 cb405cda0205
parent 1435 8e85e6bbefdf
child 1875 98698b69a902
permissions -rw-r--r--
Bug fix.
     1 /* -*- C++ -*-
     2  * lemon/path.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 /**
    18 @defgroup paths Path Structures
    19 @ingroup datas
    20 \brief Path structures implemented in LEMON.
    21 
    22 LEMON provides flexible data structures
    23 to work with paths.
    24 
    25 All of them have the same interface, especially they can be built or extended
    26 using a standard Builder subclass. This make is easy to have e.g. the Dijkstra
    27 algorithm to store its result in any kind of path structure.
    28 
    29 \sa lemon::concept::Path
    30 
    31 */
    32 
    33 ///\ingroup paths
    34 ///\file
    35 ///\brief Classes for representing paths in graphs.
    36 ///
    37 ///\todo Iterators have obsolete style
    38 
    39 #ifndef LEMON_PATH_H
    40 #define LEMON_PATH_H
    41 
    42 #include <deque>
    43 #include <vector>
    44 #include <algorithm>
    45 
    46 #include <lemon/invalid.h>
    47 
    48 namespace lemon {
    49 
    50   /// \addtogroup paths
    51   /// @{
    52 
    53 
    54   //! \brief A structure for representing directed paths in a graph.
    55   //!
    56   //! A structure for representing directed path in a graph.
    57   //! \param Graph The graph type in which the path is.
    58   //! \param DM DebugMode, defaults to DefaultDebugMode.
    59   //!
    60   //! In a sense, the path can be treated as a graph, for is has \c NodeIt
    61   //! and \c EdgeIt with the same usage. These types converts to the \c Node
    62   //! and \c Edge of the original graph.
    63   //!
    64   //! \todo Thoroughfully check all the range and consistency tests.
    65   template<typename Graph>
    66   class DirPath {
    67   public:
    68     /// Edge type of the underlying graph.
    69     typedef typename Graph::Edge GraphEdge;
    70     /// Node type of the underlying graph.
    71     typedef typename Graph::Node GraphNode;
    72     class NodeIt;
    73     class EdgeIt;
    74 
    75   protected:
    76     const Graph *gr;
    77     typedef std::vector<GraphEdge> Container;
    78     Container edges;
    79 
    80   public:
    81 
    82     /// \param _G The graph in which the path is.
    83     ///
    84     DirPath(const Graph &_G) : gr(&_G) {}
    85 
    86     /// \brief Subpath constructor.
    87     ///
    88     /// Subpath defined by two nodes.
    89     /// \warning It is an error if the two edges are not in order!
    90     DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) {
    91       gr = P.gr;
    92       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
    93     }
    94 
    95     /// \brief Subpath constructor.
    96     ///
    97     /// Subpath defined by two edges. Contains edges in [a,b)
    98     /// \warning It is an error if the two edges are not in order!
    99     DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) {
   100       gr = P.gr;
   101       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
   102     }
   103 
   104     /// Length of the path.
   105     int length() const { return edges.size(); }
   106     /// Returns whether the path is empty.
   107     bool empty() const { return edges.empty(); }
   108 
   109     /// Resets the path to an empty path.
   110     void clear() { edges.clear(); }
   111 
   112     /// \brief Starting point of the path.
   113     ///
   114     /// Starting point of the path.
   115     /// Returns INVALID if the path is empty.
   116     GraphNode source() const {
   117       return empty() ? INVALID : gr->source(edges[0]);
   118     }
   119     /// \brief End point of the path.
   120     ///
   121     /// End point of the path.
   122     /// Returns INVALID if the path is empty.
   123     GraphNode target() const {
   124       return empty() ? INVALID : gr->target(edges[length()-1]);
   125     }
   126 
   127     /// \brief Initializes node or edge iterator to point to the first
   128     /// node or edge.
   129     ///
   130     /// \sa nth
   131     template<typename It>
   132     It& first(It &i) const { return i=It(*this); }
   133 
   134     /// \brief Initializes node iterator to point to the node of a given index.
   135     NodeIt& nth(NodeIt &i, int n) const {
   136       return i=NodeIt(*this, n);
   137     }
   138 
   139     /// \brief Initializes edge iterator to point to the edge of a given index.
   140     EdgeIt& nth(EdgeIt &i, int n) const {
   141       return i=EdgeIt(*this, n);
   142     }
   143 
   144     /// \brief Returns node iterator pointing to the target node of the
   145     /// given edge iterator.
   146     NodeIt target(const EdgeIt& e) const {
   147       return NodeIt(*this, e.idx+1);
   148     }
   149 
   150     /// \brief Returns node iterator pointing to the source node of the
   151     /// given edge iterator.
   152     NodeIt source(const EdgeIt& e) const {
   153       return NodeIt(*this, e.idx);
   154     }
   155 
   156 
   157     /* Iterator classes */
   158 
   159     /**
   160      * \brief Iterator class to iterate on the edges of the paths
   161      *
   162      * This class is used to iterate on the edges of the paths
   163      *
   164      * Of course it converts to Graph::Edge
   165      *
   166      */
   167     class EdgeIt {
   168       friend class DirPath;
   169 
   170       int idx;
   171       const DirPath *p;
   172     public:
   173       /// Default constructor
   174       EdgeIt() {}
   175       /// Invalid constructor
   176       EdgeIt(Invalid) : idx(-1), p(0) {}
   177       /// Constructor with starting point
   178       EdgeIt(const DirPath &_p, int _idx = 0) :
   179 	idx(_idx), p(&_p) { validate(); }
   180 
   181       ///Validity check
   182       bool valid() const { return idx!=-1; }
   183 
   184       ///Conversion to Graph::Edge
   185       operator GraphEdge () const {
   186 	return valid() ? p->edges[idx] : INVALID;
   187       }
   188 
   189       /// Next edge
   190       EdgeIt& operator++() { ++idx; validate(); return *this; }
   191 
   192       /// Comparison operator
   193       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
   194       /// Comparison operator
   195       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
   196       /// Comparison operator
   197       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
   198 
   199     private:
   200       void validate() { if(idx >= p->length() ) idx=-1; }
   201     };
   202 
   203     /**
   204      * \brief Iterator class to iterate on the nodes of the paths
   205      *
   206      * This class is used to iterate on the nodes of the paths
   207      *
   208      * Of course it converts to Graph::Node
   209      *
   210      */
   211     class NodeIt {
   212       friend class DirPath;
   213 
   214       int idx;
   215       const DirPath *p;
   216     public:
   217       /// Default constructor
   218       NodeIt() {}
   219       /// Invalid constructor
   220       NodeIt(Invalid) : idx(-1), p(0) {}
   221       /// Constructor with starting point
   222       NodeIt(const DirPath &_p, int _idx = 0) :
   223 	idx(_idx), p(&_p) { validate(); }
   224 
   225       ///Validity check
   226       bool valid() const { return idx!=-1; }
   227 
   228       ///Conversion to Graph::Node
   229       operator const GraphNode& () const {
   230 	if(idx >= p->length())
   231 	  return p->target();
   232 	else if(idx >= 0)
   233 	  return p->gr->source(p->edges[idx]);
   234 	else
   235 	  return INVALID;
   236       }
   237       /// Next node
   238       NodeIt& operator++() { ++idx; validate(); return *this; }
   239 
   240       /// Comparison operator
   241       bool operator==(const NodeIt& e) const { return idx==e.idx; }
   242       /// Comparison operator
   243       bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
   244       /// Comparison operator
   245       bool operator<(const NodeIt& e) const { return idx<e.idx; }
   246 
   247     private:
   248       void validate() { if(idx > p->length() ) idx=-1; }
   249     };
   250 
   251     friend class Builder;
   252 
   253     /**
   254      * \brief Class to build paths
   255      *
   256      * This class is used to fill a path with edges.
   257      *
   258      * You can push new edges to the front and to the back of the path in
   259      * arbitrary order then you should commit these changes to the graph.
   260      *
   261      * Fundamentally, for most "Paths" (classes fulfilling the
   262      * PathConcept) while the builder is active (after the first modifying
   263      * operation and until the commit()) the original Path is in a
   264      * "transitional" state (operations on it have undefined result). But
   265      * in the case of DirPath the original path remains unchanged until the
   266      * commit. However we don't recomend that you use this feature.
   267      */
   268     class Builder {
   269       DirPath &P;
   270       Container front, back;
   271 
   272     public:
   273       ///\param _p the path you want to fill in.
   274       ///
   275       Builder(DirPath &_p) : P(_p) {}
   276 
   277       /// Sets the starting node of the path.
   278 
   279       /// Sets the starting node of the path. Edge added to the path
   280       /// afterwards have to be incident to this node.
   281       /// It should be called if and only if
   282       /// the path is empty and before any call to
   283       /// \ref pushFront() or \ref pushBack()
   284       void setStartNode(const GraphNode &) {}
   285 
   286       ///Push a new edge to the front of the path
   287 
   288       ///Push a new edge to the front of the path.
   289       ///\sa setStartNode
   290       void pushFront(const GraphEdge& e) {
   291 	front.push_back(e);
   292       }
   293 
   294       ///Push a new edge to the back of the path
   295 
   296       ///Push a new edge to the back of the path.
   297       ///\sa setStartNode
   298       void pushBack(const GraphEdge& e) {
   299 	back.push_back(e);
   300       }
   301 
   302       ///Commit the changes to the path.
   303       void commit() {
   304 	if( !front.empty() || !back.empty() ) {
   305 	  Container tmp;
   306 	  tmp.reserve(front.size()+back.size()+P.length());
   307 	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
   308 	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
   309 	  tmp.insert(tmp.end(), back.begin(), back.end());
   310 	  P.edges.swap(tmp);
   311 	  front.clear();
   312 	  back.clear();
   313 	}
   314       }
   315 
   316       ///Reserve storage for the builder in advance.
   317 
   318       ///If you know a reasonable upper bound of the number of the edges
   319       ///to add to the front, using this function you can speed up the building.
   320 
   321       void reserveFront(size_t r) {front.reserve(r);}
   322 
   323       ///Reserve storage for the builder in advance.
   324 
   325       ///If you know a reasonable upper bound of the number of the edges
   326       ///to add to the back, using this function you can speed up the building.
   327 
   328       void reserveBack(size_t r) {back.reserve(r);}
   329 
   330     private:
   331       bool empty() {
   332 	return front.empty() && back.empty() && P.empty();
   333       }
   334 
   335       GraphNode source() const {
   336 	if( ! front.empty() )
   337 	  return P.gr->source(front[front.size()-1]);
   338 	else if( ! P.empty() )
   339 	  return P.gr->source(P.edges[0]);
   340 	else if( ! back.empty() )
   341 	  return P.gr->source(back[0]);
   342 	else
   343 	  return INVALID;
   344       }
   345       GraphNode target() const {
   346 	if( ! back.empty() )
   347 	  return P.gr->target(back[back.size()-1]);
   348 	else if( ! P.empty() )
   349 	  return P.gr->target(P.edges[P.length()-1]);
   350 	else if( ! front.empty() )
   351 	  return P.gr->target(front[0]);
   352 	else
   353 	  return INVALID;
   354       }
   355 
   356     };
   357 
   358   };
   359 
   360 
   361 
   362 
   363 
   364 
   365 
   366 
   367 
   368 
   369   /**********************************************************************/
   370 
   371 
   372   //! \brief A structure for representing undirected path in a graph.
   373   //!
   374   //! A structure for representing undirected path in a graph. Ie. this is
   375   //! a path in a \e directed graph but the edges should not be directed
   376   //! forward.
   377   //!
   378   //! \param Graph The graph type in which the path is.
   379   //! \param DM DebugMode, defaults to DefaultDebugMode.
   380   //!
   381   //! In a sense, the path can be treated as a graph, for is has \c NodeIt
   382   //! and \c EdgeIt with the same usage. These types converts to the \c Node
   383   //! and \c Edge of the original graph.
   384   //!
   385   //! \todo Thoroughfully check all the range and consistency tests.
   386   /// \todo May we need just path for undirected graph instead of this.
   387   template<typename Graph>
   388   class UndirPath {
   389   public:
   390     /// Edge type of the underlying graph.
   391     typedef typename Graph::Edge GraphEdge;
   392      /// Node type of the underlying graph.
   393    typedef typename Graph::Node GraphNode;
   394     class NodeIt;
   395     class EdgeIt;
   396 
   397   protected:
   398     const Graph *gr;
   399     typedef std::vector<GraphEdge> Container;
   400     Container edges;
   401 
   402   public:
   403 
   404     /// \param _G The graph in which the path is.
   405     ///
   406     UndirPath(const Graph &_G) : gr(&_G) {}
   407 
   408     /// \brief Subpath constructor.
   409     ///
   410     /// Subpath defined by two nodes.
   411     /// \warning It is an error if the two edges are not in order!
   412     UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) {
   413       gr = P.gr;
   414       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
   415     }
   416 
   417     /// \brief Subpath constructor.
   418     ///
   419     /// Subpath defined by two edges. Contains edges in [a,b)
   420     /// \warning It is an error if the two edges are not in order!
   421     UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) {
   422       gr = P.gr;
   423       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
   424     }
   425 
   426     /// Length of the path.
   427     size_t length() const { return edges.size(); }
   428     /// Returns whether the path is empty.
   429     bool empty() const { return edges.empty(); }
   430 
   431     /// Resets the path to an empty path.
   432     void clear() { edges.clear(); }
   433 
   434     /// \brief Starting point of the path.
   435     ///
   436     /// Starting point of the path.
   437     /// Returns INVALID if the path is empty.
   438     GraphNode source() const {
   439       return empty() ? INVALID : gr->source(edges[0]);
   440     }
   441     /// \brief End point of the path.
   442     ///
   443     /// End point of the path.
   444     /// Returns INVALID if the path is empty.
   445     GraphNode target() const {
   446       return empty() ? INVALID : gr->target(edges[length()-1]);
   447     }
   448 
   449     /// \brief Initializes node or edge iterator to point to the first
   450     /// node or edge.
   451     ///
   452     /// \sa nth
   453     template<typename It>
   454     It& first(It &i) const { return i=It(*this); }
   455 
   456     /// \brief Initializes node iterator to point to the node of a given index.
   457     NodeIt& nth(NodeIt &i, int n) const {
   458       return i=NodeIt(*this, n);
   459     }
   460 
   461     /// \brief Initializes edge iterator to point to the edge of a given index.
   462     EdgeIt& nth(EdgeIt &i, int n) const {
   463       return i=EdgeIt(*this, n);
   464     }
   465 
   466     /// Checks validity of a node or edge iterator.
   467     template<typename It>
   468     static
   469     bool valid(const It &i) { return i.valid(); }
   470 
   471     /// Steps the given node or edge iterator.
   472     template<typename It>
   473     static
   474     It& next(It &e) {
   475       return ++e;
   476     }
   477 
   478     /// \brief Returns node iterator pointing to the target node of the
   479     /// given edge iterator.
   480     NodeIt target(const EdgeIt& e) const {
   481       return NodeIt(*this, e.idx+1);
   482     }
   483 
   484     /// \brief Returns node iterator pointing to the source node of the
   485     /// given edge iterator.
   486     NodeIt source(const EdgeIt& e) const {
   487       return NodeIt(*this, e.idx);
   488     }
   489 
   490 
   491 
   492     /**
   493      * \brief Iterator class to iterate on the edges of the paths
   494      *
   495      * This class is used to iterate on the edges of the paths
   496      *
   497      * Of course it converts to Graph::Edge
   498      *
   499      * \todo Its interface differs from the standard edge iterator.
   500      * Yes, it shouldn't.
   501      */
   502     class EdgeIt {
   503       friend class UndirPath;
   504 
   505       int idx;
   506       const UndirPath *p;
   507     public:
   508       /// Default constructor
   509       EdgeIt() {}
   510       /// Invalid constructor
   511       EdgeIt(Invalid) : idx(-1), p(0) {}
   512       /// Constructor with starting point
   513       EdgeIt(const UndirPath &_p, int _idx = 0) :
   514 	idx(_idx), p(&_p) { validate(); }
   515 
   516       ///Validity check
   517       bool valid() const { return idx!=-1; }
   518 
   519       ///Conversion to Graph::Edge
   520       operator GraphEdge () const {
   521 	return valid() ? p->edges[idx] : INVALID;
   522       }
   523       /// Next edge
   524      EdgeIt& operator++() { ++idx; validate(); return *this; }
   525 
   526       /// Comparison operator
   527       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
   528       /// Comparison operator
   529       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
   530       /// Comparison operator
   531       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
   532 
   533     private:
   534       // FIXME: comparison between signed and unsigned...
   535       // Jo ez igy? Vagy esetleg legyen a length() int?
   536       void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
   537     };
   538 
   539     /**
   540      * \brief Iterator class to iterate on the nodes of the paths
   541      *
   542      * This class is used to iterate on the nodes of the paths
   543      *
   544      * Of course it converts to Graph::Node
   545      *
   546      * \todo Its interface differs from the standard node iterator.
   547      * Yes, it shouldn't.
   548      */
   549     class NodeIt {
   550       friend class UndirPath;
   551 
   552       int idx;
   553       const UndirPath *p;
   554     public:
   555       /// Default constructor
   556       NodeIt() {}
   557       /// Invalid constructor
   558       NodeIt(Invalid) : idx(-1), p(0) {}
   559       /// Constructor with starting point
   560       NodeIt(const UndirPath &_p, int _idx = 0) :
   561 	idx(_idx), p(&_p) { validate(); }
   562 
   563       ///Validity check
   564       bool valid() const { return idx!=-1; }
   565 
   566       ///Conversion to Graph::Node
   567       operator const GraphNode& () const {
   568 	if(idx >= p->length())
   569 	  return p->target();
   570 	else if(idx >= 0)
   571 	  return p->gr->source(p->edges[idx]);
   572 	else
   573 	  return INVALID;
   574       }
   575       /// Next node
   576       NodeIt& operator++() { ++idx; validate(); return *this; }
   577 
   578       /// Comparison operator
   579       bool operator==(const NodeIt& e) const { return idx==e.idx; }
   580       /// Comparison operator
   581       bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
   582        /// Comparison operator
   583      bool operator<(const NodeIt& e) const { return idx<e.idx; }
   584 
   585     private:
   586       void validate() { if( size_t(idx) > p->length() ) idx=-1; }
   587     };
   588 
   589     friend class Builder;
   590 
   591     /**
   592      * \brief Class to build paths
   593      *
   594      * This class is used to fill a path with edges.
   595      *
   596      * You can push new edges to the front and to the back of the path in
   597      * arbitrary order then you should commit these changes to the graph.
   598      *
   599      * Fundamentally, for most "Paths" (classes fulfilling the
   600      * PathConcept) while the builder is active (after the first modifying
   601      * operation and until the commit()) the original Path is in a
   602      * "transitional" state (operations ot it have undefined result). But
   603      * in the case of UndirPath the original path is unchanged until the
   604      * commit. However we don't recomend that you use this feature.
   605      */
   606     class Builder {
   607       UndirPath &P;
   608       Container front, back;
   609 
   610     public:
   611       ///\param _p the path you want to fill in.
   612       ///
   613       Builder(UndirPath &_p) : P(_p) {}
   614 
   615       /// Sets the starting node of the path.
   616 
   617       /// Sets the starting node of the path. Edge added to the path
   618       /// afterwards have to be incident to this node.
   619       /// It should be called if and only if
   620       /// the path is empty and before any call to
   621       /// \ref pushFront() or \ref pushBack()
   622       void setStartNode(const GraphNode &) {}
   623 
   624       ///Push a new edge to the front of the path
   625 
   626       ///Push a new edge to the front of the path.
   627       ///\sa setStartNode
   628       void pushFront(const GraphEdge& e) {
   629 	front.push_back(e);
   630       }
   631 
   632       ///Push a new edge to the back of the path
   633 
   634       ///Push a new edge to the back of the path.
   635       ///\sa setStartNode
   636       void pushBack(const GraphEdge& e) {
   637 	back.push_back(e);
   638       }
   639 
   640       ///Commit the changes to the path.
   641       void commit() {
   642 	if( !(front.empty() && back.empty()) ) {
   643 	  Container tmp;
   644 	  tmp.reserve(front.size()+back.size()+P.length());
   645 	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
   646 	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
   647 	  tmp.insert(tmp.end(), back.begin(), back.end());
   648 	  P.edges.swap(tmp);
   649 	  front.clear();
   650 	  back.clear();
   651 	}
   652       }
   653 
   654 
   655       ///Reserve storage for the builder in advance.
   656 
   657       ///If you know a reasonable upper bound of the number of the edges
   658       ///to add to the front, using this function you can speed up the building.
   659 
   660       void reserveFront(size_t r) {front.reserve(r);}
   661 
   662       ///Reserve storage for the builder in advance.
   663 
   664       ///If you know a reasonable upper bound of the number of the edges
   665       ///to add to the back, using this function you can speed up the building.
   666 
   667       void reserveBack(size_t r) {back.reserve(r);}
   668 
   669     private:
   670       bool empty() {
   671 	return front.empty() && back.empty() && P.empty();
   672       }
   673 
   674       GraphNode source() const {
   675 	if( ! front.empty() )
   676 	  return P.gr->source(front[front.size()-1]);
   677 	else if( ! P.empty() )
   678 	  return P.gr->source(P.edges[0]);
   679 	else if( ! back.empty() )
   680 	  return P.gr->source(back[0]);
   681 	else
   682 	  return INVALID;
   683       }
   684       GraphNode target() const {
   685 	if( ! back.empty() )
   686 	  return P.gr->target(back[back.size()-1]);
   687 	else if( ! P.empty() )
   688 	  return P.gr->target(P.edges[P.length()-1]);
   689 	else if( ! front.empty() )
   690 	  return P.gr->target(front[0]);
   691 	else
   692 	  return INVALID;
   693       }
   694 
   695     };
   696 
   697   };
   698 
   699 
   700   ///@}
   701 
   702 } // namespace lemon
   703 
   704 #endif // LEMON_PATH_H