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 Bool { 35 36 /// Binary Boolean disjunction propagator (subsumed) 37 template<class BV> 38 class OrTrueSubsumed : public BoolBinary<BV,BV> { 39 protected: 40 using BoolBinary<BV,BV>::x0; 41 using BoolBinary<BV,BV>::x1; 42 /// Constructor for cloning \a p 43 OrTrueSubsumed(Space& home, OrTrueSubsumed& p); 44 /// Post propagator 45 static ExecStatus post(Home home, BV b0, BV b1); 46 public: 47 /// Constructor 48 OrTrueSubsumed(Home home, BV b0, BV b1); 49 /// Constructor for rewriting \a p during cloning 50 OrTrueSubsumed(Space& home, Propagator& p, 51 BV b0, BV b1); 52 /// Copy propagator during cloning 53 virtual Actor* copy(Space& home); 54 /// Perform propagation 55 virtual ExecStatus propagate(Space& home, const ModEventDelta& med); 56 }; 57 58 template<class BV> 59 forceinline 60 OrTrueSubsumed<BV>::OrTrueSubsumed 61 (Home home, BV b0, BV b1) 62 : BoolBinary<BV,BV>(home,b0,b1) {} 63 64 template<class BV> 65 forceinline ExecStatus 66 OrTrueSubsumed<BV>::post(Home home, BV b0, BV b1) { 67 (void) new (home) OrTrueSubsumed(home,b0,b1); 68 return ES_OK; 69 } 70 71 template<class BV> 72 forceinline 73 OrTrueSubsumed<BV>::OrTrueSubsumed 74 (Space& home, OrTrueSubsumed<BV>& p) 75 : BoolBinary<BV,BV>(home,p) {} 76 77 template<class BV> 78 forceinline 79 OrTrueSubsumed<BV>::OrTrueSubsumed(Space& home, Propagator& p, 80 BV b0, BV b1) 81 : BoolBinary<BV,BV>(home,p,b0,b1) {} 82 83 template<class BV> 84 Actor* 85 OrTrueSubsumed<BV>::copy(Space& home) { 86 return new (home) OrTrueSubsumed<BV>(home,*this); 87 } 88 89 template<class BV> 90 ExecStatus 91 OrTrueSubsumed<BV>::propagate(Space& home, const ModEventDelta&) { 92 return home.ES_SUBSUMED(*this); 93 } 94 95 96 /* 97 * Binary Boolean disjunction propagator (true) 98 * 99 */ 100 101 template<class BVA, class BVB> 102 forceinline 103 BinOrTrue<BVA,BVB>::BinOrTrue(Home home, BVA b0, BVB b1) 104 : BoolBinary<BVA,BVB>(home,b0,b1) {} 105 106 template<class BVA, class BVB> 107 forceinline 108 BinOrTrue<BVA,BVB>::BinOrTrue(Space& home, BinOrTrue<BVA,BVB>& p) 109 : BoolBinary<BVA,BVB>(home,p) {} 110 111 template<class BVA, class BVB> 112 forceinline 113 BinOrTrue<BVA,BVB>::BinOrTrue(Space& home, Propagator& p, 114 BVA b0, BVB b1) 115 : BoolBinary<BVA,BVB>(home,p,b0,b1) {} 116 117 template<class BVA, class BVB> 118 Actor* 119 BinOrTrue<BVA,BVB>::copy(Space& home) { 120 return new (home) BinOrTrue<BVA,BVB>(home,*this); 121 } 122 123 template<class BVA, class BVB> 124 inline ExecStatus 125 BinOrTrue<BVA,BVB>::post(Home home, BVA b0, BVB b1) { 126 switch (bool_test(b0,b1)) { 127 case BT_SAME: 128 GECODE_ME_CHECK(b0.one(home)); 129 break; 130 case BT_COMP: 131 break; 132 case BT_NONE: 133 if (b0.zero()) { 134 GECODE_ME_CHECK(b1.one(home)); 135 } else if (b1.zero()) { 136 GECODE_ME_CHECK(b0.one(home)); 137 } else if (!b0.one() && !b1.one()) { 138 (void) new (home) BinOrTrue<BVA,BVB>(home,b0,b1); 139 } 140 break; 141 default: GECODE_NEVER; 142 } 143 return ES_OK; 144 } 145 146 template<class BVA, class BVB> 147 ExecStatus 148 BinOrTrue<BVA,BVB>::propagate(Space& home, const ModEventDelta&) { 149#define GECODE_INT_STATUS(S0,S1) \ 150 ((BVA::S0<<(1*BVA::BITS))|(BVB::S1<<(0*BVB::BITS))) 151 switch ((x0.status() << (1*BVA::BITS)) | (x1.status() << (0*BVB::BITS))) { 152 case GECODE_INT_STATUS(NONE,NONE): 153 GECODE_NEVER; 154 case GECODE_INT_STATUS(NONE,ZERO): 155 GECODE_ME_CHECK(x0.one_none(home)); break; 156 case GECODE_INT_STATUS(NONE,ONE): 157 break; 158 case GECODE_INT_STATUS(ZERO,NONE): 159 GECODE_ME_CHECK(x1.one_none(home)); break; 160 case GECODE_INT_STATUS(ZERO,ZERO): 161 return ES_FAILED; 162 case GECODE_INT_STATUS(ZERO,ONE): 163 case GECODE_INT_STATUS(ONE,NONE): 164 case GECODE_INT_STATUS(ONE,ZERO): 165 case GECODE_INT_STATUS(ONE,ONE): 166 break; 167 default: 168 GECODE_NEVER; 169 } 170 return home.ES_SUBSUMED(*this); 171#undef GECODE_INT_STATUS 172 } 173 174 /* 175 * Boolean disjunction propagator (true) 176 * 177 */ 178 179 template<class BV> 180 forceinline 181 TerOrTrue<BV>::TerOrTrue(Home home, BV b0, BV b1, BV b2) 182 : BoolBinary<BV,BV>(home,b0,b1), x2(b2) {} 183 184 template<class BV> 185 forceinline size_t 186 TerOrTrue<BV>::dispose(Space& home) { 187 (void) BoolBinary<BV,BV>::dispose(home); 188 return sizeof(*this); 189 } 190 191 template<class BV> 192 forceinline 193 TerOrTrue<BV>::TerOrTrue(Space& home, TerOrTrue<BV>& p) 194 : BoolBinary<BV,BV>(home,p) { 195 x2.update(home,p.x2); 196 } 197 198 template<class BV> 199 forceinline 200 TerOrTrue<BV>::TerOrTrue(Space& home, Propagator& p, 201 BV b0, BV b1, BV b2) 202 : BoolBinary<BV,BV>(home,p,b0,b1) { 203 x2.update(home,b2); 204 } 205 206 template<class BV> 207 Actor* 208 TerOrTrue<BV>::copy(Space& home) { 209 assert(x0.none() && x1.none()); 210 if (x2.one()) 211 return new (home) OrTrueSubsumed<BV>(home,*this,x0,x1); 212 else if (x2.zero()) 213 return new (home) BinOrTrue<BV,BV>(home,*this,x0,x1); 214 else 215 return new (home) TerOrTrue<BV>(home,*this); 216 } 217 218 template<class BV> 219 forceinline ExecStatus 220 TerOrTrue<BV>::post(Home home, BV b0, BV b1, BV b2) { 221 (void) new (home) TerOrTrue<BV>(home,b0,b1,b2); 222 return ES_OK; 223 } 224 225 template<class BV> 226 ExecStatus 227 TerOrTrue<BV>::propagate(Space& home, const ModEventDelta&) { 228#define GECODE_INT_STATUS(S0,S1,S2) \ 229 ((BV::S0<<(2*BV::BITS))|(BV::S1<<(1*BV::BITS))|(BV::S2<<(0*BV::BITS))) 230 switch ((x0.status() << (2*BV::BITS)) | (x1.status() << (1*BV::BITS)) | 231 (x2.status() << (0*BV::BITS))) { 232 case GECODE_INT_STATUS(NONE,NONE,NONE): 233 case GECODE_INT_STATUS(NONE,NONE,ZERO): 234 case GECODE_INT_STATUS(NONE,NONE,ONE): 235 GECODE_NEVER; 236 case GECODE_INT_STATUS(NONE,ZERO,NONE): 237 std::swap(x1,x2); x1.subscribe(home,*this,PC_BOOL_VAL); 238 return ES_FIX; 239 case GECODE_INT_STATUS(NONE,ZERO,ZERO): 240 GECODE_ME_CHECK(x0.one_none(home)); break; 241 case GECODE_INT_STATUS(NONE,ZERO,ONE): 242 case GECODE_INT_STATUS(NONE,ONE,NONE): 243 case GECODE_INT_STATUS(NONE,ONE,ZERO): 244 case GECODE_INT_STATUS(NONE,ONE,ONE): 245 break; 246 case GECODE_INT_STATUS(ZERO,NONE,NONE): 247 std::swap(x0,x2); x0.subscribe(home,*this,PC_BOOL_VAL); 248 return ES_FIX; 249 case GECODE_INT_STATUS(ZERO,NONE,ZERO): 250 GECODE_ME_CHECK(x1.one_none(home)); break; 251 case GECODE_INT_STATUS(ZERO,NONE,ONE): 252 break; 253 case GECODE_INT_STATUS(ZERO,ZERO,NONE): 254 GECODE_ME_CHECK(x2.one_none(home)); break; 255 case GECODE_INT_STATUS(ZERO,ZERO,ZERO): 256 return ES_FAILED; 257 case GECODE_INT_STATUS(ZERO,ZERO,ONE): 258 case GECODE_INT_STATUS(ZERO,ONE,NONE): 259 case GECODE_INT_STATUS(ZERO,ONE,ZERO): 260 case GECODE_INT_STATUS(ZERO,ONE,ONE): 261 case GECODE_INT_STATUS(ONE,NONE,NONE): 262 case GECODE_INT_STATUS(ONE,NONE,ZERO): 263 case GECODE_INT_STATUS(ONE,NONE,ONE): 264 case GECODE_INT_STATUS(ONE,ZERO,NONE): 265 case GECODE_INT_STATUS(ONE,ZERO,ZERO): 266 case GECODE_INT_STATUS(ONE,ZERO,ONE): 267 case GECODE_INT_STATUS(ONE,ONE,NONE): 268 case GECODE_INT_STATUS(ONE,ONE,ZERO): 269 case GECODE_INT_STATUS(ONE,ONE,ONE): 270 break; 271 default: 272 GECODE_NEVER; 273 } 274 return home.ES_SUBSUMED(*this); 275#undef GECODE_INT_STATUS 276 } 277 278 /* 279 * Boolean disjunction propagator (true) 280 * 281 */ 282 283 template<class BV> 284 forceinline 285 QuadOrTrue<BV>::QuadOrTrue(Home home, BV b0, BV b1, BV b2, BV b3) 286 : BoolBinary<BV,BV>(home,b0,b1), x2(b2), x3(b3) {} 287 288 template<class BV> 289 forceinline size_t 290 QuadOrTrue<BV>::dispose(Space& home) { 291 (void) BoolBinary<BV,BV>::dispose(home); 292 return sizeof(*this); 293 } 294 295 template<class BV> 296 forceinline 297 QuadOrTrue<BV>::QuadOrTrue(Space& home, QuadOrTrue<BV>& p) 298 : BoolBinary<BV,BV>(home,p) { 299 x2.update(home,p.x2); 300 x3.update(home,p.x3); 301 } 302 303 template<class BV> 304 forceinline 305 QuadOrTrue<BV>::QuadOrTrue(Space& home, Propagator& p, 306 BV b0, BV b1, BV b2, BV b3) 307 : BoolBinary<BV,BV>(home,p,b0,b1) { 308 x2.update(home,b2); 309 x3.update(home,b3); 310 } 311 312 template<class BV> 313 Actor* 314 QuadOrTrue<BV>::copy(Space& home) { 315 assert(x0.none() && x1.none()); 316 if (x2.one() || x3.one()) 317 return new (home) OrTrueSubsumed<BV>(home,*this,x0,x1); 318 else if (x2.zero() && x3.zero()) 319 return new (home) BinOrTrue<BV,BV>(home,*this,x0,x1); 320 else if (x2.zero()) 321 return new (home) TerOrTrue<BV>(home,*this,x0,x1,x3); 322 else if (x3.zero()) 323 return new (home) TerOrTrue<BV>(home,*this,x0,x1,x2); 324 else 325 return new (home) QuadOrTrue<BV>(home,*this); 326 } 327 328 template<class BV> 329 forceinline ExecStatus 330 QuadOrTrue<BV>::post(Home home, BV b0, BV b1, BV b2, BV b3) { 331 (void) new (home) QuadOrTrue<BV>(home,b0,b1,b2,b3); 332 return ES_OK; 333 } 334 335 template<class BV> 336 ExecStatus 337 QuadOrTrue<BV>::propagate(Space& home, const ModEventDelta&) { 338#define GECODE_INT_STATUS(S0,S1,S2,S3) \ 339 ((BV::S0 << (3*BV::BITS)) | (BV::S1 << (2*BV::BITS)) | \ 340 (BV::S2 << (1*BV::BITS)) | (BV::S3 << (0*BV::BITS))) 341 switch ((x0.status() << (3*BV::BITS)) | (x1.status() << (2*BV::BITS)) | 342 (x2.status() << (1*BV::BITS)) | (x3.status() << (0*BV::BITS))) { 343 case GECODE_INT_STATUS(NONE,NONE,NONE,NONE): 344 case GECODE_INT_STATUS(NONE,NONE,NONE,ZERO): 345 case GECODE_INT_STATUS(NONE,NONE,NONE,ONE): 346 case GECODE_INT_STATUS(NONE,NONE,ZERO,NONE): 347 case GECODE_INT_STATUS(NONE,NONE,ZERO,ZERO): 348 case GECODE_INT_STATUS(NONE,NONE,ZERO,ONE): 349 case GECODE_INT_STATUS(NONE,NONE,ONE,NONE): 350 case GECODE_INT_STATUS(NONE,NONE,ONE,ZERO): 351 case GECODE_INT_STATUS(NONE,NONE,ONE,ONE): 352 GECODE_NEVER; 353 case GECODE_INT_STATUS(NONE,ZERO,NONE,NONE): 354 case GECODE_INT_STATUS(NONE,ZERO,NONE,ZERO): 355 std::swap(x1,x2); x1.subscribe(home,*this,PC_BOOL_VAL,false); 356 return ES_FIX; 357 case GECODE_INT_STATUS(NONE,ZERO,NONE,ONE): 358 break; 359 case GECODE_INT_STATUS(NONE,ZERO,ZERO,NONE): 360 std::swap(x1,x3); x1.subscribe(home,*this,PC_BOOL_VAL,false); 361 return ES_FIX; 362 case GECODE_INT_STATUS(NONE,ZERO,ZERO,ZERO): 363 GECODE_ME_CHECK(x0.one_none(home)); break; 364 case GECODE_INT_STATUS(NONE,ZERO,ZERO,ONE): 365 case GECODE_INT_STATUS(NONE,ZERO,ONE,NONE): 366 case GECODE_INT_STATUS(NONE,ZERO,ONE,ZERO): 367 case GECODE_INT_STATUS(NONE,ZERO,ONE,ONE): 368 case GECODE_INT_STATUS(NONE,ONE,NONE,NONE): 369 case GECODE_INT_STATUS(NONE,ONE,NONE,ZERO): 370 case GECODE_INT_STATUS(NONE,ONE,NONE,ONE): 371 case GECODE_INT_STATUS(NONE,ONE,ZERO,NONE): 372 case GECODE_INT_STATUS(NONE,ONE,ZERO,ZERO): 373 case GECODE_INT_STATUS(NONE,ONE,ZERO,ONE): 374 case GECODE_INT_STATUS(NONE,ONE,ONE,NONE): 375 case GECODE_INT_STATUS(NONE,ONE,ONE,ZERO): 376 case GECODE_INT_STATUS(NONE,ONE,ONE,ONE): 377 break; 378 case GECODE_INT_STATUS(ZERO,NONE,NONE,NONE): 379 case GECODE_INT_STATUS(ZERO,NONE,NONE,ZERO): 380 std::swap(x0,x2); x0.subscribe(home,*this,PC_BOOL_VAL,false); 381 return ES_FIX; 382 case GECODE_INT_STATUS(ZERO,NONE,NONE,ONE): 383 break; 384 case GECODE_INT_STATUS(ZERO,NONE,ZERO,NONE): 385 std::swap(x0,x3); x0.subscribe(home,*this,PC_BOOL_VAL,false); 386 return ES_FIX; 387 case GECODE_INT_STATUS(ZERO,NONE,ZERO,ZERO): 388 GECODE_ME_CHECK(x1.one_none(home)); break; 389 case GECODE_INT_STATUS(ZERO,NONE,ZERO,ONE): 390 case GECODE_INT_STATUS(ZERO,NONE,ONE,NONE): 391 case GECODE_INT_STATUS(ZERO,NONE,ONE,ZERO): 392 case GECODE_INT_STATUS(ZERO,NONE,ONE,ONE): 393 break; 394 case GECODE_INT_STATUS(ZERO,ZERO,NONE,NONE): 395 std::swap(x0,x2); x0.subscribe(home,*this,PC_BOOL_VAL,false); 396 std::swap(x1,x3); x1.subscribe(home,*this,PC_BOOL_VAL,false); 397 return ES_FIX; 398 case GECODE_INT_STATUS(ZERO,ZERO,NONE,ZERO): 399 GECODE_ME_CHECK(x2.one_none(home)); break; 400 case GECODE_INT_STATUS(ZERO,ZERO,NONE,ONE): 401 break; 402 case GECODE_INT_STATUS(ZERO,ZERO,ZERO,NONE): 403 GECODE_ME_CHECK(x3.one_none(home)); break; 404 case GECODE_INT_STATUS(ZERO,ZERO,ZERO,ZERO): 405 return ES_FAILED; 406 case GECODE_INT_STATUS(ZERO,ZERO,ZERO,ONE): 407 case GECODE_INT_STATUS(ZERO,ZERO,ONE,NONE): 408 case GECODE_INT_STATUS(ZERO,ZERO,ONE,ZERO): 409 case GECODE_INT_STATUS(ZERO,ZERO,ONE,ONE): 410 case GECODE_INT_STATUS(ZERO,ONE,NONE,NONE): 411 case GECODE_INT_STATUS(ZERO,ONE,NONE,ZERO): 412 case GECODE_INT_STATUS(ZERO,ONE,NONE,ONE): 413 case GECODE_INT_STATUS(ZERO,ONE,ZERO,NONE): 414 case GECODE_INT_STATUS(ZERO,ONE,ZERO,ZERO): 415 case GECODE_INT_STATUS(ZERO,ONE,ZERO,ONE): 416 case GECODE_INT_STATUS(ZERO,ONE,ONE,NONE): 417 case GECODE_INT_STATUS(ZERO,ONE,ONE,ZERO): 418 case GECODE_INT_STATUS(ZERO,ONE,ONE,ONE): 419 case GECODE_INT_STATUS(ONE,NONE,NONE,NONE): 420 case GECODE_INT_STATUS(ONE,NONE,NONE,ZERO): 421 case GECODE_INT_STATUS(ONE,NONE,NONE,ONE): 422 case GECODE_INT_STATUS(ONE,NONE,ZERO,NONE): 423 case GECODE_INT_STATUS(ONE,NONE,ZERO,ZERO): 424 case GECODE_INT_STATUS(ONE,NONE,ZERO,ONE): 425 case GECODE_INT_STATUS(ONE,NONE,ONE,NONE): 426 case GECODE_INT_STATUS(ONE,NONE,ONE,ZERO): 427 case GECODE_INT_STATUS(ONE,NONE,ONE,ONE): 428 case GECODE_INT_STATUS(ONE,ZERO,NONE,NONE): 429 case GECODE_INT_STATUS(ONE,ZERO,NONE,ZERO): 430 case GECODE_INT_STATUS(ONE,ZERO,NONE,ONE): 431 case GECODE_INT_STATUS(ONE,ZERO,ZERO,NONE): 432 case GECODE_INT_STATUS(ONE,ZERO,ZERO,ZERO): 433 case GECODE_INT_STATUS(ONE,ZERO,ZERO,ONE): 434 case GECODE_INT_STATUS(ONE,ZERO,ONE,NONE): 435 case GECODE_INT_STATUS(ONE,ZERO,ONE,ZERO): 436 case GECODE_INT_STATUS(ONE,ZERO,ONE,ONE): 437 case GECODE_INT_STATUS(ONE,ONE,NONE,NONE): 438 case GECODE_INT_STATUS(ONE,ONE,NONE,ZERO): 439 case GECODE_INT_STATUS(ONE,ONE,NONE,ONE): 440 case GECODE_INT_STATUS(ONE,ONE,ZERO,NONE): 441 case GECODE_INT_STATUS(ONE,ONE,ZERO,ZERO): 442 case GECODE_INT_STATUS(ONE,ONE,ZERO,ONE): 443 case GECODE_INT_STATUS(ONE,ONE,ONE,NONE): 444 case GECODE_INT_STATUS(ONE,ONE,ONE,ZERO): 445 case GECODE_INT_STATUS(ONE,ONE,ONE,ONE): 446 break; 447 default: 448 GECODE_NEVER; 449 } 450 return home.ES_SUBSUMED(*this); 451#undef GECODE_INT_STATUS 452 } 453 454 /* 455 * Boolean disjunction propagator 456 * 457 */ 458 459 template<class BVA, class BVB, class BVC> 460 forceinline 461 Or<BVA,BVB,BVC>::Or(Home home, BVA b0, BVB b1, BVC b2) 462 : BoolTernary<BVA,BVB,BVC>(home,b0,b1,b2) {} 463 464 template<class BVA, class BVB, class BVC> 465 forceinline 466 Or<BVA,BVB,BVC>::Or(Space& home, Or<BVA,BVB,BVC>& p) 467 : BoolTernary<BVA,BVB,BVC>(home,p) {} 468 469 template<class BVA, class BVB, class BVC> 470 forceinline 471 Or<BVA,BVB,BVC>::Or(Space& home, Propagator& p, 472 BVA b0, BVB b1, BVC b2) 473 : BoolTernary<BVA,BVB,BVC>(home,p,b0,b1,b2) {} 474 475 template<class BVA, class BVB, class BVC> 476 Actor* 477 Or<BVA,BVB,BVC>::copy(Space& home) { 478 if (x2.one()) { 479 assert(x0.none() && x1.none()); 480 return new (home) BinOrTrue<BVA,BVB>(home,*this,x0,x1); 481 } else if (x0.zero()) { 482 assert(x1.none() && x2.none()); 483 return new (home) Eq<BVB,BVC>(home,*this,x1,x2); 484 } else if (x1.zero()) { 485 assert(x0.none() && x2.none()); 486 return new (home) Eq<BVA,BVC>(home,*this,x0,x2); 487 } else { 488 return new (home) Or<BVA,BVB,BVC>(home,*this); 489 } 490 } 491 492 template<class BVA, class BVB, class BVC> 493 inline ExecStatus 494 Or<BVA,BVB,BVC>::post(Home home, BVA b0, BVB b1, BVC b2) { 495 if (b2.zero()) { 496 GECODE_ME_CHECK(b0.zero(home)); 497 GECODE_ME_CHECK(b1.zero(home)); 498 } else if (b2.one()) { 499 return BinOrTrue<BVA,BVB>::post(home,b0,b1); 500 } else { 501 switch (bool_test(b0,b1)) { 502 case BT_SAME: 503 return Eq<BVA,BVC>::post(home,b0,b2); 504 case BT_COMP: 505 GECODE_ME_CHECK(b2.one(home)); 506 break; 507 case BT_NONE: 508 if (b0.one() || b1.one()) { 509 GECODE_ME_CHECK(b2.one(home)); 510 } else if (b0.zero()) { 511 return Eq<BVB,BVC>::post(home,b1,b2); 512 } else if (b1.zero()) { 513 return Eq<BVA,BVC>::post(home,b0,b2); 514 } else { 515 (void) new (home) Or<BVA,BVB,BVC>(home,b0,b1,b2); 516 } 517 break; 518 default: GECODE_NEVER; 519 } 520 } 521 return ES_OK; 522 } 523 524 template<class BVA, class BVB, class BVC> 525 ExecStatus 526 Or<BVA,BVB,BVC>::propagate(Space& home, const ModEventDelta&) { 527#define GECODE_INT_STATUS(S0,S1,S2) \ 528 ((BVA::S0<<(2*BVA::BITS))|(BVB::S1<<(1*BVB::BITS))|(BVC::S2<<(0*BVC::BITS))) 529 switch ((x0.status() << (2*BVA::BITS)) | (x1.status() << (1*BVB::BITS)) | 530 (x2.status() << (0*BVC::BITS))) { 531 case GECODE_INT_STATUS(NONE,NONE,NONE): 532 GECODE_NEVER; 533 case GECODE_INT_STATUS(NONE,NONE,ZERO): 534 GECODE_ME_CHECK(x0.zero_none(home)); 535 GECODE_ME_CHECK(x1.zero_none(home)); 536 break; 537 case GECODE_INT_STATUS(NONE,NONE,ONE): 538 return ES_FIX; 539 case GECODE_INT_STATUS(NONE,ZERO,NONE): 540 switch (bool_test(x0,x2)) { 541 case BT_SAME: return home.ES_SUBSUMED(*this); 542 case BT_COMP: return ES_FAILED; 543 case BT_NONE: return ES_FIX; 544 default: GECODE_NEVER; 545 } 546 GECODE_NEVER; 547 case GECODE_INT_STATUS(NONE,ZERO,ZERO): 548 GECODE_ME_CHECK(x0.zero_none(home)); break; 549 case GECODE_INT_STATUS(NONE,ZERO,ONE): 550 GECODE_ME_CHECK(x0.one_none(home)); break; 551 case GECODE_INT_STATUS(NONE,ONE,NONE): 552 GECODE_ME_CHECK(x2.one_none(home)); break; 553 case GECODE_INT_STATUS(NONE,ONE,ZERO): 554 return ES_FAILED; 555 case GECODE_INT_STATUS(NONE,ONE,ONE): 556 break; 557 case GECODE_INT_STATUS(ZERO,NONE,NONE): 558 switch (bool_test(x1,x2)) { 559 case BT_SAME: return home.ES_SUBSUMED(*this); 560 case BT_COMP: return ES_FAILED; 561 case BT_NONE: return ES_FIX; 562 default: GECODE_NEVER; 563 } 564 GECODE_NEVER; 565 case GECODE_INT_STATUS(ZERO,NONE,ZERO): 566 GECODE_ME_CHECK(x1.zero_none(home)); break; 567 case GECODE_INT_STATUS(ZERO,NONE,ONE): 568 GECODE_ME_CHECK(x1.one_none(home)); break; 569 case GECODE_INT_STATUS(ZERO,ZERO,NONE): 570 GECODE_ME_CHECK(x2.zero_none(home)); break; 571 case GECODE_INT_STATUS(ZERO,ZERO,ZERO): 572 break; 573 case GECODE_INT_STATUS(ZERO,ZERO,ONE): 574 return ES_FAILED; 575 case GECODE_INT_STATUS(ZERO,ONE,NONE): 576 GECODE_ME_CHECK(x2.one_none(home)); break; 577 case GECODE_INT_STATUS(ZERO,ONE,ZERO): 578 return ES_FAILED; 579 case GECODE_INT_STATUS(ZERO,ONE,ONE): 580 break; 581 case GECODE_INT_STATUS(ONE,NONE,NONE): 582 GECODE_ME_CHECK(x2.one_none(home)); break; 583 case GECODE_INT_STATUS(ONE,NONE,ZERO): 584 return ES_FAILED; 585 case GECODE_INT_STATUS(ONE,NONE,ONE): 586 break; 587 case GECODE_INT_STATUS(ONE,ZERO,NONE): 588 GECODE_ME_CHECK(x2.one_none(home)); break; 589 case GECODE_INT_STATUS(ONE,ZERO,ZERO): 590 return ES_FAILED; 591 case GECODE_INT_STATUS(ONE,ZERO,ONE): 592 break; 593 case GECODE_INT_STATUS(ONE,ONE,NONE): 594 GECODE_ME_CHECK(x2.one_none(home)); break; 595 case GECODE_INT_STATUS(ONE,ONE,ZERO): 596 return ES_FAILED; 597 case GECODE_INT_STATUS(ONE,ONE,ONE): 598 break; 599 default: 600 GECODE_NEVER; 601 } 602 return home.ES_SUBSUMED(*this); 603#undef GECODE_INT_STATUS 604 } 605 606 /* 607 * N-ary Boolean disjunction propagator (true) 608 * 609 */ 610 611 template<class BV> 612 forceinline 613 NaryOrTrue<BV>::NaryOrTrue(Home home, ViewArray<BV>& b) 614 : BinaryPropagator<BV,PC_BOOL_VAL>(home,b[0],b[1]), x(b) { 615 assert(x.size() > 2); 616 x.drop_fst(2); 617 } 618 619 template<class BV> 620 PropCost 621 NaryOrTrue<BV>::cost(const Space&, const ModEventDelta&) const { 622 return PropCost::binary(PropCost::LO); 623 } 624 625 template<class BV> 626 forceinline 627 NaryOrTrue<BV>::NaryOrTrue(Space& home, NaryOrTrue<BV>& p) 628 : BinaryPropagator<BV,PC_BOOL_VAL>(home,p) { 629 x.update(home,p.x); 630 } 631 632 template<class BV> 633 Actor* 634 NaryOrTrue<BV>::copy(Space& home) { 635 int n = x.size(); 636 if (n > 0) { 637 // Eliminate all zeros and find a one 638 for (int i=n; i--; ) 639 if (x[i].one()) { 640 // Only keep the one 641 x[0]=x[i]; x.size(1); 642 return new (home) OrTrueSubsumed<BV>(home,*this,x0,x1); 643 } else if (x[i].zero()) { 644 // Eliminate the zero 645 x[i]=x[--n]; 646 } 647 x.size(n); 648 } 649 switch (n) { 650 case 0: 651 return new (home) BinOrTrue<BV,BV>(home,*this,x0,x1); 652 case 1: 653 return new (home) TerOrTrue<BV>(home,*this,x0,x1,x[0]); 654 case 2: 655 return new (home) QuadOrTrue<BV>(home,*this,x0,x1,x[0],x[1]); 656 default: 657 return new (home) NaryOrTrue<BV>(home,*this); 658 } 659 } 660 661 template<class BV> 662 inline ExecStatus 663 NaryOrTrue<BV>::post(Home home, ViewArray<BV>& b) { 664 for (int i=b.size(); i--; ) 665 if (b[i].one()) 666 return ES_OK; 667 else if (b[i].zero()) 668 b.move_lst(i); 669 if (b.size() == 0) 670 return ES_FAILED; 671 if (b.size() == 1) { 672 GECODE_ME_CHECK(b[0].one(home)); 673 } else if (b.size() == 2) { 674 return BinOrTrue<BV,BV>::post(home,b[0],b[1]); 675 } else if (b.size() == 3) { 676 return TerOrTrue<BV>::post(home,b[0],b[1],b[2]); 677 } else if (b.size() == 4) { 678 return QuadOrTrue<BV>::post(home,b[0],b[1],b[2],b[3]); 679 } else { 680 (void) new (home) NaryOrTrue(home,b); 681 } 682 return ES_OK; 683 } 684 685 template<class BV> 686 forceinline size_t 687 NaryOrTrue<BV>::dispose(Space& home) { 688 (void) BinaryPropagator<BV,PC_BOOL_VAL>::dispose(home); 689 return sizeof(*this); 690 } 691 692 template<class BV> 693 forceinline ExecStatus 694 NaryOrTrue<BV>::resubscribe(Space& home, BV& x0, BV x1) { 695 if (x0.zero()) { 696 int n = x.size(); 697 for (int i=n; i--; ) 698 if (x[i].one()) { 699 return home.ES_SUBSUMED(*this); 700 } else if (x[i].zero()) { 701 x[i] = x[--n]; 702 } else { 703 // Move to x0 and subscribe 704 x0=x[i]; x[i]=x[--n]; 705 x.size(n); 706 x0.subscribe(home,*this,PC_BOOL_VAL,false); 707 return ES_FIX; 708 } 709 // All views have been assigned! 710 GECODE_ME_CHECK(x1.one(home)); 711 return home.ES_SUBSUMED(*this); 712 } 713 return ES_FIX; 714 } 715 716 template<class BV> 717 ExecStatus 718 NaryOrTrue<BV>::propagate(Space& home, const ModEventDelta&) { 719 if (x0.one()) 720 return home.ES_SUBSUMED(*this); 721 if (x1.one()) 722 return home.ES_SUBSUMED(*this); 723 GECODE_ES_CHECK(resubscribe(home,x0,x1)); 724 GECODE_ES_CHECK(resubscribe(home,x1,x0)); 725 return ES_FIX; 726 } 727 728 729 /* 730 * N-ary Boolean disjunction propagator 731 * 732 */ 733 734 template<class VX, class VY> 735 forceinline 736 NaryOr<VX,VY>::NaryOr(Home home, ViewArray<VX>& x, VY y) 737 : MixNaryOnePropagator<VX,PC_BOOL_NONE,VY,PC_BOOL_VAL>(home,x,y), 738 n_zero(0), c(home) { 739 x.subscribe(home,*new (home) Advisor(home,*this,c)); 740 } 741 742 template<class VX, class VY> 743 forceinline 744 NaryOr<VX,VY>::NaryOr(Space& home, NaryOr<VX,VY>& p) 745 : MixNaryOnePropagator<VX,PC_BOOL_NONE,VY,PC_BOOL_VAL>(home,p), 746 n_zero(p.n_zero) { 747 c.update(home,p.c); 748 } 749 750 template<class VX, class VY> 751 Actor* 752 NaryOr<VX,VY>::copy(Space& home) { 753 assert(n_zero < x.size()); 754 if (n_zero > 0) { 755 int n=x.size(); 756 // Eliminate all zeros 757 for (int i=n; i--; ) 758 if (x[i].zero()) 759 x[i]=x[--n]; 760 x.size(n); 761 n_zero = 0; 762 } 763 assert(n_zero < x.size()); 764 return new (home) NaryOr<VX,VY>(home,*this); 765 } 766 767 template<class VX, class VY> 768 inline ExecStatus 769 NaryOr<VX,VY>::post(Home home, ViewArray<VX>& x, VY y) { 770 assert(!shared(x)); 771 if (y.one()) 772 return NaryOrTrue<VX>::post(home,x); 773 if (y.zero()) { 774 for (int i=0; i<x.size(); i++) 775 GECODE_ME_CHECK(x[i].zero(home)); 776 return ES_OK; 777 } 778 for (int i=x.size(); i--; ) 779 if (x[i].one()) { 780 GECODE_ME_CHECK(y.one_none(home)); 781 return ES_OK; 782 } else if (x[i].zero()) { 783 x.move_lst(i); 784 } 785 if (x.size() == 0) { 786 GECODE_ME_CHECK(y.zero_none(home)); 787 } else if (x.size() == 1) { 788 return Eq<VX,VY>::post(home,x[0],y); 789 } else if (x.size() == 2) { 790 return Or<VX,VX,VY>::post(home,x[0],x[1],y); 791 } else { 792 (void) new (home) NaryOr(home,x,y); 793 } 794 return ES_OK; 795 } 796 797 template<class VX, class VY> 798 PropCost 799 NaryOr<VX,VY>::cost(const Space&, const ModEventDelta&) const { 800 return PropCost::unary(PropCost::LO); 801 } 802 803 template<class VX, class VY> 804 ExecStatus 805 NaryOr<VX,VY>::advise(Space&, Advisor&, const Delta& d) { 806 // Decides whether the propagator must be run 807 if (VX::zero(d) && (++n_zero < x.size())) 808 return ES_FIX; 809 else 810 return ES_NOFIX; 811 } 812 813 template<class VX, class VY> 814 void 815 NaryOr<VX,VY>::reschedule(Space& home) { 816 y.reschedule(home,*this,PC_BOOL_VAL); 817 if (n_zero == x.size()) 818 VX::schedule(home,*this,ME_BOOL_VAL); 819 for (int i=0; i<x.size(); i++) 820 if (x[i].one()) { 821 VX::schedule(home,*this,ME_BOOL_VAL); 822 break; 823 } 824 } 825 826 template<class VX, class VY> 827 forceinline size_t 828 NaryOr<VX,VY>::dispose(Space& home) { 829 Advisors<Advisor> as(c); 830 x.cancel(home,as.advisor()); 831 c.dispose(home); 832 (void) MixNaryOnePropagator<VX,PC_BOOL_NONE,VY,PC_BOOL_VAL> 833 ::dispose(home); 834 return sizeof(*this); 835 } 836 837 template<class VX, class VY> 838 ExecStatus 839 NaryOr<VX,VY>::propagate(Space& home, const ModEventDelta&) { 840 if (y.one()) 841 GECODE_REWRITE(*this,NaryOrTrue<VX>::post(home(*this),x)); 842 if (y.zero()) { 843 // Note that this might trigger the advisor of this propagator! 844 for (int i=0; i<x.size(); i++) 845 GECODE_ME_CHECK(x[i].zero(home)); 846 } else if (n_zero == x.size()) { 847 // All views are zero 848 GECODE_ME_CHECK(y.zero_none(home)); 849 } else { 850 // There is at least one view which is one 851 GECODE_ME_CHECK(y.one_none(home)); 852 } 853 return home.ES_SUBSUMED(*this); 854 } 855 856}}} 857 858// STATISTICS: int-prop 859