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
00035
00036
00037
00038 namespace Gecode { namespace Int { namespace Linear {
00039
00047 class SupportSet {
00048 private:
00050 static const unsigned int bpui = sizeof(unsigned int) * 8;
00052 unsigned int* bits;
00053 public:
00055 void init(unsigned int n);
00057 void support(unsigned int i);
00059 bool supported(unsigned int i) const;
00060
00061 private:
00063 class ResultIter : public ViewValues<IntView> {
00064 protected:
00066 const SupportSet* s;
00068 unsigned int p;
00069 public:
00071 ResultIter(const SupportSet* s0, const IntView& x);
00073 void operator++(void);
00074 };
00075
00076 public:
00078 ModEvent tell(Space* home, IntView& x) const;
00080 void dispose(void);
00081 };
00082
00087 template <class Val>
00088 class SupportIter {
00089 protected:
00091 int a;
00093 IntView x;
00095 SupportSet s;
00097 int c;
00099 unsigned int p;
00101 Val l;
00103 Val u;
00104 public:
00106 void init(int a, const IntView& x, Val l, Val u);
00108 void support(void);
00110 ModEvent tell(Space* home);
00112 void dispose(void);
00113 };
00114
00115
00120 template <class Val>
00121 class PosSupportIter : public SupportIter<Val> {
00122 private:
00124 IntVarImpFwd i;
00125
00126 using SupportIter<Val>::a;
00127 using SupportIter<Val>::x;
00128 using SupportIter<Val>::s;
00129 using SupportIter<Val>::c;
00130 using SupportIter<Val>::p;
00131 using SupportIter<Val>::l;
00132 using SupportIter<Val>::u;
00133 public:
00135 bool reset(Val& d);
00137 bool adjust(Val& d);
00138 };
00139
00140
00145 template <class Val>
00146 class NegSupportIter : public SupportIter<Val> {
00147 private:
00149 IntVarImpBwd i;
00150
00151 using SupportIter<Val>::a;
00152 using SupportIter<Val>::x;
00153 using SupportIter<Val>::s;
00154 using SupportIter<Val>::c;
00155 using SupportIter<Val>::p;
00156 using SupportIter<Val>::l;
00157 using SupportIter<Val>::u;
00158 public:
00160 bool reset(Val& d);
00162 bool adjust(Val& d);
00163 };
00164
00165
00166
00167
00168
00169
00170 forceinline void
00171 SupportSet::init(unsigned int n) {
00172 bits = Memory::bmalloc<unsigned int>((n / bpui) + 1);
00173 for (unsigned int i = (n / bpui) + 1; i--; )
00174 bits[i] = 0;
00175 }
00176 forceinline void
00177 SupportSet::support(unsigned int i) {
00178 unsigned int p = i / bpui;
00179 bits[p] |= 1 << (i-p*bpui);
00180 }
00181 forceinline bool
00182 SupportSet::supported(unsigned int i) const {
00183 unsigned int p = i / bpui;
00184 return (bits[p] & (1 << (i-p*bpui))) != 0;
00185 }
00186
00187 forceinline
00188 SupportSet::ResultIter::ResultIter(const SupportSet* s0, const IntView& x)
00189 : ViewValues<IntView>(x), s(s0), p(0) {
00190 while (ViewValues<IntView>::operator()() && s->supported(p)) {
00191 ViewValues<IntView>::operator++(); ++p;
00192 }
00193 }
00194 forceinline void
00195 SupportSet::ResultIter::operator++(void) {
00196 do {
00197 ViewValues<IntView>::operator++(); ++p;
00198 } while (ViewValues<IntView>::operator()() && s->supported(p));
00199 }
00200
00201
00202 inline ModEvent
00203 SupportSet::tell(Space* home, IntView& x) const {
00204 unsigned int n = x.size() / bpui;
00205
00206 for (unsigned int i=n+1; i--; )
00207 if (bits[i] != 0)
00208 goto all;
00209 return ME_INT_FAILED;
00210 all:
00211
00212 for (unsigned int i=n; i--; )
00213 if (bits[i] != ~0U)
00214 goto tell;
00215
00216 for (unsigned int i=n*bpui; i<x.size(); i++)
00217 if (!supported(i))
00218 goto tell;
00219 return ME_INT_NONE;
00220 tell:
00221 {
00222 ResultIter i(this,x);
00223 return x.minus_v(home,i);
00224 }
00225 }
00226
00227 forceinline void
00228 SupportSet::dispose(void) {
00229 Memory::free(bits);
00230 }
00231
00232
00233
00234
00235
00236
00237 template <class Val>
00238 forceinline void
00239 SupportIter<Val>::init(int a0, const IntView& x0, Val l0, Val u0) {
00240 a=a0; x=x0; l=l0; u=u0;
00241 s.init(x.size());
00242 }
00243 template <class Val>
00244 forceinline void
00245 SupportIter<Val>::support(void) {
00246 s.support(p);
00247 }
00248 template <class Val>
00249 forceinline ModEvent
00250 SupportIter<Val>::tell(Space* home) {
00251 return s.tell(home,x);
00252 }
00253 template <class Val>
00254 forceinline void
00255 SupportIter<Val>::dispose(void) {
00256 s.dispose();
00257 }
00258
00259
00260
00261
00262
00263
00264 template <class Val>
00265 forceinline bool
00266 PosSupportIter<Val>::reset(Val& d) {
00267
00268 if (d + static_cast<Val>(a)*x.max() < u)
00269 return false;
00270
00271 i.init(x.var()); p = 0;
00272
00273 while (d + static_cast<Val>(a)*i.max() < u) {
00274 p += i.width(); ++i;
00275 }
00276
00277 assert(i());
00278
00279 c = i.min();
00280
00281 while (d + static_cast<Val>(a)*c < u) {
00282 p++; c++;
00283 }
00284
00285 d += static_cast<Val>(a) * c;
00286 return true;
00287 }
00288 template <class Val>
00289 forceinline bool
00290 PosSupportIter<Val>::adjust(Val& d) {
00291
00292 Val v = static_cast<Val>(a) * c;
00293
00294 d -= v;
00295
00296 p++;
00297
00298 if (c < i.max()) {
00299
00300 c += 1; v += a;
00301 } else {
00302
00303 ++i;
00304 if (!i())
00305 return false;
00306 c = i.min(); v = static_cast<Val>(a) * c;
00307 }
00308
00309 if (d + v > l)
00310 return false;
00311
00312 d += v;
00313 return true;
00314 }
00315
00316
00317
00318
00319
00320
00321 template <class Val>
00322 forceinline bool
00323 NegSupportIter<Val>::reset(Val& d) {
00324
00325 if (d + static_cast<Val>(a)*x.min() < u)
00326 return false;
00327
00328 i.init(x.var()); p = x.size()-1;
00329
00330 while (d + static_cast<Val>(a)*i.min() < u) {
00331 p -= i.width(); ++i;
00332 }
00333
00334 assert(i());
00335
00336 c = i.max();
00337
00338 while (d + static_cast<Val>(a)*c < u) {
00339 p--; c--;
00340 }
00341
00342 d += static_cast<Val>(a) * c;
00343 return true;
00344 }
00345 template <class Val>
00346 forceinline bool
00347 NegSupportIter<Val>::adjust(Val& d) {
00348
00349 Val v = static_cast<Val>(a) * c;
00350
00351 d -= v;
00352
00353 p--;
00354
00355 if (c > i.min()) {
00356
00357 c -= 1; v -= a;
00358 } else {
00359
00360 ++i;
00361 if (!i())
00362 return false;
00363 c = i.max(); v = static_cast<Val>(a) * c;
00364 }
00365
00366 if (d + v > l)
00367 return false;
00368
00369 d += v;
00370 return true;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379 template <class Val, class View>
00380 forceinline
00381 DomEq<Val,View>::DomEq(Space* home,
00382 ViewArray<View >& x, ViewArray<View >& y,
00383 Val c)
00384 : Lin<Val,View,View,PC_INT_DOM>(home,x,y,c) {}
00385
00386 template <class Val, class View>
00387 ExecStatus
00388 DomEq<Val,View>::post(Space* home,
00389 ViewArray<View>& x, ViewArray<View>& y,
00390 Val c) {
00391 (void) new (home) DomEq<Val,View>(home,x,y,c);
00392 return ES_OK;
00393 }
00394
00395 template <class Val, class View>
00396 forceinline
00397 DomEq<Val,View>::DomEq(Space* home, bool share, DomEq<Val,View>& p)
00398 : Lin<Val,View,View,PC_INT_DOM>(home,share,p) {}
00399
00400 template <class Val, class View>
00401 Actor*
00402 DomEq<Val,View>::copy(Space* home, bool share) {
00403 return new (home) DomEq<Val,View>(home,share,*this);
00404 }
00405
00406 template <class Val, class View>
00407 PropCost
00408 DomEq<Val,View>::cost(ModEventDelta med) const {
00409 return (View::me(med) != ME_INT_DOM)
00410 ? cost_hi(x.size()+y.size(),PC_LINEAR_LO)
00411 : cost_hi(x.size()+y.size(),PC_CRAZY_HI);
00412 }
00413
00414 template <class Val, class View>
00415 inline Support::Symbol
00416 DomEq<Val,View>::ati(void) {
00417 return Reflection::mangle<Val,View>("Gecode::Int::Linear::DomEq");
00418 }
00419
00420 template <class Val, class View>
00421 Reflection::ActorSpec
00422 DomEq<Val,View>::spec(const Space* home, Reflection::VarMap& m) const {
00423 return Lin<Val,View,View,PC_INT_DOM>::spec(home, m, ati());
00424 }
00425
00426 template <class Val, class View>
00427 void
00428 DomEq<Val,View>::post(Space* home, Reflection::VarMap& vars,
00429 const Reflection::ActorSpec& spec) {
00430 spec.checkArity(3);
00431 ViewArray<View> x(home, vars, spec[0]);
00432 ViewArray<View> y(home, vars, spec[1]);
00433 Val c = spec[2]->toInt();
00434 (void) new (home) DomEq<Val,View>(home, x, y, c);
00435 }
00436
00437 template <class Val, class View>
00438 ExecStatus
00439 DomEq<Val,View>::propagate(Space* home, ModEventDelta med) {
00440 if (View::me(med) != ME_INT_DOM) {
00441 ExecStatus es = prop_bnd<Val,View,View>(home,med,this,x,y,c);
00442 GECODE_ES_CHECK(es);
00443 return ES_FIX_PARTIAL(this,View::med(ME_INT_DOM));
00444 }
00445
00446
00447 Val d = -c;
00448
00449 int n = x.size();
00450 int m = y.size();
00451
00452
00453 GECODE_AUTOARRAY(PosSupportIter<Val>, xp, n);
00454 GECODE_AUTOARRAY(NegSupportIter<Val>, yp, m);
00455
00456
00457 {
00458 Val l = 0;
00459 Val u = 0;
00460 for (int j=m; j--; ) {
00461 yp[j].init(-y[j].scale(),y[j].base(),l,u);
00462 l += y[j].max(); u += y[j].min();
00463 }
00464 for (int i=n; i--; ) {
00465 xp[i].init(x[i].scale(),x[i].base(),l,u);
00466 l -= x[i].min(); u -= x[i].max();
00467 }
00468 }
00469
00470
00471 {
00472
00473 int i = 0;
00474 int j = 0;
00475
00476 next_i:
00477
00478 while (i<n) {
00479 if (!xp[i].reset(d)) goto prev_i;
00480 i++;
00481 }
00482 next_j:
00483
00484 while (j<m) {
00485 if (!yp[j].reset(d)) goto prev_j;
00486 j++;
00487 }
00488
00489 if (d == 0) {
00490
00491 for (int is=n; is--; ) xp[is].support();
00492 for (int js=m; js--; ) yp[js].support();
00493 }
00494 prev_j:
00495
00496 while (j>0) {
00497 if (yp[j-1].adjust(d)) goto next_j;
00498 j--;
00499 }
00500 prev_i:
00501
00502 while (i>0) {
00503 if (xp[i-1].adjust(d)) goto next_i;
00504 i--;
00505 }
00506 }
00507
00508
00509 ExecStatus es = ES_NOFIX;
00510 for (int i=n; i--; ) {
00511 ModEvent me = xp[i].tell(home);
00512 if (me_failed(me)) {
00513 es = ES_FAILED; goto dispose;
00514 }
00515 if (!x[i].assigned())
00516 es = ES_FIX;
00517 }
00518 for (int j=m; j--; ) {
00519 ModEvent me = yp[j].tell(home);
00520 if (me_failed(me)) {
00521 es = ES_FAILED; goto dispose;
00522 }
00523 if (!y[j].assigned())
00524 es = ES_FIX;
00525 }
00526
00527
00528 dispose:
00529 for (int i=n; i--; ) xp[i].dispose();
00530 for (int j=m; j--; ) yp[j].dispose();
00531
00532 if (es == ES_NOFIX)
00533 return ES_SUBSUMED(this,sizeof(*this));
00534 return es;
00535 }
00536
00537 }}}
00538
00539