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

bnd.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, 2003
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-01-31 18:29:16 +0100 (Thu, 31 Jan 2008) $ by $Author: tack $
00011  *     $Revision: 6017 $
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 Distinct {
00039 
00040   template <class View>
00041   forceinline
00042   Bnd<View>::Bnd(Space* home, ViewArray<View>& x0)
00043     : Propagator(home), x(x0), y(home,x0) {
00044     // Both x and y initially contain the same variables
00045     //  - x is used for bounds propagation
00046     //  - y is used for performing singleton propagation
00047     // They can not be shared as singleton propagation removes
00048     // determined variables still required for bounds propagation.
00049     y.subscribe(home,this,PC_INT_BND);
00050   }
00051 
00052   template <class View>
00053   forceinline size_t
00054   Bnd<View>::dispose(Space* home) {
00055     y.cancel(home,this,PC_INT_BND);
00056     (void) Propagator::dispose(home);
00057     return sizeof(*this);
00058   }
00059 
00060   template <class View>
00061   forceinline
00062   Bnd<View>::Bnd(Space* home, bool share, Bnd<View>& p)
00063     : Propagator(home,share,p) {
00064       x.update(home,share,p.x);
00065       y.update(home,share,p.y);
00066   }
00067 
00068   template <class View>
00069   Actor*
00070   Bnd<View>::copy(Space* home, bool share) {
00071     return new (home) Bnd<View>(home,share,*this);
00072   }
00073 
00074   template <class View>
00075   PropCost
00076   Bnd<View>::cost(ModEventDelta med) const {
00077     return (View::me(med) == ME_INT_VAL)
00078       ? cost_lo(y.size(),PC_LINEAR_LO)
00079       : cost_hi(x.size(),PC_LINEAR_HI);
00080   }
00081 
00082   template <class View>
00083   Support::Symbol
00084   Bnd<View>::ati(void) {
00085     return Reflection::mangle<View>("Gecode::Int::Distinct::Bnd");
00086   }
00087 
00088   template <class View>
00089   Reflection::ActorSpec
00090   Bnd<View>::spec(const Space* home, Reflection::VarMap& m) const {
00091     Reflection::ActorSpec s(ati());
00092     return s << x.spec(home, m);
00093   }
00094 
00095 
00097   class Rank {
00098   public:
00099     int min, max;
00100   };
00101 
00103   template <class View>
00104   class MaxInc {
00105   protected:
00106     ViewArray<View> x;
00107   public:
00108     MaxInc(const ViewArray<View>& x0) : x(x0) {}
00109     forceinline bool
00110     operator()(const int i, const int j) {
00111       return x[i].max() < x[j].max();
00112     }
00113   };
00114 
00116   template <class View>
00117   class MinInc {
00118   public:
00119     forceinline bool
00120     operator()(const View& x, const View& y) {
00121       return x.min() < y.min();
00122     }
00123   };
00124 
00126   class HallInfo {
00127   public:
00128     int bounds, t, d, h;
00129   };
00130 
00131   forceinline void
00132   pathset_t(HallInfo hall[], int start, int end, int to) {
00133     int k, l;
00134     for (l=start; (k=l) != end; hall[k].t=to) {
00135       l = hall[k].t;
00136     }
00137   }
00138 
00139   forceinline void
00140   pathset_h(HallInfo hall[], int start, int end, int to) {
00141     int k, l;
00142     for (l=start; (k=l) != end; hall[k].h=to) {
00143       l = hall[k].h;
00144     }
00145   }
00146 
00147   forceinline int
00148   pathmin_h(const HallInfo hall[], int i) {
00149     while (hall[i].h < i)
00150       i = hall[i].h;
00151     return i;
00152   }
00153 
00154   forceinline int
00155   pathmin_t(const HallInfo hall[], int i) {
00156     while (hall[i].t < i)
00157       i = hall[i].t;
00158     return i;
00159   }
00160 
00161   forceinline int
00162   pathmax_h(const HallInfo hall[], int i) {
00163     while (hall[i].h > i)
00164       i = hall[i].h;
00165     return i;
00166   }
00167 
00168   forceinline int
00169   pathmax_t(const HallInfo hall[], int i) {
00170     while (hall[i].t > i)
00171       i = hall[i].t;
00172     return i;
00173   }
00174 
00175 #define GECODE_INT_MINSORTED(i) (i)
00176 #define GECODE_INT_MAXSORTED(i) (_maxsorted[i])
00177 
00178   template <class View>
00179   ExecStatus
00180   prop_bnd(Space* home, ViewArray<View>& x) {
00181     const int n = x.size();
00182     // Sort variable array for minimum directly
00183     {
00184       MinInc<View> min_inc;
00185       Support::insertion<View,MinInc<View> >(&x[0], n, min_inc);
00186     }
00187 
00188     GECODE_AUTOARRAY(int, _maxsorted, n);
00189     for (int i = n; i--; )
00190       _maxsorted[i]=i;
00191 
00192     {
00193       MaxInc<View> max_inc(x);
00194       Support::insertion<int,MaxInc<View> >(_maxsorted, n, max_inc);
00195     }
00196 
00197     // Setup rank and bounds info
00198     GECODE_AUTOARRAY(HallInfo, hall, 2*n+2);
00199     GECODE_AUTOARRAY(Rank,     rank, n);
00200 
00201     int nb = 0;
00202     {
00203       int min  = x[GECODE_INT_MINSORTED(0)].min();
00204       int max  = x[GECODE_INT_MAXSORTED(0)].max() + 1;
00205       int last = min - 2;
00206 
00207       hall[0].bounds = last;
00208 
00209       int i = 0;
00210       int j = 0;
00211       while (true) {
00212         if ((i < n) && (min < max)) {
00213           if (min != last)
00214             hall[++nb].bounds = last = min;
00215           rank[GECODE_INT_MINSORTED(i)].min = nb;
00216           if (++i < n)
00217             min = x[GECODE_INT_MINSORTED(i)].min();
00218         } else {
00219           if (max != last)
00220             hall[++nb].bounds = last = max;
00221           rank[GECODE_INT_MAXSORTED(j)].max = nb;
00222           if (++j == n)
00223             break;
00224           max = x[GECODE_INT_MAXSORTED(j)].max() + 1;
00225         }
00226       }
00227       hall[nb+1].bounds = hall[nb].bounds + 2;
00228     }
00229 
00230     // If tells cross holes, we do not compute a fixpoint
00231     ExecStatus es = ES_FIX;
00232 
00233     // Propagate lower bounds
00234     for (int i=nb+2; --i;) {
00235       hall[i].t = hall[i].h = i-1;
00236       hall[i].d = hall[i].bounds - hall[i-1].bounds;
00237     }
00238     for (int i=0; i<n; i++) { // visit intervals in increasing max order
00239       int x0 = rank[GECODE_INT_MAXSORTED(i)].min;
00240       int z = pathmax_t(hall, x0+1);
00241       int j = hall[z].t;
00242       if (--hall[z].d == 0)
00243         hall[z = pathmax_t(hall, hall[z].t=z+1)].t = j;
00244       pathset_t(hall, x0+1, z, z); // path compression
00245       int y = rank[GECODE_INT_MAXSORTED(i)].max;
00246       if (hall[z].d < hall[z].bounds-hall[y].bounds)
00247         return ES_FAILED;
00248       if (hall[x0].h > x0) {
00249         int w = pathmax_h(hall, hall[x0].h);
00250         int m = hall[w].bounds;
00251         ModEvent me = x[GECODE_INT_MAXSORTED(i)].gq(home,m);
00252         if (me_failed(me))
00253           return ES_FAILED;
00254         if ((me == ME_INT_VAL) || 
00255             ((me == ME_INT_BND) && (m != x[GECODE_INT_MAXSORTED(i)].min())))
00256           es = ES_NOFIX;
00257         pathset_h(hall, x0, w, w); // path compression
00258       }
00259       if (hall[z].d == hall[z].bounds-hall[y].bounds) {
00260         pathset_h(hall, hall[y].h, j-1, y); // mark hall interval
00261         hall[y].h = j-1;
00262       }
00263     }
00264 
00265     // Propagate upper bounds
00266     for (int i=nb+1; i--;) {
00267       hall[i].t = hall[i].h = i+1;
00268       hall[i].d = hall[i+1].bounds - hall[i].bounds;
00269     }
00270     for (int i=n; --i>=0; ) { // visit intervals in decreasing min order
00271       int x0 = rank[GECODE_INT_MINSORTED(i)].max;
00272       int z = pathmin_t(hall, x0-1);
00273       int j = hall[z].t;
00274       if (--hall[z].d == 0)
00275         hall[z = pathmin_t(hall, hall[z].t=z-1)].t = j;
00276       pathset_t(hall, x0-1, z, z);
00277       int y = rank[GECODE_INT_MINSORTED(i)].min;
00278       if (hall[z].d < hall[y].bounds-hall[z].bounds)
00279         return ES_FAILED;
00280       if (hall[x0].h < x0) {
00281         int w = pathmin_h(hall, hall[x0].h);
00282         int m = hall[w].bounds - 1;
00283         ModEvent me = x[GECODE_INT_MINSORTED(i)].lq(home,m);
00284         if (me_failed(me))
00285           return ES_FAILED;
00286         if ((me == ME_INT_VAL) || 
00287             ((me == ME_INT_BND) && (m != x[GECODE_INT_MAXSORTED(i)].min())))
00288           es = ES_NOFIX;
00289         pathset_h(hall, x0, w, w);
00290       }
00291       if (hall[z].d == hall[y].bounds-hall[z].bounds) {
00292         pathset_h(hall, hall[y].h, j+1, y);
00293         hall[y].h = j+1;
00294       }
00295     }
00296 
00297     return es;
00298   }
00299 
00300 #undef GECODE_INT_MINSORTED
00301 #undef GECODE_INT_MAXSORTED
00302 
00303   template <class View>
00304   ExecStatus
00305   Bnd<View>::propagate(Space* home, ModEventDelta med) {
00306     assert(x.size() > 1);
00307 
00308     if (View::me(med) == ME_INT_VAL) {
00309       ExecStatus es = prop_val<View,false>(home,y);
00310       GECODE_ES_CHECK(es);
00311       if (y.size() < 2)
00312         return ES_SUBSUMED(this,home);
00313       if (es == ES_FIX)
00314         return ES_FIX_PARTIAL(this,View::med(ME_INT_BND));
00315     }
00316 
00317     if (y.size() == 2)
00318       GECODE_REWRITE(this,Rel::Nq<View>::post(home,y[0],y[1]));
00319 
00320     ExecStatus es = prop_bnd<View>(home,x);
00321 
00322     GECODE_ES_CHECK(es);
00323 
00324     const int n = x.size();
00325 
00326     if ((n > 2*y.size()) && (n > 6)) {
00327       // If there are many assigned views, try to eliminate them
00328       MinInc<View> min_inc;
00329       Support::insertion<View,MinInc<View> >(&x[0], n, min_inc);
00330       int i   = 0;
00331       int j   = 0;
00332       int max = x[0].max()-1;
00333       while (i < n-1) {
00334         if (!x[i].assigned() ||
00335             (x[i].val() <= max) || (x[i].val() > x[i+1].min())) {
00336           // Keep view x[i]
00337           max = std::max(max,x[i].max());
00338           x[j++]=x[i];
00339         }
00340         i++;
00341       }
00342       if (!x[i].assigned() || (x[i].val() <= max))
00343         x[j++]=x[i];
00344       x.size(j);
00345     }
00346     
00347     if (x.size() < 2)
00348       return ES_SUBSUMED(this,home);
00349 
00350     if (x.size() == 2)
00351       GECODE_REWRITE(this,Rel::Nq<View>::post(home,x[0],x[1]));
00352 
00353     return es;
00354   }
00355 
00356   template <class View>
00357   ExecStatus
00358   Bnd<View>::post(Space* home, ViewArray<View>& x){
00359     if (x.size() == 2)
00360       return Rel::Nq<View>::post(home,x[0],x[1]);
00361     if (x.size() > 2)
00362       (void) new (home) Bnd<View>(home,x);
00363     return ES_OK;
00364   }
00365 
00366   template <class View>
00367   void
00368   Bnd<View>::post(Space* home, Reflection::VarMap& vars,
00369                   const Reflection::ActorSpec& spec) {
00370     spec.checkArity(1);
00371     ViewArray<View> x(home, vars, spec[0]);
00372     (void) new (home) Bnd<View>(home, x);
00373   }
00374 
00375 }}}
00376 
00377 // STATISTICS: int-prop
00378