00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 namespace Gecode { namespace Int { namespace GCC {
00023
00025 template <class View, class Card, bool isView, bool shared>
00026 inline ExecStatus
00027 prop_bnd(Space* home, ViewArray<View>& x, ViewArray<Card>& k,
00028 PartialSum<Card>*& lps, PartialSum<Card>*& ups,
00029 bool card_fixed, bool card_all, bool nolbc){
00030
00031 bool all_assigned = true;
00032 bool mod = false;
00033 int smin = 0;
00034 int smax = 0;
00035
00036 if (isView) {
00037
00038
00039
00040
00041 int m = k.size();
00042 bool locut = k[0].max() == 0;
00043 bool hicut = k[m - 1].max() == 0;
00044
00045 if (locut) {
00046 int low = k[0].card();
00047 for (int i = 0; i < x.size(); i++) {
00048 ModEvent me = x[i].gr(home, low);
00049 GECODE_ME_CHECK(me);
00050 mod |= me_modified(me) && (x[i].min() != low + 1);
00051 mod |= shared && me_modified(me);
00052 }
00053 }
00054 if (hicut) {
00055 int hi = k[m - 1].card();
00056 for (int i = 0; i < x.size(); i++) {
00057 ModEvent me = x[i].le(home, hi);
00058 GECODE_ME_CHECK(me);
00059 mod |= me_modified(me) && (x[i].max() != hi - 1);
00060 mod |= shared && me_modified(me);
00061 }
00062 }
00063
00064 if (locut || hicut) {
00065 int cmin = k[0].card();
00066 int cmax = k[m - 1].card();
00067 if (k[0].max() == 0) {
00068 cmin = k[1].card();
00069 }
00070 if (k[m - 1].max() == 0) {
00071 cmax = k[m - 2].card();
00072 }
00073 reduce_card<Card>(cmin, cmax, k);
00074
00075 if (lps != NULL) {
00076 delete lps; lps = NULL;
00077 assert(ups != NULL);
00078 delete ups; ups = NULL;
00079 }
00080 }
00081 }
00082
00083 GECODE_AUTOARRAY(int, count, k.size());
00084 for (int i = k.size(); i--; ) {
00085 count[i] = 0;
00086 }
00087
00088 int noa = 0;
00089 int single = 0;
00090 int xlb = 0;
00091 int xub = 0;
00092
00093 for (int i = x.size(); i--; ) {
00094 bool b = x[i].assigned();
00095 xlb += x[i].min();
00096 xub += x[i].max();
00097 all_assigned &= b;
00098 if (b) {
00099 noa++;
00100 int idx = lookupValue(k,x[i].val());
00101
00102
00103 if (idx == -1) {
00104 return ES_FAILED;
00105 }
00106 count[idx]++;
00107 } else {
00108 single = i;
00109 }
00110 }
00111
00112 if (isView) {
00113
00114 if (noa > 0) {
00115 int n = x.size();
00116 int ks = k.size();
00117
00118 for (int i = ks; i--; ) {
00119 if (!k[i].assigned()) {
00120 int ub = n - (noa - count[i]);
00121 int lb = count[i];
00122 ModEvent melq = k[i].lq(home, ub);
00123 GECODE_ME_CHECK(melq);
00124 mod |= me_modified(melq) && (k[i].max() != ub);
00125 mod |= shared && me_modified(melq);
00126
00127 ModEvent megq = k[i].gq(home, lb);
00128 GECODE_ME_CHECK(megq);
00129 mod |= me_modified(megq) && (k[i].min() != lb);
00130 mod |= shared && me_modified(megq);
00131 }
00132 }
00133 }
00134
00135 if (!card_consistent<View, Card>(smin, smax, x, k, card_all)) {
00136 return ES_FAILED;
00137 }
00138
00139
00140 GECODE_ES_CHECK((prop_card<View, Card, shared>(home, x, k, mod)));
00141
00142
00143 int smax = 0;
00144 int smin = 0;
00145 int total_min = 0;
00146 int total_max = 0;
00147 for (int i = k.size(); i--; ) {
00148 smax += k[i].max();
00149 total_min += k[i].card() * k[i].min();
00150 total_max += k[i].card() * k[i].max();
00151 }
00152 int xsmax = x.size() - smax;
00153 int xsmin = x.size() - smin;
00154 smax = 0;
00155 smin = 0;
00156 bool card_ass = true;
00157 for (int i = k.size(); i--; ) {
00158 int lb = xsmax + k[i].max();
00159 int ub = xsmin + k[i].min();
00160 ModEvent me = k[i].gq(home, lb);
00161 GECODE_ME_CHECK(me);
00162 mod |= me_modified(me) && (k[i].min() != lb);
00163 mod |= shared && me_modified(me);
00164 smax += k[i].max();
00165
00166 me = k[i].lq(home, ub);
00167 GECODE_ME_CHECK(me);
00168 mod |= me_modified(me) && (k[i].max() != ub);
00169 mod |= shared && me_modified(me);
00170 card_ass &= k[i].assigned();
00171 }
00172 if (card_ass) {
00173 if (smax < x.size() || smax > x.size()) {
00174 return ES_FAILED;
00175 }
00176
00177
00178 for (int i = x.size(); i--; ) {
00179 if (!x[i].assigned()) {
00180 int xmin = xub - x[i].max();
00181 int xgq = total_max - xmin;
00182
00183 int xmax = xlb - x[i].min();
00184 int xlq = total_max - xmax;
00185
00186 ModEvent me = x[i].gq(home, xgq);
00187 GECODE_ME_CHECK(me);
00188 mod |= me_modified(me) && (x[i].min() != xgq);
00189 mod |= shared && me_modified(me);
00190
00191 me = x[i].lq(home, xlq);
00192 GECODE_ME_CHECK(me);
00193 mod |= me_modified(me) && (x[i].max() != xlq);
00194 mod |= shared && me_modified(me);
00195 }
00196 }
00197 }
00198 }
00199
00200 for (int i = k.size(); i--; ) {
00201 count[i] = 0;
00202 }
00203
00204 all_assigned = true;
00205 noa = 0;
00206 single = 0;
00207
00208 for (int i = x.size(); i--; ) {
00209 bool b = x[i].assigned();
00210 xlb += x[i].min();
00211 xub += x[i].max();
00212 all_assigned &= b;
00213 if (b) {
00214 noa++;
00215 int idx = lookupValue(k,x[i].val());
00216
00217
00218 if (idx == -1) {
00219 return ES_FAILED;
00220 }
00221 count[idx]++;
00222 } else {
00223 single = i;
00224 }
00225 }
00226
00227 if (all_assigned) {
00228 for (int i = k.size(); i--; ) {
00229 int ci = count[i];
00230 if (! (k[i].min() <= ci && ci <= k[i].max())) {
00231 return ES_FAILED;
00232 } else {
00233 if (isView) {
00234 if (!k[i].assigned()) {
00235 ModEvent me = k[i].eq(home, ci);
00236 GECODE_ME_CHECK(me);
00237 mod |= k[i].assigned();
00238 }
00239 all_assigned &= k[i].assigned();
00240 }
00241 }
00242 }
00243 if (all_assigned) {
00244 return ES_SUBSUMED;
00245 }
00246 }
00247
00248 if (isView) {
00249
00250 int m = k.size();
00251 bool locut = k[0].max() == 0;
00252 bool hicut = k[m - 1].max() == 0;
00253
00254 if (locut) {
00255 int low = k[0].card();
00256 for (int i = 0; i < x.size(); i++) {
00257 ModEvent me = x[i].gr(home, low);
00258 GECODE_ME_CHECK(me);
00259 mod |= me_modified(me) && (x[i].min() != low + 1);
00260 mod |= shared && me_modified(me);
00261 }
00262 }
00263 if (hicut) {
00264 int hi = k[m - 1].card();
00265 for (int i = 0; i < x.size(); i++) {
00266 ModEvent me = x[i].le(home, hi);
00267 GECODE_ME_CHECK(me);
00268 mod |= me_modified(me) && (x[i].max() != hi - 1);
00269 mod |= shared && me_modified(me);
00270 }
00271 }
00272
00273 if (locut || hicut) {
00274 int cmin = k[0].card();
00275 int cmax = k[m - 1].card();
00276 if (k[0].max() == 0) {
00277 cmin = k[1].card();
00278 }
00279 if (k[m - 1].max() == 0) {
00280 cmax = k[m - 2].card();
00281 }
00282 reduce_card<Card>(cmin, cmax, k);
00283
00284 if (lps != NULL) {
00285 delete lps;
00286 lps = NULL;
00287 assert(ups != NULL);
00288 delete ups;
00289 ups = NULL;
00290 }
00291 }
00292 }
00293
00294 ExecStatus es_ubc = ES_FIX;
00295 ExecStatus es_lbc = ES_FIX;
00296 int n = x.size();
00297
00298 GECODE_AUTOARRAY(int, mu, n);
00299 GECODE_AUTOARRAY(int, nu, n);
00300
00301 for (int i = n; i--; ) {
00302 nu[i] = i;
00303 mu[i] = i;
00304 }
00305
00306 MaxInc<View> max_inc(x);
00307 Support::quicksort<int, MaxInc<View> >(mu, n, max_inc);
00308
00309
00310 MinInc<View> min_inc(x);
00311 Support::quicksort<int, MinInc<View> >(nu, n, min_inc);
00312
00313 if (isView) {
00314
00315 assert(k[0].card() == x[nu[0]].min());
00316 }
00317
00318
00319 int cur_minx = x[nu[0]].min();
00320 if (lps == NULL) {
00321 assert (ups == NULL);
00322 lps = new PartialSum<Card>(cur_minx, k.size(), k, false);
00323 ups = new PartialSum<Card>(cur_minx, k.size(), k, true);
00324 }
00325
00326 if (isView) {
00327
00328
00329 if (lps->check_update_min(k)) {
00330 delete lps;
00331 lps = new PartialSum<Card>(cur_minx, k.size(), k, false);
00332 }
00333
00334 if (ups->check_update_max(k)) {
00335 delete ups;
00336 ups = new PartialSum<Card>(cur_minx, k.size(), k, true);
00337 }
00338 }
00339
00340
00341 assert(lps->minValue() == ups->minValue());
00342 assert(lps->maxValue() == ups->maxValue());
00343
00344 bool minima_equal = lps->minValue() == ups->minValue();
00345 bool maxima_equal = lps->maxValue() == ups->maxValue();
00346
00347 if (!minima_equal || !maxima_equal ) {
00348 delete lps;
00349 lps = new PartialSum<Card>(cur_minx, k.size(), k, false);
00350 delete ups;
00351 ups = new PartialSum<Card>(cur_minx, k.size(), k, true);
00352 }
00353
00354
00355
00356 assert(lps->minValue() <= x[nu[0]].min());
00357
00358
00359 assert(x[mu[x.size() - 1]].max() <= ups->maxValue());
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 GECODE_AUTOARRAY(HallInfo, hall, (2 * n + 2));
00370 GECODE_AUTOARRAY(Rank, rank, n);
00371
00372 int nb = 0;
00373
00374 int min = x[nu[0]].min();
00375 int max = x[mu[0]].max() + 1;
00376 int last = lps->firstValue + 1;
00377 hall[0].bounds = last;
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 {
00388 int i = 0;
00389 int j = 0;
00390 while (true) {
00391 if (i < n && min < max) {
00392 if (min != last) {
00393 last = min;
00394 hall[++nb].bounds = last;
00395 }
00396 rank[nu[i]].min = nb;
00397 if (++i < n) {
00398 min = x[nu[i]].min();
00399 }
00400 } else {
00401 if (max != last) {
00402 last = max;
00403 hall[++nb].bounds = last;
00404 }
00405 rank[mu[j]].max = nb;
00406 if (++j == n) {
00407 break;
00408 }
00409 max = x[mu[j]].max() + 1;
00410 }
00411 }
00412 }
00413
00414 int rightmost = nb + 1;
00415 hall[rightmost].bounds = ups->lastValue + 1 ;
00416
00417 nolbc = true;
00418 for (int i = k.size(); i--; ) {
00419 nolbc &= (k[i].min() == 0);
00420 }
00421
00422 if (!card_fixed && !nolbc) {
00423 es_lbc = lbc<View, Card, shared>(home, x, nb, hall, rank,lps, mu, nu);
00424 if (es_lbc == ES_FAILED || es_lbc == ES_SUBSUMED) {
00425 return es_lbc;
00426 }
00427 mod |= (es_lbc == ES_NOFIX);
00428 }
00429
00430 es_ubc = ubc<View, Card, shared>(home, x, nb, hall, rank, ups, mu, nu);
00431 if (es_ubc == ES_FAILED || es_ubc == ES_SUBSUMED) {
00432 return es_ubc;
00433 }
00434 mod |= (es_ubc == ES_NOFIX);
00435
00436 if (isView) {
00437 GECODE_ES_CHECK((prop_card<View, Card, shared>(home, x, k, mod)));
00438 }
00439
00440 all_assigned = true;
00441 noa = 0;
00442 single = 0;
00443 for (int i = k.size(); i--; ) {
00444 count[i] = 0;
00445 }
00446
00447 for (int i = x.size(); i--; ) {
00448 bool b = x[i].assigned();
00449 all_assigned &= b;
00450 if (b) {
00451 noa++;
00452 int idx = lookupValue(k,x[i].val());
00453 count[idx]++;
00454 } else {
00455 single = i;
00456 }
00457 }
00458
00459 if (all_assigned) {
00460 for (int i = k.size(); i--; ) {
00461 int ci = count[i];
00462 if (! (k[i].min() <= ci && ci <= k[i].max())) {
00463 return ES_FAILED;
00464 } else {
00465 if (isView) {
00466 if (!k[i].assigned()) {
00467 ModEvent me = k[i].eq(home, ci);
00468 GECODE_ME_CHECK(me);
00469 mod |= k[i].assigned();
00470 }
00471 all_assigned &= k[i].assigned();
00472 }
00473 }
00474 }
00475 if (all_assigned) {
00476 return ES_SUBSUMED;
00477 }
00478 }
00479
00480 return mod ? ES_NOFIX : ES_FIX;
00481 }
00482
00483
00484 template <class View, class Card, bool isView, bool shared>
00485 inline
00486 BndImp<View, Card, isView, shared>::
00487 BndImp(Space* home, ViewArray<View>& x0, ViewArray<Card>& k0,
00488 bool cf, bool all, bool nolbc) :
00489 Propagator(home, true), x(x0), k(k0), lps(NULL), ups(NULL),
00490 card_fixed(cf), card_all(all), skip_lbc(nolbc) {
00491 x.subscribe(home, this, PC_INT_BND);
00492 k.subscribe(home, this, PC_INT_BND);
00493 }
00494
00495
00496 template <class View, class Card, bool isView, bool shared>
00497 forceinline
00498 BndImp<View, Card, isView, shared>::
00499 BndImp(Space* home, bool share, BndImp<View, Card, isView, shared>& p)
00500 : Propagator(home, share, p), lps(NULL), ups(NULL),
00501 card_fixed(p.card_fixed), card_all(p.card_all),
00502 skip_lbc(p.skip_lbc) {
00503 x.update(home, share, p.x);
00504 k.update(home, share, p.k);
00505 }
00506
00507 template <class View, class Card, bool isView, bool shared>
00508 size_t
00509 BndImp<View, Card, isView, shared>::dispose(Space* home){
00510 if (!home->failed()) {
00511 x.cancel(home,this, PC_INT_BND);
00512 k.cancel(home,this, PC_INT_BND);
00513 }
00514 if (lps != NULL) {
00515 delete lps;
00516 }
00517 if (ups != NULL) {
00518 delete ups;
00519 }
00520 (void) Propagator::dispose(home);
00521 return sizeof(*this);
00522 }
00523
00524 template <class View, class Card, bool isView, bool shared>
00525 Actor*
00526 BndImp<View, Card, isView, shared>::copy(Space* home, bool share){
00527 return new (home) BndImp<View, Card, isView, shared>
00528 (home, share, *this);
00529 }
00530
00531 template <class View, class Card, bool isView, bool shared>
00532 PropCost
00533 BndImp<View, Card, isView, shared>::cost (void) const {
00534
00535
00536
00537
00538
00539
00540
00541 PropCost pc = PC_LINEAR_HI;
00542 return cost_hi(x.size(),pc);
00543 }
00544
00545 template <class View, class Card, bool isView, bool shared>
00546 ExecStatus
00547 BndImp<View, Card, isView, shared>::propagate(Space* home) {
00548 return prop_bnd<View, Card, isView, shared>
00549 (home, x, k, lps, ups, card_fixed, card_all, skip_lbc);
00550 }
00551
00560 template <class View1, class View2>
00561 class SharingTest {
00562 public:
00567 static bool shared(Space* home, ViewArray<View1>& x0,
00568 ViewArray<View2>& k0) {
00569 ViewArray<View1> xc(home, x0.size()+k0.size());
00570 for (int i = 0; i < x0.size(); i++) {
00571 xc[i] = x0[i];
00572 }
00573 for (int i = x0.size(); i < x0.size()+k0.size(); i++) {
00574 xc[i] = k0[i - x0.size()].intview();
00575 }
00576 return xc.shared();
00577 }
00578 };
00579
00584 template <>
00585 class SharingTest<IntView,OccurBndsView> {
00586 public:
00588 static bool shared(Space* home,
00589 ViewArray<IntView>& xs, ViewArray<OccurBndsView>&) {
00590 return xs.shared();
00591 }
00592 };
00593
00594 template <class View, class Card, bool isView>
00595 ExecStatus
00596 Bnd<View, Card, isView>::post(Space* home,
00597 ViewArray<View>& x0,
00598 ViewArray<Card>& k0,
00599 bool all) {
00600 bool cardfix = true;
00601 bool nolbc = true;
00602 for (int i = k0.size(); i--; ) {
00603 cardfix &= k0[i].assigned();
00604 nolbc &= (k0[i].min() == 0);
00605 }
00606
00607 if (SharingTest<View,Card>::shared(home,x0,k0)) {
00608 new (home) BndImp<View, Card, isView, true>
00609 (home, x0, k0, cardfix, all, nolbc);
00610 } else {
00611 new (home) BndImp<View, Card, isView, false>
00612 (home, x0, k0, cardfix, all, nolbc);
00613 }
00614 return ES_OK;
00615 }
00616
00617 template <class View, class Card, bool isView, bool shared>
00618 void
00619 BndImp<View, Card, isView, shared>::flush(void){
00620 delete lps;
00621 lps = NULL;
00622 delete ups;
00623 ups = NULL;
00624 }
00625
00626 }}}
00627
00628
00629