# HG changeset patch # User klao # Date 1083290355 0 # Node ID bbd1db03f0fefa8225345ff86d74204bd9b3c8ec # Parent d649b43e2dc0a35e27a628e4152d75d899fdc8de DirPath fejlodes. Kiserleti struktura a forditasi idoben kapcsolhato konzisztencia es range ellenorzesekre. diff -r d649b43e2dc0 -r bbd1db03f0fe src/work/klao/debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/klao/debug.h Fri Apr 30 01:59:15 2004 +0000 @@ -0,0 +1,36 @@ +// -*- C++ -*- // + +#ifndef HUGO_DEBUG_H +#define HUGO_DEBUG_H + +//! \file +//! \brief Basic definitions for debug control. + +namespace hugo { + + struct DebugOn { + //! Example: check whether the edges added to a path are adjacent + static const bool consistensy_check = true; + + static const bool range_check = true; + + //! Examples: initialize maps with some value; + //! after deleting an item from UnionFindEnum set its value in the + //! corresponding map to NULL... + static const bool ensure_safe_state = true; + }; + + struct DebugOff { + static const bool consistensy_check = false; + static const bool range_check = false; + static const bool ensure_safe_state = false; + }; + +#ifdef DEBUG + typedef DebugOn DefaultDebugMode; +#else + typedef DebugOff DefaultDebugMode; +#endif + +} +#endif // HUGO_DEBUG_H diff -r d649b43e2dc0 -r bbd1db03f0fe src/work/klao/path.h --- a/src/work/klao/path.h Fri Apr 30 01:10:13 2004 +0000 +++ b/src/work/klao/path.h Fri Apr 30 01:59:15 2004 +0000 @@ -1,8 +1,8 @@ // -*- c++ -*- // -///ingroup datas +///\ingroup datas ///\file -///\brief Class for representing paths in graphs. +///\brief Classes for representing paths in graphs. #ifndef HUGO_PATH_H #define HUGO_PATH_H @@ -12,22 +12,26 @@ #include #include +#include +#include namespace hugo { /// \addtogroup datas /// @{ - ///A container for directed paths - ///\param Graph The graph type in which the path is. - /// - ///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 How to clear a path? - ///\todo Clarify the consistency checks to do. - template + //! \brief 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. + //! + //! 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 class DirPath { public: typedef typename Graph::Edge GraphEdge; @@ -42,43 +46,86 @@ public: - /// Constructor - /// \param _G The graph in which the path is. /// DirPath(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! + /// \todo Implement! DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b); + /// \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); + /// 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 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 - It& nth(It &i, int n) const { return i=It(*this, n); } + It& nth(It &i, int n) const { + // FIXME: this test should be different for NodeIt and EdgeIt: + if( DM::range_check && (n<0 || n>int(length())) ) + fault("DirPath::nth: index out of range"); + return i=It(*this, n); + } + /// Checks validity of a node or edge iterator. template bool valid(const It &i) const { return i.valid(); } + /// Steps the given node or edge iterator. template - It& next(It &e) const { return ++e; } + It& next(It &e) const { + if( DM::range_check && !e.valid() ) + fault("DirPath::next() on invalid iterator"); + return ++e; + } - /// \todo ! - NodeIt head(const EdgeIt& e) const; - NodeIt tail(const EdgeIt& e) const; + /// \brief Returns node iterator pointing to the head node of the + /// given edge iterator. + NodeIt head(const EdgeIt& e) const { + 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 { + return NodeIt(*this, e.idx); + } /*** Iterator classes ***/ @@ -143,92 +190,118 @@ friend class Builder; - ///Class to build paths - - ///\ingroup datas - ///This class is used to build new paths. - ///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. - ///\todo We must clarify when the path will be in "transitional" state. + /** + * \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 the you can 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 DirPath the original path is unchanged until the + * commit. However we don't recomend that you use this feature. + */ class Builder { DirPath &P; - Container d; + Container front, back; public: - ///Constructor - - ///\param _P the path you want to build. + ///\param _P the path you want to fill in. /// Builder(DirPath &_P) : P(_P) {} - ///Set the first node of the path. + ///Sets the first node of the path. - ///Set the first node of the path. - ///If the path is empty, this must be call before any call of - ///\ref pushFront() or \ref pushBack() - void setFirst(const GraphNode &) { } + ///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 &) {} ///Push a new edge to the front of the path ///Push a new edge to the front of the path. - ///\sa setFirst() - bool pushFront(const GraphEdge& e) { - if( empty() || P.gr->head(e)==from() ) { - d.push_back(e); - return true; + ///\sa setTo + void pushFront(const GraphEdge& e) { + if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) { + fault("DirPath::Builder::pushFront: nonincident edge"); } - return false; + 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 setFirst() - bool pushBack(const GraphEdge& e) { - if( empty() || P.gr->tail(e)==to() ) { - P.edges.push_back(e); - return true; + ///\sa setFrom + void pushBack(const GraphEdge& e) { + if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) { + fault("DirPath::Builder::pushBack: nonincident edge"); } - return false; + back.push_back(e); } ///Commit the changes to the path. void commit() { - if( !d.empty() ) { - P.edges.insert(P.edges.begin(), d.rbegin(), d.rend()); - d.clear(); + 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(); } } - ///Desctuctor +// ///Desctuctor - ///The desctuctor. - ///It commit also commit the changes. - ///\todo Is this what we want? - ~Builder() { commit(); } +// ///The desctuctor. +// ///It commit also commit the changes. +// ///\todo Is this what we want? +// Nope. Let's use commit() explicitly. +// ~Builder() { commit(); } // FIXME: Hmm, pontosan hogy is kene ezt csinalni? // Hogy kenyelmes egy ilyet hasznalni? void reserve(size_t r) { - d.reserve(r); - P.edges.reserve(P.length()+r); + front.reserve(r); + back.reserve(r); } private: - bool empty() { return d.empty() && P.empty(); } + bool empty() { + return front.empty() && back.empty() && P.empty(); + } GraphNode from() const { - if( ! d.empty() ) - return P.gr->tail(d[d.size()-1]); + 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( ! P.empty() ) + 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( ! d.empty() ) - return P.gr->head(d[0]); + else if( ! front.empty() ) + return P.gr->head(front[0]); else return INVALID; } diff -r d649b43e2dc0 -r bbd1db03f0fe src/work/klao/path_test.cc --- a/src/work/klao/path_test.cc Fri Apr 30 01:10:13 2004 +0000 +++ b/src/work/klao/path_test.cc Fri Apr 30 01:59:15 2004 +0000 @@ -16,233 +16,142 @@ } } +#ifdef DEBUG +const bool debug = true; +#else +const bool debug = false; +#endif + + int main() { - typedef ListGraph::Node Node; - typedef ListGraph::Edge Edge; + try { - ListGraph G; + typedef ListGraph::Node Node; + typedef ListGraph::Edge Edge; - Node s=G.addNode(); - Node v1=G.addNode(); - Node v2=G.addNode(); - Node v3=G.addNode(); - Node v4=G.addNode(); - Node t=G.addNode(); + ListGraph G; + + Node s=G.addNode(); + Node v1=G.addNode(); + Node v2=G.addNode(); + Node v3=G.addNode(); + Node v4=G.addNode(); + Node t=G.addNode(); - Edge e1 = G.addEdge(s, v1); - Edge e2 = G.addEdge(s, v2); - Edge e3 = G.addEdge(v1, v2); - Edge e4 = G.addEdge(v2, v1); - Edge e5 = G.addEdge(v1, v3); - Edge e6 = G.addEdge(v3, v2); - Edge e7 = G.addEdge(v2, v4); - Edge e8 = G.addEdge(v4, v3); - Edge e9 = G.addEdge(v3, t); - Edge e10 = G.addEdge(v4, t); + Edge e1 = G.addEdge(s, v1); + Edge e2 = G.addEdge(s, v2); + Edge e3 = G.addEdge(v1, v2); + Edge e4 = G.addEdge(v2, v1); + Edge e5 = G.addEdge(v1, v3); + Edge e6 = G.addEdge(v3, v2); + Edge e7 = G.addEdge(v2, v4); + Edge e8 = G.addEdge(v4, v3); + Edge e9 = G.addEdge(v3, t); + Edge e10 = G.addEdge(v4, t); - bool rc; + bool rc; - { - cout << "DynamicPath tesztelese...\n"; + { + cout << "\n\n\nDirPath tesztelese...\n"; - cout << "Ures path letrehozasa" << endl; - typedef DynamicPath LPath; - LPath P(G); - cout << "P.length() == " << P.length() << endl; - check(P.length() == 0); + cout << "Ures path letrehozasa" << endl; + typedef DirPath DPath; + DPath P(G); - cout << "P.from() valid? " << G.valid(P.from()) << endl; - check(! G.valid(P.from())); + cout << "P.length() == " << P.length() << endl; + check(P.length() == 0); - cout << "Hozzaadunk ket elet..." << endl; - check(P.pushBack(e1)); - check(P.pushBack(e3)); - cout << "P.length() == " << P.length() << endl; - check(P.length() == 2); + cout << "P.from() valid? " << G.valid(P.from()) << endl; + check(! G.valid(P.from())); - cout << "P.from() valid? " << G.valid(P.from()) << endl; - check(G.valid(P.from())); - - cout << "P.from()==s ? " << (P.from()==s) << endl; - check(P.from() == s); + { + cout << "Builder objektum letrehozasa" << endl; + DPath::Builder B(P); - cout << "Hozzaadunk egy nem illeszkedo elt." << endl; - rc = P.pushBack(e8); - cout << "Sukerult: " << rc << endl; - check(!rc); + cout << "Hozzaadunk az elejehez ket elet..." << endl; + B.pushFront(e6); + B.pushFront(e5); + cout << "P.length() == " << P.length() << endl; + check(P.length() == 0); + + cout << "Commitolunk..." << endl; + B.commit(); - cout << "Meg 3 el hozzaadasa, nem mind elore iranyu..." << endl; - check(P.pushBack(e6)); - check(P.pushBack(e8)); - check(P.pushBack(e10)); + cout << "P.length() == " << P.length() << endl; + check(P.length() == 2); + cout << "P.from() valid? " << G.valid(P.from()) << endl; + check(G.valid(P.from())); + cout << "P.from()==v1 ? " << (P.from()==v1) << endl; + check(P.from() == v1); - cout << "P.length() == " << P.length() << endl; - check(P.length() == 5); + // Na ja, ez igy nem igazi, mindket esetet le kene tesztelni, + // de legalabb valami: +#ifdef DEBUG + cout << "Hozzaadunk az elejehez egy nem illeszkedo elet..." << endl; + rc = false; + try { + B.pushFront(e3); + } + catch(const Exception &e) { + cout << "E: " << e.what() << endl; + rc = true; + } + check(rc); +#endif - cout << "P.from()==s ? " << (P.from()==s) << endl; - check(P.from() == s); - cout << "P.to()==t ? " << (P.to()==t) << endl; - check(P.to() == t); + cout << "Hozzaadunk a vegehez ket elet..." << endl; + B.pushBack(e7); + B.pushBack(e8); + cout << "P.length() == " << P.length() << endl; + check(P.length() == 2); + + cout << "Es commitolunk...\n"; + B.commit(); + } + cout << "P.length() == " << P.length() << endl; + check(P.length() == 4); + cout << "P.to()==v3 ? " << (P.to()==v3) << endl; + check(P.to() == v3); - cout << "Vegpont bellitasa: " << endl; - rc = P.setTo(v2); - cout << "Hibasra: " << rc << endl; - check(!rc); - rc = P.setTo(t); - cout << "Helyesre: " << rc << endl; - check(rc); + cout << "Vegigiteralunk az eleken." << endl; + typedef DPath::NodeIt NodeIt; + typedef DPath::EdgeIt EdgeIt; + EdgeIt e; + int i=1; + for(P.first(e); P.valid(e); P.next(e), ++i) { + cout << i << ". el: " << e << endl; + } - cout << "Elek iranyitasanak ellenorzese." << endl; - cout << "El: " << e1 << ", G.tail(el): " << G.head(e1) << endl; - check(G.tail(e1)==s); - cout << "Vegigiteralunk az eleken." << endl; - typedef LPath::NodeIt NodeIt; - typedef LPath::EdgeIt EdgeIt; - EdgeIt e = P.first(); - int i=1; - for(; P.valid(e); P.next(e), ++i) { - cout << i << ". el: " << P.graphEdge(e) - << ", elore el? " << P.isForward(e) << endl; - if(i>=3 && i<5) - check(!P.isForward(e)); - else - check(P.isForward(e)); + // Na ja, ez igy nem igazi, mindket esetet le kene tesztelni, + // de legalabb valami: + rc = false; + try { + cout << "Setting an edgeiter to a nonexistant edge." << endl; + P.nth(e,134); + rc = !debug; + } + catch(const Exception &e) { + cout << "E: " << e.what() << endl; + rc = debug; + } + check(rc); } - { - cout << "Reszut letrehozasa: [2. el, 4. el)..." << endl; - LPath P2(P, P.nth(1), P.nth(3)); - - cout << "P2.length() == " << P2.length() << endl; - check(P2.length() == 2); - - cout << "P2.from()==v1 ? " << (P2.from()==v1) << endl; - check(P2.from() == v1); - cout << "P2.to()==v3 ? " << (P2.to()==v3) << endl; - check(P2.to() == v3); - } - { - cout << "Reszut letrehozasa: [1. el, 6. el)..." << endl; - LPath P2(P, P.nth(0), P.nth(5)); - - cout << "P2.length() == " << P2.length() << endl; - check(P2.length() == 5); - - cout << "P2.from()==s ? " << (P2.from()==s) << endl; - check(P2.from() == s); - cout << "P2.to()==t ? " << (P2.to()==t) << endl; - check(P2.to() == t); - } - - { - cout << "Ket pont altal megadott reszut letrehozasa: [2. pont, 4. pont]..." - << endl; - LPath P2(P, P.nth(1), P.nth(3)); - - cout << "P2.length() == " << P2.length() << endl; - check(P2.length() == 2); - - cout << "P2.from()==v1 ? " << (P2.from()==v1) << endl; - check(P2.from() == v1); - cout << "P2.to()==v3 ? " << (P2.to()==v3) << endl; - check(P2.to() == v3); - } - { - cout << "Egy pontu reszut letrehozasa: [4. pont, 4. pont]..." - << endl; - LPath P2(P, P.nth(3), P.nth(3)); - - cout << "P2.length() == " << P2.length() << endl; - check(P2.length() == 0); - - cout << "P2.from()==v3 ? " << (P2.from()==v3) << endl; - check(P2.from() == v3); - cout << "P2.to()==v3 ? " << (P2.to()==v3) << endl; - check(P2.to() == v3); - } - { - cout << "Forditott ut letrehozasa: [6. pont, 1. pont]..." - << endl; - LPath P2(P, P.nth(5), P.nth(0)); - - cout << "P2.length() == " << P2.length() << endl; - check(P2.length() == 5); - - cout << "P2.from()==t ? " << (P2.from()==t) << endl; - check(P2.from() == t); - cout << "P2.to()==s ? " << (P2.to()==s) << endl; - check(P2.to() == s); - } } + catch(const std::exception &e) { + cout << "Uncaught exception: " << e.what() << endl; + return 1; + } + catch(...) { + cout << "Something horrible happened: an exception which isn't " + << "std::exception" << endl; + return 2; + } - { - cout << "\n\n\nDirPath tesztelese...\n"; - - - cout << "Ures path letrehozasa" << endl; - typedef DirPath DPath; - DPath P(G); - - cout << "P.length() == " << P.length() << endl; - check(P.length() == 0); - - cout << "P.from() valid? " << G.valid(P.from()) << endl; - check(! G.valid(P.from())); - - { - cout << "Builder objektum letrehozasa" << endl; - DPath::Builder B(P); - - cout << "Hozzaadunk az elejehez ket elet..." << endl; - check(B.pushFront(e6)); - check(B.pushFront(e5)); - cout << "P.length() == " << P.length() << endl; - check(P.length() == 0); - - cout << "Commitolunk..." << endl; - B.commit(); - - cout << "P.length() == " << P.length() << endl; - check(P.length() == 2); - cout << "P.from() valid? " << G.valid(P.from()) << endl; - check(G.valid(P.from())); - cout << "P.from()==v1 ? " << (P.from()==v1) << endl; - check(P.from() == v1); - - cout << "Hozzaadunk az elejehez egy nem illeszkedo elet..." << endl; - check(!B.pushFront(e3)); - - cout << "Hozzaadunk a vegehez ket elet..." << endl; - check(B.pushBack(e7)); - check(B.pushBack(e8)); - cout << "P.length() == " << P.length() << endl; - check(P.length() == 4); - - cout << "Hozzaadunk az elejehez meg egy elet..." << endl; - check(B.pushFront(e4)); - cout << "P.length() == " << P.length() << endl; - check(P.length() == 4); - - cout << "Es megvarjuk, amig megszunik a Builder...\n"; - } - cout << "P.length() == " << P.length() << endl; - check(P.length() == 5); - cout << "P.from()==v2 ? " << (P.from()==v2) << endl; - check(P.from() == v2); - - cout << "Vegigiteralunk az eleken." << endl; - typedef DPath::NodeIt NodeIt; - typedef DPath::EdgeIt EdgeIt; - EdgeIt e; - int i=1; - for(P.first(e); P.valid(e); P.next(e), ++i) { - cout << i << ". el: " << e << endl; - } - } cout << (passed ? "All tests passed." : "Some of the tests failed!!!") << endl; diff -r d649b43e2dc0 -r bbd1db03f0fe src/work/makefile --- a/src/work/makefile Fri Apr 30 01:10:13 2004 +0000 +++ b/src/work/makefile Fri Apr 30 01:59:15 2004 +0000 @@ -11,6 +11,10 @@ CXX := $(shell type -p g++-3.3 || type -p g++-3.2 || type -p g++-3.0 || type -p g++-3 || echo g++) endif +ifdef DEBUG +CXXFLAGS += -DDEBUG +endif + CC := $(CXX)