Generated on Wed Nov 1 15:04:40 2006 for Gecode by doxygen 1.4.5

imp.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Contributing authors:
00006  *     Guido Tack <tack@gecode.org>
00007  *
00008  *  Copyright:
00009  *     Christian Schulte, 2003
00010  *     Guido Tack, 2004
00011  *
00012  *  Last modified:
00013  *     $Date: 2006-08-25 10:43:21 +0200 (Fri, 25 Aug 2006) $ by $Author: schulte $
00014  *     $Revision: 3568 $
00015  *
00016  *  This file is part of Gecode, the generic constraint
00017  *  development environment:
00018  *     http://www.gecode.org
00019  *
00020  *  See the file "LICENSE" for information on usage and
00021  *  redistribution of this file, and for a
00022  *     DISCLAIMER OF ALL WARRANTIES.
00023  *
00024  */
00025 
00026 namespace Gecode { namespace Int {
00027 
00028   /*
00029    * Range lists
00030    *
00031    */
00032 
00033 #define GECODE_INT_RL2PD(r) reinterpret_cast<ptrdiff_t>(r)
00034 #define GECODE_INT_PD2RL(p) reinterpret_cast<RangeList*>(p)
00035 
00036   forceinline
00037   IntVarImp::RangeList::RangeList(void) {}
00038 
00039   forceinline
00040   IntVarImp::RangeList::RangeList(int min, int max)
00041     : _min(min), _max(max) {}
00042 
00043   forceinline
00044   IntVarImp::RangeList::RangeList(int min, int max, RangeList* p, RangeList* n)
00045     : _min(min), _max(max) {
00046     _next = GECODE_INT_PD2RL(GECODE_INT_RL2PD(p)^GECODE_INT_RL2PD(n));
00047   }
00048 
00049   forceinline IntVarImp::RangeList*
00050   IntVarImp::RangeList::next(const RangeList* p) const {
00051     return GECODE_INT_PD2RL(GECODE_INT_RL2PD(_next)^GECODE_INT_RL2PD(p));
00052   }
00053   forceinline IntVarImp::RangeList*
00054   IntVarImp::RangeList::prev(const RangeList* n) const {
00055     return GECODE_INT_PD2RL(GECODE_INT_RL2PD(_next)^GECODE_INT_RL2PD(n));
00056   }
00057   forceinline void
00058   IntVarImp::RangeList::prevnext(RangeList* p, RangeList* n) {
00059     _next = GECODE_INT_PD2RL(GECODE_INT_RL2PD(p)^GECODE_INT_RL2PD(n));
00060   }
00061   forceinline void
00062   IntVarImp::RangeList::next(RangeList* o, RangeList* n) {
00063     _next = GECODE_INT_PD2RL(GECODE_INT_RL2PD(_next)^
00064                              (GECODE_INT_RL2PD(o)^GECODE_INT_RL2PD(n)));
00065   }
00066   forceinline void
00067   IntVarImp::RangeList::prev(RangeList* o, RangeList* n) {
00068     _next = GECODE_INT_PD2RL(GECODE_INT_RL2PD(_next)^
00069                              (GECODE_INT_RL2PD(o)^GECODE_INT_RL2PD(n)));
00070   }
00071   forceinline void
00072   IntVarImp::RangeList::fix(RangeList* n) {
00073     _next = n;
00074   }
00075 
00076   forceinline void
00077   IntVarImp::RangeList::min(int n) {
00078     _min = n;
00079   }
00080   forceinline void
00081   IntVarImp::RangeList::max(int n) {
00082     _max = n;
00083   }
00084 
00085   forceinline int
00086   IntVarImp::RangeList::min(void) const {
00087     return _min;
00088   }
00089   forceinline int
00090   IntVarImp::RangeList::max(void) const {
00091     return _max;
00092   }
00093   forceinline unsigned int
00094   IntVarImp::RangeList::width(void) const {
00095     return _max - _min + 1;
00096   }
00097 
00098 
00099   forceinline void
00100   IntVarImp::RangeList::operator delete(void*) {}
00101 
00102   forceinline void
00103   IntVarImp::RangeList::operator delete(void*, Space*) {
00104     GECODE_NEVER;
00105   }
00106 
00107   forceinline void*
00108   IntVarImp::RangeList::operator new(size_t s, Space* home) {
00109     assert(s == sizeof(RangeList));
00110     return home->fl_alloc<sizeof(RangeList)>();
00111   }
00112 
00113   forceinline void
00114   IntVarImp::RangeList::dispose(Space* home, RangeList* p, RangeList* l) {
00115     RangeList* c = this;
00116     while (c != l) {
00117       RangeList* n = c->next(p);
00118       c->fix(n);
00119       p=c; c=n;
00120     }
00121     home->fl_dispose<sizeof(RangeList)>(this,l);
00122   }
00123 
00124   forceinline void
00125   IntVarImp::RangeList::dispose(Space* home, RangeList* l) {
00126     home->fl_dispose<sizeof(RangeList)>(this,l);
00127   }
00128 
00129   forceinline void
00130   IntVarImp::RangeList::dispose(Space* home) {
00131     home->fl_dispose<sizeof(RangeList)>(this,this);
00132   }
00133 
00134 #undef GECODE_INT_RL2PD
00135 #undef GECODE_INT_PD2RL
00136 
00137   /*
00138    * Mainitaining range lists for variable domain
00139    *
00140    */
00141 
00142   forceinline IntVarImp::RangeList*
00143   IntVarImp::fst(void) const {
00144     return dom.next(NULL);
00145   }
00146 
00147   forceinline void
00148   IntVarImp::fst(IntVarImp::RangeList* f) {
00149     dom.prevnext(NULL,f);
00150   }
00151 
00152   forceinline IntVarImp::RangeList*
00153   IntVarImp::lst(void) const {
00154     return _lst;
00155   }
00156 
00157   forceinline void
00158   IntVarImp::lst(IntVarImp::RangeList* l) {
00159     _lst = l;
00160   }
00161 
00162   /*
00163    * Creation of new variable implementations
00164    *
00165    */
00166 
00167   forceinline
00168   IntVarImp::IntVarImp(Space* home, int min, int max)
00169     : IntVarImpBase(home), dom(min,max,NULL,NULL), holes(0) {}
00170 
00171   forceinline
00172   IntVarImp::IntVarImp(Space* home, const IntSet& d)
00173     : IntVarImpBase(home), dom(d.min(),d.max()) {
00174     if (d.size() > 1) {
00175       int n = d.size();
00176       RangeList* r = reinterpret_cast<RangeList*>
00177         (home->alloc(sizeof(RangeList)*n));
00178       fst(r); lst(r+n-1);
00179       unsigned int h = d.max()-d.min()+1;
00180       for (int i = n; i--; ) {
00181         h -= d.width(i);
00182         r[i].min(d.min(i)); r[i].max(d.max(i));
00183         r[i].prevnext(&r[i-1],&r[i+1]);
00184       }
00185       r[0].prev(&r[-1],NULL);
00186       r[n-1].next(&r[n],NULL);
00187       holes = h;
00188     } else {
00189       fst(NULL); holes = 0;
00190     }
00191   }
00192 
00193 
00194   /*
00195    * Operations on integer variable implementations
00196    *
00197    */
00198 
00199   forceinline int
00200   IntVarImp::min(void) const {
00201     return dom.min();
00202   }
00203   forceinline int
00204   IntVarImp::max(void) const {
00205     return dom.max();
00206   }
00207   forceinline int
00208   IntVarImp::val(void) const {
00209     assert(dom.min() == dom.max());
00210     return dom.min();
00211   }
00212 
00213   forceinline bool
00214   IntVarImp::range(void) const {
00215     return fst() == NULL;
00216   }
00217   forceinline bool
00218   IntVarImp::assigned(void) const {
00219     return dom.min() == dom.max();
00220   }
00221 
00222 
00223   forceinline unsigned int
00224   IntVarImp::width(void) const {
00225     return dom.width();
00226   }
00227 
00228   forceinline unsigned int
00229   IntVarImp::size(void) const {
00230     return dom.width() - holes;
00231   }
00232 
00233   forceinline unsigned int
00234   IntVarImp::regret_min(void) const {
00235     if (fst() == NULL) {
00236       return (dom.min() == dom.max()) ? 0 : 1;
00237     } else if (dom.min() == fst()->max()) {
00238       return fst()->next(NULL)->min()-dom.min();
00239     } else {
00240       return 1;
00241     }
00242   }
00243   forceinline unsigned int
00244   IntVarImp::regret_max(void) const {
00245     if (lst() == NULL) {
00246       return (dom.min() == dom.max()) ? 0 : 1;
00247     } else if (dom.max() == lst()->min()) {
00248       return dom.max()-lst()->prev(NULL)->max();
00249     } else {
00250       return 1;
00251     }
00252   }
00253 
00254 
00255 
00256   /*
00257    * Tests
00258    *
00259    */
00260 
00261   forceinline bool
00262   IntVarImp::in(int n) const {
00263     if ((n < dom.min()) || (n > dom.max()))
00264       return false;
00265     return (fst() == NULL) || in_full(n);
00266   }
00267   forceinline bool
00268   IntVarImp::in(double n) const {
00269     if ((n < dom.min()) || (n > dom.max()))
00270       return false;
00271     return (fst() == NULL) || in_full(static_cast<int>(n));
00272   }
00273 
00274 
00275   /*
00276    * Accessing rangelists for iteration
00277    *
00278    */
00279 
00280   forceinline const IntVarImp::RangeList*
00281   IntVarImp::ranges_fwd(void) const {
00282     return (fst() == NULL) ? &dom : fst();
00283   }
00284 
00285   forceinline const IntVarImp::RangeList*
00286   IntVarImp::ranges_bwd(void) const {
00287     return (fst() == NULL) ? &dom : lst();
00288   }
00289 
00290 
00291 
00292   /*
00293    * Tell operations (to be inlined: performing bounds checks first)
00294    *
00295    */
00296 
00297   forceinline ModEvent
00298   IntVarImp::gq(Space* home, int n) {
00299     if (n <= dom.min()) return ME_INT_NONE;
00300     if (n > dom.max())  return ME_INT_FAILED;
00301     gq_full(home,n);
00302     if (assigned())
00303       return ME_INT_VAL;
00304     return ME_INT_BND;
00305   }
00306   forceinline ModEvent
00307   IntVarImp::gq(Space* home, double n) {
00308     if (n <= dom.min()) return ME_INT_NONE;
00309     if (n > dom.max())  return ME_INT_FAILED;
00310     gq_full(home,static_cast<int>(n));
00311     if (assigned())
00312       return ME_INT_VAL;
00313     return ME_INT_BND;
00314   }
00315 
00316 
00317   forceinline ModEvent
00318   IntVarImp::lq(Space* home, int n) {
00319     if (n >= dom.max()) return ME_INT_NONE;
00320     if (n < dom.min())  return ME_INT_FAILED;
00321     lq_full(home,n);
00322     if (dom.min() == n)
00323       return ME_INT_VAL;
00324     return ME_INT_BND;
00325   }
00326   forceinline ModEvent
00327   IntVarImp::lq(Space* home, double n) {
00328     if (n >= dom.max()) return ME_INT_NONE;
00329     if (n < dom.min())  return ME_INT_FAILED;
00330     lq_full(home,static_cast<int>(n));
00331     if (dom.max() == n)
00332       return ME_INT_VAL;
00333     return ME_INT_BND;
00334   }
00335 
00336 
00337   forceinline ModEvent
00338   IntVarImp::eq(Space* home, int n) {
00339     if ((n < dom.min()) || (n > dom.max()))
00340       return ME_INT_FAILED;
00341     if ((n == dom.min()) && (n == dom.max()))
00342       return ME_INT_NONE;
00343     eq_full(home,n);
00344     if (dom.min() == Limits::Int::int_max+1)
00345       return ME_INT_FAILED;
00346     return ME_INT_VAL;
00347   }
00348   forceinline ModEvent
00349   IntVarImp::eq(Space* home, double n) {
00350     if ((n < dom.min()) || (n > dom.max()))
00351       return ME_INT_FAILED;
00352     if ((n == dom.min()) && (n == dom.max()))
00353       return ME_INT_NONE;
00354     eq_full(home,static_cast<int>(n));
00355     if (dom.min() == Limits::Int::int_max+1)
00356       return ME_INT_FAILED;
00357     return ME_INT_VAL;
00358   }
00359 
00360 
00361   forceinline ModEvent
00362   IntVarImp::nq(Space* home, int n) {
00363     if ((n < dom.min()) || (n > dom.max())) return ME_INT_NONE;
00364     return nq_full(home,n);
00365   }
00366   forceinline ModEvent
00367   IntVarImp::nq(Space* home, double d) {
00368     if ((d < dom.min()) || (d > dom.max())) return ME_INT_NONE;
00369     return nq_full(home,static_cast<int>(d));
00370   }
00371 
00372 
00373   /*
00374    * Tell operations with respect to iterators
00375    *
00376    */
00377 
00378   template <class I>
00379   forceinline ModEvent
00380   IntVarImp::narrow(Space* home, I& ri) {
00381     // Is new domain empty?
00382     if (!ri())
00383       return ME_INT_FAILED;
00384     int min0 = ri.min();
00385     int max0 = ri.max();
00386     ++ri;
00387     // Is new domain range?
00388     if (!ri()) {
00389       // Remove possible rangelist (if it was not a range, the domain
00390       // must have been narrowed!)
00391       if (fst()) {
00392         fst()->dispose(home,NULL,lst());
00393         fst(NULL); holes = 0;
00394       }
00395       const int min1 = dom.min(); dom.min(min0);
00396       const int max1 = dom.max(); dom.max(max0);
00397       if ((min0 == min1) && (max0 == max1))
00398         return ME_INT_NONE;
00399       if (min0 == max0) {
00400         notify(home,ME_INT_VAL);
00401         return ME_INT_VAL;
00402       }
00403     } else {
00404       // Construct new rangelist
00405       RangeList*   f = new (home) RangeList(min0,max0,NULL,NULL);
00406       RangeList*   l = f;
00407       unsigned int s = max0-min0+1;
00408       do {
00409         RangeList* n = new (home) RangeList(ri.min(),ri.max(),l,NULL);
00410         l->next(NULL,n);
00411         l = n;
00412         s += ri.width();
00413         ++ri;
00414       } while (ri());
00415       if (fst() != NULL)
00416         fst()->dispose(home,NULL,lst());
00417       fst(f); lst(l);
00418       // Check for modification
00419       if (size() == s)
00420         return ME_INT_NONE;
00421       const int min1 = dom.min(); min0 = f->min(); dom.min(min0);
00422       const int max1 = dom.max(); max0 = l->max(); dom.max(max0);
00423       holes = width() - s;
00424       if ((min0 == min1) && (max0 == max1)) {
00425         notify(home,ME_INT_DOM);
00426         return ME_INT_DOM;
00427       }
00428     }
00429     notify(home,ME_INT_BND);
00430     return ME_INT_BND;
00431   }
00432 
00433   /*
00434    * Copying a variable
00435    *
00436    */
00437 
00438   forceinline IntVarImp*
00439   IntVarImp::copy(Space* home, bool share) {
00440     return copied() ? static_cast<IntVarImp*>(forward())
00441       : perform_copy(home,share);
00442   }
00443   forceinline IntVarImp*
00444   IntVarImp::copy_bool(Space* home, bool share) {
00445     return copied() ? static_cast<IntVarImp*>(forward())
00446       : perform_copy_bool(home,share);
00447   }
00448 
00449 
00450 
00451   /*
00452    * Boolean tell operations (assume not yet assigned 0/1 variable)
00453    *
00454    */
00455 
00456   forceinline void
00457   IntVarImp::t_zero_none(Space* home) {
00458     assert((dom.min() == 0) && (dom.max() == 1));
00459     dom.max(0);
00460     notify(home,ME_INT_VAL);
00461   }
00462 
00463   forceinline void
00464   IntVarImp::t_one_none(Space* home) {
00465     assert((dom.min() == 0) && (dom.max() == 1));
00466     dom.min(1);
00467     notify(home,ME_INT_VAL);
00468   }
00469 
00470 
00471   /*
00472    * Forward range iterator for rangelists
00473    *
00474    */
00475 
00476   forceinline
00477   IntVarImpFwd::IntVarImpFwd(void) {}
00478   forceinline
00479   IntVarImpFwd::IntVarImpFwd(const IntVarImp* x)
00480     : p(NULL), c(x->ranges_fwd()) {}
00481   forceinline void
00482   IntVarImpFwd::init(const IntVarImp* x) {
00483     p=NULL; c=x->ranges_fwd();
00484   }
00485 
00486   forceinline bool
00487   IntVarImpFwd::operator()(void) const {
00488     return c != NULL;
00489   }
00490   forceinline void
00491   IntVarImpFwd::operator++(void) {
00492     const IntVarImp::RangeList* n=c->next(p); p=c; c=n;
00493   }
00494 
00495   forceinline int
00496   IntVarImpFwd::min(void) const {
00497     return c->min();
00498   }
00499   forceinline int
00500   IntVarImpFwd::max(void) const {
00501     return c->max();
00502   }
00503   forceinline unsigned int
00504   IntVarImpFwd::width(void) const {
00505     return c->width();
00506   }
00507 
00508 
00509   /*
00510    * Backward range iterator for rangelists
00511    *
00512    */
00513 
00514   forceinline
00515   IntVarImpBwd::IntVarImpBwd(void) {}
00516   forceinline
00517   IntVarImpBwd::IntVarImpBwd(const IntVarImp* x)
00518     : n(NULL), c(x->ranges_bwd()) {}
00519   forceinline void
00520   IntVarImpBwd::init(const IntVarImp* x) {
00521     n=NULL; c=x->ranges_bwd();
00522   }
00523 
00524   forceinline bool
00525   IntVarImpBwd::operator()(void) const {
00526     return c != NULL;
00527   }
00528   forceinline void
00529   IntVarImpBwd::operator++(void) {
00530     const IntVarImp::RangeList* p=c->prev(n); n=c; c=p;
00531   }
00532 
00533   forceinline int
00534   IntVarImpBwd::min(void) const {
00535     return c->min();
00536   }
00537   forceinline int
00538   IntVarImpBwd::max(void) const {
00539     return c->max();
00540   }
00541   forceinline unsigned int
00542   IntVarImpBwd::width(void) const {
00543     return c->width();
00544   }
00545 
00546 
00547   /*
00548    * More domain operations
00549    *
00550    */
00551   template <class I>
00552   forceinline ModEvent
00553   IntVarImp::inter(Space* home, I& i) {
00554     IntVarImpFwd j(this);
00555     Iter::Ranges::Inter<I,IntVarImpFwd> ij(i,j);
00556     return narrow(home,ij);
00557   }
00558 
00559   template <class I>
00560   forceinline ModEvent
00561   IntVarImp::minus(Space* home, I& i) {
00562     IntVarImpFwd j(this);
00563     Iter::Ranges::Diff<IntVarImpFwd,I> ij(j,i);
00564     return narrow(home,ij);
00565   }
00566 
00567   /*
00568    * Subscribing to variables
00569    *
00570    */
00571   forceinline void
00572   IntVarImp::subscribe(Space* home, Propagator* p, PropCond pc, bool process) {
00573     IntVarImpBase::subscribe(home,p,pc,dom.min()==dom.max(),process);
00574   }
00575 
00576 }}
00577 
00578 // STATISTICS: int-var
00579