00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00031
00032
00033
00034
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
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
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
00205 ExecStatus es = ES_FIX;
00206
00207
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++) {
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);
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);
00232 }
00233 if (hall[z].d == hall[z].bounds-hall[y].bounds) {
00234 pathset_h(hall, hall[y].h, j-1, y);
00235 hall[y].h = j-1;
00236 }
00237 }
00238
00239
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; ) {
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
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
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
00335