Complex1.h

Go to the documentation of this file.
00001 #ifndef Complex1_HEADER
00002 #define Complex1_HEADER
00003 
00004 #ifdef HAVE_CONFIG_H
00005 # include <config.h>
00006 #endif
00007 
00008 #include "SimplicialComplex.h"
00009 #include <boost/iterator/iterator_facade.hpp>
00010 
00015 template <class Vertex_, class SimplexData_, class VertexPrinter_>
00016 class SimplicialComplex<1, Vertex_, SimplexData_, VertexPrinter_> {
00017 
00018   public:
00019   typedef Vertex_ Vertex; 
00020   typedef VertexPrinter_ VertexPrinter; 
00021   typedef SimplexData_ SimplexData; 
00023   typedef typename hudson::Bucket<SimplexData>::reference data_ref; 
00024   typedef typename hudson::Bucket<SimplexData>::const_reference data_const_ref; 
00025   class Star;
00026   class Cavity;
00027 
00028   private:
00029   enum Index { LEFT, RIGHT, DONE };
00030   enum Status { BORN = 0, IN = 1, DEAD = 2 }; // must fit in 2 bits
00031 
00032   template <class Derived, class OutType, class Reference>
00033   class iterator_base : public boost::iterator_facade
00034                                 < Derived
00035                                 , OutType
00036                                 , boost::bidirectional_traversal_tag
00037                                 , Reference >
00038   {
00039     private:
00041       //
00042       // Curiously Recurring Template interface.
00043       //
00044       Derived& derived() { return *static_cast<Derived*>(this); }
00045       Derived const& derived() const { return *static_cast<Derived const*>(this); }
00046 
00047     protected:
00048       Index index_;
00049       iterator_base(Index index): index_(index) { }
00050 
00051     public:
00052       void increment() { assert(index_ < DONE); index_ = Index(unsigned(index_) + 1); }
00053       void decrement() { assert(index_ > LEFT); index_ = Index(unsigned(index_) - 1); }
00054       bool equal(const Derived& other) const { return index_ == other.index_; }
00055       Reference dereference() const {
00056         switch(index_) {
00057           case LEFT: return derived().getLeft();
00058           case RIGHT: return derived().getRight();
00059           case DONE: assert(0 && "dereferencing end()");
00060           default:   assert(0 && "major bug");
00061                      return derived().getLeft();
00062         }
00063       }
00064   };
00065 
00066   class ISimplex {
00067     ISimplex *left_;
00068     ISimplex *right_;
00069     Vertex *leftV_;
00070 
00071     size_t refcount_:(sizeof(size_t)*8 - 2);
00072     Status status_:2;
00073 
00074     public:
00075     hudson::Bucket<SimplexData> data_;
00076 
00077     ISimplex() {
00078       left_ = right_ = 0;
00079       leftV_ = 0;
00080       refcount_ = 0;
00081       status_ = BORN/*0*/;
00082     }
00083 
00084     bool isDummy() const { return right_ == 0; }
00085 
00086     ISimplex *getLeft() const { return left_; }
00087     ISimplex *getRight() const {
00088       assert(right_);
00089       if (right_->isDummy()) {
00090         return 0;
00091       } else return right_;
00092     }
00093     ISimplex *getRightOrDummy() const { return right_; }
00094 
00095     Vertex *getLeftV() const {
00096       return leftV_;
00097     }
00098     Vertex *getRightV() const {
00099       assert(!isDummy());
00100       return getRightOrDummy()->getLeftV();
00101     }
00102 
00103     Status getStatus() const { return status_; }
00104 
00105 
00106 
00107     void setLeft(ISimplex *left)  { left_ = left; }
00108     void setRight(ISimplex *right) { right_ = right; }
00109     void setVertex(Vertex *v) { leftV_ = v; }
00110     void setStatus(Status stat) {
00111       status_ = stat;
00112       switch(status_) {
00113         case IN:   add_ref(this); break;
00114         case DEAD: release(this); break;
00115         case BORN: break;
00116       }
00117     }
00118 
00119     /* Refcounting */
00120     static void add_ref(ISimplex *s) {
00121       s->refcount_++;
00122     }
00123     static void release(ISimplex *s) {
00124       s->refcount_--;
00125       if (s->refcount_ == 0) {
00126         delete s;
00127       }
00128     }
00129   };
00130 
00131   public:
00132   class Simplex {
00133     hudson::IntrusivePtr<ISimplex> s_;
00134 
00135     friend class Cavity;
00136     friend class Star;
00137     friend class SimplicialComplex;
00138     ISimplex *get() const { return s_.get(); }
00139     ISimplex *operator->() const { return get(); }
00140     void set(ISimplex *is) { s_ = is; }
00141 
00142     public:
00145     Simplex(const Simplex& other): s_(other.s_) { }
00146 
00147     static const size_t dimension = 1;
00148 
00152     Simplex(ISimplex *s): s_(s) { }
00153 
00154     size_t hash() const { return hudson::hashWord((size_t)get()); }
00155     std::string toString() const {
00156       VertexPrinter printer;
00157       return std::string("<") + printer(s_->getLeftV()) + " " + printer(s_->getRightV()) + ">";
00158     }
00159 
00160     class vertex_iterator : public iterator_base<vertex_iterator, Vertex*, Vertex*> {
00161       const Simplex& s;
00162       typedef iterator_base<vertex_iterator, Vertex*, Vertex*> super;
00163       friend class /*super*/ iterator_base<vertex_iterator, Vertex*, Vertex*>;
00164       friend class Simplex;
00165       Vertex *getLeft() const { return s->getLeftV(); }
00166       Vertex *getRight() const { return s->getRightV(); }
00167       vertex_iterator(const Simplex& s, Index i): super(i), s(s) { }
00168     };
00169     friend class vertex_iterator;
00170     typedef vertex_iterator iterator;
00171     typedef vertex_iterator const_iterator;
00172 
00173     vertex_iterator begin() const { return vertex_iterator(*this, LEFT); }
00174     vertex_iterator end() const { return vertex_iterator(*this, DONE); }
00175 
00176     Vertex *operator[](size_t i) const {
00177       switch(i) {
00178         case 0: return s_->getLeftV();
00179         case 1: return s_->getRightV();
00180         default: assert(0); return s_->getLeftV();
00181       }
00182     }
00183 
00184     bool has(const Vertex *v) const {
00185       return v == s_->getLeftV() || v == s_->getRightV();
00186     }
00187     template <class BinaryPredicate>
00188     bool has(const Vertex *v, const BinaryPredicate& pred) const {
00189       return pred(v, s_->getLeftV()) || pred(v, s_->getRightV());
00190     }
00191 
00192     bool operator== (const Simplex& other) const { return s_.get() == other.get(); }
00193     bool operator!= (const Simplex& other) const { return s_.get() != other.get(); }
00194   };
00195 
00196   /***************************************************************************
00197     Construction.
00198    ***************************************************************************/
00199   private:
00200   void init(Vertex *leftV, Vertex *rightV) {
00201     ISimplex *left = handle_.get();
00202     ISimplex *right = new ISimplex;
00203 
00204     left->setVertex(leftV);
00205     right->setVertex(rightV);
00206     left->setLeft(0);
00207     left->setRight(right);
00208     right->setLeft(left);
00209     right->setRight(0);
00210 
00211     left->setStatus(IN);
00212   }
00213 
00214   public:
00215   SimplicialComplex(Vertex *leftV, Vertex *rightV) : handle_(new ISimplex) {
00216     init(leftV, rightV);
00217   }
00218 
00219   SimplicialComplex(const vector<Vertex*>& verts) : handle_(new ISimplex) {
00220     assert(verts.size() == 2);
00221     init(verts[0], verts[1]);
00222   }
00223 
00224   /*
00225   SimplicialComplex(const vector<Vertex*>& verts, const vector<vector<unsigned> >& elts, int zeroindex) {
00226   // TODO
00227   }
00228   */
00229 
00230   /***************************************************************************
00231     Dimension
00232    ***************************************************************************/
00233 
00234   public:
00235   static size_t dim() { return 1; }
00236   static const size_t dimension = 1;
00237 
00238 
00239   /***************************************************************************
00240     Insert/remove
00241    ***************************************************************************/
00242   public:
00243   struct Cavity {
00244     typedef const Simplex *iterator;
00245     typedef const Simplex *const_iterator;
00246 
00247     Cavity(): s_(NULL) { }
00248 
00249     iterator begin() const { return &s_; }
00250     iterator end() const { return begin()+1; }
00251 
00252     bool empty() const { return s_.get() == NULL; }
00253     size_t size() const { return empty() ? 0 : 1; }
00254 
00255     void add(const Simplex& s) {
00256       assert(empty());
00257       s_ = s;
00258     }
00259 
00260     private:
00261     friend class SimplicialComplex;
00262     Simplex s_;
00263   };
00264 
00265   class Star {
00266     Simplex left_;
00267     Simplex right_;
00268 
00269     friend class SimplicialComplex;
00270 
00271     public:
00272     Star() : left_(0), right_(0) { }
00273     void clear() {
00274       left_.set(0);
00275       right_.set(0);
00276     }
00277 
00278     class iterator : public iterator_base<iterator, Simplex, const Simplex&> {
00279       typedef iterator_base<iterator, Simplex, const Simplex&> super;
00280       friend class iterator_base<iterator, Simplex, const Simplex&> /*super*/;
00281       friend class Star;
00282       const Star * star_;
00283       iterator(const Star& star, Index index): super(index), star_(&star) { }
00284       const Simplex& getLeft() const { return star_->left_; }
00285       const Simplex& getRight() const { return star_->right_; }
00286     };
00287     typedef iterator const_iterator;
00288 
00289     /* neigh_iterator returns a "reference" of type Simplex, because it's constructed in-place. */
00290     class neigh_iterator : public iterator_base<neigh_iterator, Simplex, Simplex> {
00291       typedef iterator_base<iterator, Simplex, Simplex> super;
00292       friend class iterator_base<iterator, Simplex, Simplex> /*super*/;
00293       friend class Star;
00294       const Star& star_;
00295       neigh_iterator(const Star& star, Index index): super(index), star_(star) { }
00296       const Simplex& getLeft() const { return star_.left_->getLeft(); }
00297       const Simplex& getRight() const { return star_.right_->getRight(); }
00298     };
00299 
00300     iterator begin() const { return iterator(*this, LEFT); }
00301     iterator end() const { return iterator(*this, DONE); }
00302 
00303     neigh_iterator begin_neighbours() const { return neigh_iterator(*this, LEFT); }
00304     neigh_iterator end_neighbours() const { return neigh_iterator(*this, DONE); }
00305 
00306     const Simplex& operator[] (size_t i) {
00307       switch(i) {
00308         case 0: return left_;
00309         case 1: return right_;
00310         default: assert(0); return left_;
00311       }
00312     }
00313 
00314     static size_t size() { return 2; }
00315 
00316     const iterator& erase(const iterator& it) {
00317       // Not possible in 1-d, but I'd rather not force every user to specialize
00318       // for 1-d, so we simply leave the function defined and assert if it's called.
00319       assert(0);
00320       return it;
00321     }
00322 
00323     private:
00324     void computeStar(const Simplex& tosplit, Vertex *v) {
00325       assert(!left_.get()); assert(!right_.get());
00326       left_.set(new ISimplex);
00327       right_.set(new ISimplex);
00328 
00329       left_->setLeft(tosplit->getLeft());
00330       left_->setRight(right_.get());
00331       left_->setVertex(tosplit->getLeftV());
00332 
00333       right_->setLeft(left_.get());
00334       right_->setRight(tosplit->getRightOrDummy());
00335       right_->setVertex(v);
00336       assert(left_.get()); assert(right_.get());
00337     }
00338 
00339     void commit(const Simplex& tosplit) {
00340       assert(left_.get()); assert(right_.get());
00341       assert(left_->getLeftV() == tosplit->getLeftV());
00342       if (left_->getLeft()) {
00343         left_->getLeft()->setRight(left_.get());
00344       }
00345       assert(right_->getRightOrDummy());
00346       right_->getRightOrDummy()->setLeft(right_.get());
00347       // left and right already point to each other, and we don't care about
00348       // the "head" of the doubly-linked list, so we're done.
00349       assert(left_->getRight() == right_.get());
00350       assert(right_->getLeft() == left_.get());
00351       left_->setStatus(IN);
00352       right_->setStatus(IN);
00353       tosplit->setStatus(DEAD);
00354     }
00355   };
00356 
00357   void computeStar(const Simplex& tosplit, Vertex *apex, Star& star) {
00358     assert(isMember(tosplit));
00359     star.computeStar(tosplit, apex);
00360   }
00361   void computeStar(const Cavity& cavity, Vertex *apex, Star& star) {
00362     computeStar(cavity.s_, apex, star);
00363   }
00364 
00365   void replaceCavity(const Simplex& tosplit, Star& star) {
00366     assert(isMember(tosplit));
00367     star.commit(tosplit);
00368     setHandle(star.left_);
00369   }
00370   void replaceCavity(const Cavity& cavity, Star& star) {
00371     replaceCavity(cavity.s_, star);
00372   }
00373 
00374   void replaceCavity(const Simplex& tosplit, Vertex *apex) {
00375     Star star;
00376     computeStar(tosplit, apex, star);
00377     replaceCavity(tosplit, star);
00378   }
00379   void replaceCavity(const Cavity& cavity, Vertex *apex) {
00380     replaceCavity(cavity.s_, apex);
00381   }
00382 
00383   void checkedRemoveSimplex(const Simplex& s) {
00384     assert(isMember(s));
00385     assert(getHandle() != s);
00386     if (s->getLeft()) {
00387       s->getLeft()->setRight(0);
00388     }
00389     ISimplex *right = s->getRightOrDummy();
00390     assert(right);
00391     if (right->isDummy()) {
00392       // delete it: it's otherwise an orphaned dummy
00393       delete right;
00394     } else {
00395       right->setLeft(0);
00396     }
00397     s->setLeft(0);
00398     s->setRight(0);
00399     s->setStatus(DEAD);
00400   }
00401 
00402   /***************************************************************************
00403    ***************************************************************************/
00404   bool isMember(const Simplex& s) const {
00405     return s.get() && (s->getStatus() == IN) && !s->isDummy();
00406   }
00407 
00408   const Simplex& getHandle() const {
00409     return handle_;
00410   }
00411 
00412   void setHandle(const Simplex& s) {
00413     assert(isMember(s));
00414     handle_ = s;
00415   }
00416 
00417   /***************************************************************************
00418    ***************************************************************************/
00419   Simplex getNeighbour(int i, const Simplex& s) const {
00420     assert(isMember(s));
00421     switch (i) {
00422       case 0: return s->getRight();
00423       case 1: return s->getLeft();
00424       default: assert(0); return s->getLeft();
00425     }
00426   }
00427 
00428   /***************************************************************************
00429    ***************************************************************************/
00430   template <class SearchClosure>
00431   bool dfsBySimplex(SearchClosure& data, const Simplex& seed) const {
00432     assert(isMember(seed));
00433     if (!data.canEnter(seed)) {
00434       return false;
00435     } else if (data.choose(seed)) {
00436       return true;
00437     }
00438     // first go left all the way
00439     ISimplex *next = seed->getLeft();
00440     while (next && data.canEnter(next)) {
00441       if (data.choose(next)) { return true; }
00442       next = next->getLeft();
00443     }
00444     // then go right all the way
00445     next = seed->getRight();
00446     while (next && data.canEnter(next)) {
00447       if (data.choose(next)) { return true; }
00448       next = next->getRight();
00449     }
00450     // didn't find it.
00451     return false;
00452   }
00453 
00454   template <class SearchClosure>
00455   bool bfsBySimplex(SearchClosure& data, const Simplex& seed) const {
00456     assert(isMember(seed));
00457     if (!data.canEnter(seed)) {
00458       return false;
00459     } else if (data.choose(seed)) {
00460       return true;
00461     }
00462 
00463     ISimplex *left = seed->getLeft();
00464     ISimplex *right = seed->getRight();
00465 
00466     while (left || right) {
00467       if (left) {
00468         if (!data.canEnter(left)) {
00469           left = 0;
00470         } else if (data.choose(left)) {
00471           return true;
00472         } else {
00473           left = left->getLeft();
00474         }
00475       }
00476       if (right) {
00477         if (!data.canEnter(right)) {
00478           right = 0;
00479         } else if (data.choose(right)) {
00480           return true;
00481         } else {
00482           right = right->getRight();
00483         }
00484       }
00485     }
00486     // never chose anyone.
00487     return false;
00488   }
00489 
00490   /***************************************************************************
00491    * \name Data access
00492    * We have to be careful with what we return, in order to handle void data.
00493    * We forward the request on to the complex, and then we pull out the
00494    * user's part of it.
00495    ***************************************************************************/
00496   data_ref getDataRW(const Simplex& s) {
00497     return s->data_.getRef();
00498   }
00499 
00501   data_const_ref getData(const Simplex& s) const {
00502     return s->data_.getCRef();
00503   }
00504 
00505   private:
00506   Simplex handle_;
00507 };
00508 
00509 #endif

Generated on Thu Mar 27 19:04:14 2008 by  doxygen 1.4.6