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

int.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2004
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-07-11 09:36:57 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00011  *     $Revision: 7295 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 namespace Gecode { namespace Int { namespace Element {
00039 
00049   class IdxValLink  {
00050   public:
00051     IdxValLink* idx_next;
00052     IdxValLink* val_next;
00053     int idx, val;
00054 
00055     void mark(void);
00056     bool marked(void) const;
00057   };
00058 
00059   forceinline void
00060   IdxValLink::mark(void) {
00061     idx = -1;
00062   }
00063   forceinline bool
00064   IdxValLink::marked(void) const {
00065     return idx<0;
00066   }
00067 
00068 
00069 
00076   class IterIdx {
00077   private:
00078     IdxValLink* l;
00079   public:
00080     IterIdx(void);
00081     IterIdx(IdxValLink&);
00082     void init(IdxValLink&);
00083     bool operator()(void) const;
00084     void operator++(void);
00085     int  val(void) const;
00086   };
00087 
00088   forceinline
00089   IterIdx::IterIdx(void) {}
00090   forceinline
00091   IterIdx::IterIdx(IdxValLink& ivl) {
00092     IdxValLink* p=&ivl;
00093     l = p->idx_next;
00094     while ((l != NULL) && l->marked())
00095       l=l->idx_next;
00096     p->idx_next=l;
00097   }
00098   forceinline void
00099   IterIdx::init(IdxValLink& ivl) {
00100     IdxValLink* p=&ivl;
00101     l = p->idx_next;
00102     while ((l != NULL) && l->marked())
00103       l=l->idx_next;
00104     p->idx_next=l;
00105   }
00106   forceinline bool
00107   IterIdx::operator()(void) const {
00108     return l != NULL;
00109   }
00110   forceinline void
00111   IterIdx::operator++(void) {
00112     IdxValLink* p=l;
00113     l = p->idx_next;
00114     while ((l != NULL) && l->marked())
00115       l=l->idx_next;
00116     p->idx_next=l;
00117   }
00118   forceinline int
00119   IterIdx::val(void) const {
00120     assert(!l->marked());
00121     return l->idx;
00122   }
00123 
00124 
00125 
00132   class IterVal {
00133   private:
00134     const IdxValLink* l;
00135   public:
00136     IterVal(void);
00137     IterVal(const IdxValLink&);
00138     void init(const IdxValLink&);
00139     bool operator()(void) const;
00140     void operator++(void);
00141     int  val(void) const;
00142   };
00143 
00144   forceinline
00145   IterVal::IterVal(void) {}
00146   forceinline
00147   IterVal::IterVal(const IdxValLink& ivl)
00148     : l(ivl.val_next) {}
00149   forceinline void
00150   IterVal::init(const IdxValLink& ivl) {
00151     l = ivl.val_next;
00152   }
00153   forceinline bool
00154   IterVal::operator()(void) const {
00155     return l != NULL;
00156   }
00157   forceinline void
00158   IterVal::operator++(void) {
00159     l=l->val_next;
00160   }
00161   forceinline int
00162   IterVal::val(void) const {
00163     assert(!l->marked());
00164     return l->val;
00165   }
00166 
00167 
00168 
00169 
00174   class IdxValMap {
00175   private:
00177     class ByVal {
00178     public:
00179       bool operator()(IdxValLink*&, IdxValLink*&);
00180     };
00181     size_t _size;
00182     IdxValLink iv[1];
00183   public:
00185     static IdxValMap* allocate(int);
00186     template <class ViewA> void init(int*,ViewA);
00187 
00189     template <class ViewA> void prune_idx(ViewA);
00190     template <class ViewB> void prune_val(ViewB);
00191 
00193     template <class ViewA, class ViewB>
00194     ExecStatus tell(Space*,ViewA,ViewB);
00195 
00196     size_t size(void) const;
00197     static void operator delete(void* p,size_t);
00198   private:
00199     static void* operator new(size_t);
00200   };
00201 
00202   forceinline bool
00203   IdxValMap::ByVal::operator()(IdxValLink*& x, IdxValLink*& y) {
00204     return x->val < y->val;
00205   }
00206 
00207   forceinline IdxValMap*
00208   IdxValMap::allocate(int n) {
00209     size_t s = sizeof(IdxValMap)+n*sizeof(IdxValLink);
00210     IdxValMap* ivm = static_cast<IdxValMap*>(Memory::malloc(s));
00211     ivm->_size = s;
00212     return ivm;
00213   }
00214 
00215   forceinline size_t
00216   IdxValMap::size(void) const {
00217     return _size;
00218   }
00219 
00220   template <class ViewA>
00221   inline void
00222   IdxValMap::init(int* a, ViewA ix) {
00223     // The first element in iv[0] is used as sentinel
00224     // Enter information sorted by idx
00225     IdxValLink* by_idx = &iv[1];
00226     {
00227       int i = 0;
00228       ViewValues<ViewA> v(ix);
00229       while (v()) {
00230         by_idx[i].idx = v.val();
00231         by_idx[i].val = a[v.val()];
00232         ++i; ++v;
00233       }
00234     }
00235     int size = ix.size();
00236     // Create val links sorted by val
00237     GECODE_AUTOARRAY(IdxValLink*,by_val,size);
00238     for (int i = size; i--; )
00239       by_val[i] = &iv[i+1];
00240     ByVal lt;
00241     Support::quicksort<IdxValLink*>(by_val,size,lt);
00242     // Create idx and val links
00243     for (int i = size-1; i--; ) {
00244       by_idx[i].idx_next  = by_idx+i+1;
00245       by_val[i]->val_next = by_val[i+1];
00246     }
00247     by_idx[size-1].idx_next  = NULL;
00248     by_val[size-1]->val_next = NULL;
00249     // Set up sentinel element: iv[0]
00250     iv[0].idx_next = &by_idx[0];
00251     iv[0].val_next = by_val[0];
00252   }
00253 
00254   template <class ViewA>
00255   forceinline void
00256   IdxValMap::prune_idx(ViewA x0) {
00257     IdxValLink* p = &iv[0];
00258     IdxValLink* l = p->idx_next;
00259     ViewRanges<ViewA> i(x0);
00260     while (i() && (l != NULL)) {
00261       assert(!l->marked());
00262       if (l->idx < i.min()) {
00263         l->mark(); l=l->idx_next; p->idx_next=l;
00264       } else if (l->idx > i.max()) {
00265         ++i;
00266       } else {
00267         p=l; l=l->idx_next;
00268       }
00269     }
00270     p->idx_next = NULL;
00271     while (l != NULL) { l->mark(); l=l->idx_next; }
00272   }
00273 
00274   template <class ViewB>
00275   forceinline void
00276   IdxValMap::prune_val(ViewB x1) {
00277     IdxValLink* p = &iv[0];
00278     IdxValLink* l = p->val_next;
00279     ViewRanges<ViewB> v(x1);
00280     while (v() && (l != NULL)) {
00281       if (l->marked()) {
00282         l=l->val_next; p->val_next=l;
00283       } else if (l->val < v.min()) {
00284         l->mark(); l=l->val_next; p->val_next=l;
00285       } else if (l->val > v.max()) {
00286         ++v;
00287       } else {
00288         p=l; l=l->val_next;
00289       }
00290     }
00291     p->val_next = NULL;
00292     while (l != NULL) { l->mark(); l=l->val_next; }
00293   }
00294 
00295   template <class ViewA, class ViewB>
00296   forceinline ExecStatus
00297   IdxValMap::tell(Space* home, ViewA x0, ViewB x1) {
00298     IterIdx i(iv[0]);
00299     GECODE_ME_CHECK(x0.narrow_v(home,i,false));
00300     IterVal v(iv[0]);
00301     if (shared(x0,x1)) {
00302       GECODE_ME_CHECK(x1.inter_v(home,v,false));
00303       return ES_NOFIX;
00304     } else {
00305       GECODE_ME_CHECK(x1.narrow_v(home,v,false));
00306       return ES_FIX;
00307     }
00308   }
00309 
00310   forceinline void
00311   IdxValMap::operator delete(void* p,size_t) {
00312     Memory::free(p);
00313   }
00314 
00315 
00316 
00317 
00318   /*
00319    * Element propagator proper
00320    *
00321    */
00322 
00323 
00324   template <class ViewA, class ViewB>
00325   forceinline
00326   Int<ViewA,ViewB>::Int(Space* home, IntSharedArray& c0, ViewA y0, ViewB y1)
00327     : Propagator(home), x0(y0), x1(y1), c(c0), ivm(NULL) {
00328     force(home);
00329     x0.subscribe(home,this,PC_INT_DOM);
00330     x1.subscribe(home,this,PC_INT_DOM);
00331   }
00332 
00333   template <class ViewA, class ViewB>
00334   forceinline size_t
00335   Int<ViewA,ViewB>::dispose(Space* home) {
00336     unforce(home);
00337     if (!home->failed()) {
00338       x0.cancel(home,this,PC_INT_DOM);
00339       x1.cancel(home,this,PC_INT_DOM);
00340     }
00341     c.~IntSharedArray();
00342     delete ivm;
00343     (void) Propagator::dispose(home);
00344     return sizeof(*this);
00345   }
00346 
00347   template <class ViewA, class ViewB>
00348   ExecStatus
00349   Int<ViewA,ViewB>::post(Space* home, IntSharedArray& c, ViewA x0, ViewB x1) {
00350     GECODE_ME_CHECK(x0.gq(home,0));
00351     GECODE_ME_CHECK(x0.le(home,c.size()));
00352     if (x0.assigned()) {
00353       GECODE_ME_CHECK(x1.eq(home,c[x0.val()]));
00354     } else {
00355       (void) new (home) Int<ViewA,ViewB>(home,c,x0,x1);
00356     }
00357     return ES_OK;
00358   }
00359 
00360 
00361   template <class ViewA, class ViewB>
00362   size_t
00363   Int<ViewA,ViewB>::allocated(void) const {
00364     return (ivm != NULL) ? ivm->size() : 0;
00365   }
00366 
00367   template <class ViewA, class ViewB>
00368   forceinline
00369   Int<ViewA,ViewB>::Int(Space* home, bool share, Int& p)
00370     : Propagator(home,share,p), ivm(NULL) {
00371     c.update(home,share,p.c);
00372     x0.update(home,share,p.x0);
00373     x1.update(home,share,p.x1);
00374   }
00375 
00376   template <class ViewA, class ViewB>
00377   Actor*
00378   Int<ViewA,ViewB>::copy(Space* home, bool share) {
00379     return new (home) Int<ViewA,ViewB>(home,share,*this);
00380   }
00381 
00382   template <class ViewA, class ViewB>
00383   PropCost
00384   Int<ViewA,ViewB>::cost(ModEventDelta) const {
00385     return PC_BINARY_HI;
00386   }
00387 
00388   template <class ViewA, class ViewB>
00389   inline Support::Symbol
00390   Int<ViewA,ViewB>::ati(void) {
00391     return Reflection::mangle<ViewA,ViewB>("Gecode::Int::Element::Int");
00392   }
00393 
00394   template <class ViewA, class ViewB>
00395   Reflection::ActorSpec
00396   Int<ViewA,ViewB>::spec(const Space* home, Reflection::VarMap& m) const {
00397     Reflection::ActorSpec s(ati());
00398     return s << x0.spec(home, m)
00399              << x1.spec(home, m)
00400              << Reflection::Arg::newIntArray(c);
00401   }
00402 
00403   template <class ViewA, class ViewB>
00404   void
00405   Int<ViewA,ViewB>::post(Space* home, Reflection::VarMap& vars,
00406                          const Reflection::ActorSpec& spec) {
00407     spec.checkArity(3);
00408     ViewA x0(home, vars, spec[0]);
00409     ViewB x1(home, vars, spec[1]);
00410     Reflection::IntArrayArg* a = spec[2]->toIntArray();
00411     IntSharedArray is(a->size());
00412     for (int i=a->size(); i--; ) {
00413       is[i] = (*a)[i];
00414     }
00415     (void) new (home) Int<ViewA,ViewB>(home, is, x0, x1);
00416   }
00417 
00418   template <class ViewA, class ViewB>
00419   ExecStatus
00420   Int<ViewA,ViewB>::propagate(Space* home, ModEventDelta) {
00421     bool assigned = x0.assigned() && x1.assigned();
00422     if (ivm == NULL) {
00423       ivm = IdxValMap::allocate(x0.size());
00424       ivm->init(&c[0],x0);
00425     } else {
00426       ivm->prune_idx(x0);
00427     }
00428     ivm->prune_val(x1);
00429 
00430     ExecStatus es = ivm->tell(home,x0,x1);
00431     if (es == ES_FAILED)
00432       return es;
00433     if (es == ES_NOFIX)
00434       return assigned ? ES_SUBSUMED(this,home) : ES_NOFIX;
00435 
00436     return (x0.assigned() || x1.assigned()) ? 
00437       ES_SUBSUMED(this,home) : es;
00438   }
00439 
00440 }}}
00441 
00442 
00443 // STATISTICS: int-prop
00444