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 * Mikael Lagerkvist <lagerkvist@gecode.org> 6 * 7 * Copyright: 8 * Christian Schulte, 2005 9 * Mikael Lagerkvist, 2005 10 * 11 * This file is part of Gecode, the generic constraint 12 * development environment: 13 * http://www.gecode.org 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining 16 * a copy of this software and associated documentation files (the 17 * "Software"), to deal in the Software without restriction, including 18 * without limitation the rights to use, copy, modify, merge, publish, 19 * distribute, sublicense, and/or sell copies of the Software, and to 20 * permit persons to whom the Software is furnished to do so, subject to 21 * the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 * 34 */ 35 36#include "test/int.hh" 37 38#include <algorithm> 39 40namespace Test { namespace Int { 41 42 43 /* 44 * Complete assignments 45 * 46 */ 47 void 48 CpltAssignment::next(Gecode::Support::RandomGenerator&) { 49 int i = n-1; 50 while (true) { 51 ++dsv[i]; 52 if (dsv[i]() || (i == 0)) 53 return; 54 dsv[i--].init(d); 55 } 56 } 57 58 /* 59 * Random assignments 60 * 61 */ 62 void RandomAssignment::next(Gecode::Support::RandomGenerator& rand) { 63 for (int i = this->n; i--; ) 64 this->vals[i]= this->randval(rand); 65 this->a--; 66 } 67 68 void 69 RandomMixAssignment::next(Gecode::Support::RandomGenerator& rand) { 70 for (int i=n-_n1; i--; ) 71 vals[i] = randval(d, rand); 72 for (int i=_n1; i--; ) 73 vals[n-_n1+i] = randval(_d1, rand); 74 a--; 75 } 76 77}} 78 79std::ostream& 80operator<<(std::ostream& os, const Test::Int::Assignment& a) { 81 int n = a.size(); 82 os << "{"; 83 for (int i=0; i<n; i++) 84 os << a[i] << ((i!=n-1) ? "," : "}"); 85 return os; 86} 87 88namespace Test { namespace Int { 89 90 TestSpace::TestSpace(int n, Gecode::IntSet& d0, Test* t) 91 : d(d0), x(*this,n,Gecode::Int::Limits::min,Gecode::Int::Limits::max), 92 test(t), reified(false) { 93 Gecode::IntVarArgs _x(*this,n,d); 94 if (x.size() == 1) 95 Gecode::dom(*this,x[0],_x[0]); 96 else 97 Gecode::dom(*this,x,_x); 98 Gecode::BoolVar b(*this,0,1); 99 r = Gecode::Reify(b,Gecode::RM_EQV); 100 if (opt.log) 101 olog << ind(2) << "Initial: x[]=" << x 102 << std::endl; 103 } 104 105 TestSpace::TestSpace(int n, Gecode::IntSet& d0, Test* t, 106 Gecode::ReifyMode rm) 107 : d(d0), x(*this,n,Gecode::Int::Limits::min,Gecode::Int::Limits::max), 108 test(t), reified(true) { 109 Gecode::IntVarArgs _x(*this,n,d); 110 if (x.size() == 1) 111 Gecode::dom(*this,x[0],_x[0]); 112 else 113 Gecode::dom(*this,x,_x); 114 Gecode::BoolVar b(*this,0,1); 115 r = Gecode::Reify(b,rm); 116 if (opt.log) 117 olog << ind(2) << "Initial: x[]=" << x 118 << " b=" << r.var() << std::endl; 119 } 120 121 TestSpace::TestSpace(TestSpace& s) 122 : Gecode::Space(s), d(s.d), test(s.test), reified(s.reified) { 123 x.update(*this, s.x); 124 Gecode::BoolVar b; 125 Gecode::BoolVar sr(s.r.var()); 126 b.update(*this, sr); 127 r.var(b); r.mode(s.r.mode()); 128 } 129 130 Gecode::Space* 131 TestSpace::copy(void) { 132 return new TestSpace(*this); 133 } 134 135 bool 136 TestSpace::assigned(void) const { 137 for (int i=x.size(); i--; ) 138 if (!x[i].assigned()) 139 return false; 140 return true; 141 } 142 143 void 144 TestSpace::post(void) { 145 if (reified){ 146 test->post(*this,x,r); 147 if (opt.log) 148 olog << ind(3) << "Posting reified propagator" << std::endl; 149 } else { 150 test->post(*this,x); 151 if (opt.log) 152 olog << ind(3) << "Posting propagator" << std::endl; 153 } 154 } 155 156 bool 157 TestSpace::failed(void) { 158 if (opt.log) { 159 olog << ind(3) << "Fixpoint: " << x; 160 bool f=(status() == Gecode::SS_FAILED); 161 olog << std::endl << ind(3) << " --> " << x << std::endl; 162 return f; 163 } else { 164 return status() == Gecode::SS_FAILED; 165 } 166 } 167 168 int 169 TestSpace::rndvar(Gecode::Support::RandomGenerator& rand) { 170 assert(!assigned()); 171 // Select variable to be pruned 172 int i = static_cast<int>(rand(static_cast<unsigned int>(x.size()))); 173 while (x[i].assigned()) { 174 i = (i+1) % x.size(); 175 } 176 return i; 177 } 178 179 void 180 TestSpace::rndrel(const Assignment& a, int i, Gecode::IntRelType& irt, int& v, 181 Gecode::Support::RandomGenerator& rand) { 182 using namespace Gecode; 183 // Select mode for pruning 184 irt = IRT_EQ; // Means do nothing! 185 switch (rand(3)) { 186 case 0: 187 if (a[i] < x[i].max()) { 188 v=a[i]+1+ 189 static_cast<int>(rand(static_cast<unsigned int>(x[i].max()-a[i]))); 190 assert((v > a[i]) && (v <= x[i].max())); 191 irt = IRT_LE; 192 } 193 break; 194 case 1: 195 if (a[i] > x[i].min()) { 196 v=x[i].min()+ 197 static_cast<int>(rand(static_cast<unsigned int>(a[i]-x[i].min()))); 198 assert((v < a[i]) && (v >= x[i].min())); 199 irt = IRT_GR; 200 } 201 break; 202 default: 203 { 204 Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]); 205 unsigned int skip = rand(static_cast<unsigned int>(x[i].size()-1)); 206 while (true) { 207 if (it.width() > skip) { 208 v = it.min() + static_cast<int>(skip); 209 if (v == a[i]) { 210 if (it.width() == 1) { 211 ++it; v = it.min(); 212 } else if (v < it.max()) { 213 ++v; 214 } else { 215 --v; 216 } 217 } 218 break; 219 } 220 skip -= it.width(); ++it; 221 } 222 irt = IRT_NQ; 223 break; 224 } 225 } 226 } 227 228 void 229 TestSpace::rel(int i, Gecode::IntRelType irt, int n) { 230 if (opt.log) { 231 olog << ind(4) << "x[" << i << "] "; 232 switch (irt) { 233 case Gecode::IRT_EQ: olog << "="; break; 234 case Gecode::IRT_NQ: olog << "!="; break; 235 case Gecode::IRT_LQ: olog << "<="; break; 236 case Gecode::IRT_LE: olog << "<"; break; 237 case Gecode::IRT_GQ: olog << ">="; break; 238 case Gecode::IRT_GR: olog << ">"; break; 239 } 240 olog << " " << n << std::endl; 241 } 242 Gecode::rel(*this, x[i], irt, n); 243 } 244 245 void 246 TestSpace::rel(bool sol) { 247 int n = sol ? 1 : 0; 248 assert(reified); 249 if (opt.log) 250 olog << ind(4) << "b = " << n << std::endl; 251 Gecode::rel(*this, r.var(), Gecode::IRT_EQ, n); 252 } 253 254 void 255 TestSpace::assign(const Assignment& a, bool skip, Gecode::Support::RandomGenerator& rand) { 256 using namespace Gecode; 257 int i = skip ? 258 static_cast<int>(rand(static_cast<unsigned int>(a.size()))) : -1; 259 for (int j=a.size(); j--; ) 260 if (i != j) { 261 rel(j, IRT_EQ, a[j]); 262 if (Base::fixpoint(rand) && failed()) 263 return; 264 } 265 } 266 267 void 268 TestSpace::bound(Gecode::Support::RandomGenerator& rand) { 269 using namespace Gecode; 270 int i = rndvar(rand); 271 bool min = rand(2); 272 rel(i, IRT_EQ, min ? x[i].min() : x[i].max()); 273 } 274 275 void 276 TestSpace::prune(int i, bool bounds_only, Gecode::Support::RandomGenerator& rand) { 277 using namespace Gecode; 278 // Prune values 279 if (bounds_only) { 280 if (rand(2) && !x[i].assigned()) { 281 int v=x[i].min()+1+ 282 static_cast<int>(rand(static_cast<unsigned int>(x[i].max()-x[i].min()))); 283 assert((v > x[i].min()) && (v <= x[i].max())); 284 rel(i, Gecode::IRT_LE, v); 285 } 286 if (rand(2) && !x[i].assigned()) { 287 int v=x[i].min()+ 288 static_cast<int>(rand(static_cast<unsigned int>(x[i].max()-x[i].min()))); 289 assert((v < x[i].max()) && (v >= x[i].min())); 290 rel(i, Gecode::IRT_GR, v); 291 } 292 } else { 293 for (int vals = 294 static_cast<int>(rand(static_cast<unsigned int>(x[i].size()-1))+1); vals--; ) { 295 int v; 296 Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]); 297 unsigned int skip = rand(x[i].size()-1); 298 while (true) { 299 if (it.width() > skip) { 300 v = it.min() + static_cast<int>(skip); break; 301 } 302 skip -= it.width(); ++it; 303 } 304 rel(i, IRT_NQ, v); 305 } 306 } 307 } 308 309 void 310 TestSpace::prune(Gecode::Support::RandomGenerator& rand) { 311 prune(rndvar(rand), false, rand); 312 } 313 314 bool 315 TestSpace::prune(const Assignment& a, bool testfix, Gecode::Support::RandomGenerator& rand) { 316 using namespace Gecode; 317 // Select variable to be pruned 318 int i = rndvar(rand); 319 // Select mode for pruning 320 IntRelType irt; 321 int v; 322 rndrel(a, i, irt, v, rand); 323 if (irt != IRT_EQ) 324 rel(i, irt, v); 325 if (Base::fixpoint(rand)) { 326 if (failed() || !testfix) 327 return true; 328 TestSpace* c = static_cast<TestSpace*>(clone()); 329 if (opt.log) 330 olog << ind(3) << "Testing fixpoint on copy" << std::endl; 331 c->post(); 332 if (c->failed()) { 333 if (opt.log) 334 olog << ind(4) << "Copy failed after posting" << std::endl; 335 delete c; return false; 336 } 337 for (int j=x.size(); j--; ) 338 if (x[j].size() != c->x[j].size()) { 339 if (opt.log) 340 olog << ind(4) << "Different domain size" << std::endl; 341 delete c; return false; 342 } 343 if (reified && (r.var().size() != c->r.var().size())) { 344 if (opt.log) 345 olog << ind(4) << "Different control variable" << std::endl; 346 delete c; return false; 347 } 348 if (opt.log) 349 olog << ind(3) << "Finished testing fixpoint on copy" << std::endl; 350 delete c; 351 } 352 return true; 353 } 354 355 void 356 TestSpace::enable(void) { 357 Gecode::PropagatorGroup::all.enable(*this); 358 } 359 360 void 361 TestSpace::disable(void) { 362 Gecode::PropagatorGroup::all.disable(*this); 363 (void) status(); 364 } 365 366 bool 367 TestSpace::disabled(const Assignment& a, TestSpace& c, bool testfix, Gecode::Support::RandomGenerator& rand) { 368 using namespace Gecode; 369 // Disable propagators 370 c.disable(); 371 // Select variable to be pruned 372 int i = rndvar(rand); 373 // Select mode for pruning 374 IntRelType irt; 375 int v; 376 rndrel(a, i, irt, v, rand); 377 if (irt != IRT_EQ) { 378 rel(i, irt, v); 379 c.rel(i, irt, v); 380 } 381 // Enable propagators 382 c.enable(); 383 if (!testfix) 384 return true; 385 if (failed()) { 386 if (!c.failed()) { 387 if (opt.log) 388 olog << ind(3) << "No failure on disabled copy" << std::endl; 389 return false; 390 } 391 return true; 392 } 393 if (c.failed()) { 394 if (opt.log) 395 olog << ind(3) << "Failure on disabled copy" << std::endl; 396 return false; 397 } 398 for (int j=x.size(); j--; ) { 399 if (x[j].size() != c.x[j].size()) { 400 if (opt.log) 401 olog << ind(4) << "Different domain size" << std::endl; 402 return false; 403 } 404 if (reified && (r.var().size() != c.r.var().size())) { 405 if (opt.log) 406 olog << ind(4) << "Different control variable" << std::endl; 407 return false; 408 } 409 } 410 return true; 411 } 412 413 unsigned int 414 TestSpace::propagators(void) { 415 return Gecode::PropagatorGroup::all.size(*this); 416 } 417 418 const Gecode::IntPropLevel IntPropLevels::ipls[] = 419 {Gecode::IPL_DOM,Gecode::IPL_BND,Gecode::IPL_VAL}; 420 421 const Gecode::IntPropLevel IntPropBasicAdvanced::ipls[] = 422 {Gecode::IPL_BASIC_ADVANCED,Gecode::IPL_ADVANCED,Gecode::IPL_BASIC}; 423 424 const Gecode::IntRelType IntRelTypes::irts[] = 425 {Gecode::IRT_EQ,Gecode::IRT_NQ,Gecode::IRT_LQ, 426 Gecode::IRT_LE,Gecode::IRT_GQ,Gecode::IRT_GR}; 427 428 const Gecode::BoolOpType BoolOpTypes::bots[] = 429 {Gecode::BOT_AND,Gecode::BOT_OR,Gecode::BOT_IMP, 430 Gecode::BOT_EQV,Gecode::BOT_XOR}; 431 432 Assignment* 433 Test::assignment(void) const { 434 return new CpltAssignment(arity,dom); 435 } 436 437 438 /// Check the test result and handle failed test 439#define CHECK_TEST(T,M) \ 440do { \ 441if (opt.log) \ 442 olog << ind(3) << "Check: " << (M) << std::endl; \ 443if (!(T)) { \ 444 problem = (M); delete s; goto failed; \ 445} \ 446} while (false) 447 448 /// Start new test 449#define START_TEST(T) \ 450do { \ 451 if (opt.log) { \ 452 olog.str(""); \ 453 olog << ind(2) << "Testing: " << (T) << std::endl; \ 454 } \ 455 test = (T); \ 456} while (false) 457 458 bool 459 Test::ignore(const Assignment&) const { 460 return false; 461 } 462 463 void 464 Test::post(Gecode::Space&, Gecode::IntVarArray&, 465 Gecode::Reify) {} 466 467 bool 468 Test::run(void) { 469 using namespace Gecode; 470 const char* test = "NONE"; 471 const char* problem = "NONE"; 472 473 // Set up assignments 474 Assignment* ap = assignment(); 475 Assignment& a = *ap; 476 477 // Set up space for all solution search 478 TestSpace* search_s = new TestSpace(arity,dom,this); 479 post(*search_s,search_s->x); 480 branch(*search_s,search_s->x,INT_VAR_NONE(),INT_VAL_MIN()); 481 Search::Options search_o; 482 search_o.threads = 1; 483 DFS<TestSpace> e_s(search_s,search_o); 484 delete search_s; 485 486 while (a.has_more()) { 487 bool sol = solution(a); 488 if (opt.log) { 489 olog << ind(1) << "Assignment: " << a 490 << (sol ? " (solution)" : " (no solution)") 491 << std::endl; 492 } 493 494 START_TEST("Assignment (after posting)"); 495 { 496 TestSpace* s = new TestSpace(arity,dom,this); 497 TestSpace* sc = nullptr; 498 s->post(); 499 switch (_rand(2)) { 500 case 0: 501 if (opt.log) 502 olog << ind(3) << "No copy" << std::endl; 503 sc = s; 504 s = nullptr; 505 break; 506 case 1: 507 if (opt.log) 508 olog << ind(3) << "Copy" << std::endl; 509 if (s->status() != SS_FAILED) { 510 sc = static_cast<TestSpace*>(s->clone()); 511 } else { 512 sc = s; s = nullptr; 513 } 514 break; 515 default: assert(false); 516 } 517 sc->assign(a, false, _rand); 518 if (sol) { 519 CHECK_TEST(!sc->failed(), "Failed on solution"); 520 CHECK_TEST(sc->propagators()==0, "No subsumption"); 521 } else { 522 CHECK_TEST(sc->failed(), "Solved on non-solution"); 523 } 524 delete s; delete sc; 525 } 526 START_TEST("Partial assignment (after posting)"); 527 { 528 TestSpace* s = new TestSpace(arity,dom,this); 529 s->post(); 530 s->assign(a, true, _rand); 531 (void) s->failed(); 532 s->assign(a, false, _rand); 533 if (sol) { 534 CHECK_TEST(!s->failed(), "Failed on solution"); 535 CHECK_TEST(s->propagators()==0, "No subsumption"); 536 } else { 537 CHECK_TEST(s->failed(), "Solved on non-solution"); 538 } 539 delete s; 540 } 541 START_TEST("Assignment (after posting, disable)"); 542 { 543 TestSpace* s = new TestSpace(arity,dom,this); 544 s->post(); 545 s->disable(); 546 s->assign(a, false, _rand); 547 s->enable(); 548 if (sol) { 549 CHECK_TEST(!s->failed(), "Failed on solution"); 550 CHECK_TEST(s->propagators()==0, "No subsumption"); 551 } else { 552 CHECK_TEST(s->failed(), "Solved on non-solution"); 553 } 554 delete s; 555 } 556 START_TEST("Partial assignment (after posting, disable)"); 557 { 558 TestSpace* s = new TestSpace(arity,dom,this); 559 s->post(); 560 s->assign(a, true, _rand); 561 s->disable(); 562 (void) s->failed(); 563 s->assign(a, false, _rand); 564 s->enable(); 565 if (sol) { 566 CHECK_TEST(!s->failed(), "Failed on solution"); 567 CHECK_TEST(s->propagators()==0, "No subsumption"); 568 } else { 569 CHECK_TEST(s->failed(), "Solved on non-solution"); 570 } 571 delete s; 572 } 573 START_TEST("Assignment (before posting)"); 574 { 575 TestSpace* s = new TestSpace(arity,dom,this); 576 s->assign(a, false, _rand); 577 s->post(); 578 if (sol) { 579 CHECK_TEST(!s->failed(), "Failed on solution"); 580 CHECK_TEST(s->propagators()==0, "No subsumption"); 581 } else { 582 CHECK_TEST(s->failed(), "Solved on non-solution"); 583 } 584 delete s; 585 } 586 START_TEST("Partial assignment (before posting)"); 587 { 588 TestSpace* s = new TestSpace(arity,dom,this); 589 s->assign(a, true, _rand); 590 s->post(); 591 (void) s->failed(); 592 s->assign(a, false, _rand); 593 if (sol) { 594 CHECK_TEST(!s->failed(), "Failed on solution"); 595 CHECK_TEST(s->propagators()==0, "No subsumption"); 596 } else { 597 CHECK_TEST(s->failed(), "Solved on non-solution"); 598 } 599 delete s; 600 } 601 START_TEST("Prune"); 602 { 603 TestSpace* s = new TestSpace(arity,dom,this); 604 s->post(); 605 while (!s->failed() && !s->assigned()) 606 if (!s->prune(a, testfix, _rand)) { 607 problem = "No fixpoint"; 608 delete s; 609 goto failed; 610 } 611 s->assign(a, false, _rand); 612 if (sol) { 613 CHECK_TEST(!s->failed(), "Failed on solution"); 614 CHECK_TEST(s->propagators()==0, "No subsumption"); 615 } else { 616 CHECK_TEST(s->failed(), "Solved on non-solution"); 617 } 618 delete s; 619 } 620 START_TEST("Prune (disable)"); 621 { 622 TestSpace* s = new TestSpace(arity,dom,this); 623 TestSpace* c = static_cast<TestSpace*>(s->clone()); 624 s->post(); c->post(); 625 while (!s->failed() && !s->assigned()) 626 if (!s->disabled(a, *c, testfix, _rand)) { 627 problem = "Different result after re-enable"; 628 delete s; delete c; 629 goto failed; 630 } 631 if (testfix && (s->failed() != c->failed())) { 632 problem = "Different failure after re-enable"; 633 delete s; delete c; 634 goto failed; 635 } 636 delete s; delete c; 637 } 638 if (!ignore(a)) { 639 if (eqv()) { 640 { 641 START_TEST("Assignment reified (rewrite after post, <=>)"); 642 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 643 s->post(); 644 s->rel(sol); 645 s->assign(a, false, _rand); 646 CHECK_TEST(!s->failed(), "Failed"); 647 CHECK_TEST(s->propagators()==0, "No subsumption"); 648 delete s; 649 } 650 { 651 START_TEST("Assignment reified (rewrite failure, <=>)"); 652 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 653 s->post(); 654 s->rel(!sol); 655 s->assign(a, false, _rand); 656 CHECK_TEST(s->failed(), "Not failed"); 657 delete s; 658 } 659 { 660 START_TEST("Assignment reified (immediate rewrite, <=>)"); 661 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 662 s->rel(sol); 663 s->post(); 664 s->assign(a, false, _rand); 665 CHECK_TEST(!s->failed(), "Failed"); 666 CHECK_TEST(s->propagators()==0, "No subsumption"); 667 delete s; 668 } 669 { 670 START_TEST("Assignment reified (immediate failure, <=>)"); 671 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 672 s->rel(!sol); 673 s->post(); 674 s->assign(a, false, _rand); 675 CHECK_TEST(s->failed(), "Not failed"); 676 delete s; 677 } 678 { 679 START_TEST("Assignment reified (before posting, <=>)"); 680 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 681 s->assign(a, false, _rand); 682 s->post(); 683 CHECK_TEST(!s->failed(), "Failed"); 684 CHECK_TEST(s->propagators()==0, "No subsumption"); 685 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 686 if (sol) { 687 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 688 } else { 689 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 690 } 691 delete s; 692 } 693 { 694 START_TEST("Assignment reified (after posting, <=>)"); 695 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 696 s->post(); 697 s->assign(a, false, _rand); 698 CHECK_TEST(!s->failed(), "Failed"); 699 CHECK_TEST(s->propagators()==0, "No subsumption"); 700 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 701 if (sol) { 702 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 703 } else { 704 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 705 } 706 delete s; 707 } 708 { 709 START_TEST("Assignment reified (after posting, <=>, disable)"); 710 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 711 s->post(); 712 s->disable(); 713 s->assign(a, false, _rand); 714 s->enable(); 715 CHECK_TEST(!s->failed(), "Failed"); 716 CHECK_TEST(s->propagators()==0, "No subsumption"); 717 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 718 if (sol) { 719 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 720 } else { 721 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 722 } 723 delete s; 724 } 725 { 726 START_TEST("Prune reified, <=>"); 727 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 728 s->post(); 729 while (!s->failed() && 730 (!s->assigned() || !s->r.var().assigned())) 731 if (!s->prune(a, testfix, _rand)) { 732 problem = "No fixpoint"; 733 delete s; 734 goto failed; 735 } 736 CHECK_TEST(!s->failed(), "Failed"); 737 CHECK_TEST(s->propagators()==0, "No subsumption"); 738 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 739 if (sol) { 740 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 741 } else { 742 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 743 } 744 delete s; 745 } 746 { 747 START_TEST("Prune reified, <=>, disable"); 748 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV); 749 TestSpace* c = static_cast<TestSpace*>(s->clone()); 750 s->post(); c->post(); 751 while (!s->failed() && 752 (!s->assigned() || !s->r.var().assigned())) 753 if (!s->disabled(a, *c, testfix, _rand)) { 754 problem = "No fixpoint"; 755 delete s; 756 delete c; 757 goto failed; 758 } 759 CHECK_TEST(!c->failed(), "Failed"); 760 CHECK_TEST(c->propagators()==0, "No subsumption"); 761 CHECK_TEST(c->r.var().assigned(), "Control variable unassigned"); 762 if (sol) { 763 CHECK_TEST(c->r.var().val()==1, "Zero on solution"); 764 } else { 765 CHECK_TEST(c->r.var().val()==0, "One on non-solution"); 766 } 767 delete s; 768 delete c; 769 } 770 } 771 772 if (imp()) { 773 { 774 START_TEST("Assignment reified (rewrite after post, =>)"); 775 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 776 s->post(); 777 s->rel(sol); 778 s->assign(a, false, _rand); 779 CHECK_TEST(!s->failed(), "Failed"); 780 CHECK_TEST(s->propagators()==0, "No subsumption"); 781 delete s; 782 } 783 { 784 START_TEST("Assignment reified (rewrite failure, =>)"); 785 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 786 s->post(); 787 s->rel(!sol); 788 s->assign(a, false, _rand); 789 if (sol) { 790 CHECK_TEST(!s->failed(), "Failed"); 791 CHECK_TEST(s->propagators()==0, "No subsumption"); 792 } else { 793 CHECK_TEST(s->failed(), "Not failed"); 794 } 795 delete s; 796 } 797 { 798 START_TEST("Assignment reified (immediate rewrite, =>)"); 799 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 800 s->rel(sol); 801 s->post(); 802 s->assign(a, false, _rand); 803 CHECK_TEST(!s->failed(), "Failed"); 804 CHECK_TEST(s->propagators()==0, "No subsumption"); 805 delete s; 806 } 807 { 808 START_TEST("Assignment reified (immediate failure, =>)"); 809 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 810 s->rel(!sol); 811 s->post(); 812 s->assign(a, false, _rand); 813 if (sol) { 814 CHECK_TEST(!s->failed(), "Failed"); 815 CHECK_TEST(s->propagators()==0, "No subsumption"); 816 } else { 817 CHECK_TEST(s->failed(), "Not failed"); 818 } 819 delete s; 820 } 821 { 822 START_TEST("Assignment reified (before posting, =>)"); 823 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 824 s->assign(a, false, _rand); 825 s->post(); 826 CHECK_TEST(!s->failed(), "Failed"); 827 CHECK_TEST(s->propagators()==0, "No subsumption"); 828 if (sol) { 829 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 830 } else { 831 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 832 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 833 } 834 delete s; 835 } 836 { 837 START_TEST("Assignment reified (after posting, =>)"); 838 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 839 s->post(); 840 s->assign(a, false, _rand); 841 CHECK_TEST(!s->failed(), "Failed"); 842 CHECK_TEST(s->propagators()==0, "No subsumption"); 843 if (sol) { 844 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 845 } else { 846 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 847 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 848 } 849 delete s; 850 } 851 { 852 START_TEST("Assignment reified (after posting, =>, disable)"); 853 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 854 s->post(); 855 s->disable(); 856 s->assign(a, false, _rand); 857 s->enable(); 858 CHECK_TEST(!s->failed(), "Failed"); 859 CHECK_TEST(s->propagators()==0, "No subsumption"); 860 if (sol) { 861 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 862 } else { 863 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 864 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 865 } 866 delete s; 867 } 868 { 869 START_TEST("Prune reified, =>"); 870 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 871 s->post(); 872 while (!s->failed() && 873 (!s->assigned() || (!sol && !s->r.var().assigned()))) 874 if (!s->prune(a, testfix, _rand)) { 875 problem = "No fixpoint"; 876 delete s; 877 goto failed; 878 } 879 CHECK_TEST(!s->failed(), "Failed"); 880 CHECK_TEST(s->propagators()==0, "No subsumption"); 881 if (sol) { 882 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 883 } else { 884 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 885 CHECK_TEST(s->r.var().val()==0, "One on non-solution"); 886 } 887 delete s; 888 } 889 { 890 START_TEST("Prune reified, =>, disable"); 891 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP); 892 TestSpace* c = static_cast<TestSpace*>(s->clone()); 893 s->post(); c->post(); 894 while (!s->failed() && 895 (!s->assigned() || (!sol && !s->r.var().assigned()))) 896 if (!s->disabled(a, *c, testfix, _rand)) { 897 problem = "No fixpoint"; 898 delete s; 899 delete c; 900 goto failed; 901 } 902 CHECK_TEST(!c->failed(), "Failed"); 903 CHECK_TEST(c->propagators()==0, "No subsumption"); 904 if (sol) { 905 CHECK_TEST(!c->r.var().assigned(), "Control variable assigned"); 906 } else { 907 CHECK_TEST(c->r.var().assigned(), "Control variable unassigned"); 908 CHECK_TEST(c->r.var().val()==0, "One on non-solution"); 909 } 910 delete s; 911 delete c; 912 } 913 } 914 915 if (pmi()) { 916 { 917 START_TEST("Assignment reified (rewrite after post, <=)"); 918 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 919 s->post(); 920 s->rel(sol); 921 s->assign(a, false, _rand); 922 CHECK_TEST(!s->failed(), "Failed"); 923 CHECK_TEST(s->propagators()==0, "No subsumption"); 924 delete s; 925 } 926 { 927 START_TEST("Assignment reified (rewrite failure, <=)"); 928 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 929 s->post(); 930 s->rel(!sol); 931 s->assign(a, false, _rand); 932 if (sol) { 933 CHECK_TEST(s->failed(), "Not failed"); 934 } else { 935 CHECK_TEST(!s->failed(), "Failed"); 936 CHECK_TEST(s->propagators()==0, "No subsumption"); 937 } 938 delete s; 939 } 940 { 941 START_TEST("Assignment reified (immediate rewrite, <=)"); 942 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 943 s->rel(sol); 944 s->post(); 945 s->assign(a, false, _rand); 946 CHECK_TEST(!s->failed(), "Failed"); 947 CHECK_TEST(s->propagators()==0, "No subsumption"); 948 delete s; 949 } 950 { 951 START_TEST("Assignment reified (immediate failure, <=)"); 952 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 953 s->rel(!sol); 954 s->post(); 955 s->assign(a, false, _rand); 956 if (sol) { 957 CHECK_TEST(s->failed(), "Not failed"); 958 } else { 959 CHECK_TEST(!s->failed(), "Failed"); 960 CHECK_TEST(s->propagators()==0, "No subsumption"); 961 } 962 delete s; 963 } 964 { 965 START_TEST("Assignment reified (before posting, <=)"); 966 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 967 s->assign(a, false, _rand); 968 s->post(); 969 CHECK_TEST(!s->failed(), "Failed"); 970 CHECK_TEST(s->propagators()==0, "No subsumption"); 971 if (sol) { 972 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 973 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 974 } else { 975 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 976 } 977 delete s; 978 } 979 { 980 START_TEST("Assignment reified (after posting, <=)"); 981 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 982 s->post(); 983 s->assign(a, false, _rand); 984 CHECK_TEST(!s->failed(), "Failed"); 985 CHECK_TEST(s->propagators()==0, "No subsumption"); 986 if (sol) { 987 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 988 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 989 } else { 990 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 991 } 992 delete s; 993 } 994 { 995 START_TEST("Assignment reified (after posting, <=, disable)"); 996 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 997 s->post(); 998 s->disable(); 999 s->assign(a, false, _rand); 1000 s->enable(); 1001 CHECK_TEST(!s->failed(), "Failed"); 1002 CHECK_TEST(s->propagators()==0, "No subsumption"); 1003 if (sol) { 1004 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 1005 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 1006 } else { 1007 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 1008 } 1009 delete s; 1010 } 1011 { 1012 START_TEST("Prune reified, <="); 1013 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 1014 s->post(); 1015 while (!s->failed() && 1016 (!s->assigned() || (sol && !s->r.var().assigned()))) 1017 if (!s->prune(a, testfix, _rand)) { 1018 problem = "No fixpoint"; 1019 delete s; 1020 goto failed; 1021 } 1022 CHECK_TEST(!s->failed(), "Failed"); 1023 CHECK_TEST(s->propagators()==0, "No subsumption"); 1024 if (sol) { 1025 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned"); 1026 CHECK_TEST(s->r.var().val()==1, "Zero on solution"); 1027 } else { 1028 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned"); 1029 } 1030 delete s; 1031 } 1032 { 1033 START_TEST("Prune reified, <=, disable"); 1034 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI); 1035 TestSpace* c = static_cast<TestSpace*>(s->clone()); 1036 s->post(); c->post(); 1037 while (!s->failed() && 1038 (!s->assigned() || (sol && !s->r.var().assigned()))) 1039 if (!s->disabled(a, *c, testfix, _rand)) { 1040 problem = "No fixpoint"; 1041 delete s; 1042 delete c; 1043 goto failed; 1044 } 1045 CHECK_TEST(!c->failed(), "Failed"); 1046 CHECK_TEST(c->propagators()==0, "No subsumption"); 1047 if (sol) { 1048 CHECK_TEST(c->r.var().assigned(), "Control variable unassigned"); 1049 CHECK_TEST(c->r.var().val()==1, "Zero on solution"); 1050 } else { 1051 CHECK_TEST(!c->r.var().assigned(), "Control variable assigned"); 1052 } 1053 delete s; 1054 delete c; 1055 } 1056 } 1057 } 1058 1059 if (testsearch) { 1060 if (sol) { 1061 START_TEST("Search"); 1062 TestSpace* s = e_s.next(); 1063 CHECK_TEST(s != nullptr, "Solutions exhausted"); 1064 CHECK_TEST(s->propagators()==0, "No subsumption"); 1065 for (int i=a.size(); i--; ) { 1066 CHECK_TEST(s->x[i].assigned(), "Unassigned variable"); 1067 CHECK_TEST(a[i] == s->x[i].val(), "Wrong value in solution"); 1068 } 1069 delete s; 1070 } 1071 } 1072 1073 a.next(_rand); 1074 } 1075 1076 if (testsearch) { 1077 test = "Search"; 1078 if (e_s.next() != nullptr) { 1079 problem = "Excess solutions"; 1080 goto failed; 1081 } 1082 } 1083 1084 switch (contest) { 1085 case CTL_NONE: break; 1086 case CTL_DOMAIN: { 1087 START_TEST("Full domain consistency"); 1088 TestSpace* s = new TestSpace(arity,dom,this); 1089 s->post(); 1090 if (!s->failed()) { 1091 while (!s->failed() && !s->assigned()) 1092 s->prune(_rand); 1093 CHECK_TEST(!s->failed(), "Failed"); 1094 CHECK_TEST(s->propagators()==0, "No subsumption"); 1095 } 1096 delete s; 1097 // Fall-through -- domain implies bounds(d) and bounds(z) 1098 } 1099 case CTL_BOUNDS_D: { 1100 START_TEST("Bounds(D)-consistency"); 1101 TestSpace* s = new TestSpace(arity,dom,this); 1102 s->post(); 1103 for (int i = s->x.size(); i--; ) 1104 s->prune(i, false, _rand); 1105 if (!s->failed()) { 1106 while (!s->failed() && !s->assigned()) 1107 s->bound(_rand); 1108 CHECK_TEST(!s->failed(), "Failed"); 1109 CHECK_TEST(s->propagators()==0, "No subsumption"); 1110 } 1111 delete s; 1112 // Fall-through -- bounds(d) implies bounds(z) 1113 } 1114 case CTL_BOUNDS_Z: { 1115 START_TEST("Bounds(Z)-consistency"); 1116 TestSpace* s = new TestSpace(arity,dom,this); 1117 s->post(); 1118 for (int i = s->x.size(); i--; ) 1119 s->prune(i, true, _rand); 1120 if (!s->failed()) { 1121 while (!s->failed() && !s->assigned()) 1122 s->bound(_rand); 1123 CHECK_TEST(!s->failed(), "Failed"); 1124 CHECK_TEST(s->propagators()==0, "No subsumption"); 1125 } 1126 delete s; 1127 break; 1128 } 1129 } 1130 1131 delete ap; 1132 return true; 1133 1134 failed: 1135 if (opt.log) 1136 olog << "FAILURE" << std::endl 1137 << ind(1) << "Test: " << test << std::endl 1138 << ind(1) << "Problem: " << problem << std::endl; 1139 if (a.has_more() && opt.log) 1140 olog << ind(1) << "Assignment: " << a << std::endl; 1141 delete ap; 1142 1143 return false; 1144 } 1145 1146}} 1147 1148#undef START_TEST 1149#undef CHECK_TEST 1150 1151// STATISTICS: test-int