00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "gecode/int.hh"
00023
00024 #include "gecode/limits.hh"
00025
00026 #include "gecode/int/var/imp-body.icc"
00027
00028 namespace Gecode { namespace Int {
00029
00030 forceinline bool
00031 IntVarImp::closer_min(int n) const {
00032 unsigned int l = n - dom.min();
00033 unsigned int r = dom.max() - n;
00034 return l < r;
00035 }
00036
00037 int
00038 IntVarImp::med(void) const {
00039
00040 if (fst() == NULL)
00041 return (dom.min()+dom.max())/2;
00042 unsigned int i = size() / 2;
00043 const RangeList* p = NULL;
00044 const RangeList* c = fst();
00045 while (i >= c->width()) {
00046 i -= c->width();
00047 const RangeList* n=c->next(p); p=c; c=n;
00048 }
00049 return c->min() + static_cast<int>(i);
00050 }
00051
00052 bool
00053 IntVarImp::in_full(int m) const {
00054 if (closer_min(m)) {
00055 const RangeList* p = NULL;
00056 const RangeList* c = fst();
00057 while (m > c->max()) {
00058 const RangeList* n=c->next(p); p=c; c=n;
00059 }
00060 return (m >= c->min());
00061 } else {
00062 const RangeList* n = NULL;
00063 const RangeList* c = lst();
00064 while (m < c->min()) {
00065 const RangeList* p=c->prev(n); n=c; c=p;
00066 }
00067 return (m <= c->max());
00068 }
00069 }
00070
00071
00072
00073
00074
00075
00076 void
00077 IntVarImp::lq_full(Space* home, int m) {
00078 assert((m >= dom.min()) && (m <= dom.max()));
00079 if (range()) {
00080 dom.max(m);
00081 if (assigned()) goto notify_val;
00082 } else if (m < fst()->next(NULL)->min()) {
00083 dom.max(std::min(m,fst()->max()));
00084 fst()->dispose(home,NULL,lst());
00085 fst(NULL); holes = 0;
00086 if (assigned()) goto notify_val;
00087 } else {
00088 RangeList* n = NULL;
00089 RangeList* c = lst();
00090 unsigned int h = 0;
00091 while (m < c->min()) {
00092 RangeList* p = c->prev(n); c->fix(n);
00093 h += (c->min() - p->max() - 1);
00094 n=c; c=p;
00095 }
00096 holes -= h;
00097 int max_c = std::min(m,c->max());
00098 dom.max(max_c); c->max(max_c);
00099 if (c != lst()) {
00100 lst()->dispose(home,n);
00101 c->next(n,NULL); lst(c);
00102 }
00103 }
00104 notify(home,ME_INT_BND);
00105 return;
00106 notify_val:
00107 notify(home,ME_INT_VAL);
00108 }
00109
00110 void
00111 IntVarImp::gq_full(Space* home, int m) {
00112 assert((m >= dom.min()) && (m <= dom.max()));
00113 if (range()) {
00114 dom.min(m);
00115 if (assigned()) goto notify_val;
00116 } else if (m > lst()->prev(NULL)->max()) {
00117 dom.min(std::max(m,lst()->min()));
00118 fst()->dispose(home,NULL,lst());
00119 fst(NULL); holes = 0;
00120 if (assigned()) goto notify_val;
00121 } else {
00122 RangeList* p = NULL;
00123 RangeList* c = fst();
00124 unsigned int h = 0;
00125 while (m > c->max()) {
00126 RangeList* n = c->next(p); c->fix(n);
00127 h += (n->min() - c->max() - 1);
00128 p=c; c=n;
00129 }
00130 holes -= h;
00131 int min_c = std::max(m,c->min());
00132 dom.min(min_c); c->min(min_c);
00133 if (c != fst()) {
00134 fst()->dispose(home,p);
00135 c->prev(p,NULL); fst(c);
00136 }
00137 }
00138 notify(home,ME_INT_BND);
00139 return;
00140 notify_val:
00141 notify(home,ME_INT_VAL);
00142 }
00143
00144 void
00145 IntVarImp::eq_full(Space* home, int m) {
00146 if (!range()) {
00147 RangeList* p = NULL;
00148 RangeList* c = fst();
00149 while (m > c->max()) {
00150 RangeList* n=c->next(p); c->fix(n); p=c; c=n;
00151 }
00152 if (m < c->min()) {
00153 dom.min(Limits::Int::int_max+1);
00154 return;
00155 }
00156 while (c != NULL) {
00157 RangeList* n=c->next(p); c->fix(n); p=c; c=n;
00158 }
00159 assert(p == lst());
00160 fst()->dispose(home,p);
00161 fst(NULL); holes = 0;
00162 }
00163 dom.min(m); dom.max(m);
00164 notify(home,ME_INT_VAL);
00165 }
00166
00167 ModEvent
00168 IntVarImp::nq_full(Space* home, int m) {
00169 assert(!((m < dom.min()) || (m > dom.max())));
00170 if (range()) {
00171 if ((m == dom.min()) && (m == dom.max()))
00172 return ME_INT_FAILED;
00173 if (m == dom.min()) {
00174 dom.min(m+1); goto notify_bnd_or_val;
00175 }
00176 if (m == dom.max()) {
00177 dom.max(m-1); goto notify_bnd_or_val;
00178 }
00179 RangeList* f = new (home) RangeList(dom.min(),m-1);
00180 RangeList* l = new (home) RangeList(m+1,dom.max());
00181 f->prevnext(NULL,l);
00182 l->prevnext(f,NULL);
00183 fst(f); lst(l); holes = 1;
00184 } else if (m < fst()->next(NULL)->min()) {
00185 int f_max = fst()->max();
00186 if (m > f_max)
00187 return ME_INT_NONE;
00188 int f_min = dom.min();
00189 if ((m == f_min) && (m == f_max)) {
00190 RangeList* f_next = fst()->next(NULL);
00191 dom.min(f_next->min());
00192 if (f_next == lst()) {
00193
00194 fst()->dispose(home,f_next);
00195 fst(NULL); holes = 0;
00196 goto notify_bnd_or_val;
00197 } else {
00198 f_next->prev(fst(),NULL);
00199 fst()->dispose(home); fst(f_next);
00200 holes -= dom.min() - f_min - 1;
00201 goto notify_bnd;
00202 }
00203 } else if (m == f_min) {
00204 dom.min(m+1); fst()->min(m+1);
00205 goto notify_bnd;
00206 } else if (m == f_max) {
00207 fst()->max(m-1); holes += 1;
00208 } else {
00209
00210 RangeList* f = new (home) RangeList(f_min,m-1);
00211 f->prevnext(NULL,fst());
00212 fst()->min(m+1); fst()->prev(NULL,f);
00213 fst(f); holes += 1;
00214 }
00215 } else if (m > lst()->prev(NULL)->max()) {
00216 int l_min = lst()->min();
00217 if (m < l_min)
00218 return ME_INT_NONE;
00219 int l_max = dom.max();
00220 if ((m == l_min) && (m == l_max)) {
00221 RangeList* l_prev = lst()->prev(NULL);
00222 dom.max(l_prev->max());
00223 if (l_prev == fst()) {
00224
00225 l_prev->dispose(home,lst());
00226 fst(NULL); holes = 0;
00227 goto notify_bnd_or_val;
00228 } else {
00229 l_prev->next(lst(),NULL);
00230 lst()->dispose(home); lst(l_prev);
00231 holes -= l_max - dom.max() - 1;
00232 goto notify_bnd;
00233 }
00234 } else if (m == l_max) {
00235 dom.max(m-1); lst()->max(m-1);
00236 goto notify_bnd;
00237 } else if (m == l_min) {
00238 lst()->min(m+1); holes += 1;
00239 } else {
00240 RangeList* l = new (home) RangeList(m+1,l_max);
00241 l->prevnext(lst(),NULL);
00242 lst()->max(m-1); lst()->next(NULL,l);
00243 lst(l); holes += 1;
00244 }
00245 } else {
00246 RangeList* p;
00247 RangeList* c;
00248 RangeList* n;
00249 if (closer_min(m)) {
00250 assert(m > fst()->max());
00251 p = NULL;
00252 c = fst();
00253 do {
00254 n=c->next(p); p=c; c=n;
00255 } while (m > c->max());
00256 if (m < c->min())
00257 return ME_INT_NONE;
00258 n=c->next(p);
00259 } else {
00260 assert(m < lst()->min());
00261 n = NULL;
00262 c = lst();
00263 do {
00264 p=c->prev(n); n=c; c=p;
00265 } while (m < c->min());
00266 if (m > c->max())
00267 return ME_INT_NONE;
00268 p=c->prev(n);
00269 }
00270 assert((fst() != c) && (lst() != c));
00271 assert((m >= c->min()) && (m <= c->max()));
00272 holes += 1;
00273 int c_min = c->min();
00274 int c_max = c->max();
00275 if ((c_min == m) && (c_max == m)) {
00276 c->dispose(home);
00277 p->next(c,n); n->prev(c,p);
00278 } else if (c_min == m) {
00279 c->min(m+1);
00280 } else {
00281 c->max(m-1);
00282 if (c_max != m) {
00283 RangeList* l = new (home) RangeList(m+1,c_max);
00284 l->prevnext(c,n);
00285 c->next(n,l);
00286 n->prev(c,l);
00287 }
00288 }
00289 }
00290 notify(home,ME_INT_DOM);
00291 return ME_INT_DOM;
00292 notify_bnd_or_val:
00293 if (assigned()) {
00294 notify(home,ME_INT_VAL);
00295 return ME_INT_VAL;
00296 }
00297 notify_bnd:
00298 notify(home,ME_INT_BND);
00299 return ME_INT_BND;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309 forceinline
00310 IntVarImp::IntVarImp(Space* home, bool share, IntVarImp& x, bool is_bool)
00311 : IntVarImpBase(home,share,x), dom(x.dom.min(),x.dom.max()) {
00312 if (is_bool) {
00313 holes = 0; fst(NULL);
00314 } else {
00315 holes = x.holes;
00316 if (holes) {
00317 int m = 1;
00318
00319 {
00320 RangeList* s_p = x.fst();
00321 RangeList* s_c = s_p->next(NULL);
00322 do {
00323 m++;
00324 RangeList* s_n = s_c->next(s_p); s_p=s_c; s_c=s_n;
00325 } while (s_c != NULL);
00326 }
00327 RangeList* d_c =
00328 reinterpret_cast<RangeList*>(home->alloc(m*sizeof(RangeList)));
00329 fst(d_c); lst(d_c+m-1);
00330 d_c->min(x.fst()->min());
00331 d_c->max(x.fst()->max());
00332 d_c->prevnext(NULL,NULL);
00333 RangeList* s_p = x.fst();
00334 RangeList* s_c = s_p->next(NULL);
00335 do {
00336 RangeList* d_n = d_c + 1;
00337 d_c->next(NULL,d_n);
00338 d_n->prevnext(d_c,NULL);
00339 d_n->min(s_c->min()); d_n->max(s_c->max());
00340 d_c = d_n;
00341 RangeList* s_n=s_c->next(s_p); s_p=s_c; s_c=s_n;
00342 } while (s_c != NULL);
00343 d_c->next(NULL,NULL);
00344 } else {
00345 fst(NULL);
00346 }
00347 }
00348 }
00349
00350 IntVarImp*
00351 IntVarImp::perform_copy(Space* home, bool share) {
00352 return new (home) IntVarImp(home,share,*this,false);
00353 }
00354 IntVarImp*
00355 IntVarImp::perform_copy_bool(Space* home, bool share) {
00356 return new (home) IntVarImp(home,share,*this,true);
00357 }
00358
00359 }}
00360
00361