Actual source code: Sifter.hh

  1: #ifndef included_ALE_Sifter_hh
  2: #define included_ALE_Sifter_hh

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

 10: // ALE extensions

 12: #ifndef  included_ALE_hh
 13: #include <ALE.hh>
 14: #endif

 16: namespace ALE {

 18:   namespace def {
 19:     //
 20:     // This is a set of classes and class templates describing an interface to point containers.
 21:     //

 23:     // Basic object
 24:     class Point {
 25:     public:
 26:       int32_t prefix, index;
 27:       // Constructors
 28:       Point() : prefix(0), index(0){};
 29:       Point(int p, int i) : prefix(p), index(i){};
 30:       Point(const Point& p) : prefix(p.prefix), index(p.index){};
 31:       // Comparisons
 32:       bool operator==(const Point& q) const {
 33:         return ( (this->prefix == q.prefix) && (this->index == q.index) );
 34:       };
 35:       bool operator!=(const Point& q) const {
 36:         return ( (this->prefix != q.prefix) || (this->index != q.index) );
 37:       };
 38:       bool operator<(const Point& q) const {
 39:         return( (this->prefix < q.prefix) || ((this->prefix == q.prefix) && (this->index < q.index)));
 40:       };
 41:       // Printing
 42:       friend std::ostream& operator<<(std::ostream& os, const Point& p) {
 43:         os << "(" << p.prefix << ", "<< p.index << ")";
 44:         return os;
 45:       };
 46:     };
 47:     typedef std::set<Point> PointSet;
 48:     typedef std::vector<Point> PointArray;

 50:     template <typename Source_, typename Target_, typename Color_>
 51:     struct Arrow {
 52:       Source_ source;
 53:       Target_ target;
 54:       Color_ color;

 56:       Arrow(Source_ s, Target_ t, Color_ c) : source(s), target(t), color(c) {};
 57:       friend std::ostream& operator<<(std::ostream& os, const Arrow& a) {
 58:         os << a.source << " --" << a.color << "--> " << a.target << std::endl;
 59:         return os;
 60:       }
 61:     };

 63:     //
 64:     // BiGraph (short for BipartiteGraph) implements a sequential interface similar to that of Sieve (below),
 65:     // except the source and target points may have different types and iterated operations (e.g., nCone, closure)
 66:     // are not available.
 67:     //
 68:     template<typename Source_, typename Target_, typename Color_>
 69:     class BiGraph {
 70:     public:
 71:       typedef Source_ source_type;
 72:       typedef Target_ target_type;
 73:       typedef Color_  color_type;
 74:       int debug;
 75:     private:
 76:       // Arrow storage
 77:       struct source{};
 78:       struct target{};
 79:       struct color{};
 80:       struct sourceColor{};
 81:       struct targetColor{};
 82:       typedef Arrow<source_type,target_type,color_type> Arrow_;
 83:       typedef ::boost::multi_index::multi_index_container<
 84:         Arrow_,
 85:         ::boost::multi_index::indexed_by<
 86:           ::boost::multi_index::ordered_non_unique<
 87:             ::boost::multi_index::tag<source>, BOOST_MULTI_INDEX_MEMBER(Arrow_,source_type,source)>,
 88:           ::boost::multi_index::ordered_non_unique<
 89:             ::boost::multi_index::tag<target>, BOOST_MULTI_INDEX_MEMBER(Arrow_,target_type,target)>,
 90:           ::boost::multi_index::ordered_non_unique<
 91:             ::boost::multi_index::tag<color>,  BOOST_MULTI_INDEX_MEMBER(Arrow_,color_type,color)>,
 92:           ::boost::multi_index::ordered_non_unique<
 93:             ::boost::multi_index::tag<sourceColor>,
 94:             ::boost::multi_index::composite_key<
 95:               Arrow_, BOOST_MULTI_INDEX_MEMBER(Arrow_,source_type,source), BOOST_MULTI_INDEX_MEMBER(Arrow_,color_type,color)>
 96:           >,
 97:           ::boost::multi_index::ordered_non_unique<
 98:             ::boost::multi_index::tag<targetColor>,
 99:             ::boost::multi_index::composite_key<
100:               Arrow_, BOOST_MULTI_INDEX_MEMBER(Arrow_,target_type,target), BOOST_MULTI_INDEX_MEMBER(Arrow_,color_type,color)>
101:           >
102:         >,
103:         ALE_ALLOCATOR<Arrow_>
104:       > ArrowSet;
105:       ArrowSet arrows;

107:       struct point{};
108:       struct depthTag{};
109:       struct heightTag{};
110:       struct indegree{};
111:       struct outdegree{};
112:       struct StratumPoint {
113:         target_type point;
114:         int depth;
115:         int height;
116:         int indegree;
117:         int outdegree;

119:         StratumPoint() : depth(0), height(0), indegree(0), outdegree(0) {};
120:         StratumPoint(const target_type& p) : point(p), depth(0), height(0), indegree(0), outdegree(0) {};
121:         // Printing
122:         friend std::ostream& operator<<(std::ostream& os, const StratumPoint& p) {
123:           os << "[" << p.point << ", "<< p.depth << ", "<< p.height << ", "<< p.indegree << ", "<< p.outdegree << "]";
124:           return os;
125:         };
126:       };
127:       typedef ::boost::multi_index::multi_index_container<
128:         StratumPoint,
129:         ::boost::multi_index::indexed_by<
130:           ::boost::multi_index::ordered_unique<
131:             ::boost::multi_index::tag<point>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,target_type,point)>,
132:           ::boost::multi_index::ordered_non_unique<
133:             ::boost::multi_index::tag<depthTag>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,depth)>,
134:           ::boost::multi_index::ordered_non_unique<
135:             ::boost::multi_index::tag<heightTag>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,height)>,
136:           ::boost::multi_index::ordered_non_unique<
137:             ::boost::multi_index::tag<indegree>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,indegree)>,
138:           ::boost::multi_index::ordered_non_unique<
139:             ::boost::multi_index::tag<outdegree>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,outdegree)>
140:         >,
141:         ALE_ALLOCATOR<StratumPoint>
142:       > StratumSet;
143:       StratumSet strata;
144:       bool       stratification;
145:       int        maxDepth;
146:       int        maxHeight;
147:       int        graphDiameter;
148:     public:
149:       BiGraph() : debug(0), stratification(false), maxDepth(-1), maxHeight(-1), graphDiameter(-1) {};
150:       // Return types
151:       class baseSequence {
152:         const typename ::boost::multi_index::index<StratumSet,indegree>::type& baseIndex;
153:       public:
154:         class iterator {
155:         public:
156:           typedef std::input_iterator_tag iterator_category;
157:           typedef target_type  value_type;
158:           typedef int          difference_type;
159:           typedef target_type* pointer;
160:           typedef target_type& reference;
161:           typename boost::multi_index::index<StratumSet,indegree>::type::iterator pointIter;

163:           iterator(const typename boost::multi_index::index<StratumSet,indegree>::type::iterator& iter) {
164:             this->pointIter = typename boost::multi_index::index<StratumSet,indegree>::type::iterator(iter);
165:           };
166:           virtual ~iterator() {};
167:           //
168:           virtual iterator    operator++() {++this->pointIter; return *this;};
169:           virtual iterator    operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
170:           virtual bool        operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
171:           virtual bool        operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
172:           virtual const target_type& operator*() const {return this->pointIter->point;};
173:         };

175:         baseSequence(const typename ::boost::multi_index::index<StratumSet,indegree>::type& base) : baseIndex(base) {};
176:         virtual ~baseSequence() {};
177:         virtual iterator    begin() {return iterator(this->baseIndex.upper_bound(0));};
178:         virtual iterator    end()   {return iterator(this->baseIndex.end());};
179:         virtual std::size_t size()  {return -1;};
180:       };
181:       class capSequence {
182:         const typename ::boost::multi_index::index<StratumSet,outdegree>::type& capIndex;
183:       public:
184:         class iterator {
185:         public:
186:           typedef std::input_iterator_tag iterator_category;
187:           typedef target_type  value_type;
188:           typedef int          difference_type;
189:           typedef target_type* pointer;
190:           typedef target_type& reference;
191:           typename boost::multi_index::index<StratumSet,outdegree>::type::iterator pointIter;

193:           iterator(const typename boost::multi_index::index<StratumSet,outdegree>::type::iterator& iter) {
194:             this->pointIter = typename boost::multi_index::index<StratumSet,outdegree>::type::iterator(iter);
195:           };
196:           virtual ~iterator() {};
197:           //
198:           virtual iterator    operator++() {++this->pointIter; return *this;};
199:           virtual iterator    operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
200:           virtual bool        operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
201:           virtual bool        operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
202:           virtual const target_type& operator*() const {return this->pointIter->point;};
203:         };

205:         capSequence(const typename ::boost::multi_index::index<StratumSet,outdegree>::type& cap) : capIndex(cap) {};
206:         virtual ~capSequence() {};
207:         virtual iterator    begin() {return iterator(this->capIndex.upper_bound(0));};
208:         virtual iterator    end()   {return iterator(this->capIndex.end());};
209:         virtual std::size_t size()  {return -1;};
210:       };
211:       class coneSequence {
212:         typename ::boost::multi_index::index<ArrowSet,targetColor>::type& coneIndex;
213:         const target_type key;
214:         const color_type  color;
215:         const bool        useColor;
216:         struct changeColor {
217:           changeColor(color_type newColor) : newColor(newColor) {};

219:           void operator()(Arrow_& p) {
220:             p.color = newColor;
221:           }
222:         private:
223:           color_type newColor;
224:         };
225:       public:
226:         class iterator {
227:           typename ::boost::multi_index::index<ArrowSet,targetColor>::type& index;
228:         public:
229:           typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator arrowIter;

231:           iterator(typename ::boost::multi_index::index<ArrowSet,targetColor>::type& index, const typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator& iter) : index(index) {
232:             this->arrowIter = typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator(iter);
233:           };
234:           virtual ~iterator() {};
235:           //
236:           virtual iterator    operator++() {++this->arrowIter; return *this;};
237:           virtual iterator    operator++(int n) {iterator tmp(this->index, this->arrowIter); ++this->arrowIter; return tmp;};
238:           virtual iterator    operator--() {--this->arrowIter; return *this;};
239:           virtual iterator    operator--(int n) {iterator tmp(this->index, this->arrowIter); --this->arrowIter; return tmp;};
240:           virtual bool        operator==(const iterator& itor) const {return this->arrowIter == itor.arrowIter;};
241:           virtual bool        operator!=(const iterator& itor) const {return this->arrowIter != itor.arrowIter;};
242:           virtual const source_type& operator*() const {return this->arrowIter->source;};
243:           void                setColor(int newColor) {this->index.modify(this->arrowIter, changeColor(newColor));};
244:         };
245:         class reverse_iterator {
246:         public:
247:           typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator arrowIter;

249:           reverse_iterator(const typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator& iter) {
250:             this->arrowIter = typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator(iter);
251:           };
252:           virtual ~reverse_iterator() {};
253:           //
254:           virtual reverse_iterator operator++() {--this->arrowIter; return *this;};
255:           virtual reverse_iterator operator++(int n) {reverse_iterator tmp(this->arrowIter); --this->arrowIter; return tmp;};
256:           virtual bool             operator==(const reverse_iterator& itor) const {return this->arrowIter == itor.arrowIter;};
257:           virtual bool             operator!=(const reverse_iterator& itor) const {return this->arrowIter != itor.arrowIter;};
258:           virtual const source_type& operator*() const {return this->arrowIter->source;};
259:         };

261:         coneSequence(typename ::boost::multi_index::index<ArrowSet,targetColor>::type& cone, const target_type& p) : coneIndex(cone), key(p), color(color_type()), useColor(0) {};
262:         coneSequence(typename ::boost::multi_index::index<ArrowSet,targetColor>::type& cone, const target_type& p, const color_type& c) : coneIndex(cone), key(p), color(c), useColor(1) {};
263:         virtual ~coneSequence() {};
264:         virtual iterator    begin() {
265:           if (useColor) {
266:             return iterator(this->coneIndex, this->coneIndex.lower_bound(::boost::make_tuple(key,color)));
267:           } else {
268:             return iterator(this->coneIndex, this->coneIndex.lower_bound(::boost::make_tuple(key)));
269:           }
270:         };
271:         virtual iterator    end()   {
272:           if (useColor) {
273:             return iterator(this->coneIndex, this->coneIndex.upper_bound(::boost::make_tuple(key,color)));
274:           } else {
275:             return iterator(this->coneIndex, this->coneIndex.upper_bound(::boost::make_tuple(key)));
276:           }
277:         };
278:         virtual reverse_iterator rbegin() {
279:           if (useColor) {
280:             return reverse_iterator(--this->coneIndex.upper_bound(::boost::make_tuple(key,color)));
281:           } else {
282:             return reverse_iterator(--this->coneIndex.upper_bound(::boost::make_tuple(key)));
283:           }
284:         };
285:         virtual reverse_iterator rend()   {
286:           typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator i;

288:           if (useColor) {
289:             return reverse_iterator(--this->coneIndex.lower_bound(::boost::make_tuple(key,color)));
290:           } else {
291:             return reverse_iterator(--this->coneIndex.lower_bound(::boost::make_tuple(key)));
292:           }
293:         };
294:         virtual std::size_t size()  {
295:           if (useColor) {
296:             return this->coneIndex.count(::boost::make_tuple(key,color));
297:           } else {
298:             return this->coneIndex.count(::boost::make_tuple(key));
299:           }
300:         };
301:       };
302:       class supportSequence {
303:         const typename ::boost::multi_index::index<ArrowSet,sourceColor>::type& supportIndex;
304:         const source_type key;
305:         const color_type  color;
306:         const bool        useColor;
307:       public:
308:         class iterator {
309:         public:
310:           typename boost::multi_index::index<ArrowSet,sourceColor>::type::iterator arrowIter;

312:           iterator(const typename boost::multi_index::index<ArrowSet,sourceColor>::type::iterator& iter) {
313:             this->arrowIter = typename boost::multi_index::index<ArrowSet,sourceColor>::type::iterator(iter);
314:           };
315:           virtual ~iterator() {};
316:           //
317:           virtual iterator    operator++() {++this->arrowIter; return *this;};
318:           virtual iterator    operator++(int n) {iterator tmp(this->arrowIter); ++this->arrowIter; return tmp;};
319:           virtual bool        operator==(const iterator& itor) const {return this->arrowIter == itor.arrowIter;};
320:           virtual bool        operator!=(const iterator& itor) const {return this->arrowIter != itor.arrowIter;};
321:           virtual const target_type& operator*() const {return this->arrowIter->target;};
322:         };

324:         supportSequence(const typename ::boost::multi_index::index<ArrowSet,sourceColor>::type& support, const source_type& p) : supportIndex(support), key(p), color(color_type()), useColor(0) {};
325:         supportSequence(const typename ::boost::multi_index::index<ArrowSet,sourceColor>::type& support, const source_type& p, const color_type& c) : supportIndex(support), key(p), color(c), useColor(1) {};
326:         virtual ~supportSequence() {};
327:         virtual iterator    begin() {
328:           if (useColor) {
329:             return iterator(this->supportIndex.lower_bound(::boost::make_tuple(key,color)));
330:           } else {
331:             return iterator(this->supportIndex.lower_bound(::boost::make_tuple(key)));
332:           }
333:         };
334:         virtual iterator    end()   {
335:           if (useColor) {
336:             return iterator(this->supportIndex.upper_bound(::boost::make_tuple(key,color)));
337:           } else {
338:             return iterator(this->supportIndex.upper_bound(::boost::make_tuple(key)));
339:           }
340:         };
341:         virtual std::size_t size()  {
342:           if (useColor) {
343:             return this->supportIndex.count(::boost::make_tuple(key,color));
344:           } else {
345:             return this->supportIndex.count(::boost::make_tuple(key));
346:           }
347:         };
348:       };
349:       typedef std::set<source_type, std::less<source_type>, ALE_ALLOCATOR<source_type> > coneSet;
350:       typedef std::set<target_type, std::less<target_type>, ALE_ALLOCATOR<target_type> > supportSet;
351:       // Completion types (some redundant)
352:       //   Color of completions; encodes the color of the completed BiGraph as well as the rank of the process that contributed arrow.
353:       typedef std::pair<color_type, int> completion_color_type;
354:       typedef BiGraph<source_type, target_type, completion_color_type> completion_type;
355:       // Query methods
356:       Obj<capSequence>     cap() {
357:         return capSequence(::boost::multi_index::get<outdegree>(this->strata));
358:       };
359:       Obj<baseSequence>    base() {
360:         return baseSequence(::boost::multi_index::get<indegree>(this->strata));
361:       };
362:       Obj<coneSequence> cone(const target_type& p) {
363:         return coneSequence(::boost::multi_index::get<targetColor>(this->arrows), p);
364:       }
365:       template<class InputSequence> Obj<coneSet> cone(const Obj<InputSequence>& points) {
366:         return this->cone(points, color_type(), false);
367:       };
368:       Obj<coneSequence>    cone(const target_type& p, const color_type& color) {
369:         return coneSequence(::boost::multi_index::get<targetColor>(this->arrows), p, color);
370:       };
371:       template<class InputSequence>
372:       Obj<coneSet>         cone(const Obj<InputSequence>& points, const color_type& color, bool useColor = true) {
373:         Obj<coneSet> cone = coneSet();

375:         for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
376:           Obj<coneSequence> pCone;

378:           if (useColor) {
379:             pCone = this->cone(*p_itor, color);
380:           } else {
381:             pCone = this->cone(*p_itor);
382:           }
383:           cone->insert(pCone->begin(), pCone->end());
384:         }
385:         return cone;
386:       };
387:       Obj<supportSequence> support(const source_type& p) {
388:         return supportSequence(::boost::multi_index::get<sourceColor>(this->arrows), p);
389:       };
390:       Obj<supportSequence> support(const source_type& p, const color_type& color) {
391:         return supportSequence(::boost::multi_index::get<sourceColor>(this->arrows), p, color);
392:       };
393:       template<class sourceInputSequence>
394:       Obj<supportSet>      support(const Obj<sourceInputSequence>& sources);
395:       template<class sourceInputSequence>
396:       Obj<supportSet>      support(const Obj<sourceInputSequence>& sources, const color_type& color);
397:       bool                 supportContains(const source_type& p, const target_type& q) {
398:         //FIX: Shouldn't we just be able to query an arrow?
399:         Obj<supportSequence> support = this->support(p);
400: 
401:         for(typename supportSequence::iterator s_iter = support->begin(); s_iter != support->end(); s_iter++) {
402:           if (*s_iter == q) return true;
403:         }
404:         return false;
405:       }
406:       // Lattice queries
407:       template<class targetInputSequence>
408:       Obj<coneSequence> meet(const Obj<targetInputSequence>& targets);
409:       template<class targetInputSequence>
410:       Obj<coneSequence> meet(const Obj<targetInputSequence>& targets, const color_type& color);
411:       template<class sourceInputSequence>
412:       Obj<coneSequence> join(const Obj<sourceInputSequence>& sources);
413:       template<class sourceInputSequence>
414:       Obj<coneSequence> join(const Obj<sourceInputSequence>& sources, const color_type& color);
415:       // Manipulation
416:       void clear() {
417:         this->arrows.clear();
418:         this->strata.clear();
419:       };
420:       void addArrow(const source_type& p, const target_type& q) {
421:         this->addArrow(p, q, color_type());
422:       };
423:       void addArrow(const source_type& p, const target_type& q, const color_type& color) {
424:         this->arrows.insert(Arrow_(p, q, color));
425:         //std::cout << "Added " << Arrow_(p, q, color);
426:       };
427:       void addCone(const source_type& source, const target_type& target){
428:         this->addArrow(source, target);
429:       };
430:       template<class sourceInputSequence>
431:       void addCone(const Obj<sourceInputSequence>& sources, const target_type& target) {
432:         this->addCone(sources, target, color_type());
433:       };
434:       void addCone(const source_type& source, const target_type& target, const color_type& color) {
435:         this->addArrow(source, target, color);
436:       };
437:       template<class sourceInputSequence>
438:       void addCone(const Obj<sourceInputSequence>& sources, const target_type& target, const color_type& color) {
439:         if (debug) {std::cout << "Adding a cone " << std::endl;}
440:         for(typename sourceInputSequence::iterator iter = sources->begin(); iter != sources->end(); ++iter) {
441:           if (debug) {std::cout << "Adding arrow from " << *iter << " to " << target << "(" << color << ")" << std::endl;}
442:           this->addArrow(*iter, target, color);
443:         }
444:       };
445:     private:
446:       void __clearCone(const target_type& p, const color_type& color, bool useColor) {
447:         typename ::boost::multi_index::index<ArrowSet,targetColor>::type& coneIndex = ::boost::multi_index::get<targetColor>(this->arrows);
448:         if (useColor) {
449:           coneIndex.erase(coneIndex.lower_bound(::boost::make_tuple(p,color)), coneIndex.upper_bound(::boost::make_tuple(p,color)));
450:         } else {
451:           coneIndex.erase(coneIndex.lower_bound(::boost::make_tuple(p)),       coneIndex.upper_bound(::boost::make_tuple(p)));
452:         }
453:       }
454:     public:
455:       void setCone(const source_type& source, const target_type& target){
456:         this->__clearCone(target, color_type(), false);
457:         this->addCone(source, target);
458:       };
459:       template<class sourceInputSequence>
460:       void setCone(const Obj<sourceInputSequence>& sources, const target_type& target) {
461:         this->__clearCone(target, color_type(), false);
462:         this->addCone(sources, target, color_type());
463:       };
464:       void setCone(const source_type& source, const target_type& target, const color_type& color) {
465:         this->__clearCone(target, color, true);
466:         this->addCone(source, target, color);
467:       };
468:       template<class sourceInputSequence>
469:       void setCone(const Obj<sourceInputSequence>& sources, const target_type& target, const color_type& color) {
470:         this->__clearCone(target, color, true);
471:         this->addCone(sources, target, color);
472:       };
473:       template<class targetInputSequence>
474:       void addSupport(const source_type& source, const Obj<targetInputSequence >& targets);
475:       template<class targetInputSequence>
476:       void addSupport(const source_type& source, const Obj<targetInputSequence >& targets, const color_type& color);
477:       void add(const Obj<BiGraph<source_type, target_type, color_type> >& bigraph);
478:     private:
479:       struct changeSource {
480:         changeSource(source_type newSource) : newSource(newSource) {};

482:         void operator()(Arrow_& p) {
483:           p.source = newSource;
484:         }
485:       private:
486:         source_type newSource;
487:       };
488:     public:
489:       void replaceSource(const source_type& s, const source_type& new_s) {
490:         typename ::boost::multi_index::index<ArrowSet,source>::type& index = ::boost::multi_index::get<source>(this->arrows);
491:         typename ::boost::multi_index::index<ArrowSet,source>::type::iterator i = index.find(s);
492:         if (i != index.end()) {
493:           index.modify(i, changeSource(new_s));
494:         } else {
495:           std::cout << "ERROR: Could not replace source " << s << " with " << new_s << std::endl;
496:         }
497:       };
498:     private:
499:       struct changeTarget {
500:         changeTarget(target_type newTarget) : newTarget(newTarget) {};

502:         void operator()(Arrow_& p) {
503:           p.target = newTarget;
504:         }
505:       private:
506:         target_type newTarget;
507:       };
508:     public:
509:       void replaceTarget(const target_type& t, const target_type& new_t) {
510:         typename ::boost::multi_index::index<ArrowSet,target>::type& index = ::boost::multi_index::get<target>(this->arrows);
511:         typename ::boost::multi_index::index<ArrowSet,target>::type::iterator i = index.find(t);
512:         if (i != index.end()) {
513:           index.modify(i, changeTarget(new_t));
514:         } else {
515:           std::cout << "ERROR: Could not replace target " << t << " with " << new_t << std::endl;
516:         }
517:       };
518:       void replaceSourceOfTarget(const target_type& t, const target_type& new_s) {
519:         typename ::boost::multi_index::index<ArrowSet,target>::type& index = ::boost::multi_index::get<target>(this->arrows);
520:         typename ::boost::multi_index::index<ArrowSet,target>::type::iterator i = index.find(t);
521:         if (i != index.end()) {
522:           index.modify(i, changeSource(new_s));
523:         } else {
524:           std::cout << "ERROR: Could not replace source of target" << t << " with " << new_s << std::endl;
525:         }
526:       }
527:     private:
528:       struct changeColor {
529:         changeColor(color_type newColor) : newColor(newColor) {};

531:         void operator()(Arrow_& p) {
532:           p.color = newColor;
533:         }
534:       private:
535:         color_type newColor;
536:       };
537:     public:
538:       bool replaceSourceColor(const source_type& p, const color_type& newColor) {
539:         typename ::boost::multi_index::index<ArrowSet,source>::type& index = ::boost::multi_index::get<source>(this->arrows);
540:         typename ::boost::multi_index::index<ArrowSet,source>::type::iterator i = index.find(p);
541:         if (i != index.end()) {
542:           index.modify(i, changeColor(newColor));
543:         } else {
544:           return false;
545:         }
546:         return true;
547:       };
548:       // Structural methods
551:       void stratify() {
552:         ALE_LOG_EVENT_BEGIN;
553:         std::cout << "Stratifying" << std::endl;
554:         this->__computeDegrees();
555:         ALE_LOG_EVENT_END;
556:       }
557:     private:
558:       struct changeIndegree {
559:         changeIndegree(int newIndegree) : newIndegree(newIndegree) {};

561:         void operator()(StratumPoint& p) {
562:           p.indegree = newIndegree;
563:         }
564:       private:
565:         int newIndegree;
566:       };
567:       struct changeOutdegree {
568:         changeOutdegree(int newOutdegree) : newOutdegree(newOutdegree) {};

570:         void operator()(StratumPoint& p) {
571:           p.outdegree = newOutdegree;
572:         }
573:       private:
574:         int newOutdegree;
575:       };
576:       void __computeDegrees() {
577:         const typename ::boost::multi_index::index<ArrowSet,target>::type& cones = ::boost::multi_index::get<target>(this->arrows);
578: #if 0
579:         const typename ::boost::multi_index::index<ArrowSet,source>::type& supports = ::boost::multi_index::get<source>(this->arrows);
580: #endif
581:         typename ::boost::multi_index::index<StratumSet,point>::type& points = ::boost::multi_index::get<point>(this->strata);

583:         for(typename ::boost::multi_index::index<ArrowSet,target>::type::iterator c_iter = cones.begin(); c_iter != cones.end(); ++c_iter) {
584:           if (points.find(c_iter->target) != points.end()) {
585:             typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = points.find(c_iter->target);

587:             points.modify(i, changeIndegree(cones.count(c_iter->target)));
588:           } else {
589:             StratumPoint p;

591:             p.point    = c_iter->target;
592:             p.indegree = cones.count(c_iter->target);
593:             this->strata.insert(p);
594:           }
595:         }

597: #if 0
598:         for(typename ::boost::multi_index::index<ArrowSet,source>::type::iterator s_iter = supports.begin(); s_iter != supports.end(); ++s_iter) {
599:           if (points.find(s_iter->source) != points.end()) {
600:             typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = points.find(s_iter->source);

602:             points.modify(i, changeOutdegree(supports.count(s_iter->source)));
603:           } else {
604:             StratumPoint p;

606:             p.point     = s_iter->source;
607:             p.outdegree = supports.count(s_iter->source);
608:             this->strata.insert(p);
609:           }
610:         }
611: #endif
612:       };
613:     public:
614:       // Parallelism
615:       // Compute the cone completion and return it in a separate BiGraph with arrows labeled by completion_color_type colors.
616:       Obj<completion_type> coneCompletion();
617:       // Compute the support completion and return it in a separate BiGraph with arrows labeled by completion_color_type colors.
618:       Obj<completion_type> supportCompletion();
619:       // Merge the BiGraph with the provided completion; do nothing if the completion is Null
620:       void complete(const Obj<completion_type>& completion);
621:       // Merge the BiGraph with the provided completion or compute a cone completion and merge with it, if a Null completion provided
622:       void coneComplete(const Obj<completion_type>& completion = Obj<completion_type>());
623:       // Merge the BiGraph with the provided completion or compute a support completion and merge with it, if a Null completion provided
624:       void supportComplete(const Obj<completion_type>& completion = Obj<completion_type>());
625:     };

627:     //
628:     // Sieve:
629:     //   A Sieve is a set of {\emph arrows} connecting {\emph points} of type Point_. Thus we
630:     // could realize a sieve, for instance, as a directed graph. In addition, we will often
631:     // assume an acyclicity constraint, arriving at a DAG. Each arrow may also carry a label,
632:     // or {\emph color} of type Color_, and the interface allows sets of arrows to be filtered
633:     // by color.
634:     //
635:     template <typename Point_, typename Color_>
636:     class Sieve { // class Sieve
637:     public:
638:       typedef Color_  color_type;
639:       typedef Point_  point_type;
640:       typedef int     marker_type;
641:       int debug;
642:     private:
643:       // Arrow query tags
644:       struct source{};
645:       struct target{};
646:       struct color{};
647:       struct sourceColor{};
648:       struct targetColor{};
649:       // Arrow structures
650:       typedef Arrow<Point,Point,Color_> Arrow_;
651:       typedef ::boost::multi_index::multi_index_container<
652:         Arrow_,
653:         ::boost::multi_index::indexed_by<
654:           ::boost::multi_index::ordered_non_unique<
655:             ::boost::multi_index::tag<source>, BOOST_MULTI_INDEX_MEMBER(Arrow_,Point_,source)>,
656:           ::boost::multi_index::ordered_non_unique<
657:             ::boost::multi_index::tag<target>, BOOST_MULTI_INDEX_MEMBER(Arrow_,Point_,target)>,
658:           ::boost::multi_index::ordered_non_unique<
659:             ::boost::multi_index::tag<color>,  BOOST_MULTI_INDEX_MEMBER(Arrow_,Color_,color)>,
660:           ::boost::multi_index::ordered_non_unique<
661:             ::boost::multi_index::tag<sourceColor>,
662:             ::boost::multi_index::composite_key<
663:               Arrow_, BOOST_MULTI_INDEX_MEMBER(Arrow_,Point_,source), BOOST_MULTI_INDEX_MEMBER(Arrow_,Color_,color)>
664:           >,
665:           ::boost::multi_index::ordered_non_unique<
666:             ::boost::multi_index::tag<targetColor>,
667:             ::boost::multi_index::composite_key<
668:               Arrow_, BOOST_MULTI_INDEX_MEMBER(Arrow_,Point_,target), BOOST_MULTI_INDEX_MEMBER(Arrow_,Color_,color)>
669:           >
670:         >,
671:         ALE_ALLOCATOR<Arrow_>
672:       > ArrowSet;
673:       ArrowSet arrows;

675:       // Stratum query tags
676:       // Could eliminate some sequences
677:       struct point{};
678:       struct depthTag{};
679:       struct heightTag{};
680:       struct indegree{};
681:       struct outdegree{};
682:       struct marker{};
683:       struct heightMarker{};
684:       struct depthMarker{};
685:       // Stratum stuctures
686:       struct StratumPoint {
687:         Point_  point;
688:         int   depth;
689:         int   height;
690:         int   indegree;
691:         int   outdegree;
692:         marker_type marker;

694:         StratumPoint() : depth(0), height(0), indegree(0), outdegree(0), marker(marker_type()) {};
695:         StratumPoint(const Point_& p) : point(p), depth(0), height(0), indegree(0), outdegree(0), marker(marker_type()) {};
696:         // Printing
697:         friend std::ostream& operator<<(std::ostream& os, const StratumPoint& p) {
698:           os << "[" << p.point << ", "<< p.depth << ", "<< p.height << ", "<< p.indegree << ", "<< p.outdegree << ", " << p.marker << "]";
699:           return os;
700:         };
701:       };
702:       typedef ::boost::multi_index::multi_index_container<
703:         StratumPoint,
704:         ::boost::multi_index::indexed_by<
705:           ::boost::multi_index::ordered_unique<
706:             ::boost::multi_index::tag<point>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,Point_,point)>,
707:           ::boost::multi_index::ordered_non_unique<
708:             ::boost::multi_index::tag<depthTag>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,depth)>,
709:           ::boost::multi_index::ordered_non_unique<
710:             ::boost::multi_index::tag<heightTag>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,height)>,
711:           ::boost::multi_index::ordered_non_unique<
712:             ::boost::multi_index::tag<indegree>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,indegree)>,
713:           ::boost::multi_index::ordered_non_unique<
714:             ::boost::multi_index::tag<outdegree>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,outdegree)>,
715:           ::boost::multi_index::ordered_non_unique<
716:             ::boost::multi_index::tag<marker>, BOOST_MULTI_INDEX_MEMBER(StratumPoint,marker_type,marker)>,
717:           ::boost::multi_index::ordered_non_unique<
718:             ::boost::multi_index::tag<depthMarker>,
719:             ::boost::multi_index::composite_key<
720:               StratumPoint, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,depth), BOOST_MULTI_INDEX_MEMBER(StratumPoint,marker_type,marker)>
721:           >,
722:           ::boost::multi_index::ordered_non_unique<
723:             ::boost::multi_index::tag<heightMarker>,
724:             ::boost::multi_index::composite_key<
725:               StratumPoint, BOOST_MULTI_INDEX_MEMBER(StratumPoint,int,height), BOOST_MULTI_INDEX_MEMBER(StratumPoint,marker_type,marker)>
726:           >
727:         >,
728:         ALE_ALLOCATOR<StratumPoint>
729:       > StratumSet;

731:       StratumSet strata;
732:       bool       stratification;
733:       int        maxDepth;
734:       int        maxHeight;
735:       int        graphDiameter;
736:     public:
737:       //
738:       // Output sequence types
739:       //

741:       class baseSequence {
742:         const typename ::boost::multi_index::index<StratumSet,indegree>::type& baseIndex;
743:       public:
744:         class iterator {
745:         public:
746:           typedef std::input_iterator_tag iterator_category;
747:           typedef Point_  value_type;
748:           typedef int     difference_type;
749:           typedef Point_* pointer;
750:           typedef Point_& reference;
751:           typename boost::multi_index::index<StratumSet,indegree>::type::iterator pointIter;
752: 
753:           iterator(const typename boost::multi_index::index<StratumSet,indegree>::type::iterator& iter) {
754:             this->pointIter = typename boost::multi_index::index<StratumSet,indegree>::type::iterator(iter);
755:           };
756:           virtual ~iterator() {};
757:           //
758:           virtual iterator    operator++() {++this->pointIter; return *this;};
759:           virtual iterator    operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
760:           virtual bool        operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
761:           virtual bool        operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
762:           virtual const Point_& operator*() const {return this->pointIter->point;};
763:         };
764:         baseSequence(const typename ::boost::multi_index::index<StratumSet,indegree>::type& base) : baseIndex(base) {};
765:         virtual ~baseSequence() {};
766:         virtual iterator    begin() {return iterator(this->baseIndex.upper_bound(0));};
767:         virtual iterator    end()   {return iterator(this->baseIndex.end());};
768:         virtual std::size_t size()  {return -1;};
769:       };

771:       class capSequence {
772:         const typename ::boost::multi_index::index<StratumSet,outdegree>::type& capIndex;
773:       public:
774:         class iterator {
775:         public:
776:           typedef std::input_iterator_tag iterator_category;
777:           typedef Point_  value_type;
778:           typedef int     difference_type;
779:           typedef Point_* pointer;
780:           typedef Point_& reference;
781:           typename boost::multi_index::index<StratumSet,outdegree>::type::iterator pointIter;
782: 
783:           iterator(const typename boost::multi_index::index<StratumSet,outdegree>::type::iterator& iter) {
784:             this->pointIter = typename boost::multi_index::index<StratumSet,outdegree>::type::iterator(iter);
785:           };
786:           virtual ~iterator() {};
787:           //
788:           virtual iterator    operator++() {++this->pointIter; return *this;};
789:           virtual iterator    operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
790:           virtual bool        operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
791:           virtual bool        operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
792:           virtual const Point_& operator*() const {return this->pointIter->point;};
793:         };
794:         capSequence(const typename ::boost::multi_index::index<StratumSet,outdegree>::type& cap) : capIndex(cap) {};
795:         virtual ~capSequence() {};
796:         virtual iterator    begin() {return iterator(this->capIndex.upper_bound(0));};
797:         virtual iterator    end()   {return iterator(this->capIndex.end());};
798:         virtual std::size_t size()  {return -1;};
799:       };

801:       class rootSequence {
802:         const typename ::boost::multi_index::index<StratumSet,indegree>::type& rootIndex;
803:       public:
804:         class iterator {
805:         public:
806:           typedef std::input_iterator_tag iterator_category;
807:           typedef Point_  value_type;
808:           typedef int     difference_type;
809:           typedef Point_* pointer;
810:           typedef Point_& reference;
811:           typename boost::multi_index::index<StratumSet,indegree>::type::iterator pointIter;
812: 
813:           iterator(const typename boost::multi_index::index<StratumSet,indegree>::type::iterator& iter){
814:             this->pointIter = typename boost::multi_index::index<StratumSet,indegree>::type::iterator(iter);
815:           };
816:           virtual ~iterator() {};
817:           //
818:           virtual iterator    operator++() {++this->pointIter; return *this;};
819:           virtual iterator    operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
820:           virtual bool        operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
821:           virtual bool        operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
822:           virtual const Point_& operator*() const {return this->pointIter->point;};
823:         };
824:         rootSequence(const typename ::boost::multi_index::index<StratumSet,indegree>::type& root) : rootIndex(root) {};
825:         virtual ~rootSequence() {};
826:         virtual iterator    begin() {return iterator(this->rootIndex.lower_bound(0));};
827:         virtual iterator    end()   {return iterator(this->rootIndex.upper_bound(0));};
828:         virtual std::size_t size()  {return this->rootIndex.count(0);};
829:       };
830: 
831:       class leafSequence {
832:         const typename ::boost::multi_index::index<StratumSet,outdegree>::type& leafIndex;
833:       public:
834:         class iterator {
835:         public:
836:           typedef std::input_iterator_tag iterator_category;
837:           typedef Point_  value_type;
838:           typedef int     difference_type;
839:           typedef Point_* pointer;
840:           typedef Point_& reference;
841:           typename boost::multi_index::index<StratumSet,outdegree>::type::iterator pointIter;
842: 
843:           iterator(const typename boost::multi_index::index<StratumSet,outdegree>::type::iterator& iter) {
844:             this->pointIter = typename boost::multi_index::index<StratumSet,outdegree>::type::iterator(iter);
845:           };
846:           virtual ~iterator() {};
847:           //
848:           virtual iterator    operator++() {++this->pointIter; return *this;};
849:           virtual iterator    operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
850:           virtual bool        operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
851:           virtual bool        operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
852:           virtual const Point_& operator*() const {return this->pointIter->point;};
853:         };
854: 
855:         leafSequence(const typename ::boost::multi_index::index<StratumSet,outdegree>::type& leaf) : leafIndex(leaf) {};
856:         virtual ~leafSequence() {};
857:         virtual iterator    begin() {return iterator(this->leafIndex.lower_bound(0));};
858:         virtual iterator    end()   {return iterator(this->leafIndex.upper_bound(0));};
859:         virtual std::size_t size()  {return this->leafIndex.count(0);};
860:       };
861: 
862:       class coneSequence {
863:         typename ::boost::multi_index::index<ArrowSet,targetColor>::type& coneIndex;
864:         const Point_ key;
865:         const Color_ color;
866:         const bool useColor;
867:         struct changeColor {
868:           changeColor(color_type newColor) : newColor(newColor) {};

870:           void operator()(Arrow_& p) {
871:             p.color = newColor;
872:           }
873:         private:
874:           color_type newColor;
875:         };
876:       public:
877:         class iterator {
878:           typename ::boost::multi_index::index<ArrowSet,targetColor>::type& index;
879:         public:
880:           typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator arrowIter;
881: 
882:           iterator(typename ::boost::multi_index::index<ArrowSet,targetColor>::type& index, const typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator& iter) : index(index) {
883:             this->arrowIter = typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator(iter);
884:           };
885:           virtual ~iterator() {};
886:           //
887:           virtual iterator    operator++() {++this->arrowIter; return *this;};
888:           virtual iterator    operator++(int n) {iterator tmp(this->index, this->arrowIter); ++this->arrowIter; return tmp;};
889:           virtual iterator    operator--() {--this->arrowIter; return *this;};
890:           virtual iterator    operator--(int n) {iterator tmp(this->index, this->arrowIter); --this->arrowIter; return tmp;};
891:           virtual bool        operator==(const iterator& itor) const {return this->arrowIter == itor.arrowIter;};
892:           virtual bool        operator!=(const iterator& itor) const {return this->arrowIter != itor.arrowIter;};
893:           virtual const Point_& operator*() const {return this->arrowIter->source;};
894:           void                setColor(int newColor) {this->index.modify(this->arrowIter, changeColor(newColor));};
895:         };
896:         class reverse_iterator {
897:         public:
898:           typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator arrowIter;
899: 
900:           reverse_iterator(const typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator& iter) {
901:             this->arrowIter = typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator(iter);
902:           };
903:           virtual ~reverse_iterator() {};
904:           //
905:           virtual reverse_iterator operator++() {--this->arrowIter; return *this;};
906:           virtual reverse_iterator operator++(int n) {reverse_iterator tmp(this->arrowIter); --this->arrowIter; return tmp;};
907:           virtual bool             operator==(const reverse_iterator& itor) const {return this->arrowIter == itor.arrowIter;};
908:           virtual bool             operator!=(const reverse_iterator& itor) const {return this->arrowIter != itor.arrowIter;};
909:           virtual const Point_&      operator*() const {return this->arrowIter->source;};
910:         };
911: 
912:         coneSequence(typename ::boost::multi_index::index<ArrowSet,targetColor>::type& cone, const Point_& p) :
913:           coneIndex(cone), key(p), color(Color_()), useColor(0) {};
914:         coneSequence(typename ::boost::multi_index::index<ArrowSet,targetColor>::type& cone, const Point_& p, const Color_& c) :
915:           coneIndex(cone), key(p), color(c), useColor(1) {};
916:         virtual ~coneSequence() {};
917:         virtual iterator    begin() {
918:           if (useColor) {
919:             return iterator(this->coneIndex, this->coneIndex.lower_bound(::boost::make_tuple(key,color)));
920:           } else {
921:             return iterator(this->coneIndex, this->coneIndex.lower_bound(::boost::make_tuple(key)));
922:           }
923:         };
924:         virtual iterator    end()   {
925:           if (useColor) {
926:             return iterator(this->coneIndex, this->coneIndex.upper_bound(::boost::make_tuple(key,color)));
927:           } else {
928:             return iterator(this->coneIndex, this->coneIndex.upper_bound(::boost::make_tuple(key)));
929:           }
930:         };
931:         virtual reverse_iterator rbegin() {
932:           if (useColor) {
933:             return reverse_iterator(--this->coneIndex.upper_bound(::boost::make_tuple(key,color)));
934:           } else {
935:             return reverse_iterator(--this->coneIndex.upper_bound(::boost::make_tuple(key)));
936:           }
937:         };
938:         virtual reverse_iterator rend()   {
939:           typename boost::multi_index::index<ArrowSet,targetColor>::type::iterator i;
940: 
941:           if (useColor) {
942:             return reverse_iterator(--this->coneIndex.lower_bound(::boost::make_tuple(key,color)));
943:           } else {
944:             return reverse_iterator(--this->coneIndex.lower_bound(::boost::make_tuple(key)));
945:           }
946:         };
947:         virtual std::size_t size()  {
948:           if (useColor) {
949:             return this->coneIndex.count(::boost::make_tuple(key,color));
950:           } else {
951:             return this->coneIndex.count(::boost::make_tuple(key));
952:           }
953:         };
954:       }; // class Sieve<Point_,Color_>::coneSequence
955: 
956:       class supportSequence {
957:         const typename ::boost::multi_index::index<ArrowSet,sourceColor>::type& supportIndex;
958:         const Point_ key;
959:         const Color_ color;
960:         const bool useColor;
961:       public:
962:         class iterator {
963:         public:
964:           typename boost::multi_index::index<ArrowSet,sourceColor>::type::iterator arrowIter;
965: 
966:           iterator(const typename boost::multi_index::index<ArrowSet,sourceColor>::type::iterator& iter) {
967:             this->arrowIter = typename boost::multi_index::index<ArrowSet,sourceColor>::type::iterator(iter);
968:           };
969:           virtual ~iterator() {};
970:           //
971:           virtual iterator    operator++() {++this->arrowIter; return *this;};
972:           virtual iterator    operator++(int n) {iterator tmp(this->arrowIter); ++this->arrowIter; return tmp;};
973:           virtual bool        operator==(const iterator& itor) const {return this->arrowIter == itor.arrowIter;};
974:           virtual bool        operator!=(const iterator& itor) const {return this->arrowIter != itor.arrowIter;};
975:           virtual const Point_& operator*() const {return this->arrowIter->target;};
976:         };
977: 
978:         supportSequence(const typename ::boost::multi_index::index<ArrowSet,sourceColor>::type& support, const Point_& p)
979:           : supportIndex(support), key(p), color(Color_()), useColor(0) {};
980:         supportSequence(const typename ::boost::multi_index::index<ArrowSet,sourceColor>::type& support,const Point_& p,const Color_& c)
981:           : supportIndex(support), key(p), color(c), useColor(1) {};
982:         virtual ~supportSequence() {};
983:         virtual iterator    begin() {
984:           if (useColor) {
985:             return iterator(this->supportIndex.lower_bound(::boost::make_tuple(key,color)));
986:           } else {
987:             return iterator(this->supportIndex.lower_bound(::boost::make_tuple(key)));
988:           }
989:         };
990:         virtual iterator    end()   {
991:           if (useColor) {
992:             return iterator(this->supportIndex.upper_bound(::boost::make_tuple(key,color)));
993:           } else {
994:             return iterator(this->supportIndex.upper_bound(::boost::make_tuple(key)));
995:           }
996:         };
997:         virtual std::size_t size()  {
998:           if (useColor) {
999:             return this->supportIndex.count(::boost::make_tuple(key,color));
1000:           } else {
1001:             return this->supportIndex.count(::boost::make_tuple(key));
1002:           }
1003:         };
1004:       };


1007:       class depthSequence {
1008:         const typename ::boost::multi_index::index<StratumSet,depthTag>::type& depthIndex;
1009:         const int d;
1010:       public:
1011:         class iterator {
1012:         public:
1013:           typedef std::input_iterator_tag iterator_category;
1014:           typedef Point_  value_type;
1015:           typedef int     difference_type;
1016:           typedef Point_* pointer;
1017:           typedef Point_& reference;
1018:           typename boost::multi_index::index<StratumSet,depthTag>::type::iterator pointIter;

1020:           iterator(const typename boost::multi_index::index<StratumSet,depthTag>::type::iterator& iter) {
1021:             this->pointIter = typename boost::multi_index::index<StratumSet,depthTag>::type::iterator(iter);
1022:           };
1023:           virtual ~iterator() {};
1024:           //
1025:           virtual iterator      operator++() {++this->pointIter; return *this;};
1026:           virtual iterator      operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
1027:           virtual bool          operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
1028:           virtual bool          operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
1029:           virtual const Point_& operator*() const {return this->pointIter->point;};
1030:           marker_type           getMarker() const {return this->pointIter->marker;};
1031:         };

1033:         depthSequence(const typename ::boost::multi_index::index<StratumSet,depthTag>::type& depthIndex, const int d) : depthIndex(depthIndex), d(d) {};
1034:         virtual ~depthSequence() {};
1035:         virtual iterator    begin() {return iterator(this->depthIndex.lower_bound(d));};
1036:         virtual iterator    end()   {return iterator(this->depthIndex.upper_bound(d));};
1037:         virtual std::size_t size()  {return this->depthIndex.count(d);};
1038:       };

1040:       class heightSequence {
1041:         const typename ::boost::multi_index::index<StratumSet,heightTag>::type& heightIndex;
1042:         const int h;
1043:       public:
1044:         class iterator {
1045:         public:
1046:           typedef std::input_iterator_tag iterator_category;
1047:           typedef Point_  value_type;
1048:           typedef int     difference_type;
1049:           typedef Point_* pointer;
1050:           typedef Point_& reference;
1051:           typename boost::multi_index::index<StratumSet,heightTag>::type::iterator pointIter;
1052: 
1053:           iterator(const typename boost::multi_index::index<StratumSet,heightTag>::type::iterator& iter) {
1054:             this->pointIter = typename boost::multi_index::index<StratumSet,heightTag>::type::iterator(iter);
1055:           };
1056:           virtual ~iterator() {};
1057:           //
1058:           virtual iterator    operator++() {++this->pointIter; return *this;};
1059:           virtual iterator    operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
1060:           virtual bool        operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
1061:           virtual bool        operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
1062:           virtual const Point_& operator*() const {return this->pointIter->point;};
1063:           marker_type           getMarker() const {return this->pointIter->marker;};
1064:         };
1065: 
1066:         heightSequence(const typename ::boost::multi_index::index<StratumSet,heightTag>::type& height, const int h) :
1067:           heightIndex(height), h(h) {};
1068:         virtual ~heightSequence() {};
1069:         virtual iterator    begin() {return iterator(this->heightIndex.lower_bound(h));};
1070:         virtual iterator    end()   {return iterator(this->heightIndex.upper_bound(h));};
1071:         virtual std::size_t size()  {return this->heightIndex.count(h);};
1072:       };
1073: 
1074:       class markerSequence {
1075:         const typename ::boost::multi_index::index<StratumSet,marker>::type& markerIndex;
1076:         const marker_type m;
1077:       public:
1078:         class iterator {
1079:         public:
1080:           typedef std::input_iterator_tag iterator_category;
1081:           typedef Point_  value_type;
1082:           typedef int     difference_type;
1083:           typedef Point_* pointer;
1084:           typedef Point_& reference;
1085:           typename boost::multi_index::index<StratumSet,marker>::type::iterator pointIter;

1087:           iterator(const typename boost::multi_index::index<StratumSet,marker>::type::iterator& iter) {
1088:             this->pointIter = typename boost::multi_index::index<StratumSet,marker>::type::iterator(iter);
1089:           };
1090:           virtual ~iterator() {};
1091:           //
1092:           virtual iterator      operator++() {++this->pointIter; return *this;};
1093:           virtual iterator      operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
1094:           virtual bool          operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
1095:           virtual bool          operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
1096:           virtual const Point_& operator*() const {return this->pointIter->point;};
1097:         };

1099:         markerSequence(const typename ::boost::multi_index::index<StratumSet,marker>::type& marker, const marker_type m) : markerIndex(marker), m(m) {};
1100:         virtual ~markerSequence() {};
1101:         virtual iterator    begin() {return iterator(this->markerIndex.lower_bound(m));};
1102:         virtual iterator    end()   {return iterator(this->markerIndex.upper_bound(m));};
1103:         virtual std::size_t size()  {return this->markerIndex.count(m);};
1104:       };

1106:       class depthMarkerSequence {
1107:         const typename ::boost::multi_index::index<StratumSet,depthMarker>::type& markerIndex;
1108:         const int depth;
1109:         const marker_type m;
1110:         const bool useMarker;
1111:       public:
1112:         class iterator {
1113:         public:
1114:           typedef std::input_iterator_tag iterator_category;
1115:           typedef Point_  value_type;
1116:           typedef int     difference_type;
1117:           typedef Point_* pointer;
1118:           typedef Point_& reference;
1119:           typename boost::multi_index::index<StratumSet,depthMarker>::type::iterator pointIter;

1121:           iterator(const typename boost::multi_index::index<StratumSet,depthMarker>::type::iterator& iter) {
1122:             this->pointIter = typename boost::multi_index::index<StratumSet,depthMarker>::type::iterator(iter);
1123:           };
1124:           virtual ~iterator() {};
1125:           //
1126:           virtual iterator     operator++() {++this->pointIter; return *this;};
1127:           virtual iterator     operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
1128:           virtual bool         operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
1129:           virtual bool         operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
1130:           virtual const Point_ & operator*() const {return this->pointIter->point;};
1131:           marker_type          getMarker() const {return this->pointIter->marker;};
1132:         };

1134:         depthMarkerSequence(const typename ::boost::multi_index::index<StratumSet,depthMarker>::type& marker, const int depth) : markerIndex(marker), depth(depth), m(marker_type()), useMarker(false) {};
1135:         depthMarkerSequence(const typename ::boost::multi_index::index<StratumSet,depthMarker>::type& marker, const int depth, const marker_type m) : markerIndex(marker), depth(depth), m(m), useMarker(true) {};
1136:         virtual ~depthMarkerSequence() {};
1137:         virtual iterator    begin() {
1138:           if (useMarker) {
1139:             return iterator(this->markerIndex.lower_bound(::boost::make_tuple(depth,m)));
1140:           } else {
1141:             return iterator(this->markerIndex.lower_bound(::boost::make_tuple(depth)));
1142:           }
1143:         };
1144:         virtual iterator    end()   {
1145:           if (useMarker) {
1146:             return iterator(this->markerIndex.upper_bound(::boost::make_tuple(depth,m)));
1147:           } else {
1148:             return iterator(this->markerIndex.upper_bound(::boost::make_tuple(depth)));
1149:           }
1150:         };
1151:         virtual std::size_t size()  {
1152:           if (useMarker) {
1153:             return this->markerIndex.count(::boost::make_tuple(depth,m));
1154:           } else {
1155:             return this->markerIndex.count(::boost::make_tuple(depth));
1156:           }
1157:         };
1158:       };

1160:       class heightMarkerSequence {
1161:         const typename ::boost::multi_index::index<StratumSet,heightMarker>::type& markerIndex;
1162:         const int height;
1163:         const marker_type m;
1164:         const bool useMarker;
1165:       public:
1166:         class iterator {
1167:         public:
1168:           typedef std::input_iterator_tag iterator_category;
1169:           typedef Point_  value_type;
1170:           typedef int     difference_type;
1171:           typedef Point_* pointer;
1172:           typedef Point_& reference;
1173:           typename boost::multi_index::index<StratumSet,heightMarker>::type::iterator pointIter;

1175:           iterator(const typename boost::multi_index::index<StratumSet,heightMarker>::type::iterator& iter) {
1176:             this->pointIter = typename boost::multi_index::index<StratumSet,heightMarker>::type::iterator(iter);
1177:           };
1178:           virtual ~iterator() {};
1179:           //
1180:           virtual iterator     operator++() {++this->pointIter; return *this;};
1181:           virtual iterator     operator++(int n) {iterator tmp(this->pointIter); ++this->pointIter; return tmp;};
1182:           virtual bool         operator==(const iterator& itor) const {return this->pointIter == itor.pointIter;};
1183:           virtual bool         operator!=(const iterator& itor) const {return this->pointIter != itor.pointIter;};
1184:           virtual const Point_ & operator*() const {return this->pointIter->point;};
1185:           marker_type          getMarker() const {return this->pointIter->marker;};
1186:         };

1188:         heightMarkerSequence(const typename ::boost::multi_index::index<StratumSet,marker>::type& marker, const int height) : markerIndex(marker), height(height), m(marker_type()), useMarker(false) {};
1189:         heightMarkerSequence(const typename ::boost::multi_index::index<StratumSet,marker>::type& marker, const int height, const marker_type m) : markerIndex(marker), height(height), m(m), useMarker(true) {};
1190:         virtual ~heightMarkerSequence() {};
1191:         virtual iterator    begin() {
1192:           if (useMarker) {
1193:             return iterator(this->markerIndex.lower_bound(::boost::make_tuple(height,m)));
1194:           } else {
1195:             return iterator(this->markerIndex.lower_bound(::boost::make_tuple(height)));
1196:           }
1197:         };
1198:         virtual iterator    end()   {
1199:           if (useMarker) {
1200:             return iterator(this->markerIndex.upper_bound(::boost::make_tuple(height,m)));
1201:           } else {
1202:             return iterator(this->markerIndex.upper_bound(::boost::make_tuple(height)));
1203:           }
1204:         };
1205:         virtual std::size_t size()  {
1206:           if (useMarker) {
1207:             return this->markerIndex.count(::boost::make_tuple(height,m));
1208:           } else {
1209:             return this->markerIndex.count(::boost::make_tuple(height));
1210:           }
1211:         };
1212:       };

1214:     public:
1215:       Sieve(int debug = 0) : debug(debug), stratification(false), maxDepth(-1), maxHeight(-1), graphDiameter(-1) {};
1216:       // Printing
1217:       friend std::ostream& operator<<(std::ostream& os, Obj<Sieve<Point_,Color_> > s) {
1218:         os << *s;
1219:         return os;
1220:       };
1221: 
1222:       friend std::ostream& operator<<(std::ostream& os, Sieve<Point_,Color_>& s) {
1223:         Obj<baseSequence> base = s.base();
1224:         for(typename baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
1225:           Obj<coneSequence> cone = s.cone(*b_iter);
1226:           os << "Base point " << *b_iter << " with cone:" << std::endl;
1227:           for(typename coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
1228:             os << "  " << *c_iter << std::endl;
1229:           }
1230:         }
1231:         return os;
1232:       };

1234:       //friend std::ostream& operator<<(std::ostream& os, Obj<Sieve<Point_,Color_> > s);
1235:       //friend std::ostream& operator<<(std::ostream& os, Sieve<Point_,Color_>& s);

1237:     public:
1238:       //
1239:       // The basic Sieve interface
1240:       //
1241:       void clear();

1243:       Obj<coneSequence> cone(const Point_& p);

1245:       template<class InputSequence>
1246:       Obj<PointSet>     cone(const Obj<InputSequence>& points);

1248:       Obj<coneSequence> cone(const Point_& p, const Color_& color);

1250:       template<class InputSequence>
1251:       Obj<PointSet> cone(const Obj<InputSequence>& points, const Color_& color);

1253:       Obj<PointArray> nCone(const Point_& p, int n);

1255:       Obj<PointArray> nCone(const Point_& p, int n, const Color_& color, bool useColor = true);

1257:       template<class InputSequence>
1258:       Obj<PointSet> nCone(const Obj<InputSequence>& points, int n);

1260:       template<class InputSequence>
1261:       Obj<PointSet> nCone(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);

1263:       bool          coneContains(const Point_& p, const Point_& q);

1265:       Obj<supportSequence> support(const Point_& p);

1267:       template<class InputSequence>
1268:       Obj<PointSet>        support(const Obj<InputSequence>& points);

1270:       Obj<supportSequence> support(const Point_& p, const Color_& color);

1272:       template<class InputSequence>
1273:       Obj<PointSet>        support(const Obj<InputSequence>& points, const Color_& color);

1275:       template<class InputSequence>
1276:       Obj<PointSet>        nSupport(const Obj<InputSequence>& points, int n);

1278:       template<class InputSequence>
1279:       Obj<PointSet>        nSupport(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);

1281:       bool                 supportContains(const Point_& q, const Point_& p);

1283:     private:
1284:       template<class InputSequence> Obj<PointSet>
1285:       __nCone(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor);

1287:       template<class pointSequence> void
1288:       __nCone(const Obj<pointSequence>& cone, int n, const Color_& color, bool useColor, Obj<PointArray> cone, Obj<PointSet> seen);
1289: 
1290:     public:
1291:       //
1292:       // Iterated versions
1293:       //
1294:       Obj<PointSet> closure(const Point_& p);

1296:       Obj<PointSet> closure(const Point_& p, const Color_& color);

1298:       template<class InputSequence>
1299:       Obj<PointSet> closure(const Obj<InputSequence>& points);

1301:       template<class InputSequence>
1302:       Obj<PointSet> closure(const Obj<InputSequence>& points, const Color_& color);

1304:       Obj<PointSet> nClosure(const Point_& p, int n);

1306:       Obj<PointSet> nClosure(const Point_& p, int n, const Color_& color, bool useColor = true);

1308:       template<class InputSequence>
1309:       Obj<PointSet> nClosure(const Obj<InputSequence>& points, int n);

1311:       template<class InputSequence>
1312:       Obj<PointSet> nClosure(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);

1314:       Obj<Sieve<Point_,Color_> > closureSieve(const Point_& p);

1316:       Obj<Sieve<Point_,Color_> > closureSieve(const Point_& p, const Color_& color);

1318:       template<class InputSequence>
1319:       Obj<Sieve<Point_,Color_> > closureSieve(const Obj<InputSequence>& points);

1321:       template<class InputSequence>
1322:       Obj<Sieve<Point_,Color_> > closureSieve(const Obj<InputSequence>& points, const Color_& color);

1324:       Obj<Sieve<Point_,Color_> > nClosureSieve(const Point_& p, int n);

1326:       Obj<Sieve<Point_,Color_> > nClosureSieve(const Point_& p, int n, const Color_& color, bool useColor = true);

1328:       template<class InputSequence>
1329:       Obj<Sieve<Point_,Color_> > nClosureSieve(const Obj<InputSequence>& points, int n);

1331:       template<class InputSequence>
1332:       Obj<Sieve<Point_,Color_> > nClosureSieve(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);

1334:       Obj<PointSet> star(const Point_& p);

1336:       Obj<PointSet> star(const Point_& p, const Color_& color);

1338:       template<class InputSequence>
1339:       Obj<PointSet> star(const Obj<InputSequence>& points);

1341:       template<class InputSequence>
1342:       Obj<PointSet> star(const Obj<InputSequence>& points, const Color_& color);

1344:       Obj<PointSet> nStar(const Point_& p, int n);

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

1348:       template<class InputSequence>
1349:       Obj<PointSet> nStar(const Obj<InputSequence>& points, int n);

1351:       template<class InputSequence>
1352:       Obj<PointSet> nStar(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor = true);

1354:     private:
1355:       template<class InputSequence>
1356:       Obj<PointSet> __nClosure(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor);

1358:       template<class InputSequence>
1359:       Obj<Sieve<Point_,Color_> > __nClosureSieve(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor);

1361:       template<class InputSequence>
1362:       Obj<PointSet> __nStar(Obj<InputSequence>& support, int n, const Color_& color, bool useColor);

1364:     public:
1365:       //
1366:       // Lattice methods
1367:       //
1368:       Obj<PointSet> meet(const Point_& p, const Point_& q);

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

1372:       template<class InputSequence>
1373:       Obj<PointSet> meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1);

1375:       template<class InputSequence>
1376:       Obj<PointSet> meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color);

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

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

1382:       template<class InputSequence>
1383:       Obj<PointSet> nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n);

1385:       template<class InputSequence>
1386:       Obj<PointSet> nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n,
1387:                           const Color_& color, bool useColor = true);

1389:       Obj<PointSet> join(const Point_& p, const Point_& q);

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

1393:       template<class InputSequence>
1394:       Obj<PointSet> join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1);

1396:       template<class InputSequence>
1397:       Obj<PointSet> join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color);

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

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

1403:       template<class InputSequence>
1404:       Obj<PointSet> nJoin(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n);

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

1409:     public:
1410:       //
1411:       // Manipulation
1412:       //
1413:       void addPoint(const Point_& p);

1415:       void addArrow(const Point_& p, const Point_& q);

1417:       void addArrow(const Point_& p, const Point_& q, const Color_& color);

1419:       template<class InputSequence>
1420:       void addCone(const Obj<InputSequence >& points, const Point_& p);

1422:       template<class InputSequence>
1423:       void addCone(const Obj<InputSequence >& points, const Point_& p, const Color_& color);

1425:       template<class InputSequence>
1426:       void addSupport(const Point_& p, const Obj<InputSequence >& points);

1428:       template<class InputSequence>
1429:       void addSupport(const Point_& p, const Obj<InputSequence >& points, const Color_& color);

1431:       void add(const Obj<Sieve<Point_,Color_> >& sieve);

1433:     public:
1434:       //
1435:       // Parallelism
1436:       //
1437:       Obj<std::map<Point_, Sieve<Point_,Color_> > > completion(const Sieve<Point_,Color_>& base);

1439:     public:
1440:       //
1441:       // Views
1442:       //
1443:       Obj<baseSequence> base() {
1444:         return baseSequence(::boost::multi_index::get<indegree>(this->strata));
1445:       };
1446:       Obj<capSequence>  cap() {
1447:         return capSequence(::boost::multi_index::get<outdegree>(this->strata));
1448:       };
1449:       Obj<rootSequence> roots() {
1450:         return rootSequence(::boost::multi_index::get<indegree>(this->strata));
1451:       };
1452:       Obj<leafSequence> leaves() {
1453:         return leafSequence(::boost::multi_index::get<outdegree>(this->strata));
1454:       };

1456:     public:
1457:       //
1458:       // Structural queries
1459:       //
1460:       int depth();
1461:       int depth(const Point_& p);

1463:       template<typename InputSequence>
1464:       int depth(const Obj<InputSequence>& points);

1466:       int height();

1468:       int height(const Point_& p);

1470:       template<typename InputSequence>
1471:       int height(const Obj<InputSequence>& points);

1473:       int diameter();

1475:       int diameter(const Point_& p);

1477:       Obj<depthSequence> depthStratum(int d);

1479:       Obj<depthMarkerSequence> depthStratum(int d, marker_type m);

1481:       Obj<heightSequence> heightStratum(int h);

1483:       Obj<heightMarkerSequence> heightStratum(int h, marker_type m);

1485:       Obj<markerSequence> markerStratum(marker_type m);
1486: 
1487:       void setStratification(bool doStratify);

1489:       bool getStratification();

1491:       void stratify(bool show = false);


1494:     public:
1495:       //
1496:       // Structural manipulation
1497:       //

1499:       struct changeMarker {
1500:         changeMarker(int newMarker) : newMarker(newMarker) {};

1502:         void operator()(StratumPoint& p) {
1503:           p.marker = newMarker;
1504:         }
1505:       private:
1506:         marker_type newMarker;
1507:       };

1509:       void setMarker(const point_type& p, const marker_type& marker);

1511:       template<class InputSequence>
1512:       void setMarker(const Obj<InputSequence>& points, const marker_type& marker);

1514:     private:
1515:       struct changeIndegree {
1516:         changeIndegree(int newIndegree) : newIndegree(newIndegree) {};

1518:         void operator()(StratumPoint& p) {
1519:           p.indegree = newIndegree;
1520:         }
1521:       private:
1522:         int newIndegree;
1523:       };

1525:       struct changeOutdegree {
1526:         changeOutdegree(int newOutdegree) : newOutdegree(newOutdegree) {};

1528:         void operator()(StratumPoint& p) {
1529:           p.outdegree = newOutdegree;
1530:         }
1531:       private:
1532:         int newOutdegree;
1533:       };

1535:       void __computeDegrees();

1537:       struct changeHeight {
1538:         changeHeight(int newHeight) : newHeight(newHeight) {};

1540:         void operator()(StratumPoint& p) {
1541:           p.height = newHeight;
1542:         }
1543:       private:
1544:         int newHeight;
1545:       };
1546: 
1547:       template<class InputSequence>
1548:       void __computeClosureHeights(const Obj<InputSequence>& points);

1550:       struct changeDepth {
1551:         changeDepth(int newDepth) : newDepth(newDepth) {};

1553:         void operator()(StratumPoint& p) {
1554:           p.depth = newDepth;
1555:         }
1556:       private:
1557:         int newDepth;
1558:       };

1560:       template<class InputSequence>
1561:       void __computeStarDepths(const Obj<InputSequence>& points);

1563:     };//class Sieve


1566:     //
1567:     // Sieve printing
1568:     //
1569: 
1570: //     template <typename Point_, typename Color_>
1571: //     std::ostream& operator<<(std::ostream& os, Obj<Sieve<Point_,Color_> > s) {
1572: //       os << *s;
1573: //       return os;
1574: //     };
1575: 
1576: //     template <typename Point_, typename Color_>
1577: //     std::ostream& operator<<(std::ostream& os, Sieve<Point_,Color_>& s) {
1578: //       Obj<Sieve<Point_,Color_>::baseSequence> base = s.base();
1579: 
1580: //       for(typename baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
1581: //         Obj<Sieve<Point_,Color_>::coneSequence> cone = s.cone(*b_iter);
1582: 
1583: //         os << "Base point " << *b_iter << " with cone:" << std::endl;
1584: //         for(typename Sieve<Point_,Color_>::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
1585: //           os << "  " << *c_iter << std::endl;
1586: //         }
1587: //       }
1588: //       return os;
1589: //     };
1590: 
1591:     //
1592:     // The basic Sieve interface
1593:     //
1594:     template <typename Point_, typename Color_>
1595:     void Sieve<Point_, Color_>::clear() {
1596:       this->arrows.clear(); this->strata.clear();
1597:     };

1599:     template <typename Point_, typename Color_>
1600:     Obj<typename Sieve<Point_, Color_>::coneSequence> Sieve<Point_, Color_>::cone(const Point_& p) {
1601:       return coneSequence(::boost::multi_index::get<targetColor>(this->arrows), p);
1602:     }
1603: 
1604:     template <typename Point_, typename Color_>
1605:     template<class InputSequence>
1606:     Obj<PointSet> Sieve<Point_, Color_>::cone(const Obj<InputSequence>& points) {
1607:       return this->nCone(points, 1);
1608:     };
1609: 
1610:     template <typename Point_, typename Color_>
1611:     Obj<typename Sieve<Point_, Color_>::coneSequence> Sieve<Point_, Color_>::cone(const Point_& p, const Color_& color) {
1612:       return coneSequence(::boost::multi_index::get<targetColor>(this->arrows), p, color);
1613:     };
1614: 
1615:     template <typename Point_, typename Color_>
1616:     template<class InputSequence>
1617:     Obj<PointSet> Sieve<Point_, Color_>::cone(const Obj<InputSequence>& points, const Color_& color) {
1618:       return this->nCone(points, 1, color);
1619:     };
1620: 
1621:     template <typename Point_, typename Color_>
1622:     Obj<PointArray> Sieve<Point_, Color_>::nCone(const Point_& p, int n) {
1623:       return this->nCone(p, n, Color_(), false);
1624:     };
1625: 
1626:     template <typename Point_, typename Color_>
1627:     Obj<PointArray> Sieve<Point_, Color_>::nCone(const Point_& p, int n, const Color_& color, bool useColor) {
1628: //       Obj<PointSet> cone = PointSet();
1629: //       cone->insert(p);
1630: //       return this->__nCone(cone, n, color, useColor);
1631:       Obj<PointArray> cone = PointArray();
1632:       Obj<PointSet>   seen = PointSet();

1634:       this->__nCone(this->cone(p), n-1, color, useColor, cone, seen);
1635:       return cone;
1636:     };

1638:     template <typename Point_, typename Color_>
1639:     template<class pointSequence>
1640:     void Sieve<Point_, Color_>::__nCone(const Obj<pointSequence>& points, int n, const Color_& color, bool useColor, Obj<PointArray> cone, Obj<PointSet> seen) {
1641:       if (n == 0) {
1642:         for(typename pointSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
1643:           if (seen->find(*p_itor) == seen->end()) {
1644:             cone->push_back(*p_itor);
1645:             seen->insert(*p_itor);
1646:           }
1647:         }
1648:       } else {
1649:         for(typename pointSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
1650:           if (useColor) {
1651:             this->__nCone(this->cone(*p_itor, color), n-1, color, useColor, cone, seen);
1652:           } else {
1653:             this->__nCone(this->cone(*p_itor), n-1, color, useColor, cone, seen);
1654:           }
1655:         }
1656:       }
1657:     };
1658: 
1659:     template <typename Point_, typename Color_>
1660:     template<class InputSequence>
1661:     Obj<PointSet> Sieve<Point_, Color_>::nCone(const Obj<InputSequence>& points, int n) {
1662:       return this->nCone(points, n, Color_(), false);
1663:     };

1665:     template <typename Point_, typename Color_>
1666:     template<class InputSequence>
1667:     Obj<PointSet> Sieve<Point_, Color_>::nCone(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor ) {
1668:       Obj<PointSet> cone = PointSet();
1669:       cone->insert(points->begin(), points->end());
1670:       return this->__nCone(cone, n, color, useColor);
1671:     };

1673:     template <typename Point_, typename Color_>
1674:     template<class InputSequence>
1675:     Obj<PointSet> Sieve<Point_, Color_>::__nCone(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor) {
1676:       Obj<PointSet> base = PointSet();

1678:       for(int i = 0; i < n; ++i) {
1679:         Obj<PointSet> tmp = cone; cone = base; base = tmp;
1680: 
1681:         cone->clear();
1682:         for(PointSet::iterator b_itor = base->begin(); b_itor != base->end(); ++b_itor) {
1683:           Obj<coneSequence> pCone;
1684: 
1685:           if (useColor) {
1686:             pCone = this->cone(*b_itor, color);
1687:           } else {
1688:             pCone = this->cone(*b_itor);
1689:           }
1690:           cone->insert(pCone->begin(), pCone->end());
1691:         }
1692:       }
1693:       return cone;
1694:     };

1696:     template <typename Point_, typename Color_>
1697:     bool Sieve<Point_, Color_>::coneContains(const Point_& p, const Point_& q) {
1698:       //FIX: Shouldn't we just be able to query an arrow?
1699:       Obj<coneSequence> cone = this->cone(p);
1700: 
1701:       for(typename Sieve<Point_, Color_>::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); c_iter++) {
1702:         if (*c_iter == q) return true;
1703:       }
1704:       return false;
1705:     }

1707:     template <typename Point_, typename Color_>
1708:     Obj<typename Sieve<Point_,Color_>::supportSequence> Sieve<Point_, Color_>::support(const Point_& p) {
1709:       return supportSequence(::boost::multi_index::get<sourceColor>(this->arrows), p);
1710:     };

1712:     template <typename Point_, typename Color_>
1713:     template<class InputSequence>
1714:     Obj<PointSet> Sieve<Point_, Color_>::support(const Obj<InputSequence>& points) {
1715:       return this->nSupport(points, 1);
1716:     };

1718:     template <typename Point_, typename Color_>
1719:     Obj<typename Sieve<Point_,Color_>::supportSequence> Sieve<Point_, Color_>::support(const Point_& p, const Color_& color) {
1720:       return supportSequence(::boost::multi_index::get<sourceColor>(this->arrows), p, color);
1721:     };

1723:     template <typename Point_, typename Color_>
1724:     template<class InputSequence>
1725:     Obj<PointSet> Sieve<Point_, Color_>::support(const Obj<InputSequence>& points, const Color_& color) {
1726:       return this->nSupport(points, 1, color);
1727:     };

1729:     template <typename Point_, typename Color_>
1730:     template<class InputSequence>
1731:     Obj<PointSet> Sieve<Point_, Color_>::nSupport(const Obj<InputSequence>& points, int n) {
1732:       return this->nSupport(points, n, Color_(), false);
1733:     };

1735:     template <typename Point_, typename Color_>
1736:     template<class InputSequence>
1737:     Obj<PointSet> Sieve<Point_, Color_>::nSupport(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor ) {
1738:       Obj<PointSet> support = PointSet();
1739:       Obj<PointSet> cap = PointSet();
1740: 
1741:       support->insert(points->begin(), points->end());
1742:       for(int i = 0; i < n; ++i) {
1743:         Obj<PointSet> tmp = support; support = cap; cap = tmp;
1744: 
1745:         support->clear();
1746:         for(PointSet::iterator c_itor = cap->begin(); c_itor != cap->end(); ++c_itor) {
1747:           Obj<supportSequence> pSupport;
1748: 
1749:           if (useColor) {
1750:             pSupport = this->support(*c_itor, color);
1751:           } else {
1752:             pSupport = this->support(*c_itor);
1753:           }
1754:           support->insert(pSupport->begin(), pSupport->end());
1755:         }
1756:       }
1757:       return support;
1758:     };

1760:     template <typename Point_, typename Color_>
1761:     bool Sieve<Point_, Color_>::supportContains(const Point_& q, const Point_& p) {
1762:       //FIX: Shouldn't we just be able to query an arrow?
1763:       Obj<supportSequence> support = this->support(q);
1764: 
1765:       for(typename Sieve<Point_, Color_>::supportSequence::iterator s_iter = support->begin(); s_iter != support->end(); s_iter++) {
1766:         if (*s_iter == p) return true;
1767:       }
1768:       return false;
1769:     }

1771:     //
1772:     // Iterated versions
1773:     //
1774: 
1775:     template <typename Point_, typename Color_>
1776:     Obj<PointSet> Sieve<Point_,Color_>::closure(const Point_& p) {
1777:       return nClosure(p, this->depth());
1778:     };
1779: 
1780:     template <typename Point_, typename Color_>
1781:     Obj<PointSet> Sieve<Point_,Color_>::closure(const Point_& p, const Color_& color) {
1782:       return nClosure(p, this->depth(), color);
1783:     };

1785:     template <typename Point_, typename Color_>
1786:     template<class InputSequence>
1787:     Obj<PointSet> Sieve<Point_,Color_>::closure(const Obj<InputSequence>& points) {
1788:       return nClosure(points, this->depth());
1789:     };
1790: 
1791:     template <typename Point_, typename Color_>
1792:     template<class InputSequence>
1793:     Obj<PointSet> Sieve<Point_,Color_>::closure(const Obj<InputSequence>& points, const Color_& color) {
1794:       return nClosure(points, this->depth(), color);
1795:     };
1796: 
1797:     template <typename Point_, typename Color_>
1798:     Obj<PointSet> Sieve<Point_,Color_>::nClosure(const Point_& p, int n) {
1799:       return this->nClosure(p, n, Color_(), false);
1800:     };

1802:     template <typename Point_, typename Color_>
1803:     Obj<PointSet> Sieve<Point_,Color_>::nClosure(const Point_& p, int n, const Color_& color, bool useColor ) {
1804:       Obj<PointSet> cone = PointSet();
1805: 
1806:       cone->insert(p);
1807:       return this->__nClosure(cone, n, color, useColor);
1808:     };

1810:     template <typename Point_, typename Color_>
1811:     template<class InputSequence>
1812:     Obj<PointSet> Sieve<Point_,Color_>::nClosure(const Obj<InputSequence>& points, int n) {
1813:       return this->nClosure(points, n, Color_(), false);
1814:     };

1816:     template <typename Point_, typename Color_>
1817:     template<class InputSequence>
1818:     Obj<PointSet> Sieve<Point_,Color_>::nClosure(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor ) {
1819:       Obj<PointSet> cone = PointSet();
1820:       cone->insert(points->begin(), points->end());
1821:       return this->__nClosure(cone, n, color, useColor);
1822:     };

1824:     template <typename Point_, typename Color_>
1825:     template<class InputSequence>
1826:     Obj<PointSet> Sieve<Point_,Color_>::__nClosure(Obj<InputSequence>& cone, int n, const Color_& color, bool useColor) {
1827:       Obj<PointSet> base = PointSet();
1828:       Obj<PointSet> closure = PointSet();
1829: 
1830:       for(int i = 0; i < n; ++i) {
1831:         Obj<PointSet> tmp = cone; cone = base; base = tmp;
1832: 
1833:         cone->clear();
1834:         for(PointSet::iterator b_itor = base->begin(); b_itor != base->end(); ++b_itor) {
1835:           Obj<coneSequence> pCone;
1836: 
1837:           if (useColor) {
1838:             pCone = this->cone(*b_itor, color);
1839:           } else {
1840:             pCone = this->cone(*b_itor);
1841:           }
1842:           cone->insert(pCone->begin(), pCone->end());
1843:           closure->insert(pCone->begin(), pCone->end());
1844:         }
1845:       }
1846:       return closure;
1847:     };

1849:     template <typename Point_, typename Color_>
1850:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::closureSieve(const Point_& p) {
1851:       return nClosureSieve(p, this->depth());
1852:     };

1854:     template <typename Point_, typename Color_>
1855:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::closureSieve(const Point_& p, const Color_& color) {
1856:       return nClosureSieve(p, this->depth(), color);
1857:     };
1858: 
1859:     template <typename Point_, typename Color_>
1860:     template<class InputSequence>
1861:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::closureSieve(const Obj<InputSequence>& points) {
1862:       return nClosureSieve(points, this->depth());
1863:     };
1864: 
1865:     template <typename Point_, typename Color_>
1866:     template<class InputSequence>
1867:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::closureSieve(const Obj<InputSequence>& points, const Color_& color) {
1868:       return nClosureSieve(points, this->depth(), color);
1869:     };
1870: 
1871:     template <typename Point_, typename Color_>
1872:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::nClosureSieve(const Point_& p, int n) {
1873:       return this->nClosureSieve(p, n, Color_(), false);
1874:     };
1875: 
1876:     template <typename Point_, typename Color_>
1877:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::nClosureSieve(const Point_& p, int n, const Color_& color, bool useColor ) {
1878:       Obj<PointSet> cone = PointSet();
1879: 
1880:       cone->insert(p);
1881:       return this->__nClosureSieve(cone, n, color, useColor);
1882:     };
1883: 
1884:     template <typename Point_, typename Color_>
1885:     template<class InputSequence>
1886:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::nClosureSieve(const Obj<InputSequence>& points, int n) {
1887:       return this->nClosureSieve(points, n, Color_(), false);
1888:     };
1889: 
1890:     template <typename Point_, typename Color_>
1891:     template<class InputSequence>
1892:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::nClosureSieve(const Obj<InputSequence>& points, int n,
1893:                                                                    const Color_& color, bool useColor ) {
1894:       Obj<PointSet> cone = PointSet();
1895: 
1896:       cone->insert(points->begin(), points->end());
1897:       return this->__nClosureSieve(cone, n, color, useColor);
1898:     };
1899: 
1900:     template <typename Point_, typename Color_>
1901:     template<class InputSequence>
1902:     Obj<Sieve<Point_,Color_> > Sieve<Point_,Color_>::__nClosureSieve(Obj<InputSequence>& cone,int n,const Color_& color,bool useColor) {
1903:       Obj<PointSet> base = PointSet();
1904:       Obj<Sieve<Point_,Color_> > closure = Sieve<Point_,Color_>();
1905: 
1906:       for(int i = 0; i < n; ++i) {
1907:         Obj<PointSet> tmp = cone; cone = base; base = tmp;
1908: 
1909:         cone->clear();
1910:         for(PointSet::iterator b_itor = base->begin(); b_itor != base->end(); ++b_itor) {
1911:           Obj<coneSequence> pCone;
1912: 
1913:           if (useColor) {
1914:             pCone = this->cone(*b_itor, color);
1915:           } else {
1916:             pCone = this->cone(*b_itor);
1917:           }
1918:           cone->insert(pCone->begin(), pCone->end());
1919:           closure->addCone(pCone, *b_itor);
1920:         }
1921:       }
1922:       return closure;
1923:     };
1924: 
1925:     template <typename Point_, typename Color_>
1926:     Obj<PointSet> Sieve<Point_,Color_>::star(const Point_& p) {
1927:       return nStar(p, this->height());
1928:     };
1929: 
1930:     template <typename Point_, typename Color_>
1931:     Obj<PointSet> Sieve<Point_,Color_>::star(const Point_& p, const Color_& color) {
1932:       return nStar(p, this->depth(), color);
1933:     };
1934: 
1935:     template <typename Point_, typename Color_>
1936:     template<class InputSequence>
1937:     Obj<PointSet> Sieve<Point_,Color_>::star(const Obj<InputSequence>& points) {
1938:       return nStar(points, this->height());
1939:     };
1940: 
1941:     template <typename Point_, typename Color_>
1942:     template<class InputSequence>
1943:     Obj<PointSet> Sieve<Point_,Color_>::star(const Obj<InputSequence>& points, const Color_& color) {
1944:       return nStar(points, this->height(), color);
1945:     };

1947:     template <typename Point_, typename Color_>
1948:     Obj<PointSet> Sieve<Point_,Color_>::nStar(const Point_& p, int n) {
1949:       return this->nStar(p, n, Color_(), false);
1950:     };
1951: 
1952:     template <typename Point_, typename Color_>
1953:     Obj<PointSet> Sieve<Point_,Color_>::nStar(const Point_& p, int n, const Color_& color, bool useColor ) {
1954:       Obj<PointSet> support = PointSet();
1955: 
1956:       support->insert(p);
1957:       return this->__nStar(support, n, color, useColor);
1958:     };

1960:     template <typename Point_, typename Color_>
1961:     template<class InputSequence>
1962:     Obj<PointSet> Sieve<Point_,Color_>::nStar(const Obj<InputSequence>& points, int n) {
1963:       return this->nStar(points, n, Color_(), false);
1964:     };

1966:     template <typename Point_, typename Color_>
1967:     template<class InputSequence>
1968:     Obj<PointSet> Sieve<Point_,Color_>::nStar(const Obj<InputSequence>& points, int n, const Color_& color, bool useColor ) {
1969:       Obj<PointSet> support = PointSet();
1970: 
1971:       support->insert(points->begin(), points->end());
1972:       return this->__nStar(cone, n, color, useColor);
1973:     };
1974: 
1975:     template <typename Point_, typename Color_>
1976:     template<class InputSequence>
1977:     Obj<PointSet> Sieve<Point_,Color_>::__nStar(Obj<InputSequence>& support, int n, const Color_& color, bool useColor) {
1978:       Obj<PointSet> cap = PointSet();
1979:       Obj<PointSet> star = PointSet();
1980: 
1981:       for(int i = 0; i < n; ++i) {
1982:         Obj<PointSet> tmp = support; support = base; base = tmp;
1983: 
1984:         support->clear();
1985:         for(PointSet::iterator b_itor = base->begin(); b_itor != base->end(); ++b_itor) {
1986:           Obj<supportSequence> pSupport;
1987: 
1988:           if (useColor) {
1989:             pSupport = this->support(*b_itor, color);
1990:           } else {
1991:             pSupport = this->support(*b_itor);
1992:           }
1993:           support->insert(pSupport->begin(), pSupport->end());
1994:           star->insert(pSupport->begin(), pSupport->end());
1995:         }
1996:       }
1997:       return star;
1998:     };
1999: 
2000:     //
2001:     // Lattice methods
2002:     //

2004:     template <typename Point_, typename Color_>
2005:     Obj<PointSet> Sieve<Point_,Color_>::meet(const Point_& p, const Point_& q) {
2006:       return nMeet(p, q, this->depth());
2007:     };
2008: 
2009:     template <typename Point_, typename Color_>
2010:     Obj<PointSet> Sieve<Point_,Color_>::meet(const Point_& p, const Point_& q, const Color_& color) {
2011:       return nMeet(p, q, this->depth(), color);
2012:     };

2014:     template <typename Point_, typename Color_>
2015:     template<class InputSequence>
2016:     Obj<PointSet> Sieve<Point_,Color_>::meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1) {
2017:       return nMeet(chain0, chain1, this->depth());
2018:     };

2020:     template <typename Point_, typename Color_>
2021:     template<class InputSequence>
2022:     Obj<PointSet> Sieve<Point_,Color_>::meet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color) {
2023:         return nMeet(chain0, chain1, this->depth(), color);
2024:     };

2026:     template <typename Point_, typename Color_>
2027:     Obj<PointSet> Sieve<Point_,Color_>::nMeet(const Point_& p, const Point_& q, int n) {
2028:         return nMeet(p, q, n, Color_(), false);
2029:     };

2031:     template <typename Point_, typename Color_>
2032:     Obj<PointSet> Sieve<Point_,Color_>::nMeet(const Point_& p, const Point_& q, int n, const Color_& color, bool useColor ) {
2033:       Obj<PointSet> chain0 = PointSet();
2034:       Obj<PointSet> chain1 = PointSet();
2035: 
2036:       chain0->insert(p);
2037:       chain1->insert(q);
2038:       return this->nMeet(chain0, chain1, n, color, useColor);
2039:     };

2041:     template <typename Point_, typename Color_>
2042:     template<class InputSequence>
2043:     Obj<PointSet> Sieve<Point_,Color_>::nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n) {
2044:       return this->nMeet(chain0, chain1, n, Color_(), false);
2045:     };
2046: 
2047:     template <typename Point_, typename Color_>
2048:     template<class InputSequence>
2049:     Obj<PointSet> Sieve<Point_,Color_>::nMeet(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1,int n,const Color_& color, bool useColor){
2050:       // The strategy is to compute the intersection of cones over the chains, remove the intersection
2051:       // and use the remaining two parts -- two disjoined components of the symmetric difference of cones -- as the new chains.
2052:       // The intersections at each stage are accumulated and their union is the meet.
2053:       // 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.
2054:       Obj<PointSet> meet = PointSet();
2055:       Obj<PointSet> cone;
2056: 
2057:       if((chain0->size() != 0) && (chain1->size() != 0)) {
2058:         for(int i = 0; i <= n; ++i) {
2059:           // Compute the intersection of chains and put it in meet at the same time removing it from c and cc
2060:           //std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<PointSet>(meet, meet->begin()));
2061:           //chain0->erase(meet->begin(), meet->end());
2062:           //chain1->erase(meet->begin(), meet->end());
2063:           for(typename InputSequence::iterator iter = chain0->begin(); iter != chain0->end(); ++iter) {
2064:             if (chain1->find(*iter) != chain1->end()) {
2065:               meet->insert(*iter);
2066:               chain0->erase(*iter);
2067:               chain1->erase(*iter);
2068:             }
2069:           }
2070:           // 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.
2071:           cone = this->cone(chain0);
2072:           chain0->insert(cone->begin(), cone->end());
2073:           if(chain0->size() == 0) {
2074:             break;
2075:           }
2076:           cone = this->cone(chain1);
2077:           chain1->insert(cone->begin(), cone->end());
2078:           if(chain1->size() == 0) {
2079:             break;
2080:           }
2081:         }
2082:       }
2083:       return meet;
2084:     };
2085: 
2086:     template <typename Point_, typename Color_>
2087:     Obj<PointSet> Sieve<Point_,Color_>::join(const Point_& p, const Point_& q) {
2088:       return this->nJoin(p, q, this->depth());
2089:     };
2090: 
2091:     template <typename Point_, typename Color_>
2092:     Obj<PointSet> Sieve<Point_,Color_>::join(const Point_& p, const Point_& q, const Color_& color) {
2093:       return this->nJoin(p, q, this->depth(), color);
2094:     };

2096:     template <typename Point_, typename Color_>
2097:     template<class InputSequence>
2098:     Obj<PointSet> Sieve<Point_,Color_>::join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1) {
2099:       return this->nJoin(chain0, chain1, this->depth());
2100:     };
2101: 
2102:     template <typename Point_, typename Color_>
2103:     template<class InputSequence>
2104:     Obj<PointSet> Sieve<Point_,Color_>::join(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, const Color_& color) {
2105:       return this->nJoin(chain0, chain1, this->depth(), color);
2106:     };
2107: 
2108:     template <typename Point_, typename Color_>
2109:     Obj<PointSet> Sieve<Point_,Color_>::nJoin(const Point_& p, const Point_& q, int n) {
2110:       return this->nJoin(p, q, n, Color_(), false);
2111:     };
2112: 
2113:     template <typename Point_, typename Color_>
2114:     Obj<PointSet> Sieve<Point_,Color_>::nJoin(const Point_& p, const Point_& q, int n, const Color_& color, bool useColor) {
2115:       Obj<PointSet> chain0 = PointSet();
2116:       Obj<PointSet> chain1 = PointSet();
2117: 
2118:       chain0->insert(p);
2119:       chain1->insert(q);
2120:       return this->nJoin(chain0, chain1, n, color, useColor);
2121:     };

2123:     template <typename Point_, typename Color_>
2124:     template<class InputSequence>
2125:     Obj<PointSet> Sieve<Point_,Color_>::nJoin(const Obj<InputSequence>& chain0, const Obj<InputSequence>& chain1, int n) {
2126:       return this->nJoin(chain0, chain1, n, Color_(), false);
2127:     };

2129:     template <typename Point_, typename Color_>
2130:     template<class InputSequence>
2131:     Obj<PointSet> Sieve<Point_,Color_>::nJoin(const Obj<InputSequence>& chain0,const Obj<InputSequence>& chain1,int n,const Color_& color,bool useColor){
2132:       // The strategy is to compute the intersection of supports over the chains, remove the intersection
2133:       // and use the remaining two parts -- two disjoined components of the symmetric difference of supports -- as the new chains.
2134:       // The intersections at each stage are accumulated and their union is the join.
2135:       // 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.
2136:       Obj<PointSet> join = PointSet();
2137:       Obj<PointSet> support;
2138: 
2139:       if((chain0->size() != 0) && (chain1->size() != 0)) {
2140:         for(int i = 0; i <= n; ++i) {
2141:           // Compute the intersection of chains and put it in meet at the same time removing it from c and cc
2142:           //std::set_intersection(chain0->begin(), chain0->end(), chain1->begin(), chain1->end(), std::insert_iterator<PointSet>(join.obj(), join->begin()));
2143:           //chain0->erase(join->begin(), join->end());
2144:           //chain1->erase(join->begin(), join->end());
2145:           for(typename InputSequence::iterator iter = chain0->begin(); iter != chain0->end(); ++iter) {
2146:             if (chain1->find(*iter) != chain1->end()) {
2147:               join->insert(*iter);
2148:               chain0->erase(*iter);
2149:               chain1->erase(*iter);
2150:             }
2151:           }
2152:           // 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.
2153:           support = this->support(chain0);
2154:           chain0->insert(support->begin(), support->end());
2155:           if(chain0->size() == 0) {
2156:             break;
2157:           }
2158:           support = this->support(chain1);
2159:           chain1->insert(support->begin(), support->end());
2160:           if(chain1->size() == 0) {
2161:             break;
2162:           }
2163:         }
2164:       }
2165:       return join;
2166:     };
2167: 
2168:     //
2169:     // Manipulation
2170:     //
2171: 
2172:     template <typename Point_, typename Color_>
2173:     void Sieve<Point_,Color_>::addPoint(const Point_& p) {
2174:       this->strata(StratumPoint(p));
2175:     };

2177:     template <typename Point_, typename Color_>
2178:     void Sieve<Point_,Color_>::addArrow(const Point_& p, const Point_& q) {
2179:       this->addArrow(p, q, Color_());
2180:     };

2182:     template <typename Point_, typename Color_>
2183:     void Sieve<Point_,Color_>::addArrow(const Point_& p, const Point_& q, const Color_& color) {
2184:       this->arrows.insert(Arrow_(p, q, color));
2185:       if (debug) {std::cout << "Added " << Arrow_(p, q, color);}
2186:     };

2188:     template <typename Point_, typename Color_>
2189:     template<class InputSequence>
2190:     void Sieve<Point_,Color_>::addCone(const Obj<InputSequence >& points, const Point_& p) {
2191:       this->addCone(points, p, Color_());
2192:     };

2194:     template <typename Point_, typename Color_>
2195:     template<class InputSequence>
2196:     void Sieve<Point_,Color_>::addCone(const Obj<InputSequence >& points, const Point_& p, const Color_& color){
2197:       if (debug) {std::cout << "Adding a cone " << std::endl;}
2198:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
2199:         if (debug) {std::cout << "Adding arrow from " << *iter << " to " << p << "(" << color << ")" << std::endl;}
2200:         this->addArrow(*iter, p, color);
2201:       }
2202:     };

2204:     template <typename Point_, typename Color_>
2205:     template<class InputSequence>
2206:     void Sieve<Point_,Color_>::addSupport(const Point_& p, const Obj<InputSequence >& points) {
2207:       this->addSupport(p, points, Color_());
2208:     };

2210:     template <typename Point_, typename Color_>
2211:     template<class InputSequence>
2212:     void Sieve<Point_,Color_>::addSupport(const Point_& p, const Obj<InputSequence >& points, const Color_& color) {
2213:       if (debug) {std::cout << "Adding a support " << std::endl;}
2214:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
2215:         if (debug) {std::cout << "Adding arrow from " << p << " to " << *iter << std::endl;}
2216:         this->addArrow(p, *iter, color);
2217:       }
2218:     };

2220:     template <typename Point_, typename Color_>
2221:     void Sieve<Point_,Color_>::add(const Obj<Sieve<Point_,Color_> >& sieve) {
2222:       const typename ::boost::multi_index::index<ArrowSet,target>::type& cones = ::boost::multi_index::get<target>(sieve.arrows);
2223: 
2224:       for(typename ::boost::multi_index::index<ArrowSet,target>::type::iterator iter = cones.begin(); iter != cones.end(); ++iter) {
2225:         this->addArrow(*iter);
2226:       }
2227:     };
2228: 

2230:     //
2231:     // Structural queries
2232:     //
2233:     template <typename Point_, typename Color_>
2234:     int Sieve<Point_,Color_>::depth() {
2235:       return this->maxDepth;
2236:     };

2238:     template <typename Point_, typename Color_>
2239:     int Sieve<Point_,Color_>::depth(const Point_& p) {
2240:         return ::boost::multi_index::get<point>(this->strata).find(p)->depth;
2241:     };
2242: 
2243:     template <typename Point_, typename Color_>
2244:     template<typename InputSequence>
2245:     int Sieve<Point_,Color_>::depth(const Obj<InputSequence>& points) {
2246:       const typename ::boost::multi_index::index<StratumSet,point>::type& index =
2247:         ::boost::multi_index::get<point>(this->strata);
2248:       int maxDepth = -1;
2249: 
2250:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
2251:         maxDepth = std::max(maxDepth, index.find(*iter)->depth);
2252:       }
2253:       return maxDepth;
2254:     };

2256:     template <typename Point_, typename Color_>
2257:     int Sieve<Point_,Color_>::height() {
2258:       return this->maxHeight;
2259:     };
2260: 
2261:     template <typename Point_, typename Color_>
2262:     int Sieve<Point_,Color_>::height(const Point_& p) {
2263:       return ::boost::multi_index::get<point>(this->strata).find(p)->height;
2264:     };
2265: 
2266:     template <typename Point_, typename Color_>
2267:     template<typename InputSequence>
2268:     int Sieve<Point_,Color_>::height(const Obj<InputSequence>& points) {
2269:       const typename ::boost::multi_index::index<StratumSet,point>::type& index = ::boost::multi_index::get<point>(this->strata);
2270:       int maxHeight = -1;
2271: 
2272:       for(typename InputSequence::iterator iter = points->begin(); iter != points->end(); ++iter) {
2273:         maxHeight = std::max(maxHeight, index.find(*iter)->height);
2274:       }
2275:       return maxHeight;
2276:     };
2277: 
2278:     template <typename Point_, typename Color_>
2279:     int Sieve<Point_,Color_>::diameter() {
2280:       int globalDiameter;
2281:       int MPI_Allreduce(&this->graphDiameter, &globalDiameter, 1, MPI_INT, MPI_MAX, this->comm);
2282:       CHKMPIERROR(ierr, ERRORMSG("Error in MPI_Allreduce"));
2283:       return globalDiameter;
2284:     };
2285: 
2286:     template <typename Point_, typename Color_>
2287:     int Sieve<Point_,Color_>::diameter(const Point_& p) {
2288:       return this->depth(p) + this->height(p);
2289:     };
2290: 
2291:     template <typename Point_, typename Color_>
2292:     Obj<typename Sieve<Point_,Color_>::depthSequence> Sieve<Point_,Color_>::depthStratum(int d) {
2293:       return depthSequence(::boost::multi_index::get<depthTag>(this->strata), d);
2294:     };
2295: 
2296:     template <typename Point_, typename Color_>
2297:     Obj<typename Sieve<Point_,Color_>::depthMarkerSequence> Sieve<Point_,Color_>::depthStratum(int d, marker_type m) {
2298:       return depthMarkerSequence(::boost::multi_index::get<depthMarker>(this->strata), d, m);
2299:     };

2301:     template <typename Point_, typename Color_>
2302:     Obj<typename Sieve<Point_,Color_>::heightSequence> Sieve<Point_,Color_>::heightStratum(int h) {
2303:       return heightSequence(::boost::multi_index::get<heightTag>(this->strata), h);
2304:     };
2305: 
2306:     template <typename Point_, typename Color_>
2307:     Obj<typename Sieve<Point_,Color_>::heightMarkerSequence> Sieve<Point_,Color_>::heightStratum(int h, marker_type m) {
2308:       return heightMarkerSequence(::boost::multi_index::get<depthMarker>(this->strata), h, m);
2309:     };

2311:     template <typename Point_, typename Color_>
2312:     Obj<typename Sieve<Point_,Color_>::markerSequence> Sieve<Point_,Color_>::markerStratum(marker_type m) {
2313:       return markerSequence(::boost::multi_index::get<marker>(this->strata), m);
2314:     };

2316:     template <typename Point_, typename Color_>
2317:     void Sieve<Point_,Color_>::setStratification(bool doStratify) {
2318:       this->stratification = doStratify;
2319:     };
2320: 
2321:     template <typename Point_, typename Color_>
2322:     bool Sieve<Point_,Color_>::getStratification() {
2323:       return this->stratification;
2324:     };
2325: 
2326:     //
2327:     // Structural manipulation
2328:     //
2329: 
2330:     template <typename Point_, typename Color_>
2331:     void Sieve<Point_,Color_>::setMarker(const point_type& p, const marker_type& marker) {
2332:       typename ::boost::multi_index::index<StratumSet,point>::type& index = ::boost::multi_index::get<point>(this->strata);
2333:       typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = index.find(p);
2334:       if (i != index.end()) {
2335:         index.modify(i, changeMarker(marker));
2336:       }
2337:     };

2339:     template <typename Point_, typename Color_>
2340:     template<class InputSequence>
2341:     void Sieve<Point_,Color_>::setMarker(const Obj<InputSequence>& points, const marker_type& marker) {
2342:       typename ::boost::multi_index::index<StratumSet,point>::type& index = ::boost::multi_index::get<point>(this->strata);
2343:       changeMarker changer(marker);
2344: 
2345:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
2346:         typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = index.find(*p_itor);
2347:         if (i != index.end()) {
2348:           index.modify(i, changer);
2349:         }
2350:       }
2351:     };

2353:     // __FUNCT__ used by the logging macros
2356:     template <typename Point_, typename Color_>
2357:     void Sieve<Point_,Color_>::stratify(bool show) {
2358:       ALE_LOG_EVENT_BEGIN;
2359:       this->__computeDegrees();
2360:       // FIX: We would like to avoid the copy here with cone() and support()
2361:       this->__computeClosureHeights(this->cone(this->leaves()));
2362:       this->__computeStarDepths(this->support(this->roots()));
2363: 
2364:       if (debug || show) {
2365:         const typename ::boost::multi_index::index<StratumSet,point>::type& points = ::boost::multi_index::get<point>(this->strata);
2366:         for(typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = points.begin(); i != points.end(); i++) {
2367:           std::cout << *i << std::endl;
2368:         }
2369:       }
2370:       ALE_LOG_EVENT_END;
2371:     };


2374:     template <typename Point_, typename Color_>
2375:     void Sieve<Point_,Color_>::__computeDegrees() {
2376:       const typename ::boost::multi_index::index<ArrowSet,target>::type& cones = ::boost::multi_index::get<target>(this->arrows);
2377:       const typename ::boost::multi_index::index<ArrowSet,source>::type& supports = ::boost::multi_index::get<source>(this->arrows);
2378:       typename ::boost::multi_index::index<StratumSet,point>::type& points = ::boost::multi_index::get<point>(this->strata);
2379: 
2380:       for(typename ::boost::multi_index::index<ArrowSet,target>::type::iterator c_iter = cones.begin(); c_iter != cones.end();++c_iter){
2381:         if (points.find(c_iter->target) != points.end()) {
2382:           typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = points.find(c_iter->target);
2383: 
2384:           points.modify(i, changeIndegree(cones.count(c_iter->target)));
2385:         } else {
2386:           StratumPoint p;
2387: 
2388:           p.point    = c_iter->target;
2389:           p.indegree = cones.count(c_iter->target);
2390:           this->strata.insert(p);
2391:         }
2392:       }
2393: 
2394:       for(typename ::boost::multi_index::index<ArrowSet,source>::type::iterator s_iter = supports.begin(); s_iter != supports.end(); ++s_iter) {
2395:         if (points.find(s_iter->source) != points.end()) {
2396:           typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = points.find(s_iter->source);
2397: 
2398:           points.modify(i, changeOutdegree(supports.count(s_iter->source)));
2399:         } else {
2400:           StratumPoint p;
2401: 
2402:           p.point     = s_iter->source;
2403:           p.outdegree = supports.count(s_iter->source);
2404:           this->strata.insert(p);
2405:         }
2406:       }
2407:     };

2409:     template <typename Point_, typename Color_>
2410:     template<class InputSequence>
2411:     void Sieve<Point_,Color_>::__computeClosureHeights(const Obj<InputSequence>& points) {
2412:       typename ::boost::multi_index::index<StratumSet,point>::type& index = ::boost::multi_index::get<point>(this->strata);
2413:       Obj<PointSet> modifiedPoints = PointSet();
2414: 
2415:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
2416:         // Compute the max height of the points in the support of p, and add 1
2417:         int h0 = this->height(*p_itor);
2418:         int h1 = this->height(this->support(*p_itor)) + 1;
2419:         if(h1 != h0) {
2420:           typename ::boost::multi_index::index<StratumSet,point>::type::iterator i = index.find(*p_itor);
2421:           index.modify(i, changeHeight(h1));
2422:           if (h1 > this->maxHeight) this->maxHeight = h1;
2423:           modifiedPoints->insert(*p_itor);
2424:         }
2425:       }
2426:       // FIX: We would like to avoid the copy here with cone()
2427:       if(modifiedPoints->size() > 0) {
2428:         this->__computeClosureHeights(this->cone(modifiedPoints));
2429:       }
2430:     };

2432: 
2433:     template <typename Point_, typename Color_>
2434:     template<class InputSequence>
2435:     void Sieve<Point_,Color_>::__computeStarDepths(const Obj<InputSequence>& points) {
2436:       typename ::boost::multi_index::index<StratumSet,point>::type& index = ::boost::multi_index::get<point>(this->strata);
2437:       Obj<PointSet> modifiedPoints = PointSet();
2438: 
2439:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
2440:         // Compute the max depth of the points in the support of p, and add 1
2441:         int d0 = this->depth(*p_itor);
2442:         int d1 = this->depth(this->cone(*p_itor)) + 1;
2443:         if(d1 != d0) {
2444:           index.modify(index.find(*p_itor), changeDepth(d1));
2445:           if (d1 > this->maxDepth) this->maxDepth = d1;
2446:           modifiedPoints->insert(*p_itor);
2447:         }
2448:       }
2449:       // FIX: We would like to avoid the copy here with cone()
2450:       if(modifiedPoints->size() > 0) {
2451:         this->__computeStarDepths(this->support(modifiedPoints));
2452:       }
2453:     };



2457:   } // namespace def
2458: 
2459: } // namespace ALE

2461: #endif