[Lemon-commits] [lemon_svn] klao: r804 - hugo/trunk/src/work/klao
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:41:35 CET 2006
Author: klao
Date: Wed May 12 00:50:09 2004
New Revision: 804
Modified:
hugo/trunk/src/work/klao/debug.h
hugo/trunk/src/work/klao/path.h
Log:
path improvements
Modified: hugo/trunk/src/work/klao/debug.h
==============================================================================
--- hugo/trunk/src/work/klao/debug.h (original)
+++ hugo/trunk/src/work/klao/debug.h Wed May 12 00:50:09 2004
@@ -18,12 +18,15 @@
//! after deleting an item from UnionFindEnum set its value in the
//! corresponding map to NULL...
static const bool ensure_safe_state = true;
+
+ static const int verbose = 5;
};
struct DebugOff {
static const bool consistensy_check = false;
static const bool range_check = false;
static const bool ensure_safe_state = false;
+ static const int verbose = 0;
};
#ifdef DEBUG
Modified: hugo/trunk/src/work/klao/path.h
==============================================================================
--- hugo/trunk/src/work/klao/path.h (original)
+++ hugo/trunk/src/work/klao/path.h Wed May 12 00:50:09 2004
@@ -23,6 +23,7 @@
//! \brief A structure for representing directed path in a graph.
//!
+ //! A structure for representing directed path in a graph.
//! \param Graph The graph type in which the path is.
//! \param DM DebugMode, defaults to DefaultDebugMode.
//!
@@ -54,14 +55,27 @@
///
/// Subpath defined by two nodes.
/// \warning It is an error if the two edges are not in order!
- /// \todo Implement!
- DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b);
+ DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) {
+ if( DM::range_check && (!a.valid() || !b.valid) ) {
+ // FIXME: this check should be more elaborate...
+ fault("DirPath, subpath ctor: invalid bounding nodes");
+ }
+ gr = P.gr;
+ edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
+ }
+
/// \brief Subpath constructor.
///
/// Subpath defined by two edges. Contains edges in [a,b)
/// \warning It is an error if the two edges are not in order!
- /// \todo Implement!
- DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b);
+ DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) {
+ if( DM::range_check && (!a.valid() || !b.valid) ) {
+ // FIXME: this check should be more elaborate...
+ fault("DirPath, subpath ctor: invalid bounding nodes");
+ }
+ gr = P.gr;
+ edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
+ }
/// Length of the path.
size_t length() const { return edges.size(); }
@@ -93,23 +107,29 @@
template<typename It>
It& first(It &i) const { return i=It(*this); }
- /// \brief Initializes node or edge iterator to point to the node or edge
- /// of a given index.
- template<typename It>
- It& nth(It &i, int n) const {
- // FIXME: this test should be different for NodeIt and EdgeIt:
+ /// \brief Initializes node iterator to point to the node of a given index.
+ NodeIt& nth(NodeIt &i, int n) const {
if( DM::range_check && (n<0 || n>int(length())) )
fault("DirPath::nth: index out of range");
- return i=It(*this, n);
+ return i=NodeIt(*this, n);
+ }
+
+ /// \brief Initializes edge iterator to point to the edge of a given index.
+ EdgeIt& nth(EdgeIt &i, int n) const {
+ if( DM::range_check && (n<0 || n>=int(length())) )
+ fault("DirPath::nth: index out of range");
+ return i=EdgeIt(*this, n);
}
/// Checks validity of a node or edge iterator.
template<typename It>
- bool valid(const It &i) const { return i.valid(); }
+ static
+ bool valid(const It &i) { return i.valid(); }
/// Steps the given node or edge iterator.
template<typename It>
- It& next(It &e) const {
+ static
+ It& next(It &e) {
if( DM::range_check && !e.valid() )
fault("DirPath::next() on invalid iterator");
return ++e;
@@ -118,12 +138,16 @@
/// \brief Returns node iterator pointing to the head node of the
/// given edge iterator.
NodeIt head(const EdgeIt& e) const {
+ if( DM::range_check && !e.valid() )
+ fault("DirPath::head() on invalid iterator");
return NodeIt(*this, e.idx+1);
}
/// \brief Returns node iterator pointing to the tail node of the
/// given edge iterator.
NodeIt tail(const EdgeIt& e) const {
+ if( DM::range_check && !e.valid() )
+ fault("DirPath::tail() on invalid iterator");
return NodeIt(*this, e.idx);
}
@@ -170,7 +194,7 @@
bool valid() const { return idx!=-1; }
- operator const GraphEdge& () const {
+ operator const GraphNode& () const {
if(idx >= p->length())
return p->to();
else if(idx >= 0)
@@ -197,7 +221,7 @@
* This class is used to fill a path with edges.
*
* You can push new edges to the front and to the back of the path in
- * arbitrary order the you can commit these changes to the graph.
+ * arbitrary order then you should commit these changes to the graph.
*
* Fundamentally, for most "Paths" (classes fulfilling the
* PathConcept) while the builder is active (after the first modifying
@@ -215,24 +239,18 @@
///
Builder(DirPath &_P) : P(_P) {}
- ///Sets the first node of the path.
-
- ///Sets the first node of the path. If the path is empty, this
- ///function or setTo() have to be called before any call to \ref
- ///pushFront() or \ref pushBack()
- void setFrom(const GraphNode &) {}
-
- ///Sets the last node of the path.
-
- ///Sets the last node of the path. If the path is empty, this
- ///function or setFrom() have to be called before any call of \ref
- ///pushFront() or \ref pushBack()
- void setTo(const GraphNode &) {}
+ /// Sets the starting node of the path.
+ /// Sets the starting node of the path. Edge added to the path
+ /// afterwards have to be incident to this node.
+ /// It should be called iff the path is empty and before any call to
+ /// \ref pushFront() or \ref pushBack()
+ void setStart(const GraphNode &) {}
+
///Push a new edge to the front of the path
///Push a new edge to the front of the path.
- ///\sa setTo
+ ///\sa setStart
void pushFront(const GraphEdge& e) {
if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
fault("DirPath::Builder::pushFront: nonincident edge");
@@ -243,7 +261,7 @@
///Push a new edge to the back of the path
///Push a new edge to the back of the path.
- ///\sa setFrom
+ ///\sa setStart
void pushBack(const GraphEdge& e) {
if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
fault("DirPath::Builder::pushBack: nonincident edge");
@@ -265,13 +283,319 @@
}
}
-// ///Desctuctor
+ // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
+ // Hogy kenyelmes egy ilyet hasznalni?
+ void reserve(size_t r) {
+ front.reserve(r);
+ back.reserve(r);
+ }
+
+ private:
+ bool empty() {
+ return front.empty() && back.empty() && P.empty();
+ }
+
+ GraphNode from() const {
+ if( ! front.empty() )
+ return P.gr->tail(front[front.size()-1]);
+ else if( ! P.empty() )
+ return P.gr->tail(P.edges[0]);
+ else if( ! back.empty() )
+ return P.gr->tail(back[0]);
+ else
+ return INVALID;
+ }
+ GraphNode to() const {
+ if( ! back.empty() )
+ return P.gr->head(back[back.size()-1]);
+ else if( ! P.empty() )
+ return P.gr->head(P.edges[P.length()-1]);
+ else if( ! front.empty() )
+ return P.gr->head(front[0]);
+ else
+ return INVALID;
+ }
+
+ };
+
+ };
+
+
+
+
+
+
+
+
+
+
+ /**********************************************************************/
+
+
+ //! \brief A structure for representing undirected path in a graph.
+ //!
+ //! A structure for representing undirected path in a graph. Ie. this is
+ //! a path in a \e directed graph but the edges should not be directed
+ //! forward.
+ //!
+ //! \param Graph The graph type in which the path is.
+ //! \param DM DebugMode, defaults to DefaultDebugMode.
+ //!
+ //! In a sense, the path can be treated as a graph, for is has \c NodeIt
+ //! and \c EdgeIt with the same usage. These types converts to the \c Node
+ //! and \c Edge of the original graph.
+ //!
+ //! \todo Thoroughfully check all the range and consistency tests.
+ template<typename Graph, typename DM = DefaultDebugMode>
+ class UndirPath {
+ public:
+ typedef typename Graph::Edge GraphEdge;
+ typedef typename Graph::Node GraphNode;
+ class NodeIt;
+ class EdgeIt;
+
+ protected:
+ const Graph *gr;
+ typedef std::vector<GraphEdge> Container;
+ Container edges;
+
+ public:
+
+ /// \param _G The graph in which the path is.
+ ///
+ UndirPath(const Graph &_G) : gr(&_G) {}
+
+ /// \brief Subpath constructor.
+ ///
+ /// Subpath defined by two nodes.
+ /// \warning It is an error if the two edges are not in order!
+ UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) {
+ if( DM::range_check && (!a.valid() || !b.valid) ) {
+ // FIXME: this check should be more elaborate...
+ fault("UndirPath, subpath ctor: invalid bounding nodes");
+ }
+ gr = P.gr;
+ edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
+ }
+
+ /// \brief Subpath constructor.
+ ///
+ /// Subpath defined by two edges. Contains edges in [a,b)
+ /// \warning It is an error if the two edges are not in order!
+ UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) {
+ if( DM::range_check && (!a.valid() || !b.valid) ) {
+ // FIXME: this check should be more elaborate...
+ fault("UndirPath, subpath ctor: invalid bounding nodes");
+ }
+ gr = P.gr;
+ edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
+ }
+
+ /// Length of the path.
+ size_t length() const { return edges.size(); }
+ /// Returns whether the path is empty.
+ bool empty() const { return edges.empty(); }
+
+ /// Resets the path to an empty path.
+ void clear() { edges.clear(); }
+
+ /// \brief Starting point of the path.
+ ///
+ /// Starting point of the path.
+ /// Returns INVALID if the path is empty.
+ GraphNode from() const {
+ return empty() ? INVALID : gr->tail(edges[0]);
+ }
+ /// \brief End point of the path.
+ ///
+ /// End point of the path.
+ /// Returns INVALID if the path is empty.
+ GraphNode to() const {
+ return empty() ? INVALID : gr->head(edges[length()-1]);
+ }
+
+ /// \brief Initializes node or edge iterator to point to the first
+ /// node or edge.
+ ///
+ /// \sa nth
+ template<typename It>
+ It& first(It &i) const { return i=It(*this); }
+
+ /// \brief Initializes node iterator to point to the node of a given index.
+ NodeIt& nth(NodeIt &i, int n) const {
+ if( DM::range_check && (n<0 || n>int(length())) )
+ fault("UndirPath::nth: index out of range");
+ return i=NodeIt(*this, n);
+ }
+
+ /// \brief Initializes edge iterator to point to the edge of a given index.
+ EdgeIt& nth(EdgeIt &i, int n) const {
+ if( DM::range_check && (n<0 || n>=int(length())) )
+ fault("UndirPath::nth: index out of range");
+ return i=EdgeIt(*this, n);
+ }
+
+ /// Checks validity of a node or edge iterator.
+ template<typename It>
+ static
+ bool valid(const It &i) { return i.valid(); }
+
+ /// Steps the given node or edge iterator.
+ template<typename It>
+ static
+ It& next(It &e) {
+ if( DM::range_check && !e.valid() )
+ fault("UndirPath::next() on invalid iterator");
+ return ++e;
+ }
+
+ /// \brief Returns node iterator pointing to the head node of the
+ /// given edge iterator.
+ NodeIt head(const EdgeIt& e) const {
+ if( DM::range_check && !e.valid() )
+ fault("UndirPath::head() on invalid iterator");
+ return NodeIt(*this, e.idx+1);
+ }
+
+ /// \brief Returns node iterator pointing to the tail node of the
+ /// given edge iterator.
+ NodeIt tail(const EdgeIt& e) const {
+ if( DM::range_check && !e.valid() )
+ fault("UndirPath::tail() on invalid iterator");
+ return NodeIt(*this, e.idx);
+ }
+
+
+ /*** Iterator classes ***/
+ class EdgeIt {
+ friend class UndirPath;
+
+ int idx;
+ const UndirPath *p;
+ public:
+ EdgeIt() {}
+ EdgeIt(Invalid) : idx(-1), p(0) {}
+ EdgeIt(const UndirPath &_p, int _idx = 0) :
+ idx(_idx), p(&_p) { validate(); }
+
+ bool valid() const { return idx!=-1; }
+
+ operator GraphEdge () const {
+ return valid() ? p->edges[idx] : INVALID;
+ }
+ EdgeIt& operator++() { ++idx; validate(); return *this; }
+
+ bool operator==(const EdgeIt& e) const { return idx==e.idx; }
+ bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
+ bool operator<(const EdgeIt& e) const { return idx<e.idx; }
+
+ private:
+ // FIXME: comparison between signed and unsigned...
+ // Jo ez igy? Vagy esetleg legyen a length() int?
+ void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
+ };
+
+ class NodeIt {
+ friend class UndirPath;
+
+ int idx;
+ const UndirPath *p;
+ public:
+ NodeIt() {}
+ NodeIt(Invalid) : idx(-1), p(0) {}
+ NodeIt(const UndirPath &_p, int _idx = 0) :
+ idx(_idx), p(&_p) { validate(); }
+
+ bool valid() const { return idx!=-1; }
+
+ operator const GraphNode& () const {
+ if(idx >= p->length())
+ return p->to();
+ else if(idx >= 0)
+ return p->gr->tail(p->edges[idx]);
+ else
+ return INVALID;
+ }
+ NodeIt& operator++() { ++idx; validate(); return *this; }
+
+ bool operator==(const NodeIt& e) const { return idx==e.idx; }
+ bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
+ bool operator<(const NodeIt& e) const { return idx<e.idx; }
+
+ private:
+ void validate() { if( size_t(idx) > p->length() ) idx=-1; }
+ };
+
+ friend class Builder;
+
+ /**
+ * \brief Class to build paths
+ *
+ * \ingroup datas
+ * This class is used to fill a path with edges.
+ *
+ * You can push new edges to the front and to the back of the path in
+ * arbitrary order then you should commit these changes to the graph.
+ *
+ * Fundamentally, for most "Paths" (classes fulfilling the
+ * PathConcept) while the builder is active (after the first modifying
+ * operation and until the commit()) the original Path is in a
+ * "transitional" state (operations ot it have undefined result). But
+ * in the case of UndirPath the original path is unchanged until the
+ * commit. However we don't recomend that you use this feature.
+ */
+ class Builder {
+ UndirPath &P;
+ Container front, back;
+
+ public:
+ ///\param _P the path you want to fill in.
+ ///
+ Builder(UndirPath &_P) : P(_P) {}
+
+ /// Sets the starting node of the path.
+
+ /// Sets the starting node of the path. Edge added to the path
+ /// afterwards have to be incident to this node.
+ /// It should be called iff the path is empty and before any call to
+ /// \ref pushFront() or \ref pushBack()
+ void setStart(const GraphNode &) {}
+
+ ///Push a new edge to the front of the path
+
+ ///Push a new edge to the front of the path.
+ ///\sa setStart
+ void pushFront(const GraphEdge& e) {
+ if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
+ fault("UndirPath::Builder::pushFront: nonincident edge");
+ }
+ front.push_back(e);
+ }
+
+ ///Push a new edge to the back of the path
+
+ ///Push a new edge to the back of the path.
+ ///\sa setStart
+ void pushBack(const GraphEdge& e) {
+ if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
+ fault("UndirPath::Builder::pushBack: nonincident edge");
+ }
+ back.push_back(e);
+ }
-// ///The desctuctor.
-// ///It commit also commit the changes.
-// ///\todo Is this what we want?
-// Nope. Let's use commit() explicitly.
-// ~Builder() { commit(); }
+ ///Commit the changes to the path.
+ void commit() {
+ if( !(front.empty() && back.empty()) ) {
+ Container tmp;
+ tmp.reserve(front.size()+back.size()+P.length());
+ tmp.insert(tmp.end(), front.rbegin(), front.rend());
+ tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
+ tmp.insert(tmp.end(), back.begin(), back.end());
+ P.edges.swap(tmp);
+ front.clear();
+ back.clear();
+ }
+ }
// FIXME: Hmm, pontosan hogy is kene ezt csinalni?
// Hogy kenyelmes egy ilyet hasznalni?
More information about the Lemon-commits
mailing list