Actual source code: Sieve.hh

  2: #ifndef included_ALE_Sieve_hh
  3: #define included_ALE_Sieve_hh

  5: #include <boost/multi_index_container.hpp>
  6: #include <boost/multi_index/member.hpp>
  7: #include <boost/multi_index/ordered_index.hpp>
  8: #include <boost/multi_index/composite_key.hpp>
  9: #include <iostream>

 11: #ifndef  included_ALE_Sifter_hh
 12: #include <Sifter.hh>
 13: #endif


 16: namespace ALE {

 18:   namespace SieveDef {
 19:     //
 20:     // Rec & RecContainer definitions.
 21:     // Rec is intended to denote a graph point record.
 22:     //
 23:     template <typename Point_, typename Marker_>
 24:     struct Rec {
 25:       typedef Point_  point_type;
 26:       typedef Marker_ marker_type;
 27:       template<typename OtherPoint_, typename OtherMarker_ = Marker_>
 28:       struct rebind {
 29:         typedef Rec<OtherPoint_, OtherMarker_> type;
 30:       };
 31:       point_type  point;
 32:       int         degree;
 33:       int         depth;
 34:       int         height;
 35:       marker_type marker;
 36:       // Basic interface
 37:       Rec() : point(point_type()), degree(0), depth(0), height(0), marker(marker_type()) {};
 38:       Rec(const Rec& r) : point(r.point), degree(r.degree), depth(r.depth), height(r.height), marker(r.marker) {}
 39:       Rec(const point_type& p) : point(p), degree(0), depth(0), height(0), marker(marker_type()) {};
 40:       Rec(const point_type& p, const int degree) : point(p), degree(degree), depth(0), height(0), marker(marker_type()) {};
 41:       Rec(const point_type& p, const int degree, const int depth, const int height, const marker_type marker) : point(p), degree(degree), depth(depth), height(height), marker(marker) {};
 42:       // Printing
 43:       friend std::ostream& operator<<(std::ostream& os, const Rec& p) {
 44:         os << "<" << p.point << ", "<< p.degree << ", "<< p.depth << ", "<< p.height << ", "<< p.marker << ">";
 45:         return os;
 46:       };

 48:       struct degreeAdjuster {
 49:         degreeAdjuster(int newDegree) : _newDegree(newDegree) {};
 50:         void operator()(Rec& r) { r.degree = this->_newDegree; }
 51:       private:
 52:         int _newDegree;
 53:       };
 54:     };// class Rec

 56:     template <typename Point_, typename Rec_>
 57:     struct RecContainerTraits {
 58:       typedef Rec_ rec_type;
 59:       typedef typename rec_type::marker_type marker_type;
 60:       // Index tags
 61:       struct pointTag{};
 62:       struct degreeTag{};
 63:       struct markerTag{};
 64:       struct depthMarkerTag{};
 65:       struct heightMarkerTag{};
 66:       // Rec set definition
 67:       typedef ::boost::multi_index::multi_index_container<
 68:         rec_type,
 69:         ::boost::multi_index::indexed_by<
 70:           ::boost::multi_index::ordered_unique<
 71:             ::boost::multi_index::tag<pointTag>, BOOST_MULTI_INDEX_MEMBER(rec_type, typename rec_type::point_type, point)
 72:           >,
 73: //           ::boost::multi_index::ordered_non_unique<
 74: //             ::boost::multi_index::tag<degreeTag>, BOOST_MULTI_INDEX_MEMBER(rec_type, int, degree)
 75: //           >,
 76:           ::boost::multi_index::ordered_non_unique<
 77:             ::boost::multi_index::tag<markerTag>, BOOST_MULTI_INDEX_MEMBER(rec_type, marker_type, marker)
 78:           >,
 79:           ::boost::multi_index::ordered_non_unique<
 80:             ::boost::multi_index::tag<depthMarkerTag>,
 81:             ::boost::multi_index::composite_key<
 82:               rec_type, BOOST_MULTI_INDEX_MEMBER(rec_type,int,depth), BOOST_MULTI_INDEX_MEMBER(rec_type,marker_type,marker)>
 83:           >,
 84:           ::boost::multi_index::ordered_non_unique<
 85:             ::boost::multi_index::tag<heightMarkerTag>,
 86:             ::boost::multi_index::composite_key<
 87:               rec_type, BOOST_MULTI_INDEX_MEMBER(rec_type,int,height), BOOST_MULTI_INDEX_MEMBER(rec_type,marker_type,marker)>
 88:           >
 89:         >,
 90:         ALE_ALLOCATOR<rec_type>
 91:       > set_type;
 92:       //
 93:       // Return types
 94:       //

 96:      class PointSequence {
 97:      public:
 98:        typedef ALE::SifterDef::IndexSequenceTraits<typename ::boost::multi_index::index<set_type, pointTag>::type,
 99:                                     BOOST_MULTI_INDEX_MEMBER(rec_type, typename rec_type::point_type,point)>
100:        traits;
101:       protected:
102:         const typename traits::index_type& _index;
103:       public:
104: 
105:        // Need to extend the inherited iterator to be able to extract the degree
106:        class iterator : public traits::iterator {
107:        public:
108:          iterator(const typename traits::iterator::itor_type& itor) : traits::iterator(itor) {};
109:          virtual const int& degree() const {return this->_itor->degree;};
110:          virtual const int& marker() const {return this->_itor->marker;};
111:          virtual const int& depth()  const {return this->_itor->depth;};
112:          virtual const int& height() const {return this->_itor->height;};
113:          //void setDegree(const int degree) {this->_index.modify(this->_itor, typename traits::rec_type::degreeAdjuster(degree));};
114:        };
115: 
116:        PointSequence(const PointSequence& seq)            : _index(seq._index) {};
117:        PointSequence(typename traits::index_type& index) : _index(index)     {};
118:        virtual ~PointSequence(){};
119: 
120:        virtual bool empty(){return this->_index.empty();};
121: 
122:        virtual typename traits::index_type::size_type size() {return this->_index.size();};

124:        virtual iterator begin() {
125:          // Retrieve the beginning iterator of the index
126:          return iterator(this->_index.begin());
127:        };
128:        virtual iterator end() {
129:          // Retrieve the ending iterator of the index
130:          // Since the elements in this index are ordered by degree, this amounts to the end() of the index.
131:          return iterator(this->_index.end());
132:        };
133:        virtual bool contains(const typename rec_type::point_type& p) {
134:          // Check whether a given point is in the index
135:          return (this->_index.find(p) != this->_index.end());
136:        };
137:      }; // class PointSequence

139:      template<typename Tag_, typename Value_>
140:      class ValueSequence {
141:      public:
142:        typedef Value_ value_type;
143:        typedef ALE::SifterDef::IndexSequenceTraits<typename ::boost::multi_index::index<set_type, Tag_>::type,
144:                                    BOOST_MULTI_INDEX_MEMBER(rec_type, typename rec_type::point_type,point)>
145:        traits;
146:      protected:
147:        const typename traits::index_type& _index;
148:        const value_type _value;
149:      public:
150:        // Need to extend the inherited iterator to be able to extract the degree
151:        class iterator : public traits::iterator {
152:        public:
153:          iterator(const typename traits::iterator::itor_type& itor) : traits::iterator(itor) {};
154:          virtual const int& degree()  const {return this->_itor->degree;};
155:          virtual const int& marker()  const {return this->_itor->marker;};
156:          virtual const int& depth()   const {return this->_itor->depth;};
157:          virtual const int& height()  const {return this->_itor->height;};
158:        };
159: 
160:        ValueSequence(const PointSequence& seq)           : _index(seq._index), _value(seq._value) {};
161:        ValueSequence(typename traits::index_type& index, const value_type& value) : _index(index), _value(value) {};
162:        virtual ~ValueSequence(){};
163: 
164:        virtual bool empty(){return this->_index.empty();};
165: 
166:        virtual typename traits::index_type::size_type size() {return this->_index.count(this->_value);};

168:        virtual iterator begin() {
169:          return iterator(this->_index.lower_bound(this->_value));
170:        };
171:        virtual iterator end() {
172:          return iterator(this->_index.upper_bound(this->_value));
173:        };
174:      }; // class ValueSequence

176:      template<typename Tag_, typename Value_>
177:      class TwoValueSequence {
178:      public:
179:        typedef Value_ value_type;
180:        typedef ALE::SifterDef::IndexSequenceTraits<typename ::boost::multi_index::index<set_type, Tag_>::type,
181:                                    BOOST_MULTI_INDEX_MEMBER(rec_type, typename rec_type::point_type,point)>
182:        traits;
183:      protected:
184:        const typename traits::index_type& _index;
185:        const value_type _valueA, _valueB;
186:        const bool _useTwoValues;
187:      public:
188:        // Need to extend the inherited iterator to be able to extract the degree
189:        class iterator : public traits::iterator {
190:        public:
191:          iterator(const typename traits::iterator::itor_type& itor) : traits::iterator(itor) {};
192:          virtual const int& degree()  const {return this->_itor->degree;};
193:          virtual const int& marker()  const {return this->_itor->marker;};
194:        };
195: 
196:        TwoValueSequence(const PointSequence& seq)           : _index(seq._index), _valueA(seq._valueA), _valueB(seq._valueB), _useTwoValues(seq._useTwoValues) {};
197:        TwoValueSequence(typename traits::index_type& index, const value_type& valueA) : _index(index), _valueA(valueA), _valueB(value_type()), _useTwoValues(false) {};
198:        TwoValueSequence(typename traits::index_type& index, const value_type& valueA, const value_type& valueB) : _index(index), _valueA(valueA), _valueB(valueB), _useTwoValues(true) {};
199:        virtual ~TwoValueSequence(){};
200: 
201:        virtual bool empty(){return this->_index.empty();};
202: 
203:        virtual typename traits::index_type::size_type size() {
204:          if (this->_useTwoValues) {
205:            return this->_index.count(::boost::make_tuple(this->_valueA,this->_valueB));
206:          } else {
207:            return this->_index.count(::boost::make_tuple(this->_valueA));
208:          }
209:        };

211:        virtual iterator begin() {
212:          if (this->_useTwoValues) {
213:            return iterator(this->_index.lower_bound(::boost::make_tuple(this->_valueA,this->_valueB)));
214:          } else {
215:            return iterator(this->_index.lower_bound(::boost::make_tuple(this->_valueA)));
216:          }
217:        };
218:        virtual iterator end() {
219:          if (this->_useTwoValues) {
220:            return iterator(this->_index.upper_bound(::boost::make_tuple(this->_valueA,this->_valueB)));
221:          } else {
222:            return iterator(this->_index.upper_bound(::boost::make_tuple(this->_valueA)));
223:          }
224:        };
225:      }; // class TwoValueSequence
226:     };// struct RecContainerTraits

228:     template <typename Point_, typename Rec_>
229:     struct RecContainer {
230:       typedef RecContainerTraits<Point_, Rec_> traits;
231:       typedef typename traits::set_type set_type;
232:       template <typename OtherPoint_, typename OtherRec_>
233:       struct rebind {
234:         typedef RecContainer<OtherPoint_, OtherRec_> type;
235:       };
236:       set_type set;

238:       void removePoint(const typename traits::rec_type::point_type& p) {
239:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type& index =
240:           ::boost::multi_index::get<typename traits::pointTag>(this->set);
241:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type::iterator i = index.find(p);
242:         if (i != index.end()) { // Point exists
243:           index.erase(i);
244:         }
245:       };
246:       void adjustDegree(const typename traits::rec_type::point_type& p, int delta) {
247:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type& index =
248:           ::boost::multi_index::get<typename traits::pointTag>(this->set);
249:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type::iterator i = index.find(p);
250:         if (i == index.end()) { // No such point exists
251:           if(delta < 0) { // Cannot decrease degree of a non-existent point
252:             ostringstream err;
253:             err << "ERROR: adjustDegree: Non-existent point " << p;
254:             std::cout << err << std::endl;
255:             throw(Exception(err.str().c_str()));
256:           }
257:           else { // We CAN INCREASE the degree of a non-existent point: simply insert a new element with degree == delta
258:             std::pair<typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type::iterator, bool> ii;
259:             typename traits::rec_type r(p,delta);
260:             ii = index.insert(r);
261:             if(ii.second == false) {
262:               ostringstream err;
263:               err << "ERROR: adjustDegree: Failed to insert a rec " << r;
264:               std::cout << err << std::endl;
265:               throw(Exception(err.str().c_str()));
266:             }
267:           }
268:         }
269:         else { // Point exists, so we try to modify its degree
270:           // If the adjustment is zero, there is nothing to do, otherwise ...
271:           if(delta != 0) {
272:             int newDegree = i->degree + delta;
273:             if(newDegree < 0) {
274:               ostringstream ss;
275:               ss << "adjustDegree: Adjustment of " << *i << " by " << delta << " would result in negative degree: " << newDegree;
276:               throw Exception(ss.str().c_str());
277:             }
278:             index.modify(i, typename traits::rec_type::degreeAdjuster(newDegree));
279:           }
280:         }
281:       }; // adjustDegree()
282:     }; // struct RecContainer
283:   };// namespace SieveDef

285:     //
286:     // Sieve:
287:     //   A Sieve is a set of {\emph arrows} connecting {\emph points} of type Point_. Thus we
288:     // could realize a sieve, for instance, as a directed graph. In addition, we will often
289:     // assume an acyclicity constraint, arriving at a DAG. Each arrow may also carry a label,
290:     // or {\emph color} of type Color_, and the interface allows sets of arrows to be filtered
291:     // by color.
292:     //
293:     template <typename Point_, typename Marker_, typename Color_>
294:     class Sieve : public ALE::Sifter<Point_, Point_, Color_, ::boost::multi_index::composite_key_compare<std::less<Point_>, std::less<Color_>, std::less<Point_> >, SieveDef::RecContainer<Point_, SieveDef::Rec<Point_, Marker_> >, SieveDef::RecContainer<Point_, SieveDef::Rec<Point_, Marker_> > > {
295:     public:
296:       typedef Color_  color_type;
297:       typedef Point_  point_type;
298:       typedef Marker_ marker_type;
299:       typedef struct {
300:         typedef ALE::Sifter<Point_, Point_, Color_, ::boost::multi_index::composite_key_compare<std::less<Point_>, std::less<Color_>, std::less<Point_> >, SieveDef::RecContainer<Point_, SieveDef::Rec<Point_, Marker_> >, SieveDef::RecContainer<Point_, SieveDef::Rec<Point_, Marker_> > > baseType;
301:         // Encapsulated container types
302:         typedef typename baseType::traits::arrow_container_type arrow_container_type;
303:         typedef typename baseType::traits::cap_container_type   cap_container_type;
304:         typedef typename baseType::traits::base_container_type  base_container_type;
305:         // Types associated with records held in containers
306:         typedef typename baseType::traits::arrow_type           arrow_type;
307:         typedef typename baseType::traits::source_type          source_type;
308:         typedef typename baseType::traits::sourceRec_type       sourceRec_type;
309:         typedef typename baseType::traits::target_type          target_type;
310:         typedef typename baseType::traits::targetRec_type       targetRec_type;
311:         typedef typename baseType::traits::color_type           color_type;
312:         typedef Point_                                          point_type;
313:         // Convenient tag names
314:         typedef typename baseType::traits::supportInd           supportInd;
315:         typedef typename baseType::traits::coneInd              coneInd;
316:         typedef typename baseType::traits::arrowInd             arrowInd;
317:         typedef typename baseType::traits::baseInd              baseInd;
318:         typedef typename baseType::traits::capInd               capInd;

320:         //
321:         // Return types
322:         //
323:         typedef typename baseType::traits::arrowSequence        arrowSequence;
324:         typedef typename baseType::traits::coneSequence         coneSequence;
325:         typedef typename baseType::traits::supportSequence      supportSequence;
326:         typedef typename baseType::traits::baseSequence         baseSequence;
327:         typedef typename baseType::traits::capSequence          capSequence;
328:         typedef typename base_container_type::traits::template TwoValueSequence<typename base_container_type::traits::depthMarkerTag,int> depthSequence;
329:         typedef typename cap_container_type::traits::template TwoValueSequence<typename cap_container_type::traits::heightMarkerTag,int> heightSequence;
330:         typedef typename cap_container_type::traits::template ValueSequence<typename cap_container_type::traits::markerTag,marker_type> markerSequence;
331:       } traits;
332:       typedef std::set<point_type>    pointSet;
333:       typedef ALE::array<point_type>  pointArray;
334:       typedef std::set<marker_type>   markerSet;
335:       typedef pointSet                coneSet;
336:       typedef pointSet                supportSet;
337:       typedef pointArray              coneArray;
338:       typedef pointArray              supportArray;
339:     public:
340:       Sieve(MPI_Comm comm = PETSC_COMM_SELF, const int& debug = 0) : ALE::Sifter<Point_, Point_, Color_, ::boost::multi_index::composite_key_compare<std::less<Point_>, std::less<Color_>, std::less<Point_> >, SieveDef::RecContainer<Point_, SieveDef::Rec<Point_, Marker_> >, SieveDef::RecContainer<Point_, SieveDef::Rec<Point_, Marker_> > >(comm, debug), doStratify(false), maxDepth(-1), maxHeight(-1), graphDiameter(-1) {
341:         this->_markers = new markerSet();
342:         this->_meetSet = new coneSet();
343:       };
344:       virtual ~Sieve() {};
345:       // Printing
346:       friend std::ostream& operator<<(std::ostream& os, Obj<Sieve<Point_,Marker_,Color_> > s) {
347:         os << *s;
348:         return os;
349:       };
350: 
351:       friend std::ostream& operator<<(std::ostream& os, Sieve<Point_,Marker_,Color_>& s) {
352:         Obj<typename traits::baseSequence> base = s.base();
353:         for(typename traits::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
354:           Obj<typename traits::coneSequence> cone = s.cone(*b_iter);
355:           os << "Base point " << *b_iter << " with cone:" << std::endl;
356:           for(typename traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
357:             os << "  " << *c_iter << std::endl;
358:           }
359:         }
360:         return os;
361:       };

363:       template<typename ostream_type>
364:       void view(ostream_type& os, const char* label, bool rawData);
365:       void view(const char* label, MPI_Comm comm);

367:       Obj<Sieve> copy() {
368:         Obj<Sieve> s = Sieve(this->comm(), this->debug);
369:         Obj<typename traits::capSequence>  cap  = this->cap();
370:         Obj<typename traits::baseSequence> base = this->base();

372:         for(typename traits::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
373:           s->addCapPoint(*c_iter);
374:         }
375:         for(typename traits::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
376:           Obj<typename traits::coneSequence> cone = this->cone(*b_iter);

378:           for(typename traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
379:             s->addArrow(*c_iter, *b_iter, c_iter.color());
380:           }
381:         }
382:         s->stratify();
383:         return s;
384:       };
385:       bool hasPoint(const point_type& point) {
386:         if (this->baseContains(point) || this->capContains(point)) return true;
387:         return false;
388:       };
389:     private:
390:       template<class InputSequence> Obj<coneSet> __nCone(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor);
391:       template<class pointSequence> void __nCone(const Obj<pointSequence>& points, int n, const Color_& color, bool useColor, Obj<coneArray> cone, Obj<coneSet> seen);
392:       template<class pointSequence> void __nSupport(const Obj<pointSequence>& points, int n, const Color_& color, bool useColor, Obj<supportArray> cone, Obj<supportSet> seen);
393:     public:
394:       //
395:       // The basic Sieve interface (extensions to Sifter)
396:       //
397:       Obj<coneArray> nCone(const Point_& p, int n);
398:       Obj<coneArray> nCone(const Point_& p, int n, const Color_& color, bool useColor = true);
399:       template<class InputSequence> Obj<coneSet> nCone(const Obj<InputSequence>& points, int n);
400:       template<class InputSequence> Obj<coneSet> nCone(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);

402:       Obj<supportArray> nSupport(const Point_& p, int n);
403:       Obj<supportArray> nSupport(const Point_& p, int n, const Color_& color, bool useColor = true);
404:       template<class InputSequence> Obj<supportSet> nSupport(const Obj<InputSequence>& points, int n);
405:       template<class InputSequence> Obj<supportSet> nSupport(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);
406:     public:
407:       virtual bool checkArrow(const typename traits::arrow_type& a) {
408:         if ((this->_cap.set.find(a.source) == this->_cap.set.end()) && (this->_base.set.find(a.source) == this->_base.set.end())) return false;
409:         if ((this->_cap.set.find(a.target) == this->_cap.set.end()) && (this->_base.set.find(a.target) == this->_base.set.end())) return false;
410:         return true;
411:       };
412:       //
413:       // Iterated versions
414:       //
415:       Obj<supportSet> star(const Point_& p);

417:       Obj<supportSet> star(const Point_& p, const Color_& color);

419:       template<class InputSequence>
420:       Obj<supportSet> star(const Obj<InputSequence>& points);

422:       template<class InputSequence>
423:       Obj<supportSet> star(const Obj<InputSequence>& points, const Color_& color);

425:       Obj<supportSet> nStar(const Point_& p, int n);

427:       Obj<supportSet> nStar(const Point_& p, int n, const Color_& color, bool useColor = true);

429:       template<class InputSequence>
430:       Obj<supportSet> nStar(const Obj<InputSequence>& points, int n);

432:       template<class InputSequence>
433:       Obj<supportSet> nStar(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);

435:     private:
436:       template<class InputSequence>
437:       Obj<supportSet> __nStar(Obj<InputSequence>& support, int n, const Color_& color, bool useColor);

439:     public:
440:       //
441:       // Lattice methods
442:       //
443:       const Obj<coneSet>& meet(const Point_& p, const Point_& q);

445:       const Obj<coneSet>& meet(const Point_& p, const Point_& q, const Color_& color);

447:       template<class InputSequence>
448:       const Obj<coneSet>& meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1);

450:       template<class InputSequence>
451:       const Obj<coneSet>& meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color);

453:       const Obj<coneSet>& nMeet(const Point_& p, const Point_& q, int n);

455:       const Obj<coneSet>& nMeet(const Point_& p, const Point_& q, int n, const Color_& color, bool useColor = true);

457:       template<class InputSequence>
458:       const Obj<coneSet>& nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n);

460:       template<class InputSequence>
461:       const Obj<coneSet>& nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n,
462:                                 const Color_& color, bool useColor = true);

464:       Obj<supportSet> join(const Point_& p, const Point_& q);

466:       Obj<supportSet> join(const Point_& p, const Point_& q, const Color_& color);

468:       template<class InputSequence>
469:       Obj<supportSet> join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1);

471:       template<class InputSequence>
472:       Obj<supportSet> join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color);

474:       template<class InputSequence>
475:       Obj<supportSet> nJoin1(const Obj<InputSequence>& chain);

477:       Obj<supportSet> nJoin(const Point_& p, const Point_& q, int n);

479:       Obj<supportSet> nJoin(const Point_& p, const Point_& q, int n, const Color_& color, bool useColor = true);

481:       template<class InputSequence>
482:       Obj<supportSet> nJoin(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n);

484:       template<class InputSequence>
485:       Obj<supportSet> nJoin(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n, const Color_& color, bool useColor = true);

487:     public:
488:       Obj<typename traits::depthSequence> roots() {
489:         return this->depthStratum(0);
490:       };
491:       Obj<typename traits::heightSequence> leaves() {
492:         return this->heightStratum(0);
493:       };
494:     private:
495:       bool doStratify;
496:       int  maxDepth, maxHeight, graphDiameter;
497:     public:
498:       //
499:       // Structural queries
500:       //
501:       int depth();
502:       int depth(const point_type& p);
503:       template<typename InputSequence> int depth(const Obj<InputSequence>& points);

505:       int height();
506:       int height(const point_type& p);
507:       template<typename InputSequence> int height(const Obj<InputSequence>& points);

509:       int diameter();
510:       int diameter(const point_type& p);

512:       Obj<typename traits::depthSequence> depthStratum(int d);
513:       Obj<typename traits::depthSequence> depthStratum(int d, marker_type m);

515:       Obj<typename traits::heightSequence> heightStratum(int h);
516:       Obj<typename traits::heightSequence> heightStratum(int h, marker_type m);

518:       Obj<typename traits::markerSequence> markerStratum(marker_type m);
519: 
520:       void setStratification(bool doStratify) {this->doStratify = doStratify;};

522:       bool getStratification() {return this->doStratify;};

524:       void stratify(bool show = false);
525:     protected:
526:       Obj<markerSet> _markers;
527:       Obj<coneSet>   _meetSet;
528:     public:
529:       //
530:       // Structural manipulation
531:       //

533:       struct changeMarker {
534:         changeMarker(int newMarker) : newMarker(newMarker) {};

536:         void operator()(typename traits::base_container_type::traits::rec_type& p) {
537:           p.marker = newMarker;
538:         }
539:       private:
540:         marker_type newMarker;
541:       };

543:       void setMarker(const point_type& p, const marker_type& marker);
544:       template<class InputSequence> void setMarker(const Obj<InputSequence>& points, const marker_type& marker);

546:       void clearMarkers() {this->_markers.clear();};
547:       Obj<markerSet> markers() {return this->_markers;};
548:     private:
549:       struct changeHeight {
550:         changeHeight(int newHeight) : newHeight(newHeight) {};

552:         void operator()(typename traits::base_container_type::traits::rec_type& p) {
553:           p.height = newHeight;
554:         }
555:       private:
556:         int newHeight;
557:       };
558: 
559:       template<class InputSequence> void __computeClosureHeights(const Obj<InputSequence>& points);

561:       struct changeDepth {
562:         changeDepth(int newDepth) : newDepth(newDepth) {};

564:         void operator()(typename traits::base_container_type::traits::rec_type& p) {
565:           p.depth = newDepth;
566:         }
567:       private:
568:         int newDepth;
569:       };

571:       template<class InputSequence> void __computeStarDepths(const Obj<InputSequence>& points);
572:     };

574:     template <typename Point_, typename Marker_, typename Color_>
575:     Obj<typename Sieve<Point_,Marker_,Color_>::coneArray> Sieve<Point_,Marker_,Color_>::nCone(const Point_& p, int n) {
576:       return this->nCone(p, n, Color_(), false);
577:     };

579:     template <typename Point_, typename Marker_, typename Color_>
580:     Obj<typename Sieve<Point_,Marker_,Color_>::coneArray> Sieve<Point_,Marker_,Color_>::nCone(const Point_& p, int n, const Color_& color, bool useColor) {
581:       Obj<coneArray> cone = new coneArray();
582:       Obj<coneSet>   seen = new coneSet();

584:       this->__nCone(this->cone(p), n-1, color, useColor, cone, seen);
585:       return cone;
586:     };

588:     template <typename Point_, typename Marker_, typename Color_>
589:     template<class pointSequence>
590:     void Sieve<Point_,Marker_,Color_>::__nCone(const Obj<pointSequence>& points, int n, const Color_& color, bool useColor, Obj<coneArray> cone, Obj<coneSet> seen) {
591:       if (n == 0) {
592:         for(typename pointSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
593:           if (seen->find(*p_itor) == seen->end()) {
594:             cone->push_back(*p_itor);
595:             seen->insert(*p_itor);
596:           }
597:         }
598:       } else {
599:         typename pointSequence::iterator end = points->end();
600:         for(typename pointSequence::iterator p_itor = points->begin(); p_itor != end; ++p_itor) {
601:           if (useColor) {
602:             this->__nCone(this->cone(*p_itor, color), n-1, color, useColor, cone, seen);
603:           } else {
604:             this->__nCone(this->cone(*p_itor), n-1, color, useColor, cone, seen);
605:           }
606:         }
607:       }
608:     };

610:     template <typename Point_, typename Marker_, typename Color_>
611:     template<class InputSequence>
612:     Obj<typename Sieve<Point_,Marker_,Color_>::coneSet> Sieve<Point_,Marker_,Color_>::nCone(const Obj<InputSequence>& points, int n) {
613:       return this->nCone(points, n, Color_(), false);
614:     };

616:     template <typename Point_, typename Marker_, typename Color_>
617:     template<class InputSequence>
618:     Obj<typename Sieve<Point_,Marker_,Color_>::coneSet> Sieve<Point_,Marker_,Color_>::nCone(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor ) {
619:       Obj<coneSet> cone = new coneSet();
620:       cone->insert(points->begin(), points->end());
621:       return this->__nCone(cone, n, color, useColor);
622:     };

624:     template <typename Point_, typename Marker_, typename Color_>
625:     template<class InputSequence>
626:     Obj<typename Sieve<Point_,Marker_,Color_>::coneSet> Sieve<Point_,Marker_,Color_>::__nCone(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor) {
627:       Obj<coneSet> base = new coneSet();

629:       for(int i = 0; i < n; ++i) {
630:         Obj<coneSet> tmp = cone; cone = base; base = tmp;
631: 
632:         cone->clear();
633:         for(typename coneSet::iterator b_itor = base->begin(); b_itor != base->end(); ++b_itor) {
634:           Obj<typename traits::coneSequence> pCone;
635: 
636:           if (useColor) {
637:             pCone = this->cone(*b_itor, color);
638:           } else {
639:             pCone = this->cone(*b_itor);
640:           }
641:           cone->insert(pCone->begin(), pCone->end());
642:         }
643:       }
644:       return cone;
645:     };

647:     template <typename Point_, typename Marker_, typename Color_>
648:     Obj<typename Sieve<Point_,Marker_,Color_>::supportArray> Sieve<Point_,Marker_,Color_>::nSupport(const Point_& p, int n) {
649:       return this->nSupport(p, n, Color_(), false);
650:     };

652:     template <typename Point_, typename Marker_, typename Color_>
653:     Obj<typename Sieve<Point_,Marker_,Color_>::supportArray> Sieve<Point_,Marker_,Color_>::nSupport(const Point_& p, int n, const Color_& color, bool useColor) {
654:       Obj<supportArray> cone = new supportArray();
655:       Obj<supportSet>   seen = new supportSet();

657:       this->__nSupport(this->support(p), n-1, color, useColor, cone, seen);
658:       return cone;
659:     };

661:     template <typename Point_, typename Marker_, typename Color_>
662:     template<class pointSequence>
663:     void Sieve<Point_,Marker_,Color_>::__nSupport(const Obj<pointSequence>& points, int n, const Color_& color, bool useColor, Obj<supportArray> support, Obj<supportSet> seen) {
664:       if (n == 0) {
665:         for(typename pointSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
666:           if (seen->find(*p_itor) == seen->end()) {
667:             support->push_back(*p_itor);
668:             seen->insert(*p_itor);
669:           }
670:         }
671:       } else {
672:         typename pointSequence::iterator end = points->end();
673:         for(typename pointSequence::iterator p_itor = points->begin(); p_itor != end; ++p_itor) {
674:           if (useColor) {
675:             this->__nSupport(this->support(*p_itor, color), n-1, color, useColor, support, seen);
676:           } else {
677:             this->__nSupport(this->support(*p_itor), n-1, color, useColor, support, seen);
678:           }
679:         }
680:       }
681:     };

683:     template <typename Point_, typename Marker_, typename Color_>
684:     template<class InputSequence>
685:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nSupport(const Obj<InputSequence>& points, int n) {
686:       return this->nSupport(points, n, Color_(), false);
687:     };

689:     template <typename Point_, typename Marker_, typename Color_>
690:     template<class InputSequence>
691:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nSupport(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor ) {
692:       Obj<supportSet> support = supportSet();
693:       Obj<supportSet> cap = supportSet();
694: 
695:       support->insert(points->begin(), points->end());
696:       for(int i = 0; i < n; ++i) {
697:         Obj<supportSet> tmp = support; support = cap; cap = tmp;
698: 
699:         support->clear();
700:         for(typename supportSet::iterator c_itor = cap->begin(); c_itor != cap->end(); ++c_itor) {
701:           Obj<typename traits::supportSequence> pSupport;
702: 
703:           if (useColor) {
704:             pSupport = this->support(*c_itor, color);
705:           } else {
706:             pSupport = this->support(*c_itor);
707:           }
708:           support->insert(pSupport->begin(), pSupport->end());
709:         }
710:       }
711:       return support;
712:     };
713:     //
714:     // Iterated versions
715:     //
716:     template <typename Point_, typename Marker_, typename Color_>
717:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::star(const Point_& p) {
718:       return nStar(p, this->height());
719:     };
720: 
721:     template <typename Point_, typename Marker_, typename Color_>
722:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::star(const Point_& p, const Color_& color) {
723:       return nStar(p, this->depth(), color);
724:     };
725: 
726:     template <typename Point_, typename Marker_, typename Color_>
727:     template<class InputSequence>
728:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::star(const Obj<InputSequence>& points) {
729:       return nStar(points, this->height());
730:     };
731: 
732:     template <typename Point_, typename Marker_, typename Color_>
733:     template<class InputSequence>
734:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::star(const Obj<InputSequence>& points, const Color_& color) {
735:       return nStar(points, this->height(), color);
736:     };

738:     template <typename Point_, typename Marker_, typename Color_>
739:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nStar(const Point_& p, int n) {
740:       return this->nStar(p, n, Color_(), false);
741:     };
742: 
743:     template <typename Point_, typename Marker_, typename Color_>
744:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nStar(const Point_& p, int n, const Color_& color, bool useColor ) {
745:       Obj<supportSet> support = supportSet();
746:       support->insert(p);
747:       return this->__nStar(support, n, color, useColor);
748:     };

750:     template <typename Point_, typename Marker_, typename Color_>
751:     template<class InputSequence>
752:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nStar(const Obj<InputSequence>& points, int n) {
753:       return this->nStar(points, n, Color_(), false);
754:     };

756:     template <typename Point_, typename Marker_, typename Color_>
757:     template<class InputSequence>
758:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nStar(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor ) {
759:       Obj<supportSet> support = supportSet();
760:       support->insert(points->begin(), points->end());
761:       return this->__nStar(support, n, color, useColor);
762:     };
763: 
764:     template <typename Point_, typename Marker_, typename Color_>
765:     template<class InputSequence>
766:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::__nStar(Obj<InputSequence>& support, int n, const Color_& color, bool useColor) {
767:       Obj<supportSet> cap = supportSet();
768:       Obj<supportSet> star = supportSet();
769:       star->insert(support->begin(), support->end());
770:       for(int i = 0; i < n; ++i) {
771:         Obj<supportSet> tmp = support; support = cap; cap = tmp;
772:         support->clear();
773:         for(typename supportSet::iterator c_itor = cap->begin(); c_itor != cap->end(); ++c_itor) {
774:           Obj<typename traits::supportSequence> pSupport;
775:           if (useColor) {
776:             pSupport = this->support(*c_itor, color);
777:           } else {
778:             pSupport = this->support(*c_itor);
779:           }
780:           support->insert(pSupport->begin(), pSupport->end());
781:           star->insert(pSupport->begin(), pSupport->end());
782:         }
783:       }
784:       return star;
785:     };

787:     //
788:     // Lattice methods
789:     //

791:     template <typename Point_, typename Marker_, typename Color_>
792:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::meet(const Point_& p, const Point_& q) {
793:       return nMeet(p, q, this->depth());
794:     };
795: 
796:     template <typename Point_, typename Marker_, typename Color_>
797:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::meet(const Point_& p, const Point_& q, const Color_& color) {
798:       return nMeet(p, q, this->depth(), color);
799:     };

801:     template <typename Point_, typename Marker_, typename Color_>
802:     template<class InputSequence>
803:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1) {
804:       return nMeet(chain0, chain1, this->depth());
805:     };

807:     template <typename Point_, typename Marker_, typename Color_>
808:     template<class InputSequence>
809:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color) {
810:         return nMeet(chain0, chain1, this->depth(), color);
811:     };

813:     template <typename Point_, typename Marker_, typename Color_>
814:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::nMeet(const Point_& p, const Point_& q, int n) {
815:       if (n == 1) {
816:         std::vector<point_type> vecA, vecB;
817:         const Obj<typename traits::coneSequence>&     coneA  = this->cone(p);
818:         const typename traits::coneSequence::iterator beginA = coneA->begin();
819:         const typename traits::coneSequence::iterator endA   = coneA->end();
820:         const Obj<typename traits::coneSequence>&     coneB  = this->cone(q);
821:         const typename traits::coneSequence::iterator beginB = coneB->begin();
822:         const typename traits::coneSequence::iterator endB   = coneB->end();

824:         vecA.insert(vecA.begin(), beginA, endA);
825:         std::sort(vecA.begin(), vecA.end());
826:         vecB.insert(vecB.begin(), beginB, endB);
827:         std::sort(vecB.begin(), vecB.end());
828:         this->_meetSet->clear();
829:         std::set_intersection(vecA.begin(), vecA.end(), vecB.begin(), vecB.end(), std::insert_iterator<typename Sieve<Point_,Marker_,Color_>::coneSet>(*this->_meetSet, this->_meetSet->begin()));
830:         return this->_meetSet;
831:       }
832:       return nMeet(p, q, n, Color_(), false);
833:     };

835:     template <typename Point_, typename Marker_, typename Color_>
836:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::nMeet(const Point_& p, const Point_& q, int n, const Color_& color, bool useColor ) {
837:       Obj<coneSet> chain0 = new coneSet();
838:       Obj<coneSet> chain1 = new coneSet();
839:       chain0->insert(p);
840:       chain1->insert(q);
841:       return this->nMeet(chain0, chain1, n, color, useColor);
842:     };

844:     template <typename Point_, typename Marker_, typename Color_>
845:     template<class InputSequence>
846:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n) {
847:       return this->nMeet(chain0, chain1, n, Color_(), false);
848:     };
849: 
850:     template <typename Point_, typename Marker_, typename Color_>
851:     template<class InputSequence>
852:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1,int n,const Color_& color, bool useColor){
853:       // The strategy is to compute the intersection of cones over the chains, remove the intersection
854:       // and use the remaining two parts -- two disjoined components of the symmetric difference of cones -- as the new chains.
855:       // The intersections at each stage are accumulated and their union is the meet.
856:       // The iteration stops after n steps in addition to the meet of the initial chains or sooner if at least one of the chains is empty.
857:       Obj<coneSet> cone;

859:       this->_meetSet->clear();
860:       if((chain0->size() != 0) && (chain1->size() != 0)) {
861:         for(int i = 0; i <= n; ++i) {
862:           // Compute the intersection of chains and put it in meet at the same time removing it from c and cc
863:           std::set<point_type> intersect;
864:           //std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<coneSet>(meet, meet->begin()));
865:           std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<std::set<point_type> >(intersect, intersect.begin()));
866:           this->_meetSet->insert(intersect.begin(), intersect.end());
867:           for(typename std::set<point_type>::iterator i_iter = intersect.begin(); i_iter != intersect.end(); ++i_iter) {
868:             chain0->erase(chain0->find(*i_iter));
869:             chain1->erase(chain1->find(*i_iter));
870:           }
871:           // Replace each of the cones with a cone over it, and check if either is empty; if so, return what's in meet at the moment.
872:           cone = this->cone(chain0);
873:           chain0->insert(cone->begin(), cone->end());
874:           if(chain0->size() == 0) {
875:             break;
876:           }
877:           cone = this->cone(chain1);
878:           chain1->insert(cone->begin(), cone->end());
879:           if(chain1->size() == 0) {
880:             break;
881:           }
882:           // If both cones are empty, we should quit
883:         }
884:       }
885:       return this->_meetSet;
886:     };
887: 
888:     template <typename Point_, typename Marker_, typename Color_>
889:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::join(const Point_& p, const Point_& q) {
890:       return this->nJoin(p, q, this->depth());
891:     };
892: 
893:     template <typename Point_, typename Marker_, typename Color_>
894:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::join(const Point_& p, const Point_& q, const Color_& color) {
895:       return this->nJoin(p, q, this->depth(), color);
896:     };

898:     template <typename Point_, typename Marker_, typename Color_>
899:     template<class InputSequence>
900:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1) {
901:       return this->nJoin(chain0, chain1, this->depth());
902:     };
903: 
904:     template <typename Point_, typename Marker_, typename Color_>
905:     template<class InputSequence>
906:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color) {
907:       return this->nJoin(chain0, chain1, this->depth(), color);
908:     };

910:     // Warning: I think this can be much more efficient by eliminating copies
911:     template <typename Point_, typename Marker_, typename Color_>
912:     template<class InputSequence>
913:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin1(const Obj<InputSequence>& chain) {
914:       Obj<supportSet> join = new supportSet();
915:       std::set<point_type> intersectA;
916:       std::set<point_type> intersectB;
917:       int p = 0;

919:       //std::cout << "Doing nJoin1:" << std::endl;
920:       for(typename InputSequence::iterator p_iter = chain->begin(); p_iter != chain->end(); ++p_iter) {
921:         //std::cout << "  point " << *p_iter << std::endl;
922:         const Obj<typename traits::supportSequence>& support = this->support(*p_iter);

924:         join->insert(support->begin(), support->end());
925:         if (p == 0) {
926:           intersectB.insert(support->begin(), support->end());
927:           p++;
928:         } else {
929:           std::set_intersection(intersectA.begin(), intersectA.end(), join->begin(), join->end(), std::insert_iterator<std::set<point_type> >(intersectB, intersectB.begin()));
930:         }
931:         intersectA.clear();
932:         intersectA.insert(intersectB.begin(), intersectB.end());
933:         intersectB.clear();
934:         join->clear();
935:         //std::cout << "  intersection:" << std::endl;
936:         //for(typename std::set<point_type>::iterator i_iter = intersectA.begin(); i_iter != intersectA.end(); ++i_iter) {
937:         //  std::cout << "    " << *i_iter << std::endl;
938:         //}
939:       }
940:       join->insert(intersectA.begin(), intersectA.end());
941:       return join;
942:     };
943: 
944:     template <typename Point_, typename Marker_, typename Color_>
945:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin(const Point_& p, const Point_& q, int n) {
946:       return this->nJoin(p, q, n, Color_(), false);
947:     };
948: 
949:     template <typename Point_, typename Marker_, typename Color_>
950:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin(const Point_& p, const Point_& q, int n, const Color_& color, bool useColor) {
951:       Obj<supportSet> chain0 = supportSet();
952:       Obj<supportSet> chain1 = supportSet();
953:       chain0->insert(p);
954:       chain1->insert(q);
955:       return this->nJoin(chain0, chain1, n, color, useColor);
956:     };

958:     template <typename Point_, typename Marker_, typename Color_>
959:     template<class InputSequence>
960:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n) {
961:       return this->nJoin(chain0, chain1, n, Color_(), false);
962:     };

964:     template <typename Point_, typename Marker_, typename Color_>
965:     template<class InputSequence>
966:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin(const Obj<InputSequence>& chain0,const Obj<InputSequence>& chain1,int n,const Color_& color,bool useColor){
967:       // The strategy is to compute the intersection of supports over the chains, remove the intersection
968:       // and use the remaining two parts -- two disjoined components of the symmetric difference of supports -- as the new chains.
969:       // The intersections at each stage are accumulated and their union is the join.
970:       // The iteration stops after n steps in addition to the join of the initial chains or sooner if at least one of the chains is empty.
971:       Obj<supportSet> join = supportSet();
972:       Obj<supportSet> support;
973: //       std::cout << "Computing nJoin" << std::endl;
974: //       std::cout << "  chain 0:" << std::endl;
975: //       for(typename InputSequence::iterator i_iter = chain0->begin(); i_iter != chain0->end(); ++i_iter) {
976: //         std::cout << "    " << *i_iter << std::endl;
977: //       }
978: //       std::cout << "  chain 1:" << std::endl;
979: //       for(typename InputSequence::iterator i_iter = chain1->begin(); i_iter != chain1->end(); ++i_iter) {
980: //         std::cout << "    " << *i_iter << std::endl;
981: //       }
982:       if((chain0->size() != 0) && (chain1->size() != 0)) {
983:         for(int i = 0; i <= n; ++i) {
984: //           std::cout << "Level " << i << std::endl;
985:           // Compute the intersection of chains and put it in meet at the same time removing it from c and cc
986:           std::set<point_type> intersect;
987:           //std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<supportSet>(join.obj(), join->begin()));
988:           std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<std::set<point_type> >(intersect, intersect.begin()));
989:           join->insert(intersect.begin(), intersect.end());
990: //           std::cout << "  Join set:" << std::endl;
991: //           for(typename supportSet::iterator i_iter = join->begin(); i_iter != join->end(); ++i_iter) {
992: //             std::cout << "    " << *i_iter << std::endl;
993: //           }
994:           for(typename std::set<point_type>::iterator i_iter = intersect.begin(); i_iter != intersect.end(); ++i_iter) {
995:             chain0->erase(chain0->find(*i_iter));
996:             chain1->erase(chain1->find(*i_iter));
997:           }
998:           // Replace each of the supports with the support over it, and check if either is empty; if so, return what's in join at the moment.
999:           support = this->support(chain0);
1000:           chain0->insert(support->begin(), support->end());
1001:           if(chain0->size() == 0) {
1002:             break;
1003:           }
1004: //           std::cout << "  chain 0:" << std::endl;
1005: //           for(typename InputSequence::iterator i_iter = chain0->begin(); i_iter != chain0->end(); ++i_iter) {
1006: //             std::cout << "    " << *i_iter << std::endl;
1007: //           }
1008:           support = this->support(chain1);
1009:           chain1->insert(support->begin(), support->end());
1010:           if(chain1->size() == 0) {
1011:             break;
1012:           }
1013: //           std::cout << "  chain 1:" << std::endl;
1014: //           for(typename InputSequence::iterator i_iter = chain1->begin(); i_iter != chain1->end(); ++i_iter) {
1015: //             std::cout << "    " << *i_iter << std::endl;
1016: //           }
1017:           // If both supports are empty, we should quit
1018:         }
1019:       }
1020:       return join;
1021:     };

1023:     template <typename Point_, typename Marker_, typename Color_>
1024:     template<typename ostream_type>
1025:     void Sieve<Point_,Marker_,Color_>::view(ostream_type& os, const char* label = NULL, bool rawData = false){
1026:       if(label != NULL) {
1027:         os << "Viewing Sieve '" << label << "':" << std::endl;
1028:       }
1029:       else {
1030:         os << "Viewing a Sieve:" << std::endl;
1031:       }
1032:       if(!rawData) {
1033:         os << "cap --> base:" << std::endl;
1034:         Obj<typename traits::capSequence> cap = this->cap();
1035:         for(typename traits::capSequence::iterator capi = cap->begin(); capi != cap->end(); ++capi) {
1036:           Obj<typename traits::supportSequence> supp = this->support(*capi);
1037:           for(typename traits::supportSequence::iterator suppi = supp->begin(); suppi != supp->end(); ++suppi) {
1038:             os << *capi << "--(" << suppi.color() << ")-->" << *suppi << std::endl;
1039:           }
1040:         }
1041:         os << "base <-- cap:" << std::endl;
1042:         Obj<typename traits::baseSequence> base = this->base();
1043:         for(typename traits::baseSequence::iterator basei = base->begin(); basei != base->end(); ++basei) {
1044:           Obj<typename traits::coneSequence> cone = this->cone(*basei);
1045:           for(typename traits::coneSequence::iterator conei = cone->begin(); conei != cone->end(); ++conei) {
1046:             os << *basei <<  "<--(" << conei.color() << ")--" << *conei << std::endl;
1047:           }
1048:         }
1049:         os << "cap --> (outdegree, marker, depth, height):" << std::endl;
1050:         for(typename traits::capSequence::iterator capi = cap->begin(); capi != cap->end(); ++capi) {
1051:           os << *capi <<  "-->" << capi.degree() << ", " << capi.marker() << ", " << capi.depth() << ", " << capi.height() << std::endl;
1052:         }
1053:         os << "base --> (indegree, marker, depth, height):" << std::endl;
1054:         for(typename traits::baseSequence::iterator basei = base->begin(); basei != base->end(); ++basei) {
1055:           os << *basei <<  "-->" << basei.degree() << ", " << basei.marker() << ", " << basei.depth() << ", " << basei.height() << std::endl;
1056:         }
1057:       }
1058:       else {
1059:         os << "'raw' arrow set:" << std::endl;
1060:         for(typename traits::arrow_container_type::set_type::iterator ai = this->_arrows.set.begin(); ai != this->_arrows.set.end(); ai++)
1061:         {
1062:           typename traits::arrow_type arr = *ai;
1063:           os << arr << std::endl;
1064:         }
1065:         os << "'raw' base set:" << std::endl;
1066:         for(typename traits::base_container_type::set_type::iterator bi = this->_base.set.begin(); bi != this->_base.set.end(); bi++)
1067:         {
1068:           typename traits::base_container_type::traits::rec_type bp = *bi;
1069:           os << bp << std::endl;
1070:         }
1071:         os << "'raw' cap set:" << std::endl;
1072:         for(typename traits::cap_container_type::set_type::iterator ci = this->_cap.set.begin(); ci != this->_cap.set.end(); ci++)
1073:         {
1074:           typename traits::cap_container_type::traits::rec_type cp = *ci;
1075:           os << cp << std::endl;
1076:         }
1077:       }
1078:     };
1079:     template <typename Point_, typename Marker_, typename Color_>
1080:     void Sieve<Point_,Marker_,Color_>::view(const char* label = NULL, MPI_Comm comm = MPI_COMM_NULL) {
1081:         ostringstream txt;

1083:         if (this->debug()) {
1084:           std::cout << "viewing a Sieve, comm = " << this->comm() << ", commRank = " << this->commRank() << std::endl;
1085:         }
1086:         if(label != NULL) {
1087:           if(this->commRank() == 0) {
1088:             txt << "viewing Sieve :'" << label << "'" << std::endl;
1089:           }
1090:         }
1091:         else {
1092:           if(this->commRank() == 0) {
1093:             txt << "viewing a Sieve" << std::endl;
1094:           }
1095:         }
1096:         if(this->commRank() == 0) {
1097:           txt << "cap --> base:\n";
1098:         }
1099:         typename traits::capSequence cap   = this->cap();
1100:         typename traits::baseSequence base = this->base();
1101:         if(cap.empty()) {
1102:           txt << "[" << this->commRank() << "]: empty" << std::endl;
1103:         }
1104:         for(typename traits::capSequence::iterator capi = cap.begin(); capi != cap.end(); capi++) {
1105:           const Obj<typename traits::supportSequence>& supp = this->support(*capi);
1106:           const typename traits::supportSequence::iterator suppEnd = supp->end();

1108:           for(typename traits::supportSequence::iterator suppi = supp->begin(); suppi != suppEnd; suppi++) {
1109:             txt << "[" << this->commRank() << "]: " << *capi << "--(" << suppi.color() << ")-->" << *suppi << std::endl;
1110:           }
1111:         }
1112:         PetscSynchronizedPrintf(this->comm(), txt.str().c_str());
1113:         PetscSynchronizedFlush(this->comm());
1114:         //
1115:         ostringstream txt1;
1116:         if(this->commRank() == 0) {
1117:           txt1 << "base --> cap:\n";
1118:         }
1119:         if(base.empty()) {
1120:           txt1 << "[" << this->commRank() << "]: empty" << std::endl;
1121:         }
1122:         for(typename traits::baseSequence::iterator basei = base.begin(); basei != base.end(); basei++) {
1123:           const Obj<typename traits::coneSequence>& cone = this->cone(*basei);
1124:           const typename traits::coneSequence::iterator coneEnd = cone->end();

1126:           for(typename traits::coneSequence::iterator conei = cone->begin(); conei != coneEnd; conei++) {
1127:             txt1 << "[" << this->commRank() << "]: " << *basei << "<--(" << conei.color() << ")--" << *conei << std::endl;
1128:           }
1129:         }
1130:         //
1131:         PetscSynchronizedPrintf(this->comm(), txt1.str().c_str());
1132:         PetscSynchronizedFlush(this->comm());
1133:         //
1134:         ostringstream txt2;
1135:         if(this->commRank() == 0) {
1136:           txt2 << "cap <point, outdegree, marker, depth, height>:\n";
1137:         }
1138:         txt2 << "[" << this->commRank() << "]:  [";
1139:         for(typename traits::capSequence::iterator capi = cap.begin(); capi != cap.end(); capi++) {
1140:           txt2 << " <" << *capi << ", " << capi.degree() << ", " << capi.marker() << ", " << capi.depth() << ", " << capi.height() << ">";
1141:         }
1142:         txt2 << " ]" << std::endl;
1143:         //
1144:         PetscSynchronizedPrintf(this->comm(), txt2.str().c_str());
1145:         PetscSynchronizedFlush(this->comm());
1146:         //
1147:         ostringstream txt3;
1148:         if(this->commRank() == 0) {
1149:           txt3 << "base <point, indegree, marker, depth, height>:\n";
1150:         }
1151:         txt3 << "[" << this->commRank() << "]:  [";
1152:         for(typename traits::baseSequence::iterator basei = base.begin(); basei != base.end(); basei++) {
1153:           txt3 << " <" << *basei << "," << basei.degree() << ", " << basei.marker() << ", " << basei.depth() << ", " << basei.height() << ">";
1154:         }
1155:         txt3 << " ]" << std::endl;
1156:         //
1157:         PetscSynchronizedPrintf(this->comm(), txt3.str().c_str());
1158:         PetscSynchronizedFlush(this->comm());
1159:     };
1160:     //
1161:     // Structural queries
1162:     //
1163:     template <typename Point_, typename Marker_, typename Color_>
1164:     void Sieve<Point_,Marker_,Color_>::setMarker(const point_type& p, const marker_type& marker) {
1165:       typename ::boost::multi_index::index<typename traits::base_container_type::set_type,typename traits::base_container_type::traits::pointTag>::type& bIndex = ::boost::multi_index::get<typename traits::base_container_type::traits::pointTag>(this->_base.set);
1166:       typename ::boost::multi_index::index<typename traits::cap_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type& cIndex = ::boost::multi_index::get<typename traits::cap_container_type::traits::pointTag>(this->_cap.set);

1168:       if (bIndex.find(p) != bIndex.end()) {
1169:         bIndex.modify(bIndex.find(p), changeMarker(marker));
1170:       }
1171:       if (cIndex.find(p) != cIndex.end()) {
1172:         cIndex.modify(cIndex.find(p), changeMarker(marker));
1173:       }
1174:       this->_markers->insert(marker);
1175:     };

1177:     template <typename Point_, typename Marker_, typename Color_>
1178:     template <typename Sequence>
1179:     void Sieve<Point_,Marker_,Color_>::setMarker(const Obj<Sequence>& points, const marker_type& marker) {
1180:       for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1181:         this->setMarker(*p_iter, marker);
1182:       }
1183:     };

1185:     template <typename Point_, typename Marker_, typename Color_>
1186:     int Sieve<Point_,Marker_,Color_>::depth() {
1187:       return this->maxDepth;
1188:     };
1189:     template <typename Point_, typename Marker_, typename Color_>
1190:     int Sieve<Point_,Marker_,Color_>::depth(const point_type& p) {
1191:       const typename ::boost::multi_index::index<typename traits::base_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type& i = ::boost::multi_index::get<typename traits::base_container_type::traits::pointTag>(this->_base.set);
1192:       if (i.find(p) != i.end()) {
1193:         return i.find(p)->depth;
1194:       }
1195:       return 0;
1196:     };
1197:     template <typename Point_, typename Marker_, typename Color_>
1198:     template<typename InputSequence>
1199:     int Sieve<Point_,Marker_,Color_>::depth(const Obj<InputSequence>& points) {
1200:       const typename ::boost::multi_index::index<typename traits::base_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type& i = ::boost::multi_index::get<typename traits::base_container_type::traits::pointTag>(this->_base.set);
1201:       int maxDepth = 0;
1202: 
1203:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
1204:         if (i.find(*iter) != i.end()) {
1205:           maxDepth = std::max(maxDepth, i.find(*iter)->depth);
1206:         }
1207:       }
1208:       return maxDepth;
1209:     };
1210:     template <typename Point_, typename Marker_, typename Color_>
1211:     int Sieve<Point_,Marker_,Color_>::height() {
1212:       return this->maxHeight;
1213:     };
1214:     template <typename Point_, typename Marker_, typename Color_>
1215:     int Sieve<Point_,Marker_,Color_>::height(const point_type& p) {
1216:       const typename ::boost::multi_index::index<typename traits::cap_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type& i = ::boost::multi_index::get<typename traits::cap_container_type::traits::pointTag>(this->_cap.set);
1217:       if (i.find(p) != i.end()) {
1218:         return i.find(p)->height;
1219:       }
1220:       return 0;
1221:     };
1222:     template <typename Point_, typename Marker_, typename Color_>
1223:     template<typename InputSequence>
1224:     int Sieve<Point_,Marker_,Color_>::height(const Obj<InputSequence>& points) {
1225:       const typename ::boost::multi_index::index<typename traits::cap_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type& i = ::boost::multi_index::get<typename traits::cap_container_type::traits::pointTag>(this->_cap.set);
1226:       int maxHeight = 0;
1227: 
1228:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
1229:         if (i.find(*iter) != i.end()) {
1230:           maxHeight = std::max(maxHeight, i.find(*iter)->height);
1231:         }
1232:       }
1233:       return maxHeight;
1234:     };

1236:     template <typename Point_, typename Marker_, typename Color_>
1237:     int Sieve<Point_,Marker_,Color_>::diameter() {
1238:       int globalDiameter;
1239:       int MPI_Allreduce(&this->graphDiameter, &globalDiameter, 1, MPI_INT, MPI_MAX, this->comm());
1240:       CHKMPIERROR(ierr, ERRORMSG("Error in MPI_Allreduce"));
1241:       return globalDiameter;
1242:     };
1243:     template <typename Point_, typename Marker_, typename Color_>
1244:     int Sieve<Point_,Marker_,Color_>::diameter(const point_type& p) {
1245:       return this->depth(p) + this->height(p);
1246:     };

1248:     template <typename Point_, typename Marker_, typename Color_>
1249:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::depthSequence> Sieve<Point_,Marker_,Color_>::depthStratum(int d) {
1250:       if (d == 0) {
1251:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::depthMarkerTag>(this->_cap.set), d);
1252:       } else {
1253:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::base_container_type::traits::depthMarkerTag>(this->_base.set), d);
1254:       }
1255:     };
1256:     template <typename Point_, typename Marker_, typename Color_>
1257:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::depthSequence> Sieve<Point_,Marker_,Color_>::depthStratum(int d, marker_type m) {
1258:       if (d == 0) {
1259:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::depthMarkerTag>(this->_cap.set), d, m);
1260:       } else {
1261:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::base_container_type::traits::depthMarkerTag>(this->_base.set), d, m);
1262:       }
1263:     };
1264:     template <typename Point_, typename Marker_, typename Color_>
1265:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::heightSequence> Sieve<Point_,Marker_,Color_>::heightStratum(int h) {
1266:       if (h == 0) {
1267:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::base_container_type::traits::heightMarkerTag>(this->_base.set), h);
1268:       } else {
1269:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::heightMarkerTag>(this->_cap.set), h);
1270:       }
1271:     };
1272:     template <typename Point_, typename Marker_, typename Color_>
1273:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::heightSequence> Sieve<Point_,Marker_,Color_>::heightStratum(int h, marker_type m) {
1274:       if (h == 0) {
1275:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::base_container_type::traits::heightMarkerTag>(this->_base.set), h, m);
1276:       } else {
1277:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::heightMarkerTag>(this->_cap.set), h, m);
1278:       }
1279:     };
1280:     template <typename Point_, typename Marker_, typename Color_>
1281:     template<class InputSequence>
1282:     void Sieve<Point_,Marker_,Color_>::__computeClosureHeights(const Obj<InputSequence>& points) {
1283:       typename ::boost::multi_index::index<typename traits::cap_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type& index = ::boost::multi_index::get<typename traits::cap_container_type::traits::pointTag>(this->_cap.set);
1284:       typename ::boost::multi_index::index<typename traits::base_container_type::set_type,typename traits::base_container_type::traits::pointTag>::type& bIndex = ::boost::multi_index::get<typename traits::base_container_type::traits::pointTag>(this->_base.set);
1285:       Obj<coneSet> modifiedPoints = coneSet();
1286: 
1287:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
1288:         // Compute the max height of the points in the support of p, and add 1
1289:         int h0 = this->height(*p_itor);
1290:         int h1 = this->height(this->support(*p_itor)) + 1;
1291:         if(h1 != h0) {
1292:           typename ::boost::multi_index::index<typename traits::base_container_type::set_type,typename traits::base_container_type::traits::pointTag>::type::iterator bIter = bIndex.find(*p_itor);

1294:           index.modify(index.find(*p_itor), changeHeight(h1));
1295:           if (bIter != bIndex.end()) {
1296:             bIndex.modify(bIter, changeHeight(h1));
1297:           }
1298:           if (h1 > this->maxHeight) this->maxHeight = h1;
1299:           modifiedPoints->insert(*p_itor);
1300:         }
1301:       }
1302:       // FIX: We would like to avoid the copy here with cone()
1303:       if(modifiedPoints->size() > 0) {
1304:         this->__computeClosureHeights(this->cone(modifiedPoints));
1305:       }
1306:     };
1307:     template <typename Point_, typename Marker_, typename Color_>
1308:     template<class InputSequence>
1309:     void Sieve<Point_,Marker_,Color_>::__computeStarDepths(const Obj<InputSequence>& points) {
1310:       typename ::boost::multi_index::index<typename traits::base_container_type::set_type,typename traits::base_container_type::traits::pointTag>::type& index = ::boost::multi_index::get<typename traits::base_container_type::traits::pointTag>(this->_base.set);
1311:       typename ::boost::multi_index::index<typename traits::cap_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type& cIndex = ::boost::multi_index::get<typename traits::cap_container_type::traits::pointTag>(this->_cap.set);
1312:       Obj<supportSet> modifiedPoints = supportSet();
1313:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
1314:         // Compute the max depth of the points in the support of p, and add 1
1315:         int d0 = this->depth(*p_itor);
1316:         int d1 = this->depth(this->cone(*p_itor)) + 1;
1317:         if(d1 != d0) {
1318:           typename ::boost::multi_index::index<typename traits::cap_container_type::set_type,typename traits::cap_container_type::traits::pointTag>::type::iterator cIter = cIndex.find(*p_itor);

1320:           index.modify(index.find(*p_itor), changeDepth(d1));
1321:           if (cIter != cIndex.end()) {
1322:             cIndex.modify(cIter, changeDepth(d1));
1323:           }
1324:           if (d1 > this->maxDepth) this->maxDepth = d1;
1325:           modifiedPoints->insert(*p_itor);
1326:         }
1327:       }
1328:       // FIX: We would like to avoid the copy here with cone()
1329:       if(modifiedPoints->size() > 0) {
1330:         this->__computeStarDepths(this->support(modifiedPoints));
1331:       }
1332:     };
1335:     template <typename Point_, typename Marker_, typename Color_>
1336:     void Sieve<Point_,Marker_,Color_>::stratify(bool show) {
1337:       ALE_LOG_EVENT_BEGIN;
1338:       // FIX: We would like to avoid the copy here with cone() and support()
1339:       this->__computeClosureHeights(this->cone(this->leaves()));
1340:       this->__computeStarDepths(this->support(this->roots()));
1341: 
1342:       Obj<typename traits::capSequence> base = this->base();

1344:       for(typename traits::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
1345:         maxDepth = std::max(maxDepth, b_iter.depth());
1346:         //b_iter.setDegree(this->cone(*b_iter)->size());
1347:         this->_base.adjustDegree(*b_iter, this->cone(*b_iter)->size());
1348:       }
1349:       Obj<typename traits::capSequence> cap = this->cap();

1351:       for(typename traits::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
1352:         maxHeight = std::max(maxHeight, c_iter.height());
1353:         //c_iter.setDegree(this->support(*c_iter)->size());
1354:         this->_cap.adjustDegree(*c_iter, this->support(*c_iter)->size());
1355:       }
1356:       if (this->debug() || show) {
1357: //         const typename ::boost::multi_index::index<StratumSet,point>::type& points = ::boost::multi_index::get<point>(this->strata);
1358: //         for(typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = points.begin(); i != points.end(); i++) {
1359: //           std::cout << *i << std::endl;
1360: //         }
1361:       }
1362:       ALE_LOG_EVENT_END;
1363:     };
1364:     //
1365:     // Structural manipulation
1366:     //
1367: 
1368: } // namespace ALE

1370: #endif