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 #include <algorithm>
00037 #include <type_traits>
00038
00039 namespace Gecode { namespace Int { namespace Extensional {
00040
00041
00042
00043
00044
00045 template<class View, bool pos>
00046 forceinline void
00047 Compact<View,pos>::CTAdvisor::adjust(void) {
00048 if (pos) {
00049 {
00050 int n = view().min();
00051 assert((_fst->min <= n) && (n <= _lst->max));
00052 while (n > _fst->max)
00053 _fst++;
00054 assert((_fst->min <= n) && (n <= _lst->max));
00055 }
00056 {
00057 int n = view().max();
00058 assert((_fst->min <= n) && (n <= _lst->max));
00059 while (n < _lst->min)
00060 _lst--;
00061 assert((_fst->min <= n) && (n <= _lst->max));
00062 }
00063 } else {
00064 {
00065 int n = view().min();
00066 while ((_fst <= _lst) && (n > _fst->max))
00067 _fst++;
00068 }
00069 {
00070 int n = view().max();
00071 while ((_fst <= _lst) && (n < _lst->min))
00072 _lst--;
00073 }
00074 }
00075 }
00076
00077 template<class View, bool pos>
00078 forceinline
00079 Compact<View,pos>::CTAdvisor::CTAdvisor
00080 (Space& home, Propagator& p,
00081 Council<CTAdvisor>& c, const TupleSet& ts, View x0, int i)
00082 : ViewAdvisor<View>(home,p,c,x0), _fst(ts.fst(i)), _lst(ts.lst(i)) {
00083 adjust();
00084 }
00085
00086 template<class View, bool pos>
00087 forceinline
00088 Compact<View,pos>::CTAdvisor::CTAdvisor(Space& home, CTAdvisor& a)
00089 : ViewAdvisor<View>(home,a), _fst(a._fst), _lst(a._lst) {}
00090
00091 template<class View, bool pos>
00092 forceinline const typename Compact<View,pos>::Range*
00093 Compact<View,pos>::CTAdvisor::fst(void) const {
00094 return _fst;
00095 }
00096
00097 template<class View, bool pos>
00098 forceinline const typename Compact<View,pos>::Range*
00099 Compact<View,pos>::CTAdvisor::lst(void) const {
00100 return _lst;
00101 }
00102
00103 template<class View, bool pos>
00104 forceinline void
00105 Compact<View,pos>::CTAdvisor::dispose(Space& home, Council<CTAdvisor>& c) {
00106 (void) ViewAdvisor<View>::dispose(home,c);
00107 }
00108
00109
00110
00111
00112
00113
00114 template<class View, bool pos>
00115 const typename Compact<View,pos>::Range*
00116 Compact<View,pos>::range(CTAdvisor& a, int n) {
00117 assert((n > a.fst()->max) && (n < a.lst()->min));
00118
00119 const Range* f=a.fst()+1;
00120 const Range* l=a.lst()-1;
00121
00122 assert(!pos || (f<=l));
00123
00124 while (f < l) {
00125 const Range* m = f + ((l-f) >> 1);
00126 if (n < m->min) {
00127 l=m-1;
00128 } else if (n > m->max) {
00129 f=m+1;
00130 } else {
00131 f=m; break;
00132 }
00133 }
00134
00135 if (pos) {
00136 assert((f->min <= n) && (n <= f->max));
00137 return f;
00138 } else {
00139 if ((f <= l) && (f->min <= n) && (n <= f->max))
00140 return f;
00141 else
00142 return nullptr;
00143 }
00144 }
00145
00146 template<class View, bool pos>
00147 forceinline const BitSetData*
00148 Compact<View,pos>::supports(CTAdvisor& a, int n) {
00149 const Range* fnd;
00150 const Range* fst=a.fst();
00151 const Range* lst=a.lst();
00152 if (pos) {
00153 if (n <= fst->max) {
00154 fnd=fst;
00155 } else if (n >= lst->min) {
00156 fnd=lst;
00157 } else {
00158 fnd=range(a,n);
00159 }
00160 } else {
00161 if ((n < fst->min) || (n > lst->max))
00162 return nullptr;
00163 if (n <= fst->max) {
00164 fnd=fst;
00165 } else if (n >= lst->min) {
00166 fnd=lst;
00167 } else {
00168 fnd=range(a,n);
00169 if (!fnd)
00170 return nullptr;
00171 }
00172 }
00173 assert((fnd->min <= n) && (n <= fnd->max));
00174 return fnd->supports(n_words,n);
00175 }
00176
00177 template<class View, bool pos>
00178 forceinline void
00179 Compact<View,pos>::ValidSupports::find(void) {
00180 assert(!pos);
00181 assert(n <= max);
00182 while (true) {
00183 while (xr() && (n > xr.max()))
00184 ++xr;
00185 if (!xr()) {
00186 n = max+1; return;
00187 }
00188 assert(n <= xr.max());
00189 n = std::max(n,xr.min());
00190
00191 while ((sr <= lst) && (n > sr->max))
00192 sr++;
00193 if (sr > lst) {
00194 n = max+1; return;
00195 }
00196 assert(n <= sr->max);
00197 n = std::max(n,sr->min);
00198
00199 if ((xr.min() <= n) && (n <= xr.max())) {
00200 s = sr->supports(n_words,n);
00201 return;
00202 }
00203 }
00204 GECODE_NEVER;
00205 }
00206
00207 template<class View, bool pos>
00208 forceinline
00209 Compact<View,pos>::ValidSupports::ValidSupports(const Compact<View,pos>& p,
00210 CTAdvisor& a)
00211 : n_words(p.n_words), max(a.view().max()),
00212 xr(a.view()), sr(a.fst()), lst(a.lst()), n(xr.min()) {
00213 if (pos) {
00214 while (n > sr->max)
00215 sr++;
00216 s = sr->supports(n_words,n);
00217 } else {
00218 s = nullptr;
00219 find();
00220 }
00221 }
00222 template<class View, bool pos>
00223 forceinline
00224 Compact<View,pos>::ValidSupports::ValidSupports(const TupleSet& ts,
00225 int i, View x)
00226 : n_words(ts.words()), max(x.max()),
00227 xr(x), sr(ts.fst(i)), lst(ts.lst(i)), n(xr.min()) {
00228 if (pos) {
00229 while (n > sr->max)
00230 sr++;
00231 s = sr->supports(n_words,n);
00232 } else {
00233 s = nullptr;
00234 find();
00235 }
00236 }
00237 template<class View, bool pos>
00238 forceinline void
00239 Compact<View,pos>::ValidSupports::operator ++(void) {
00240 n++;
00241 if (pos) {
00242 if (n <= xr.max()) {
00243 assert(n <= sr->max);
00244 s += n_words;
00245 } else if (n <= max) {
00246 while (n > xr.max())
00247 ++xr;
00248 n = xr.min();
00249 while (n > sr->max)
00250 sr++;
00251 s = sr->supports(n_words,n);
00252 assert((xr.min() <= n) && (n <= xr.max()));
00253 assert((sr->min <= n) && (n <= sr->max));
00254 assert(sr->min <= xr.min());
00255 }
00256 } else {
00257 if ((n <= sr->max) && (n <= xr.max())) {
00258 s += n_words;
00259 } else if (n <= max) {
00260 find();
00261 }
00262 }
00263 }
00264 template<class View, bool pos>
00265 forceinline bool
00266 Compact<View,pos>::ValidSupports::operator ()(void) const {
00267 return n <= max;
00268 }
00269 template<class View, bool pos>
00270 forceinline const BitSetData*
00271 Compact<View,pos>::ValidSupports::supports(void) const {
00272 assert(s == sr->supports(n_words,n));
00273 return s;
00274 }
00275 template<class View, bool pos>
00276 forceinline int
00277 Compact<View,pos>::ValidSupports::val(void) const {
00278 return n;
00279 }
00280
00281
00282
00283
00284
00285 template<class View, bool pos>
00286 forceinline
00287 Compact<View,pos>::LostSupports::LostSupports
00288 (const Compact<View,pos>& p, CTAdvisor& a, int l0, int h0)
00289 : n_words(p.n_words), r(a.fst()), l(l0), h(h0) {
00290 assert(pos);
00291
00292 while (l > r->max)
00293 r++;
00294 l = std::max(l,r->min);
00295 s = r->supports(n_words,l);
00296 }
00297 template<class View, bool pos>
00298 forceinline void
00299 Compact<View,pos>::LostSupports::operator ++(void) {
00300 l++; s += n_words;
00301 while ((l <= h) && (l > r->max)) {
00302 r++; l=r->min; s=r->s;
00303 }
00304 }
00305 template<class View, bool pos>
00306 forceinline bool
00307 Compact<View,pos>::LostSupports::operator ()(void) const {
00308 return l<=h;
00309 }
00310 template<class View, bool pos>
00311 forceinline const TupleSet::BitSetData*
00312 Compact<View,pos>::LostSupports::supports(void) const {
00313 assert((l >= r->min) && (l <= r->max));
00314 assert(s == r->supports(n_words,l));
00315 return s;
00316 }
00317
00318 template<class View, bool pos>
00319 forceinline bool
00320 Compact<View,pos>::all(void) const {
00321 Advisors<CTAdvisor> as(c);
00322 return !as();
00323 }
00324 template<class View, bool pos>
00325 forceinline bool
00326 Compact<View,pos>::atmostone(void) const {
00327 Advisors<CTAdvisor> as(c);
00328 if (!as()) return true;
00329 ++as;
00330 return !as();
00331 }
00332
00333 template<class View, bool pos>
00334 forceinline
00335 Compact<View,pos>::Compact(Space& home, Compact& p)
00336 : Propagator(home,p), n_words(p.n_words), ts(p.ts) {
00337 c.update(home,p.c);
00338 }
00339
00340 template<class View, bool pos>
00341 forceinline
00342 Compact<View,pos>::Compact(Home home, const TupleSet& ts0)
00343 : Propagator(home), n_words(ts0.words()), ts(ts0), c(home) {
00344 home.notice(*this, AP_DISPOSE);
00345 }
00346
00347 template<class View, bool pos>
00348 template<class Table>
00349 void
00350 Compact<View,pos>::setup(Space& home, Table& table, ViewArray<View>& x) {
00351
00352 ModEvent me = ME_INT_BND;
00353 Region r;
00354 BitSetData* mask = r.alloc<BitSetData>(table.size());
00355
00356 for (int i=0; i<x.size(); i++) {
00357 table.clear_mask(mask);
00358 for (ValidSupports vs(ts,i,x[i]); vs(); ++vs)
00359 table.add_to_mask(vs.supports(),mask);
00360 table.template intersect_with_mask<false>(mask);
00361
00362 if (table.empty())
00363 goto schedule;
00364 }
00365
00366 for (int i=0; i<x.size(); i++)
00367 if (!x[i].assigned())
00368 (void) new (home) CTAdvisor(home,*this,c,ts,x[i],i);
00369 else
00370 me = ME_INT_VAL;
00371
00372 schedule:
00373 View::schedule(home,*this,me);
00374 }
00375
00376 template<class View, bool pos>
00377 template<class Table>
00378 forceinline bool
00379 Compact<View,pos>::full(const Table& table) const {
00380 unsigned long long int s = 1U;
00381 for (Advisors<CTAdvisor> as(c); as(); ++as) {
00382 s *= static_cast<unsigned long long int>(as.advisor().view().size());
00383 if (s > table.bits())
00384 return false;
00385 }
00386 return s == table.ones();
00387 }
00388
00389 template<class View, bool pos>
00390 PropCost
00391 Compact<View,pos>::cost(const Space&, const ModEventDelta&) const {
00392
00393 int n = 0;
00394
00395 for (Advisors<CTAdvisor> as(c); as() && (n <= 3); ++as)
00396 n++;
00397 return PropCost::quadratic(PropCost::HI,n);
00398 }
00399
00400 template<class View, bool pos>
00401 forceinline size_t
00402 Compact<View,pos>::dispose(Space& home) {
00403 home.ignore(*this,AP_DISPOSE);
00404 c.dispose(home);
00405 ts.~TupleSet();
00406 (void) Propagator::dispose(home);
00407 return sizeof(*this);
00408 }
00409
00410
00411
00412
00413
00414
00415 template<class View, class Table>
00416 forceinline
00417 PosCompact<View,Table>::Status::Status(StatusType t)
00418 : s(t) {}
00419 template<class View, class Table>
00420 forceinline
00421 PosCompact<View,Table>::Status::Status(const Status& s)
00422 : s(s.s) {}
00423 template<class View, class Table>
00424 forceinline typename PosCompact<View,Table>::StatusType
00425 PosCompact<View,Table>::Status::type(void) const {
00426 return static_cast<StatusType>(s & 3);
00427 }
00428 template<class View, class Table>
00429 forceinline bool
00430 PosCompact<View,Table>::Status::single(CTAdvisor& a) const {
00431 if (type() != SINGLE)
00432 return false;
00433 assert(type() == 0);
00434 return reinterpret_cast<CTAdvisor*>(s) == &a;
00435 }
00436 template<class View, class Table>
00437 forceinline void
00438 PosCompact<View,Table>::Status::touched(CTAdvisor& a) {
00439 if (!single(a))
00440 s = MULTIPLE;
00441 }
00442 template<class View, class Table>
00443 forceinline void
00444 PosCompact<View,Table>::Status::none(void) {
00445 s = NONE;
00446 }
00447 template<class View, class Table>
00448 forceinline void
00449 PosCompact<View,Table>::Status::propagating(void) {
00450 s = PROPAGATING;
00451 }
00452
00453
00454
00455
00456
00457 template<class View, class Table>
00458 template<class TableProp>
00459 forceinline
00460 PosCompact<View,Table>::PosCompact(Space& home, TableProp& p)
00461 : Compact<View,true>(home,p), status(NONE), table(home,p.table) {
00462 assert(!table.empty());
00463 }
00464
00465 template<class View, class Table>
00466 Actor*
00467 PosCompact<View,Table>::copy(Space& home) {
00468 assert((table.words() > 0U) && (table.width() >= table.words()));
00469 if (table.words() <= 4U) {
00470 switch (table.width()) {
00471 case 0U:
00472 GECODE_NEVER; break;
00473 case 1U:
00474 return new (home) PosCompact<View,TinyBitSet<1U>>(home,*this);
00475 case 2U:
00476 return new (home) PosCompact<View,TinyBitSet<2U>>(home,*this);
00477 case 3U:
00478 return new (home) PosCompact<View,TinyBitSet<3U>>(home,*this);
00479 case 4U:
00480 return new (home) PosCompact<View,TinyBitSet<4U>>(home,*this);
00481 default:
00482 break;
00483 }
00484 }
00485 if (std::is_same<Table,BitSet<unsigned char>>::value) {
00486 goto copy_char;
00487 } else if (std::is_same<Table,BitSet<unsigned short int>>::value) {
00488 switch (Gecode::Support::u_type(table.width())) {
00489 case Gecode::Support::IT_CHAR: goto copy_char;
00490 case Gecode::Support::IT_SHRT: goto copy_short;
00491 case Gecode::Support::IT_INT: GECODE_NEVER;
00492 default: GECODE_NEVER;
00493 }
00494 } else {
00495 switch (Gecode::Support::u_type(table.width())) {
00496 case Gecode::Support::IT_CHAR: goto copy_char;
00497 case Gecode::Support::IT_SHRT: goto copy_short;
00498 case Gecode::Support::IT_INT: goto copy_int;
00499 default: GECODE_NEVER;
00500 }
00501 GECODE_NEVER;
00502 return nullptr;
00503 }
00504 copy_char:
00505 return new (home) PosCompact<View,BitSet<unsigned char>>(home,*this);
00506 copy_short:
00507 return new (home) PosCompact<View,BitSet<unsigned short int>>(home,*this);
00508 copy_int:
00509 return new (home) PosCompact<View,BitSet<unsigned int>>(home,*this);
00510 }
00511
00512 template<class View, class Table>
00513 forceinline
00514 PosCompact<View,Table>::PosCompact(Home home, ViewArray<View>& x,
00515 const TupleSet& ts)
00516 : Compact<View,true>(home,ts), status(MULTIPLE), table(home,ts.words()) {
00517 setup(home,table,x);
00518 }
00519
00520 template<class View, class Table>
00521 forceinline ExecStatus
00522 PosCompact<View,Table>::post(Home home, ViewArray<View>& x,
00523 const TupleSet& ts) {
00524 auto ct = new (home) PosCompact(home,x,ts);
00525 assert((x.size() > 1) && (ts.tuples() > 1));
00526 return ct->table.empty() ? ES_FAILED : ES_OK;
00527 }
00528
00529 template<class View, class Table>
00530 forceinline size_t
00531 PosCompact<View,Table>::dispose(Space& home) {
00532 (void) Compact<View,true>::dispose(home);
00533 return sizeof(*this);
00534 }
00535
00536 template<class View, class Table>
00537 void
00538 PosCompact<View,Table>::reschedule(Space& home) {
00539
00540 if ((status.type() != StatusType::NONE) ||
00541 all() || table.empty())
00542 View::schedule(home,*this,ME_INT_DOM);
00543 }
00544
00545 template<class View, class Table>
00546 ExecStatus
00547 PosCompact<View,Table>::propagate(Space& home, const ModEventDelta&) {
00548 if (table.empty())
00549 return ES_FAILED;
00550 if (all())
00551 return home.ES_SUBSUMED(*this);
00552
00553 Status touched(status);
00554
00555 status.propagating();
00556
00557 Region r;
00558
00559
00560 for (Advisors<CTAdvisor> as(c); as(); ++as) {
00561 CTAdvisor& a = as.advisor();
00562 View x = a.view();
00563
00564
00565 if (touched.single(a) || x.assigned())
00566 continue;
00567
00568 if (x.size() == 2) {
00569 if (!table.intersects(supports(a,x.min())))
00570 GECODE_ME_CHECK(x.eq(home,x.max()));
00571 else if (!table.intersects(supports(a,x.max())))
00572 GECODE_ME_CHECK(x.eq(home,x.min()));
00573 if (!x.assigned())
00574 a.adjust();
00575 } else {
00576
00577 int* nq = r.alloc<int>(x.size());
00578 unsigned int n_nq = 0;
00579
00580 int last_support = 0;
00581 for (ValidSupports vs(*this,a); vs(); ++vs)
00582 if (!table.intersects(vs.supports()))
00583 nq[n_nq++] = vs.val();
00584 else
00585 last_support = vs.val();
00586
00587 if (n_nq > 0U) {
00588 if (n_nq == 1U) {
00589 GECODE_ME_CHECK(x.nq(home,nq[0]));
00590 } else if (n_nq == x.size() - 1U) {
00591 GECODE_ME_CHECK(x.eq(home,last_support));
00592 goto noadjust;
00593 } else {
00594 Iter::Values::Array rnq(nq,n_nq);
00595 GECODE_ASSUME(n_nq >= 2U);
00596 GECODE_ME_CHECK(x.minus_v(home,rnq,false));
00597 }
00598 a.adjust();
00599 noadjust: ;
00600 }
00601 r.free();
00602 }
00603 }
00604
00605
00606 status.none();
00607
00608 assert(!table.empty());
00609
00610 return atmostone() ? home.ES_SUBSUMED(*this) : ES_FIX;
00611 }
00612
00613 template<class View, class Table>
00614 ExecStatus
00615 PosCompact<View,Table>::advise(Space& home, Advisor& a0, const Delta& d) {
00616 CTAdvisor& a = static_cast<CTAdvisor&>(a0);
00617
00618
00619 if (table.empty())
00620 return Compact<View,true>::disabled() ?
00621 home.ES_NOFIX_DISPOSE(c,a) : ES_FAILED;
00622
00623 View x = a.view();
00624
00625
00626
00627
00628
00629 if (status.type() == StatusType::PROPAGATING)
00630 return x.assigned() ? home.ES_FIX_DISPOSE(c,a) : ES_FIX;
00631
00632
00633 status.touched(a);
00634
00635 if (x.assigned()) {
00636
00637 table.template intersect_with_mask<true>(supports(a,x.val()));
00638 return home.ES_NOFIX_DISPOSE(c,a);
00639 }
00640
00641 if (!x.any(d) && (x.min(d) == x.max(d))) {
00642 table.nand_with_mask(supports(a,x.min(d)));
00643 a.adjust();
00644 } else if (!x.any(d) && (x.width(d) <= x.size())) {
00645
00646 for (LostSupports ls(*this,a,x.min(d),x.max(d)); ls(); ++ls) {
00647 table.nand_with_mask(ls.supports());
00648 if (table.empty())
00649 return Compact<View,true>::disabled() ?
00650 home.ES_NOFIX_DISPOSE(c,a) : ES_FAILED;
00651 }
00652 a.adjust();
00653 } else {
00654 a.adjust();
00655
00656 if (x.size() == 2) {
00657 table.intersect_with_masks(supports(a,x.min()),
00658 supports(a,x.max()));
00659 } else {
00660 Region r;
00661 BitSetData* mask = r.alloc<BitSetData>(table.size());
00662
00663 table.clear_mask(mask);
00664 for (ValidSupports vs(*this,a); vs(); ++vs)
00665 table.add_to_mask(vs.supports(),mask);
00666 table.template intersect_with_mask<false>(mask);
00667 }
00668 }
00669
00670
00671 if (table.empty())
00672 return Compact<View,true>::disabled() ?
00673 home.ES_NOFIX_DISPOSE(c,a) : ES_FAILED;
00674
00675
00676 return ES_NOFIX;
00677 }
00678
00679
00680
00681
00682
00683 template<class View>
00684 ExecStatus
00685 postposcompact(Home home, ViewArray<View>& x, const TupleSet& ts) {
00686 if (ts.tuples() == 0)
00687 return (x.size() == 0) ? ES_OK : ES_FAILED;
00688
00689
00690 for (int i=0; i<x.size(); i++) {
00691 TupleSet::Ranges r(ts,i);
00692 GECODE_ME_CHECK(x[i].inter_r(home, r, false));
00693 }
00694
00695 if ((x.size() <= 1) || (ts.tuples() <= 1))
00696 return ES_OK;
00697
00698
00699 switch (ts.words()) {
00700 case 0U:
00701 GECODE_NEVER; return ES_OK;
00702 case 1U:
00703 return PosCompact<View,TinyBitSet<1U>>::post(home,x,ts);
00704 case 2U:
00705 return PosCompact<View,TinyBitSet<2U>>::post(home,x,ts);
00706 case 3U:
00707 return PosCompact<View,TinyBitSet<3U>>::post(home,x,ts);
00708 case 4U:
00709 return PosCompact<View,TinyBitSet<4U>>::post(home,x,ts);
00710 default:
00711 switch (Gecode::Support::u_type(ts.words())) {
00712 case Gecode::Support::IT_CHAR:
00713 return PosCompact<View,BitSet<unsigned char>>
00714 ::post(home,x,ts);
00715 case Gecode::Support::IT_SHRT:
00716 return PosCompact<View,BitSet<unsigned short int>>
00717 ::post(home,x,ts);
00718 case Gecode::Support::IT_INT:
00719 return PosCompact<View,BitSet<unsigned int>>
00720 ::post(home,x,ts);
00721 default: GECODE_NEVER;
00722 }
00723 }
00724 GECODE_NEVER;
00725 return ES_OK;
00726 }
00727
00728
00729
00730
00731
00732
00733 template<class View, class Table>
00734 template<class TableProp>
00735 forceinline
00736 NegCompact<View,Table>::NegCompact(Space& home, TableProp& p)
00737 : Compact<View,false>(home,p), table(home,p.table) {
00738 assert(!table.empty());
00739 }
00740
00741 template<class View, class Table>
00742 Actor*
00743 NegCompact<View,Table>::copy(Space& home) {
00744 assert((table.words() > 0U) && (table.width() >= table.words()));
00745 if (table.words() <= 4U) {
00746 switch (table.width()) {
00747 case 0U:
00748 GECODE_NEVER; break;
00749 case 1U:
00750 return new (home) NegCompact<View,TinyBitSet<1U>>(home,*this);
00751 case 2U:
00752 return new (home) NegCompact<View,TinyBitSet<2U>>(home,*this);
00753 case 3U:
00754 return new (home) NegCompact<View,TinyBitSet<3U>>(home,*this);
00755 case 4U:
00756 return new (home) NegCompact<View,TinyBitSet<4U>>(home,*this);
00757 default:
00758 break;
00759 }
00760 }
00761 if (std::is_same<Table,BitSet<unsigned char>>::value) {
00762 goto copy_char;
00763 } else if (std::is_same<Table,BitSet<unsigned short int>>::value) {
00764 switch (Gecode::Support::u_type(table.width())) {
00765 case Gecode::Support::IT_CHAR: goto copy_char;
00766 case Gecode::Support::IT_SHRT: goto copy_short;
00767 case Gecode::Support::IT_INT: GECODE_NEVER;
00768 default: GECODE_NEVER;
00769 }
00770 } else {
00771 switch (Gecode::Support::u_type(table.width())) {
00772 case Gecode::Support::IT_CHAR: goto copy_char;
00773 case Gecode::Support::IT_SHRT: goto copy_short;
00774 case Gecode::Support::IT_INT: goto copy_int;
00775 default: GECODE_NEVER;
00776 }
00777 GECODE_NEVER;
00778 return nullptr;
00779 }
00780 copy_char:
00781 return new (home) NegCompact<View,BitSet<unsigned char>>(home,*this);
00782 copy_short:
00783 return new (home) NegCompact<View,BitSet<unsigned short int>>(home,*this);
00784 copy_int:
00785 return new (home) NegCompact<View,BitSet<unsigned int>>(home,*this);
00786 }
00787
00788 template<class View, class Table>
00789 forceinline
00790 NegCompact<View,Table>::NegCompact(Home home, ViewArray<View>& x,
00791 const TupleSet& ts)
00792 : Compact<View,false>(home,ts), table(home,ts.words()) {
00793 setup(home,table,x);
00794 }
00795
00796 template<class View, class Table>
00797 forceinline ExecStatus
00798 NegCompact<View,Table>::post(Home home, ViewArray<View>& x,
00799 const TupleSet& ts) {
00800 auto ct = new (home) NegCompact(home,x,ts);
00801 return ct->full(ct->table) ? ES_FAILED : ES_OK;
00802 }
00803
00804 template<class View, class Table>
00805 forceinline size_t
00806 NegCompact<View,Table>::dispose(Space& home) {
00807 (void) Compact<View,false>::dispose(home);
00808 return sizeof(*this);
00809 }
00810
00811 template<class View, class Table>
00812 void
00813 NegCompact<View,Table>::reschedule(Space& home) {
00814 View::schedule(home,*this,ME_INT_DOM);
00815 }
00816
00817 template<class View, class Table>
00818 ExecStatus
00819 NegCompact<View,Table>::propagate(Space& home, const ModEventDelta&) {
00820 #ifndef NDEBUG
00821 if (!table.empty()) {
00822
00823 for (Advisors<CTAdvisor> as(c); as(); ++as) {
00824 ValidSupports vs(*this,as.advisor());
00825 assert(vs());
00826 }
00827 }
00828 #endif
00829
00830 if (table.empty())
00831 return home.ES_SUBSUMED(*this);
00832
00833
00834 unsigned long long int x_size = 1U;
00835 unsigned long long int x_max = 1U;
00836
00837
00838
00839 for (Advisors<CTAdvisor> as(c); as(); ++as) {
00840 unsigned long long int n = as.advisor().view().size();
00841 if (n > x_max) {
00842 x_size *= x_max; x_max = n;
00843 } else {
00844 x_size *= n;
00845 }
00846 if (x_size > table.bits())
00847 return ES_FIX;
00848 }
00849 if (x_size > table.ones())
00850 return ES_FIX;
00851
00852 {
00853
00854 x_size *= x_max;
00855
00856 Region r;
00857
00858 for (Advisors<CTAdvisor> as(c); as(); ++as) {
00859 assert(!table.empty());
00860 CTAdvisor& a = as.advisor();
00861 View x = a.view();
00862
00863
00864 x_size /= static_cast<unsigned long long int>(x.size());
00865
00866 if ((x_size <= table.bits()) && (x_size <= table.ones())) {
00867
00868 int* nq = r.alloc<int>(x.size());
00869 unsigned int n_nq = 0U;
00870
00871 for (ValidSupports vs(*this,a); vs(); ++vs)
00872 if (x_size == table.ones(vs.supports()))
00873 nq[n_nq++] = vs.val();
00874
00875
00876 if (n_nq > 0U) {
00877 if (n_nq == 1U) {
00878 GECODE_ME_CHECK(x.nq(home,nq[0]));
00879 } else {
00880 Iter::Values::Array rnq(nq,n_nq);
00881 GECODE_ASSUME(n_nq >= 2U);
00882 GECODE_ME_CHECK(x.minus_v(home,rnq,false));
00883 }
00884 if (table.empty())
00885 return home.ES_SUBSUMED(*this);
00886 a.adjust();
00887 }
00888 r.free();
00889 }
00890
00891 x_size *= static_cast<unsigned long long int>(x.size());
00892 }
00893 }
00894
00895 if (table.ones() == x_size)
00896 return ES_FAILED;
00897 if (table.empty() || atmostone())
00898 return home.ES_SUBSUMED(*this);
00899 return ES_FIX;
00900 }
00901
00902 template<class View, class Table>
00903 ExecStatus
00904 NegCompact<View,Table>::advise(Space& home, Advisor& a0, const Delta&) {
00905 CTAdvisor& a = static_cast<CTAdvisor&>(a0);
00906
00907
00908 if (table.empty())
00909 return home.ES_NOFIX_DISPOSE(c,a);
00910
00911 View x = a.view();
00912
00913 a.adjust();
00914
00915 if (x.assigned()) {
00916
00917 if (const BitSetData* s = supports(a,x.val()))
00918 table.template intersect_with_mask<true>(s);
00919 else
00920 table.flush();
00921 return home.ES_NOFIX_DISPOSE(c,a);
00922 }
00923
00924 {
00925 ValidSupports vs(*this,a);
00926 if (!vs()) {
00927 table.flush();
00928 return home.ES_NOFIX_DISPOSE(c,a);
00929 }
00930
00931 Region r;
00932 BitSetData* mask = r.alloc<BitSetData>(table.size());
00933
00934 table.clear_mask(mask);
00935 do {
00936 table.add_to_mask(vs.supports(),mask);
00937 ++vs;
00938 } while (vs());
00939 table.template intersect_with_mask<false>(mask);
00940 }
00941
00942 if (table.empty())
00943 return home.ES_NOFIX_DISPOSE(c,a);
00944
00945
00946 return ES_NOFIX;
00947 }
00948
00949
00950
00951
00952
00953 template<class View>
00954 ExecStatus
00955 postnegcompact(Home home, ViewArray<View>& x, const TupleSet& ts) {
00956 if (ts.tuples() == 0)
00957 return ES_OK;
00958
00959
00960 for (int i=0; i<x.size(); i++) {
00961 TupleSet::Ranges rs(ts,i);
00962 ViewRanges<View> rx(x[i]);
00963 if (Iter::Ranges::disjoint(rs,rx))
00964 return ES_OK;
00965 }
00966
00967
00968 switch (ts.words()) {
00969 case 0U:
00970 GECODE_NEVER; return ES_OK;
00971 case 1U:
00972 return NegCompact<View,TinyBitSet<1U>>::post(home,x,ts);
00973 case 2U:
00974 return NegCompact<View,TinyBitSet<2U>>::post(home,x,ts);
00975 case 3U:
00976 return NegCompact<View,TinyBitSet<3U>>::post(home,x,ts);
00977 case 4U:
00978 return NegCompact<View,TinyBitSet<4U>>::post(home,x,ts);
00979 default:
00980 switch (Gecode::Support::u_type(ts.words())) {
00981 case Gecode::Support::IT_CHAR:
00982 return NegCompact<View,BitSet<unsigned char>>
00983 ::post(home,x,ts);
00984 case Gecode::Support::IT_SHRT:
00985 return NegCompact<View,BitSet<unsigned short int>>
00986 ::post(home,x,ts);
00987 case Gecode::Support::IT_INT:
00988 return NegCompact<View,BitSet<unsigned int>>
00989 ::post(home,x,ts);
00990 default: GECODE_NEVER;
00991 }
00992 }
00993 GECODE_NEVER;
00994 return ES_OK;
00995 }
00996
00997
00998
00999
01000
01001
01002 template<class View, class Table, class CtrlView, ReifyMode rm>
01003 template<class TableProp>
01004 forceinline
01005 ReCompact<View,Table,CtrlView,rm>::ReCompact(Space& home, TableProp& p)
01006 : Compact<View,false>(home,p), table(home,p.table) {
01007 b.update(home,p.b);
01008 y.update(home,p.y);
01009 assert(!table.empty());
01010 }
01011
01012 template<class View, class Table, class CtrlView, ReifyMode rm>
01013 Actor*
01014 ReCompact<View,Table,CtrlView,rm>::copy(Space& home) {
01015 assert((table.words() > 0U) && (table.width() >= table.words()));
01016 if (table.words() <= 4U) {
01017 switch (table.width()) {
01018 case 0U:
01019 GECODE_NEVER; break;
01020 case 1U:
01021 return new (home) ReCompact<View,TinyBitSet<1U>,CtrlView,rm>
01022 (home,*this);
01023 case 2U:
01024 return new (home) ReCompact<View,TinyBitSet<2U>,CtrlView,rm>
01025 (home,*this);
01026 case 3U:
01027 return new (home) ReCompact<View,TinyBitSet<3U>,CtrlView,rm>
01028 (home,*this);
01029 case 4U:
01030 return new (home) ReCompact<View,TinyBitSet<4U>,CtrlView,rm>
01031 (home,*this);
01032 default:
01033 break;
01034 }
01035 }
01036 if (std::is_same<Table,BitSet<unsigned char>>::value) {
01037 goto copy_char;
01038 } else if (std::is_same<Table,BitSet<unsigned short int>>::value) {
01039 switch (Gecode::Support::u_type(table.width())) {
01040 case Gecode::Support::IT_CHAR: goto copy_char;
01041 case Gecode::Support::IT_SHRT: goto copy_short;
01042 case Gecode::Support::IT_INT: GECODE_NEVER;
01043 default: GECODE_NEVER;
01044 }
01045 } else {
01046 switch (Gecode::Support::u_type(table.width())) {
01047 case Gecode::Support::IT_CHAR: goto copy_char;
01048 case Gecode::Support::IT_SHRT: goto copy_short;
01049 case Gecode::Support::IT_INT: goto copy_int;
01050 default: GECODE_NEVER;
01051 }
01052 GECODE_NEVER;
01053 return nullptr;
01054 }
01055 copy_char:
01056 return new (home) ReCompact<View,BitSet<unsigned char>,CtrlView,rm>
01057 (home,*this);
01058 copy_short:
01059 return new (home) ReCompact<View,BitSet<unsigned short int>,CtrlView,rm>
01060 (home,*this);
01061 copy_int:
01062 return new (home) ReCompact<View,BitSet<unsigned int>,CtrlView,rm>
01063 (home,*this);
01064 }
01065
01066 template<class View, class Table, class CtrlView, ReifyMode rm>
01067 forceinline
01068 ReCompact<View,Table,CtrlView,rm>::ReCompact(Home home, ViewArray<View>& x,
01069 const TupleSet& ts, CtrlView b0)
01070 : Compact<View,false>(home,ts), table(home,ts.words()), b(b0), y(x) {
01071 b.subscribe(home,*this,PC_BOOL_VAL);
01072 setup(home,table,x);
01073 }
01074
01075 template<class View, class Table, class CtrlView, ReifyMode rm>
01076 forceinline ExecStatus
01077 ReCompact<View,Table,CtrlView,rm>::post(Home home, ViewArray<View>& x,
01078 const TupleSet& ts, CtrlView b) {
01079 if (b.one()) {
01080 if (rm == RM_PMI)
01081 return ES_OK;
01082 return postposcompact(home,x,ts);
01083 }
01084 if (b.zero()) {
01085 if (rm == RM_IMP)
01086 return ES_OK;
01087 return postnegcompact(home,x,ts);
01088 }
01089 (void) new (home) ReCompact(home,x,ts,b);
01090 return ES_OK;
01091 }
01092
01093 template<class View, class Table, class CtrlView, ReifyMode rm>
01094 forceinline size_t
01095 ReCompact<View,Table,CtrlView,rm>::dispose(Space& home) {
01096 b.cancel(home,*this,PC_BOOL_VAL);
01097 (void) Compact<View,false>::dispose(home);
01098 return sizeof(*this);
01099 }
01100
01101 template<class View, class Table, class CtrlView, ReifyMode rm>
01102 void
01103 ReCompact<View,Table,CtrlView,rm>::reschedule(Space& home) {
01104 View::schedule(home,*this,ME_INT_DOM);
01105 }
01106
01107 template<class View, class Table, class CtrlView, ReifyMode rm>
01108 ExecStatus
01109 ReCompact<View,Table,CtrlView,rm>::propagate(Space& home,
01110 const ModEventDelta&) {
01111 if (b.one()) {
01112 if (rm == RM_PMI)
01113 return home.ES_SUBSUMED(*this);
01114 TupleSet keep(ts);
01115 GECODE_REWRITE(*this,postposcompact(home(*this),y,keep));
01116 }
01117 if (b.zero()) {
01118 if (rm == RM_IMP)
01119 return home.ES_SUBSUMED(*this);
01120 TupleSet keep(ts);
01121 GECODE_REWRITE(*this,postnegcompact(home(*this),y,keep));
01122 }
01123
01124 if (table.empty()) {
01125 if (rm != RM_PMI)
01126 GECODE_ME_CHECK(b.zero_none(home));
01127 return home.ES_SUBSUMED(*this);
01128 }
01129 if (full(table)) {
01130 if (rm != RM_IMP)
01131 GECODE_ME_CHECK(b.one_none(home));
01132 return home.ES_SUBSUMED(*this);
01133 }
01134
01135 return ES_FIX;
01136 }
01137
01138 template<class View, class Table, class CtrlView, ReifyMode rm>
01139 ExecStatus
01140 ReCompact<View,Table,CtrlView,rm>::advise(Space& home,
01141 Advisor& a0, const Delta&) {
01142 CTAdvisor& a = static_cast<CTAdvisor&>(a0);
01143
01144
01145 if (table.empty() || b.assigned())
01146 return home.ES_NOFIX_DISPOSE(c,a);
01147
01148 View x = a.view();
01149
01150 a.adjust();
01151
01152 if (x.assigned()) {
01153
01154 if (const BitSetData* s = supports(a,x.val()))
01155 table.template intersect_with_mask<true>(s);
01156 else
01157 table.flush();
01158 return home.ES_NOFIX_DISPOSE(c,a);
01159 }
01160
01161 {
01162 ValidSupports vs(*this,a);
01163 if (!vs()) {
01164 table.flush();
01165 return home.ES_NOFIX_DISPOSE(c,a);
01166 }
01167
01168 Region r;
01169 BitSetData* mask = r.alloc<BitSetData>(table.size());
01170
01171 table.clear_mask(mask);
01172 do {
01173 table.add_to_mask(vs.supports(),mask);
01174 ++vs;
01175 } while (vs());
01176 table.template intersect_with_mask<false>(mask);
01177 }
01178
01179 if (table.empty())
01180 return home.ES_NOFIX_DISPOSE(c,a);
01181
01182
01183 return ES_NOFIX;
01184 }
01185
01186
01187
01188
01189
01190 template<class View, class CtrlView, ReifyMode rm>
01191 ExecStatus
01192 postrecompact(Home home, ViewArray<View>& x, const TupleSet& ts,
01193 CtrlView b) {
01194
01195 if (ts.tuples() == 0) {
01196 if (x.size() != 0) {
01197 if (rm != RM_PMI)
01198 GECODE_ME_CHECK(b.zero(home));
01199 } else {
01200 if (rm != RM_IMP)
01201 GECODE_ME_CHECK(b.one(home));
01202 }
01203 return ES_OK;
01204 }
01205
01206 for (int i=0; i<x.size(); i++) {
01207 TupleSet::Ranges rs(ts,i);
01208 ViewRanges<View> rx(x[i]);
01209 if (Iter::Ranges::disjoint(rs,rx)) {
01210 if (rm != RM_PMI)
01211 GECODE_ME_CHECK(b.zero(home));
01212 return ES_OK;
01213 }
01214 }
01215
01216 switch (ts.words()) {
01217 case 0U:
01218 GECODE_NEVER; return ES_OK;
01219 case 1U:
01220 return ReCompact<View,TinyBitSet<1U>,CtrlView,rm>::post(home,x,ts,b);
01221 case 2U:
01222 return ReCompact<View,TinyBitSet<2U>,CtrlView,rm>::post(home,x,ts,b);
01223 case 3U:
01224 return ReCompact<View,TinyBitSet<3U>,CtrlView,rm>::post(home,x,ts,b);
01225 case 4U:
01226 return ReCompact<View,TinyBitSet<4U>,CtrlView,rm>::post(home,x,ts,b);
01227 default:
01228 switch (Gecode::Support::u_type(ts.words())) {
01229 case Gecode::Support::IT_CHAR:
01230 return ReCompact<View,BitSet<unsigned char>,CtrlView,rm>
01231 ::post(home,x,ts,b);
01232 case Gecode::Support::IT_SHRT:
01233 return ReCompact<View,BitSet<unsigned short int>,CtrlView,rm>
01234 ::post(home,x,ts,b);
01235 case Gecode::Support::IT_INT:
01236 return ReCompact<View,BitSet<unsigned int>,CtrlView,rm>
01237 ::post(home,x,ts,b);
01238 default: GECODE_NEVER;
01239 }
01240 }
01241 GECODE_NEVER;
01242 return ES_OK;
01243 }
01244
01245 }}}
01246
01247