Actual source code: Filter.hh

  1: #ifndef included_ALE_Predicate_hh
  2: #define included_ALE_Predicate_hh

  4: #ifndef  included_ALE_hh
  5: #include <ALE.hh>
  6: #endif

  8: #include <boost/multi_index/mem_fun.hpp>

 10: namespace ALE {

 12:   //
 13:   // Various Filter concepts and definitions
 14:   //
 15:   namespace FilterDef {
 16:     //
 17:     // PredicateTraits encapsulates Predicate types encoding object subsets with a given Predicate value or within a value range.
 18:     template<typename Predicate_>
 19:     struct PredicateTraits {};
 20:     // Traits of different predicate types are defined via specialization of PredicateTraits.
 21:     // We require that the predicate type act like a signed int.
 22:     template<>
 23:     struct PredicateTraits<int> {
 24:       typedef      int  predicate_type;
 25:       typedef      int  printable_type;
 26:       //
 27:       static const predicate_type third;
 28:       static const predicate_type max;
 29:       static const predicate_type min;
 30:     };
 31:     const PredicateTraits<int>::predicate_type PredicateTraits<int>::max   = INT_MAX;
 32:     const PredicateTraits<int>::predicate_type PredicateTraits<int>::min   = INT_MIN;
 33:     const PredicateTraits<int>::predicate_type PredicateTraits<int>::third = (abs(INT_MIN)<abs(INT_MAX))?abs(INT_MIN)/3:abs(INT_MAX)/3;
 34:     //
 35:     template<>
 36:     struct PredicateTraits<short> {
 37:       typedef      short  predicate_type;
 38:       typedef      short  printable_type;
 39:       //
 40:       static const predicate_type third;
 41:       static const predicate_type max;
 42:       static const predicate_type min;
 43:     };
 44:     const PredicateTraits<short>::predicate_type PredicateTraits<short>::max   = SHRT_MAX;
 45:     const PredicateTraits<short>::predicate_type PredicateTraits<short>::min   = SHRT_MIN;
 46:     const PredicateTraits<short>::predicate_type PredicateTraits<short>::third = (abs(SHRT_MIN)<abs(SHRT_MAX))?abs(SHRT_MIN)/3:abs(SHRT_MAX)/3;;
 47:     //
 48:     template<>
 49:     struct PredicateTraits<char> {
 50:       typedef char  predicate_type;
 51:       typedef short printable_type;
 52:       //
 53:       static const predicate_type third;
 54:       static const predicate_type max;
 55:       static const predicate_type min;
 56:     };
 57:     const PredicateTraits<char>::predicate_type PredicateTraits<char>::max   = CHAR_MAX;
 58:     const PredicateTraits<char>::predicate_type PredicateTraits<char>::min   = CHAR_MIN;
 59:     const PredicateTraits<char>::predicate_type PredicateTraits<char>::third = (abs(CHAR_MIN)<abs(CHAR_MAX))?abs(CHAR_MIN)/3:abs(CHAR_MAX)/3;
 60:     //
 61:     template <typename Predicate_, typename PredicateTraits_ = PredicateTraits<Predicate_> >
 62:     struct PredicateRec {
 63:       typedef  PredicateRec<Predicate_, PredicateTraits_> predicate_rec_type;
 64:       typedef Predicate_                                  predicate_type;
 65:       typedef PredicateTraits_                            predicate_traits;
 66:       //
 67:       predicate_type     predicate;
 68:       struct PredicateAdjuster {
 69:         PredicateAdjuster(const predicate_type& newPredicate = 0) :
 70:           _newPredicate(newPredicate) {};
 71:         void operator()(predicate_rec_type& r) {r.predicate = this->_newPredicate;};
 72:       private:
 73:         predicate_type _newPredicate; // assume predicate is cheap to copy,no more expensive than a pointer -- else ref would be used
 74:       };
 75:       //
 76:       // Basic interface
 77:       PredicateRec(const predicate_type& p = 0) : predicate(p) {};
 78:       PredicateRec(const PredicateRec& r) : predicate(r.p) {};
 79:       ~PredicateRec() {};
 80:     };

 82:     class FilterError : public ALE::Exception {
 83:     public:
 84:       explicit FilterError(const string&  msg)       : ALE::Exception(msg){}
 85:       explicit FilterError(const ostringstream& txt) : ALE::Exception(txt){};
 86:      ~FilterError(){};
 87:     };

 89:     template <typename PredicateSet_>
 90:     class DummyPredicateSetClearer {
 91:     public:
 92:       typedef PredicateSet_                                                  predicate_set_type;
 93:       typedef typename predicate_set_type::value_type                        predicate_rec_type;
 94:       typedef typename predicate_rec_type::predicate_type                    predicate_type;
 95:       typedef typename predicate_rec_type::predicate_traits                  predicate_traits;
 96:       //
 97:       void clear(predicate_set_type& set, const predicate_type& low, const predicate_type& high){};
 98:     };

100:     template <typename PredicateSet_, typename PredicateSetClearer_ = DummyPredicateSetClearer<PredicateSet_> >
101:     struct FilterContainer {
102:     public:
103:       //
104:       // Encapsulated types
105:       typedef FilterContainer                                                filter_container_type;
106:       typedef PredicateSet_                                                  predicate_set_type;
107:       typedef typename predicate_set_type::value_type                        predicate_rec_type;
108:       typedef typename predicate_rec_type::predicate_type                    predicate_type;
109:       typedef typename predicate_rec_type::predicate_traits                  predicate_traits;
110:       //
111:       typedef PredicateSetClearer_                                           clearer_type;
112:       //
113:       class Filter : public std::pair<predicate_type, predicate_type> {
114:       protected:
115:         filter_container_type& _container;
116:       public:
117:         Filter(filter_container_type& container) : std::pair<predicate_type, predicate_type>(0,0),  _container(container) {};
118:         Filter(filter_container_type& container, const predicate_type& left, const predicate_type& right) :
119:           std::pair<predicate_type, predicate_type>(left, right), _container(container) {};
120:         Filter(const Filter& f) : std::pair<predicate_type, predicate_type>(f.left(), f.right()),_container(f._container) {};
121:         ~Filter(){if((this->left()!=0)||(this->right()!=0)){this->_container.returnFilter(*this);}};
122:         //
123:         predicate_type         left()      const {return this->first;};
124:         predicate_type         right()     const {return this->second;};
125:         filter_container_type  container() const {return this->_container;};
126:         void extend(const predicate_type& width) {this->_container.extendFilter(*this, width);};
127:         void contract(const predicate_type& width) {this->_container.contractFilter(*this, width);};
128:         template <typename Stream_>
129:         friend Stream_& operator<<(Stream_& os, const Filter& f) {
130:           os << "[";
131:           os << ((typename predicate_traits::printable_type)(f.left())) << ",";
132:           os << ((typename predicate_traits::printable_type)(f.right()));
133:           os << "]";
134:           return os;
135:         };
136:         template <typename Stream_>
137:         friend Stream_& operator<<(Stream_& os, const Obj<Filter>& f) {
138:           os << "[";
139:           os << ((typename predicate_traits::printable_type)(f->left())) << ",";
140:           os << ((typename predicate_traits::printable_type)(f->right()));
141:           os << "]";
142:           return os;
143:         };
144:       };
145:       typedef Filter                                                          filter_type;
146:       typedef Obj<Filter>                                                     filter_object_type;
147: 
148:       //
149:       //
150:       // FilterSequence extends IndexSequence:
151:       //       0) elements are 'PredicateRec's
152:       //       1) holds the parent FilterContainer and an Obj<Filter>
153:       //       2) elements' predicates can be modified through the index iterator
154:       //       3) intent: in subclasses iterator construction (begin(), end()) and other queries should depend on the Filter(Object).
155:       template <typename FilterContainer_, typename Index_, typename ValueExtractor_>
156:       class FilterSequence : public IndexSequence<Index_, ValueExtractor_> { // class FilterSequence
157:       public:
158:         typedef FilterContainer_                             container_type;
159:         typedef IndexSequence<Index_, ValueExtractor_>       index_sequence_type;
160:         typedef typename index_sequence_type::index_type     index_type;
161:         typedef typename index_sequence_type::extractor_type extractor_type;
162:         typedef typename container_type::filter_type         filter_type;
163:         typedef typename container_type::filter_object_type  filter_object_type;
164:         //
165:         // Basic iterator over records with predicates
166:         template <typename Sequence_ = FilterSequence>
167:         class iterator : public index_sequence_type::template iterator<Sequence_> { // class iterator
168:         public:
169:           typedef typename index_sequence_type::template iterator<Sequence_> index_sequence_iterator;
170:           typedef typename index_sequence_iterator::sequence_type            sequence_type;
171:         public:
172:           iterator(sequence_type& sequence, typename index_type::iterator& itor) : index_sequence_iterator(sequence, itor) {};
173:           iterator(const iterator& iter)                                         : index_sequence_iterator(iter) {};
174:           //
175:           predicate_type  predicate()               const {return this->_itor->predicate;};
176:           bool            markOut(const predicate_type& p) {
177:             // We only allow predicate to increase or decrease so as to leave the filter.
178:             // In either case the iterator is advanced
179:             filter_object_type f = this->_sequence.filter();
180:             predicate_type left  = 0;
181:             predicate_type right = 0;
182:             bool result = false;
183:             if(!f.isNull()) {
184:               left  = f->left();
185:               right = f->right();
186:             }
187:             if((p < left) || (p > right)){
188:               // We keep a copy of the inderlying _itor of the location following *this prior to the mark up.
189:               // This becomes the new value of *this at the end, since the marked up *this will be out of the filter.
190:               iterator it(*this); ++it;
191:               // We have to deal with the following "corner case":
192:               // ++it points to this->_sequence.end(), but after having been marked Up *this becomes the new this->_sequence.end().
193:               // There are two ways to deal with the situation:
194:               // (1) the situation arises only if *this <= it, hence we can check for this using the ordering of this->_sequence --
195:               //    the ordering of the underlying index;
196:               // (2) the situation arises only if until the markUp ++it == this->_sequence.end(), so we can check for this
197:               //    and at the end of the markUp enforce *this == this->_sequence.end() regardless of the actual relationship
198:               //    between ++it and *this;
199:               // We choose option (2).
200:               bool atEnd = (it == this->_sequence.end());
201:               this->_sequence.mark(this->_itor, p);
202:               // now we advance this->_itor relative to ++it, not to the new marked up *this
203:               // can't use 'iterator' assignments because of the reference member _sequence
204:               if(atEnd) {
205:                 this->_itor = this->_sequence.end()._itor;
206:               }
207:               else {
208:                 this->_itor =  it._itor;
209:               }
210:               result = true;
211:             }// if((p < left) || (p > right))
212:             else {
213:               ++(*this);
214:             }
215:             return result; // return true if markUp successful
216:           };// markOut()
217:         };// class iterator
218:       protected:
219:         container_type&        _container;
220:         filter_object_type     _filter;
221:       public:
222:         //
223:         // Basic interface
224:         FilterSequence(const FilterSequence& seq) : index_sequence_type(seq),_container(seq._container), _filter(seq._filter) {};
225:         FilterSequence(container_type& container, index_type& index, const filter_object_type& filter = filter_object_type()) :
226:           index_sequence_type(index), _container(container), _filter(filter) {};
227:         ~FilterSequence(){};
228:         //
229:         // Extended interface
230:         filter_object_type filter() {return _filter;};
231:         void               mark(typename index_type::iterator itor, const predicate_type& p)      {
232:           this->_index.modify(itor, typename predicate_rec_type::PredicateAdjuster(p));
233:         };
234:       }; // class FilterSequence
235:     protected:
236:       predicate_set_type _set;
237:       predicate_type     _top;
238:       predicate_type     _bottom;
239:       predicate_type     _poccupancy[3];
240:       predicate_type     _noccupancy[3];
241:       clearer_type       _clearer;
242:       void __clear(const predicate_type& low, const predicate_type& high) {this->_clearer.clear(this->_set,low,high);};
243:       //
244:       void __validateFilter(const filter_type& f) {
245:         // Check filter validity
246:         bool negative = (f.left() < 0);
247:         // Produce correct filter limits and figure out which occupancy array to use
248:         predicate_type  left;
249:         predicate_type  right;
250:         if(negative) {
251:           left = -f.right(); right = -f.left();
252:         }
253:         else {
254:           left = f.left(); right = f.right();
255:         }
256:         predicate_type width = right - left + 1;
257:         if(((f.left() > 0)&&(f.right() < 0)) || ((f.left() < 0)&&(f.right() > 0))) {
258:           throw FilterError("inverted");
259:         }
260:         if((f.left()==0) || (f.right()==0)) {
261:           throw FilterError("zero extremum");
262:         }
263:         if(width > predicate_traits::third) {
264:           ostringstream txt;
265:           txt << "width too large: " << (typename predicate_traits::printable_type)width;;
266:           txt << " (limit is " << (typename predicate_traits::printable_type)predicate_traits::third << ")";
267:           throw FilterError(txt);
268:         }
269:       };// __validateFilter()
270:     public:
271:       //
272:       // Basic interface
273:       FilterContainer() : _top(1), _bottom(1) {
274:         this->_poccupancy[0] = 0; this->_poccupancy[1] = 0; this->_poccupancy[2] = 0;
275:         this->_noccupancy[0] = 0; this->_noccupancy[1] = 0; this->_noccupancy[2] = 0;
276:       };
277:      ~FilterContainer() {};
278:       //
279:       // Extended interface
280:       predicate_type   top()                   const {return this->_top;};
281:       predicate_type   bottom()                const {return this->_bottom;};
282:       predicate_type   pOccupancy(const int& i) const {
283:         if((i < 0) || (i > 2)){throw FilterError("Invalid interval index");}
284:         return this->_poccupancy[i];
285:       };
286:       predicate_type   nOccupancy(const int& i) const {
287:         if((i < 0) || (i > 2)){throw FilterError("Invalid interval index");}
288:         return this->_noccupancy[i];
289:       };
290:     public:
291:       //
292:       filter_object_type newFilter(predicate_type width) {
293:         // This routine will allocate a new filter prescribed by a (left,right) predicate pair.
294:         // Depending on the sign of width, left & right are both positive or negative; here we describe the positive case.
295:         // Filter endpoints are chosen from three different intervals of size predicate_traits::third ('third' here) each:
296:         // 'left' is picked from [1,third] or [third+1,2*third],
297:         // while 'right' is picked from [1,third],[third+1,2*third],[2*third+1,3*third].
298:         // The container keeps track of the number of filters intersecting each interval as well as the 'top' of the allocated
299:         // predicate range: 'top' is the next available predicate -- the next 'left'. Here are the rules for picking 'left' and 'right':
300:         //   (1) 'left' = 'top', 'right' = 'left' + width - 1,  and allocation of 'width' = 'right' - 'left' + 1 >= 'third' fails.
301:         //       Hence, if 'left' is from [1,third] then 'right' can be from [1,third] or [third+1,2*third]
302:         //       (depending on 'left' & 'width').
303:         //       Likewise, if 'left' is from [third+1,2*third] then 'right' can be from [third+1,2*third] or [2*third+1,3*third].
304:         //   (2) When 'top' ends up in [2*third+1, 3*third] it is shifted to 1 upon a subsequent allocation request so that it is
305:         //       served from [1,third] thereby completing the 'circle'.
306:         //   (3) Any time a filter crosses into a new interval, that interval is required to have no intersections with previously
307:         //       allocated filters, or allocation fails.
308:         // The rules can be intuitively summed up by imagining a cycle of intervals such that all old filters are deallocated from
309:         // an interval before new filters move in there again.  The working assumption is that the life span of filters is short enough
310:         // relative to the rate of new filter creation.  Rule (2) ensures that the interval endpoints always satisfy left <= right:
311:         // [2*third+1, 3*third] forms an 'overlflow buffer' for [third+1,2*third] and is little used.
312:         //
313:         if(width == 0) {
314:           ostringstream txt; txt << "Invalid filter requested: width = " << width << " (" << *this << ")";
315:           throw FilterError(txt);
316:         }
317:         // Select the correct 'top' & 'occupancy' indicators and make 'width' positive, if necessary
318:         bool negative = (width < 0);
319:         predicate_type* occupancy;
320:         predicate_type* top;
321:         if(negative) {
322:           width = -width;
323:           occupancy = this->_noccupancy;
324:           top = &(this->_bottom);
325: 
326:         }
327:         else {
328:           occupancy = this->_poccupancy;
329:           top = &(this->_top);
330:         }
331:         if(width > predicate_traits::third){
332:           ostringstream txt; txt << "Too big a filter requested: width = " << (typename predicate_traits::printable_type)width;
333:           txt << " (" << *this << ")";
334:           throw FilterError(txt);
335:         }
336:         // First, we set 'top' to 1 if it is greater than 2*third (i.e. within [2*third+1, 3*third]).
337:         if(*top > 2*predicate_traits::third) {
338:           *top = 1;
339:         }
340:         predicate_type lastRight = *top-1;      // 'right' of the preceeding interval
341:         predicate_type left      = *top;
342:         predicate_type right     = *top+width-1;
343:         // Before we return the new filter, internal bookkeeping and checks must be done to enforce the rules above.
344:         for(int i = 0; i < 2; i++) {
345:           // Check if crossing from the (i-1)-st interval  [(i-1)*third+1,i*third] to the i-th interval [i*third+1,i*third] has occured.
346:           if((lastRight <= i*predicate_traits::third) && (right > i*predicate_traits::third)) {
347:             // Line from [(i-1)*third+1,i*third] to [i*third+1,(i+1)*third] has been crossed
348:             // Check if [i*third+1,(i+1)*third] has been fully vacated
349:             if(occupancy[i] > 0){
350:               ostringstream txt;
351:               if(negative) {
352:                 txt << "Negative ";
353:               }
354:               else {
355:                 txt << "Positive ";
356:               }
357:               txt << "interval " << i << " not fully vacated when new filter requested: width = ";
358:               txt << (typename predicate_traits::printable_type)width;
359:               txt << " (" << *this << ")";
360:               throw FilterError(txt);
361:             }
362:             // Clear out the interval [i*third+1,(i+1)*third]
363:             this->__clear(i*predicate_traits::third+1, (i+1)*predicate_traits::third);
364:             break;
365:           }
366:         }// for(int i = 0; i < 2; i++) {
367:         // Adjust occupancy of intervals
368:         // Find the interval that 'left' lies in: 'left' is only allowed in the first two intervals
369:         for(int i = 0; i < 2; i++) {
370:           if((i*predicate_traits::third < left) && (left <= (i+1)*predicate_traits::third)) {
371:             ++(occupancy[i]);
372:             // Now check whether the interval spans two intervals (i.e., 'right' lies in the following interval)
373:             if(right > (i+1)*predicate_traits::third) {
374:               ++(occupancy[i+1]);
375:             }
376:           }
377:         }// for(int i = 0; i < 2; i++)
378:         // Finally, we advance 'top'
379:         *top = right+1;
380:         //
381:         filter_object_type f;
382:         f.create(filter_type(*this));
383:         if(negative) {
384:           f->first =  -right;
385:           f->second = -left;
386:         }
387:         else {
388:           f->first =  left;
389:           f->second = right;
390:         }
391:         return f;
392:       }; // newFilter()
393:       //
394:       void extendFilter(filter_type& f, const predicate_type& w) {
395:         try {
396:           __validateFilter(f);
397:         }
398:         catch(const FilterError& e) {
399:           ostringstream txt;
400:           txt << "Cannot extend invalid filter " << f << " in container " << f.container() << ": " << e.msg();
401:           throw FilterError(txt);
402:         }
403:         // Positive or negative filter?
404:         bool negative = (f.left() < 0);
405:         predicate_type width = f.right()-f.left()+1;
406:         predicate_type *top;
407:         predicate_type *occupancy;
408:         predicate_type left, right;
409:         if(negative) {
410:           width = -width;
411:           top = &this->_bottom;
412:           occupancy = this->_noccupancy;
413:           left = -f.right();
414:           right = -f.left();
415:         }
416:         else {
417:           top = &this->_top;
418:           occupancy = this->_poccupancy;
419:           left  = f.left();
420:           right = f.right();
421:         }
422:         // Only top filters can be extended
423:         if(right + 1 != *top){
424:           ostringstream txt;
425:           txt << "Only top/bottom filters can be extended: filter " << f << " in container " << *this;
426:         }
427:         if((width + w) > predicate_traits::third) {
428:           ostringstream txt;
429:           txt << "Extesion of ";
430:           if(negative) {
431:             txt << "negative ";
432:           }
433:           else {
434:             txt << "positive ";
435:           }
436:           txt << "filter " << f << " by " << w;
437:           txt << " width would exceed width limit of " << predicate_traits::third << " in container " << *this;
438:         }
439:         // newRight is right + w. Is newRight > 3*third? How do we check without an overflow?
440:         // newRight = left + width - 1 + w, so newRight > 3*third <==> width + w = newRight - left + 1 > third - left + 1.
441:         if(w+width > (3*predicate_traits::third-left+1)) {
442:           ostringstream txt;
443:           txt << "Extesion of ";
444:           if(negative) {
445:             txt << "negative ";
446:           }
447:           else {
448:             txt << "positive ";
449:           }
450:           txt << "filter " << f << " by " << w;
451:           txt << " width would exceed the upper limit limit of " << 3*predicate_traits::third << " in container " << *this;
452:         }
453:         predicate_type newRight = right + w;
454:         // CONTINUE: this is sorta messed up
455:         // Locate the 'right' footprint
456:         for(int i = 0; i < 2; i++) {
457:           if((i*predicate_traits::third < right) && (right <= (i+1)*predicate_traits::third)) {
458:             if(newRight > (i+1)*predicate_traits::third){ // crossing occured
459:               // Extension leads to a new interval crossing into the (i+1)-st interval
460:               // We check if the interval is occupied or not
461:               if(occupancy[i+1] > 0){
462:                 ostringstream txt;
463:                 if(negative) {
464:                   txt << "Negative ";
465:                 }
466:                 else {
467:                   txt << "Positive ";
468:                 }
469:                 txt << "interval " << i+1 << " not fully vacated when attempting extension of filter " << f << "by  width = " << w;
470:                 txt << (typename predicate_traits::printable_type)w;
471:                 txt << " (container " << *this << ")";
472:                 throw FilterError(txt);
473:               }
474:               // Clear out the interval [i*third+1,(i+1)*third]
475:               this->__clear((i+1)*predicate_traits::third+1, (i+2)*predicate_traits::third);
476:               // We record the new crossing in the occupancy array
477:               ++(occupancy[i+1]);
478:               break;
479:             }// if(newRight > (i+1)*predicate_traits::third): crossing occured
480:           }// if((i*predicate_traits::third < right) && (right <= (i+1)*predicate_traits::third))
481:         }// for(int i = 0; i < 2; i++)
482:         // Update 'top'
483:         *top = newRight+1;
484:         // Update filter limits
485:         if(negative) {
486:           f.first = -newRight;
487:         }
488:         else {
489:           f.second = newRight;
490:         }
491:       };// extendFilter()
492:       //
493:       void contractFilter(filter_type& f, const predicate_type& w) {
494:         try{
495:           __validateFilter(f);
496:         }
497:         catch(const FilterError& e) {
498:           ostringstream txt;
499:           txt << "Cannot contract invalid filter " << f << " in container " << f.container() << ": " << e.msg();
500:           throw FilterError(txt);
501:         }
502:         // Positive or negative filter?
503:         bool negative = (f.left() < 0);
504:         predicate_type width = f.right()-f.left()+1;
505:         predicate_type *top;
506:         predicate_type *occupancy;
507:         predicate_type left, right;
508:         if(negative) {
509:           width = -width;
510:           top = &this->_bottom;
511:           occupancy = this->_noccupancy;
512:           left  = -f.right();
513:           right = -f.left();
514:         }
515:         else {
516:           top = &this->_top;
517:           occupancy = this->_poccupancy;
518:           left  = f.left();
519:           right = f.right();
520:         }
521:         if((width - w) <= 0) {
522:           ostringstream txt;
523:           txt << "Contraction of ";
524:           if(negative) {
525:             txt << "negative ";
526:           }
527:           else {
528:             txt << "positive ";
529:           }
530:           txt << "filter " << f << " by " << w;
531:           txt << " would result in non-positive filter width " << width - w << " in container " << *this;
532:         }
533:         predicate_type newLeft = left + w;
534:         // Locate the 'left' footprint
535:         for(int i = 0; i < 2; i++) {
536:           if((i*predicate_traits::third < left) && (left <= (i+1)*predicate_traits::third)) {
537:             if(newLeft > (i+1)*predicate_traits::third){
538:               // Extension leads to a new interval crossing eliminated, which we record in the occupancy array
539:               --occupancy[i];
540:             }
541:           }
542:         }
543:         // Update filter limits
544:         if(negative) {
545:           f.second = -newLeft;
546:         }
547:         else {
548:           f.first = newLeft;
549:         }
550:       };// contractFilter()
551:       //
552:       void returnFilter(const filter_type& f) {
553:         try {
554:           __validateFilter(f);
555:         }
556:         catch(const FilterError& e) {
557:           ostringstream txt;
558:           txt << "Cannot return invalid filter " << f << " in container " << f.container() << ": " << e.msg();
559:           throw FilterError(txt);
560:         }
561:         // Compute the sign of the filter
562:         bool negative = (f.left() < 0);
563:         // Produce correct filter limits and figure out which occupancy array to use
564:         predicate_type  left;
565:         predicate_type  right;
566:         predicate_type* occupancy;
567:         if(negative) {
568:           left = -f.right(); right = -f.left();
569:           occupancy = this->_noccupancy;
570:         }
571:         else {
572:           left = f.left(); right = f.right();
573:           occupancy = this->_poccupancy;
574:         }
575:         // Find the interval that 'left' lies in: 'left' only allowed in the first two intervals
576:         for(int i = 0; i < 2; i++) {
577:           if((i*predicate_traits::third < left) && (left <= (i+1)*predicate_traits::third)) {
578:             if(occupancy[i] == 0) {
579:               ostringstream txt;
580:               if(negative) {
581:                 txt << "Negative ";
582:               }
583:               else {
584:                 txt << "Positive ";
585:               }
586:               txt << "occupancy of interval " << i << " will be negative upon closing of filter " << f;
587:               txt << " (container: " << *this << ")";
588:               throw FilterError(txt);
589:             }
590:             --(occupancy[i]);
591:             // Now check whether the interval spans two intervals (i.e., 'right' lies in the following interval)
592:             if(right > (i+1)*predicate_traits::third) {
593:               if(occupancy[i+1] == 0) {
594:                 ostringstream txt;
595:                 if(negative) {
596:                   txt << "Negative ";
597:                 }
598:                 else {
599:                   txt << "Positive ";
600:                 }
601:                 txt << "occupancy of interval " << i+1 << " will be negative upon closing of filter " << f;
602:               txt << " (container: " << *this << ")";
603:                 throw FilterError(txt);
604:               }
605:               --(occupancy[i+1]);
606:             }
607:           }
608:         }// for(int i = 0; i < 2; i++)
609:       }; // returnFilter()
610:       //
611:       // Printing
612:       template <typename Stream_>
613:       friend Stream_& operator<<(Stream_& os, const FilterContainer& fc) {
614:         os << "top = " << (typename predicate_traits::printable_type)(fc.top()) << ", pOccupancy = [";
615:         os << (typename predicate_traits::printable_type)(fc.pOccupancy(0)) << ",";
616:         os << (typename predicate_traits::printable_type)(fc.pOccupancy(1)) << ",";
617:         os << (typename predicate_traits::printable_type)(fc.pOccupancy(2));
618:         os << "]; ";
619:         os << "bottom = " << (typename predicate_traits::printable_type)(fc.bottom()) << ", nOccupancy = [";
620:         os << (typename predicate_traits::printable_type)(fc.nOccupancy(0)) << ",";
621:         os << (typename predicate_traits::printable_type)(fc.nOccupancy(1)) << ",";
622:         os << (typename predicate_traits::printable_type)(fc.nOccupancy(2));
623:         os << "]; ";
624:         return os;
625:       };
626:     };// class FilterContainer
627:   }// namespace FilterDef

629:   namespace X {
630:     using namespace ALE::FilterDef;
631:     namespace SifterDef { // namespace SifterDef
632:       //
633:       // Various ArrowContainer definitionsg
634:       //

636:       // Index tags
637:       struct PredicateTag{};
638:       struct ConeTag{};

640:       // Arrow record 'concept' -- conceptual structure names the fields expected in such an ArrowRec
641:       template <typename Predicate_, typename Arrow_>
642:       struct ArrowRec : public PredicateRec<Predicate_> {
643:         typedef PredicateRec<Predicate_>                      predicate_rec_type;
644:         typedef typename predicate_rec_type::predicate_type   predicate_type;
645:         typedef typename predicate_rec_type::predicate_traits predicate_traits;
646:         //
647:         typedef Arrow_                                        arrow_type;
648:         typedef  typename arrow_type::source_type             source_type;
649:         typedef  typename arrow_type::target_type             target_type;
650:         typedef  typename arrow_type::color_type              color_type;
651:       public:
652:         //
653:         arrow_type arrow;
654:       public:
655:         //
656:         // Basic interface
657:         ArrowRec(const source_type& s, const target_type& t, const color_type& c, const predicate_type& p = predicate_type()) :
658:           predicate_rec_type(p), arrow(s,t,c) {};
659:         ArrowRec(const ArrowRec& r) :
660:           predicate_rec_type(r.predicate), arrow(r.arrow.source, r.arrow.target, r.arrow.color)  {};
661:         ~ArrowRec(){};
662:         //
663:         // Extended interface
664:         const predicate_type& getPredicate() const {return this->predicate;};
665:         const arrow_type&     getArrow()     const {return this->arrow;};
666:         const source_type&    getSource()    const {return this->arrow.source;};
667:         const target_type&    getTarget()    const {return this->arrow.target;};
668:         const color_type&     getColor()     const {return this->arrow.color;};
669:         template <typename Stream_>
670:         friend Stream_& operator<<(Stream_& os, const ArrowRec& r) {
671:           os << r.getArrow() << " <" << (typename predicate_traits::printable_type)(r.getPredicate()) << "> ";
672:           return os;
673:         };
674:       };// class ArrowRec
675: 
676:       template<typename ArrowRecSet_, typename FilterTag_>
677:       struct ArrowContainer : public FilterContainer<ArrowRecSet_, FilterTag_> { // class ArrowContainer
678:       public:
679:         //
680:         // Encapsulated types
681:         typedef FilterContainer<ArrowRecSet_, FilterTag_>            filter_container_type;
682:         typedef typename filter_container_type::filter_type          filter_type;
683:         typedef typename filter_container_type::filter_object_type   filter_object_type;
684:         //
685:         typedef ArrowRecSet_                               arrow_rec_set_type; //must have correct tags
686:         typedef typename arrow_rec_set_type::value_type    arrow_rec_type;     // must (conceptually) extend ArrowContainerDef::ArrowRec
687:         typedef typename arrow_rec_type::arrow_type        arrow_type;         // arrow_type must have 'source','target','color' fields
688:         typedef typename arrow_rec_type::predicate_type    predicate_type;
689:         typedef typename arrow_rec_type::predicate_traits  predicate_traits;
690:         //
691:         typedef typename arrow_type::source_type           source_type;
692:         typedef typename arrow_type::target_type           target_type;
693:         typedef typename arrow_type::color_type            color_type;
694:         //
695:         //
696:         template <typename ArrowContainer_, typename Index_, typename ValueExtractor_>
697:         class NoKeyArrowSequence : public filter_container_type::template FilterSequence<ArrowContainer_, Index_, ValueExtractor_>
698:         { // class NoKeyArrowSequence
699:         public:
700:           //
701:           // Encapsulated types
702:           typedef typename filter_container_type::template FilterSequence<ArrowContainer_,Index_,ValueExtractor_> filter_sequence_type;
703:           typedef typename filter_sequence_type::container_type                                                   container_type;
704:           typedef typename filter_sequence_type::index_sequence_type                                              index_sequence_type;
705:           typedef typename filter_sequence_type::index_type                                                       index_type;
706:           typedef typename filter_sequence_type::extractor_type                                                   extractor_type;
707:           typedef typename filter_sequence_type::filter_type                                                      filter_type;
708:           typedef typename filter_sequence_type::filter_object_type                                               filter_object_type;
709:           // Need to extend the inherited iterator to be able to extract arrow attributes
710:           template <typename Sequence_ = NoKeyArrowSequence>
711:           class iterator : public filter_sequence_type::template iterator<Sequence_> {
712:           public:
713:             typedef typename filter_sequence_type::template iterator<Sequence_> filter_sequence_iterator;
714:             typedef typename filter_sequence_iterator::sequence_type            sequence_type;
715:             typedef typename sequence_type::index_type                          index_type;
716:             //
717:             iterator(sequence_type& sequence, typename index_type::iterator itor) : filter_sequence_iterator(sequence, itor) {};
718:             virtual const source_type& source()  const {return this->_itor->arrow.source;};
719:             virtual const color_type&  color ()  const {return this->_itor->arrow.color;};
720:             virtual const target_type& target()  const {return this->_itor->arrow.target;};
721:             virtual const arrow_type&  arrow ()  const {return this->_itor->arrow;};
722:           };// class iterator
723:         public:
724:           //
725:           // Basic interface
726:           NoKeyArrowSequence(const NoKeyArrowSequence& seq) : filter_sequence_type(seq) {};
727:           NoKeyArrowSequence(container_type& container, index_type& index, filter_object_type filter=filter_object_type()) : filter_sequence_type(container, index, filter) {};
728:          ~NoKeyArrowSequence() {};
729:           //
730:           // Extended interface
731:           virtual typename index_type::size_type  size()  {
732:             typename index_type::size_type sz = 0;
733:             predicate_type low  = 0;
734:             predicate_type high = 0;
735:             if(!(this->_filter.isNull())) {
736:               low  = this->_filter->left();
737:               high = this->_filter->right();
738:             }
739:             for(predicate_type p = low; p != high; p++) {
740:               sz += this->_index.count(p);
741:             }
742:             return sz;
743:           };
744:           virtual iterator<> begin() {
745:             predicate_type low = 0;
746:             if(!(this->_filter.isNull())) {
747:               low = this->_filter->left();
748:             }
749:             return iterator<>(*this, this->_index.lower_bound(low));
750:           };
751:           virtual iterator<> end() {
752:             predicate_type high = 0;
753:             if(!(this->_filter.isNull())) {
754:               high = this->_filter->right();
755:             }
756:             return iterator<>(*this, this->_index.upper_bound(high));
757:           };
758:           template<typename ostream_type>
759:           void view(ostream_type& os, const char* label = NULL){
760:             os << "Viewing";
761:             if(label != NULL) {
762:               os << " " << label;
763:             }
764:             if(!this->_filter.isNull()) {
765:               os << " filtered";
766:             }
767:             os << " sequence";
768:             if(!this->_filter.isNull()) {
769:               os << ", filter " << this->_filter;
770:             }
771:             os << ":" << std::endl;
772:             os << "[";
773:             for(iterator<> i = this->begin(); i != this->end(); i++) {
774:               if(i != this->begin()) {
775:                 os << ", " << i.arrow();
776:               }
777:               else {
778:                 os  << i.arrow();
779:               }
780:               os << " <" << (typename predicate_traits::printable_type)(i.predicate()) << ">";
781:             };
782:             os << "]" << std::endl;
783:           };// view()
784:         };// class NoKeyArrowSequence
785:         //
786:         template <typename ArrowContainer_, typename Index_, typename Key_, typename ValueExtractor_>
787:         class UniKeyArrowSequence : public filter_container_type::template FilterSequence<ArrowContainer_, Index_, ValueExtractor_>
788:         { // class TopFilterArrowSequence
789:         public:
790:           //
791:           // Encapsulated types
792:           typedef typename filter_container_type::template FilterSequence<ArrowContainer_,Index_,ValueExtractor_> filter_sequence_type;
793:           typedef typename filter_sequence_type::container_type                                                   container_type;
794:           typedef typename filter_sequence_type::index_sequence_type                                              index_sequence_type;
795:           typedef typename filter_sequence_type::index_type                                                       index_type;
796:           typedef typename filter_sequence_type::extractor_type                                                   extractor_type;
797:           typedef typename filter_sequence_type::filter_type                                                      filter_type;
798:           typedef typename filter_sequence_type::filter_object_type                                               filter_object_type;
799:           typedef Key_                                                                                            key_type;
800:           // Need to extend the inherited iterator to be able to extract arrow attributes
801:           template <typename Sequence_ = UniKeyArrowSequence>
802:           class iterator : public filter_sequence_type::template iterator<Sequence_> {
803:           public:
804:             typedef typename filter_sequence_type::template iterator<Sequence_> filter_sequence_iterator;
805:             typedef typename filter_sequence_iterator::sequence_type            sequence_type;
806:             typedef typename sequence_type::index_type                          index_type;
807:             //
808:             iterator(sequence_type& sequence, typename index_type::iterator itor) : filter_sequence_iterator(sequence, itor) {};
809:             virtual const source_type& source()  const {return this->_itor->arrow.source;};
810:             virtual const color_type&  color ()  const {return this->_itor->arrow.color;};
811:             virtual const target_type& target()  const {return this->_itor->arrow.target;};
812:             virtual const arrow_type&  arrow ()  const {return this->_itor->arrow;};
813:           };// class iterator
814:         protected:
815:           const key_type         _key;
816:         public:
817:           //
818:           // Basic interface
819:           UniKeyArrowSequence(const UniKeyArrowSequence& seq) : filter_sequence_type(seq), _key(seq._key) {};
820:           UniKeyArrowSequence(container_type& container, index_type& index,const key_type& key, filter_object_type filter=filter_object_type()) : filter_sequence_type(container, index, filter), _key(key) {};
821:          ~UniKeyArrowSequence() {};
822:           //
823:           // Extended interface
824:           virtual typename index_type::size_type  size()  {
825:             typename index_type::size_type sz = 0;
826:             predicate_type low  = 0;
827:             predicate_type high = 0;
828:             if(!(this->_filter.isNull())) {
829:               low  = this->_filter->left();
830:               high = this->_filter->right();
831:             }
832:             for(predicate_type p = low; p != high; p++) {
833:               sz += this->_index.count(::boost::make_tuple(this->_key,p));
834:             }
835:             return sz;
836:           };
837:           virtual iterator<> begin() {
838:             predicate_type low = 0;
839:             if(!(this->_filter.isNull())) {
840:               low = this->_filter->left();
841:             }
842:             return iterator<>(*this, this->_index.lower_bound(::boost::make_tuple(this->_key,low)));
843:           };
844:           virtual iterator<> end() {
845:             predicate_type high = 0;
846:             if(!(this->_filter.isNull())) {
847:               high = this->_filter->right();
848:             }
849:             return iterator<>(*this, this->_index.upper_bound(::boost::make_tuple(this->_key,high)));
850:           };
851:           virtual iterator<> beginAll() {
852:             return iterator<>(*this, this->_index.lower_bound(::boost::make_tuple(this->_key)));
853:           };
854:           virtual iterator<> endAll() {
855:             return iterator<>(*this, this->_index.upper_bound(::boost::make_tuple(this->_key)));
856:           };
857:           template<typename ostream_type>
858:           void view(ostream_type& os, const char* label = NULL){
859:             os << "Viewing";
860:             if(label != NULL) {
861:               os << " " << label;
862:             }
863:             if(!this->_filter.isNull()) {
864:               os << " filtered";
865:             }
866:             os << " sequence";
867:             if(!this->_filter.isNull()) {
868:               os << ", filter " << this->_filter;
869:             }
870:             os << ":" << std::endl;
871:             os << "[";
872:             for(iterator<> i = this->begin(); i != this->end(); i++) {
873:               if(i != this->begin()) {
874:                 os << ", " << i.arrow();
875:               }
876:               else {
877:                 os  << i.arrow();
878:               }
879:               os << " <" << (typename predicate_traits::printable_type)(i.predicate()) << ">";
880:             };
881:             os << "]" << std::endl;
882:           };// view()
883:         };// class UniKeyArrowSequence
884:       public:
885:         //
886:         // Basic interface
887:         ArrowContainer() {};
888:         ArrowContainer(const ArrowContainer& container) : filter_container_type(container) {};
889:         ~ArrowContainer(){};
890:         //
891:         // Extended interface
892:         void addArrow(const source_type& s, const target_type& t, const color_type& c) {
893:           this->_set.insert(arrow_rec_type(s,t,c));
894:         };
895:         //
896:         typedef UniKeyArrowSequence<ArrowContainer,
897:                                     typename ::boost::multi_index::index<arrow_rec_set_type,ConeTag>::type,
898:                                     target_type,
899:                                     typename ::boost::multi_index::const_mem_fun<arrow_rec_type, const source_type&, &arrow_rec_type::getSource> >
900:         ConeSequence;
901:         ConeSequence cone(const target_type& t, typename ConeSequence::filter_object_type f = filter_object_type()) {
902:           return ConeSequence(*this, ::boost::multi_index::get<ConeTag>(this->_set), t, f);
903:         };
904:       };// class ArrowContainer

906:       //
907:       // Various PointContainer definitions
908:       //

910:       // Index tags
911:       struct PointTag{};

913:       // Point record 'concept' -- conceptual structure names the fields expected in such an PointRec
914:       template <typename Predicate_, typename Point_>
915:       struct PointRec : public PredicateRec<Predicate_> {
916:         typedef PredicateRec<Predicate_>                      predicate_rec_type;
917:         typedef typename predicate_rec_type::predicate_type   predicate_type;
918:         typedef typename predicate_rec_type::predicate_traits predicate_traits;
919:         //
920:         typedef Point_                                        point_type;
921:       public:
922:         //
923:         point_type point;
924:       public:
925:         //
926:         // Basic interface
927:         PointRec(const point_type& q, const predicate_type& p = predicate_type()) : predicate_rec_type(p), point(q) {};
928:         PointRec(const PointRec& r) : predicate_rec_type(r.predicate), point(r.point)  {};
929:        ~PointRec(){};
930:         //
931:         // Extended interface
932:         const predicate_type& getPredicate() const {return this->predicate;};
933:         const point_type&     getPoint()     const {return this->point;};
934:         template <typename Stream_>
935:         friend Stream_& operator<<(Stream_& os, const PointRec& r) {
936:           os << r.getPoint() << " <" << (typename predicate_traits::printable_type)(r.getPredicate()) << "> ";
937:           return os;
938:         };
939:       };// class PointRec

941:     };// namespace SifterDef

943:     typedef SifterDef::ArrowRec<char, ALE::Arrow<int, int, int> > MyArrowRec;
944:     typedef SifterDef::PointRec<char, ALE::Point>                 MySourceRec;
945:     typedef SifterDef::PointRec<char, ALE::Point>                 MyTargetRec;

947:     // multi-index set type -- arrow set
948:     typedef  ::boost::multi_index::multi_index_container<
949:                MyArrowRec,
950:                ::boost::multi_index::indexed_by<
951:                  ::boost::multi_index::ordered_non_unique<
952:                    ::boost::multi_index::tag<SifterDef::ConeTag>,
953:                    ::boost::multi_index::composite_key<
954:                      MyArrowRec,
955:                      ::boost::multi_index::const_mem_fun<MyArrowRec, const MyArrowRec::target_type&,    &MyArrowRec::getTarget>,
956:                      ::boost::multi_index::const_mem_fun<MyArrowRec, const MyArrowRec::predicate_type&, &MyArrowRec::getPredicate>,
957:                      ::boost::multi_index::const_mem_fun<MyArrowRec, const MyArrowRec::color_type&,     &MyArrowRec::getColor>
958:                    >
959:                  >
960:                >,
961:                ALE_ALLOCATOR<MyArrowRec>
962:     > UniColorArrowSet;
963:   }; // namespace X
964: }; // namespace ALE

966: #endif