this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * 6 * Copyright: 7 * Christian Schulte, 2004 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34namespace Gecode { namespace Int { namespace Rel { 35 36 /* 37 * Binary value propagation equality 38 * 39 */ 40 41 template<class View0, class View1> 42 forceinline 43 EqVal<View0,View1>::EqVal(Home home, View0 x0, View1 x1) 44 : MixBinaryPropagator<View0,PC_INT_VAL,View1,PC_INT_VAL>(home,x0,x1) {} 45 46 template<class View0, class View1> 47 ExecStatus 48 EqVal<View0,View1>::post(Home home, View0 x0, View1 x1){ 49 if (x0.assigned()) { 50 GECODE_ME_CHECK(x1.eq(home,x0.val())); 51 } else if (x1.assigned()) { 52 GECODE_ME_CHECK(x0.eq(home,x1.val())); 53 } else if (x0 != x1) { 54 (void) new (home) EqVal<View0,View1>(home,x0,x1); 55 } 56 return ES_OK; 57 } 58 59 template<class View0, class View1> 60 forceinline 61 EqVal<View0,View1>::EqVal(Space& home, EqVal<View0,View1>& p) 62 : MixBinaryPropagator<View0,PC_INT_VAL,View1,PC_INT_VAL>(home,p) {} 63 64 template<class View0, class View1> 65 forceinline 66 EqVal<View0,View1>::EqVal(Space& home, Propagator& p, 67 View0 x0, View1 x1) 68 : MixBinaryPropagator<View0,PC_INT_VAL,View1,PC_INT_VAL>(home,p, 69 x0,x1) {} 70 71 template<class View0, class View1> 72 Actor* 73 EqVal<View0,View1>::copy(Space& home) { 74 return new (home) EqVal<View0,View1>(home,*this); 75 } 76 77 template<class View0, class View1> 78 PropCost 79 EqVal<View0,View1>::cost(const Space&, const ModEventDelta&) const { 80 return PropCost::unary(PropCost::LO); 81 } 82 83 template<class View0, class View1> 84 ExecStatus 85 EqVal<View0,View1>::propagate(Space& home, const ModEventDelta&) { 86 if (x0.assigned()) { 87 GECODE_ME_CHECK(x1.eq(home,x0.val())); 88 } else { 89 assert(x1.assigned()); 90 GECODE_ME_CHECK(x0.eq(home,x1.val())); 91 } 92 return home.ES_SUBSUMED(*this); 93 } 94 95 96 /* 97 * Binary bounds consistent equality 98 * 99 */ 100 101 template<class View0, class View1> 102 forceinline 103 EqBnd<View0,View1>::EqBnd(Home home, View0 x0, View1 x1) 104 : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,x0,x1) {} 105 106 template<class View0, class View1> 107 ExecStatus 108 EqBnd<View0,View1>::post(Home home, View0 x0, View1 x1){ 109 if (x0.assigned()) { 110 GECODE_ME_CHECK(x1.eq(home,x0.val())); 111 } else if (x1.assigned()) { 112 GECODE_ME_CHECK(x0.eq(home,x1.val())); 113 } else if (x0 != x1) { 114 GECODE_ME_CHECK(x0.lq(home,x1.max())); 115 GECODE_ME_CHECK(x1.lq(home,x0.max())); 116 GECODE_ME_CHECK(x0.gq(home,x1.min())); 117 GECODE_ME_CHECK(x1.gq(home,x0.min())); 118 (void) new (home) EqBnd<View0,View1>(home,x0,x1); 119 } 120 return ES_OK; 121 } 122 123 template<class View0, class View1> 124 forceinline 125 EqBnd<View0,View1>::EqBnd(Space& home, EqBnd<View0,View1>& p) 126 : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,p) {} 127 128 template<class View0, class View1> 129 forceinline 130 EqBnd<View0,View1>::EqBnd(Space& home, Propagator& p, 131 View0 x0, View1 x1) 132 : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,p, 133 x0,x1) {} 134 135 template<class View0, class View1> 136 Actor* 137 EqBnd<View0,View1>::copy(Space& home) { 138 return new (home) EqBnd<View0,View1>(home,*this); 139 } 140 141 template<class View0, class View1> 142 ExecStatus 143 EqBnd<View0,View1>::propagate(Space& home, const ModEventDelta&) { 144 if (x0.assigned()) { 145 GECODE_ME_CHECK(x1.eq(home,x0.val())); 146 } else if (x1.assigned()) { 147 GECODE_ME_CHECK(x0.eq(home,x1.val())); 148 } else { 149 do { 150 GECODE_ME_CHECK(x0.gq(home,x1.min())); 151 GECODE_ME_CHECK(x1.gq(home,x0.min())); 152 } while (x0.min() != x1.min()); 153 do { 154 GECODE_ME_CHECK(x0.lq(home,x1.max())); 155 GECODE_ME_CHECK(x1.lq(home,x0.max())); 156 } while (x0.max() != x1.max()); 157 if (!x0.assigned()) 158 return ES_FIX; 159 } 160 assert(x0.assigned() && x1.assigned()); 161 return home.ES_SUBSUMED(*this); 162 } 163 164 /* 165 * Binary domain consistent equality 166 * 167 */ 168 169 template<class View0, class View1> 170 forceinline 171 EqDom<View0,View1>::EqDom(Home home, View0 x0, View1 x1) 172 : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,x0,x1) {} 173 174 template<class View0, class View1> 175 ExecStatus 176 EqDom<View0,View1>::post(Home home, View0 x0, View1 x1){ 177 if (x0.assigned()) { 178 GECODE_ME_CHECK(x1.eq(home,x0.val())); 179 } else if (x1.assigned()) { 180 GECODE_ME_CHECK(x0.eq(home,x1.val())); 181 } else if (x0 != x1) { 182 GECODE_ME_CHECK(x0.lq(home,x1.max())); 183 GECODE_ME_CHECK(x1.lq(home,x0.max())); 184 GECODE_ME_CHECK(x0.gq(home,x1.min())); 185 GECODE_ME_CHECK(x1.gq(home,x0.min())); 186 (void) new (home) EqDom<View0,View1>(home,x0,x1); 187 } 188 return ES_OK; 189 } 190 191 192 template<class View0, class View1> 193 forceinline 194 EqDom<View0,View1>::EqDom(Space& home, EqDom<View0,View1>& p) 195 : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,p) {} 196 197 template<class View0, class View1> 198 forceinline 199 EqDom<View0,View1>::EqDom(Space& home, Propagator& p, 200 View0 x0, View1 x1) 201 : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,p, 202 x0,x1) {} 203 204 template<class View0, class View1> 205 Actor* 206 EqDom<View0,View1>::copy(Space& home) { 207 return new (home) EqDom<View0,View1>(home,*this); 208 } 209 210 template<class View0, class View1> 211 PropCost 212 EqDom<View0,View1>::cost(const Space&, const ModEventDelta& med) const { 213 if ((View0::me(med) == ME_INT_VAL) || (View1::me(med) == ME_INT_VAL)) 214 return PropCost::unary(PropCost::LO); 215 else if ((View0::me(med) == ME_INT_DOM) || (View1::me(med) == ME_INT_DOM)) 216 return PropCost::binary(PropCost::LO); 217 else 218 return PropCost::binary(PropCost::HI); 219 } 220 221 template<class View0, class View1> 222 ExecStatus 223 EqDom<View0,View1>::propagate(Space& home, const ModEventDelta& med) { 224 if (x0.assigned()) { 225 GECODE_ME_CHECK(x1.eq(home,x0.val())); 226 return home.ES_SUBSUMED(*this); 227 } 228 if (x1.assigned()) { 229 GECODE_ME_CHECK(x0.eq(home,x1.val())); 230 return home.ES_SUBSUMED(*this); 231 } 232 if ((View0::me(med) != ME_INT_DOM) && (View1::me(med) != ME_INT_DOM)) { 233 do { 234 GECODE_ME_CHECK(x0.gq(home,x1.min())); 235 GECODE_ME_CHECK(x1.gq(home,x0.min())); 236 } while (x0.min() != x1.min()); 237 do { 238 GECODE_ME_CHECK(x0.lq(home,x1.max())); 239 GECODE_ME_CHECK(x1.lq(home,x0.max())); 240 } while (x0.max() != x1.max()); 241 if (x0.assigned()) 242 return home.ES_SUBSUMED(*this); 243 if (x0.range() && x1.range()) 244 return ES_FIX; 245 return home.ES_FIX_PARTIAL(*this,View0::med(ME_INT_DOM)); 246 } 247 ViewRanges<View0> r0(x0); 248 GECODE_ME_CHECK(x1.inter_r(home,r0,shared(x0,x1))); 249 ViewRanges<View1> r1(x1); 250 GECODE_ME_CHECK(x0.narrow_r(home,r1,shared(x0,x1))); 251 if (x0.assigned()) 252 return home.ES_SUBSUMED(*this); 253 return ES_FIX; 254 } 255 256 257 258 /* 259 * Nary domain consistent equality 260 * 261 */ 262 263 template<class View> 264 forceinline 265 NaryEqDom<View>::NaryEqDom(Home home, ViewArray<View>& x) 266 : NaryPropagator<View,PC_INT_DOM>(home,x) {} 267 268 template<class View> 269 ExecStatus 270 NaryEqDom<View>::post(Home home, ViewArray<View>& x) { 271 x.unique(); 272 if (x.size() == 2) { 273 return EqDom<View,View>::post(home,x[0],x[1]); 274 } else if (x.size() > 2) { 275 int l = x[0].min(); 276 int u = x[0].max(); 277 for (int i=1; i<x.size(); i++) { 278 l = std::max(l,x[i].min()); 279 u = std::min(u,x[i].max()); 280 } 281 for (int i=0; i<x.size(); i++) { 282 GECODE_ME_CHECK(x[i].gq(home,l)); 283 GECODE_ME_CHECK(x[i].lq(home,u)); 284 } 285 (void) new (home) NaryEqDom<View>(home,x); 286 } 287 return ES_OK; 288 } 289 290 template<class View> 291 forceinline 292 NaryEqDom<View>::NaryEqDom(Space& home, NaryEqDom<View>& p) 293 : NaryPropagator<View,PC_INT_DOM>(home,p) {} 294 295 template<class View> 296 Actor* 297 NaryEqDom<View>::copy(Space& home) { 298 return new (home) NaryEqDom<View>(home,*this); 299 } 300 301 template<class View> 302 PropCost 303 NaryEqDom<View>::cost(const Space&, const ModEventDelta& med) const { 304 if (View::me(med) == ME_INT_VAL) 305 return PropCost::unary(PropCost::LO); 306 else 307 return PropCost::linear((View::me(med) == ME_INT_DOM) ? 308 PropCost::LO : PropCost::HI, x.size()); 309 } 310 311 template<class View> 312 ExecStatus 313 NaryEqDom<View>::propagate(Space& home, const ModEventDelta& med) { 314 assert(x.size() > 2); 315 316 ModEvent me = View::me(med); 317 if (me == ME_INT_VAL) { 318 // One of the variables is assigned 319 for (int i=0; ; i++) 320 if (x[i].assigned()) { 321 int n = x[i].val(); 322 x.move_lst(i); 323 for (int j=0; j<x.size(); j++) 324 GECODE_ME_CHECK(x[j].eq(home,n)); 325 return home.ES_SUBSUMED(*this); 326 } 327 GECODE_NEVER; 328 } 329 330 if (me == ME_INT_BND) { 331 { 332 // One of the mins has changed 333 int mn = x[0].min(); 334 restart_min: 335 for (int i=0; i<x.size(); i++) { 336 GECODE_ME_CHECK(x[i].gq(home,mn)); 337 if (mn < x[i].min()) { 338 mn = x[i].min(); 339 goto restart_min; 340 } 341 } 342 } 343 { 344 // One of the maxs has changed 345 int mx = x[0].max(); 346 restart_max: 347 for (int i=0; i<x.size(); i++) { 348 GECODE_ME_CHECK(x[i].lq(home,mx)); 349 if (mx > x[i].max()) { 350 mx = x[i].max(); 351 goto restart_max; 352 } 353 } 354 } 355 if (x[0].assigned()) 356 return home.ES_SUBSUMED(*this); 357 return home.ES_FIX_PARTIAL(*this,View::med(ME_INT_DOM)); 358 } 359 360 int n = x.size(); 361 362 Region re; 363 ViewRanges<View>* i_x = re.alloc<ViewRanges<View> >(n); 364 for (int i=0; i<n; i++) { 365 ViewRanges<View> i_xi(x[i]); 366 i_x[i] = i_xi; 367 } 368 Iter::Ranges::NaryInter r(re,i_x,n); 369 370 if (!r()) 371 return ES_FAILED; 372 ++r; 373 if (!r()) { 374 r.reset(); 375 for (int i=0; i<n; i++) { 376 GECODE_ME_CHECK(x[i].gq(home,r.min())); 377 GECODE_ME_CHECK(x[i].lq(home,r.max())); 378 } 379 } else { 380 for (int i=0; i<n; i++) { 381 r.reset(); 382 GECODE_ME_CHECK(x[i].narrow_r(home,r,false)); 383 } 384 } 385 return ES_FIX; 386 } 387 388 389 390 /* 391 * Nary bound consistent equality 392 * 393 */ 394 395 template<class View> 396 forceinline 397 NaryEqBnd<View>::NaryEqBnd(Home home, ViewArray<View>& x) 398 : NaryPropagator<View,PC_INT_BND>(home,x) {} 399 400 template<class View> 401 ExecStatus 402 NaryEqBnd<View>::post(Home home, ViewArray<View>& x) { 403 x.unique(); 404 if (x.size() == 2) { 405 return EqBnd<View,View>::post(home,x[0],x[1]); 406 } else if (x.size() > 2) { 407 int l = x[0].min(); 408 int u = x[0].max(); 409 for (int i=1; i<x.size(); i++) { 410 l = std::max(l,x[i].min()); 411 u = std::min(u,x[i].max()); 412 } 413 for (int i=0; i<x.size(); i++) { 414 GECODE_ME_CHECK(x[i].gq(home,l)); 415 GECODE_ME_CHECK(x[i].lq(home,u)); 416 } 417 (void) new (home) NaryEqBnd<View>(home,x); 418 } 419 return ES_OK; 420 } 421 422 template<class View> 423 forceinline 424 NaryEqBnd<View>::NaryEqBnd(Space& home, NaryEqBnd<View>& p) 425 : NaryPropagator<View,PC_INT_BND>(home,p) {} 426 427 template<class View> 428 Actor* 429 NaryEqBnd<View>::copy(Space& home) { 430 return new (home) NaryEqBnd<View>(home,*this); 431 } 432 433 template<class View> 434 PropCost 435 NaryEqBnd<View>::cost(const Space&, const ModEventDelta& med) const { 436 if (View::me(med) == ME_INT_VAL) 437 return PropCost::unary(PropCost::LO); 438 else 439 return PropCost::linear(PropCost::LO, x.size()); 440 } 441 442 template<class View> 443 ExecStatus 444 NaryEqBnd<View>::propagate(Space& home, const ModEventDelta& med) { 445 assert(x.size() > 2); 446 if (View::me(med) == ME_INT_VAL) { 447 // One of the variables is assigned 448 for (int i = 0; ; i++) 449 if (x[i].assigned()) { 450 int n = x[i].val(); 451 x.move_lst(i); 452 for (int j=0; j<x.size(); j++) 453 GECODE_ME_CHECK(x[j].eq(home,n)); 454 return home.ES_SUBSUMED(*this); 455 } 456 GECODE_NEVER; 457 } 458 459 int mn = x[0].min(); 460 restart_min: 461 for (int i=0; i<x.size(); i++) { 462 GECODE_ME_CHECK(x[i].gq(home,mn)); 463 if (mn < x[i].min()) { 464 mn = x[i].min(); 465 goto restart_min; 466 } 467 } 468 int mx = x[0].max(); 469 restart_max: 470 for (int i=0; i<x.size(); i++) { 471 GECODE_ME_CHECK(x[i].lq(home,mx)); 472 if (mx > x[i].max()) { 473 mx = x[i].max(); 474 goto restart_max; 475 } 476 } 477 return x[0].assigned() ? home.ES_SUBSUMED(*this) : ES_FIX; 478 } 479 480 481 482 /* 483 * Reified domain consistent equality 484 * 485 */ 486 487 template<class View, class CtrlView, ReifyMode rm> 488 forceinline 489 ReEqDom<View,CtrlView,rm>::ReEqDom(Home home, View x0, View x1, CtrlView b) 490 : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,x0,x1,b) {} 491 492 template<class View, class CtrlView, ReifyMode rm> 493 ExecStatus 494 ReEqDom<View,CtrlView,rm>::post(Home home, View x0, View x1, CtrlView b) { 495 if (b.one()) { 496 if (rm == RM_PMI) 497 return ES_OK; 498 return EqDom<View,View>::post(home,x0,x1); 499 } 500 if (b.zero()) { 501 if (rm == RM_IMP) 502 return ES_OK; 503 return Nq<View,View>::post(home,x0,x1); 504 } 505 if (x0 != x1) { 506 (void) new (home) ReEqDom(home,x0,x1,b); 507 } else if (rm != RM_IMP) { 508 GECODE_ME_CHECK(b.one(home)); 509 } 510 return ES_OK; 511 } 512 513 514 template<class View, class CtrlView, ReifyMode rm> 515 forceinline 516 ReEqDom<View,CtrlView,rm>::ReEqDom(Space& home, ReEqDom& p) 517 : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,p) {} 518 519 template<class View, class CtrlView, ReifyMode rm> 520 Actor* 521 ReEqDom<View,CtrlView,rm>::copy(Space& home) { 522 return new (home) ReEqDom<View,CtrlView,rm>(home,*this); 523 } 524 525 template<class View, class CtrlView, ReifyMode rm> 526 ExecStatus 527 ReEqDom<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { 528 if (b.one()) { 529 if (rm == RM_PMI) 530 return home.ES_SUBSUMED(*this); 531 GECODE_REWRITE(*this,(EqDom<View,View>::post(home(*this),x0,x1))); 532 } 533 if (b.zero()) { 534 if (rm == RM_IMP) 535 return home.ES_SUBSUMED(*this); 536 GECODE_REWRITE(*this,(Nq<View,View>::post(home(*this),x0,x1))); 537 } 538 switch (rtest_eq_dom(x0,x1)) { 539 case RT_TRUE: 540 if (rm != RM_IMP) 541 GECODE_ME_CHECK(b.one_none(home)); 542 break; 543 case RT_FALSE: 544 if (rm != RM_PMI) 545 GECODE_ME_CHECK(b.zero_none(home)); 546 break; 547 case RT_MAYBE: 548 return ES_FIX; 549 default: GECODE_NEVER; 550 } 551 return home.ES_SUBSUMED(*this); 552 } 553 554 555 556 /* 557 * Reified bounds consistent equality 558 * 559 */ 560 561 template<class View, class CtrlView, ReifyMode rm> 562 forceinline 563 ReEqBnd<View,CtrlView,rm>::ReEqBnd(Home home, View x0, View x1, CtrlView b) 564 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,x0,x1,b) {} 565 566 template<class View, class CtrlView, ReifyMode rm> 567 ExecStatus 568 ReEqBnd<View,CtrlView,rm>::post(Home home, View x0, View x1, CtrlView b){ 569 if (b.one()) { 570 if (rm == RM_PMI) 571 return ES_OK; 572 return EqBnd<View,View>::post(home,x0,x1); 573 } 574 if (b.zero()) { 575 if (rm == RM_IMP) 576 return ES_OK; 577 return Nq<View,View>::post(home,x0,x1); 578 } 579 if (x0 != x1) { 580 (void) new (home) ReEqBnd(home,x0,x1,b); 581 } else if (rm != RM_IMP) { 582 GECODE_ME_CHECK(b.one(home)); 583 } 584 return ES_OK; 585 } 586 587 588 template<class View, class CtrlView, ReifyMode rm> 589 forceinline 590 ReEqBnd<View,CtrlView,rm>::ReEqBnd(Space& home, ReEqBnd& p) 591 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,p) {} 592 593 template<class View, class CtrlView, ReifyMode rm> 594 Actor* 595 ReEqBnd<View,CtrlView,rm>::copy(Space& home) { 596 return new (home) ReEqBnd<View,CtrlView,rm>(home,*this); 597 } 598 599 template<class View, class CtrlView, ReifyMode rm> 600 ExecStatus 601 ReEqBnd<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { 602 if (b.one()) { 603 if (rm == RM_PMI) 604 return home.ES_SUBSUMED(*this); 605 GECODE_REWRITE(*this,(EqBnd<View,View>::post(home(*this),x0,x1))); 606 } 607 if (b.zero()) { 608 if (rm == RM_IMP) 609 return home.ES_SUBSUMED(*this); 610 GECODE_REWRITE(*this,(Nq<View,View>::post(home(*this),x0,x1))); 611 } 612 switch (rtest_eq_bnd(x0,x1)) { 613 case RT_TRUE: 614 if (rm != RM_IMP) 615 GECODE_ME_CHECK(b.one_none(home)); 616 break; 617 case RT_FALSE: 618 if (rm != RM_PMI) 619 GECODE_ME_CHECK(b.zero_none(home)); 620 break; 621 case RT_MAYBE: 622 return ES_FIX; 623 default: GECODE_NEVER; 624 } 625 return home.ES_SUBSUMED(*this); 626 } 627 628 629 630 631 /* 632 * Reified domain consistent equality (one variable) 633 * 634 */ 635 636 template<class View, class CtrlView, ReifyMode rm> 637 forceinline 638 ReEqDomInt<View,CtrlView,rm>::ReEqDomInt 639 (Home home, View x, int c0, CtrlView b) 640 : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,x,b), c(c0) {} 641 642 template<class View, class CtrlView, ReifyMode rm> 643 ExecStatus 644 ReEqDomInt<View,CtrlView,rm>::post(Home home, View x, int c, CtrlView b) { 645 if (b.one()) { 646 if (rm != RM_PMI) 647 GECODE_ME_CHECK(x.eq(home,c)); 648 } else if (b.zero()) { 649 if (rm != RM_IMP) 650 GECODE_ME_CHECK(x.nq(home,c)); 651 } else if (x.assigned()) { 652 assert(b.none()); 653 if (x.val() == c) { 654 if (rm != RM_IMP) 655 GECODE_ME_CHECK(b.one_none(home)); 656 } else { 657 if (rm != RM_PMI) 658 GECODE_ME_CHECK(b.zero_none(home)); 659 } 660 } else { 661 (void) new (home) ReEqDomInt(home,x,c,b); 662 } 663 return ES_OK; 664 } 665 666 667 template<class View, class CtrlView, ReifyMode rm> 668 forceinline 669 ReEqDomInt<View,CtrlView,rm>::ReEqDomInt(Space& home, ReEqDomInt& p) 670 : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,p), c(p.c) {} 671 672 template<class View, class CtrlView, ReifyMode rm> 673 Actor* 674 ReEqDomInt<View,CtrlView,rm>::copy(Space& home) { 675 return new (home) ReEqDomInt<View,CtrlView,rm>(home,*this); 676 } 677 678 template<class View, class CtrlView, ReifyMode rm> 679 ExecStatus 680 ReEqDomInt<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { 681 if (b.one()) { 682 if (rm != RM_PMI) 683 GECODE_ME_CHECK(x0.eq(home,c)); 684 } else if (b.zero()) { 685 if (rm != RM_IMP) 686 GECODE_ME_CHECK(x0.nq(home,c)); 687 } else { 688 switch (rtest_eq_dom(x0,c)) { 689 case RT_TRUE: 690 if (rm != RM_IMP) 691 GECODE_ME_CHECK(b.one_none(home)); 692 break; 693 case RT_FALSE: 694 if (rm != RM_PMI) 695 GECODE_ME_CHECK(b.zero_none(home)); 696 break; 697 case RT_MAYBE: 698 return ES_FIX; 699 default: GECODE_NEVER; 700 } 701 } 702 return home.ES_SUBSUMED(*this); 703 } 704 705 706 707 708 /* 709 * Reified bounds consistent equality (one variable) 710 * 711 */ 712 713 template<class View, class CtrlView, ReifyMode rm> 714 forceinline 715 ReEqBndInt<View,CtrlView,rm>::ReEqBndInt 716 (Home home, View x, int c0, CtrlView b) 717 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,x,b), c(c0) {} 718 719 template<class View, class CtrlView, ReifyMode rm> 720 ExecStatus 721 ReEqBndInt<View,CtrlView,rm>::post(Home home, View x, int c, CtrlView b) { 722 if (b.one()) { 723 if (rm != RM_PMI) 724 GECODE_ME_CHECK(x.eq(home,c)); 725 } else if (b.zero()) { 726 if (rm != RM_IMP) 727 GECODE_ME_CHECK(x.nq(home,c)); 728 } else if (x.assigned()) { 729 assert(b.none()); 730 if (x.val() == c) { 731 if (rm != RM_IMP) 732 GECODE_ME_CHECK(b.one_none(home)); 733 } else { 734 if (rm != RM_PMI) 735 GECODE_ME_CHECK(b.zero_none(home)); 736 } 737 } else { 738 (void) new (home) ReEqBndInt(home,x,c,b); 739 } 740 return ES_OK; 741 } 742 743 744 template<class View, class CtrlView, ReifyMode rm> 745 forceinline 746 ReEqBndInt<View,CtrlView,rm>::ReEqBndInt(Space& home, ReEqBndInt& p) 747 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,p), c(p.c) {} 748 749 template<class View, class CtrlView, ReifyMode rm> 750 Actor* 751 ReEqBndInt<View,CtrlView,rm>::copy(Space& home) { 752 return new (home) ReEqBndInt<View,CtrlView,rm>(home,*this); 753 } 754 755 template<class View, class CtrlView, ReifyMode rm> 756 ExecStatus 757 ReEqBndInt<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { 758 if (b.one()) { 759 if (rm != RM_PMI) 760 GECODE_ME_CHECK(x0.eq(home,c)); 761 } else if (b.zero()) { 762 if (rm != RM_IMP) 763 GECODE_ME_CHECK(x0.nq(home,c)); 764 } else { 765 switch (rtest_eq_bnd(x0,c)) { 766 case RT_TRUE: 767 if (rm != RM_IMP) 768 GECODE_ME_CHECK(b.one_none(home)); 769 break; 770 case RT_FALSE: 771 if (rm != RM_PMI) 772 GECODE_ME_CHECK(b.zero_none(home)); 773 break; 774 case RT_MAYBE: 775 return ES_FIX; 776 default: GECODE_NEVER; 777 } 778 } 779 return home.ES_SUBSUMED(*this); 780 } 781 782}}} 783 784// STATISTICS: int-prop