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
00039
00040 namespace Gecode { namespace Int { namespace GCC {
00041
00042 template<class Card>
00043 forceinline
00044 Bnd<Card>::
00045 Bnd(Home home, ViewArray<IntView>& x0, ViewArray<Card>& k0,
00046 bool cf, bool nolbc) :
00047 Propagator(home), x(x0), y(home, x0), k(k0),
00048 card_fixed(cf), skip_lbc(nolbc) {
00049 y.subscribe(home, *this, PC_INT_BND);
00050 k.subscribe(home, *this, PC_INT_BND);
00051 }
00052
00053 template<class Card>
00054 forceinline
00055 Bnd<Card>::
00056 Bnd(Space& home, Bnd<Card>& p)
00057 : Propagator(home, p),
00058 card_fixed(p.card_fixed), skip_lbc(p.skip_lbc) {
00059 x.update(home, p.x);
00060 y.update(home, p.y);
00061 k.update(home, p.k);
00062 }
00063
00064 template<class Card>
00065 forceinline size_t
00066 Bnd<Card>::dispose(Space& home) {
00067 y.cancel(home,*this, PC_INT_BND);
00068 k.cancel(home,*this, PC_INT_BND);
00069 (void) Propagator::dispose(home);
00070 return sizeof(*this);
00071 }
00072
00073 template<class Card>
00074 Actor*
00075 Bnd<Card>::copy(Space& home) {
00076 return new (home) Bnd<Card>(home,*this);
00077 }
00078
00079 template<class Card>
00080 PropCost
00081 Bnd<Card>::cost(const Space&,
00082 const ModEventDelta& med) const {
00083 int n_k = Card::propagate ? k.size() : 0;
00084 if (IntView::me(med) == ME_INT_VAL)
00085 return PropCost::linear(PropCost::LO, y.size() + n_k);
00086 else
00087 return PropCost::quadratic(PropCost::LO, x.size() + n_k);
00088 }
00089
00090
00091 template<class Card>
00092 void
00093 Bnd<Card>::reschedule(Space& home) {
00094 y.reschedule(home, *this, PC_INT_BND);
00095 k.reschedule(home, *this, PC_INT_BND);
00096 }
00097
00098 template<class Card>
00099 forceinline ExecStatus
00100 Bnd<Card>::lbc(Space& home, int& nb,
00101 HallInfo hall[], Rank rank[], int mu[], int nu[]) {
00102 int n = x.size();
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 int i = 0;
00138 int j = 0;
00139 int w = 0;
00140 int z = 0;
00141 int v = 0;
00142
00143
00144 int rightmost = nb + 1;
00145 int bsize = nb + 2;
00146 w = rightmost;
00147
00148
00149
00150 hall[0].d = 0;
00151 hall[0].s = 0;
00152 hall[0].ps = 0;
00153
00154 for (i = bsize; --i; ) {
00155 int pred = i - 1;
00156 hall[i].s = pred;
00157 hall[i].ps = pred;
00158 hall[i].d = lps.sumup(hall[pred].bounds, hall[i].bounds - 1);
00159
00160
00161
00162
00163
00164
00165 if (hall[i].d == 0) {
00166 hall[pred].h = w;
00167 } else {
00168 hall[w].h = pred;
00169 w = pred;
00170 }
00171 }
00172
00173 w = rightmost;
00174 for (i = bsize; i--; ) {
00175 hall[i].t = i - 1;
00176 if (hall[i].d == 0) {
00177 hall[i].t = w;
00178 } else {
00179 hall[w].t = i;
00180 w = i;
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 for (i = 0; i < n; i++) {
00197
00198 int x0 = rank[mu[i]].min;
00199 int y = rank[mu[i]].max;
00200 int succ = x0 + 1;
00201 z = pathmax_t(hall, succ);
00202 j = hall[z].t;
00203
00204
00205
00206
00207
00208
00209
00210
00211 if (z != succ) {
00212 w = pathmax_ps(hall, succ);
00213 v = hall[w].ps;
00214 pathset_ps(hall, succ, w, w);
00215 w = std::min(y, z);
00216 pathset_ps(hall, hall[w].ps, v, w);
00217 hall[w].ps = v;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 if (hall[z].d <= lps.sumup(hall[y].bounds, hall[z].bounds - 1)) {
00228 w = pathmax_s(hall, hall[y].ps);
00229 pathset_s(hall, hall[y].ps, w, w);
00230
00231 v = hall[w].s;
00232 pathset_s(hall, hall[y].s, v, y);
00233 hall[y].s = v;
00234 } else {
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 if (--hall[z].d == 0) {
00245 hall[z].t = z + 1;
00246 z = pathmax_t(hall, hall[z].t);
00247 hall[z].t = j;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 if (hall[x0].h > x0) {
00257 hall[i].newBound = pathmax_h(hall, x0);
00258 w = hall[i].newBound;
00259 pathset_h(hall, x0, w, w);
00260 } else {
00261
00262 hall[i].newBound = x0;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272 if (hall[z].d == lps.sumup(hall[y].bounds, hall[z].bounds - 1)) {
00273 if (hall[y].h > y)
00274
00275
00276
00277
00278 y = hall[y].h;
00279
00280 pathset_h(hall, hall[y].h, j-1, y);
00281
00282 hall[y].h = j-1;
00283 }
00284 }
00285 pathset_t(hall, succ, z, z);
00286 }
00287
00288
00289
00290
00291
00292
00293 if (hall[nb].h != 0)
00294 return ES_FAILED;
00295
00296
00297
00298
00299
00300
00301 for (i = bsize; --i;)
00302 if (hall[i].s > i)
00303 hall[i].s = w;
00304 else
00305 w = i;
00306
00307
00308
00309
00310
00311
00312
00313
00314 for (i = n; i--; ) {
00315 int x0 = rank[mu[i]].min;
00316 int y = rank[mu[i]].max;
00317
00318 if ((hall[x0].s <= x0) || (y > hall[x0].s)) {
00319
00320 int m = lps.skipNonNullElementsRight(hall[hall[i].newBound].bounds);
00321 GECODE_ME_CHECK(x[mu[i]].gq(home, m));
00322 }
00323 }
00324
00325
00326 w = 0;
00327 for (i = 0; i <= nb; i++) {
00328 hall[i].d = lps.sumup(hall[i].bounds, hall[i + 1].bounds - 1);
00329 if (hall[i].d == 0) {
00330 hall[i].t = w;
00331 } else {
00332 hall[w].t = i;
00333 w = i;
00334 }
00335 }
00336 hall[w].t = i;
00337
00338 w = 0;
00339 for (i = 1; i <= nb; i++)
00340 if (hall[i - 1].d == 0) {
00341 hall[i].h = w;
00342 } else {
00343 hall[w].h = i;
00344 w = i;
00345 }
00346 hall[w].h = i;
00347
00348 for (i = n; i--; ) {
00349
00350
00351 int x0 = rank[nu[i]].max;
00352 int y = rank[nu[i]].min;
00353 int pred = x0 - 1;
00354 z = pathmin_t(hall, pred);
00355 j = hall[z].t;
00356
00357
00358
00359
00360 if (hall[z].d > lps.sumup(hall[z].bounds, hall[y].bounds - 1)) {
00361
00362 if (--hall[z].d == 0) {
00363 hall[z].t = z - 1;
00364 z = pathmin_t(hall, hall[z].t);
00365 hall[z].t = j;
00366 }
00367
00368 if (hall[x0].h < x0) {
00369 w = pathmin_h(hall, hall[x0].h);
00370 hall[i].newBound = w;
00371 pathset_h(hall, x0, w, w);
00372 } else {
00373 hall[i].newBound = x0;
00374 }
00375
00376 if (hall[z].d == lps.sumup(hall[z].bounds, hall[y].bounds - 1)) {
00377 if (hall[y].h < y) {
00378 y = hall[y].h;
00379 }
00380 int succj = j + 1;
00381
00382 pathset_h(hall, hall[y].h, succj, y);
00383 hall[y].h = succj;
00384 }
00385 }
00386 pathset_t(hall, pred, z, z);
00387 }
00388
00389
00390 for (i = n; i--; ) {
00391 int x0 = rank[nu[i]].min;
00392 int y = rank[nu[i]].max;
00393 if ((hall[x0].s <= x0) || (y > hall[x0].s)) {
00394 int m = lps.skipNonNullElementsLeft(hall[hall[i].newBound].bounds - 1);
00395 GECODE_ME_CHECK(x[nu[i]].lq(home, m));
00396 }
00397 }
00398 return ES_OK;
00399 }
00400
00401
00402 template<class Card>
00403 forceinline ExecStatus
00404 Bnd<Card>::ubc(Space& home, int& nb,
00405 HallInfo hall[], Rank rank[], int mu[], int nu[]) {
00406 int rightmost = nb + 1;
00407 int bsize = nb + 2;
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 hall[0].h = 0;
00419 hall[0].t = 0;
00420 hall[0].d = 0;
00421
00422 for (int i = bsize; --i; ) {
00423 hall[i].h = hall[i].t = i-1;
00424 hall[i].d = ups.sumup(hall[i-1].bounds, hall[i].bounds - 1);
00425 }
00426
00427 int n = x.size();
00428
00429 for (int i = 0; i < n; i++) {
00430
00431 int x0 = rank[mu[i]].min;
00432 int succ = x0 + 1;
00433 int y = rank[mu[i]].max;
00434 int z = pathmax_t(hall, succ);
00435 int j = hall[z].t;
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 if (--hall[z].d == 0) {
00453 hall[z].t = z + 1;
00454 z = pathmax_t(hall, hall[z].t);
00455 if (z >= bsize)
00456 z--;
00457 hall[z].t = j;
00458 }
00459 pathset_t(hall, succ, z, z);
00460
00461
00462
00463
00464
00465
00466
00467
00468 if (hall[z].d < ups.sumup(hall[y].bounds, hall[z].bounds - 1))
00469 return ES_FAILED;
00470
00471
00472
00473
00474
00475
00476 if (hall[x0].h > x0) {
00477 int w = pathmax_h(hall, hall[x0].h);
00478 int m = hall[w].bounds;
00479 GECODE_ME_CHECK(x[mu[i]].gq(home, m));
00480 pathset_h(hall, x0, w, w);
00481 }
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 if (hall[z].d == ups.sumup(hall[y].bounds, hall[z].bounds - 1)) {
00500
00501
00502
00503
00504 int predj = j - 1;
00505 pathset_h(hall, hall[y].h, predj, y);
00506 hall[y].h = predj;
00507 }
00508 }
00509
00510
00511
00512
00513 for (int i = 0; i < rightmost; i++) {
00514 hall[i].h = hall[i].t = i+1;
00515 hall[i].d = ups.sumup(hall[i].bounds, hall[i+1].bounds - 1);
00516 }
00517
00518 for (int i = n; i--; ) {
00519
00520 int x0 = rank[nu[i]].max;
00521 int pred = x0 - 1;
00522 int y = rank[nu[i]].min;
00523 int z = pathmin_t(hall, pred);
00524 int j = hall[z].t;
00525
00526
00527 if (--hall[z].d == 0) {
00528 hall[z].t = z - 1;
00529 z = pathmin_t(hall, hall[z].t);
00530 hall[z].t = j;
00531 }
00532 pathset_t(hall, pred, z, z);
00533
00534
00535 if (hall[z].d < ups.sumup(hall[z].bounds,hall[y].bounds-1))
00536 return ES_FAILED;
00537
00538
00539
00540
00541
00542
00543 if (hall[x0].h < x0) {
00544 int w = pathmin_h(hall, hall[x0].h);
00545 int m = hall[w].bounds - 1;
00546 GECODE_ME_CHECK(x[nu[i]].lq(home, m));
00547 pathset_h(hall, x0, w, w);
00548 }
00549
00550
00551 if (hall[z].d == ups.sumup(hall[z].bounds, hall[y].bounds - 1)) {
00552
00553 pathset_h(hall, hall[y].h, j+1, y);
00554 hall[y].h = j+1;
00555 }
00556 }
00557 return ES_OK;
00558 }
00559
00560 template<class Card>
00561 ExecStatus
00562 Bnd<Card>::pruneCards(Space& home) {
00563
00564
00565
00566
00567 int n_z = 0;
00568 for (int i=k.size(); i--;)
00569 if (k[i].max() == 0)
00570 n_z++;
00571
00572 if (n_z > 0) {
00573 Region r;
00574 int* z = r.alloc<int>(n_z);
00575 n_z = 0;
00576 int n_k = 0;
00577 for (int i=0; i<k.size(); i++)
00578 if (k[i].max() == 0) {
00579 z[n_z++] = k[i].card();
00580 } else {
00581 k[n_k++] = k[i];
00582 }
00583 k.size(n_k);
00584 Support::quicksort(z,n_z);
00585 for (int i=x.size(); i--;) {
00586 Iter::Values::Array zi(z,n_z);
00587 GECODE_ME_CHECK(x[i].minus_v(home,zi,false));
00588 }
00589 lps.reinit(); ups.reinit();
00590 }
00591 return ES_OK;
00592 }
00593
00594 template<class Card>
00595 ExecStatus
00596 Bnd<Card>::propagate(Space& home, const ModEventDelta& med) {
00597 if (IntView::me(med) == ME_INT_VAL) {
00598 GECODE_ES_CHECK(prop_val<Card>(home,*this,y,k));
00599 return home.ES_NOFIX_PARTIAL(*this,IntView::med(ME_INT_BND));
00600 }
00601
00602 if (Card::propagate)
00603 GECODE_ES_CHECK(pruneCards(home));
00604
00605 Region r;
00606 int* count = r.alloc<int>(k.size());
00607
00608 for (int i = k.size(); i--; )
00609 count[i] = 0;
00610 bool all_assigned = true;
00611 int noa = 0;
00612 for (int i = x.size(); i--; ) {
00613 if (x[i].assigned()) {
00614 noa++;
00615 int idx;
00616
00617
00618 if (!lookupValue(k,x[i].val(),idx))
00619 return ES_FAILED;
00620 count[idx]++;
00621 } else {
00622 all_assigned = false;
00623
00624
00625 if (!Card::propagate)
00626 break;
00627 }
00628 }
00629
00630 if (Card::propagate) {
00631
00632 if (noa > 0)
00633 for (int i = k.size(); i--; )
00634 if (!k[i].assigned()) {
00635 GECODE_ME_CHECK(k[i].lq(home, x.size() - (noa - count[i])));
00636 GECODE_ME_CHECK(k[i].gq(home, count[i]));
00637 }
00638
00639 if (!card_consistent<Card>(x, k))
00640 return ES_FAILED;
00641
00642 GECODE_ES_CHECK(prop_card<Card>(home, x, k));
00643
00644
00645
00646 for (int i = k.size(); i--; )
00647 count[i] = 0;
00648 all_assigned = true;
00649 for (int i = x.size(); i--; ) {
00650 if (x[i].assigned()) {
00651 int idx;
00652
00653
00654 if (!lookupValue(k,x[i].val(),idx))
00655 return ES_FAILED;
00656 count[idx]++;
00657 } else {
00658
00659
00660 all_assigned = false;
00661 break;
00662 }
00663 }
00664 }
00665
00666 if (all_assigned) {
00667 for (int i = k.size(); i--; )
00668 GECODE_ME_CHECK(k[i].eq(home, count[i]));
00669 return home.ES_SUBSUMED(*this);
00670 }
00671
00672 if (Card::propagate)
00673 GECODE_ES_CHECK(pruneCards(home));
00674
00675 int n = x.size();
00676
00677 int* mu = r.alloc<int>(n);
00678 int* nu = r.alloc<int>(n);
00679
00680 for (int i = n; i--; )
00681 nu[i] = mu[i] = i;
00682
00683
00684 MaxInc<IntView> max_inc(x);
00685 Support::quicksort<int, MaxInc<IntView> >(mu, n, max_inc);
00686
00687
00688 MinInc<IntView> min_inc(x);
00689 Support::quicksort<int, MinInc<IntView> >(nu, n, min_inc);
00690
00691
00692 MinIdx<Card> min_idx;
00693 Support::quicksort<Card, MinIdx<Card> >(&k[0], k.size(), min_idx);
00694
00695 if (!lps) {
00696 assert(!ups);
00697 lps.init(home, k, false);
00698 ups.init(home, k, true);
00699 } else if (Card::propagate) {
00700
00701
00702 if (lps.check_update_min(k))
00703 lps.init(home, k, false);
00704 if (ups.check_update_max(k))
00705 ups.init(home, k, true);
00706 }
00707
00708
00709
00710 assert(lps.minValue() <= x[nu[0]].min());
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 HallInfo* hall = r.alloc<HallInfo>(2 * n + 2);
00723 Rank* rank = r.alloc<Rank>(n);
00724
00725 int nb = 0;
00726
00727 int min = x[nu[0]].min();
00728 int max = x[mu[0]].max() + 1;
00729 int last = lps.firstValue + 1;
00730 hall[0].bounds = last;
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 {
00741 int i = 0;
00742 int j = 0;
00743 while (true) {
00744 if (i < n && min < max) {
00745 if (min != last) {
00746 last = min;
00747 hall[++nb].bounds = last;
00748 }
00749 rank[nu[i]].min = nb;
00750 if (++i < n)
00751 min = x[nu[i]].min();
00752 } else {
00753 if (max != last) {
00754 last = max;
00755 hall[++nb].bounds = last;
00756 }
00757 rank[mu[j]].max = nb;
00758 if (++j == n)
00759 break;
00760 max = x[mu[j]].max() + 1;
00761 }
00762 }
00763 }
00764
00765 int rightmost = nb + 1;
00766 hall[rightmost].bounds = ups.lastValue + 1 ;
00767
00768 if (Card::propagate) {
00769 skip_lbc = true;
00770 for (int i = k.size(); i--; )
00771 if (k[i].min() != 0) {
00772 skip_lbc = false;
00773 break;
00774 }
00775 }
00776
00777 if (!card_fixed && !skip_lbc)
00778 GECODE_ES_CHECK((lbc(home, nb, hall, rank, mu, nu)));
00779
00780 GECODE_ES_CHECK((ubc(home, nb, hall, rank, mu, nu)));
00781
00782 if (Card::propagate)
00783 GECODE_ES_CHECK(prop_card<Card>(home, x, k));
00784
00785 for (int i = k.size(); i--; )
00786 count[i] = 0;
00787 for (int i = x.size(); i--; )
00788 if (x[i].assigned()) {
00789 int idx;
00790 if (!lookupValue(k,x[i].val(),idx))
00791 return ES_FAILED;
00792 count[idx]++;
00793 } else {
00794
00795
00796 return ES_NOFIX;
00797 }
00798
00799 for (int i = k.size(); i--; )
00800 GECODE_ME_CHECK(k[i].eq(home, count[i]));
00801
00802 return home.ES_SUBSUMED(*this);
00803 }
00804
00805
00806 template<class Card>
00807 ExecStatus
00808 Bnd<Card>::post(Home home,
00809 ViewArray<IntView>& x, ViewArray<Card>& k) {
00810 bool cardfix = true;
00811 for (int i=k.size(); i--; )
00812 if (!k[i].assigned()) {
00813 cardfix = false; break;
00814 }
00815 bool nolbc = true;
00816 for (int i=k.size(); i--; )
00817 if (k[i].min() != 0) {
00818 nolbc = false; break;
00819 }
00820
00821 GECODE_ES_CHECK(postSideConstraints<Card>(home, x, k));
00822
00823 if (isDistinct<Card>(x,k))
00824 return Distinct::Bnd<IntView>::post(home,x);
00825
00826 (void) new (home) Bnd<Card>(home,x,k,cardfix,nolbc);
00827 return ES_OK;
00828 }
00829
00830 }}}
00831
00832