Generated on Thu Mar 22 10:39:45 2012 for Gecode by doxygen 1.6.3

integerset.hpp

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: 2011-09-19 14:02:26 +0200 (Mon, 19 Sep 2011) $ by $Author: schulte $
00015  *     $Revision: 12400 $
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    * BndSet
00046    *
00047    */
00048 
00049   forceinline
00050   BndSet::BndSet(void) :
00051     first(NULL), last(NULL), _size(0), _card(0) {}
00052 
00053   forceinline RangeList*
00054   BndSet::fst(void) const {
00055     return first;
00056   }
00057 
00058   forceinline RangeList*
00059   BndSet::lst(void) const {
00060     return last;
00061   }
00062 
00063   forceinline void
00064   BndSet::dispose(Space& home) {
00065     if (fst()!=NULL)
00066       fst()->dispose(home,lst());
00067   }
00068 
00069   forceinline void
00070   BndSet::fst(RangeList* f) {
00071     first = f;
00072   }
00073 
00074   forceinline void
00075   BndSet::lst(RangeList* l) {
00076     last = l;
00077   }
00078 
00079   forceinline
00080   BndSet::BndSet(Space& home, int mn, int mx) {
00081     if (mn>mx) {
00082       fst(NULL); lst(NULL); _size = 0;
00083     } else {
00084       RangeList* p =
00085         new (home) RangeList(mn,mx,NULL);
00086       fst(p); lst(p);
00087       _size = static_cast<unsigned int>(mx-mn+1);
00088     }
00089   }
00090 
00091   forceinline RangeList*
00092   BndSet::ranges(void) const {
00093     return fst();
00094   }
00095 
00096   forceinline unsigned int
00097   BndSet::size(void) const {
00098     return _size;
00099   }
00100 
00101   forceinline bool
00102   BndSet::empty(void) const {
00103     return (_size==0);
00104   }
00105 
00106   forceinline int
00107   BndSet::min(void) const {
00108     if (fst()==NULL)
00109       return MIN_OF_EMPTY;
00110     else
00111       return fst()->min();
00112   }
00113 
00114   forceinline int
00115   BndSet::max(void) const {
00116     if (lst()==NULL) 
00117       return MAX_OF_EMPTY;
00118     else 
00119       return lst()->max();
00120   }
00121 
00122   // nth smallest element
00123   forceinline int
00124   BndSet::minN(unsigned int n) const {
00125     for (RangeList* c = fst(); c != NULL; c = c->next()) {
00126       if (c->width() > n)
00127         return static_cast<int>(c->min() + n);
00128       n -= c->width();
00129     }
00130     return MIN_OF_EMPTY;
00131   }
00132 
00133   forceinline unsigned int
00134   BndSet::card(void) const {
00135     return _card;
00136   }
00137 
00138   forceinline void
00139   BndSet::card(unsigned int c) {
00140     _card = c;
00141   }
00142 
00143   forceinline void
00144   BndSet::update(Space& home, BndSet& d) {
00145     if (d.fst() == fst())
00146       return;
00147     if (fst() != NULL)
00148       fst()->dispose(home,lst());
00149     _size = d.size();
00150     if (_size == 0) {
00151       fst(NULL); lst(NULL);
00152       return;
00153     }
00154 
00155     int n=0;
00156     for (RangeList* c = d.fst(); c != NULL; c = c->next())
00157       n++;
00158 
00159     RangeList* r = home.alloc<RangeList>(n);
00160     fst(r); lst(r+n-1);
00161 
00162     {
00163       RangeList* c = d.fst();
00164       for (int i=0; i<n; i++) {
00165         r[i].min(c->min());
00166         r[i].max(c->max());
00167         r[i].next(&r[i+1]);
00168         c = c->next();
00169       }
00170     }
00171     r[n-1].next(NULL);
00172   }
00173 
00174   template<class I> forceinline bool
00175   BndSet::overwrite(Space& home, I& ri) {
00176     // Is new domain empty?
00177     if (!ri()) {
00178       //Was it empty?
00179       if (fst()==NULL)
00180         return false;
00181       fst()->dispose(home,lst());
00182       _size=0; fst(NULL); lst(NULL);
00183       return true;
00184     }
00185 
00186     RangeList* f =
00187       new (home) RangeList(ri.min(),ri.max(),NULL);
00188     RangeList* l = f;
00189     unsigned int s = ri.width();
00190 
00191     ++ri;
00192 
00193     while (ri()){
00194       RangeList *n = new (home) RangeList(ri.min(),ri.max(),NULL);
00195       l->next(n);
00196       l=n;
00197       s += ri.width();
00198       ++ri;
00199     }
00200 
00201     if (fst() != NULL)
00202       fst()->dispose(home,lst());
00203     fst(f); lst(l);
00204 
00205     // If the size did not change, nothing changed, as overwriting
00206     // must not at the same time include and exclude elements.
00207     if (size() == s)
00208       return false;
00209 
00210     _size = s;
00211     return true;
00212   }
00213 
00214   forceinline void
00215   BndSet::become(Space& home, const BndSet& that){
00216     if (fst()!=NULL){
00217       assert(lst()!=NULL);
00218       assert(fst()!= that.fst());
00219       fst()->dispose(home,lst());
00220     }
00221     fst(that.fst());
00222     lst(that.lst());
00223     _size = that.size();
00224     assert(isConsistent());
00225   }
00226 
00227   forceinline bool
00228   BndSet::in(int i) const {
00229     for (RangeList* c = fst(); c != NULL; c = c->next()) {
00230       if (c->min() <= i && c->max() >= i)
00231         return true;
00232       if (c->min() > i)
00233         return false;
00234     }
00235     return false;
00236   }
00237 
00238   /*
00239    * Range iterator for BndSets
00240    *
00241    */
00242 
00243   forceinline
00244   BndSetRanges::BndSetRanges(void) {}
00245 
00246   forceinline
00247   BndSetRanges::BndSetRanges(const BndSet& s)
00248     : Iter::Ranges::RangeList(s.ranges()) {}
00249 
00250   forceinline void
00251   BndSetRanges::init(const BndSet& s) {
00252     Iter::Ranges::RangeList::init(s.ranges());
00253   }
00254 
00255   /*
00256    * GLBndSet
00257    *
00258    */
00259 
00260   forceinline
00261   GLBndSet::GLBndSet(void) {}
00262 
00263   forceinline
00264   GLBndSet::GLBndSet(Space&) {}
00265 
00266   forceinline
00267   GLBndSet::GLBndSet(Space& home, int mi, int ma)
00268     : BndSet(home,mi,ma) {}
00269 
00270   forceinline
00271   GLBndSet::GLBndSet(Space& home, const IntSet& s)
00272     : BndSet(home,s) {}
00273 
00274   forceinline void
00275   GLBndSet::init(Space& home) {
00276     dispose(home);
00277     fst(NULL);
00278     lst(NULL);
00279     _size = 0;
00280   }
00281 
00282   forceinline bool
00283   GLBndSet::include(Space& home, int mi, int ma, SetDelta& d) {
00284     assert(ma >= mi);
00285     if (fst()==NULL) {
00286       RangeList* p = new (home) RangeList(mi,ma,NULL);
00287       fst(p);
00288       lst(p);
00289       _size=static_cast<unsigned int>(ma-mi+1);
00290       d._glbMin = mi;
00291       d._glbMax = ma;
00292       return true;
00293     }
00294     bool ret = include_full(home, mi, ma, d);
00295     assert(isConsistent());
00296     return ret;
00297   }
00298 
00299   template<class I> bool
00300   GLBndSet::includeI(Space& home, I& i) {
00301     if (!i())
00302       return false;
00303     BndSetRanges j(*this);
00304     Iter::Ranges::Union<BndSetRanges,I> ij(j,i);
00305     bool me = overwrite(home, ij);
00306     assert(isConsistent());
00307     return me;
00308   }
00309 
00310 
00311   /*
00312    * LUBndSet
00313    *
00314    */
00315 
00316   forceinline
00317   LUBndSet::LUBndSet(void) {}
00318 
00319   forceinline
00320   LUBndSet::LUBndSet(Space& home)
00321     : BndSet(home,Limits::min,Limits::max) {}
00322 
00323   forceinline
00324   LUBndSet::LUBndSet(Space& home, int mi, int ma)
00325     : BndSet(home,mi,ma) {}
00326 
00327   forceinline
00328   LUBndSet::LUBndSet(Space& home, const IntSet& s)
00329     : BndSet(home,s) {}
00330 
00331   forceinline void
00332   LUBndSet::init(Space& home) {
00333     RangeList *p =
00334       new (home) RangeList(Limits::min,
00335                            Limits::max,
00336                            NULL);
00337     fst(p);
00338     lst(p);
00339     _size = Limits::card;
00340   }
00341 
00342   forceinline bool
00343   LUBndSet::exclude(Space& home, int mi, int ma, SetDelta& d) {
00344     assert(ma >= mi);
00345     if ((mi > max()) || (ma < min())) { return false; }
00346     if (mi <= min() && ma >= max() ) { //the range covers the whole set
00347       d._lubMin = min();
00348       d._lubMax = max();
00349       fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00350       _size=0;
00351       return true;
00352     }
00353     bool ret =  exclude_full(home, mi, ma, d);
00354     assert(isConsistent());
00355     return ret;
00356   }
00357 
00358   forceinline bool
00359   LUBndSet::intersect(Space& home, int mi, int ma) {
00360     assert(ma >= mi);
00361     if ((mi <= min()) && (ma >= max())) { return false; }
00362     if (_size == 0) return false;
00363     if (ma < min() || mi > max() ) { // empty the whole set
00364      fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00365      _size=0;
00366      return true;
00367     }
00368     bool ret = intersect_full(home, mi, ma);
00369     assert(isConsistent());
00370     return ret;
00371   }
00372 
00373   template<class I> bool
00374   LUBndSet::intersectI(Space& home, I& i) {
00375     if (fst()==NULL) { return false; }
00376     if (!i()) {
00377       fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00378       _size=0;
00379       return true;
00380     }
00381     BndSetRanges j(*this);
00382     Iter::Ranges::Inter<BndSetRanges,I> ij(j,i);
00383     bool ret = overwrite(home, ij);
00384     assert(isConsistent());
00385     return ret;
00386   }
00387 
00388   template<class I> bool
00389   LUBndSet::excludeI(Space& home, I& i) {
00390     if (!i()) { return false; }
00391     BndSetRanges j(*this);
00392     Iter::Ranges::Diff<BndSetRanges,I> ij(j,i);
00393     bool ret = overwrite(home, ij);
00394     assert(isConsistent());
00395     return ret;
00396   }
00397 
00398   forceinline void
00399   LUBndSet::excludeAll(Space& home) {
00400     fst()->dispose(home,lst()); fst(NULL); lst(NULL);
00401     _size=0;
00402   }
00403 
00404   /*
00405    * A complement iterator spezialized for the BndSet limits
00406    *
00407    */
00408   template<class I>
00409   RangesCompl<I>::RangesCompl(void) {}
00410 
00411   template<class I>
00412   RangesCompl<I>::RangesCompl(I& i)
00413     : Iter::Ranges::Compl<Limits::min,
00414                           Limits::max,
00415                           I>(i) {}
00416 
00417   template<class I> void
00418   RangesCompl<I>::init(I& i) {
00419     Iter::Ranges::Compl<Limits::min,
00420       Limits::max,I>::init(i);
00421   }
00422 
00423 }}
00424 
00425 // STATISTICS: set-var
00426