# HG changeset patch # User klao # Date 1082591221 0 # Node ID dc9c19f4ca9ad301230031f3a3ebb4cd3745a857 # Parent 0beed7a490636398513120fdcb415906e17e54c8 Directed path structure. Proposal for a path building interface. diff -r 0beed7a49063 -r dc9c19f4ca9a src/work/klao/path.h --- a/src/work/klao/path.h Wed Apr 21 20:48:00 2004 +0000 +++ b/src/work/klao/path.h Wed Apr 21 23:47:01 2004 +0000 @@ -10,17 +10,204 @@ #define HUGO_PATH_H #include +#include #include #include namespace hugo { + template + class DirPath { + public: + typedef typename Graph::Edge GraphEdge; + typedef typename Graph::Node GraphNode; + class NodeIt; + class EdgeIt; + + protected: + const Graph *gr; + typedef std::vector Container; + Container edges; + + public: + + DirPath(const Graph &_G) : gr(&_G) {} + + /// Subpath defined by two nodes. + /// It is an error if the two edges are not in order! + DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b); + /// Subpath defined by two edges. Contains edges in [a,b) + /// It is an error if the two edges are not in order! + DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b); + + size_t length() const { return edges.size(); } + bool empty() const { return edges.empty(); } + GraphNode from() const { + return empty() ? INVALID : gr->tail(edges[0]); + } + GraphNode to() const { + return empty() ? INVALID : gr->head(edges[length()-1]); + } + + template + It& first(It &i) const { return i=It(*this); } + + template + It& nth(It &i, int n) const { return i=It(*this, n); } + + template + bool valid(const It &i) const { return i.valid(); } + + template + It& next(It &e) const { return ++e; } + + /// \todo ! + NodeIt head(const EdgeIt& e) const; + NodeIt tail(const EdgeIt& e) const; + + + /*** Iterator classes ***/ + class EdgeIt { + friend class DirPath; + + int idx; + const DirPath *p; + public: + EdgeIt() {} + EdgeIt(Invalid) : idx(-1), p(0) {} + EdgeIt(const DirPath &_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= p->length() ) idx=-1; } + }; + + class NodeIt { + friend class DirPath; + + int idx; + const DirPath *p; + public: + NodeIt() {} + NodeIt(Invalid) : idx(-1), p(0) {} + NodeIt(const DirPath &_p, int _idx = 0) : + idx(_idx), p(&_p) { validate(); } + + bool valid() const { return idx!=-1; } + + operator const GraphEdge& () 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 p->length() ) idx=-1; } + }; + + friend class Builder; + class Builder { + DirPath &P; + Container d; + + public: + Builder(DirPath &_P) : P(_P) {} + + bool pushFront(const GraphEdge& e) { + if( empty() || P.gr->head(e)==from() ) { + d.push_back(e); + return true; + } + return false; + } + bool pushBack(const GraphEdge& e) { + if( empty() || P.gr->tail(e)==to() ) { + P.edges.push_back(e); + return true; + } + return false; + } + + void commit() { + if( !d.empty() ) { + P.edges.insert(P.edges.begin(), d.rbegin(), d.rend()); + d.clear(); + } + } + + ~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); + } + + private: + bool empty() { return d.empty() && P.empty(); } + + GraphNode from() const { + if( ! d.empty() ) + return P.gr->tail(d[d.size()-1]); + else if( ! P.empty() ) + return P.gr->tail(P.edges[0]); + else + return INVALID; + } + GraphNode to() const { + if( ! P.empty() ) + return P.gr->head(P.edges[P.length()-1]); + else if( ! d.empty() ) + return P.gr->head(d[0]); + else + return INVALID; + } + + }; + + }; + + + + + + + + + + + + /**********************************************************************/ + + /* Ennek az allocatorosdinak sokkal jobban utana kene nezni a hasznalata elott. Eleg bonyinak nez ki, ahogyan azokat az STL-ben hasznaljak. */ template - class Path { + class DynamicPath { public: typedef typename Graph::Edge GraphEdge; @@ -38,15 +225,15 @@ public: - Path(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {} + DynamicPath(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {} /// Subpath defined by two nodes. /// Nodes may be in reversed order, then /// we contstruct the reversed path. - Path(const Path &P, const NodeIt &a, const NodeIt &b); + DynamicPath(const DynamicPath &P, const NodeIt &a, const NodeIt &b); /// Subpath defined by two edges. Contains edges in [a,b) /// It is an error if the two edges are not in order! - Path(const Path &P, const EdgeIt &a, const EdgeIt &b); + DynamicPath(const DynamicPath &P, const EdgeIt &a, const EdgeIt &b); size_t length() const { return edges.size(); } GraphNode from() const { return _first; } @@ -112,7 +299,7 @@ /*** Iterator classes ***/ class EdgeIt { - friend class Path; + friend class DynamicPath; typename Container::const_iterator it; bool forw; @@ -128,8 +315,7 @@ }; class NodeIt { - friend class Path; - friend class EdgeIt; + friend class DynamicPath; size_t idx; bool tail; // Is this node the tail of the edge with same idx? @@ -150,8 +336,8 @@ }; template - typename Path::EdgeIt& - Path::next(Path::EdgeIt &e) const { + typename DynamicPath::EdgeIt& + DynamicPath::next(DynamicPath::EdgeIt &e) const { if( e.it == edges.end() ) return e; @@ -169,7 +355,7 @@ } template - typename Path::NodeIt& Path::next(NodeIt &n) const { + typename DynamicPath::NodeIt& DynamicPath::next(NodeIt &n) const { if( n.idx >= length() ) { // FIXME: invalid n.idx = length()+1; @@ -191,7 +377,7 @@ } template - bool Path::edgeIncident(const GraphEdge &e, const GraphNode &a, + bool DynamicPath::edgeIncident(const GraphEdge &e, const GraphNode &a, GraphNode &b) { if( G.tail(e) == a ) { b=G.head(e); @@ -205,7 +391,7 @@ } template - bool Path::connectTwoEdges(const GraphEdge &e, + bool DynamicPath::connectTwoEdges(const GraphEdge &e, const GraphEdge &f) { if( edgeIncident(f, G.tail(e), _last) ) { _first = G.head(e); @@ -219,7 +405,7 @@ } template - bool Path::pushFront(const GraphEdge &e) { + bool DynamicPath::pushFront(const GraphEdge &e) { if( G.valid(_first) ) { if( edgeIncident(e, _first, _first) ) { edges.push_front(e); @@ -237,7 +423,7 @@ } template - bool Path::pushBack(const GraphEdge &e) { + bool DynamicPath::pushBack(const GraphEdge &e) { if( G.valid(_last) ) { if( edgeIncident(e, _last, _last) ) { edges.push_back(e); @@ -256,7 +442,7 @@ template - bool Path::setFrom(const GraphNode &n) { + bool DynamicPath::setFrom(const GraphNode &n) { if( G.valid(_first) ) { return _first == n; } @@ -276,7 +462,7 @@ } template - bool Path::setTo(const GraphNode &n) { + bool DynamicPath::setTo(const GraphNode &n) { if( G.valid(_last) ) { return _last == n; } @@ -297,8 +483,8 @@ template - typename Path::NodeIt - Path::tail(const EdgeIt& e) const { + typename DynamicPath::NodeIt + DynamicPath::tail(const EdgeIt& e) const { NodeIt n; if( e.it == edges.end() ) { @@ -314,8 +500,8 @@ } template - typename Path::NodeIt - Path::head(const EdgeIt& e) const { + typename DynamicPath::NodeIt + DynamicPath::head(const EdgeIt& e) const { if( e.it == edges.end()-1 ) { return _last; } @@ -326,8 +512,8 @@ } template - typename Path::GraphEdge - Path::graphEdge(const EdgeIt& e) const { + typename DynamicPath::GraphEdge + DynamicPath::graphEdge(const EdgeIt& e) const { if( e.it != edges.end() ) { return *e.it; } @@ -337,8 +523,8 @@ } template - typename Path::GraphNode - Path::graphNode(const NodeIt& n) const { + typename DynamicPath::GraphNode + DynamicPath::graphNode(const NodeIt& n) const { if( n.idx < length() ) { return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]); } @@ -351,7 +537,8 @@ } template - typename Path::EdgeIt& Path::nth(EdgeIt &e, size_t k) const { + typename DynamicPath::EdgeIt& + DynamicPath::nth(EdgeIt &e, size_t k) const { if( k<0 || k>=length() ) { // FIXME: invalid EdgeIt e.it = edges.end(); @@ -371,7 +558,8 @@ } template - typename Path::NodeIt& Path::nth(NodeIt &n, size_t k) const { + typename DynamicPath::NodeIt& + DynamicPath::nth(NodeIt &n, size_t k) const { if( k<0 || k>length() ) { // FIXME: invalid NodeIt n.idx = length()+1; @@ -391,7 +579,8 @@ template - Path::Path(const Path &P, const EdgeIt &a, const EdgeIt &b) : + DynamicPath::DynamicPath(const DynamicPath &P, const EdgeIt &a, + const EdgeIt &b) : G(P.G), edges(a.it, b.it) // WARNING: if b.it < a.it this will blow up! { if( G.valid(P._first) && a.it < P.edges.end() ) { @@ -406,8 +595,8 @@ } template - Path::Path(const Path &P, const NodeIt &a, const NodeIt &b) : - G(P.G) + DynamicPath::DynamicPath(const DynamicPath &P, const NodeIt &a, + const NodeIt &b) : G(P.G) { if( !P.valid(a) || !P.valid(b) ) return; diff -r 0beed7a49063 -r dc9c19f4ca9a src/work/klao/path_test.cc --- a/src/work/klao/path_test.cc Wed Apr 21 20:48:00 2004 +0000 +++ b/src/work/klao/path_test.cc Wed Apr 21 23:47:01 2004 +0000 @@ -43,137 +43,206 @@ bool rc; - cout << "Ures path letrehozasa" << endl; - typedef Path LPath; - LPath P(G); + { + cout << "DynamicPath tesztelese...\n"; - cout << "P.length() == " << P.length() << endl; - check(P.length() == 0); + cout << "Ures path letrehozasa" << endl; + typedef DynamicPath LPath; + LPath 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 << "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()==s ? " << (P.from()==s) << endl; - check(P.from() == s); + cout << "P.from()==s ? " << (P.from()==s) << endl; + check(P.from() == s); - cout << "Hozzaadunk egy nem illeszkedo elt." << endl; - rc = P.pushBack(e8); - cout << "Sukerult: " << rc << endl; - check(!rc); + cout << "Hozzaadunk egy nem illeszkedo elt." << endl; + rc = P.pushBack(e8); + cout << "Sukerult: " << rc << endl; + check(!rc); - cout << "Meg 3 el hozzaadasa, nem mind elore iranyu..." << endl; - check(P.pushBack(e6)); - check(P.pushBack(e8)); - check(P.pushBack(e10)); + 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() == 5); + cout << "P.length() == " << P.length() << endl; + check(P.length() == 5); - 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 << "P.from()==s ? " << (P.from()==s) << endl; + check(P.from() == s); + cout << "P.to()==t ? " << (P.to()==t) << endl; + check(P.to() == t); - 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 << "Vegpont bellitasa: " << endl; + rc = P.setTo(v2); + cout << "Hibasra: " << rc << endl; + check(!rc); + rc = P.setTo(t); + cout << "Helyesre: " << rc << endl; + check(rc); - cout << "Elek iranyitasanak ellenorzese." << endl; - cout << "El: " << e1 << ", G.tail(el): " << G.head(e1) << endl; - check(G.tail(e1)==s); + 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)); + 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)); + } + + { + 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); + } + } { - cout << "Reszut letrehozasa: [2. el, 4. el)..." << endl; - LPath P2(P, P.nth(1), P.nth(3)); + cout << "\n\n\nDirPath tesztelese...\n"; - cout << "P2.length() == " << P2.length() << endl; - check(P2.length() == 2); + + 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 << "P2.from()==v1 ? " << (P2.from()==v1) << endl; - check(P2.from() == v1); - cout << "P2.to()==v3 ? " << (P2.to()==v3) << endl; - check(P2.to() == v3); + 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 << "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); - } - cout << (passed ? "All tests passed." : "Some of the tests failed!!!") << endl;