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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

488:       template<class InputSequence>
489:       Obj<supportSet> nJoin(const Obj<InputSequence>& chain, const int depth);

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

509:       int height();
510:       int height(const point_type& p);
511:       template<typename InputSequence> int height(const Obj<InputSequence>& points);

513:       int diameter();
514:       int diameter(const point_type& p);

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

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

522:       Obj<typename traits::markerSequence> markerStratum(marker_type m);
523: 
524:       void setStratification(bool doStratify) {this->doStratify = doStratify;};

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

528:       void stratify(bool show = false);
529:     protected:
530:       Obj<markerSet> _markers;
531:       Obj<coneSet>   _meetSet;
532:     public:
533:       //
534:       // Structural manipulation
535:       //

537:       struct changeMarker {
538:         changeMarker(int newMarker) : newMarker(newMarker) {};

540:         void operator()(typename traits::base_container_type::traits::rec_type& p) {
541:           p.marker = newMarker;
542:         }
543:       private:
544:         marker_type newMarker;
545:       };

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

550:       void clearMarkers() {this->_markers.clear();};
551:       Obj<markerSet> markers() {return this->_markers;};
552:     private:
553:       struct changeHeight {
554:         changeHeight(int newHeight) : newHeight(newHeight) {};

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

565:       struct changeDepth {
566:         changeDepth(int newDepth) : newDepth(newDepth) {};

568:         void operator()(typename traits::base_container_type::traits::rec_type& p) {
569:           p.depth = newDepth;
570:         }
571:       private:
572:         int newDepth;
573:       };

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

578:     template <typename Point_, typename Marker_, typename Color_>
579:     Obj<typename Sieve<Point_,Marker_,Color_>::coneArray> Sieve<Point_,Marker_,Color_>::nCone(const Point_& p, int n) {
580:       return this->nCone(p, n, Color_(), false);
581:     };

583:     template <typename Point_, typename Marker_, typename Color_>
584:     Obj<typename Sieve<Point_,Marker_,Color_>::coneArray> Sieve<Point_,Marker_,Color_>::nCone(const Point_& p, int n, const Color_& color, bool useColor) {
585:       Obj<coneArray> cone = new coneArray();
586:       Obj<coneSet>   seen = new coneSet();

588:       this->__nCone(this->cone(p), n-1, color, useColor, cone, seen);
589:       return cone;
590:     };

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

614:     template <typename Point_, typename Marker_, typename Color_>
615:     template<class InputSequence>
616:     Obj<typename Sieve<Point_,Marker_,Color_>::coneSet> Sieve<Point_,Marker_,Color_>::nCone(const Obj<InputSequence>& points, int n) {
617:       return this->nCone(points, n, Color_(), false);
618:     };

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

628:     template <typename Point_, typename Marker_, typename Color_>
629:     template<class InputSequence>
630:     Obj<typename Sieve<Point_,Marker_,Color_>::coneSet> Sieve<Point_,Marker_,Color_>::__nCone(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor) {
631:       Obj<coneSet> base = new coneSet();

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

651:     template <typename Point_, typename Marker_, typename Color_>
652:     Obj<typename Sieve<Point_,Marker_,Color_>::supportArray> Sieve<Point_,Marker_,Color_>::nSupport(const Point_& p, int n) {
653:       return this->nSupport(p, n, Color_(), false);
654:     };

656:     template <typename Point_, typename Marker_, typename Color_>
657:     Obj<typename Sieve<Point_,Marker_,Color_>::supportArray> Sieve<Point_,Marker_,Color_>::nSupport(const Point_& p, int n, const Color_& color, bool useColor) {
658:       Obj<supportArray> cone = new supportArray();
659:       Obj<supportSet>   seen = new supportSet();

661:       this->__nSupport(this->support(p), n-1, color, useColor, cone, seen);
662:       return cone;
663:     };

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

687:     template <typename Point_, typename Marker_, typename Color_>
688:     template<class InputSequence>
689:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nSupport(const Obj<InputSequence>& points, int n) {
690:       return this->nSupport(points, n, Color_(), false);
691:     };

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

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

754:     template <typename Point_, typename Marker_, typename Color_>
755:     template<class InputSequence>
756:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nStar(const Obj<InputSequence>& points, int n) {
757:       return this->nStar(points, n, Color_(), false);
758:     };

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

791:     //
792:     // Lattice methods
793:     //

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

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

811:     template <typename Point_, typename Marker_, typename Color_>
812:     template<class InputSequence>
813:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color) {
814:         return nMeet(chain0, chain1, this->depth(), color);
815:     };

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

828:         vecA.insert(vecA.begin(), beginA, endA);
829:         std::sort(vecA.begin(), vecA.end());
830:         vecB.insert(vecB.begin(), beginB, endB);
831:         std::sort(vecB.begin(), vecB.end());
832:         this->_meetSet->clear();
833:         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()));
834:         return this->_meetSet;
835:       }
836:       return nMeet(p, q, n, Color_(), false);
837:     };

839:     template <typename Point_, typename Marker_, typename Color_>
840:     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 ) {
841:       Obj<coneSet> chain0 = new coneSet();
842:       Obj<coneSet> chain1 = new coneSet();
843:       chain0->insert(p);
844:       chain1->insert(q);
845:       return this->nMeet(chain0, chain1, n, color, useColor);
846:     };

848:     template <typename Point_, typename Marker_, typename Color_>
849:     template<class InputSequence>
850:     const Obj<typename Sieve<Point_,Marker_,Color_>::coneSet>& Sieve<Point_,Marker_,Color_>::nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n) {
851:       return this->nMeet(chain0, chain1, n, Color_(), false);
852:     };
853: 
854:     template <typename Point_, typename Marker_, typename Color_>
855:     template<class InputSequence>
856:     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){
857:       // The strategy is to compute the intersection of cones over the chains, remove the intersection
858:       // and use the remaining two parts -- two disjoined components of the symmetric difference of cones -- as the new chains.
859:       // The intersections at each stage are accumulated and their union is the meet.
860:       // 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.
861:       Obj<coneSet> cone;

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

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

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

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

928:         join->insert(support->begin(), support->end());
929:         if (p == 0) {
930:           intersectB.insert(support->begin(), support->end());
931:           p++;
932:         } else {
933:           std::set_intersection(intersectA.begin(), intersectA.end(), join->begin(), join->end(), std::insert_iterator<std::set<point_type> >(intersectB, intersectB.begin()));
934:         }
935:         intersectA.clear();
936:         intersectA.insert(intersectB.begin(), intersectB.end());
937:         intersectB.clear();
938:         join->clear();
939:         //std::cout << "  intersection:" << std::endl;
940:         //for(typename std::set<point_type>::iterator i_iter = intersectA.begin(); i_iter != intersectA.end(); ++i_iter) {
941:         //  std::cout << "    " << *i_iter << std::endl;
942:         //}
943:       }
944:       join->insert(intersectA.begin(), intersectA.end());
945:       return join;
946:     };

948:     // Warning: I think this can be much more efficient by eliminating copies
949:     template <typename Point_, typename Marker_, typename Color_>
950:     template<class InputSequence>
951:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin(const Obj<InputSequence>& chain, const int depth) {
952:       Obj<supportSet> join = new supportSet();
953:       std::set<point_type> intersectA;
954:       std::set<point_type> intersectB;
955:       int p = 0;

957:       //std::cout << "Doing nJoin1:" << std::endl;
958:       for(typename InputSequence::iterator p_iter = chain->begin(); p_iter != chain->end(); ++p_iter) {
959:         //std::cout << "  point " << *p_iter << std::endl;
960:         const Obj<supportArray> support = this->nSupport(*p_iter, depth);

962:         join->insert(support->begin(), support->end());
963:         if (p == 0) {
964:           intersectB.insert(support->begin(), support->end());
965:           p++;
966:         } else {
967:           std::set_intersection(intersectA.begin(), intersectA.end(), join->begin(), join->end(), std::insert_iterator<std::set<point_type> >(intersectB, intersectB.begin()));
968:         }
969:         intersectA.clear();
970:         intersectA.insert(intersectB.begin(), intersectB.end());
971:         intersectB.clear();
972:         join->clear();
973:         //std::cout << "  intersection:" << std::endl;
974:         //for(typename std::set<point_type>::iterator i_iter = intersectA.begin(); i_iter != intersectA.end(); ++i_iter) {
975:         //  std::cout << "    " << *i_iter << std::endl;
976:         //}
977:       }
978:       join->insert(intersectA.begin(), intersectA.end());
979:       return join;
980:     };
981: 
982:     template <typename Point_, typename Marker_, typename Color_>
983:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin(const Point_& p, const Point_& q, int n) {
984:       return this->nJoin(p, q, n, Color_(), false);
985:     };
986: 
987:     template <typename Point_, typename Marker_, typename Color_>
988:     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) {
989:       Obj<supportSet> chain0 = supportSet();
990:       Obj<supportSet> chain1 = supportSet();
991:       chain0->insert(p);
992:       chain1->insert(q);
993:       return this->nJoin(chain0, chain1, n, color, useColor);
994:     };

996:     template <typename Point_, typename Marker_, typename Color_>
997:     template<class InputSequence>
998:     Obj<typename Sieve<Point_,Marker_,Color_>::supportSet> Sieve<Point_,Marker_,Color_>::nJoin(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n) {
999:       return this->nJoin(chain0, chain1, n, Color_(), false);
1000:     };

1002:     template <typename Point_, typename Marker_, typename Color_>
1003:     template<class InputSequence>
1004:     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){
1005:       // The strategy is to compute the intersection of supports over the chains, remove the intersection
1006:       // and use the remaining two parts -- two disjoined components of the symmetric difference of supports -- as the new chains.
1007:       // The intersections at each stage are accumulated and their union is the join.
1008:       // 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.
1009:       Obj<supportSet> join = supportSet();
1010:       Obj<supportSet> support;
1011: //       std::cout << "Computing nJoin" << std::endl;
1012: //       std::cout << "  chain 0:" << std::endl;
1013: //       for(typename InputSequence::iterator i_iter = chain0->begin(); i_iter != chain0->end(); ++i_iter) {
1014: //         std::cout << "    " << *i_iter << std::endl;
1015: //       }
1016: //       std::cout << "  chain 1:" << std::endl;
1017: //       for(typename InputSequence::iterator i_iter = chain1->begin(); i_iter != chain1->end(); ++i_iter) {
1018: //         std::cout << "    " << *i_iter << std::endl;
1019: //       }
1020:       if((chain0->size() != 0) && (chain1->size() != 0)) {
1021:         for(int i = 0; i <= n; ++i) {
1022: //           std::cout << "Level " << i << std::endl;
1023:           // Compute the intersection of chains and put it in meet at the same time removing it from c and cc
1024:           std::set<point_type> intersect;
1025:           //std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<supportSet>(join.obj(), join->begin()));
1026:           std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<std::set<point_type> >(intersect, intersect.begin()));
1027:           join->insert(intersect.begin(), intersect.end());
1028: //           std::cout << "  Join set:" << std::endl;
1029: //           for(typename supportSet::iterator i_iter = join->begin(); i_iter != join->end(); ++i_iter) {
1030: //             std::cout << "    " << *i_iter << std::endl;
1031: //           }
1032:           for(typename std::set<point_type>::iterator i_iter = intersect.begin(); i_iter != intersect.end(); ++i_iter) {
1033:             chain0->erase(chain0->find(*i_iter));
1034:             chain1->erase(chain1->find(*i_iter));
1035:           }
1036:           // 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.
1037:           support = this->support(chain0);
1038:           chain0->insert(support->begin(), support->end());
1039:           if(chain0->size() == 0) {
1040:             break;
1041:           }
1042: //           std::cout << "  chain 0:" << std::endl;
1043: //           for(typename InputSequence::iterator i_iter = chain0->begin(); i_iter != chain0->end(); ++i_iter) {
1044: //             std::cout << "    " << *i_iter << std::endl;
1045: //           }
1046:           support = this->support(chain1);
1047:           chain1->insert(support->begin(), support->end());
1048:           if(chain1->size() == 0) {
1049:             break;
1050:           }
1051: //           std::cout << "  chain 1:" << std::endl;
1052: //           for(typename InputSequence::iterator i_iter = chain1->begin(); i_iter != chain1->end(); ++i_iter) {
1053: //             std::cout << "    " << *i_iter << std::endl;
1054: //           }
1055:           // If both supports are empty, we should quit
1056:         }
1057:       }
1058:       return join;
1059:     };

1061:     template <typename Point_, typename Marker_, typename Color_>
1062:     template<typename ostream_type>
1063:     void Sieve<Point_,Marker_,Color_>::view(ostream_type& os, const char* label = NULL, bool rawData = false){
1064:       if(label != NULL) {
1065:         os << "Viewing Sieve '" << label << "':" << std::endl;
1066:       }
1067:       else {
1068:         os << "Viewing a Sieve:" << std::endl;
1069:       }
1070:       if(!rawData) {
1071:         os << "cap --> base:" << std::endl;
1072:         Obj<typename traits::capSequence> cap = this->cap();
1073:         for(typename traits::capSequence::iterator capi = cap->begin(); capi != cap->end(); ++capi) {
1074:           Obj<typename traits::supportSequence> supp = this->support(*capi);
1075:           for(typename traits::supportSequence::iterator suppi = supp->begin(); suppi != supp->end(); ++suppi) {
1076:             os << *capi << "--(" << suppi.color() << ")-->" << *suppi << std::endl;
1077:           }
1078:         }
1079:         os << "base <-- cap:" << std::endl;
1080:         Obj<typename traits::baseSequence> base = this->base();
1081:         for(typename traits::baseSequence::iterator basei = base->begin(); basei != base->end(); ++basei) {
1082:           Obj<typename traits::coneSequence> cone = this->cone(*basei);
1083:           for(typename traits::coneSequence::iterator conei = cone->begin(); conei != cone->end(); ++conei) {
1084:             os << *basei <<  "<--(" << conei.color() << ")--" << *conei << std::endl;
1085:           }
1086:         }
1087:         os << "cap --> (outdegree, marker, depth, height):" << std::endl;
1088:         for(typename traits::capSequence::iterator capi = cap->begin(); capi != cap->end(); ++capi) {
1089:           os << *capi <<  "-->" << capi.degree() << ", " << capi.marker() << ", " << capi.depth() << ", " << capi.height() << std::endl;
1090:         }
1091:         os << "base --> (indegree, marker, depth, height):" << std::endl;
1092:         for(typename traits::baseSequence::iterator basei = base->begin(); basei != base->end(); ++basei) {
1093:           os << *basei <<  "-->" << basei.degree() << ", " << basei.marker() << ", " << basei.depth() << ", " << basei.height() << std::endl;
1094:         }
1095:       }
1096:       else {
1097:         os << "'raw' arrow set:" << std::endl;
1098:         for(typename traits::arrow_container_type::set_type::iterator ai = this->_arrows.set.begin(); ai != this->_arrows.set.end(); ai++)
1099:         {
1100:           typename traits::arrow_type arr = *ai;
1101:           os << arr << std::endl;
1102:         }
1103:         os << "'raw' base set:" << std::endl;
1104:         for(typename traits::base_container_type::set_type::iterator bi = this->_base.set.begin(); bi != this->_base.set.end(); bi++)
1105:         {
1106:           typename traits::base_container_type::traits::rec_type bp = *bi;
1107:           os << bp << std::endl;
1108:         }
1109:         os << "'raw' cap set:" << std::endl;
1110:         for(typename traits::cap_container_type::set_type::iterator ci = this->_cap.set.begin(); ci != this->_cap.set.end(); ci++)
1111:         {
1112:           typename traits::cap_container_type::traits::rec_type cp = *ci;
1113:           os << cp << std::endl;
1114:         }
1115:       }
1116:     };
1117:     template <typename Point_, typename Marker_, typename Color_>
1118:     void Sieve<Point_,Marker_,Color_>::view(const char* label = NULL, MPI_Comm comm = MPI_COMM_NULL) {
1119:         ostringstream txt;

1121:         if (this->debug()) {
1122:           std::cout << "viewing a Sieve, comm = " << this->comm() << ", commRank = " << this->commRank() << std::endl;
1123:         }
1124:         if(label != NULL) {
1125:           if(this->commRank() == 0) {
1126:             txt << "viewing Sieve :'" << label << "'" << std::endl;
1127:           }
1128:         }
1129:         else {
1130:           if(this->commRank() == 0) {
1131:             txt << "viewing a Sieve" << std::endl;
1132:           }
1133:         }
1134:         if(this->commRank() == 0) {
1135:           txt << "cap --> base:\n";
1136:         }
1137:         typename traits::capSequence cap   = this->cap();
1138:         typename traits::baseSequence base = this->base();
1139:         if(cap.empty()) {
1140:           txt << "[" << this->commRank() << "]: empty" << std::endl;
1141:         }
1142:         for(typename traits::capSequence::iterator capi = cap.begin(); capi != cap.end(); capi++) {
1143:           const Obj<typename traits::supportSequence>& supp = this->support(*capi);
1144:           const typename traits::supportSequence::iterator suppEnd = supp->end();

1146:           for(typename traits::supportSequence::iterator suppi = supp->begin(); suppi != suppEnd; suppi++) {
1147:             txt << "[" << this->commRank() << "]: " << *capi << "--(" << suppi.color() << ")-->" << *suppi << std::endl;
1148:           }
1149:         }
1150:         PetscSynchronizedPrintf(this->comm(), txt.str().c_str());
1151:         PetscSynchronizedFlush(this->comm());
1152:         //
1153:         ostringstream txt1;
1154:         if(this->commRank() == 0) {
1155:           txt1 << "base --> cap:\n";
1156:         }
1157:         if(base.empty()) {
1158:           txt1 << "[" << this->commRank() << "]: empty" << std::endl;
1159:         }
1160:         for(typename traits::baseSequence::iterator basei = base.begin(); basei != base.end(); basei++) {
1161:           const Obj<typename traits::coneSequence>& cone = this->cone(*basei);
1162:           const typename traits::coneSequence::iterator coneEnd = cone->end();

1164:           for(typename traits::coneSequence::iterator conei = cone->begin(); conei != coneEnd; conei++) {
1165:             txt1 << "[" << this->commRank() << "]: " << *basei << "<--(" << conei.color() << ")--" << *conei << std::endl;
1166:           }
1167:         }
1168:         //
1169:         PetscSynchronizedPrintf(this->comm(), txt1.str().c_str());
1170:         PetscSynchronizedFlush(this->comm());
1171:         //
1172:         ostringstream txt2;
1173:         if(this->commRank() == 0) {
1174:           txt2 << "cap <point, outdegree, marker, depth, height>:\n";
1175:         }
1176:         txt2 << "[" << this->commRank() << "]:  [";
1177:         for(typename traits::capSequence::iterator capi = cap.begin(); capi != cap.end(); capi++) {
1178:           txt2 << " <" << *capi << ", " << capi.degree() << ", " << capi.marker() << ", " << capi.depth() << ", " << capi.height() << ">";
1179:         }
1180:         txt2 << " ]" << std::endl;
1181:         //
1182:         PetscSynchronizedPrintf(this->comm(), txt2.str().c_str());
1183:         PetscSynchronizedFlush(this->comm());
1184:         //
1185:         ostringstream txt3;
1186:         if(this->commRank() == 0) {
1187:           txt3 << "base <point, indegree, marker, depth, height>:\n";
1188:         }
1189:         txt3 << "[" << this->commRank() << "]:  [";
1190:         for(typename traits::baseSequence::iterator basei = base.begin(); basei != base.end(); basei++) {
1191:           txt3 << " <" << *basei << "," << basei.degree() << ", " << basei.marker() << ", " << basei.depth() << ", " << basei.height() << ">";
1192:         }
1193:         txt3 << " ]" << std::endl;
1194:         //
1195:         PetscSynchronizedPrintf(this->comm(), txt3.str().c_str());
1196:         PetscSynchronizedFlush(this->comm());
1197:     };
1198:     //
1199:     // Structural queries
1200:     //
1201:     template <typename Point_, typename Marker_, typename Color_>
1202:     void Sieve<Point_,Marker_,Color_>::setMarker(const point_type& p, const marker_type& marker) {
1203:       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);
1204:       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);

1206:       if (bIndex.find(p) != bIndex.end()) {
1207:         bIndex.modify(bIndex.find(p), changeMarker(marker));
1208:       }
1209:       if (cIndex.find(p) != cIndex.end()) {
1210:         cIndex.modify(cIndex.find(p), changeMarker(marker));
1211:       }
1212:       this->_markers->insert(marker);
1213:     };

1215:     template <typename Point_, typename Marker_, typename Color_>
1216:     template <typename Sequence>
1217:     void Sieve<Point_,Marker_,Color_>::setMarker(const Obj<Sequence>& points, const marker_type& marker) {
1218:       for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1219:         this->setMarker(*p_iter, marker);
1220:       }
1221:     };

1223:     template <typename Point_, typename Marker_, typename Color_>
1224:     int Sieve<Point_,Marker_,Color_>::depth() {
1225:       return this->maxDepth;
1226:     };
1227:     template <typename Point_, typename Marker_, typename Color_>
1228:     int Sieve<Point_,Marker_,Color_>::depth(const point_type& p) {
1229:       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);
1230:       if (i.find(p) != i.end()) {
1231:         return i.find(p)->depth;
1232:       }
1233:       return 0;
1234:     };
1235:     template <typename Point_, typename Marker_, typename Color_>
1236:     template<typename InputSequence>
1237:     int Sieve<Point_,Marker_,Color_>::depth(const Obj<InputSequence>& points) {
1238:       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);
1239:       int maxDepth = 0;
1240: 
1241:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
1242:         if (i.find(*iter) != i.end()) {
1243:           maxDepth = std::max(maxDepth, i.find(*iter)->depth);
1244:         }
1245:       }
1246:       return maxDepth;
1247:     };
1248:     template <typename Point_, typename Marker_, typename Color_>
1249:     int Sieve<Point_,Marker_,Color_>::height() {
1250:       return this->maxHeight;
1251:     };
1252:     template <typename Point_, typename Marker_, typename Color_>
1253:     int Sieve<Point_,Marker_,Color_>::height(const point_type& p) {
1254:       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);
1255:       if (i.find(p) != i.end()) {
1256:         return i.find(p)->height;
1257:       }
1258:       return 0;
1259:     };
1260:     template <typename Point_, typename Marker_, typename Color_>
1261:     template<typename InputSequence>
1262:     int Sieve<Point_,Marker_,Color_>::height(const Obj<InputSequence>& points) {
1263:       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);
1264:       int maxHeight = 0;
1265: 
1266:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
1267:         if (i.find(*iter) != i.end()) {
1268:           maxHeight = std::max(maxHeight, i.find(*iter)->height);
1269:         }
1270:       }
1271:       return maxHeight;
1272:     };

1274:     template <typename Point_, typename Marker_, typename Color_>
1275:     int Sieve<Point_,Marker_,Color_>::diameter() {
1276:       int globalDiameter;
1277:       int MPI_Allreduce(&this->graphDiameter, &globalDiameter, 1, MPI_INT, MPI_MAX, this->comm());
1278:       CHKMPIERROR(ierr, ERRORMSG("Error in MPI_Allreduce"));
1279:       return globalDiameter;
1280:     };
1281:     template <typename Point_, typename Marker_, typename Color_>
1282:     int Sieve<Point_,Marker_,Color_>::diameter(const point_type& p) {
1283:       return this->depth(p) + this->height(p);
1284:     };

1286:     template <typename Point_, typename Marker_, typename Color_>
1287:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::depthSequence> Sieve<Point_,Marker_,Color_>::depthStratum(int d) {
1288:       if (d == 0) {
1289:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::depthMarkerTag>(this->_cap.set), d);
1290:       } else {
1291:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::base_container_type::traits::depthMarkerTag>(this->_base.set), d);
1292:       }
1293:     };
1294:     template <typename Point_, typename Marker_, typename Color_>
1295:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::depthSequence> Sieve<Point_,Marker_,Color_>::depthStratum(int d, marker_type m) {
1296:       if (d == 0) {
1297:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::depthMarkerTag>(this->_cap.set), d, m);
1298:       } else {
1299:         return typename traits::depthSequence(::boost::multi_index::get<typename traits::base_container_type::traits::depthMarkerTag>(this->_base.set), d, m);
1300:       }
1301:     };
1302:     template <typename Point_, typename Marker_, typename Color_>
1303:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::heightSequence> Sieve<Point_,Marker_,Color_>::heightStratum(int h) {
1304:       if (h == 0) {
1305:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::base_container_type::traits::heightMarkerTag>(this->_base.set), h);
1306:       } else {
1307:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::heightMarkerTag>(this->_cap.set), h);
1308:       }
1309:     };
1310:     template <typename Point_, typename Marker_, typename Color_>
1311:     Obj<typename Sieve<Point_,Marker_,Color_>::traits::heightSequence> Sieve<Point_,Marker_,Color_>::heightStratum(int h, marker_type m) {
1312:       if (h == 0) {
1313:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::base_container_type::traits::heightMarkerTag>(this->_base.set), h, m);
1314:       } else {
1315:         return typename traits::heightSequence(::boost::multi_index::get<typename traits::cap_container_type::traits::heightMarkerTag>(this->_cap.set), h, m);
1316:       }
1317:     };
1318:     template <typename Point_, typename Marker_, typename Color_>
1319:     template<class InputSequence>
1320:     void Sieve<Point_,Marker_,Color_>::__computeClosureHeights(const Obj<InputSequence>& points) {
1321:       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);
1322:       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);
1323:       Obj<coneSet> modifiedPoints = coneSet();
1324: 
1325:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
1326:         // Compute the max height of the points in the support of p, and add 1
1327:         int h0 = this->height(*p_itor);
1328:         int h1 = this->height(this->support(*p_itor)) + 1;
1329:         if(h1 != h0) {
1330:           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);

1332:           index.modify(index.find(*p_itor), changeHeight(h1));
1333:           if (bIter != bIndex.end()) {
1334:             bIndex.modify(bIter, changeHeight(h1));
1335:           }
1336:           if (h1 > this->maxHeight) this->maxHeight = h1;
1337:           modifiedPoints->insert(*p_itor);
1338:         }
1339:       }
1340:       // FIX: We would like to avoid the copy here with cone()
1341:       if(modifiedPoints->size() > 0) {
1342:         this->__computeClosureHeights(this->cone(modifiedPoints));
1343:       }
1344:     };
1345:     template <typename Point_, typename Marker_, typename Color_>
1346:     template<class InputSequence>
1347:     void Sieve<Point_,Marker_,Color_>::__computeStarDepths(const Obj<InputSequence>& points) {
1348:       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);
1349:       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);
1350:       Obj<supportSet> modifiedPoints = supportSet();
1351:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
1352:         // Compute the max depth of the points in the support of p, and add 1
1353:         int d0 = this->depth(*p_itor);
1354:         int d1 = this->depth(this->cone(*p_itor)) + 1;
1355:         if(d1 != d0) {
1356:           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);

1358:           index.modify(index.find(*p_itor), changeDepth(d1));
1359:           if (cIter != cIndex.end()) {
1360:             cIndex.modify(cIter, changeDepth(d1));
1361:           }
1362:           if (d1 > this->maxDepth) this->maxDepth = d1;
1363:           modifiedPoints->insert(*p_itor);
1364:         }
1365:       }
1366:       // FIX: We would like to avoid the copy here with cone()
1367:       if(modifiedPoints->size() > 0) {
1368:         this->__computeStarDepths(this->support(modifiedPoints));
1369:       }
1370:     };
1373:     template <typename Point_, typename Marker_, typename Color_>
1374:     void Sieve<Point_,Marker_,Color_>::stratify(bool show) {
1375:       ALE_LOG_EVENT_BEGIN;
1376:       // FIX: We would like to avoid the copy here with cone() and support()
1377:       this->__computeClosureHeights(this->cone(this->leaves()));
1378:       this->__computeStarDepths(this->support(this->roots()));
1379: 
1380:       Obj<typename traits::capSequence> base = this->base();

1382:       for(typename traits::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
1383:         maxDepth = std::max(maxDepth, b_iter.depth());
1384:         //b_iter.setDegree(this->cone(*b_iter)->size());
1385:         this->_base.adjustDegree(*b_iter, this->cone(*b_iter)->size());
1386:       }
1387:       Obj<typename traits::capSequence> cap = this->cap();

1389:       for(typename traits::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
1390:         maxHeight = std::max(maxHeight, c_iter.height());
1391:         //c_iter.setDegree(this->support(*c_iter)->size());
1392:         this->_cap.adjustDegree(*c_iter, this->support(*c_iter)->size());
1393:       }
1394:       if (this->debug() || show) {
1395: //         const typename ::boost::multi_index::index<StratumSet,point>::type& points = ::boost::multi_index::get<point>(this->strata);
1396: //         for(typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = points.begin(); i != points.end(); i++) {
1397: //           std::cout << *i << std::endl;
1398: //         }
1399:       }
1400:       ALE_LOG_EVENT_END;
1401:     };
1402:     //
1403:     // Structural manipulation
1404:     //
1405: 
1406: } // namespace ALE

1408: #endif