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

dom.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Contributing authors:
00006  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00007  *
00008  *  Copyright:
00009  *     Christian Schulte, 2006
00010  *     Mikael Lagerkvist, 2006
00011  *
00012  *  Last modified:
00013  *     $Date: 2006-08-04 16:03:26 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00014  *     $Revision: 3512 $
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 #include "gecode/iter.hh"
00027 
00028 namespace Gecode { namespace Int { namespace Channel {
00029 
00034   template <class View>
00035   class DomInfo {
00036   public:
00037     View         view;
00038     unsigned int card;
00039     int          min;
00040     int          max;
00042     static DomInfo<View>* allocate(Space* home, int n);
00044     void init(View x, int n);
00046     void update(Space* home, bool share, DomInfo<View>& vcb);
00048     bool doval(void) const;
00050     bool dodom(void) const;
00052     void assigned(void);
00054     void removed(int i);
00056     void done(void);
00057   };
00058 
00059   template <class View>
00060   forceinline DomInfo<View>*
00061   DomInfo<View>::allocate(Space* home, int n) {
00062     return reinterpret_cast<DomInfo<View>*>
00063       (home->alloc(n*sizeof(DomInfo<View>)));
00064   }
00065 
00066   template <class View>
00067   forceinline void
00068   DomInfo<View>::init(View x, int n) {
00069     view = x;
00070     card = static_cast<unsigned int>(n);
00071     min  = 0;
00072     max  = n-1;
00073   }
00074 
00075   template <class View>
00076   forceinline void
00077   DomInfo<View>::update(Space* home, bool share, DomInfo<View>& di) {
00078     view.update(home,share,di.view);
00079     card = di.card;
00080     min  = di.min;
00081     max  = di.max;
00082   }
00083 
00084   template <class View>
00085   forceinline bool
00086   DomInfo<View>::doval(void) const {
00087     return (card != 1) && view.assigned();
00088   }
00089 
00090   template <class View>
00091   forceinline bool
00092   DomInfo<View>::dodom(void) const {
00093     return card != view.size();
00094   }
00095 
00096   template <class View>
00097   forceinline void
00098   DomInfo<View>::assigned(void) {
00099     card = 1;
00100   }
00101 
00102   template <class View>
00103   forceinline void
00104   DomInfo<View>::removed(int i) {
00105     card--;
00106     if (i == min)
00107       min++;
00108     else if (i == max)
00109       max--;
00110   }
00111 
00112   template <class View>
00113   forceinline void
00114   DomInfo<View>::done(void) {
00115     card = view.size();
00116     min  = view.min();
00117     max  = view.max();
00118   }
00119 
00120   // Propagate domain information from x to y
00121   template <class View>
00122   ExecStatus
00123   prop_dom(Space* home, int n, DomInfo<View>* x, DomInfo<View>* y,
00124            ProcessStack& ya) {
00125     for (int i = n; i--; )
00126       // Only views with not yet propagated missing values
00127       if (x[i].dodom()) {
00128         // Iterate the values in the complement of x[i]
00129         ViewRanges<IntView>
00130           xir(x[i].view);
00131         Iter::Ranges::ComplVal<ViewRanges<IntView> >
00132           xirc(x[i].min,x[i].max,xir);
00133         Iter::Ranges::ToValues<Iter::Ranges::ComplVal<ViewRanges<IntView> > >
00134           jv(xirc);
00135         while (jv()) {
00136           // j is not in the domain of x[i], so prune i from y[j]
00137           int j = jv.val();
00138           ModEvent me = y[j].view.nq(home,i);
00139           if (me_failed(me))
00140             return ES_FAILED;
00141           if (me_modified(me))
00142             if (me == ME_INT_VAL) {
00143               // Record that y[j] has been assigned and must be propagated
00144               ya.push(j);
00145             } else {
00146               // Obvious as x[i] is different from j
00147               y[j].removed(i);
00148             }
00149           ++jv;
00150         }
00151         // Update which values have been propagated and what are the new bounds
00152         x[i].done();
00153       }
00154     return ES_OK;
00155   }
00156 
00157   /*
00158    * The actual propagator
00159    *
00160    */
00161   template <class View>
00162   forceinline
00163   Dom<View>::Dom(Space* home, int n, DomInfo<View>* xy)
00164     : Base<DomInfo<View>,PC_INT_DOM>(home,n,xy,true) {}
00165 
00166   template <class View>
00167   forceinline
00168   Dom<View>::Dom(Space* home, bool share, Dom<View>& p)
00169     : Base<DomInfo<View>,PC_INT_DOM>(home,share,p) {}
00170 
00171   template <class View>
00172   Actor*
00173   Dom<View>::copy(Space* home, bool share) {
00174     return new (home) Dom<View>(home,share,*this);
00175   }
00176 
00177   template <class View>
00178   PropCost
00179   Dom<View>::cost(void) const {
00180     return (View::pme(this) == ME_INT_VAL) ? PC_QUADRATIC_LO : PC_CUBIC_HI;
00181   }
00182 
00183   template <class View>
00184   ExecStatus
00185   Dom<View>::propagate(Space* home) {
00186     GECODE_AUTOARRAY(int, __xa, n+1);
00187     GECODE_AUTOARRAY(int, __ya, n+1);
00188     ProcessStack xa(__xa);
00189     ProcessStack ya(__ya);
00190 
00191     DomInfo<View>* x = xy;
00192     DomInfo<View>* y = xy+n;
00193 
00194     if (View::pme(this) == ME_INT_VAL) {
00195       // Scan x and y for assigned but not yet propagated views
00196       for (int i = n; i--; ) {
00197         if (x[i].doval()) xa.push(i);
00198         if (y[i].doval()) ya.push(i);
00199       }
00200 
00201       do {
00202         // Propagate assigned views for x
00203         if (prop_val<View,DomInfo<View> >(home,n,x,y,n_na,xa,ya) == ES_FAILED)
00204           return ES_FAILED;
00205         // Propagate assigned views for y
00206         if (prop_val<View,DomInfo<View> >(home,n,y,x,n_na,ya,xa) == ES_FAILED)
00207           return ES_FAILED;
00208         assert(ya.empty());
00209       } while (!xa.empty());
00210       this->ES_FIX_PARTIAL(View::pme(ME_INT_DOM));
00211     }
00212 
00213     // Process changed views for y
00214     // This propagates from y to x and possibly records xs that
00215     // got assigned
00216     if (prop_dom(home,n,y,x,xa) == ES_FAILED)
00217       return ES_FAILED;
00218 
00219     // Process assigned views for x
00220     if (prop_val<View,DomInfo<View> >(home,n,x,y,n_na,xa,ya) == ES_FAILED)
00221       return ES_FAILED;
00222 
00223     // Perform domain consistent propagation for distinct on the x views
00224     if (dc.available()) {
00225       GECODE_ES_CHECK(dc.sync());
00226     } else {
00227       GECODE_AUTOARRAY(View,xv,n);
00228       for (int i=n; i--; )
00229         xv[i] = x[i].view;
00230       GECODE_ES_CHECK(dc.init(n,&xv[0]));
00231     }
00232     dc.propagate(home);
00233     // This might assign some more views in x which goes unnoticed
00234     // (that is, not recorded in xa). This must be checked and propagated
00235     // to the y views, however the distinctness on x is already
00236     // propagated.
00237     for (int i=n; i--; )
00238       if (x[i].doval()) {
00239         int j = x[i].view.val();
00240         // Assign the y variable to i (or test if already assigned!)
00241         ModEvent me = y[j].view.eq(home,i);
00242         if (me_failed(me))
00243           return ES_FAILED;
00244         if (me_modified(me)) {
00245           // Record that y[j] has been assigned and must be propagated
00246           assert(me == ME_INT_VAL);
00247           // Otherwise the modification event would not be ME_INT_VAL
00248           ya.push(j);
00249         }
00250         x[i].assigned(); n_na--;
00251       }
00252 
00253     // Process changed views for x
00254     // This propagates from x to y and possibly records ys that
00255     // got assigned
00256     if (prop_dom(home,n,x,y,ya) == ES_FAILED)
00257       return ES_FAILED;
00258 
00259     // Process assigned view again (some might have been found above)
00260     while (!xa.empty() || !ya.empty()) {
00261       // Process assigned views for x
00262       if (prop_val<View,DomInfo<View> >(home,n,x,y,n_na,xa,ya) == ES_FAILED)
00263         return ES_FAILED;
00264       // Process assigned views for y
00265       if (prop_val<View,DomInfo<View> >(home,n,y,x,n_na,ya,xa) == ES_FAILED)
00266         return ES_FAILED;
00267     };
00268 
00269     return (n_na == 0) ? ES_SUBSUMED : ES_FIX;
00270   }
00271 
00272   template <class View>
00273   ExecStatus
00274   Dom<View>::post(Space* home, int n, DomInfo<View>* xy) {
00275     assert(n > 0);
00276     if (n == 1) {
00277       GECODE_ME_CHECK(xy[0].view.eq(home,0));
00278       GECODE_ME_CHECK(xy[1].view.eq(home,0));
00279       return ES_OK;
00280     }
00281     for (int i=2*n; i--; ) {
00282       GECODE_ME_CHECK(xy[i].view.gq(home,0));
00283       GECODE_ME_CHECK(xy[i].view.le(home,n));
00284     }
00285     (void) new (home) Dom<View>(home,n,xy);
00286     return ES_OK;
00287   }
00288 
00289   template <class View>
00290   void
00291   Dom<View>::flush(void) {
00292     dc.flush();
00293   }
00294 
00295   template <class View>
00296   size_t
00297   Dom<View>::size(void) const {
00298     return dc.size();
00299   }
00300 
00301   template <class View>
00302   size_t
00303   Dom<View>::dispose(Space* home) {
00304     dc.dispose();
00305     (void) Base<DomInfo<View>,PC_INT_DOM>::dispose(home);
00306     return sizeof(*this);
00307   }
00308 
00309 
00310 }}}
00311 
00312 // STATISTICS: int-prop
00313