COIN-OR::LEMON - Graph Library

Changeset 684:11d480a922b1 in lemon-0.x


Ignore:
Timestamp:
06/15/04 08:29:27 (20 years ago)
Author:
Alpar Juttner
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@932
Message:

Branch from path.h to extend its documentation.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • src/work/alpar/path.h

    r683 r684  
    11// -*- c++ -*- //
    22
    3 ///\ingroup datas
     3/**
     4@defgroup paths Path Structures
     5@ingroup datas
     6\brief Path structures implemented in Hugo.
     7
     8Hugolib provides flexible data structures
     9to work with paths.
     10
     11All of them have the same interface, especially they can be built or extended
     12using a standard Builder subclass. This make is easy to have e.g. the Dijkstra
     13algorithm to store its result in any kind of path structure.
     14
     15*/
     16
     17///\ingroup paths
    418///\file
    519///\brief Classes for representing paths in graphs.
     
    1832namespace hugo {
    1933
    20   /// \addtogroup datas
     34  /// \addtogroup paths
    2135  /// @{
    2236
     
    3650  class DirPath {
    3751  public:
    38     typedef typename Graph::Edge GraphEdge;
     52    /// Edge type of the underlying graph.
     53    typedef typename Graph::Edge GraphEdge;
     54    /// Node type of the underlying graph.
    3955    typedef typename Graph::Node GraphNode;
    4056    class NodeIt;
     
    153169
    154170
    155     /*** Iterator classes ***/
     171    /* Iterator classes */
     172
     173    /**
     174     * \brief Iterator class to iterate on the edges of the paths
     175     *
     176     * \ingroup paths
     177     * This class is used to iterate on the edges of the paths
     178     *
     179     * Of course it converts to Graph::Edge
     180     *
     181     * \todo Its interface differs from the standard edge iterator.
     182     * Yes, it shouldn't.
     183     */
    156184    class EdgeIt {
    157185      friend class DirPath;
     
    160188      const DirPath *p;
    161189    public:
     190      /// Default constructor
    162191      EdgeIt() {}
     192      /// Invalid constructor
    163193      EdgeIt(Invalid) : idx(-1), p(0) {}
     194      /// Constructor with starting point
    164195      EdgeIt(const DirPath &_p, int _idx = 0) :
    165196        idx(_idx), p(&_p) { validate(); }
    166197
     198      ///Validity check
    167199      bool valid() const { return idx!=-1; }
    168200
     201      ///Conversion to Graph::Edge
    169202      operator GraphEdge () const {
    170203        return valid() ? p->edges[idx] : INVALID;
    171204      }
     205
     206      /// Next edge
    172207      EdgeIt& operator++() { ++idx; validate(); return *this; }
    173208
     209      /// Comparison operator
    174210      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
     211      /// Comparison operator
    175212      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
     213      /// Comparison operator
    176214      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
    177215
     
    182220    };
    183221
     222    /**
     223     * \brief Iterator class to iterate on the nodes of the paths
     224     *
     225     * \ingroup paths
     226     * This class is used to iterate on the nodes of the paths
     227     *
     228     * Of course it converts to Graph::Node
     229     *
     230     * \todo Its interface differs from the standard node iterator.
     231     * Yes, it shouldn't.
     232     */
    184233    class NodeIt {
    185234      friend class DirPath;
     
    188237      const DirPath *p;
    189238    public:
     239      /// Default constructor
    190240      NodeIt() {}
     241      /// Invalid constructor
    191242      NodeIt(Invalid) : idx(-1), p(0) {}
     243      /// Constructor with starting point
    192244      NodeIt(const DirPath &_p, int _idx = 0) :
    193245        idx(_idx), p(&_p) { validate(); }
    194246
     247      ///Validity check
    195248      bool valid() const { return idx!=-1; }
    196249
     250      ///Conversion to Graph::Node
    197251      operator const GraphNode& () const {
    198252        if(idx >= p->length())
     
    203257          return INVALID;
    204258      }
     259      /// Next node
    205260      NodeIt& operator++() { ++idx; validate(); return *this; }
    206261
     262      /// Comparison operator
    207263      bool operator==(const NodeIt& e) const { return idx==e.idx; }
     264      /// Comparison operator
    208265      bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
     266      /// Comparison operator
    209267      bool operator<(const NodeIt& e) const { return idx<e.idx; }
    210268
     
    218276     * \brief Class to build paths
    219277     *
    220      * \ingroup datas
     278     * \ingroup paths
    221279     * This class is used to fill a path with edges.
    222280     *
     
    286344      // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
    287345      // Hogy kenyelmes egy ilyet hasznalni?
     346 
     347      ///Reserve storage in advance for the builder
     348
     349      ///If you know an reasonable upper bound of the number of the edges
     350      ///to add, using this function you can speed up the building.
    288351      void reserve(size_t r) {
    289352        front.reserve(r);
     
    320383
    321384  };
    322 
    323 
    324 
    325 
    326385
    327386
     
    350409  class UndirPath {
    351410  public:
     411    /// Edge type of the underlying graph.
    352412    typedef typename Graph::Edge GraphEdge;
    353     typedef typename Graph::Node GraphNode;
     413     /// Node type of the underlying graph.
     414   typedef typename Graph::Node GraphNode;
    354415    class NodeIt;
    355416    class EdgeIt;
     
    467528
    468529
    469     /*** Iterator classes ***/
     530
     531    /**
     532     * \brief Iterator class to iterate on the edges of the paths
     533     *
     534     * \ingroup paths
     535     * This class is used to iterate on the edges of the paths
     536     *
     537     * Of course it converts to Graph::Edge
     538     *
     539     * \todo Its interface differs from the standard edge iterator.
     540     * Yes, it shouldn't.
     541     */
    470542    class EdgeIt {
    471543      friend class UndirPath;
     
    474546      const UndirPath *p;
    475547    public:
     548      /// Default constructor
    476549      EdgeIt() {}
     550      /// Invalid constructor
    477551      EdgeIt(Invalid) : idx(-1), p(0) {}
     552      /// Constructor with starting point
    478553      EdgeIt(const UndirPath &_p, int _idx = 0) :
    479554        idx(_idx), p(&_p) { validate(); }
    480555
     556      ///Validity check
    481557      bool valid() const { return idx!=-1; }
    482558
     559      ///Conversion to Graph::Edge
    483560      operator GraphEdge () const {
    484561        return valid() ? p->edges[idx] : INVALID;
    485562      }
    486       EdgeIt& operator++() { ++idx; validate(); return *this; }
    487 
     563      /// Next edge
     564     EdgeIt& operator++() { ++idx; validate(); return *this; }
     565
     566      /// Comparison operator
    488567      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
     568      /// Comparison operator
    489569      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
     570      /// Comparison operator
    490571      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
    491572
     
    496577    };
    497578
     579    /**
     580     * \brief Iterator class to iterate on the nodes of the paths
     581     *
     582     * \ingroup paths
     583     * This class is used to iterate on the nodes of the paths
     584     *
     585     * Of course it converts to Graph::Node
     586     *
     587     * \todo Its interface differs from the standard node iterator.
     588     * Yes, it shouldn't.
     589     */
    498590    class NodeIt {
    499591      friend class UndirPath;
     
    502594      const UndirPath *p;
    503595    public:
     596      /// Default constructor
    504597      NodeIt() {}
     598      /// Invalid constructor
    505599      NodeIt(Invalid) : idx(-1), p(0) {}
     600      /// Constructor with starting point
    506601      NodeIt(const UndirPath &_p, int _idx = 0) :
    507602        idx(_idx), p(&_p) { validate(); }
    508603
     604      ///Validity check
    509605      bool valid() const { return idx!=-1; }
    510606
     607      ///Conversion to Graph::Node
    511608      operator const GraphNode& () const {
    512609        if(idx >= p->length())
     
    517614          return INVALID;
    518615      }
     616      /// Next node
    519617      NodeIt& operator++() { ++idx; validate(); return *this; }
    520618
     619      /// Comparison operator
    521620      bool operator==(const NodeIt& e) const { return idx==e.idx; }
     621      /// Comparison operator
    522622      bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
    523       bool operator<(const NodeIt& e) const { return idx<e.idx; }
     623       /// Comparison operator
     624     bool operator<(const NodeIt& e) const { return idx<e.idx; }
    524625
    525626    private:
     
    532633     * \brief Class to build paths
    533634     *
    534      * \ingroup datas
     635     * \ingroup paths
    535636     * This class is used to fill a path with edges.
    536637     *
     
    600701      // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
    601702      // Hogy kenyelmes egy ilyet hasznalni?
    602       void reserve(size_t r) {
     703
     704      ///Reserve storage in advance for the builder
     705
     706      ///If you know an reasonable upper bound of the number of the edges
     707      ///to add, using this function you can speed up the building.
     708       void reserve(size_t r) {
    603709        front.reserve(r);
    604710        back.reserve(r);
     
    636742
    637743
    638 
    639 
    640 
    641 
    642 
    643 
    644 
    645 
    646   /**********************************************************************/
    647 
    648 
    649   /* Ennek az allocatorosdinak sokkal jobban utana kene nezni a hasznalata
    650      elott. Eleg bonyinak nez ki, ahogyan azokat az STL-ben hasznaljak. */
    651 
    652   template<typename Graph>
    653   class DynamicPath {
    654 
    655   public:
    656     typedef typename Graph::Edge GraphEdge;
    657     typedef typename Graph::Node GraphNode;
    658     class NodeIt;
    659     class EdgeIt;
    660 
    661   protected:
    662     Graph& G;
    663     // FIXME: ehelyett eleg lenne tarolni ket boolt: a ket szelso el
    664     // iranyitasat:
    665     GraphNode _first, _last;
    666     typedef std::deque<GraphEdge> Container;
    667     Container edges;
    668 
    669   public:
    670 
    671     DynamicPath(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {}
    672 
    673     /// Subpath defined by two nodes.
    674     /// Nodes may be in reversed order, then
    675     /// we contstruct the reversed path.
    676     DynamicPath(const DynamicPath &P, const NodeIt &a, const NodeIt &b);
    677     /// Subpath defined by two edges. Contains edges in [a,b)
    678     /// It is an error if the two edges are not in order!
    679     DynamicPath(const DynamicPath &P, const EdgeIt &a, const EdgeIt &b);
    680    
    681     size_t length() const { return edges.size(); }
    682     GraphNode from() const { return _first; }
    683     GraphNode to() const { return _last; }
    684 
    685     NodeIt& first(NodeIt &n) const { return nth(n, 0); }
    686     EdgeIt& first(EdgeIt &e) const { return nth(e, 0); }
    687     template<typename It>
    688     It first() const {
    689       It e;
    690       first(e);
    691       return e;
    692     }
    693 
    694     NodeIt& nth(NodeIt &, size_t) const;
    695     EdgeIt& nth(EdgeIt &, size_t) const;
    696     template<typename It>
    697     It nth(size_t n) const {
    698       It e;
    699       nth(e, n);
    700       return e;
    701     }
    702 
    703     bool valid(const NodeIt &n) const { return n.idx <= length(); }
    704     bool valid(const EdgeIt &e) const { return e.it < edges.end(); }
    705 
    706     bool isForward(const EdgeIt &e) const { return e.forw; }
    707 
    708     /// index of a node on the path. Returns length+2 for the invalid NodeIt
    709     int index(const NodeIt &n) const { return n.idx; }
    710     /// index of an edge on the path. Returns length+1 for the invalid EdgeIt
    711     int index(const EdgeIt &e) const { return e.it - edges.begin(); }
    712 
    713     EdgeIt& next(EdgeIt &e) const;
    714     NodeIt& next(NodeIt &n) const;
    715     template <typename It>
    716     It getNext(It it) const {
    717       It tmp(it); return next(tmp);
    718     }
    719 
    720     // A path is constructed using the following four functions.
    721     // They return false if the requested operation is inconsistent
    722     // with the path constructed so far.
    723     // If your path has only one edge you MUST set either "from" or "to"!
    724     // So you probably SHOULD call it in any case to be safe (and check the
    725     // returned value to check if your path is consistent with your idea).
    726     bool pushFront(const GraphEdge &e);
    727     bool pushBack(const GraphEdge &e);
    728     bool setFrom(const GraphNode &n);
    729     bool setTo(const GraphNode &n);
    730 
    731     // WARNING: these two functions return the head/tail of an edge with
    732     // respect to the direction of the path!
    733     // So G.head(P.graphEdge(e)) == P.graphNode(P.head(e)) holds only if
    734     // P.forward(e) is true (or the edge is a loop)!
    735     NodeIt head(const EdgeIt& e) const;
    736     NodeIt tail(const EdgeIt& e) const;
    737 
    738     // FIXME: ezeknek valami jobb nev kellene!!!
    739     GraphEdge graphEdge(const EdgeIt& e) const;
    740     GraphNode graphNode(const NodeIt& n) const;
    741 
    742 
    743     /*** Iterator classes ***/
    744     class EdgeIt {
    745       friend class DynamicPath;
    746 
    747       typename Container::const_iterator it;
    748       bool forw;
    749     public:
    750       // FIXME: jarna neki ilyen is...
    751       // EdgeIt(Invalid);
    752 
    753       bool forward() const { return forw; }
    754 
    755       bool operator==(const EdgeIt& e) const { return it==e.it; }
    756       bool operator!=(const EdgeIt& e) const { return it!=e.it; }
    757       bool operator<(const EdgeIt& e) const { return it<e.it; }
    758     };
    759 
    760     class NodeIt {
    761       friend class DynamicPath;
    762 
    763       size_t idx;
    764       bool tail;  // Is this node the tail of the edge with same idx?
    765 
    766     public:
    767       // FIXME: jarna neki ilyen is...
    768       // NodeIt(Invalid);
    769 
    770       bool operator==(const NodeIt& n) const { return idx==n.idx; }
    771       bool operator!=(const NodeIt& n) const { return idx!=n.idx; }
    772       bool operator<(const NodeIt& n) const { return idx<n.idx; }
    773     };
    774 
    775   private:
    776     bool edgeIncident(const GraphEdge &e, const GraphNode &a,
    777                       GraphNode &b);
    778     bool connectTwoEdges(const GraphEdge &e, const GraphEdge &f);
    779   };
    780 
    781   template<typename Gr>
    782   typename DynamicPath<Gr>::EdgeIt&
    783   DynamicPath<Gr>::next(DynamicPath::EdgeIt &e) const {
    784     if( e.it == edges.end() )
    785       return e;
    786 
    787     GraphNode common_node = ( e.forw ? G.head(*e.it) : G.tail(*e.it) );
    788     ++e.it;
    789 
    790     // Invalid edgeit is always forward :)
    791     if( e.it == edges.end() ) {
    792       e.forw = true;
    793       return e;
    794     }
    795 
    796     e.forw = ( G.tail(*e.it) == common_node );
    797     return e;
    798   }
    799 
    800   template<typename Gr>
    801   typename DynamicPath<Gr>::NodeIt& DynamicPath<Gr>::next(NodeIt &n) const {
    802     if( n.idx >= length() ) {
    803       // FIXME: invalid
    804       n.idx = length()+1;
    805       return n;
    806     }
    807 
    808    
    809     GraphNode next_node = ( n.tail ? G.head(edges[n.idx]) :
    810                               G.tail(edges[n.idx]) );
    811     ++n.idx;
    812     if( n.idx < length() ) {
    813       n.tail = ( next_node == G.tail(edges[n.idx]) );
    814     }
    815     else {
    816       n.tail = true;
    817     }
    818 
    819     return n;
    820   }
    821 
    822   template<typename Gr>
    823   bool DynamicPath<Gr>::edgeIncident(const GraphEdge &e, const GraphNode &a,
    824                           GraphNode &b) {
    825     if( G.tail(e) == a ) {
    826       b=G.head(e);
    827       return true;
    828     }
    829     if( G.head(e) == a ) {
    830       b=G.tail(e);
    831       return true;
    832     }
    833     return false;
    834   }
    835 
    836   template<typename Gr>
    837   bool DynamicPath<Gr>::connectTwoEdges(const GraphEdge &e,
    838                              const GraphEdge &f) {
    839     if( edgeIncident(f, G.tail(e), _last) ) {
    840       _first = G.head(e);
    841       return true;
    842     }
    843     if( edgeIncident(f, G.head(e), _last) ) {
    844       _first = G.tail(e);
    845       return true;
    846     }
    847     return false;
    848   }
    849 
    850   template<typename Gr>
    851   bool DynamicPath<Gr>::pushFront(const GraphEdge &e) {
    852     if( G.valid(_first) ) {
    853         if( edgeIncident(e, _first, _first) ) {
    854           edges.push_front(e);
    855           return true;
    856         }
    857         else
    858           return false;
    859     }
    860     else if( length() < 1 || connectTwoEdges(e, edges[0]) ) {
    861       edges.push_front(e);
    862       return true;
    863     }
    864     else
    865       return false;
    866   }
    867 
    868   template<typename Gr>
    869   bool DynamicPath<Gr>::pushBack(const GraphEdge &e) {
    870     if( G.valid(_last) ) {
    871         if( edgeIncident(e, _last, _last) ) {
    872           edges.push_back(e);
    873           return true;
    874         }
    875         else
    876           return false;
    877     }
    878     else if( length() < 1 || connectTwoEdges(edges[0], e) ) {
    879       edges.push_back(e);
    880       return true;
    881     }
    882     else
    883       return false;
    884   }
    885 
    886 
    887   template<typename Gr>
    888   bool DynamicPath<Gr>::setFrom(const GraphNode &n) {
    889     if( G.valid(_first) ) {
    890       return _first == n;
    891     }
    892     else {
    893       if( length() > 0) {
    894         if( edgeIncident(edges[0], n, _last) ) {
    895           _first = n;
    896           return true;
    897         }
    898         else return false;
    899       }
    900       else {
    901         _first = _last = n;
    902         return true;
    903       }
    904     }
    905   }
    906 
    907   template<typename Gr>
    908   bool DynamicPath<Gr>::setTo(const GraphNode &n) {
    909     if( G.valid(_last) ) {
    910       return _last == n;
    911     }
    912     else {
    913       if( length() > 0) {
    914         if( edgeIncident(edges[0], n, _first) ) {
    915           _last = n;
    916           return true;
    917         }
    918         else return false;
    919       }
    920       else {
    921         _first = _last = n;
    922         return true;
    923       }
    924     }
    925   }
    926 
    927 
    928   template<typename Gr>
    929   typename DynamicPath<Gr>::NodeIt
    930   DynamicPath<Gr>::tail(const EdgeIt& e) const {
    931     NodeIt n;
    932 
    933     if( e.it == edges.end() ) {
    934       // FIXME: invalid-> invalid
    935       n.idx = length() + 1;
    936       n.tail = true;
    937       return n;
    938     }
    939 
    940     n.idx = e.it-edges.begin();
    941     n.tail = e.forw;
    942     return n;
    943   }
    944 
    945   template<typename Gr>
    946   typename DynamicPath<Gr>::NodeIt
    947   DynamicPath<Gr>::head(const EdgeIt& e) const {
    948     if( e.it == edges.end()-1 ) {
    949       return _last;
    950     }
    951 
    952     EdgeIt next_edge = e;
    953     next(next_edge);
    954     return tail(next_edge);
    955   }
    956      
    957   template<typename Gr>
    958   typename DynamicPath<Gr>::GraphEdge
    959   DynamicPath<Gr>::graphEdge(const EdgeIt& e) const {
    960     if( e.it != edges.end() ) {
    961       return *e.it;
    962     }
    963     else {
    964       return INVALID;
    965     }
    966   }
    967  
    968   template<typename Gr>
    969   typename DynamicPath<Gr>::GraphNode
    970   DynamicPath<Gr>::graphNode(const NodeIt& n) const {
    971     if( n.idx < length() ) {
    972       return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]);
    973     }
    974     else if( n.idx == length() ) {
    975       return _last;
    976     }
    977     else {
    978       return INVALID;
    979     }
    980   }
    981 
    982   template<typename Gr>
    983   typename DynamicPath<Gr>::EdgeIt&
    984   DynamicPath<Gr>::nth(EdgeIt &e, size_t k) const {
    985     if( k>=length() ) {
    986       // FIXME: invalid EdgeIt
    987       e.it = edges.end();
    988       e.forw = true;
    989       return e;
    990     }
    991 
    992     e.it = edges.begin()+k;
    993     if(k==0) {
    994       e.forw = ( G.tail(*e.it) == _first );
    995     }
    996     else {
    997       e.forw = ( G.tail(*e.it) == G.tail(edges[k-1]) ||
    998                  G.tail(*e.it) == G.head(edges[k-1]) );
    999     }
    1000     return e;
    1001   }
    1002    
    1003   template<typename Gr>
    1004   typename DynamicPath<Gr>::NodeIt&
    1005   DynamicPath<Gr>::nth(NodeIt &n, size_t k) const {
    1006     if( k>length() ) {
    1007       // FIXME: invalid NodeIt
    1008       n.idx = length()+1;
    1009       n.tail = true;
    1010       return n;
    1011     }
    1012     if( k==length() ) {
    1013       n.idx = length();
    1014       n.tail = true;
    1015       return n;
    1016     }
    1017     n = tail(nth<EdgeIt>(k));
    1018     return n;
    1019   }
    1020 
    1021   // Reszut konstruktorok:
    1022 
    1023 
    1024   template<typename Gr>
    1025   DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const EdgeIt &a,
    1026                                const EdgeIt &b) :
    1027     G(P.G), edges(a.it, b.it)    // WARNING: if b.it < a.it this will blow up!
    1028   {
    1029     if( G.valid(P._first) && a.it < P.edges.end() ) {
    1030       _first = ( a.forw ? G.tail(*a.it) : G.head(*a.it) );
    1031       if( b.it < P.edges.end() ) {
    1032         _last = ( b.forw ? G.tail(*b.it) : G.head(*b.it) );
    1033       }
    1034       else {
    1035         _last = P._last;
    1036       }
    1037     }
    1038   }
    1039 
    1040   template<typename Gr>
    1041   DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const NodeIt &a,
    1042                                const NodeIt &b) : G(P.G)
    1043   {
    1044     if( !P.valid(a) || !P.valid(b) )
    1045       return;
    1046 
    1047     int ai = a.idx, bi = b.idx;
    1048     if( bi<ai )
    1049       std::swap(ai,bi);
    1050    
    1051     edges.resize(bi-ai);
    1052     copy(P.edges.begin()+ai, P.edges.begin()+bi, edges.begin());
    1053 
    1054     _first = P.graphNode(a);
    1055     _last = P.graphNode(b);
    1056   }
    1057 
    1058744  ///@}
    1059745
Note: See TracChangeset for help on using the changeset viewer.