00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 namespace Gecode { namespace Int { namespace Distinct {
00035
00036 template<class View>
00037 forceinline
00038 Bnd<View>::Bnd(Home home, ViewArray<View>& x0)
00039 : Propagator(home), x(x0), y(home,x0) {
00040
00041
00042
00043
00044
00045 y.subscribe(home,*this,PC_INT_BND);
00046 int min = x[0].min(), max = x[0].max();
00047 for (int i=1; i<x.size(); i++) {
00048 min = std::min(min,x[i].min());
00049 max = std::max(max,x[i].max());
00050 }
00051 min_x = min; max_x = max;
00052 }
00053
00054 template<class View>
00055 forceinline size_t
00056 Bnd<View>::dispose(Space& home) {
00057 y.cancel(home,*this,PC_INT_BND);
00058 (void) Propagator::dispose(home);
00059 return sizeof(*this);
00060 }
00061
00062 template<class View>
00063 forceinline
00064 Bnd<View>::Bnd(Space& home, Bnd<View>& p)
00065 : Propagator(home,p), min_x(p.min_x), max_x(p.max_x) {
00066 x.update(home,p.x);
00067 y.update(home,p.y);
00068 }
00069
00070 template<class View>
00071 Actor*
00072 Bnd<View>::copy(Space& home) {
00073 return new (home) Bnd<View>(home,*this);
00074 }
00075
00076 template<class View>
00077 PropCost
00078 Bnd<View>::cost(const Space&, const ModEventDelta& med) const {
00079 if (View::me(med) == ME_INT_VAL)
00080 return PropCost::linear(PropCost::LO, y.size());
00081 else
00082 return PropCost::quadratic(PropCost::LO, x.size());
00083 }
00084
00085 template<class View>
00086 void
00087 Bnd<View>::reschedule(Space& home) {
00088 y.reschedule(home,*this,PC_INT_BND);
00089 }
00090
00091
00093 class Rank {
00094 public:
00095 int min, max;
00096 };
00097
00099 template<class View>
00100 class MaxIncIdx {
00101 protected:
00102 ViewArray<View> x;
00103 public:
00104 forceinline
00105 MaxIncIdx(const ViewArray<View>& x0) : x(x0) {}
00106 forceinline bool
00107 operator ()(const int i, const int j) {
00108 return x[i].max() < x[j].max();
00109 }
00110 };
00111
00113 template<class View>
00114 class MinIncIdx {
00115 protected:
00116 ViewArray<View> x;
00117 public:
00118 forceinline
00119 MinIncIdx(const ViewArray<View>& x0) : x(x0) {}
00120 forceinline bool
00121 operator ()(const int i, const int j) {
00122 return x[i].min() < x[j].min();
00123 }
00124 };
00125
00127 template<class View>
00128 class MinInc {
00129 public:
00130 forceinline bool
00131 operator ()(const View& x, const View& y) {
00132 return x.min() < y.min();
00133 }
00134 };
00135
00137 template<class IntType>
00138 class HallInfo {
00139 public:
00140 IntType bounds, t, d, h;
00141 };
00142
00143 template<class IntType>
00144 forceinline void
00145 pathset_t(HallInfo<IntType> hall[],
00146 IntType start, IntType end, IntType to) {
00147 IntType k, l;
00148 for (l=start; (k=l) != end; hall[k].t=to) {
00149 l = hall[k].t;
00150 }
00151 }
00152
00153 template<class IntType>
00154 forceinline void
00155 pathset_h(HallInfo<IntType> hall[],
00156 IntType start, IntType end, IntType to) {
00157 IntType k, l;
00158 for (l=start; (k=l) != end; hall[k].h=to) {
00159 l = hall[k].h;
00160 }
00161 }
00162
00163 template<class IntType>
00164 forceinline IntType
00165 pathmin_h(const HallInfo<IntType> hall[], IntType i) {
00166 while (hall[i].h < i)
00167 i = hall[i].h;
00168 return i;
00169 }
00170
00171 template<class IntType>
00172 forceinline IntType
00173 pathmin_t(const HallInfo<IntType> hall[], IntType i) {
00174 while (hall[i].t < i)
00175 i = hall[i].t;
00176 return i;
00177 }
00178
00179 template<class IntType>
00180 forceinline IntType
00181 pathmax_h(const HallInfo<IntType> hall[], IntType i) {
00182 while (hall[i].h > i)
00183 i = hall[i].h;
00184 return i;
00185 }
00186
00187 template<class IntType>
00188 forceinline IntType
00189 pathmax_t(const HallInfo<IntType> hall[], IntType i) {
00190 while (hall[i].t > i)
00191 i = hall[i].t;
00192 return i;
00193 }
00194
00195 template<class View, class IntType>
00196 forceinline ExecStatus
00197 prop_bnd(Space& home, ViewArray<View>& x,
00198 int* minsorted, int* maxsorted) {
00199 const int n = x.size();
00200
00201 Region r;
00202
00203
00204 HallInfo<IntType>* hall = r.alloc<HallInfo<IntType> >(2*n+2);
00205 Rank* rank = r.alloc<Rank>(n);
00206
00207 int nb = 0;
00208 {
00209 IntType min = x[minsorted[0]].min();
00210 IntType max = x[maxsorted[0]].max() + 1;
00211 IntType last = min - 2;
00212
00213 hall[0].bounds = last;
00214
00215 int i = 0;
00216 int j = 0;
00217 while (true) {
00218 if ((i < n) && (min < max)) {
00219 if (min != last)
00220 hall[++nb].bounds = last = min;
00221 rank[minsorted[i]].min = nb;
00222 if (++i < n)
00223 min = x[minsorted[i]].min();
00224 } else {
00225 if (max != last)
00226 hall[++nb].bounds = last = max;
00227 rank[maxsorted[j]].max = nb;
00228 if (++j == n)
00229 break;
00230 max = x[maxsorted[j]].max() + 1;
00231 }
00232 }
00233 hall[nb+1].bounds = hall[nb].bounds + 2;
00234 }
00235
00236
00237 ExecStatus es = ES_FIX;
00238
00239
00240 for (int i=nb+2; --i;) {
00241 hall[i].t = hall[i].h = i-1;
00242 hall[i].d = hall[i].bounds - hall[i-1].bounds;
00243 }
00244 for (int i=0; i<n; i++) {
00245 IntType x0 = rank[maxsorted[i]].min;
00246 IntType z = pathmax_t(hall, x0+1);
00247 IntType j = hall[z].t;
00248 if (--hall[z].d == 0)
00249 hall[z = pathmax_t(hall, hall[z].t=z+1)].t = j;
00250 pathset_t(hall, x0+1, z, z);
00251 IntType y = rank[maxsorted[i]].max;
00252 if (hall[z].d < hall[z].bounds-hall[y].bounds)
00253 return ES_FAILED;
00254 if (hall[x0].h > x0) {
00255 IntType w = pathmax_h(hall, hall[x0].h);
00256 IntType m = hall[w].bounds;
00257 ModEvent me = x[maxsorted[i]].gq(home,m);
00258 if (me_failed(me))
00259 return ES_FAILED;
00260 if ((me == ME_INT_VAL) ||
00261 ((me == ME_INT_BND) && (m != x[maxsorted[i]].min())))
00262 es = ES_NOFIX;
00263 pathset_h(hall, x0, w, w);
00264 }
00265 if (hall[z].d == hall[z].bounds-hall[y].bounds) {
00266 pathset_h(hall, hall[y].h, j-1, y);
00267 hall[y].h = j-1;
00268 }
00269 }
00270
00271
00272 for (int i=nb+1; i--;) {
00273 hall[i].t = hall[i].h = i+1;
00274 hall[i].d = hall[i+1].bounds - hall[i].bounds;
00275 }
00276 for (int i=n; --i>=0; ) {
00277 IntType x0 = rank[minsorted[i]].max;
00278 IntType z = pathmin_t(hall, x0-1);
00279 IntType j = hall[z].t;
00280 if (--hall[z].d == 0)
00281 hall[z = pathmin_t(hall, hall[z].t=z-1)].t = j;
00282 pathset_t(hall, x0-1, z, z);
00283 IntType y = rank[minsorted[i]].min;
00284 if (hall[z].d < hall[y].bounds-hall[z].bounds)
00285 return ES_FAILED;
00286 if (hall[x0].h < x0) {
00287 IntType w = pathmin_h(hall, hall[x0].h);
00288 IntType m = hall[w].bounds - 1;
00289 ModEvent me = x[minsorted[i]].lq(home,m);
00290 if (me_failed(me))
00291 return ES_FAILED;
00292 if ((me == ME_INT_VAL) ||
00293 ((me == ME_INT_BND) && (m != x[maxsorted[i]].min())))
00294 es = ES_NOFIX;
00295 pathset_h(hall, x0, w, w);
00296 }
00297 if (hall[z].d == hall[y].bounds-hall[z].bounds) {
00298 pathset_h(hall, hall[y].h, j+1, y);
00299 hall[y].h = j+1;
00300 }
00301 }
00302
00303 return es;
00304 }
00305
00306 template<class View>
00307 forceinline ExecStatus
00308 prop_bnd(Space& home, ViewArray<View>& x, int& min_x, int& max_x) {
00309
00310 const int n = x.size();
00311
00312 Region r;
00313
00314 int* minsorted = r.alloc<int>(n);
00315 int* maxsorted = r.alloc<int>(n);
00316
00317 unsigned int d = static_cast<unsigned int>(max_x - min_x) + 1;
00318
00319 if (d < static_cast<unsigned int>(n))
00320 return ES_FAILED;
00321
00322 if (d > 2*static_cast<unsigned int>(n)) {
00323 for (int i=0; i<n; i++)
00324 minsorted[i]=maxsorted[i]=i;
00325
00326 MinIncIdx<View> min_inc(x);
00327 Support::quicksort<int,MinIncIdx<View> >(minsorted, n, min_inc);
00328 MaxIncIdx<View> max_inc(x);
00329 Support::quicksort<int,MaxIncIdx<View> >(maxsorted, n, max_inc);
00330 } else {
00331
00332 int* minbucket = r.alloc<int>(d);
00333 int* maxbucket = r.alloc<int>(d);
00334 for (unsigned int i=0; i<d; i++)
00335 minbucket[i]=maxbucket[i]=0;
00336
00337 for (int i=0; i<n; i++) {
00338 minbucket[x[i].min() - min_x]++;
00339 maxbucket[x[i].max() - min_x]++;
00340 }
00341
00342 int c_min = 0, c_max = 0;
00343 for (unsigned int i=0; i<d; i++) {
00344 int t_min = minbucket[i];
00345 int t_max = maxbucket[i];
00346 minbucket[i] = c_min; c_min += t_min;
00347 maxbucket[i] = c_max; c_max += t_max;
00348 }
00349 assert((c_min == n) && (c_max == n));
00350
00351 for (int i=n; i--; ) {
00352 minsorted[minbucket[x[i].min() - min_x]++] = i;
00353 maxsorted[maxbucket[x[i].max() - min_x]++] = i;
00354 }
00355 }
00356
00357
00358 min_x = x[minsorted[0]].min();
00359 max_x = x[maxsorted[n-1]].max();
00360
00361
00362 if (d > (static_cast<unsigned int>(Int::Limits::max) / 2U))
00363 return prop_bnd<View,long long int>(home,x,minsorted,maxsorted);
00364 else
00365 return prop_bnd<View,int>(home,x,minsorted,maxsorted);
00366 }
00367
00368 template<class View>
00369 ExecStatus
00370 prop_bnd(Space& home, ViewArray<View>& x) {
00371 int min = x[0].min(), max = x[0].max();
00372 for (int i=1; i<x.size(); i++) {
00373 min = std::min(min,x[i].min());
00374 max = std::max(max,x[i].max());
00375 }
00376 return prop_bnd(home, x, min, max);
00377 }
00378
00379 template<class View>
00380 ExecStatus
00381 Bnd<View>::propagate(Space& home, const ModEventDelta& med) {
00382 assert(x.size() > 1);
00383
00384 if (View::me(med) == ME_INT_VAL) {
00385 ExecStatus es = prop_val<View,false>(home,y);
00386 GECODE_ES_CHECK(es);
00387 if (y.size() < 2)
00388 return home.ES_SUBSUMED(*this);
00389 if (es == ES_FIX)
00390 return home.ES_FIX_PARTIAL(*this,View::med(ME_INT_BND));
00391 }
00392
00393 if (y.size() == 2)
00394 GECODE_REWRITE(*this,(Rel::Nq<View,View>::post(home(*this),y[0],y[1])));
00395
00396 ExecStatus es = prop_bnd<View>(home,x,min_x,max_x);
00397
00398 GECODE_ES_CHECK(es);
00399 if (es == ES_NOFIX && View::me(modeventdelta()) == ME_INT_VAL)
00400 return es;
00401
00402 const int n = x.size();
00403
00404 if ((n > 2*y.size()) && (n > 6)) {
00405
00406 unsigned int d = static_cast<unsigned int>(max_x - min_x) + 1;
00407 if (d > 2*static_cast<unsigned int>(n)) {
00408 MinInc<View> min_inc;
00409 Support::quicksort<View,MinInc<View> >(&x[0], n, min_inc);
00410 } else {
00411 Region r;
00412 int* minbucket = r.alloc<int>(d);
00413 View* minsorted = r.alloc<View>(n);
00414
00415 for (unsigned int i=0; i<d; i++)
00416 minbucket[i]=0;
00417 for (int i=0; i<n; i++)
00418 minbucket[x[i].min() - min_x]++;
00419
00420 int c_min = 0;
00421 for (unsigned int i=0; i<d; i++) {
00422 int t_min = minbucket[i];
00423 minbucket[i] = c_min; c_min += t_min;
00424 }
00425 assert(c_min == n);
00426
00427 for (int i=0; i<n; i++)
00428 minsorted[minbucket[x[i].min() - min_x]++] = x[i];
00429 for (int i=0; i<n; i++)
00430 x[i] = minsorted[i];
00431 }
00432
00433 int i = 0;
00434 int j = 0;
00435 int max = x[0].max()-1;
00436 while (i < n-1) {
00437 if (!x[i].assigned() ||
00438 (x[i].val() <= max) || (x[i].val() > x[i+1].min())) {
00439
00440 max = std::max(max,x[i].max());
00441 x[j++]=x[i];
00442 }
00443 i++;
00444 }
00445 if (!x[i].assigned() || (x[i].val() <= max))
00446 x[j++]=x[i];
00447 x.size(j);
00448 }
00449
00450 if (x.size() < 2)
00451 return home.ES_SUBSUMED(*this);
00452
00453 if (x.size() == 2)
00454 GECODE_REWRITE(*this,(Rel::Nq<View,View>::post(home(*this),x[0],x[1])));
00455
00456 return es;
00457 }
00458
00459 #ifdef GECODE_HAS_CBS
00460 template<class View>
00461 void
00462 Bnd<View>::solndistrib(Space& home, Propagator::SendMarginal send) const {
00463 cbsdistinct(home,this->id(),x,send);
00464 }
00465
00466 template<class View>
00467 void
00468 Bnd<View>::domainsizesum(Propagator::InDecision in, unsigned int& size,
00469 unsigned int& size_b) const {
00470 cbssize(x,in,size,size_b);
00471 }
00472 #endif
00473
00474 template<class View>
00475 ExecStatus
00476 Bnd<View>::post(Home home, ViewArray<View>& x){
00477 if (x.size() == 2)
00478 return Rel::Nq<View,View>::post(home,x[0],x[1]);
00479 if (x.size() > 2)
00480 (void) new (home) Bnd<View>(home,x);
00481 return ES_OK;
00482 }
00483
00484 }}}
00485
00486
00487