path.h

Go to the documentation of this file.
00001 /* -*- C++ -*- 00002 * src/lemon/path.h - Part of LEMON, a generic C++ optimization library 00003 * 00004 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport 00005 * (Egervary Combinatorial Optimization Research Group, EGRES). 00006 * 00007 * Permission to use, modify and distribute this software is granted 00008 * provided that this copyright notice appears in all copies. For 00009 * precise terms see the accompanying LICENSE file. 00010 * 00011 * This software is provided "AS IS" with no warranty of any kind, 00012 * express or implied, and with no claim as to its suitability for any 00013 * purpose. 00014 * 00015 */ 00016 00033 00034 00035 00036 00037 #ifndef LEMON_PATH_H 00038 #define LEMON_PATH_H 00039 00040 #include <deque> 00041 #include <vector> 00042 #include <algorithm> 00043 00044 #include <lemon/invalid.h> 00045 00046 namespace lemon { 00047 00050 00051 00063 template<typename Graph> 00064 class DirPath { 00065 public: 00067 typedef typename Graph::Edge GraphEdge; 00069 typedef typename Graph::Node GraphNode; 00070 class NodeIt; 00071 class EdgeIt; 00072 00073 protected: 00074 const Graph *gr; 00075 typedef std::vector<GraphEdge> Container; 00076 Container edges; 00077 00078 public: 00079 00082 DirPath(const Graph &_G) : gr(&_G) {} 00083 00088 DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) { 00089 gr = P.gr; 00090 edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); 00091 } 00092 00097 DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) { 00098 gr = P.gr; 00099 edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); 00100 } 00101 00103 size_t length() const { return edges.size(); } 00105 bool empty() const { return edges.empty(); } 00106 00108 void clear() { edges.clear(); } 00109 00114 GraphNode tail() const { 00115 return empty() ? INVALID : gr->tail(edges[0]); 00116 } 00121 GraphNode head() const { 00122 return empty() ? INVALID : gr->head(edges[length()-1]); 00123 } 00124 00129 template<typename It> 00130 It& first(It &i) const { return i=It(*this); } 00131 00133 NodeIt& nth(NodeIt &i, int n) const { 00134 return i=NodeIt(*this, n); 00135 } 00136 00138 EdgeIt& nth(EdgeIt &i, int n) const { 00139 return i=EdgeIt(*this, n); 00140 } 00141 00144 NodeIt head(const EdgeIt& e) const { 00145 return NodeIt(*this, e.idx+1); 00146 } 00147 00150 NodeIt tail(const EdgeIt& e) const { 00151 return NodeIt(*this, e.idx); 00152 } 00153 00154 00155 /* Iterator classes */ 00156 00166 class EdgeIt { 00167 friend class DirPath; 00168 00169 int idx; 00170 const DirPath *p; 00171 public: 00173 EdgeIt() {} 00175 EdgeIt(Invalid) : idx(-1), p(0) {} 00177 EdgeIt(const DirPath &_p, int _idx = 0) : 00178 idx(_idx), p(&_p) { validate(); } 00179 00181 bool valid() const { return idx!=-1; } 00182 00184 operator GraphEdge () const { 00185 return valid() ? p->edges[idx] : INVALID; 00186 } 00187 00189 EdgeIt& operator++() { ++idx; validate(); return *this; } 00190 00192 bool operator==(const EdgeIt& e) const { return idx==e.idx; } 00194 bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } 00196 bool operator<(const EdgeIt& e) const { return idx<e.idx; } 00197 00198 private: 00199 // FIXME: comparison between signed and unsigned... 00200 // Jo ez igy? Vagy esetleg legyen a length() int? 00201 void validate() { if( size_t(idx) >= p->length() ) idx=-1; } 00202 }; 00203 00213 class NodeIt { 00214 friend class DirPath; 00215 00216 int idx; 00217 const DirPath *p; 00218 public: 00220 NodeIt() {} 00222 NodeIt(Invalid) : idx(-1), p(0) {} 00224 NodeIt(const DirPath &_p, int _idx = 0) : 00225 idx(_idx), p(&_p) { validate(); } 00226 00228 bool valid() const { return idx!=-1; } 00229 00231 operator const GraphNode& () const { 00232 if(idx >= p->length()) 00233 return p->head(); 00234 else if(idx >= 0) 00235 return p->gr->tail(p->edges[idx]); 00236 else 00237 return INVALID; 00238 } 00240 NodeIt& operator++() { ++idx; validate(); return *this; } 00241 00243 bool operator==(const NodeIt& e) const { return idx==e.idx; } 00245 bool operator!=(const NodeIt& e) const { return idx!=e.idx; } 00247 bool operator<(const NodeIt& e) const { return idx<e.idx; } 00248 00249 private: 00250 void validate() { if( size_t(idx) > p->length() ) idx=-1; } 00251 }; 00252 00253 friend class Builder; 00254 00271 class Builder { 00272 DirPath &P; 00273 Container front, back; 00274 00275 public: 00278 Builder(DirPath &_P) : P(_P) {} 00279 00281 00287 void setStartNode(const GraphNode &) {} 00288 00290 00293 void pushFront(const GraphEdge& e) { 00294 front.push_back(e); 00295 } 00296 00298 00301 void pushBack(const GraphEdge& e) { 00302 back.push_back(e); 00303 } 00304 00306 void commit() { 00307 if( !front.empty() || !back.empty() ) { 00308 Container tmp; 00309 tmp.reserve(front.size()+back.size()+P.length()); 00310 tmp.insert(tmp.end(), front.rbegin(), front.rend()); 00311 tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); 00312 tmp.insert(tmp.end(), back.begin(), back.end()); 00313 P.edges.swap(tmp); 00314 front.clear(); 00315 back.clear(); 00316 } 00317 } 00318 00320 00323 00324 void reserveFront(size_t r) {front.reserve(r);} 00325 00327 00330 00331 void reserveBack(size_t r) {back.reserve(r);} 00332 00333 private: 00334 bool empty() { 00335 return front.empty() && back.empty() && P.empty(); 00336 } 00337 00338 GraphNode tail() const { 00339 if( ! front.empty() ) 00340 return P.gr->tail(front[front.size()-1]); 00341 else if( ! P.empty() ) 00342 return P.gr->tail(P.edges[0]); 00343 else if( ! back.empty() ) 00344 return P.gr->tail(back[0]); 00345 else 00346 return INVALID; 00347 } 00348 GraphNode head() const { 00349 if( ! back.empty() ) 00350 return P.gr->head(back[back.size()-1]); 00351 else if( ! P.empty() ) 00352 return P.gr->head(P.edges[P.length()-1]); 00353 else if( ! front.empty() ) 00354 return P.gr->head(front[0]); 00355 else 00356 return INVALID; 00357 } 00358 00359 }; 00360 00361 }; 00362 00363 00364 00365 00366 00367 00368 00369 00370 00371 00372 /**********************************************************************/ 00373 00374 00389 template<typename Graph> 00390 class UndirPath { 00391 public: 00393 typedef typename Graph::Edge GraphEdge; 00395 typedef typename Graph::Node GraphNode; 00396 class NodeIt; 00397 class EdgeIt; 00398 00399 protected: 00400 const Graph *gr; 00401 typedef std::vector<GraphEdge> Container; 00402 Container edges; 00403 00404 public: 00405 00408 UndirPath(const Graph &_G) : gr(&_G) {} 00409 00414 UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) { 00415 gr = P.gr; 00416 edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); 00417 } 00418 00423 UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) { 00424 gr = P.gr; 00425 edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); 00426 } 00427 00429 size_t length() const { return edges.size(); } 00431 bool empty() const { return edges.empty(); } 00432 00434 void clear() { edges.clear(); } 00435 00440 GraphNode tail() const { 00441 return empty() ? INVALID : gr->tail(edges[0]); 00442 } 00447 GraphNode head() const { 00448 return empty() ? INVALID : gr->head(edges[length()-1]); 00449 } 00450 00455 template<typename It> 00456 It& first(It &i) const { return i=It(*this); } 00457 00459 NodeIt& nth(NodeIt &i, int n) const { 00460 return i=NodeIt(*this, n); 00461 } 00462 00464 EdgeIt& nth(EdgeIt &i, int n) const { 00465 return i=EdgeIt(*this, n); 00466 } 00467 00469 template<typename It> 00470 static 00471 bool valid(const It &i) { return i.valid(); } 00472 00474 template<typename It> 00475 static 00476 It& next(It &e) { 00477 return ++e; 00478 } 00479 00482 NodeIt head(const EdgeIt& e) const { 00483 return NodeIt(*this, e.idx+1); 00484 } 00485 00488 NodeIt tail(const EdgeIt& e) const { 00489 return NodeIt(*this, e.idx); 00490 } 00491 00492 00493 00505 class EdgeIt { 00506 friend class UndirPath; 00507 00508 int idx; 00509 const UndirPath *p; 00510 public: 00512 EdgeIt() {} 00514 EdgeIt(Invalid) : idx(-1), p(0) {} 00516 EdgeIt(const UndirPath &_p, int _idx = 0) : 00517 idx(_idx), p(&_p) { validate(); } 00518 00520 bool valid() const { return idx!=-1; } 00521 00523 operator GraphEdge () const { 00524 return valid() ? p->edges[idx] : INVALID; 00525 } 00527 EdgeIt& operator++() { ++idx; validate(); return *this; } 00528 00530 bool operator==(const EdgeIt& e) const { return idx==e.idx; } 00532 bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } 00534 bool operator<(const EdgeIt& e) const { return idx<e.idx; } 00535 00536 private: 00537 // FIXME: comparison between signed and unsigned... 00538 // Jo ez igy? Vagy esetleg legyen a length() int? 00539 void validate() { if( size_t(idx) >= p->length() ) idx=-1; } 00540 }; 00541 00553 class NodeIt { 00554 friend class UndirPath; 00555 00556 int idx; 00557 const UndirPath *p; 00558 public: 00560 NodeIt() {} 00562 NodeIt(Invalid) : idx(-1), p(0) {} 00564 NodeIt(const UndirPath &_p, int _idx = 0) : 00565 idx(_idx), p(&_p) { validate(); } 00566 00568 bool valid() const { return idx!=-1; } 00569 00571 operator const GraphNode& () const { 00572 if(idx >= p->length()) 00573 return p->head(); 00574 else if(idx >= 0) 00575 return p->gr->tail(p->edges[idx]); 00576 else 00577 return INVALID; 00578 } 00580 NodeIt& operator++() { ++idx; validate(); return *this; } 00581 00583 bool operator==(const NodeIt& e) const { return idx==e.idx; } 00585 bool operator!=(const NodeIt& e) const { return idx!=e.idx; } 00587 bool operator<(const NodeIt& e) const { return idx<e.idx; } 00588 00589 private: 00590 void validate() { if( size_t(idx) > p->length() ) idx=-1; } 00591 }; 00592 00593 friend class Builder; 00594 00611 class Builder { 00612 UndirPath &P; 00613 Container front, back; 00614 00615 public: 00618 Builder(UndirPath &_P) : P(_P) {} 00619 00621 00627 void setStartNode(const GraphNode &) {} 00628 00630 00633 void pushFront(const GraphEdge& e) { 00634 front.push_back(e); 00635 } 00636 00638 00641 void pushBack(const GraphEdge& e) { 00642 back.push_back(e); 00643 } 00644 00646 void commit() { 00647 if( !(front.empty() && back.empty()) ) { 00648 Container tmp; 00649 tmp.reserve(front.size()+back.size()+P.length()); 00650 tmp.insert(tmp.end(), front.rbegin(), front.rend()); 00651 tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); 00652 tmp.insert(tmp.end(), back.begin(), back.end()); 00653 P.edges.swap(tmp); 00654 front.clear(); 00655 back.clear(); 00656 } 00657 } 00658 00659 00661 00664 00665 void reserveFront(size_t r) {front.reserve(r);} 00666 00668 00671 00672 void reserveBack(size_t r) {back.reserve(r);} 00673 00674 private: 00675 bool empty() { 00676 return front.empty() && back.empty() && P.empty(); 00677 } 00678 00679 GraphNode tail() const { 00680 if( ! front.empty() ) 00681 return P.gr->tail(front[front.size()-1]); 00682 else if( ! P.empty() ) 00683 return P.gr->tail(P.edges[0]); 00684 else if( ! back.empty() ) 00685 return P.gr->tail(back[0]); 00686 else 00687 return INVALID; 00688 } 00689 GraphNode head() const { 00690 if( ! back.empty() ) 00691 return P.gr->head(back[back.size()-1]); 00692 else if( ! P.empty() ) 00693 return P.gr->head(P.edges[P.length()-1]); 00694 else if( ! front.empty() ) 00695 return P.gr->head(front[0]); 00696 else 00697 return INVALID; 00698 } 00699 00700 }; 00701 00702 }; 00703 00704 00706 00707 } // namespace lemon 00708 00709 #endif // LEMON_PATH_H

Generated on Thu Sep 30 12:18:33 2004 for LEMON by doxygen 1.3.8