COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/path.h @ 1188:7e529047df1a

Last change on this file since 1188:7e529047df1a was 1164:80bb73097736, checked in by Alpar Juttner, 19 years ago

A year has passed again.

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