Generated on Mon Aug 25 11:35:44 2008 for Gecode by doxygen 1.5.6

integerset.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *     Gabor Szokoli <szokoli@gecode.org>
00006  *     Christian Schulte <schulte@gecode.org>
00007  *
00008  *  Copyright:
00009  *     Guido Tack, 2004
00010  *     Christian Schulte, 2004
00011  *     Gabor Szokoli, 2004
00012  *
00013  *  Last modified:
00014  *     $Date: 2008-02-06 18:48:22 +0100 (Wed, 06 Feb 2008) $ by $Author: schulte $
00015  *     $Revision: 6102 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */
00041 
00042 namespace Gecode { namespace Set {
00043 
00044   /*
00045    * Range lists
00046    *
00047    */
00048 
00049   forceinline
00050   RangeList::RangeList(void) {}
00051 
00052   forceinline
00053   RangeList::RangeList(int min, int max, RangeList* n)
00054     : FreeList(n), _min(min), _max(max) {}
00055 
00056   forceinline RangeList*
00057   RangeList::next() const {
00058     return static_cast<RangeList*>(FreeList::next());
00059   }
00060   
00061   forceinline void
00062   RangeList::min(int n) {
00063     _min = n;
00064   }
00065   forceinline void
00066   RangeList::max(int n) {
00067     _max = n;
00068   }
00069   forceinline void
00070   RangeList::next(RangeList* n) {
00071     FreeList::next(n);
00072   }
00073 
00074   forceinline int
00075   RangeList::min(void) const {
00076     return _min;
00077   }
00078   forceinline int
00079   RangeList::max(void) const {
00080     return _max;
00081   }
00082   forceinline unsigned int
00083   RangeList::width(void) const {
00084     return _max - _min + 1;
00085   }
00086 
00087 
00088   forceinline void
00089   RangeList::operator delete(void*) {}
00090 
00091   forceinline void
00092   RangeList::operator delete(void*, Space*) {
00093     GECODE_NEVER;
00094   }
00095 
00096   forceinline void*
00097   RangeList::operator new(size_t, Space* home) {
00098     return home->fl_alloc<sizeof(RangeList)>();
00099   }
00100 
00101   forceinline void
00102   RangeList::dispose(Space* home, RangeList* l) {
00103     home->fl_dispose<sizeof(RangeList)>(this,l);
00104   }
00105 
00106 
00107   /*
00108    * BndSet
00109    *
00110    */
00111 
00112   forceinline
00113   BndSet::BndSet(void) :
00114     first(NULL), last(NULL), _size(0) {}
00115 
00116   forceinline RangeList*
00117   BndSet::fst(void) const {
00118     return first;
00119   }
00120 
00121   forceinline RangeList*
00122   BndSet::lst(void) const {
00123     return last;
00124   }
00125 
00126   forceinline void
00127   BndSet::dispose(Space* home) {
00128     if (fst()!=NULL)
00129       fst()->dispose(home,lst());
00130   }
00131 
00132   forceinline void
00133   BndSet::fst(RangeList* f) {
00134     first = f;
00135   }
00136 
00137   forceinline void
00138   BndSet::lst(RangeList* l) {
00139     last = l;
00140   }
00141 
00142   forceinline
00143   BndSet::BndSet(Space* home, int mn, int mx) {
00144     RangeList* p = 
00145       new (home) RangeList(mn,mx,NULL);
00146     fst(p); lst(p);
00147     _size = mx-mn+1;
00148   }
00149 
00150   forceinline RangeList*
00151   BndSet::ranges(void) const {
00152     return fst();
00153   }
00154 
00155   forceinline unsigned int
00156   BndSet::size(void) const {
00157     return _size;
00158   }
00159 
00160   forceinline bool
00161   BndSet::empty(void) const {
00162     return (_size==0);
00163   }
00164 
00165   forceinline int
00166   BndSet::min(void) const {
00167     if (fst()==NULL) { return MIN_OF_EMPTY; }
00168     else { return fst()->min(); }
00169   }
00170 
00171   forceinline int
00172   BndSet::max(void) const {
00173     if (lst()==NULL) { return MAX_OF_EMPTY; }
00174     else { return lst()->max(); }
00175   }
00176 
00177   // nth smallest element
00178   forceinline int
00179   BndSet::minN(unsigned int n) const {
00180     for (RangeList* c = fst(); c != NULL; c = c->next()) {
00181       if (c->width() > n)
00182         return c->min() + n;
00183       n -= c->width();
00184     }
00185     return MIN_OF_EMPTY;
00186   }
00187 
00188   forceinline void
00189   BndSet::update(Space* home, BndSet& d) {
00190     if ( d.fst() == fst())
00191       return;
00192     if (fst()!=NULL)
00193       fst()->dispose(home,lst());
00194     _size = d.size();
00195     if (_size==0) {
00196       fst(NULL); lst(NULL);
00197       return;
00198     }
00199 
00200     int n=0;
00201     for (RangeList* c = d.fst(); c != NULL; c = c->next())
00202       n++;
00203 
00204     RangeList* r = static_cast<RangeList*>(home->alloc(sizeof(RangeList)*n));
00205     fst(r); lst(r+n-1);
00206 
00207     RangeList* c = d.fst();
00208     for (int i=0; i<n; i++) {
00209       r[i].min(c->min());
00210       r[i].max(c->max());
00211       r[i].next(&r[i+1]);
00212       c = c->next();
00213     }
00214     r[n-1].next(NULL);
00215   }
00216 
00217   template <class I> forceinline bool
00218   BndSet::overwrite(Space* home, I& ri) {
00219     // Is new domain empty?
00220     if (!ri()) {
00221       //Was it empty?
00222       if (fst()==NULL)
00223         return false;
00224       fst()->dispose(home,lst());
00225       _size=0; fst(NULL); lst(NULL);
00226       return true;
00227     }
00228 
00229     RangeList* f =
00230       new (home) RangeList(ri.min(),ri.max(),NULL);
00231     RangeList* l = f;
00232     unsigned int s = ri.width();
00233 
00234     ++ri;
00235     
00236     while (ri()){
00237       RangeList *n = new (home) RangeList(ri.min(),ri.max(),NULL);
00238       l->next(n);
00239       l=n;
00240       s += ri.width();
00241       ++ri;
00242     }
00243 
00244     if (fst() != NULL)
00245       fst()->dispose(home,lst());
00246     fst(f); lst(l);
00247 
00248     // If the size did not change, nothing changed, as overwriting
00249     // must not at the same time include and exclude elements.
00250     if (size() == s)
00251       return false;
00252 
00253     _size = s;
00254     return true;
00255   }
00256 
00257   forceinline void
00258   BndSet::become(Space* home, const BndSet& that){
00259     if (fst()!=NULL){
00260       assert(lst()!=NULL);
00261       assert(fst()!= that.fst());
00262       fst()->dispose(home,lst());
00263     }
00264     fst(that.fst());
00265     lst(that.lst());
00266     _size = that.size();
00267     assert(isConsistent());
00268   }
00269 
00270   forceinline bool
00271   BndSet::in(int i) const {
00272     for (RangeList* c = fst(); c != NULL; c = c->next()) {
00273       if (c->min() <= i && c->max() >= i)
00274         return true;
00275       if (c->min() > i)
00276         return false;      
00277     }
00278     return false;
00279   }
00280 
00281   /*
00282    * Range iterator for BndSets
00283    *
00284    */
00285 
00286   forceinline
00287   BndSetRanges::BndSetRanges(void) {}
00288 
00289   forceinline
00290   BndSetRanges::BndSetRanges(const BndSet& s) : c(s.ranges()) {}
00291 
00292   forceinline void
00293   BndSetRanges::init(const BndSet& s) { c = s.ranges(); }
00294 
00295   forceinline bool
00296   BndSetRanges::operator()(void) const { return c != NULL; }
00297   
00298   forceinline void
00299   BndSetRanges::operator++(void) {
00300     c = c->next();
00301   }
00302 
00303   forceinline int
00304   BndSetRanges::min(void) const {
00305     return c->min();
00306   }
00307   forceinline int
00308   BndSetRanges::max(void) const {
00309     return c->max();
00310   }
00311   forceinline unsigned int
00312   BndSetRanges::width(void) const {
00313     return c->width();
00314   }
00315 
00316   /*
00317    * GLBndSet
00318    *
00319    */
00320 
00321   forceinline
00322   GLBndSet::GLBndSet(Space*) {}
00323 
00324   forceinline
00325   GLBndSet::GLBndSet(Space* home, int mi, int ma)
00326     : BndSet(home,mi,ma) { assert(mi<=ma); }
00327 
00328   forceinline
00329   GLBndSet::GLBndSet(Space* home, const IntSet& s)
00330     : BndSet(home,s) {}
00331 
00332   forceinline void
00333   GLBndSet::init(Space* home) {
00334     dispose(home);
00335     fst(NULL);
00336     lst(NULL);
00337     _size = 0;
00338   }
00339 
00340   forceinline bool
00341   GLBndSet::include(Space* home, int mi, int ma, SetDelta& d) {
00342     assert(ma >= mi);
00343     if (fst()==NULL) {
00344       RangeList* p = new (home) RangeList(mi,ma,NULL);
00345       fst(p);
00346       lst(p);
00347       _size=ma-mi+1;
00348       d._glbMin = mi;
00349       d._glbMax = ma;
00350       return true;
00351     }
00352     bool ret = include_full(home, mi, ma, d);
00353     assert(isConsistent());
00354     return ret;
00355   }
00356 
00357   template <class I> bool
00358   GLBndSet::includeI(Space* home, I& i) {
00359     if (!i())
00360       return false;
00361     BndSetRanges j(*this);
00362     Iter::Ranges::Union<BndSetRanges,I> ij(j,i);
00363     bool me = overwrite(home, ij);
00364     assert(isConsistent());
00365     return me;
00366   }
00367 
00368 
00369   /*
00370    * LUBndSet
00371    *
00372    */
00373 
00374   forceinline
00375   LUBndSet::LUBndSet(void) {}
00376 
00377   forceinline
00378   LUBndSet::LUBndSet(Space* home)
00379     : BndSet(home,Limits::min,Limits::max) {}
00380 
00381   forceinline
00382   LUBndSet::LUBndSet(Space* home, int mi, int ma)
00383     : BndSet(home,mi,ma) { assert(mi<=ma); }
00384 
00385   forceinline
00386   LUBndSet::LUBndSet(Space* home, const IntSet& s)
00387     : BndSet(home,s) {}
00388 
00389   forceinline void
00390   LUBndSet::init(Space* home) {
00391     RangeList *p =
00392       new (home) RangeList(Limits::min,
00393                            Limits::max,
00394                            NULL);
00395     fst(p);
00396     lst(p);
00397     _size = Limits::card;
00398   }
00399 
00400   forceinline bool
00401   LUBndSet::exclude(Space* home, int mi, int ma, SetDelta& d) {
00402     assert(ma >= mi);
00403     if ((mi > max()) || (ma < min())) { return false; }
00404     if (mi <= min() && ma >= max() ) { //the range covers the whole set
00405       d._lubMin = min();
00406       d._lubMax = max();
00407       fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00408       _size=0;
00409       return true;
00410     }
00411     bool ret =  exclude_full(home, mi, ma, d);
00412     assert(isConsistent());
00413     return ret;
00414   }
00415 
00416   forceinline bool
00417   LUBndSet::intersect(Space* home, int mi, int ma) {
00418     assert(ma >= mi);
00419     if ((mi <= min()) && (ma >= max())) { return false; }
00420     if (_size == 0) return false;
00421     if (ma < min() || mi > max() ) { // empty the whole set
00422      fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00423      _size=0;
00424      return true;
00425     }
00426     bool ret = intersect_full(home, mi, ma);
00427     assert(isConsistent());
00428     return ret;
00429   }
00430 
00431   template <class I> bool
00432   LUBndSet::intersectI(Space* home, I& i) {
00433     if (fst()==NULL) { return false; }
00434     if (!i()) {
00435       fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00436       _size=0;
00437       return true;
00438     }
00439     BndSetRanges j(*this);
00440     Iter::Ranges::Inter<BndSetRanges,I> ij(j,i);
00441     bool ret = overwrite(home, ij);
00442     assert(isConsistent());
00443     return ret;
00444   }
00445 
00446   template <class I> bool
00447   LUBndSet::excludeI(Space* home, I& i) {
00448     if (!i()) { return false; }
00449     BndSetRanges j(*this);
00450     Iter::Ranges::Diff<BndSetRanges,I> ij(j,i);
00451     bool ret = overwrite(home, ij);
00452     assert(isConsistent());
00453     return ret;
00454   }
00455 
00456   forceinline void
00457   LUBndSet::excludeAll(Space* home) {
00458     fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00459     _size=0;    
00460   }
00461 
00462   /*
00463    * A complement iterator spezialized for the BndSet limits
00464    *
00465    */
00466   template <class I>
00467   RangesCompl<I>::RangesCompl(void) {}
00468 
00469   template <class I>
00470   RangesCompl<I>::RangesCompl(I& i)
00471     : Iter::Ranges::Compl<Limits::min,
00472                           Limits::max,
00473                           I>(i) {}
00474 
00475   template <class I> void
00476   RangesCompl<I>::init(I& i) {
00477     Iter::Ranges::Compl<Limits::min,
00478       Limits::max,I>::init(i);
00479   }
00480 
00481 }}
00482 
00483 // STATISTICS: set-var
00484