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