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
00041 #include "test/cpltset.hh"
00042
00043 #include "gecode/int.hh"
00044 #include "gecode/iter.hh"
00045 #include <algorithm>
00046
00048 #define CHECK_TEST(T,M) \
00049 if (opt.log) \
00050 olog << ind(3) << "Check: " << (M) << std::endl; \
00051 if (!(T)) { \
00052 problem = (M); delete s; goto failed; \
00053 }
00054
00056 #define START_TEST(T) \
00057 if (opt.log) { \
00058 olog.str(""); \
00059 olog << ind(2) << "Testing: " << (T) << std::endl; \
00060 } \
00061 test = (T);
00062
00063 namespace Test { namespace CpltSet {
00064
00066 class CpltSetTestSpace : public Gecode::Space {
00067 public:
00069 Gecode::CpltSetVarArray x;
00071 Gecode::IntVarArray y;
00073 int withInt;
00075 Gecode::BoolVar b;
00077 bool reified;
00079 CpltSetTest* test;
00081 const Options opt;
00082
00083 public:
00093 CpltSetTestSpace(int n, Gecode::IntSet& d, int i, bool r, CpltSetTest* t,
00094 const Options& o, bool log=true)
00095 : x(this, n, Gecode::IntSet::empty, d), y(this, i, d), withInt(i),
00096 b(this, 0, 1), reified(r), test(t), opt(o) {
00097 if (opt.log && log) {
00098 olog << ind(2) << "Initial: x[]=" << x;
00099 olog << " y[]=" << y;
00100 if (reified)
00101 olog << " b=" << b;
00102 olog << std::endl;
00103 }
00104 }
00105
00107 CpltSetTestSpace(bool share, CpltSetTestSpace& s)
00108 : Space(share,s), withInt(s.withInt), reified(s.reified), test(s.test),
00109 opt(s.opt) {
00110 x.update(this, share, s.x);
00111 y.update(this, share, s.y);
00112 b.update(this, share, s.b);
00113 }
00114
00116 virtual Space* copy(bool share) {
00117 return new CpltSetTestSpace(share,*this);
00118 }
00119
00121 void post(void) {
00122 if (reified){
00123 test->post(this,x,y,b);
00124 if (opt.log)
00125 olog << ind(3) << "Posting reified propagator" << std::endl;
00126 } else {
00127 test->post(this,x,y);
00128 if (opt.log)
00129 olog << ind(3) << "Posting propagator" << std::endl;
00130 }
00131 }
00133 bool failed(void) {
00134 if (opt.log) {
00135 olog << ind(3) << "Fixpoint: x[]=" << x
00136 << " y[]=" << y << std::endl;
00137 bool f=(status() == Gecode::SS_FAILED);
00138 olog << ind(3) << " --> x[]=" << x
00139 << " y[]=" << y << std::endl;
00140 return f;
00141 } else {
00142 return status() == Gecode::SS_FAILED;
00143 }
00144 }
00145
00147 void rel(int i, Gecode::SetRelType srt, const Gecode::IntSet& is) {
00148 if (opt.log) {
00149 olog << ind(4) << "x[" << i << "] ";
00150 switch (srt) {
00151 case Gecode::SRT_EQ: olog << "="; break;
00152 case Gecode::SRT_NQ: olog << "!="; break;
00153 case Gecode::SRT_SUB: olog << "<="; break;
00154 case Gecode::SRT_SUP: olog << ">="; break;
00155 case Gecode::SRT_DISJ: olog << "||"; break;
00156 case Gecode::SRT_CMPL: olog << "^-1 = "; break;
00157 }
00158 olog << is << std::endl;
00159 }
00160 Gecode::dom(this, x[i], srt, is);
00161 }
00163 void cardinality(int i, int cmin, int cmax) {
00164 if (opt.log) {
00165 olog << ind(4) << cmin << " <= #(x[" << i << "]) <= " << cmax
00166 << std::endl;
00167 }
00168 Gecode::cardinality(this, x[i], cmin, cmax);
00169 }
00171 void rel(int i, Gecode::IntRelType irt, int n) {
00172 if (opt.log) {
00173 olog << ind(4) << "y[" << i << "] ";
00174 switch (irt) {
00175 case Gecode::IRT_EQ: olog << "="; break;
00176 case Gecode::IRT_NQ: olog << "!="; break;
00177 case Gecode::IRT_LQ: olog << "<="; break;
00178 case Gecode::IRT_LE: olog << "<"; break;
00179 case Gecode::IRT_GQ: olog << ">="; break;
00180 case Gecode::IRT_GR: olog << ">"; break;
00181 }
00182 olog << " " << n << std::endl;
00183 }
00184 Gecode::rel(this, y[i], irt, n);
00185 }
00187 void rel(bool sol) {
00188 int n = sol ? 1 : 0;
00189 assert(reified);
00190 if (opt.log)
00191 olog << ind(4) << "b = " << n << std::endl;
00192 Gecode::rel(this, b, Gecode::IRT_EQ, n);
00193 }
00194
00196 void assign(const Test::Set::SetAssignment& a) {
00197 for (int i=a.size(); i--; ) {
00198 Test::Set::CountableSetRanges csv(a.lub, a[i]);
00199 Gecode::IntSet ai(csv);
00200 rel(i, Gecode::SRT_EQ, ai);
00201 if (Base::fixpoint() && failed())
00202 return;
00203 }
00204 for (int i=withInt; i--; ) {
00205 rel(i, Gecode::IRT_EQ, a.ints()[i]);
00206 if (Base::fixpoint() && failed())
00207 return;
00208 }
00209 }
00210
00212 bool assigned(void) const {
00213 for (int i=x.size(); i--; )
00214 if (!x[i].assigned())
00215 return false;
00216 for (int i=y.size(); i--; )
00217 if (!y[i].assigned())
00218 return false;
00219 return true;
00220 }
00221
00222 void removeFromLub(int v, int i, const Test::Set::SetAssignment& a) {
00223 Gecode::CpltSetVarUnknownRanges ur(x[i]);
00224 Test::Set::CountableSetRanges air(a.lub, a[i]);
00225 Gecode::Iter::Ranges::Diff<Gecode::CpltSetVarUnknownRanges,
00226 Test::Set::CountableSetRanges> diff(ur, air);
00227 Gecode::Iter::Ranges::ToValues<Gecode::Iter::Ranges::Diff
00228 <Gecode::CpltSetVarUnknownRanges, Test::Set::CountableSetRanges> >
00229 diffV(diff);
00230 for (int j=0; j<v; j++, ++diffV);
00231 rel(i, Gecode::SRT_DISJ, Gecode::IntSet(diffV.val(), diffV.val()));
00232 }
00233
00234 void addToGlb(int v, int i, const Test::Set::SetAssignment& a) {
00235 Gecode::CpltSetVarUnknownRanges ur(x[i]);
00236 Test::Set::CountableSetRanges air(a.lub, a[i]);
00237 Gecode::Iter::Ranges::Inter<Gecode::CpltSetVarUnknownRanges,
00238 Test::Set::CountableSetRanges> inter(ur, air);
00239 Gecode::Iter::Ranges::ToValues<Gecode::Iter::Ranges::Inter
00240 <Gecode::CpltSetVarUnknownRanges, Test::Set::CountableSetRanges> >
00241 interV(inter);
00242 for (int j=0; j<v; j++, ++interV);
00243 rel(i, Gecode::SRT_SUP, Gecode::IntSet(interV.val(), interV.val()));
00244 }
00245
00246 bool fixprob(void) {
00247 if (failed())
00248 return true;
00249 CpltSetTestSpace* c = static_cast<CpltSetTestSpace*>(clone());
00250 if (opt.log)
00251 olog << ind(3) << "Testing fixpoint on copy" << std::endl;
00252 c->post();
00253 if (c->failed()) {
00254 delete c; return false;
00255 }
00256
00257 for (int i=x.size(); i--; )
00258 if (Gecode::CpltSet::CpltSetView(x[i]).dom() !=
00259 Gecode::CpltSet::CpltSetView(c->x[i]).dom()) {
00260 delete c;
00261 return false;
00262 }
00263 for (int i=y.size(); i--; )
00264 if (y[i].size() != c->y[i].size()) {
00265 delete c; return false;
00266 }
00267 if (reified && (b.size() != c->b.size())) {
00268 delete c; return false;
00269 }
00270 if (opt.log)
00271 olog << ind(3) << "Finished testing fixpoint on copy" << std::endl;
00272 delete c;
00273 return true;
00274 }
00275
00276 bool prune(const Test::Set::SetAssignment& a) {
00277 bool setsAssigned = true;
00278 for (int j=x.size(); j--; )
00279 if (!x[j].assigned()) {
00280 setsAssigned = false;
00281 break;
00282 }
00283 bool intsAssigned = true;
00284 for (int j=y.size(); j--; )
00285 if (!y[j].assigned()) {
00286 intsAssigned = false;
00287 break;
00288 }
00289
00290
00291 int i;
00292 if (intsAssigned) {
00293 i = Base::rand(x.size());
00294 } else if (setsAssigned) {
00295 i = Base::rand(y.size());
00296 } else {
00297 i = Base::rand(x.size()+y.size());
00298 }
00299
00300 if (setsAssigned || i>=x.size()) {
00301 if (i>=x.size())
00302 i = i-x.size();
00303 while (y[i].assigned()) {
00304 i = (i+1) % y.size();
00305 }
00306
00307
00308
00309 switch (Base::rand(3)) {
00310 case 0:
00311 if (a.ints()[i] < y[i].max()) {
00312 int v=a.ints()[i]+1+
00313 Base::rand(static_cast<unsigned int>(y[i].max()-a.ints()[i]));
00314 assert((v > a.ints()[i]) && (v <= y[i].max()));
00315 rel(i, Gecode::IRT_LE, v);
00316 }
00317 break;
00318 case 1:
00319 if (a.ints()[i] > y[i].min()) {
00320 int v=y[i].min()+
00321 Base::rand(static_cast<unsigned int>(a.ints()[i]-y[i].min()));
00322 assert((v < a.ints()[i]) && (v >= y[i].min()));
00323 rel(i, Gecode::IRT_GR, v);
00324 }
00325 break;
00326 default:
00327 int v;
00328 Gecode::Int::ViewRanges<Gecode::Int::IntView> it(y[i]);
00329 unsigned int skip = Base::rand(y[i].size()-1);
00330 while (true) {
00331 if (it.width() > skip) {
00332 v = it.min() + skip;
00333 if (v == a.ints()[i]) {
00334 if (it.width() == 1) {
00335 ++it; v = it.min();
00336 } else if (v < it.max()) {
00337 ++v;
00338 } else {
00339 --v;
00340 }
00341 }
00342 break;
00343 }
00344 skip -= it.width();
00345 ++it;
00346 }
00347 rel(i, Gecode::IRT_NQ, v);
00348 }
00349 return (!Base::fixpoint() || fixprob());
00350 }
00351 while (x[i].assigned()) {
00352 i = (i+1) % x.size();
00353 }
00354 Gecode::CpltSetVarUnknownRanges ur1(x[i]);
00355 Test::Set::CountableSetRanges air1(a.lub, a[i]);
00356 Gecode::Iter::Ranges::Diff<Gecode::CpltSetVarUnknownRanges,
00357 Test::Set::CountableSetRanges> diff(ur1, air1);
00358 Gecode::CpltSetVarUnknownRanges ur2(x[i]);
00359 Test::Set::CountableSetRanges air2(a.lub, a[i]);
00360 Gecode::Iter::Ranges::Inter<Gecode::CpltSetVarUnknownRanges,
00361 Test::Set::CountableSetRanges> inter(ur2, air2);
00362
00363 Test::Set::CountableSetRanges aisizer(a.lub, a[i]);
00364 unsigned int aisize = Gecode::Iter::Ranges::size(aisizer);
00365
00366
00367 switch (Base::rand(5)) {
00368 case 0:
00369 if (inter()) {
00370 int v = Base::rand(Gecode::Iter::Ranges::size(inter));
00371 addToGlb(v, i, a);
00372 }
00373 break;
00374 case 1:
00375 if (diff()) {
00376 int v = Base::rand(Gecode::Iter::Ranges::size(diff));
00377 removeFromLub(v, i, a);
00378 }
00379 break;
00380 case 2:
00381 if (x[i].cardMin() < aisize) {
00382 unsigned int newc = x[i].cardMin() + 1 +
00383 Base::rand(aisize - x[i].cardMin());
00384 assert( newc > x[i].cardMin() );
00385 assert( newc <= aisize );
00386 cardinality(i, newc, Gecode::Set::Limits::card);
00387 }
00388 break;
00389 case 3:
00390 if (x[i].cardMax() > aisize) {
00391 unsigned int newc = x[i].cardMax() - 1 -
00392 Base::rand(x[i].cardMax() - aisize);
00393 assert( newc < x[i].cardMax() );
00394 assert( newc >= aisize );
00395 cardinality(i, 0, newc);
00396 }
00397 break;
00398 default:
00399 if (inter()) {
00400 int v = Base::rand(Gecode::Iter::Ranges::size(inter));
00401 addToGlb(v, i, a);
00402 } else {
00403 int v = Base::rand(Gecode::Iter::Ranges::size(diff));
00404 removeFromLub(v, i, a);
00405 }
00406 }
00407 return (!Base::fixpoint() || fixprob());
00408 }
00409 };
00410
00411 bool
00412 CpltSetTest::run(void) {
00413 const char* test = "NONE";
00414 const char* problem = "NONE";
00415
00416 Test::Set::SetAssignment* ap =
00417 new Test::Set::SetAssignment(arity,lub,withInt);
00418 Test::Set::SetAssignment& a = *ap;
00419
00420 int an = 0;
00421
00422 while (a()) {
00423 bool is_sol = solution(a);
00424 if (opt.log)
00425 olog << ind(1) << "Assignment: " << a
00426 << (is_sol ? " (solution)" : " (no solution)")
00427 << std::endl;
00428
00429 START_TEST("Assignment (after posting)");
00430 {
00431 Gecode::CpltSet::manager.dispose();
00432 Gecode::CpltSet::manager.init(10000,10000);
00433 CpltSetTestSpace* s =
00434 new CpltSetTestSpace(arity,lub,withInt,false,this,opt);
00435 s->post();
00436 s->assign(a);
00437 if (is_sol) {
00438 CHECK_TEST(!s->failed(), "Failed on solution");
00439 CHECK_TEST(s->propagators()==0, "No subsumption");
00440 } else {
00441 CHECK_TEST(s->failed(), "Solved on non-solution");
00442 }
00443 delete s;
00444 }
00445
00446 START_TEST("Assignment (before posting)");
00447 {
00448 Gecode::CpltSet::manager.dispose();
00449 Gecode::CpltSet::manager.init(10000,10000);
00450 CpltSetTestSpace* s =
00451 new CpltSetTestSpace(arity,lub,withInt,false,this,opt);
00452 s->assign(a);
00453 s->post();
00454 if (is_sol) {
00455 CHECK_TEST(!s->failed(), "Failed on solution");
00456 CHECK_TEST(s->propagators()==0, "No subsumption");
00457 } else {
00458 CHECK_TEST(s->failed(), "Solved on non-solution");
00459 }
00460 delete s;
00461 }
00462
00463 if (reified) {
00464 START_TEST("Assignment reified (before posting)");
00465 Gecode::CpltSet::manager.dispose();
00466 Gecode::CpltSet::manager.init(10000,10000);
00467 CpltSetTestSpace* s =
00468 new CpltSetTestSpace(arity,lub,withInt,true,this,opt);
00469 s->assign(a);
00470 s->post();
00471 CHECK_TEST(!s->failed(), "Failed");
00472 CHECK_TEST(s->propagators()==0, "No subsumption");
00473 CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00474 if (is_sol) {
00475 CHECK_TEST(s->b.val()==1, "Zero on solution");
00476 } else {
00477 CHECK_TEST(s->b.val()==0, "One on non-solution");
00478 }
00479 delete s;
00480 }
00481
00482 if (reified) {
00483 START_TEST("Assignment reified (after posting)");
00484 Gecode::CpltSet::manager.dispose();
00485 Gecode::CpltSet::manager.init(10000,10000);
00486 CpltSetTestSpace* s =
00487 new CpltSetTestSpace(arity,lub,withInt,true,this,opt);
00488 s->post();
00489 s->assign(a);
00490 CHECK_TEST(!s->failed(), "Failed");
00491 CHECK_TEST(s->propagators()==0, "No subsumption");
00492 CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00493 if (is_sol) {
00494 CHECK_TEST(s->b.val()==1, "Zero on solution");
00495 } else {
00496 CHECK_TEST(s->b.val()==0, "One on non-solution");
00497 }
00498 delete s;
00499 }
00500
00501 START_TEST("Prune");
00502 {
00503 Gecode::CpltSet::manager.dispose();
00504 Gecode::CpltSet::manager.init(10000,10000);
00505 CpltSetTestSpace* s =
00506 new CpltSetTestSpace(arity,lub,withInt,false,this,opt);
00507 s->post();
00508 while (!s->failed() && !s->assigned())
00509 if (!s->prune(a)) {
00510 problem = "No fixpoint";
00511 delete s;
00512 goto failed;
00513 }
00514 s->assign(a);
00515 if (is_sol) {
00516 CHECK_TEST(!s->failed(), "Failed on solution");
00517 CHECK_TEST(s->propagators()==0, "No subsumption");
00518 } else {
00519 CHECK_TEST(s->failed(), "Solved on non-solution");
00520 }
00521 delete s;
00522 }
00523
00524 if (reified) {
00525 START_TEST("Prune reified");
00526 Gecode::CpltSet::manager.dispose();
00527 Gecode::CpltSet::manager.init(10000,10000);
00528 CpltSetTestSpace* s =
00529 new CpltSetTestSpace(arity,lub,withInt,true,this,opt);
00530 s->post();
00531 while (!s->assigned() && !s->b.assigned())
00532 if (!s->prune(a)) {
00533 problem = "No fixpoint";
00534 delete s;
00535 goto failed;
00536 }
00537 CHECK_TEST(!s->failed(), "Failed");
00538 CHECK_TEST(s->propagators()==0, "No subsumption");
00539 CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00540 if (is_sol) {
00541 CHECK_TEST(s->b.val()==1, "Zero on solution");
00542 } else {
00543 CHECK_TEST(s->b.val()==0, "One on non-solution");
00544 }
00545 delete s;
00546 }
00547
00548 ++an;
00549 ++a;
00550 }
00551
00552 delete ap;
00553 return true;
00554 failed:
00555 if (opt.log)
00556 olog << "FAILURE" << std::endl
00557 << ind(1) << "Test: " << test << std::endl
00558 << ind(1) << "Problem: " << problem << std::endl;
00559 if (a() && opt.log)
00560 olog << ind(1) << "Assignment: " << a << std::endl;
00561 delete ap;
00562
00563 return false;
00564 }
00565
00566 }}
00567
00568