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 #include <gecode/minimodel.hh>
00039 #include <gecode/search.hh>
00040
00041 #include "test/test.hh"
00042
00043 namespace Test {
00044
00046 namespace Search {
00047
00048 using namespace Gecode;
00049 using namespace Gecode::Int;
00050
00052 enum HowToBranch {
00053 HTB_NONE,
00054 HTB_UNARY,
00055 HTB_BINARY,
00056 HTB_NARY
00057 };
00058
00060 enum HowToConstrain {
00061 HTC_NONE,
00062 HTC_LEX_LE,
00063 HTC_LEX_GR,
00064 HTC_BAL_LE,
00065 HTC_BAL_GR
00066 };
00067
00069 enum WhichModel {
00070 WM_FAIL_IMMEDIATE,
00071 WM_FAIL_SEARCH,
00072 WM_SOLUTIONS
00073 };
00074
00076 class TestSpace : public Space {
00077 public:
00079 TestSpace(void) {}
00081 TestSpace(bool share, TestSpace& s) : Space(share,s) {}
00083 virtual int solutions(void) const = 0;
00085 virtual bool best(void) const = 0;
00087 virtual bool master(const CRI& cri) {
00088 if (cri.last() != NULL)
00089 constrain(*cri.last());
00090 return false;
00091 }
00092 };
00093
00095 class FailImmediate : public TestSpace {
00096 public:
00098 IntVarArray x;
00100 FailImmediate(HowToBranch, HowToBranch, HowToBranch,
00101 HowToConstrain=HTC_NONE)
00102 : x(*this,1,0,0) {
00103 rel(*this, x[0], IRT_EQ, 1);
00104 }
00106 FailImmediate(bool share, FailImmediate& s) : TestSpace(share,s) {
00107 x.update(*this, share, s.x);
00108 }
00110 virtual Space* copy(bool share) {
00111 return new FailImmediate(share,*this);
00112 }
00114 virtual void constrain(const Space&) {
00115 }
00117 virtual int solutions(void) const {
00118 return 0;
00119 }
00121 virtual bool best(void) const {
00122 return false;
00123 }
00125 static std::string name(void) {
00126 return "Fail";
00127 }
00128 };
00129
00131 class SolveImmediate : public TestSpace {
00132 public:
00134 IntVarArray x;
00136 SolveImmediate(HowToBranch, HowToBranch, HowToBranch,
00137 HowToConstrain=HTC_NONE)
00138 : x(*this,1,0,0) {}
00140 SolveImmediate(bool share, SolveImmediate& s) : TestSpace(share,s) {
00141 x.update(*this, share, s.x);
00142 }
00144 virtual Space* copy(bool share) {
00145 return new SolveImmediate(share,*this);
00146 }
00148 virtual void constrain(const Space&) {
00149 fail();
00150 }
00152 virtual int solutions(void) const {
00153 return 1;
00154 }
00156 virtual bool best(void) const {
00157 return true;
00158 }
00160 static std::string name(void) {
00161 return "Solve";
00162 }
00163 };
00164
00166 class HasSolutions : public TestSpace {
00167 public:
00169 IntVarArray x;
00171 HowToBranch htb1, htb2, htb3;
00173 HowToConstrain htc;
00175 void branch(const IntVarArgs& x, HowToBranch htb) {
00176 switch (htb) {
00177 case HTB_NONE:
00178 break;
00179 case HTB_UNARY:
00180 assign(*this, x, INT_ASSIGN_MIN());
00181 break;
00182 case HTB_BINARY:
00183 Gecode::branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
00184 break;
00185 case HTB_NARY:
00186 Gecode::branch(*this, x, INT_VAR_NONE(), INT_VALUES_MIN());
00187 break;
00188 }
00189 }
00191 HasSolutions(HowToBranch _htb1, HowToBranch _htb2, HowToBranch _htb3,
00192 HowToConstrain _htc=HTC_NONE)
00193 : x(*this,6,0,5), htb1(_htb1), htb2(_htb2), htb3(_htb3), htc(_htc) {
00194 distinct(*this, x);
00195 rel(*this, x[2], IRT_LQ, 3); rel(*this, x[3], IRT_LQ, 3);
00196 rel(*this, x[4], IRT_LQ, 1); rel(*this, x[5], IRT_LQ, 1);
00197 IntVarArgs x1(2); x1[0]=x[0]; x1[1]=x[1]; branch(x1, htb1);
00198 IntVarArgs x2(2); x2[0]=x[2]; x2[1]=x[3]; branch(x2, htb2);
00199 IntVarArgs x3(2); x3[0]=x[4]; x3[1]=x[5]; branch(x3, htb3);
00200 }
00202 HasSolutions(bool share, HasSolutions& s)
00203 : TestSpace(share,s),
00204 htb1(s.htb1), htb2(s.htb2), htb3(s.htb3), htc(s.htc) {
00205 x.update(*this, share, s.x);
00206 }
00208 virtual Space* copy(bool share) {
00209 return new HasSolutions(share,*this);
00210 }
00212 virtual void constrain(const Space& _s) {
00213 const HasSolutions& s = static_cast<const HasSolutions&>(_s);
00214 switch (htc) {
00215 case HTC_NONE:
00216 break;
00217 case HTC_LEX_LE:
00218 case HTC_LEX_GR:
00219 {
00220 IntVarArgs y(6);
00221 for (int i=0; i<6; i++)
00222 y[i] = IntVar(*this, s.x[i].val(), s.x[i].val());
00223 lex(*this, x, (htc == HTC_LEX_LE) ? IRT_LE : IRT_GR, y);
00224 break;
00225 }
00226 case HTC_BAL_LE:
00227 case HTC_BAL_GR:
00228 {
00229 IntVarArgs y(6);
00230 for (int i=0; i<6; i++)
00231 y[i] = IntVar(*this, s.x[i].val(), s.x[i].val());
00232 IntVar xs(*this, -18, 18);
00233 IntVar ys(*this, -18, 18);
00234 rel(*this, x[0]+x[1]+x[2]-x[3]-x[4]-x[5] == xs);
00235 rel(*this, y[0]+y[1]+y[2]-y[3]-y[4]-y[5] == ys);
00236 rel(*this,
00237 expr(*this,abs(xs)),
00238 (htc == HTC_BAL_LE) ? IRT_LE : IRT_GR,
00239 expr(*this,abs(ys)));
00240 break;
00241 }
00242 }
00243 }
00245 virtual int solutions(void) const {
00246 if (htb1 == HTB_NONE) {
00247 assert((htb2 == HTB_NONE) && (htb3 == HTB_NONE));
00248 return 1;
00249 }
00250 if ((htb1 == HTB_UNARY) || (htb2 == HTB_UNARY))
00251 return 0;
00252 if (htb3 == HTB_UNARY)
00253 return 4;
00254 return 8;
00255 }
00257 virtual bool best(void) const {
00258 if ((htb1 == HTB_NONE) || (htb2 == HTB_NONE) || (htb3 == HTB_NONE) ||
00259 (htb1 == HTB_UNARY) || (htb2 == HTB_UNARY) || (htb3 == HTB_UNARY))
00260 return true;
00261 switch (htc) {
00262 case HTC_NONE:
00263 return true;
00264 case HTC_LEX_LE:
00265 return ((x[0].val()==4) && (x[1].val()==5) &&
00266 (x[2].val()==2) && (x[3].val()==3) &&
00267 (x[4].val()==0) && (x[5].val()==1));
00268 case HTC_LEX_GR:
00269 return ((x[0].val()==5) && (x[1].val()==4) &&
00270 (x[2].val()==3) && (x[3].val()==2) &&
00271 (x[4].val()==1) && (x[5].val()==0));
00272 case HTC_BAL_LE:
00273 return ((x[0].val()==4) && (x[1].val()==5) &&
00274 (x[2].val()==2) && (x[3].val()==3) &&
00275 (x[4].val()==0) && (x[5].val()==1));
00276 case HTC_BAL_GR:
00277 return ((x[0].val()==4) && (x[1].val()==5) &&
00278 (x[2].val()==3) && (x[3].val()==2) &&
00279 (x[4].val()==0) && (x[5].val()==1));
00280 default: GECODE_NEVER;
00281 }
00282 return false;
00283 }
00285 static std::string name(void) {
00286 return "Sol";
00287 }
00289 virtual void master(unsigned long int i, const Space* _s,
00290 NoGoods&) {
00291 const HasSolutions* s = static_cast<const HasSolutions*>(_s);
00292 if (s != NULL) {
00293 BoolVarArgs b;
00294 for (int i=0; i<x.size(); i++)
00295 b << expr(*this, x[i] == s->x[i]);
00296 rel(*this, BOT_AND, b, 0);
00297 }
00298 }
00299 };
00300
00302 class Test : public Base {
00303 public:
00305 HowToBranch htb1, htb2, htb3;
00307 HowToConstrain htc;
00309 static std::string str(unsigned int i) {
00310 std::stringstream s;
00311 s << i;
00312 return s.str();
00313 }
00315 static std::string str(HowToBranch htb) {
00316 switch (htb) {
00317 case HTB_NONE: return "None";
00318 case HTB_UNARY: return "Unary";
00319 case HTB_BINARY: return "Binary";
00320 case HTB_NARY: return "Nary";
00321 default: GECODE_NEVER;
00322 }
00323 GECODE_NEVER;
00324 return "";
00325 }
00327 static std::string str(HowToConstrain htc) {
00328 switch (htc) {
00329 case HTC_NONE: return "None";
00330 case HTC_LEX_LE: return "LexLe";
00331 case HTC_LEX_GR: return "LexGr";
00332 case HTC_BAL_LE: return "BalLe";
00333 case HTC_BAL_GR: return "BalGr";
00334 default: GECODE_NEVER;
00335 }
00336 GECODE_NEVER;
00337 return "";
00338 }
00340 Test(const std::string& s,
00341 HowToBranch _htb1, HowToBranch _htb2, HowToBranch _htb3,
00342 HowToConstrain _htc=HTC_NONE)
00343 : Base("Search::"+s),
00344 htb1(_htb1), htb2(_htb2), htb3(_htb3), htc(_htc) {}
00345 };
00346
00348 template<class Model>
00349 class DFS : public Test {
00350 private:
00352 unsigned int c_d;
00354 unsigned int a_d;
00356 unsigned int t;
00357 public:
00359 DFS(HowToBranch htb1, HowToBranch htb2, HowToBranch htb3,
00360 unsigned int c_d0, unsigned int a_d0, unsigned int t0)
00361 : Test("DFS::"+Model::name()+"::"+
00362 str(htb1)+"::"+str(htb2)+"::"+str(htb3)+"::"+
00363 str(c_d0)+"::"+str(a_d0)+"::"+str(t0),
00364 htb1,htb2,htb3), c_d(c_d0), a_d(a_d0), t(t0) {}
00366 virtual bool run(void) {
00367 Model* m = new Model(htb1,htb2,htb3);
00368 Gecode::Search::FailStop f(2);
00369 Gecode::Search::Options o;
00370 o.c_d = c_d;
00371 o.a_d = a_d;
00372 o.threads = t;
00373 o.stop = &f;
00374 Gecode::DFS<Model> dfs(m,o);
00375 int n = m->solutions();
00376 delete m;
00377 while (true) {
00378 Model* s = dfs.next();
00379 if (s != NULL) {
00380 n--; delete s;
00381 }
00382 if ((s == NULL) && !dfs.stopped())
00383 break;
00384 f.limit(f.limit()+2);
00385 }
00386 return n == 0;
00387 }
00388 };
00389
00391 template<class Model>
00392 class BAB : public Test {
00393 private:
00395 unsigned int c_d;
00397 unsigned int a_d;
00399 unsigned int t;
00400 public:
00402 BAB(HowToConstrain htc,
00403 HowToBranch htb1, HowToBranch htb2, HowToBranch htb3,
00404 unsigned int c_d0, unsigned int a_d0, unsigned int t0)
00405 : Test("BAB::"+Model::name()+"::"+str(htc)+"::"+
00406 str(htb1)+"::"+str(htb2)+"::"+str(htb3)+"::"+
00407 str(c_d0)+"::"+str(a_d0)+"::"+str(t0),
00408 htb1,htb2,htb3,htc), c_d(c_d0), a_d(a_d0), t(t0) {}
00410 virtual bool run(void) {
00411 Model* m = new Model(htb1,htb2,htb3,htc);
00412 Gecode::Search::FailStop f(2);
00413 Gecode::Search::Options o;
00414 o.c_d = c_d;
00415 o.a_d = a_d;
00416 o.threads = t;
00417 o.stop = &f;
00418 Gecode::BAB<Model> bab(m,o);
00419 delete m;
00420 Model* b = NULL;
00421 while (true) {
00422 Model* s = bab.next();
00423 if (s != NULL) {
00424 delete b; b=s;
00425 }
00426 if ((s == NULL) && !bab.stopped())
00427 break;
00428 f.limit(f.limit()+2);
00429 }
00430 bool ok = (b == NULL) || b->best();
00431 delete b;
00432 return ok;
00433 }
00434 };
00435
00437 template<class Model, template<class> class Engine>
00438 class RBS : public Test {
00439 private:
00441 unsigned int t;
00442 public:
00444 RBS(const std::string& e, unsigned int t0)
00445 : Test("RBS::"+e+"::"+Model::name()+"::"+str(t0),
00446 HTB_BINARY,HTB_BINARY,HTB_BINARY), t(t0) {}
00448 virtual bool run(void) {
00449 Model* m = new Model(htb1,htb2,htb3);
00450 Gecode::Search::FailStop f(2);
00451 Gecode::Search::Options o;
00452 o.threads = t;
00453 o.stop = &f;
00454 o.cutoff = Gecode::Search::Cutoff::geometric(1,2);
00455 Gecode::RBS<Engine,Model> rbs(m,o);
00456 int n = m->solutions();
00457 delete m;
00458 while (true) {
00459 Model* s = rbs.next();
00460 if (s != NULL) {
00461 n--; delete s;
00462 }
00463 if ((s == NULL) && !rbs.stopped())
00464 break;
00465 f.limit(f.limit()+2);
00466 }
00467 return n == 0;
00468 }
00469 };
00470
00472 class BranchTypes {
00473 private:
00475 static const HowToBranch htbs[3];
00477 int i;
00478 public:
00480 BranchTypes(void) : i(0) {}
00482 bool operator()(void) const {
00483 return i<3;
00484 }
00486 void operator++(void) {
00487 i++;
00488 }
00490 HowToBranch htb(void) const {
00491 return htbs[i];
00492 }
00493 };
00494
00495 const HowToBranch BranchTypes::htbs[3] = {HTB_UNARY, HTB_BINARY, HTB_NARY};
00496
00498 class ConstrainTypes {
00499 private:
00501 static const HowToConstrain htcs[4];
00503 int i;
00504 public:
00506 ConstrainTypes(void) : i(0) {}
00508 bool operator()(void) const {
00509 return i<4;
00510 }
00512 void operator++(void) {
00513 i++;
00514 }
00516 HowToConstrain htc(void) const {
00517 return htcs[i];
00518 }
00519 };
00520
00521 const HowToConstrain ConstrainTypes::htcs[4] =
00522 {HTC_LEX_LE, HTC_LEX_GR, HTC_BAL_LE, HTC_BAL_GR};
00523
00524
00526 class Create {
00527 public:
00529 Create(void) {
00530
00531 for (unsigned int t = 1; t<=4; t++)
00532 for (unsigned int c_d = 1; c_d<10; c_d++)
00533 for (unsigned int a_d = 1; a_d<=c_d; a_d++) {
00534 for (BranchTypes htb1; htb1(); ++htb1)
00535 for (BranchTypes htb2; htb2(); ++htb2)
00536 for (BranchTypes htb3; htb3(); ++htb3)
00537 (void) new DFS<HasSolutions>
00538 (htb1.htb(),htb2.htb(),htb3.htb(),c_d, a_d, t);
00539 new DFS<FailImmediate>(HTB_NONE, HTB_NONE, HTB_NONE,
00540 c_d, a_d, t);
00541 new DFS<SolveImmediate>(HTB_NONE, HTB_NONE, HTB_NONE,
00542 c_d, a_d, t);
00543 new DFS<HasSolutions>(HTB_NONE, HTB_NONE, HTB_NONE,
00544 c_d, a_d, t);
00545 }
00546
00547
00548 for (unsigned int t = 1; t<=4; t++)
00549 for (unsigned int c_d = 1; c_d<10; c_d++)
00550 for (unsigned int a_d = 1; a_d<=c_d; a_d++) {
00551 for (ConstrainTypes htc; htc(); ++htc)
00552 for (BranchTypes htb1; htb1(); ++htb1)
00553 for (BranchTypes htb2; htb2(); ++htb2)
00554 for (BranchTypes htb3; htb3(); ++htb3) {
00555 (void) new BAB<HasSolutions>
00556 (htc.htc(),htb1.htb(),htb2.htb(),htb3.htb(),
00557 c_d,a_d,t);
00558 }
00559 (void) new BAB<FailImmediate>
00560 (HTC_NONE,HTB_NONE,HTB_NONE,HTB_NONE,c_d,a_d,t);
00561 (void) new BAB<SolveImmediate>
00562 (HTC_NONE,HTB_NONE,HTB_NONE,HTB_NONE,c_d,a_d,t);
00563 (void) new BAB<HasSolutions>
00564 (HTC_NONE,HTB_NONE,HTB_NONE,HTB_NONE,c_d,a_d,t);
00565 }
00566
00567 for (unsigned int t = 1; t<=4; t++) {
00568 (void) new RBS<HasSolutions,Gecode::DFS>("DFS",t);
00569 (void) new RBS<HasSolutions,Gecode::BAB>("BAB",t);
00570 (void) new RBS<FailImmediate,Gecode::DFS>("DFS",t);
00571 (void) new RBS<FailImmediate,Gecode::BAB>("BAB",t);
00572 (void) new RBS<SolveImmediate,Gecode::DFS>("DFS",t);
00573 (void) new RBS<SolveImmediate,Gecode::BAB>("BAB",t);
00574 }
00575 }
00576 };
00577
00578 Create c;
00579 }
00580
00581 }
00582
00583