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

bnd.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Christian Schulte, 2003
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-10-23 16:16:09 +0200 (Mon, 23 Oct 2006) $ by $Author: schulte $
00010  *     $Revision: 3768 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
00019  *
00020  */
00021 
00022 #include "gecode/support/sort.hh"
00023 
00024 namespace Gecode { namespace Int { namespace Distinct {
00025 
00026   template <class View>
00027   inline
00028   Bnd<View>::Bnd(Space* home, ViewArray<View>& x0)
00029     : Propagator(home), x(x0), y(home,x0) {
00030     // Both x and y initially contain the same variables
00031     //  - x is used for bounds propagation
00032     //  - y is used for performing singleton propagation
00033     // They can not be shared as singleton propagation removes
00034     // determined variables still required for bounds propagation.
00035     y.subscribe(home,this,PC_INT_BND);
00036   }
00037 
00038   template <class View>
00039   size_t
00040   Bnd<View>::dispose(Space* home) {
00041     assert(!home->failed());
00042     y.cancel(home,this,PC_INT_BND);
00043     (void) Propagator::dispose(home);
00044     return sizeof(*this);
00045   }
00046 
00047   template <class View>
00048   forceinline
00049   Bnd<View>::Bnd(Space* home, bool share, Bnd<View>& p)
00050     : Propagator(home,share,p) {
00051       x.update(home,share,p.x);
00052       y.update(home,share,p.y);
00053   }
00054 
00055   template <class View>
00056   Actor*
00057   Bnd<View>::copy(Space* home, bool share) {
00058     return new (home) Bnd<View>(home,share,*this);
00059   }
00060 
00061   template <class View>
00062   PropCost
00063   Bnd<View>::cost(void) const {
00064     return (View::pme(this) == ME_INT_VAL)
00065       ? cost_lo(y.size(),PC_LINEAR_LO)
00066       : cost_hi(x.size(),PC_LINEAR_HI);
00067   }
00068 
00069 
00071   class Rank {
00072   public:
00073     int min, max;
00074   };
00075 
00077   template <class View>
00078   class MaxInc {
00079   protected:
00080     ViewArray<View> x;
00081   public:
00082     MaxInc(const ViewArray<View>& x0) : x(x0) {}
00083     forceinline bool
00084     operator()(const int i, const int j) {
00085       return x[i].max() < x[j].max();
00086     }
00087   };
00088 
00090   template <class View>
00091   class MinInc {
00092   public:
00093     forceinline bool
00094     operator()(const View& x, const View& y) {
00095       return x.min() < y.min();
00096     }
00097   };
00098 
00100   class HallInfo {
00101   public:
00102     int bounds, t, d, h;
00103   };
00104 
00105   inline void
00106   pathset_t(HallInfo hall[], int start, int end, int to) {
00107     int k, l;
00108     for (l=start; (k=l) != end; hall[k].t=to) {
00109       l = hall[k].t;
00110     }
00111   }
00112 
00113   inline void
00114   pathset_h(HallInfo hall[], int start, int end, int to) {
00115     int k, l;
00116     for (l=start; (k=l) != end; hall[k].h=to) {
00117       l = hall[k].h;
00118     }
00119   }
00120 
00121   forceinline int
00122   pathmin_h(const HallInfo hall[], int i) {
00123     while (hall[i].h < i)
00124       i = hall[i].h;
00125     return i;
00126   }
00127 
00128   forceinline int
00129   pathmin_t(const HallInfo hall[], int i) {
00130     while (hall[i].t < i)
00131       i = hall[i].t;
00132     return i;
00133   }
00134 
00135   forceinline int
00136   pathmax_h(const HallInfo hall[], int i) {
00137     while (hall[i].h > i)
00138       i = hall[i].h;
00139     return i;
00140   }
00141 
00142   forceinline int
00143   pathmax_t(const HallInfo hall[], int i) {
00144     while (hall[i].t > i)
00145       i = hall[i].t;
00146     return i;
00147   }
00148 
00149 #define GECODE_INT_MINSORTED(i) (i)
00150 #define GECODE_INT_MAXSORTED(i) (_maxsorted[i])
00151 
00152   template <class View>
00153   ExecStatus
00154   prop_bnd(Space* home, ViewArray<View>& x, int m) {
00155     const int n = x.size();
00156     // Sort variable array for minimum directly
00157     {
00158       MinInc<View> min_inc;
00159       Support::insertion<View,MinInc<View> >(&x[0], n, min_inc);
00160     }
00161 
00162     GECODE_AUTOARRAY(int, _maxsorted, n);
00163     for (int i = n; i--; )
00164       _maxsorted[i]=i;
00165 
00166     {
00167       MaxInc<View> max_inc(x);
00168       Support::insertion<int,MaxInc<View> >(_maxsorted, n, max_inc);
00169     }
00170 
00171     // Setup rank and bounds info
00172     GECODE_AUTOARRAY(HallInfo, hall, 2*n+2);
00173     GECODE_AUTOARRAY(Rank,     rank, n);
00174 
00175     int nb = 0;
00176     {
00177       int min  = x[GECODE_INT_MINSORTED(0)].min();
00178       int max  = x[GECODE_INT_MAXSORTED(0)].max() + 1;
00179       int last = min - 2;
00180 
00181       hall[0].bounds = last;
00182 
00183       int i = 0;
00184       int j = 0;
00185       while (true) {
00186         if (i < n && min < max) {
00187           if (min != last)
00188             hall[++nb].bounds = last = min;
00189           rank[GECODE_INT_MINSORTED(i)].min = nb;
00190           if (++i < n)
00191             min = x[GECODE_INT_MINSORTED(i)].min();
00192         } else {
00193           if (max != last)
00194             hall[++nb].bounds = last = max;
00195           rank[GECODE_INT_MAXSORTED(j)].max = nb;
00196           if (++j == n)
00197             break;
00198           max = x[GECODE_INT_MAXSORTED(j)].max() + 1;
00199         }
00200       }
00201       hall[nb+1].bounds = hall[nb].bounds + 2;
00202     }
00203 
00204     // If tells cross holes, we do not compute a fixpoint
00205     ExecStatus es = ES_FIX;
00206 
00207     // Propagate lower bounds
00208     for (int i=nb+2; --i;) {
00209       hall[i].t = hall[i].h = i-1;
00210       hall[i].d = hall[i].bounds - hall[i-1].bounds;
00211     }
00212     for (int i=0; i<n; i++) { // visit intervals in increasing max order
00213       int x0 = rank[GECODE_INT_MAXSORTED(i)].min;
00214       int z = pathmax_t(hall, x0+1);
00215       int j = hall[z].t;
00216       if (--hall[z].d == 0)
00217         hall[z = pathmax_t(hall, hall[z].t=z+1)].t = j;
00218       pathset_t(hall, x0+1, z, z); // path compression
00219       int y = rank[GECODE_INT_MAXSORTED(i)].max;
00220       if (hall[z].d < hall[z].bounds-hall[y].bounds)
00221         return ES_FAILED;
00222       if (hall[x0].h > x0) {
00223         int w = pathmax_h(hall, hall[x0].h);
00224         int m = hall[w].bounds;
00225         ModEvent me = x[GECODE_INT_MAXSORTED(i)].gq(home,m);
00226         if (me_failed(me))
00227           return ES_FAILED;
00228         if ((me == ME_INT_VAL) || 
00229             ((me == ME_INT_BND) && (m != x[GECODE_INT_MAXSORTED(i)].min())))
00230           es = ES_NOFIX;
00231         pathset_h(hall, x0, w, w); // path compression
00232       }
00233       if (hall[z].d == hall[z].bounds-hall[y].bounds) {
00234         pathset_h(hall, hall[y].h, j-1, y); // mark hall interval
00235         hall[y].h = j-1;
00236       }
00237     }
00238 
00239     // Propagate upper bounds
00240     for (int i=nb+1; i--;) {
00241       hall[i].t = hall[i].h = i+1;
00242       hall[i].d = hall[i+1].bounds - hall[i].bounds;
00243     }
00244     for (int i=n; --i>=0; ) { // visit intervals in decreasing min order
00245       int x0 = rank[GECODE_INT_MINSORTED(i)].max;
00246       int z = pathmin_t(hall, x0-1);
00247       int j = hall[z].t;
00248       if (--hall[z].d == 0)
00249         hall[z = pathmin_t(hall, hall[z].t=z-1)].t = j;
00250       pathset_t(hall, x0-1, z, z);
00251       int y = rank[GECODE_INT_MINSORTED(i)].min;
00252       if (hall[z].d < hall[y].bounds-hall[z].bounds)
00253         return ES_FAILED;
00254       if (hall[x0].h < x0) {
00255         int w = pathmin_h(hall, hall[x0].h);
00256         int m = hall[w].bounds - 1;
00257         ModEvent me = x[GECODE_INT_MINSORTED(i)].lq(home,m);
00258         if (me_failed(me))
00259           return ES_FAILED;
00260         if ((me == ME_INT_VAL) || 
00261             ((me == ME_INT_BND) && (m != x[GECODE_INT_MAXSORTED(i)].min())))
00262           es = ES_NOFIX;
00263         pathset_h(hall, x0, w, w);
00264       }
00265       if (hall[z].d == hall[y].bounds-hall[z].bounds) {
00266         pathset_h(hall, hall[y].h, j+1, y);
00267         hall[y].h = j+1;
00268       }
00269     }
00270 
00271     if ((n > 2*m) && (n > 6)) {
00272       // If there are many assigned views, try to eliminate them
00273       MinInc<View> min_inc;
00274       Support::insertion<View,MinInc<View> >(&x[0], n, min_inc);
00275       int i   = 0;
00276       int j   = 0;
00277       int max = x[0].max()-1;
00278       while (i < n-1) {
00279         if (!x[i].assigned() ||
00280             (x[i].val() <= max) || (x[i].val() > x[i+1].min())) {
00281           // Keep view x[i]
00282           max = std::max(max,x[i].max());
00283           x[j++]=x[i];
00284         }
00285         i++;
00286       }
00287       if (!x[i].assigned() || (x[i].val() <= max))
00288         x[j++]=x[i];
00289       x.size(j);
00290       if (j < 2)
00291         return ES_SUBSUMED;
00292     }
00293 
00294     return es;
00295   }
00296 
00297 #undef GECODE_INT_MINSORTED
00298 #undef GECODE_INT_MAXSORTED
00299 
00300   template <class View>
00301   ExecStatus
00302   Bnd<View>::propagate(Space* home) {
00303     assert(x.size() > 1);
00304 
00305     if (View::pme(this) == ME_INT_VAL) {
00306       ExecStatus es = prop_val<View,false>(home,y);
00307       if ((es == ES_FAILED) || (es == ES_SUBSUMED))
00308         return es;
00309       if (es == ES_FIX)
00310         return ES_FIX_PARTIAL(View::pme(ME_INT_BND));
00311     }
00312 
00313     if (y.size() == 2) {
00314       GECODE_ES_CHECK(Rel::Nq<View>::post(home,y[0],y[1]));
00315       return ES_SUBSUMED;
00316     }
00317 
00318     return prop_bnd<View>(home,x,y.size());
00319   }
00320 
00321   template <class View>
00322   ExecStatus
00323   Bnd<View>::post(Space* home, ViewArray<View>& x){
00324     if (x.size() == 2)
00325       return Rel::Nq<View>::post(home,x[0],x[1]);
00326     if (x.size() > 2)
00327       (void) new (home) Bnd<View>(home,x);
00328     return ES_OK;
00329   }
00330 
00331 
00332 }}}
00333 
00334 // STATISTICS: int-prop
00335