00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "test/int.hh"
00041
00042 #include <algorithm>
00043
00044 namespace Test { namespace Int {
00045
00046
00047
00048
00049
00050
00051 void
00052 CpltAssignment::operator++(void) {
00053 int i = n-1;
00054 while (true) {
00055 ++dsv[i];
00056 if (dsv[i]() || (i == 0))
00057 return;
00058 dsv[i--].init(d);
00059 }
00060 }
00061
00062
00063
00064
00065
00066 void
00067 RandomAssignment::operator++(void) {
00068 for (int i = n; i--; )
00069 vals[i]=randval();
00070 a--;
00071 }
00072
00073 }}
00074
00075 std::ostream&
00076 operator<<(std::ostream& os, const Test::Int::Assignment& a) {
00077 int n = a.size();
00078 os << "{";
00079 for (int i=0; i<n; i++)
00080 os << a[i] << ((i!=n-1) ? "," : "}");
00081 return os;
00082 }
00083
00084 namespace Test { namespace Int {
00085
00087 class TestSpace : public Gecode::Space {
00088 public:
00090 Gecode::IntSet d;
00092 Gecode::IntVarArray x;
00094 Gecode::BoolVar b;
00096 bool reified;
00098 Test* test;
00099
00100 public:
00109 TestSpace(int n, Gecode::IntSet& d0, bool r, Test* t, bool log=true)
00110 : d(d0), x(this,n,d), b(this,0,1), reified(r), test(t) {
00111 if (opt.log && log) {
00112 olog << ind(2) << "Initial: x[]=" << x;
00113 if (reified)
00114 olog << " b=" << b;
00115 olog << std::endl;
00116 }
00117 }
00119 TestSpace(bool share, TestSpace& s)
00120 : Gecode::Space(share,s), d(s.d), reified(s.reified), test(s.test) {
00121 x.update(this, share, s.x);
00122 b.update(this, share, s.b);
00123 }
00125 virtual Gecode::Space* copy(bool share) {
00126 return new TestSpace(share,*this);
00127 }
00128
00130 TestSpace* cloneWithReflection(void) {
00131 TestSpace* c = new TestSpace(x.size(), d, reified, test);
00132 Gecode::Reflection::VarMap vm;
00133 vm.putArray(this, x, "x");
00134 vm.put(this, b, "b");
00135 Gecode::Reflection::VarMap cvm;
00136 cvm.putArray(c, c->x, "x", true);
00137 cvm.put(c, c->b, "b", true);
00138 Gecode::Reflection::Unreflector d(c, cvm);
00139 Gecode::Reflection::VarMapIter vmi(vm);
00140 try {
00141 for (Gecode::Reflection::ActorSpecIter si(this, vm); si(); ++si) {
00142 Gecode::Reflection::ActorSpec s = si.actor();
00143 for (; vmi(); ++vmi) {
00144 try {
00145 d.var(vmi.spec());
00146 } catch (Gecode::Reflection::ReflectionException e) {
00147 delete c;
00148 return NULL;
00149 }
00150 }
00151 try {
00152 d.post(s);
00153 } catch (Gecode::Reflection::ReflectionException e) {
00154 delete c;
00155 return NULL;
00156 }
00157 }
00158 for (; vmi(); ++vmi) {
00159 try {
00160 d.var(vmi.spec());
00161 } catch (Gecode::Reflection::ReflectionException e) {
00162 delete c;
00163 return NULL;
00164 }
00165 }
00166 assert(c != NULL);
00167 if (failed()) {
00168 c->fail();
00169 }
00170 return c;
00171 } catch (Gecode::Reflection::ReflectionException e) {
00172 delete c;
00173 if (status() == Gecode::SS_FAILED)
00174 return this;
00175 return static_cast<TestSpace*>(clone());
00176 }
00177 }
00178
00180 bool assigned(void) const {
00181 for (int i=x.size(); i--; )
00182 if (!x[i].assigned())
00183 return false;
00184 return true;
00185 }
00186
00188 void post(void) {
00189 if (reified){
00190 test->post(this,x,b);
00191 if (opt.log)
00192 olog << ind(3) << "Posting reified propagator" << std::endl;
00193 } else {
00194 test->post(this,x);
00195 if (opt.log)
00196 olog << ind(3) << "Posting propagator" << std::endl;
00197 }
00198 }
00200 bool failed(void) {
00201 if (opt.log) {
00202 olog << ind(3) << "Fixpoint: " << x;
00203 bool f=(status() == Gecode::SS_FAILED);
00204 olog << std::endl << ind(3) << " --> " << x << std::endl;
00205 return f;
00206 } else {
00207 return status() == Gecode::SS_FAILED;
00208 }
00209 }
00211 void rel(int i, Gecode::IntRelType irt, int n) {
00212 if (opt.log) {
00213 olog << ind(4) << "x[" << i << "] ";
00214 switch (irt) {
00215 case Gecode::IRT_EQ: olog << "="; break;
00216 case Gecode::IRT_NQ: olog << "!="; break;
00217 case Gecode::IRT_LQ: olog << "<="; break;
00218 case Gecode::IRT_LE: olog << "<"; break;
00219 case Gecode::IRT_GQ: olog << ">="; break;
00220 case Gecode::IRT_GR: olog << ">"; break;
00221 }
00222 olog << " " << n << std::endl;
00223 }
00224 Gecode::rel(this, x[i], irt, n);
00225 }
00227 void rel(bool sol) {
00228 int n = sol ? 1 : 0;
00229 assert(reified);
00230 if (opt.log)
00231 olog << ind(4) << "b = " << n << std::endl;
00232 Gecode::rel(this, b, Gecode::IRT_EQ, n);
00233 }
00235 void assign(const Assignment& a, bool skip=false) {
00236 using namespace Gecode;
00237 int i = skip ? static_cast<int>(Base::rand(a.size())) : -1;
00238 for (int j=a.size(); j--; )
00239 if (i != j) {
00240 rel(j, IRT_EQ, a[j]);
00241 if (Base::fixpoint() && failed())
00242 return;
00243 }
00244 }
00246 void prune(void) {
00247 using namespace Gecode;
00248
00249 int i = Base::rand(x.size());
00250 while (x[i].assigned()) {
00251 i = (i+1) % x.size();
00252 }
00253
00254 for (int vals = Base::rand(x[i].size()-1)+1; vals--; ) {
00255 int v;
00256 Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]);
00257 unsigned int skip = Base::rand(x[i].size()-1);
00258 while (true) {
00259 if (it.width() > skip) {
00260 v = it.min() + skip; break;
00261 }
00262 skip -= it.width(); ++it;
00263 }
00264 rel(i, IRT_NQ, v);
00265 }
00266 }
00268 bool prune(const Assignment& a) {
00269
00270 int i = Base::rand(x.size());
00271 while (x[i].assigned())
00272 i = (i+1) % x.size();
00273
00274 switch (Base::rand(3)) {
00275 case 0:
00276 if (a[i] < x[i].max()) {
00277 int v=a[i]+1+Base::rand(static_cast
00278 <unsigned int>(x[i].max()-a[i]));
00279 assert((v > a[i]) && (v <= x[i].max()));
00280 rel(i, Gecode::IRT_LE, v);
00281 }
00282 break;
00283 case 1:
00284 if (a[i] > x[i].min()) {
00285 int v=x[i].min()+Base::rand(static_cast
00286 <unsigned int>(a[i]-x[i].min()));
00287 assert((v < a[i]) && (v >= x[i].min()));
00288 rel(i, Gecode::IRT_GR, v);
00289 }
00290 break;
00291 default:
00292 {
00293 int v;
00294 Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]);
00295 unsigned int skip = Base::rand(x[i].size()-1);
00296 while (true) {
00297 if (it.width() > skip) {
00298 v = it.min() + skip;
00299 if (v == a[i]) {
00300 if (it.width() == 1) {
00301 ++it; v = it.min();
00302 } else if (v < it.max()) {
00303 ++v;
00304 } else {
00305 --v;
00306 }
00307 }
00308 break;
00309 }
00310 skip -= it.width(); ++it;
00311 }
00312 rel(i, Gecode::IRT_NQ, v);
00313 break;
00314 }
00315 }
00316 if (Base::fixpoint()) {
00317 if (failed())
00318 return true;
00319 TestSpace* c = static_cast<TestSpace*>(clone());
00320 if (opt.log)
00321 olog << ind(3) << "Testing fixpoint on copy" << std::endl;
00322 c->post();
00323 if (c->failed()) {
00324 delete c; return false;
00325 }
00326 for (int i=x.size(); i--; )
00327 if (x[i].size() != c->x[i].size()) {
00328 delete c; return false;
00329 }
00330 if (reified && (b.size() != c->b.size())) {
00331 delete c; return false;
00332 }
00333 if (opt.log)
00334 olog << ind(3) << "Finished testing fixpoint on copy" << std::endl;
00335 delete c;
00336 }
00337 return true;
00338 }
00339
00340 };
00341
00342 const Gecode::IntConLevel IntConLevels::icls[] =
00343 {Gecode::ICL_DOM,Gecode::ICL_BND,Gecode::ICL_VAL};
00344
00345 const Gecode::IntRelType IntRelTypes::irts[] =
00346 {Gecode::IRT_EQ,Gecode::IRT_NQ,Gecode::IRT_LQ,
00347 Gecode::IRT_LE,Gecode::IRT_GQ,Gecode::IRT_GR};
00348
00349 const Gecode::BoolOpType BoolOpTypes::bots[] =
00350 {Gecode::BOT_AND,Gecode::BOT_OR,Gecode::BOT_IMP,
00351 Gecode::BOT_EQV,Gecode::BOT_XOR};
00352
00353 Assignment*
00354 Test::assignment(void) const {
00355 return new CpltAssignment(arity,dom);
00356 }
00357
00358
00360 #define CHECK_TEST(T,M) \
00361 if (opt.log) \
00362 olog << ind(3) << "Check: " << (M) << std::endl; \
00363 if (!(T)) { \
00364 problem = (M); delete s; goto failed; \
00365 }
00366
00368 #define START_TEST(T) \
00369 if (opt.log) { \
00370 olog.str(""); \
00371 olog << ind(2) << "Testing: " << (T) << std::endl; \
00372 } \
00373 test = (T);
00374
00375 bool
00376 Test::ignore(const Assignment&) const {
00377 return false;
00378 }
00379
00380 void
00381 Test::post(Gecode::Space*, Gecode::IntVarArray&,
00382 Gecode::BoolVar) {}
00383
00384 bool
00385 Test::run(void) {
00386 using namespace Gecode;
00387 const char* test = "NONE";
00388 const char* problem = "NONE";
00389
00390
00391 Assignment* ap = assignment();
00392 Assignment& a = *ap;
00393
00394
00395 TestSpace* search_s = new TestSpace(arity,dom,false,this,false);
00396 post(search_s,search_s->x);
00397 branch(search_s,search_s->x,INT_VAR_NONE,INT_VAL_MIN);
00398 DFS<TestSpace> e_s(search_s);
00399 delete search_s;
00400
00401 while (a()) {
00402 bool sol = solution(a);
00403 if (opt.log) {
00404 olog << ind(1) << "Assignment: " << a
00405 << (sol ? " (solution)" : " (no solution)")
00406 << std::endl;
00407 }
00408
00409 START_TEST("Assignment (after posting)");
00410 {
00411 TestSpace* s = new TestSpace(arity,dom,false,this);
00412 TestSpace* sc = NULL;
00413 s->post();
00414 switch (Base::rand(3)) {
00415 case 0:
00416 if (opt.log)
00417 olog << ind(3) << "No copy" << std::endl;
00418 sc = s;
00419 s = NULL;
00420 break;
00421 case 1:
00422 if (opt.log)
00423 olog << ind(3) << "Unshared copy" << std::endl;
00424 if (s->status() != SS_FAILED) {
00425 sc = static_cast<TestSpace*>(s->clone(false));
00426 } else {
00427 sc = s; s = NULL;
00428 }
00429 break;
00430 case 2:
00431 if (opt.log)
00432 olog << ind(3) << "Shared copy" << std::endl;
00433 if (s->status() != SS_FAILED) {
00434 sc = static_cast<TestSpace*>(s->clone(true));
00435 } else {
00436 sc = s; s = NULL;
00437 }
00438 break;
00439 default: assert(false);
00440 }
00441 sc->assign(a);
00442 if (sol) {
00443 CHECK_TEST(!sc->failed(), "Failed on solution");
00444 CHECK_TEST(sc->propagators()==0, "No subsumption");
00445 } else {
00446 CHECK_TEST(sc->failed(), "Solved on non-solution");
00447 }
00448 delete s; delete sc;
00449 }
00450 if (opt.reflection) {
00451 START_TEST("Assignment (after posting + reflection)");
00452 {
00453 TestSpace* s = new TestSpace(arity,dom,false,this);
00454 TestSpace* sc = NULL;
00455 s->post();
00456 if (opt.log)
00457 olog << ind(3) << "Reflection copy" << std::endl;
00458 sc = s->cloneWithReflection();
00459 if (sc == s)
00460 s = NULL;
00461 CHECK_TEST(sc != NULL, "Reflection error");
00462 sc->assign(a);
00463 if (sol) {
00464 CHECK_TEST(!sc->failed(), "Failed on solution");
00465 CHECK_TEST(sc->propagators()==0, "No subsumption");
00466 } else {
00467 CHECK_TEST(sc->failed(), "Solved on non-solution");
00468 }
00469 delete s; delete sc;
00470 }
00471 }
00472 START_TEST("Partial assignment (after posting)");
00473 {
00474 TestSpace* s = new TestSpace(arity,dom,false,this);
00475 s->post();
00476 s->assign(a,true);
00477 (void) s->failed();
00478 s->assign(a);
00479 if (sol) {
00480 CHECK_TEST(!s->failed(), "Failed on solution");
00481 CHECK_TEST(s->propagators()==0, "No subsumption");
00482 } else {
00483 CHECK_TEST(s->failed(), "Solved on non-solution");
00484 }
00485 delete s;
00486 }
00487 START_TEST("Assignment (before posting)");
00488 {
00489 TestSpace* s = new TestSpace(arity,dom,false,this);
00490 s->assign(a);
00491 s->post();
00492 if (sol) {
00493 CHECK_TEST(!s->failed(), "Failed on solution");
00494 CHECK_TEST(s->propagators()==0, "No subsumption");
00495 } else {
00496 CHECK_TEST(s->failed(), "Solved on non-solution");
00497 }
00498 delete s;
00499 }
00500 START_TEST("Partial assignment (before posting)");
00501 {
00502 TestSpace* s = new TestSpace(arity,dom,false,this);
00503 s->assign(a,true);
00504 s->post();
00505 (void) s->failed();
00506 s->assign(a);
00507 if (sol) {
00508 CHECK_TEST(!s->failed(), "Failed on solution");
00509 CHECK_TEST(s->propagators()==0, "No subsumption");
00510 } else {
00511 CHECK_TEST(s->failed(), "Solved on non-solution");
00512 }
00513 delete s;
00514 }
00515 START_TEST("Prune");
00516 {
00517 TestSpace* s = new TestSpace(arity,dom,false,this);
00518 s->post();
00519 while (!s->failed() && !s->assigned())
00520 if (!s->prune(a)) {
00521 problem = "No fixpoint";
00522 delete s;
00523 goto failed;
00524 }
00525 s->assign(a);
00526 if (sol) {
00527 CHECK_TEST(!s->failed(), "Failed on solution");
00528 CHECK_TEST(s->propagators()==0, "No subsumption");
00529 } else {
00530 CHECK_TEST(s->failed(), "Solved on non-solution");
00531 }
00532 delete s;
00533 }
00534
00535 if (reified && !ignore(a)) {
00536 START_TEST("Assignment reified (rewrite after post)");
00537 {
00538 TestSpace* s = new TestSpace(arity,dom,true,this);
00539 s->post();
00540 s->rel(sol);
00541 s->assign(a);
00542 CHECK_TEST(!s->failed(), "Failed");
00543 CHECK_TEST(s->propagators()==0, "No subsumption");
00544 delete s;
00545 }
00546 START_TEST("Assignment reified (immediate rewrite)");
00547 {
00548 TestSpace* s = new TestSpace(arity,dom,true,this);
00549 s->rel(sol);
00550 s->post();
00551 s->assign(a);
00552 CHECK_TEST(!s->failed(), "Failed");
00553 CHECK_TEST(s->propagators()==0, "No subsumption");
00554 delete s;
00555 }
00556 START_TEST("Assignment reified (before posting)");
00557 {
00558 TestSpace* s = new TestSpace(arity,dom,true,this);
00559 s->assign(a);
00560 s->post();
00561 CHECK_TEST(!s->failed(), "Failed");
00562 CHECK_TEST(s->propagators()==0, "No subsumption");
00563 CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00564 if (sol) {
00565 CHECK_TEST(s->b.val()==1, "Zero on solution");
00566 } else {
00567 CHECK_TEST(s->b.val()==0, "One on non-solution");
00568 }
00569 delete s;
00570 }
00571 START_TEST("Assignment reified (after posting)");
00572 {
00573 TestSpace* s = new TestSpace(arity,dom,true,this);
00574 s->post();
00575 s->assign(a);
00576 CHECK_TEST(!s->failed(), "Failed");
00577 CHECK_TEST(s->propagators()==0, "No subsumption");
00578 CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00579 if (sol) {
00580 CHECK_TEST(s->b.val()==1, "Zero on solution");
00581 } else {
00582 CHECK_TEST(s->b.val()==0, "One on non-solution");
00583 }
00584 delete s;
00585 }
00586 if (opt.reflection) {
00587 START_TEST("Assignment reified (after posting + reflection)");
00588 {
00589 TestSpace* s = new TestSpace(arity,dom,true,this);
00590 TestSpace* sc = NULL;
00591 s->post();
00592 if (opt.log)
00593 olog << ind(3) << "Reflection copy" << std::endl;
00594 sc = s->cloneWithReflection();
00595 if (sc == s)
00596 s = NULL;
00597 CHECK_TEST(sc != NULL, "Reflection error");
00598 sc->assign(a);
00599 CHECK_TEST(!sc->failed(), "Failed");
00600 CHECK_TEST(sc->propagators()==0, "No subsumption");
00601 CHECK_TEST(sc->b.assigned(), "Control variable unassigned");
00602 if (sol) {
00603 CHECK_TEST(sc->b.val()==1, "Zero on solution");
00604 } else {
00605 CHECK_TEST(sc->b.val()==0, "One on non-solution");
00606 }
00607 delete s; delete sc;
00608 }
00609 }
00610 START_TEST("Prune reified");
00611 {
00612 TestSpace* s = new TestSpace(arity,dom,true,this);
00613 s->post();
00614 while (!s->failed() && (!s->assigned() || !s->b.assigned()))
00615 if (!s->prune(a)) {
00616 problem = "No fixpoint";
00617 delete s;
00618 goto failed;
00619 }
00620 CHECK_TEST(!s->failed(), "Failed");
00621 CHECK_TEST(s->propagators()==0, "No subsumption");
00622 CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00623 if (sol) {
00624 CHECK_TEST(s->b.val()==1, "Zero on solution");
00625 } else {
00626 CHECK_TEST(s->b.val()==0, "One on non-solution");
00627 }
00628 delete s;
00629 }
00630 }
00631
00632 if (testsearch) {
00633 if (sol) {
00634 START_TEST("Search");
00635 TestSpace* s = e_s.next();
00636 CHECK_TEST(s != NULL, "Solutions exhausted");
00637 CHECK_TEST(s->propagators()==0, "No subsumption");
00638 for (int i=a.size(); i--; ) {
00639 CHECK_TEST(s->x[i].assigned(), "Unassigned variable");
00640 CHECK_TEST(a[i] == s->x[i].val(), "Wrong value in solution");
00641 }
00642 delete s;
00643 }
00644 }
00645
00646 ++a;
00647 }
00648
00649 if (testsearch) {
00650 test = "Search";
00651 if (e_s.next() != NULL) {
00652 problem = "Excess solutions";
00653 goto failed;
00654 }
00655 }
00656
00657 if ((icl == ICL_DOM) && testdomcon) {
00658 START_TEST("Full domain consistency");
00659 TestSpace* s = new TestSpace(arity,dom,false,this);
00660 s->post();
00661 while (!s->failed() && !s->assigned())
00662 s->prune();
00663 CHECK_TEST(!s->failed(), "Failed");
00664 CHECK_TEST(s->propagators()==0, "No subsumption");
00665 delete s;
00666 }
00667
00668 delete ap;
00669 return true;
00670
00671 failed:
00672 if (opt.log)
00673 olog << "FAILURE" << std::endl
00674 << ind(1) << "Test: " << test << std::endl
00675 << ind(1) << "Problem: " << problem << std::endl;
00676 if (a() && opt.log)
00677 olog << ind(1) << "Assignment: " << a << std::endl;
00678 delete ap;
00679
00680 return false;
00681 }
00682
00683 }}
00684
00685 #undef START_TEST
00686 #undef CHECK_TEST
00687
00688