Actual source code: Sifter.hh

  1: #ifndef included_ALE_Sifter_hh
  2: #define included_ALE_Sifter_hh

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

 12: // ALE extensions

 14: #ifndef  included_ALE_hh
 15: #include <ALE.hh>
 16: #endif


 20: namespace ALE {

 22:   namespace SifterDef {
 23:     // Defines the traits of a sequence representing a subset of a multi_index container Index_.
 24:     // A sequence defines output (input in std terminology) iterators for traversing an Index_ object.
 25:     // Upon dereferencing values are extracted from each result record using a ValueExtractor_ object.
 26:     template <typename Index_, typename ValueExtractor_>
 27:     struct IndexSequenceTraits {
 28:       typedef Index_ index_type;
 29:       class iterator_base {
 30:       public:
 31:         // Standard iterator typedefs
 32:         typedef ValueExtractor_                        extractor_type;
 33:         typedef std::input_iterator_tag                iterator_category;
 34:         typedef typename extractor_type::result_type   value_type;
 35:         typedef int                                    difference_type;
 36:         typedef value_type*                            pointer;
 37:         typedef value_type&                            reference;
 38: 
 39:         // Underlying iterator type
 40:         typedef typename index_type::iterator          itor_type;
 41:       protected:
 42:         // Underlying iterator
 43:         itor_type      _itor;
 44:         // Member extractor
 45:         extractor_type _ex;
 46:       public:
 47:         iterator_base(itor_type itor) {
 48:           this->_itor = itor_type(itor);
 49:         };
 50:         virtual ~iterator_base() {};
 51:         virtual bool              operator==(const iterator_base& iter) const {return this->_itor == iter._itor;};
 52:         virtual bool              operator!=(const iterator_base& iter) const {return this->_itor != iter._itor;};
 53:         // FIX: operator*() should return a const reference, but it won't compile that way, because _ex() returns const value_type
 54:         virtual const value_type  operator*() const {return _ex(*(this->_itor));};
 55:       };// class iterator_base
 56:       class iterator : public iterator_base {
 57:       public:
 58:         // Standard iterator typedefs
 59:         typedef typename iterator_base::iterator_category  iterator_category;
 60:         typedef typename iterator_base::value_type         value_type;
 61:         typedef typename iterator_base::extractor_type     extractor_type;
 62:         typedef typename iterator_base::difference_type    difference_type;
 63:         typedef typename iterator_base::pointer            pointer;
 64:         typedef typename iterator_base::reference          reference;
 65:         // Underlying iterator type
 66:         typedef typename iterator_base::itor_type          itor_type;
 67:       public:
 68:         iterator(const itor_type& itor) : iterator_base(itor) {};
 69:         virtual ~iterator() {};
 70:         //
 71:         virtual iterator   operator++() {++this->_itor; return *this;};
 72:         virtual iterator   operator++(int n) {iterator tmp(this->_itor); ++this->_itor; return tmp;};
 73:       };// class iterator
 74:     }; // struct IndexSequenceTraits
 75: 
 76:     template <typename Index_, typename ValueExtractor_>
 77:     struct ReversibleIndexSequenceTraits {
 78:       typedef IndexSequenceTraits<Index_, ValueExtractor_> base_traits;
 79:       typedef typename base_traits::iterator_base   iterator_base;
 80:       typedef typename base_traits::iterator        iterator;
 81:       typedef typename base_traits::index_type      index_type;

 83:       // reverse_iterator is the reverse of iterator
 84:       class reverse_iterator : public iterator_base {
 85:       public:
 86:         // Standard iterator typedefs
 87:         typedef typename iterator_base::iterator_category  iterator_category;
 88:         typedef typename iterator_base::value_type         value_type;
 89:         typedef typename iterator_base::extractor_type     extractor_type;
 90:         typedef typename iterator_base::difference_type    difference_type;
 91:         typedef typename iterator_base::pointer            pointer;
 92:         typedef typename iterator_base::reference          reference;
 93:         // Underlying iterator type
 94:         typedef typename iterator_base::itor_type          itor_type;
 95:       public:
 96:         reverse_iterator(const itor_type& itor) : iterator_base(itor) {};
 97:         virtual ~reverse_iterator() {};
 98:         //
 99:         virtual reverse_iterator     operator++() {--this->_itor; return *this;};
100:         virtual reverse_iterator     operator++(int n) {reverse_iterator tmp(this->_itor); --this->_itor; return tmp;};
101:       };
102:     }; // class ReversibleIndexSequenceTraits


105:     //
106:     // Rec & RecContainer definitions.
107:     // Rec is intended to denote a graph point record.
108:     //
109:     template <typename Point_>
110:     struct Rec {
111:       typedef Point_ point_type;
112:       template<typename OtherPoint_>
113:       struct rebind {
114:         typedef Rec<OtherPoint_> type;
115:       };
116:       point_type     point;
117:       int            degree;
118:       // Basic interface
119:       Rec() : degree(0){};
120:       Rec(const Rec& r) : point(r.point), degree(r.degree) {}
121:       //Rec(const point_type& p) : point(p), degree(0) {};
122:       Rec(const point_type& p, const int d) : point(p), degree(d) {};
123:       // Printing
124:       friend std::ostream& operator<<(std::ostream& os, const Rec& p) {
125:         os << "<" << p.point << ", "<< p.degree << ">";
126:         return os;
127:       };
128: 
129:       struct degreeAdjuster {
130:         degreeAdjuster(int newDegree) : _newDegree(newDegree) {};
131:         void operator()(Rec& r) { r.degree = this->_newDegree; }
132:       private:
133:         int _newDegree;
134:       };// degreeAdjuster()

136:     };// class Rec

138:     template <typename Point_, typename Rec_>
139:     struct RecContainerTraits {
140:       typedef Rec_ rec_type;
141:       // Index tags
142:       struct pointTag{};
143:       // Rec set definition
144:       typedef ::boost::multi_index::multi_index_container<
145:         rec_type,
146:         ::boost::multi_index::indexed_by<
147:           ::boost::multi_index::ordered_unique<
148:             ::boost::multi_index::tag<pointTag>, BOOST_MULTI_INDEX_MEMBER(rec_type, typename rec_type::point_type, point)
149:           >
150:         >,
151:         ALE_ALLOCATOR<rec_type>
152:       > set_type;
153:       //
154:       // Return types
155:       //

157:      class PointSequence {
158:      public:
159:         typedef IndexSequenceTraits<typename ::boost::multi_index::index<set_type, pointTag>::type,
160:                                     BOOST_MULTI_INDEX_MEMBER(rec_type, typename rec_type::point_type,point)>
161:         traits;
162:       protected:
163:         const typename traits::index_type& _index;
164:       public:
165: 
166:        // Need to extend the inherited iterator to be able to extract the degree
167:        class iterator : public traits::iterator {
168:        public:
169:          iterator(const typename traits::iterator::itor_type& itor) : traits::iterator(itor) {};
170:          virtual const int& degree() const {return this->_itor->degree;};
171:        };
172: 
173:        PointSequence(const PointSequence& seq)            : _index(seq._index) {};
174:        PointSequence(typename traits::index_type& index) : _index(index)     {};
175:        virtual ~PointSequence(){};
176: 
177:        virtual bool empty(){return this->_index.empty();};
178: 
179:        virtual typename traits::index_type::size_type size() {return this->_index.size();};

181:        virtual iterator begin() {
182:          // Retrieve the beginning iterator of the index
183:          return iterator(this->_index.begin());
184:        };
185:        virtual iterator end() {
186:          // Retrieve the ending iterator of the index
187:          // Since the elements in this index are ordered by degree, this amounts to the end() of the index.
188:          return iterator(this->_index.end());
189:        };
190:        virtual bool contains(const typename rec_type::point_type& p) {
191:          // Check whether a given point is in the index
192:          return (this->_index.find(p) != this->_index.end());
193:        }
194:      }; // class PointSequence
195:     };// struct RecContainerTraits


198:     template <typename Point_, typename Rec_>
199:     struct RecContainer {
200:       typedef RecContainerTraits<Point_, Rec_> traits;
201:       typedef typename traits::set_type set_type;
202:       template <typename OtherPoint_, typename OtherRec_>
203:       struct rebind {
204:         typedef RecContainer<OtherPoint_, OtherRec_> type;
205:       };
206:       set_type set;
207:       //
208:       void removePoint(const typename traits::rec_type::point_type& p) {
209:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type& index =
210:           ::boost::multi_index::get<typename traits::pointTag>(this->set);
211:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type::iterator i = index.find(p);
212:         if (i != index.end()) { // Point exists
213:           index.erase(i);
214:         }
215:       };
216:       //
217:       void adjustDegree(const typename traits::rec_type::point_type& p, int delta) {
218:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type& index =
219:           ::boost::multi_index::get<typename traits::pointTag>(this->set);
220:         typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type::iterator i = index.find(p);
221:         if (i == index.end()) { // No such point exists
222:           if(delta < 0) { // Cannot decrease degree of a non-existent point
223:             ostringstream err;
224:             err << "ERROR: adjustDegree: Non-existent point " << p;
225:             std::cout << err << std::endl;
226:             throw(Exception(err.str().c_str()));
227:           }
228:           else { // We CAN INCREASE the degree of a non-existent point: simply insert a new element with degree == delta
229:             std::pair<typename ::boost::multi_index::index<set_type, typename traits::pointTag>::type::iterator, bool> ii;
230:             typename traits::rec_type r(p,delta);
231:             ii = index.insert(r);
232:             if(ii.second == false) {
233:               ostringstream err;
234:               err << "ERROR: adjustDegree: Failed to insert a rec " << r;
235:               std::cout << err << std::endl;
236:               throw(Exception(err.str().c_str()));
237:             }
238:           }
239:         }
240:         else { // Point exists, so we try to modify its degree
241:           // If the adjustment is zero, there is nothing to do, otherwise ...
242:           if(delta != 0) {
243:             int newDegree = i->degree + delta;
244:             if(newDegree < 0) {
245:               ostringstream ss;
246:               ss << "adjustDegree: Adjustment of " << *i << " by " << delta << " would result in negative degree: " << newDegree;
247:               throw Exception(ss.str().c_str());
248:             }
249:             index.modify(i, typename traits::rec_type::degreeAdjuster(newDegree));
250:           }
251:         }
252:       }; // adjustDegree()
253:     }; // struct RecContainer

255:     //
256:     // Arrow & ArrowContainer definitions
257:     //
258:     template<typename Source_, typename Target_, typename Color_>
259:     struct  Arrow { //: public ALE::def::Arrow<Source_, Target_, Color_> {
260:       typedef Arrow   arrow_type;
261:       typedef Source_ source_type;
262:       typedef Target_ target_type;
263:       typedef Color_  color_type;
264:       source_type source;
265:       target_type target;
266:       color_type  color;
267:       Arrow(const source_type& s, const target_type& t, const color_type& c) : source(s), target(t), color(c) {};
268:       // Flipping
269:       template <typename OtherSource_, typename OtherTarget_, typename OtherColor_>
270:       struct rebind {
271:         typedef Arrow<OtherSource_, OtherTarget_, OtherColor_> type;
272:       };
273:       struct flip {
274:         typedef Arrow<target_type, source_type, color_type> type;
275:         type arrow(const arrow_type& a) { return type(a.target, a.source, a.color);};
276:       };

278:       // Printing
279:       friend std::ostream& operator<<(std::ostream& os, const Arrow& a) {
280:         os << a.source << " --(" << a.color << ")--> " << a.target;
281:         return os;
282:       }

284:       // Arrow modifiers
285:       struct sourceChanger {
286:         sourceChanger(const source_type& newSource) : _newSource(newSource) {};
287:         void operator()(arrow_type& a) {a.source = this->_newSource;}
288:       private:
289:         source_type _newSource;
290:       };

292:       struct targetChanger {
293:         targetChanger(const target_type& newTarget) : _newTarget(newTarget) {};
294:         void operator()(arrow_type& a) { a.target = this->_newTarget;}
295:       private:
296:         const target_type _newTarget;
297:       };
298:     };// struct Arrow
299: 

301:     template<typename Source_, typename Target_, typename Color_, typename SupportCompare_>
302:     struct ArrowContainerTraits {
303:     public:
304:       //
305:       // Encapsulated types
306:       //
307:       typedef Arrow<Source_,Target_,Color_>    arrow_type;
308:       typedef typename arrow_type::source_type source_type;
309:       typedef typename arrow_type::target_type target_type;
310:       typedef typename arrow_type::color_type  color_type;
311:       typedef SupportCompare_                  support_compare_type;
312:       // Index tags
313:       struct                                   sourceColorTag{};
314:       struct                                   targetColorTag{};
315:       struct                                   sourceTargetTag{};

317:       // Sequence traits and sequence types
318:       template <typename Index_, typename Key_, typename SubKey_, typename ValueExtractor_>
319:       class ArrowSequence {
320:         // ArrowSequence implements ReversibleIndexSequencTraits with Index_ and ValueExtractor_ types.
321:         // A Key_ object and an optional SubKey_ object are used to extract the index subset.
322:       public:
323:         typedef ReversibleIndexSequenceTraits<Index_, ValueExtractor_>  traits;
324:         //typedef source_type                                             source_type;
325:         //typedef target_type                                             target_type;
326:         //typedef arrow_type                                              arrow_type;
327:         //
328:         typedef Key_                                                    key_type;
329:         typedef SubKey_                                                 subkey_type;
330:       protected:
331:         typename traits::index_type&                                    _index;
332:         key_type                                                  key;
333:         subkey_type                                               subkey;
334:         bool                                                      useSubkey;
335:       public:
336:         // Need to extend the inherited iterators to be able to extract arrow color
337:         class iterator : public traits::iterator {
338:         public:
339:           iterator(const typename traits::iterator::itor_type& itor) : traits::iterator(itor) {};
340:           virtual const source_type& source() const {return this->_itor->source;};
341:           virtual const color_type&  color()  const {return this->_itor->color;};
342:           virtual const target_type& target() const {return this->_itor->target;};
343:           virtual const arrow_type&  arrow()  const {return *(this->_itor);};
344:         };
345:         class reverse_iterator : public traits::reverse_iterator {
346:         public:
347:           reverse_iterator(const typename traits::reverse_iterator::itor_type& itor) : traits::reverse_iterator(itor) {};
348:           virtual const source_type& source() const {return this->_itor->source;};
349:           virtual const color_type&  color()  const {return this->_itor->color;};
350:           virtual const target_type& target() const {return this->_itor->target;};
351:           virtual const arrow_type&  arrow()  const {return *(this->_itor);};
352:         };
353:       public:
354:         //
355:         // Basic ArrowSequence interface
356:         //
357:         ArrowSequence(const ArrowSequence& seq) : _index(seq._index), key(seq.key), subkey(seq.subkey), useSubkey(seq.useSubkey) {};
358:         ArrowSequence(typename traits::index_type& index, const key_type& k) :
359:           _index(index), key(k), subkey(subkey_type()), useSubkey(0) {};
360:         ArrowSequence(typename traits::index_type& index, const key_type& k, const subkey_type& kk) :
361:           _index(index), key(k), subkey(kk), useSubkey(1){};
362:         virtual ~ArrowSequence() {};

364:         void setKey(const key_type& key) {this->key = key;};
365:         void setSubkey(const subkey_type& subkey) {this->subkey = subkey;};
366:         void setUseSubkey(const bool& useSubkey) {this->useSubkey = useSubkey;};
367: 
368:         virtual bool         empty() {return this->_index.empty();};

370:         virtual typename traits::index_type::size_type  size()  {
371:           if (this->useSubkey) {
372:             return this->_index.count(::boost::make_tuple(this->key,this->subkey));
373:           } else {
374:             return this->_index.count(::boost::make_tuple(this->key));
375:           }
376:         };

378:         virtual iterator begin() {
379:           if (this->useSubkey) {
380:             return iterator(this->_index.lower_bound(::boost::make_tuple(this->key,this->subkey)));
381:           } else {
382:             return iterator(this->_index.lower_bound(::boost::make_tuple(this->key)));
383:           }
384:         };
385: 
386:         virtual iterator end() {
387:           if (this->useSubkey) {
388:             return iterator(this->_index.upper_bound(::boost::make_tuple(this->key,this->subkey)));
389:           } else {
390:             return iterator(this->_index.upper_bound(::boost::make_tuple(this->key)));
391:           }
392:         };
393: 
394:         virtual reverse_iterator rbegin() {
395:           if (this->useSubkey) {
396:             return reverse_iterator(--this->_index.upper_bound(::boost::make_tuple(this->key,this->subkey)));
397:           } else {
398:             return reverse_iterator(--this->_index.upper_bound(::boost::make_tuple(this->key)));
399:           }
400:         };
401: 
402:         virtual reverse_iterator rend() {
403:           if (this->useSubkey) {
404:             return reverse_iterator(--this->_index.lower_bound(::boost::make_tuple(this->key,this->subkey)));
405:           } else {
406:             return reverse_iterator(--this->_index.lower_bound(::boost::make_tuple(this->key)));
407:           }
408:         };

410:         template<typename ostream_type>
411:         void view(ostream_type& os, const bool& useColor = false, const char* label = NULL){
412:           if(label != NULL) {
413:             os << "Viewing " << label << " sequence:" << std::endl;
414:           }
415:           os << "[";
416:           for(iterator i = this->begin(); i != this->end(); i++) {
417:             os << " (" << *i;
418:             if(useColor) {
419:               os << "," << i.color();
420:             }
421:             os  << ")";
422:           }
423:           os << " ]" << std::endl;
424:         };
425:       };// class ArrowSequence
426:     };// class ArrowContainerTraits
427: 

429:     // The specialized ArrowContainer types distinguish the cases of unique and multiple colors of arrows on
430:     // for each (source,target) pair (i.e., a single arrow, or multiple arrows between each pair of points).
431:     typedef enum {multiColor, uniColor} ColorMultiplicity;

433:     template<typename Source_, typename Target_, typename Color_, ColorMultiplicity colorMultiplicity, typename SupportCompare_>
434:     struct ArrowContainer {};
435: 
436:     template<typename Source_, typename Target_, typename Color_, typename SupportCompare_>
437:     struct ArrowContainer<Source_, Target_, Color_, multiColor, SupportCompare_> {
438:       // Define container's encapsulated types
439:       typedef ArrowContainerTraits<Source_, Target_, Color_, SupportCompare_>      traits;
440:       // need to def arrow_type locally, since BOOST_MULTI_INDEX_MEMBER barfs when first template parameter starts with 'typename'
441:       typedef typename traits::arrow_type                         arrow_type;
442:       // Container set type
443:       typedef ::boost::multi_index::multi_index_container<
444:         typename traits::arrow_type,
445:         ::boost::multi_index::indexed_by<
446:           ::boost::multi_index::ordered_non_unique<
447:             ::boost::multi_index::tag<typename traits::sourceTargetTag>,
448:             ::boost::multi_index::composite_key<
449:               typename traits::arrow_type,
450:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::source_type, source),
451:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::target_type, target),
452:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::color_type,  color)
453:             >
454:           >,
455:           ::boost::multi_index::ordered_non_unique<
456:             ::boost::multi_index::tag<typename traits::sourceColorTag>,
457:             ::boost::multi_index::composite_key<
458:               typename traits::arrow_type,
459:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::source_type, source),
460:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::color_type,  color),
461:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::target_type, target)
462:             >
463:           >,
464:           ::boost::multi_index::ordered_non_unique<
465:             ::boost::multi_index::tag<typename traits::targetColorTag>,
466:             ::boost::multi_index::composite_key<
467:               typename traits::arrow_type,
468:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::target_type, target),
469:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::color_type,  color),
470:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::source_type, source)
471:             >
472:           >
473:         >,
474:         ALE_ALLOCATOR<typename traits::arrow_type>
475:       > set_type;
476:      // multi-index set of multicolor arrows
477:       set_type set;
478:     }; // class ArrowContainer<multiColor>
479: 
480:     template<typename Source_, typename Target_, typename Color_, typename SupportCompare_>
481:     struct ArrowContainer<Source_, Target_, Color_, uniColor, SupportCompare_> {
482:       // Define container's encapsulated types
483:       typedef ArrowContainerTraits<Source_, Target_, Color_, SupportCompare_> traits;
484:       // need to def arrow_type locally, since BOOST_MULTI_INDEX_MEMBER barfs when first template parameter starts with 'typename'
485:       typedef typename traits::arrow_type                                   arrow_type;

487:       // multi-index set type -- arrow set
488:       typedef ::boost::multi_index::multi_index_container<
489:         typename traits::arrow_type,
490:         ::boost::multi_index::indexed_by<
491:           ::boost::multi_index::ordered_unique<
492:             ::boost::multi_index::tag<typename traits::sourceTargetTag>,
493:             ::boost::multi_index::composite_key<
494:               typename traits::arrow_type,
495:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::source_type, source),
496:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::target_type, target),
497:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::color_type,  color)
498:             >
499:           >,
500:           ::boost::multi_index::ordered_non_unique<
501:             ::boost::multi_index::tag<typename traits::sourceColorTag>,
502:             ::boost::multi_index::composite_key<
503:               typename traits::arrow_type,
504:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::source_type, source),
505:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::color_type,  color),
506:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::target_type, target)
507:             >,
508:             SupportCompare_
509:           >,
510:           ::boost::multi_index::ordered_non_unique<
511:             ::boost::multi_index::tag<typename traits::targetColorTag>,
512:             ::boost::multi_index::composite_key<
513:               typename traits::arrow_type,
514:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::target_type, target),
515:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::color_type,  color),
516:               BOOST_MULTI_INDEX_MEMBER(arrow_type, typename traits::source_type, source)
517:             >
518:           >
519:         >,
520:         ALE_ALLOCATOR<typename traits::arrow_type>
521:       > set_type;
522:       // multi-index set of unicolor arrow records
523:       set_type set;
524:     }; // class ArrowContainer<uniColor>
525:   }; // namespace SifterDef

527:   //
528:   // ASifter (short for Abstract Sifter, structurally a bipartite graph with colored arrows) implements a sequential interface
529:   // similar to that of Sieve, except the source and target points may have different types and iterated operations (e.g., nCone,
530:   // closure) are not available.
531:   //
532: template<typename Source_, typename Target_, typename Color_, SifterDef::ColorMultiplicity colorMultiplicity, typename SupportCompare_ = ::boost::multi_index::composite_key_compare<std::less<Source_>, std::less<Color_>, std::less<Target_> >, typename SourceCtnr_ = SifterDef::RecContainer<Source_, SifterDef::Rec<Source_> >, typename TargetCtnr_ = SifterDef::RecContainer<Target_, SifterDef::Rec<Target_> > >
533:   class ASifter { // class ASifter
534:   public:
535:     typedef struct {
536:       typedef ASifter<Source_, Target_, Color_, colorMultiplicity, SupportCompare_, SourceCtnr_, TargetCtnr_> graph_type;
537:       // Encapsulated container types
538:       typedef SifterDef::ArrowContainer<Source_, Target_, Color_, colorMultiplicity, SupportCompare_> arrow_container_type;
539:       typedef SourceCtnr_                                                            cap_container_type;
540:       typedef TargetCtnr_                                                            base_container_type;
541:       // Types associated with records held in containers
542:       typedef typename arrow_container_type::traits::arrow_type                      arrow_type;
543:       typedef typename arrow_container_type::traits::source_type                     source_type;
544:       typedef typename cap_container_type::traits::rec_type                          sourceRec_type;
545:       typedef typename arrow_container_type::traits::target_type                     target_type;
546:       typedef typename base_container_type::traits::rec_type                         targetRec_type;
547:       typedef typename arrow_container_type::traits::color_type                      color_type;
548:       typedef typename arrow_container_type::traits::support_compare_type            support_compare_type;
549:       // Convenient tag names
550:       typedef typename arrow_container_type::traits::sourceColorTag                  supportInd;
551:       typedef typename arrow_container_type::traits::targetColorTag                  coneInd;
552:       typedef typename arrow_container_type::traits::sourceTargetTag                 arrowInd;
553:       typedef typename base_container_type::traits::pointTag                         baseInd;
554:       typedef typename cap_container_type::traits::pointTag                          capInd;
555:       //
556:       // Return types
557:       //
558:       typedef typename
559:       arrow_container_type::traits::template ArrowSequence<typename ::boost::multi_index::index<typename arrow_container_type::set_type,arrowInd>::type, source_type, target_type, BOOST_MULTI_INDEX_MEMBER(arrow_type, color_type, color)>
560:       arrowSequence;

562:       // FIX: This is a temp fix to include addArrow into the interface; should probably be pushed up to ArrowSequence
563:       struct coneSequence : public arrow_container_type::traits::template ArrowSequence<typename ::boost::multi_index::index<typename arrow_container_type::set_type,coneInd>::type, target_type, color_type, BOOST_MULTI_INDEX_MEMBER(arrow_type, source_type, source)> {
564:       protected:
565:         graph_type& _graph;
566:       public:
567:         typedef typename
568:           arrow_container_type::traits::template ArrowSequence<typename ::boost::multi_index::index<typename arrow_container_type::set_type,coneInd>::type, target_type, color_type, BOOST_MULTI_INDEX_MEMBER(arrow_type, source_type, source)> base_type;
569:         // Encapsulated types
570:         typedef typename base_type::traits traits;
571:         typedef typename base_type::iterator iterator;
572:         typedef typename base_type::reverse_iterator reverse_iterator;
573:         // Basic interface
574:         coneSequence(const coneSequence& seq) : base_type(seq), _graph(seq._graph) {};
575:           coneSequence(graph_type& graph, typename traits::index_type& index, const typename base_type::key_type& k) : base_type(index, k), _graph(graph){};
576:             coneSequence(graph_type& graph, typename traits::index_type& index, const typename base_type::key_type& k, const typename base_type::subkey_type& kk) : base_type(index, k, kk), _graph(graph) {};
577:               virtual ~coneSequence() {};
578: 
579:         // Extended interface
580:         void addArrow(const arrow_type& a) {
581:           // if(a.target != this->key) {
582:           //               throw ALE::Exception("Arrow target mismatch in a coneSequence");
583:           //             }
584:           this->_graph.addArrow(a);
585:         };
586:         void addArrow(const source_type& s, const color_type& c){
587:           this->_graph.addArrow(arrow_type(s,this->key,c));
588:         };
589: 
590:         virtual bool contains(const source_type& s) {
591:           // Check whether a given point is in the index
592:           typename ::boost::multi_index::index<typename ASifter::traits::arrow_container_type::set_type,typename ASifter::traits::arrowInd>::type& index = ::boost::multi_index::get<typename ASifter::traits::arrowInd>(this->_graph._arrows.set);
593:           return (index.find(::boost::make_tuple(s,this->key)) != index.end());
594:         };
595:       };// struct coneSequence
596: 
597:       // FIX: This is a temp fix to include addArrow into the interface; should probably be pushed up to ArrowSequence
598:       struct supportSequence : public arrow_container_type::traits::template ArrowSequence<typename ::boost::multi_index::index<typename arrow_container_type::set_type,supportInd>::type, source_type, color_type, BOOST_MULTI_INDEX_MEMBER(arrow_type, target_type, target)> {
599:       protected:
600:         graph_type& _graph;
601:       public:
602:         typedef typename
603:           arrow_container_type::traits::template ArrowSequence<typename ::boost::multi_index::index<typename arrow_container_type::set_type,supportInd>::type, source_type, color_type, BOOST_MULTI_INDEX_MEMBER(arrow_type, target_type, target)> base_type;
604:         // Encapsulated types
605:         typedef typename base_type::traits traits;
606:         typedef typename base_type::iterator iterator;
607:         typedef typename base_type::reverse_iterator reverse_iterator;
608:         // Basic interface
609:         supportSequence(const supportSequence& seq) : base_type(seq), _graph(seq._graph) {};
610:         supportSequence(graph_type& graph, typename traits::index_type& index, const typename base_type::key_type& k) : base_type(index, k), _graph(graph){};
611:         supportSequence(graph_type& graph, typename traits::index_type& index, const typename base_type::key_type& k, const typename base_type::subkey_type& kk) : base_type(index, k, kk), _graph(graph) {};
612:         virtual ~supportSequence() {};
613: 
614:         // FIX: WARNING: (or a HACK?): we flip the arrow on addition here.
615:         // Fancy interface
616:         void addArrow(const typename arrow_type::flip::type& af) {
617:           this->_graph.addArrow(af.target, af.source, af.color);
618:         };
619:         void addArrow(const target_type& t, const color_type& c){
620:           this->_graph.addArrow(arrow_type(this->key,t,c));
621:         };
622:       };// struct supportSequence

624: 
625:       typedef typename base_container_type::traits::PointSequence baseSequence;
626:       typedef typename cap_container_type::traits::PointSequence  capSequence;
627:       typedef std::set<source_type>   coneSet;
628:       typedef ALE::array<source_type> coneArray;
629:       typedef std::set<target_type>   supportSet;
630:       typedef ALE::array<target_type> supportArray;
631:     } traits;

633:     template <typename OtherSource_, typename OtherTarget_, typename OtherColor_, SifterDef::ColorMultiplicity otherColorMultiplicity,
634:               typename OtherSupportCompare_  = ::boost::multi_index::composite_key_compare<std::less<OtherSource_>, std::less<OtherColor_>, std::less<OtherTarget_> >,
635:               typename OtherSourceCtnr_ = SifterDef::RecContainer<OtherSource_, SifterDef::Rec<OtherSource_> >,
636:               typename OtherTargetCtnr_ = SifterDef::RecContainer<OtherTarget_, SifterDef::Rec<OtherTarget_> > >
637:     struct rebind {
638:       typedef ASifter<OtherSource_, OtherTarget_, OtherColor_, otherColorMultiplicity, OtherSupportCompare_, OtherSourceCtnr_, OtherTargetCtnr_> type;
639:     };

641:   public:
642:     // Debug level
643:     int _debug;
644:     //protected:
645:     typename traits::arrow_container_type _arrows;
646:     typename traits::base_container_type  _base;
647:     typename traits::cap_container_type   _cap;
648:   protected:
649:     MPI_Comm    _comm;
650:     int         _commRank;
651:     int         _commSize;
652:     PetscObject _petscObj;
653:     void __init(MPI_Comm comm) {
654:       static PetscCookie sifterType = -1;
655:       //const char        *id_name = ALE::getClassName<T>();
656:       const char        *id_name = "Sifter";
657:       PetscErrorCode     ierr;

659:       if (sifterType < 0) {
660:         PetscLogClassRegister(&sifterType, id_name);CHKERROR(ierr, "Error in MPI_Comm_rank");
661:       }
662:       this->_comm = comm;
663:       MPI_Comm_rank(this->_comm, &this->_commRank); CHKERROR(ierr, "Error in MPI_Comm_rank");
664:       MPI_Comm_size(this->_comm, &this->_commSize); CHKERROR(ierr, "Error in MPI_Comm_rank");
665: #ifdef USE_PETSC_OBJ
666:       PetscObjectCreateGeneric(this->_comm, sifterType, id_name, &this->_petscObj);CHKERROR(ierr, "Error in PetscObjectCreate");
667: #endif
668:       //ALE::restoreClassName<T>(id_name);
669:     };
670:     // We store these sequence objects to avoid creating them each query
671:     Obj<typename traits::coneSequence> _coneSeq;
672:     Obj<typename traits::supportSequence> _supportSeq;
673:   public:
674:     //
675:     // Basic interface
676:     //
677:     ASifter(MPI_Comm comm = PETSC_COMM_SELF, const int& debug = 0) : _debug(debug), _petscObj(NULL) {
678:       __init(comm);
679:       this->_coneSeq    = new typename traits::coneSequence(*this, ::boost::multi_index::get<typename traits::coneInd>(this->_arrows.set), typename traits::target_type());
680:       this->_supportSeq = new typename traits::supportSequence(*this, ::boost::multi_index::get<typename traits::supportInd>(this->_arrows.set), typename traits::source_type());
681:    }
682:     virtual ~ASifter() {
683: #ifdef USE_PETSC_OBJ
684:       if (this->_petscObj) {
686:         PetscObjectDestroy(this->_petscObj); CHKERROR(ierr, "Failed in PetscObjectDestroy");
687:         this->_petscObj = NULL;
688:       }
689: #endif
690:     };
691:     //
692:     // Query methods
693:     //
694:     int         debug()    const {return this->_debug;};
695:     void        setDebug(const int debug) {this->_debug = debug;};
696:     MPI_Comm    comm()     const {return this->_comm;};
697:     int         commSize() const {return this->_commSize;};
698:     int         commRank() const {return this->_commRank;}
699: #ifdef USE_PETSC_OBJ
700:     PetscObject petscObj() const {return this->_petscObj;};
701: #endif

703:     // FIX: need const_cap, const_base returning const capSequence etc, but those need to have const_iterators, const_begin etc.
704:     Obj<typename traits::capSequence> cap() {
705:       return typename traits::capSequence(::boost::multi_index::get<typename traits::capInd>(this->_cap.set));
706:     };
707:     Obj<typename traits::baseSequence> base() {
708:       return typename traits::baseSequence(::boost::multi_index::get<typename traits::baseInd>(this->_base.set));
709:     };
710:     bool capContains(const typename traits::source_type& p) {
711:       typename traits::capSequence cap(::boost::multi_index::get<typename traits::capInd>(this->_cap.set));

713:       //for(typename traits::capSequence::iterator c_iter = cap.begin(); c_iter != cap.end(); ++c_iter) {
714:       //}
715:       return cap.contains(p);
716:     };
717:     bool baseContains(const typename traits::target_type& p) {
718:       typename traits::baseSequence base(::boost::multi_index::get<typename traits::baseInd>(this->_base.set));

720:       //for(typename traits::capSequence::iterator c_iter = cap.begin(); c_iter != cap.end(); ++c_iter) {
721:       //}
722:       return base.contains(p);
723:     };
724:     // FIX: should probably have cone and const_cone etc, since arrows can be modified through an iterator (modifyColor).
725:     Obj<typename traits::arrowSequence>
726:     arrows(const typename traits::source_type& s, const typename traits::target_type& t) {
727:       return typename traits::arrowSequence(::boost::multi_index::get<typename traits::arrowInd>(this->_arrows.set), s, t);
728:     };
729:     Obj<typename traits::arrowSequence>
730:     arrows(const typename traits::source_type& s) {
731:       return typename traits::arrowSequence(::boost::multi_index::get<typename traits::arrowInd>(this->_arrows.set), s);
732:     };
733: #ifdef SLOW
734:     Obj<typename traits::coneSequence>
735:     cone(const typename traits::target_type& p) {
736:       return typename traits::coneSequence(*this, ::boost::multi_index::get<typename traits::coneInd>(this->_arrows.set), p);
737:     };
738: #else
739:     const Obj<typename traits::coneSequence>&
740:     cone(const typename traits::target_type& p) {
741:       this->_coneSeq->setKey(p);
742:       this->_coneSeq->setUseSubkey(false);
743:       return this->_coneSeq;
744:     };
745: #endif
746:     template<class InputSequence>
747:     Obj<typename traits::coneSet>
748:     cone(const Obj<InputSequence>& points) {
749:       return this->cone(points, typename traits::color_type(), false);
750:     };
751: #ifdef SLOW
752:     Obj<typename traits::coneSequence>
753:     cone(const typename traits::target_type& p, const typename traits::color_type& color) {
754:       return typename traits::coneSequence(*this, ::boost::multi_index::get<typename traits::coneInd>(this->_arrows.set), p, color);
755:     };
756: #else
757:     const Obj<typename traits::coneSequence>&
758:     cone(const typename traits::target_type& p, const typename traits::color_type& color) {
759:       this->_coneSeq->setKey(p);
760:       this->_coneSeq->setSubkey(color);
761:       this->_coneSeq->setUseSubkey(true);
762:       return this->_coneSeq;
763:     };
764: #endif
765:     template<class InputSequence>
766:     Obj<typename traits::coneSet>
767:     cone(const Obj<InputSequence>& points, const typename traits::color_type& color, bool useColor = true) {
768:       Obj<typename traits::coneSet> cone = typename traits::coneSet();
769:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
770:         Obj<typename traits::coneSequence> pCone;
771:         if (useColor) {
772:           pCone = this->cone(*p_itor, color);
773:         } else {
774:           pCone = this->cone(*p_itor);
775:         }
776:         cone->insert(pCone->begin(), pCone->end());
777:       }
778:       return cone;
779:     };
780:     template<typename PointCheck>
781:     bool coneContains(const typename traits::target_type& p, const PointCheck& checker) {
782:       typename traits::coneSequence cone(*this, ::boost::multi_index::get<typename traits::coneInd>(this->_arrows.set), p);

784:       for(typename traits::coneSequence::iterator c_iter = cone.begin(); c_iter != cone.end(); ++c_iter) {
785:         if (checker(*c_iter, p)) return true;
786:       }
787:       return false;
788:     };
789:     template<typename PointProcess>
790:     void coneApply(const typename traits::target_type& p, PointProcess& processor) {
791:       typename traits::coneSequence cone(*this, ::boost::multi_index::get<typename traits::coneInd>(this->_arrows.set), p);

793:       for(typename traits::coneSequence::iterator c_iter = cone.begin(); c_iter != cone.end(); ++c_iter) {
794:         processor(*c_iter, p);
795:       }
796:     };
797: #ifdef SLOW
798:     Obj<typename traits::supportSequence>
799:     support(const typename traits::source_type& p) {
800:       return typename traits::supportSequence(*this, ::boost::multi_index::get<typename traits::supportInd>(this->_arrows.set), p);
801:     };
802: #else
803:     const Obj<typename traits::supportSequence>&
804:     support(const typename traits::source_type& p) {
805:       this->_supportSeq->setKey(p);
806:       this->_supportSeq->setUseSubkey(false);
807:       return this->_supportSeq;
808:     };
809: #endif
810: #ifdef SLOW
811:     Obj<typename traits::supportSequence>
812:     support(const typename traits::source_type& p, const typename traits::color_type& color) {
813:       return typename traits::supportSequence(*this, ::boost::multi_index::get<typename traits::supportInd>(this->_arrows.set), p, color);
814:     };
815: #else
816:     const Obj<typename traits::supportSequence>&
817:     support(const typename traits::source_type& p, const typename traits::color_type& color) {
818:       this->_supportSeq->setKey(p);
819:       this->_supportSeq->setSubkey(color);
820:       this->_supportSeq->setUseSubkey(true);
821:       return this->_supportSeq;
822:     };
823: #endif
824:     template<class InputSequence>
825:     Obj<typename traits::supportSet>
826:     support(const Obj<InputSequence>& sources) {
827:       return this->support(sources, typename traits::color_type(), false);
828:     };
829:     template<class InputSequence>
830:     Obj<typename traits::supportSet>
831:     support(const Obj<InputSequence>& points, const typename traits::color_type& color, bool useColor = true){
832:       Obj<typename traits::supportSet> supp = typename traits::supportSet();
833:       for(typename InputSequence::iterator p_itor = points->begin(); p_itor != points->end(); ++p_itor) {
834:         Obj<typename traits::supportSequence> pSupport;
835:         if (useColor) {
836:           pSupport = this->support(*p_itor, color);
837:         } else {
838:           pSupport = this->support(*p_itor);
839:         }
840:         supp->insert(pSupport->begin(), pSupport->end());
841:       }
842:       return supp;
843:     };
844:     template<typename PointCheck>
845:     bool supportContains(const typename traits::source_type& p, const PointCheck& checker) {
846:       typename traits::supportSequence support(*this, ::boost::multi_index::get<typename traits::supportInd>(this->_arrows.set), p);

848:       for(typename traits::supportSequence::iterator s_iter = support.begin(); s_iter != support.end(); ++s_iter) {
849:         if (checker(*s_iter, p)) return true;
850:       }
851:       return false;
852:     };
853:     template<typename PointProcess>
854:     void supportApply(const typename traits::source_type& p, PointProcess& processor) {
855:       typename traits::supportSequence support(*this, ::boost::multi_index::get<typename traits::supportInd>(this->_arrows.set), p);

857:       for(typename traits::supportSequence::iterator s_iter = support.begin(); s_iter != support.end(); ++s_iter) {
858:         processor(*s_iter, p);
859:       }
860:     };

862:     template<typename ostream_type>
863:     void view(ostream_type& os, const char* label = NULL, bool rawData = false){
864:       int rank = this->commRank();

866:       if(label != NULL) {
867:         os << "["<<rank<<"]Viewing Sifter '" << label << "':" << std::endl;
868:       }
869:       else {
870:         os << "["<<rank<<"]Viewing a Sifter:" << std::endl;
871:       }
872:       if(!rawData) {
873:         os << "cap --> base:" << std::endl;
874:         Obj<typename traits::capSequence> cap = this->cap();
875:         for(typename traits::capSequence::iterator capi = cap->begin(); capi != cap->end(); capi++) {
876:           const Obj<typename traits::supportSequence>& supp = this->support(*capi);

878:           for(typename traits::supportSequence::iterator suppi = supp->begin(); suppi != supp->end(); suppi++) {
879:             os << *capi << "--(" << suppi.color() << ")-->" << *suppi << std::endl;
880:           }
881:         }
882:         os << "base <-- cap:" << std::endl;
883:         Obj<typename traits::baseSequence> base = this->base();
884:         for(typename traits::baseSequence::iterator basei = base->begin(); basei != base->end(); basei++) {
885:           const Obj<typename traits::coneSequence>& cone = this->cone(*basei);

887:           for(typename traits::coneSequence::iterator conei = cone->begin(); conei != cone->end(); conei++) {
888:             os << *basei <<  "<--(" << conei.color() << ")--" << *conei << std::endl;
889:           }
890:         }
891:         os << "cap --> outdegrees:" << std::endl;
892:         for(typename traits::capSequence::iterator capi = cap->begin(); capi != cap->end(); capi++) {
893:           os << *capi <<  "-->" << capi.degree() << std::endl;
894:         }
895:         os << "base <-- indegrees:" << std::endl;
896:         for(typename traits::baseSequence::iterator basei = base->begin(); basei != base->end(); basei++) {
897:           os << *basei <<  "<--" << basei.degree() << std::endl;
898:         }
899:       }
900:       else {
901:         os << "'raw' arrow set:" << std::endl;
902:         for(typename traits::arrow_container_type::set_type::iterator ai = _arrows.set.begin(); ai != _arrows.set.end(); ai++)
903:         {
904:           typename traits::arrow_type arr = *ai;
905:           os << arr << std::endl;
906:         }
907:         os << "'raw' base set:" << std::endl;
908:         for(typename traits::base_container_type::set_type::iterator bi = _base.set.begin(); bi != _base.set.end(); bi++)
909:         {
910:           typename traits::base_container_type::traits::rec_type bp = *bi;
911:           os << bp << std::endl;
912:         }
913:         os << "'raw' cap set:" << std::endl;
914:         for(typename traits::cap_container_type::set_type::iterator ci = _cap.set.begin(); ci != _cap.set.end(); ci++)
915:         {
916:           typename traits::cap_container_type::traits::rec_type cp = *ci;
917:           os << cp << std::endl;
918:         }
919:       }
920:     };
921:     // A parallel viewer
922:     PetscErrorCode view(const char* label = NULL, bool raw = false){
924:       ostringstream txt;
926:       if(this->_debug) {
927:         std::cout << "viewing a Sifter, comm = " << this->comm() << ", PETSC_COMM_SELF = " << PETSC_COMM_SELF << ", commRank = " << this->commRank() << std::endl;
928:       }
929:       if(label != NULL) {
930:         PetscPrintf(this->comm(), "viewing Sifter: '%s'\n", label);
931:       } else {
932:         PetscPrintf(this->comm(), "viewing a Sifter: \n");
933:       }
934:       if(!raw) {
935:         ostringstream txt;
936:         if(this->commRank() == 0) {
937:           txt << "cap --> base:\n";
938:         }
939:         typename traits::capSequence cap   = this->cap();
940:         typename traits::baseSequence base = this->base();
941:         if(cap.empty()) {
942:           txt << "[" << this->commRank() << "]: empty" << std::endl;
943:         }
944:         for(typename traits::capSequence::iterator capi = cap.begin(); capi != cap.end(); capi++) {
945:           const Obj<typename traits::supportSequence>& supp = this->support(*capi);
946:           for(typename traits::supportSequence::iterator suppi = supp->begin(); suppi != supp->end(); suppi++) {
947:             txt << "[" << this->commRank() << "]: " << *capi << "--(" << suppi.color() << ")-->" << *suppi << std::endl;
948:           }
949:         }
950:         //
951:         PetscSynchronizedPrintf(this->comm(), txt.str().c_str()); CHKERROR(ierr, "Error in PetscSynchronizedFlush");
952:         PetscSynchronizedFlush(this->comm());  CHKERROR(ierr, "Error in PetscSynchronizedFlush");
953:         //
954:         ostringstream txt1;
955:         if(this->commRank() == 0) {
956:           //txt1 << "cap <point,degree>:\n";
957:           txt1 << "cap:\n";
958:         }
959:         txt1 << "[" << this->commRank() << "]:  [";
960:         for(typename traits::capSequence::iterator capi = cap.begin(); capi != cap.end(); capi++) {
961:           //txt1 << " <" << *capi << "," << capi.degree() << ">";
962:           txt1 << "  " << *capi;
963:         }
964:         txt1 << " ]" << std::endl;
965:         //
966:         PetscSynchronizedPrintf(this->comm(), txt1.str().c_str()); CHKERROR(ierr, "Error in PetscSynchronizedFlush");
967:         PetscSynchronizedFlush(this->comm());  CHKERROR(ierr, "Error in PetscSynchronizedFlush");
968:         //
969:         ostringstream txt2;
970:         if(this->commRank() == 0) {
971:           //txt2 << "base <point,degree>:\n";
972:           txt2 << "base:\n";
973:         }
974:         txt2 << "[" << this->commRank() << "]:  [";
975:         for(typename traits::baseSequence::iterator basei = base.begin(); basei != base.end(); basei++) {
976:           txt2 << "  " << *basei;
977:           //txt2 << " <" << *basei << "," << basei.degree() << ">";
978:         }
979:         txt2 << " ]" << std::endl;
980:         //
981:         PetscSynchronizedPrintf(this->comm(), txt2.str().c_str()); CHKERROR(ierr, "Error in PetscSynchronizedFlush");
982:         PetscSynchronizedFlush(this->comm());  CHKERROR(ierr, "Error in PetscSynchronizedFlush");
983:       }
984:       else { // if(raw)
985:         ostringstream txt;
986:         if(this->commRank() == 0) {
987:           txt << "'raw' arrow set:" << std::endl;
988:         }
989:         for(typename traits::arrow_container_type::set_type::iterator ai = _arrows.set.begin(); ai != _arrows.set.end(); ai++)
990:         {
991:           typename traits::arrow_type arr = *ai;
992:           txt << "[" << this->commRank() << "]: " << arr << std::endl;
993:         }
994:         PetscSynchronizedPrintf(this->comm(), txt.str().c_str()); CHKERROR(ierr, "Error in PetscSynchronizedFlush");
995:         PetscSynchronizedFlush(this->comm());  CHKERROR(ierr, "Error in PetscSynchronizedFlush");
996:         //
997:         ostringstream txt1;
998:         if(this->commRank() == 0) {
999:           txt1 << "'raw' base set:" << std::endl;
1000:         }
1001:         for(typename traits::base_container_type::set_type::iterator bi = _base.set.begin(); bi != _base.set.end(); bi++)
1002:         {
1003:           typename traits::base_container_type::traits::rec_type bp = *bi;
1004:           txt1 << "[" << this->commRank() << "]: " << bp << std::endl;
1005:         }
1006:         PetscSynchronizedPrintf(this->comm(), txt1.str().c_str()); CHKERROR(ierr, "Error in PetscSynchronizedFlush");
1007:         PetscSynchronizedFlush(this->comm());  CHKERROR(ierr, "Error in PetscSynchronizedFlush");
1008:         //
1009:         ostringstream txt2;
1010:         if(this->commRank() == 0) {
1011:           txt2 << "'raw' cap set:" << std::endl;
1012:         }
1013:         for(typename traits::cap_container_type::set_type::iterator ci = _cap.set.begin(); ci != _cap.set.end(); ci++)
1014:         {
1015:           typename traits::cap_container_type::traits::rec_type cp = *ci;
1016:           txt2 << "[" << this->commRank() << "]: " << cp << std::endl;
1017:         }
1018:         PetscSynchronizedPrintf(this->comm(), txt2.str().c_str()); CHKERROR(ierr, "Error in PetscSynchronizedFlush");
1019:         PetscSynchronizedFlush(this->comm());  CHKERROR(ierr, "Error in PetscSynchronizedFlush");
1020:       }// if(raw)
1021: 
1022:       return(0);
1023:     };
1024:   public:
1025:     //
1026:     // Lattice queries
1027:     //
1028:     template<class targetInputSequence>
1029:     Obj<typename traits::coneSequence> meet(const Obj<targetInputSequence>& targets);
1030:     // unimplemented
1031:     template<class targetInputSequence>
1032:     Obj<typename traits::coneSequence> meet(const Obj<targetInputSequence>& targets, const typename traits::color_type& color);
1033:     // unimplemented
1034:     template<class sourceInputSequence>
1035:     Obj<typename traits::coneSequence> join(const Obj<sourceInputSequence>& sources);
1036:     // unimplemented
1037:     template<class sourceInputSequence>
1038:     Obj<typename traits::coneSequence> join(const Obj<sourceInputSequence>& sources, const typename traits::color_type& color);
1039:   public:
1040:     //
1041:     // Structural manipulation
1042:     //
1043:     void clear() {
1044:       this->_arrows.set.clear(); this->_base.set.clear(); this->_cap.set.clear();
1045:     };
1046:     void addBasePoint(const typename traits::target_type t) {
1047:       /* // Increase degree by 0, which won't affect an existing point and will insert a new point, if necessery
1048:          this->_base.adjustDegree(t,0); */
1049:       this->_base.set.insert(typename traits::targetRec_type(t,0));
1050:     };
1051:     void addBasePoint(const typename traits::targetRec_type b) {
1052:       this->_base.set.insert(b);
1053:     };
1054:     void removeBasePoint(const typename traits::target_type t) {
1055:       if (this->_debug) {std::cout << " Removing " << t << " from the base" << std::endl;}
1056:       // Clear the cone and remove the point from _base
1057:       this->clearCone(t);
1058:       this->_base.removePoint(t);
1059:     };
1060:     void addCapPoint(const typename traits::source_type s) {
1061:       /* // Increase degree by 0, which won't affect an existing point and will insert a new point, if necessery
1062:          this->_cap.adjustDegree(s,0); */
1063:       this->_cap.set.insert(typename traits::sourceRec_type(s,0));
1064:     };
1065:     void addCapPoint(const typename traits::sourceRec_type c) {
1066:       this->_cap.set.insert(c);
1067:     };
1068:     void removeCapPoint(const typename traits::source_type s) {
1069:       if (this->_debug) {std::cout << " Removing " << s << " from the cap" << std::endl;}
1070:       // Clear the support and remove the point from _cap
1071:       this->clearSupport(s);
1072:       this->_cap.removePoint(s);
1073:     };
1074:     virtual void addArrow(const typename traits::source_type& p, const typename traits::target_type& q) {
1075:       this->addArrow(p, q, typename traits::color_type());
1076:     };
1077:     virtual void addArrow(const typename traits::source_type& p, const typename traits::target_type& q, const typename traits::color_type& color) {
1078:       this->addArrow(typename traits::arrow_type(p, q, color));
1079:       //std::cout << "Added " << arrow_type(p, q, color);
1080:     };
1081:     virtual bool checkArrow(const typename traits::arrow_type& a) {
1082:       if (this->_cap.set.find(a.source) == this->_cap.set.end()) return false;
1083:       if (this->_base.set.find(a.target) == this->_base.set.end()) return false;
1084:       return true;
1085:     };
1086:     virtual void addArrow(const typename traits::arrow_type& a, bool restrict = false) {
1087:       if (restrict && !this->checkArrow(a)) return;
1088:       this->_arrows.set.insert(a);
1089:       this->addBasePoint(a.target);
1090:       this->addCapPoint(a.source);
1091:     };
1092:     virtual void removeArrow(const typename traits::arrow_type& a) {
1093:       // First, produce an arrow sequence for the given source, target combination.
1094:       typename traits::arrowSequence::traits::index_type& arrowIndex =
1095:         ::boost::multi_index::get<typename traits::arrowInd>(this->_arrows.set);
1096:       typename traits::arrowSequence::traits::index_type::iterator i,ii,j;
1097:       i = arrowIndex.lower_bound(::boost::make_tuple(a.source,a.target));
1098:       ii = arrowIndex.upper_bound(::boost::make_tuple(a.source, a.target));
1099:       if (this->_debug) {
1100:         std::cout << "removeArrow: attempting to remove arrow:" << a << std::endl;
1101:         std::cout << "removeArrow: candidate arrows are:" << std::endl;
1102:       }
1103:       for(j = i; j != ii; j++) {
1104:         if (this->_debug) {
1105:           std::cout << " " << *j;
1106:         }
1107:         // Find the arrow of right color and remove it
1108:         if(j->color == a.color) {
1109:           if (this->_debug) {
1110:             std::cout << std::endl << "removeArrow: found:" << *j << std::endl;
1111:           }
1112:           /* this->_base.adjustDegree(a.target, -1); this->_cap.adjustDegree(a.source,-1); */
1113:           arrowIndex.erase(j);
1114:           break;
1115:         }
1116:       }
1117:     };

1119:     void addCone(const typename traits::source_type& source, const typename traits::target_type& target){
1120:       this->addArrow(source, target);
1121:     };
1122:     template<class sourceInputSequence>
1123:     void addCone(const Obj<sourceInputSequence>& sources, const typename traits::target_type& target) {
1124:       this->addCone(sources, target, typename traits::color_type());
1125:     };
1126:     void addCone(const typename traits::source_type& source, const typename traits::target_type& target, const typename traits::color_type& color) {
1127:       this->addArrow(source, target, color);
1128:     };
1129:     template<class sourceInputSequence>
1130:     void
1131:     addCone(const Obj<sourceInputSequence>& sources, const typename traits::target_type& target, const typename traits::color_type& color){
1132:       if (this->_debug > 1) {std::cout << "Adding a cone " << std::endl;}
1133:       for(typename sourceInputSequence::iterator iter = sources->begin(); iter != sources->end(); ++iter) {
1134:         if (this->_debug > 1) {std::cout << "Adding arrow from " << *iter << " to " << target << "(" << color << ")" << std::endl;}
1135:         this->addArrow(*iter, target, color);
1136:       }
1137:     };
1138:     void clearCone(const typename traits::target_type& t) {
1139:       clearCone(t, typename traits::color_type(), false);
1140:     };

1142:     void clearCone(const typename traits::target_type& t, const typename traits::color_type&  color, bool useColor = true) {
1143:       // Use the cone sequence types to clear the cone
1144:       typename traits::coneSequence::traits::index_type& coneIndex =
1145:         ::boost::multi_index::get<typename traits::coneInd>(this->_arrows.set);
1146:       typename traits::coneSequence::traits::index_type::iterator i, ii, j;
1147:       if (this->_debug > 20) {
1148:         std::cout << "clearCone: removing cone over " << t;
1149:         if(useColor) {
1150:           std::cout << " with color" << color << std::endl;
1151:           const Obj<typename traits::coneSequence>& cone = this->cone(t,color);
1152:           std::cout << "[";
1153:           for(typename traits::coneSequence::iterator ci = cone->begin(); ci != cone->end(); ci++) {
1154:             std::cout << "  " << ci.arrow();
1155:           }
1156:           std::cout << "]" << std::endl;
1157:         }
1158:         else {
1159:           std::cout << std::endl;
1160:           const Obj<typename traits::coneSequence>& cone = this->cone(t);
1161:           std::cout << "[";
1162:           for(typename traits::coneSequence::iterator ci = cone->begin(); ci != cone->end(); ci++) {
1163:             std::cout << "  " << ci.arrow();
1164:           }
1165:           std::cout << "]" << std::endl;
1166:         }
1167:       }
1168:       if (useColor) {
1169:         i = coneIndex.lower_bound(::boost::make_tuple(t,color));
1170:         ii = coneIndex.upper_bound(::boost::make_tuple(t,color));
1171:       } else {
1172:         i = coneIndex.lower_bound(::boost::make_tuple(t));
1173:         ii = coneIndex.upper_bound(::boost::make_tuple(t));
1174:       }
1175:       for(j = i; j != ii; j++){
1176:         // Adjust the degrees before removing the arrow; use a different iterator, since we'll need i,ii to do the arrow erasing.
1177:         if (this->_debug) {
1178:           std::cout << "clearCone: adjusting degrees for endpoints of arrow: " << *j << std::endl;
1179:         }
1180:         /* this->_cap.adjustDegree(j->source, -1);
1181:            this->_base.adjustDegree(j->target, -1); */
1182:       }
1183:       coneIndex.erase(i,ii);
1184:     };// clearCone()

1186:     template<class InputSequence>
1187:     void
1188:     restrictBase(const Obj<InputSequence>& points) {
1189:       typename traits::baseSequence base = this->base();
1190:       typename std::set<typename traits::target_type> remove;
1191: 
1192:       for(typename traits::baseSequence::iterator bi = base.begin(); bi != base.end(); bi++) {
1193:         // Check whether *bi is in points, if it is NOT, remove it
1194:         //           if (!points->contains(*bi)) {
1195:         if (points->find(*bi) == points->end()) {
1196:           //             this->removeBasePoint(*bi);
1197:           remove.insert(*bi);
1198:         }
1199:       }
1200:       //FIX
1201:       for(typename std::set<typename traits::target_type>::iterator r_iter = remove.begin(); r_iter != remove.end(); ++r_iter) {
1202:         this->removeBasePoint(*r_iter);
1203:       }
1204:     };

1206:     template<class InputSequence>
1207:     void
1208:     excludeBase(const Obj<InputSequence>& points) {
1209:       for(typename InputSequence::iterator pi = points->begin(); pi != points->end(); pi++) {
1210:         this->removeBasePoint(*pi);
1211:       }
1212:     };

1214:     template<class InputSequence>
1215:     void
1216:     restrictCap(const Obj<InputSequence>& points) {
1217:       typename traits::capSequence cap = this->cap();
1218:       for(typename traits::capSequence::iterator ci = cap.begin(); ci != cap.end(); ci++) {
1219:         // Check whether *ci is in points, if it is NOT, remove it
1220:         if(points->find(*ci) == points->end()) {
1221:           this->removeCapPoint(*ci);
1222:         }
1223:       }
1224:     };

1226:     template<class InputSequence>
1227:     void
1228:     excludeCap(const Obj<InputSequence>& points) {
1229:       for(typename InputSequence::iterator pi = points->begin(); pi != points->end(); pi++) {
1230:         this->removeCapPoint(*pi);
1231:       }
1232:     };

1234:     void clearSupport(const typename traits::source_type& s) {
1235:       clearSupport(s, typename traits::color_type(), false);
1236:     };
1237:     void clearSupport(const typename traits::source_type& s, const typename traits::color_type&  color, bool useColor = true) {
1238:       // Use the cone sequence types to clear the cone
1239:       typename
1240:         traits::supportSequence::traits::index_type& suppIndex = ::boost::multi_index::get<typename traits::supportInd>(this->_arrows.set);
1241:       typename traits::supportSequence::traits::index_type::iterator i, ii, j;
1242:       if (useColor) {
1243:         i = suppIndex.lower_bound(::boost::make_tuple(s,color));
1244:         ii = suppIndex.upper_bound(::boost::make_tuple(s,color));
1245:       } else {
1246:         i = suppIndex.lower_bound(::boost::make_tuple(s));
1247:         ii = suppIndex.upper_bound(::boost::make_tuple(s));
1248:       }
1249:       for(j = i; j != ii; j++){
1250:         // Adjust the degrees before removing the arrow
1251:         /* this->_cap.adjustDegree(j->source, -1);
1252:            this->_base.adjustDegree(j->target, -1); */
1253:       }
1254:       suppIndex.erase(i,ii);
1255:     };
1256:     void setCone(const typename traits::source_type& source, const typename traits::target_type& target){
1257:       this->clearCone(target, typename traits::color_type(), false); this->addCone(source, target);
1258:     };
1259:     template<class sourceInputSequence>
1260:     void setCone(const Obj<sourceInputSequence>& sources, const typename traits::target_type& target) {
1261:       this->clearCone(target, typename traits::color_type(), false); this->addCone(sources, target, typename traits::color_type());
1262:     };
1263:     void setCone(const typename traits::source_type& source, const typename traits::target_type& target, const typename traits::color_type& color) {
1264:       this->clearCone(target, color, true); this->addCone(source, target, color);
1265:     };
1266:     template<class sourceInputSequence>
1267:     void setCone(const Obj<sourceInputSequence>& sources, const typename traits::target_type& target, const typename traits::color_type& color){
1268:       this->clearCone(target, color, true); this->addCone(sources, target, color);
1269:     };
1270:     template<class targetInputSequence>
1271:     void addSupport(const typename traits::source_type& source, const Obj<targetInputSequence >& targets);
1272:     // Unimplemented
1273:     template<class targetInputSequence>
1274:     void addSupport(const typename traits::source_type& source, const Obj<targetInputSequence>& targets, const typename traits::color_type& color);
1275:     template<typename Sifter_>
1276:     void add(const Obj<Sifter_>& cbg, bool restrict = false) {
1277:       typename ::boost::multi_index::index<typename Sifter_::traits::arrow_container_type::set_type, typename Sifter_::traits::arrowInd>::type& aInd = ::boost::multi_index::get<typename Sifter_::traits::arrowInd>(cbg->_arrows.set);
1278: 
1279:       for(typename ::boost::multi_index::index<typename Sifter_::traits::arrow_container_type::set_type, typename Sifter_::traits::arrowInd>::type::iterator a_iter = aInd.begin(); a_iter != aInd.end(); ++a_iter) {
1280:         this->addArrow(*a_iter, restrict);
1281:       }
1282:       if (!restrict) {
1283:         typename ::boost::multi_index::index<typename Sifter_::traits::base_container_type::set_type, typename Sifter_::traits::baseInd>::type& bInd = ::boost::multi_index::get<typename Sifter_::traits::baseInd>(this->_base.set);
1284: 
1285:         for(typename ::boost::multi_index::index<typename Sifter_::traits::base_container_type::set_type, typename Sifter_::traits::baseInd>::type::iterator b_iter = bInd.begin(); b_iter != bInd.end(); ++b_iter) {
1286:           this->addBasePoint(*b_iter);
1287:         }
1288:         typename ::boost::multi_index::index<typename Sifter_::traits::cap_container_type::set_type, typename Sifter_::traits::capInd>::type& cInd = ::boost::multi_index::get<typename Sifter_::traits::capInd>(this->_cap.set);
1289: 
1290:         for(typename ::boost::multi_index::index<typename Sifter_::traits::cap_container_type::set_type, typename Sifter_::traits::capInd>::type::iterator c_iter = cInd.begin(); c_iter != cInd.end(); ++c_iter) {
1291:           this->addCapPoint(*c_iter);
1292:         }
1293:       }
1294:     };
1295:   }; // class ASifter

1297:   // A UniSifter aka Sifter
1298:   template <typename Source_, typename Target_, typename Color_,
1299:             typename SupportCompare_ = ::boost::multi_index::composite_key_compare<std::less<Source_>, std::less<Color_>, std::less<Target_> >,
1300:             typename SourceCtnr_ = SifterDef:: RecContainer<Source_, SifterDef::Rec<Source_> >, typename TargetCtnr_= SifterDef::RecContainer<Target_, SifterDef::Rec<Target_> > >
1301:   class Sifter : public ASifter<Source_, Target_, Color_, SifterDef::uniColor, SupportCompare_, SourceCtnr_, TargetCtnr_> {
1302:   public:
1303:       typedef typename ASifter<Source_, Target_, Color_, SifterDef::uniColor, SupportCompare_, SourceCtnr_, TargetCtnr_>::traits       traits;
1304:     template <typename OtherSource_, typename OtherTarget_, typename OtherColor_,
1305:               typename OtherSupportCompare_  = ::boost::multi_index::composite_key_compare<std::less<OtherSource_>, std::less<OtherColor_>, std::less<OtherTarget_> >,
1306:               typename OtherSourceCtnr_ = SifterDef::RecContainer<OtherSource_, SifterDef::Rec<OtherSource_> >,
1307:               typename OtherTargetCtnr_ = SifterDef::RecContainer<OtherTarget_, SifterDef::Rec<OtherTarget_> >      >
1308:     struct rebind {
1309:       typedef Sifter<OtherSource_, OtherTarget_, OtherColor_, OtherSupportCompare_, OtherSourceCtnr_, OtherTargetCtnr_> type;
1310:     };
1311:     // Re-export some typedefs expected by CoSifter
1312:     typedef typename traits::source_type                                            source_type;
1313:     typedef typename traits::target_type                                            target_type;
1314:     typedef typename traits::arrow_type                                             Arrow_;
1315:     typedef typename traits::coneSequence                                           coneSequence;
1316:     typedef typename traits::supportSequence                                        supportSequence;
1317:     typedef typename traits::baseSequence                                           baseSequence;
1318:     typedef typename traits::capSequence                                            capSequence;
1319:     // Basic interface
1320:     Sifter(MPI_Comm comm = PETSC_COMM_SELF, const int& debug = 0) :
1321:       ASifter<Source_, Target_, Color_, SifterDef::uniColor, SupportCompare_, SourceCtnr_, TargetCtnr_>(comm, debug) {};

1323:     const typename traits::color_type&
1324:     getColor(const typename traits::source_type& s, const typename traits::target_type& t, bool fail = true) {
1325:       typedef typename ::boost::multi_index::index<typename traits::arrow_container_type::set_type,typename traits::arrowInd>::type index_type;

1327:       const index_type& _index = ::boost::multi_index::get<typename traits::arrowInd>(this->_arrows.set);
1328: #if 0
1329:       ::boost::tuple<typename traits::source_type, typename traits::target_type> key = ::boost::make_tuple(s, t);
1330:       typename index_type::iterator begin = _index.lower_bound(key);
1331:       if(begin != _index.upper_bound(key)) {
1332:         return begin->color;
1333:       }
1334: #else
1335:       const typename index_type::iterator begin = _index.find(::boost::make_tuple(s, t));
1336:       if (begin != _index.end()) {
1337:         return begin->color;
1338:       }
1339: #endif
1340: //       typename traits::arrowSequence arr(::boost::multi_index::get<typename traits::arrowInd>(this->_arrows.set), s, t);
1341: //       if(arr.begin() != arr.end()) {
1342: //         return arr.begin().color();
1343: //       }
1344:       if (fail) {
1345:         ostringstream o;
1346:         o << "Arrow " << s << " --> " << t << " not present";
1347:         throw ALE::Exception(o.str().c_str());
1348:       } else {
1349:         static typename traits::color_type c;
1350:         return c;
1351:       }
1352:     };

1354:     template<typename ColorChanger>
1355:     void modifyColor(const typename traits::source_type& s, const typename traits::target_type& t, const ColorChanger& changeColor) {
1356:       typename ::boost::multi_index::index<typename traits::arrow_container_type::set_type, typename traits::arrowInd>::type& index =
1357:         ::boost::multi_index::get<typename traits::arrowInd>(this->_arrows.set);
1358:       typename ::boost::multi_index::index<typename traits::arrow_container_type::set_type, typename traits::arrowInd>::type::iterator i =
1359:         index.find(::boost::make_tuple(s,t));
1360:       if (i != index.end()) {
1361:         index.modify(i, changeColor);
1362:       } else {
1363:         typename traits::arrow_type a(s, t, typename traits::color_type());
1364:         changeColor(a);
1365:         this->addArrow(a);
1366:       }
1367:     };

1369:     struct ColorSetter {
1370:       ColorSetter(const typename traits::color_type& color) : _color(color) {};
1371:       void operator()(typename traits::arrow_type& p) const {
1372:         p.color = _color;
1373:       }
1374:     private:
1375:       const typename traits::color_type& _color;
1376:     };

1378:     void setColor(const typename traits::source_type& s, const typename traits::target_type& t, const typename traits::color_type& color) {
1379:       ColorSetter colorSetter(color);
1380:       typename ::boost::multi_index::index<typename traits::arrow_container_type::set_type, typename traits::arrowInd>::type& index =
1381:         ::boost::multi_index::get<typename traits::arrowInd>(this->_arrows.set);
1382:       typename ::boost::multi_index::index<typename traits::arrow_container_type::set_type, typename traits::arrowInd>::type::iterator i =
1383:         index.find(::boost::make_tuple(s,t));
1384:       if (i != index.end()) {
1385:         index.modify(i, colorSetter);
1386:       } else {
1387:         typename traits::arrow_type a(s, t, color);
1388:         this->addArrow(a);
1389:       }
1390:     };
1391:   };// class Sifter

1393: } // namespace ALE

1395: #endif