diff --git a/lemon/path.h b/lemon/path.h new file mode 100644 --- /dev/null +++ b/lemon/path.h @@ -0,0 +1,1079 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup paths +///\file +///\brief Classes for representing paths in digraphs. +/// + +#ifndef LEMON_PATH_H +#define LEMON_PATH_H + +#include +#include + +#include +#include +#include + +namespace lemon { + + /// \addtogroup paths + /// @{ + + + /// \brief A structure for representing directed paths in a digraph. + /// + /// A structure for representing directed path in a digraph. + /// \param Digraph The digraph type in which the path is. + /// + /// In a sense, the path can be treated as a list of arcs. The + /// lemon path type stores just this list. As a consequence, it + /// cannot enumerate the nodes of the path and the source node of + /// a zero length path is undefined. + /// + /// This implementation is a back and front insertable and erasable + /// path type. It can be indexed in O(1) time. The front and back + /// insertion and erase is done in O(1) (amortized) time. The + /// implementation uses two vectors for storing the front and back + /// insertions. + template + class Path { + public: + + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + + /// \brief Default constructor + /// + /// Default constructor + Path() {} + + /// \brief Template copy constructor + /// + /// This constuctor initializes the path from any other path type. + /// It simply makes a copy of the given path. + template + Path(const CPath& cpath) { + copyPath(*this, cpath); + } + + /// \brief Template copy assignment + /// + /// This operator makes a copy of a path of any other type. + template + Path& operator=(const CPath& cpath) { + copyPath(*this, cpath); + return *this; + } + + /// \brief Lemon style iterator for path arcs + /// + /// This class is used to iterate on the arcs of the paths. + class ArcIt { + friend class Path; + public: + /// \brief Default constructor + ArcIt() {} + /// \brief Invalid constructor + ArcIt(Invalid) : path(0), idx(-1) {} + /// \brief Initializate the iterator to the first arc of path + ArcIt(const Path &_path) + : path(&_path), idx(_path.empty() ? -1 : 0) {} + + private: + + ArcIt(const Path &_path, int _idx) + : path(&_path), idx(_idx) {} + + public: + + /// \brief Conversion to Arc + operator const Arc&() const { + return path->nth(idx); + } + + /// \brief Next arc + ArcIt& operator++() { + ++idx; + if (idx >= path->length()) idx = -1; + return *this; + } + + /// \brief Comparison operator + bool operator==(const ArcIt& e) const { return idx==e.idx; } + /// \brief Comparison operator + bool operator!=(const ArcIt& e) const { return idx!=e.idx; } + /// \brief Comparison operator + bool operator<(const ArcIt& e) const { return idx + void build(const CPath& path) { + int len = path.length(); + tail.reserve(len); + for (typename CPath::ArcIt it(path); it != INVALID; ++it) { + tail.push_back(it); + } + } + + template + void buildRev(const CPath& path) { + int len = path.length(); + head.reserve(len); + for (typename CPath::RevArcIt it(path); it != INVALID; ++it) { + head.push_back(it); + } + } + + protected: + typedef std::vector Container; + Container head, tail; + + }; + + /// \brief A structure for representing directed paths in a digraph. + /// + /// A structure for representing directed path in a digraph. + /// \param Digraph The digraph type in which the path is. + /// + /// In a sense, the path can be treated as a list of arcs. The + /// lemon path type stores just this list. As a consequence it + /// cannot enumerate the nodes in the path and the zero length paths + /// cannot store the source. + /// + /// This implementation is a just back insertable and erasable path + /// type. It can be indexed in O(1) time. The back insertion and + /// erasure is amortized O(1) time. This implementation is faster + /// then the \c Path type because it use just one vector for the + /// arcs. + template + class SimplePath { + public: + + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + + /// \brief Default constructor + /// + /// Default constructor + SimplePath() {} + + /// \brief Template copy constructor + /// + /// This path can be initialized with any other path type. It just + /// makes a copy of the given path. + template + SimplePath(const CPath& cpath) { + copyPath(*this, cpath); + } + + /// \brief Template copy assignment + /// + /// This path can be initialized with any other path type. It just + /// makes a copy of the given path. + template + SimplePath& operator=(const CPath& cpath) { + copyPath(*this, cpath); + return *this; + } + + /// \brief Iterator class to iterate on the arcs of the paths + /// + /// This class is used to iterate on the arcs of the paths + /// + /// Of course it converts to Digraph::Arc + class ArcIt { + friend class SimplePath; + public: + /// Default constructor + ArcIt() {} + /// Invalid constructor + ArcIt(Invalid) : path(0), idx(-1) {} + /// \brief Initializate the constructor to the first arc of path + ArcIt(const SimplePath &_path) + : path(&_path), idx(_path.empty() ? -1 : 0) {} + + private: + + /// Constructor with starting point + ArcIt(const SimplePath &_path, int _idx) + : idx(_idx), path(&_path) {} + + public: + + ///Conversion to Digraph::Arc + operator const Arc&() const { + return path->nth(idx); + } + + /// Next arc + ArcIt& operator++() { + ++idx; + if (idx >= path->length()) idx = -1; + return *this; + } + + /// Comparison operator + bool operator==(const ArcIt& e) const { return idx==e.idx; } + /// Comparison operator + bool operator!=(const ArcIt& e) const { return idx!=e.idx; } + /// Comparison operator + bool operator<(const ArcIt& e) const { return idx + void build(const CPath& path) { + int len = path.length(); + data.resize(len); + int index = 0; + for (typename CPath::ArcIt it(path); it != INVALID; ++it) { + data[index] = it;; + ++index; + } + } + + template + void buildRev(const CPath& path) { + int len = path.length(); + data.resize(len); + int index = len; + for (typename CPath::RevArcIt it(path); it != INVALID; ++it) { + --index; + data[index] = it;; + } + } + + protected: + typedef std::vector Container; + Container data; + + }; + + /// \brief A structure for representing directed paths in a digraph. + /// + /// A structure for representing directed path in a digraph. + /// \param Digraph The digraph type in which the path is. + /// + /// In a sense, the path can be treated as a list of arcs. The + /// lemon path type stores just this list. As a consequence it + /// cannot enumerate the nodes in the path and the zero length paths + /// cannot store the source. + /// + /// This implementation is a back and front insertable and erasable + /// path type. It can be indexed in O(k) time, where k is the rank + /// of the arc in the path. The length can be computed in O(n) + /// time. The front and back insertion and erasure is O(1) time + /// and it can be splited and spliced in O(1) time. + template + class ListPath { + public: + + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + + protected: + + // the std::list<> is incompatible + // hard to create invalid iterator + struct Node { + Arc arc; + Node *next, *prev; + }; + + Node *first, *last; + + std::allocator alloc; + + public: + + /// \brief Default constructor + /// + /// Default constructor + ListPath() : first(0), last(0) {} + + /// \brief Template copy constructor + /// + /// This path can be initialized with any other path type. It just + /// makes a copy of the given path. + template + ListPath(const CPath& cpath) : first(0), last(0) { + copyPath(*this, cpath); + } + + /// \brief Destructor of the path + /// + /// Destructor of the path + ~ListPath() { + clear(); + } + + /// \brief Template copy assignment + /// + /// This path can be initialized with any other path type. It just + /// makes a copy of the given path. + template + ListPath& operator=(const CPath& cpath) { + copyPath(*this, cpath); + return *this; + } + + /// \brief Iterator class to iterate on the arcs of the paths + /// + /// This class is used to iterate on the arcs of the paths + /// + /// Of course it converts to Digraph::Arc + class ArcIt { + friend class ListPath; + public: + /// Default constructor + ArcIt() {} + /// Invalid constructor + ArcIt(Invalid) : path(0), node(0) {} + /// \brief Initializate the constructor to the first arc of path + ArcIt(const ListPath &_path) + : path(&_path), node(_path.first) {} + + protected: + + ArcIt(const ListPath &_path, Node *_node) + : path(&_path), node(_node) {} + + + public: + + ///Conversion to Digraph::Arc + operator const Arc&() const { + return node->arc; + } + + /// Next arc + ArcIt& operator++() { + node = node->next; + return *this; + } + + /// Comparison operator + bool operator==(const ArcIt& e) const { return node==e.node; } + /// Comparison operator + bool operator!=(const ArcIt& e) const { return node!=e.node; } + /// Comparison operator + bool operator<(const ArcIt& e) const { return nodenext; + } + return node->arc; + } + + /// \brief Initializes arc iterator to point to the nth arc. + ArcIt nthIt(int n) const { + Node *node = first; + for (int i = 0; i < n; ++i) { + node = node->next; + } + return ArcIt(*this, node); + } + + /// \brief Length of the path. + int length() const { + int len = 0; + Node *node = first; + while (node != 0) { + node = node->next; + ++len; + } + return len; + } + + /// \brief Return true if the path is empty. + bool empty() const { return first == 0; } + + /// \brief Reset the path to an empty one. + void clear() { + while (first != 0) { + last = first->next; + alloc.destroy(first); + alloc.deallocate(first, 1); + first = last; + } + } + + /// \brief The first arc of the path + const Arc& front() const { + return first->arc; + } + + /// \brief Add a new arc before the current path + void addFront(const Arc& arc) { + Node *node = alloc.allocate(1); + alloc.construct(node, Node()); + node->prev = 0; + node->next = first; + node->arc = arc; + if (first) { + first->prev = node; + first = node; + } else { + first = last = node; + } + } + + /// \brief Erase the first arc of the path + void eraseFront() { + Node *node = first; + first = first->next; + if (first) { + first->prev = 0; + } else { + last = 0; + } + alloc.destroy(node); + alloc.deallocate(node, 1); + } + + /// \brief The last arc of the path. + const Arc& back() const { + return last->arc; + } + + /// \brief Add a new arc behind the current path. + void addBack(const Arc& arc) { + Node *node = alloc.allocate(1); + alloc.construct(node, Node()); + node->next = 0; + node->prev = last; + node->arc = arc; + if (last) { + last->next = node; + last = node; + } else { + last = first = node; + } + } + + /// \brief Erase the last arc of the path + void eraseBack() { + Node *node = last; + last = last->prev; + if (last) { + last->next = 0; + } else { + first = 0; + } + alloc.destroy(node); + alloc.deallocate(node, 1); + } + + /// \brief Splice a path to the back of the current path. + /// + /// It splices \c tpath to the back of the current path and \c + /// tpath becomes empty. The time complexity of this function is + /// O(1). + void spliceBack(ListPath& tpath) { + if (first) { + if (tpath.first) { + last->next = tpath.first; + tpath.first->prev = last; + last = tpath.last; + } + } else { + first = tpath.first; + last = tpath.last; + } + tpath.first = tpath.last = 0; + } + + /// \brief Splice a path to the front of the current path. + /// + /// It splices \c tpath before the current path and \c tpath + /// becomes empty. The time complexity of this function + /// is O(1). + void spliceFront(ListPath& tpath) { + if (first) { + if (tpath.first) { + first->prev = tpath.last; + tpath.last->next = first; + first = tpath.first; + } + } else { + first = tpath.first; + last = tpath.last; + } + tpath.first = tpath.last = 0; + } + + /// \brief Splice a path into the current path. + /// + /// It splices the \c tpath into the current path before the + /// position of \c it iterator and \c tpath becomes empty. The + /// time complexity of this function is O(1). If the \c it is + /// \c INVALID then it will splice behind the current path. + void splice(ArcIt it, ListPath& tpath) { + if (it.node) { + if (tpath.first) { + tpath.first->prev = it.node->prev; + if (it.node->prev) { + it.node->prev->next = tpath.first; + } else { + first = tpath.first; + } + it.node->prev = tpath.last; + tpath.last->next = it.node; + } + } else { + if (first) { + if (tpath.first) { + last->next = tpath.first; + tpath.first->prev = last; + last = tpath.last; + } + } else { + first = tpath.first; + last = tpath.last; + } + } + tpath.first = tpath.last = 0; + } + + /// \brief Split the current path. + /// + /// It splits the current path into two parts. The part before + /// the iterator \c it will remain in the current path and the part + /// starting with + /// \c it will put into \c tpath. If \c tpath have arcs + /// before the operation they are removed first. The time + /// complexity of this function is O(1) plus the the time of emtying + /// \c tpath. If \c it is \c INVALID then it just clears \c tpath + void split(ArcIt it, ListPath& tpath) { + tpath.clear(); + if (it.node) { + tpath.first = it.node; + tpath.last = last; + if (it.node->prev) { + last = it.node->prev; + last->next = 0; + } else { + first = last = 0; + } + it.node->prev = 0; + } + } + + + typedef True BuildTag; + + template + void build(const CPath& path) { + for (typename CPath::ArcIt it(path); it != INVALID; ++it) { + addBack(it); + } + } + + template + void buildRev(const CPath& path) { + for (typename CPath::RevArcIt it(path); it != INVALID; ++it) { + addFront(it); + } + } + + }; + + /// \brief A structure for representing directed paths in a digraph. + /// + /// A structure for representing directed path in a digraph. + /// \param Digraph The digraph type in which the path is. + /// + /// In a sense, the path can be treated as a list of arcs. The + /// lemon path type stores just this list. As a consequence it + /// cannot enumerate the nodes in the path and the source node of + /// a zero length path is undefined. + /// + /// This implementation is completly static, i.e. it can be copy constucted + /// or copy assigned from another path, but otherwise it cannot be + /// modified. + /// + /// Being the the most memory efficient path type in LEMON, + /// it is intented to be + /// used when you want to store a large number of paths. + template + class StaticPath { + public: + + typedef _Digraph Digraph; + typedef typename Digraph::Arc Arc; + + /// \brief Default constructor + /// + /// Default constructor + StaticPath() : len(0), arcs(0) {} + + /// \brief Template copy constructor + /// + /// This path can be initialized from any other path type. + template + StaticPath(const CPath& cpath) : arcs(0) { + copyPath(*this, cpath); + } + + /// \brief Destructor of the path + /// + /// Destructor of the path + ~StaticPath() { + if (arcs) delete[] arcs; + } + + /// \brief Template copy assignment + /// + /// This path can be made equal to any other path type. It simply + /// makes a copy of the given path. + template + StaticPath& operator=(const CPath& cpath) { + copyPath(*this, cpath); + return *this; + } + + /// \brief Iterator class to iterate on the arcs of the paths + /// + /// This class is used to iterate on the arcs of the paths + /// + /// Of course it converts to Digraph::Arc + class ArcIt { + friend class StaticPath; + public: + /// Default constructor + ArcIt() {} + /// Invalid constructor + ArcIt(Invalid) : path(0), idx(-1) {} + /// Initializate the constructor to the first arc of path + ArcIt(const StaticPath &_path) + : path(&_path), idx(_path.empty() ? -1 : 0) {} + + private: + + /// Constructor with starting point + ArcIt(const StaticPath &_path, int _idx) + : idx(_idx), path(&_path) {} + + public: + + ///Conversion to Digraph::Arc + operator const Arc&() const { + return path->nth(idx); + } + + /// Next arc + ArcIt& operator++() { + ++idx; + if (idx >= path->length()) idx = -1; + return *this; + } + + /// Comparison operator + bool operator==(const ArcIt& e) const { return idx==e.idx; } + /// Comparison operator + bool operator!=(const ArcIt& e) const { return idx!=e.idx; } + /// Comparison operator + bool operator<(const ArcIt& e) const { return idx + void build(const CPath& path) { + len = path.length(); + arcs = new Arc[len]; + int index = 0; + for (typename CPath::ArcIt it(path); it != INVALID; ++it) { + arcs[index] = it; + ++index; + } + } + + template + void buildRev(const CPath& path) { + len = path.length(); + arcs = new Arc[len]; + int index = len; + for (typename CPath::RevArcIt it(path); it != INVALID; ++it) { + --index; + arcs[index] = it; + } + } + + private: + int len; + Arc* arcs; + }; + + /////////////////////////////////////////////////////////////////////// + // Additional utilities + /////////////////////////////////////////////////////////////////////// + + namespace _path_bits { + + template + struct RevTagIndicator { + static const bool value = false; + }; + + template + struct RevTagIndicator< + Digraph, + typename enable_if::type + > { + static const bool value = true; + }; + + template + struct PathCopySelector { + static void copy(Target& target, const Source& source) { + target.clear(); + for (typename Source::ArcIt it(source); it != INVALID; ++it) { + target.addBack(it); + } + } + }; + + template + struct PathCopySelector< + Target, Source, BuildEnable, + typename enable_if::type> { + static void copy(Target& target, const Source& source) { + target.clear(); + for (typename Source::RevArcIt it(source); it != INVALID; ++it) { + target.addFront(it); + } + } + }; + + template + struct PathCopySelector< + Target, Source, + typename enable_if::type, RevEnable> { + static void copy(Target& target, const Source& source) { + target.clear(); + target.build(source); + } + }; + + template + struct PathCopySelector< + Target, Source, + typename enable_if::type, + typename enable_if::type> { + static void copy(Target& target, const Source& source) { + target.clear(); + target.buildRev(source); + } + }; + + } + + + /// \brief Make a copy of a path. + /// + /// This function makes a copy of a path. + template + void copyPath(Target& target, const Source& source) { + checkConcept, Source>(); + _path_bits::PathCopySelector::copy(target, source); + } + + /// \brief Check the consistency of a path. + /// + /// This function checks that the target of each arc is the same + /// as the source of the next one. + /// + template + bool checkPath(const Digraph& digraph, const Path& path) { + typename Path::ArcIt it(path); + if (it == INVALID) return true; + typename Digraph::Node node = digraph.target(it); + ++it; + while (it != INVALID) { + if (digraph.source(it) != node) return false; + node = digraph.target(it); + ++it; + } + return true; + } + + /// \brief The source of a path + /// + /// This function returns the source of the given path. + template + typename Digraph::Node pathSource(const Digraph& digraph, const Path& path) { + return digraph.source(path.front()); + } + + /// \brief The target of a path + /// + /// This function returns the target of the given path. + template + typename Digraph::Node pathTarget(const Digraph& digraph, const Path& path) { + return digraph.target(path.back()); + } + + /// \brief Class which helps to iterate through the nodes of a path + /// + /// In a sense, the path can be treated as a list of arcs. The + /// lemon path type stores only this list. As a consequence, it + /// cannot enumerate the nodes in the path and the zero length paths + /// cannot have a source node. + /// + /// This class implements the node iterator of a path structure. To + /// provide this feature, the underlying digraph should be passed to + /// the constructor of the iterator. + template + class PathNodeIt { + private: + const typename Path::Digraph *_digraph; + typename Path::ArcIt _it; + typename Path::Digraph::Node _nd; + + public: + + typedef typename Path::Digraph Digraph; + typedef typename Digraph::Node Node; + + /// Default constructor + PathNodeIt() {} + /// Invalid constructor + PathNodeIt(Invalid) + : _digraph(0), _it(INVALID), _nd(INVALID) {} + /// Constructor + PathNodeIt(const Digraph& digraph, const Path& path) + : _digraph(&digraph), _it(path) { + _nd = (_it != INVALID ? _digraph->source(_it) : INVALID); + } + /// Constructor + PathNodeIt(const Digraph& digraph, const Path& path, const Node& src) + : _digraph(&digraph), _it(path), _nd(src) {} + + ///Conversion to Digraph::Node + operator Node() const { + return _nd; + } + + /// Next node + PathNodeIt& operator++() { + if (_it == INVALID) _nd = INVALID; + else { + _nd = _digraph->target(_it); + ++_it; + } + return *this; + } + + /// Comparison operator + bool operator==(const PathNodeIt& n) const { + return _it == n._it && _nd == n._nd; + } + /// Comparison operator + bool operator!=(const PathNodeIt& n) const { + return _it != n._it || _nd != n._nd; + } + /// Comparison operator + bool operator<(const PathNodeIt& n) const { + return (_it < n._it && _nd != INVALID); + } + + }; + + ///@} + +} // namespace lemon + +#endif // LEMON_PATH_H