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/int.hh"
00039 #include "gecode/minimodel.hh"
00040 #include "gecode/search.hh"
00041
00042 #include "test/test.hh"
00043
00044 namespace Test {
00045
00047 namespace Search {
00048
00049 using namespace Gecode;
00050 using namespace Gecode::Int;
00051
00053 enum HowToBranch {
00054 HTB_NONE,
00055 HTB_UNARY,
00056 HTB_BINARY,
00057 HTB_NARY
00058 };
00059
00061 enum HowToConstrain {
00062 HTC_NONE,
00063 HTC_LEX_LE,
00064 HTC_LEX_GR,
00065 HTC_BAL_LE,
00066 HTC_BAL_GR
00067 };
00068
00070 enum WhichModel {
00071 WM_FAIL_IMMEDIATE,
00072 WM_FAIL_SEARCH,
00073 WM_SOLUTIONS
00074 };
00075
00077 class PosValuesDesc : public BranchingDesc {
00078 protected:
00080 int _pos;
00082 int* _values;
00083 public:
00085 PosValuesDesc(const Branching* b, int p, IntView x)
00086 : BranchingDesc(b,x.size()),
00087 _pos(p),
00088 _values(static_cast<int*>(Memory::malloc(sizeof(int)*x.size()))) {
00089 ViewValues<IntView> v(x);
00090 int i=0;
00091 while (v()) {
00092 _values[i]=v.val(); ++i; ++v;
00093 }
00094 }
00096 int pos(void) const {
00097 return _pos;
00098 }
00100 int val(unsigned int a) const {
00101 return _values[a];
00102 }
00104 virtual size_t size(void) const {
00105 return 0;
00106 }
00108 virtual ~PosValuesDesc(void) {
00109 Memory::free(_values);
00110 }
00111 };
00112
00113
00115 class NaryBranching : public Branching {
00116 protected:
00118 ViewArray<IntView> x;
00120 NaryBranching(Space* home, bool share, NaryBranching& b)
00121 : Branching(home,share,b) {
00122 x.update(home,share,b.x);
00123 }
00124 public:
00126 NaryBranching(Space* home, ViewArray<IntView>& x0)
00127 : Branching(home), x(x0) {}
00129 virtual Actor* copy(Space* home, bool share) {
00130 return new (home) NaryBranching(home,share,*this);
00131 }
00133 virtual bool status(const Space*) const {
00134 for (int i=0; i<x.size(); i++)
00135 if (!x[i].assigned())
00136 return true;
00137 return false;
00138 }
00140 virtual const BranchingDesc* description(const Space*) const {
00141 int i=0;
00142 while (x[i].assigned())
00143 i++;
00144 return new PosValuesDesc(this,i,x[i]);
00145 }
00147 virtual ExecStatus commit(Space* home, const BranchingDesc* d,
00148 unsigned int a) {
00149 const PosValuesDesc* pvd = static_cast<const PosValuesDesc*>(d);
00150 return me_failed(x[pvd->pos()].eq(home,pvd->val(a)))
00151 ? ES_FAILED : ES_OK;
00152 }
00154 static Support::Symbol ati(void) {
00155 return "Test::Search::NaryBranching";
00156 }
00158 virtual Reflection::ActorSpec spec(Space* home, Reflection::VarMap& m) {
00159 Reflection::ActorSpec s(ati());
00160 return s << x.spec(home, m);
00161 }
00162
00164 virtual Reflection::BranchingSpec branchingSpec(Space*,
00165 Reflection::VarMap&,
00166 const BranchingDesc* d) {
00167 Reflection::BranchingSpec bs(d);
00168 return bs;
00169 }
00171 static void post(Space*, Reflection::VarMap&,
00172 const Reflection::ActorSpec&) {
00173 }
00174 };
00175
00177 class TestSpace : public Space {
00178 public:
00180 TestSpace(void) {}
00182 TestSpace(bool share, TestSpace& s) : Space(share,s) {}
00184 virtual int solutions(void) const = 0;
00186 virtual bool best(void) const = 0;
00187 };
00188
00190 class FailImmediate : public TestSpace {
00191 public:
00193 IntVarArray x;
00195 FailImmediate(HowToBranch, HowToBranch, HowToBranch,
00196 HowToConstrain=HTC_NONE)
00197 : x(this,1,0,0) {
00198 rel(this, x[0], IRT_EQ, 1);
00199 }
00201 FailImmediate(bool share, FailImmediate& s) : TestSpace(share,s) {
00202 x.update(this, share, s.x);
00203 }
00205 virtual Space* copy(bool share) {
00206 return new FailImmediate(share,*this);
00207 }
00209 void constrain(Space*) {
00210 }
00212 virtual int solutions(void) const {
00213 return 0;
00214 }
00216 virtual bool best(void) const {
00217 return false;
00218 }
00220 static std::string name(void) {
00221 return "Fail";
00222 }
00223 };
00224
00226 class HasSolutions : public TestSpace {
00227 public:
00229 IntVarArray x;
00231 HowToBranch htb1, htb2, htb3;
00233 HowToConstrain htc;
00235 void branch(const IntVarArgs& x, HowToBranch htb) {
00236 switch (htb) {
00237 case HTB_NONE:
00238 break;
00239 case HTB_UNARY:
00240 assign(this, x, INT_ASSIGN_MIN);
00241 break;
00242 case HTB_BINARY:
00243 Gecode::branch(this, x, INT_VAR_NONE, INT_VAL_MIN);
00244 break;
00245 case HTB_NARY:
00246 {
00247 ViewArray<IntView> xv(this,x);
00248 new (this) NaryBranching(this, xv);
00249 break;
00250 }
00251 }
00252 }
00254 HasSolutions(HowToBranch _htb1, HowToBranch _htb2, HowToBranch _htb3,
00255 HowToConstrain _htc=HTC_NONE)
00256 : x(this,6,0,5), htb1(_htb1), htb2(_htb2), htb3(_htb3), htc(_htc) {
00257 distinct(this, x);
00258 rel(this, x[2], IRT_LQ, 3); rel(this, x[3], IRT_LQ, 3);
00259 rel(this, x[4], IRT_LQ, 1); rel(this, x[5], IRT_LQ, 1);
00260 IntVarArgs x1(2); x1[0]=x[0]; x1[1]=x[1]; branch(x1, htb1);
00261 IntVarArgs x2(2); x2[0]=x[2]; x2[1]=x[3]; branch(x2, htb2);
00262 IntVarArgs x3(2); x3[0]=x[4]; x3[1]=x[5]; branch(x3, htb3);
00263 }
00265 HasSolutions(bool share, HasSolutions& s)
00266 : TestSpace(share,s),
00267 htb1(s.htb1), htb2(s.htb2), htb3(s.htb3), htc(s.htc) {
00268 x.update(this, share, s.x);
00269 }
00271 virtual Space* copy(bool share) {
00272 return new HasSolutions(share,*this);
00273 }
00275 void constrain(Space* _s) {
00276 HasSolutions* s = static_cast<HasSolutions*>(_s);
00277 switch (htc) {
00278 case HTC_NONE:
00279 break;
00280 case HTC_LEX_LE:
00281 case HTC_LEX_GR:
00282 {
00283 IntVarArgs y(6);
00284 for (int i=0; i<6; i++)
00285 y[i].init(this, s->x[i].val(), s->x[i].val());
00286 lex(this, x, (htc == HTC_LEX_LE) ? IRT_LE : IRT_GR, y);
00287 break;
00288 }
00289 case HTC_BAL_LE:
00290 case HTC_BAL_GR:
00291 {
00292 IntVarArgs y(6);
00293 for (int i=0; i<6; i++)
00294 y[i].init(this, s->x[i].val(), s->x[i].val());
00295 IntVar xs(this, -18, 18);
00296 IntVar ys(this, -18, 18);
00297 post(this, x[0]+x[1]+x[2]-x[3]-x[4]-x[5] == xs);
00298 post(this, y[0]+y[1]+y[2]-y[3]-y[4]-y[5] == ys);
00299 rel(this,
00300 abs(this,xs),
00301 (htc == HTC_BAL_LE) ? IRT_LE : IRT_GR,
00302 abs(this,ys));
00303 break;
00304 }
00305 }
00306 }
00308 virtual int solutions(void) const {
00309 if (htb1 == HTB_NONE) {
00310 assert((htb2 == HTB_NONE) && (htb3 == HTB_NONE));
00311 return 1;
00312 }
00313 if ((htb1 == HTB_UNARY) || (htb2 == HTB_UNARY))
00314 return 0;
00315 if (htb3 == HTB_UNARY)
00316 return 4;
00317 return 8;
00318 }
00320 virtual bool best(void) const {
00321 if ((htb1 == HTB_NONE) || (htb2 == HTB_NONE) || (htb3 == HTB_NONE) ||
00322 (htb1 == HTB_UNARY) || (htb2 == HTB_UNARY) || (htb3 == HTB_UNARY))
00323 return true;
00324 switch (htc) {
00325 case HTC_NONE:
00326 return true;
00327 case HTC_LEX_LE:
00328 return ((x[0].val()==4) && (x[1].val()==5) &&
00329 (x[2].val()==2) && (x[3].val()==3) &&
00330 (x[4].val()==0) && (x[5].val()==1));
00331 case HTC_LEX_GR:
00332 return ((x[0].val()==5) && (x[1].val()==4) &&
00333 (x[2].val()==3) && (x[3].val()==2) &&
00334 (x[4].val()==1) && (x[5].val()==0));
00335 case HTC_BAL_LE:
00336 return ((x[0].val()==4) && (x[1].val()==5) &&
00337 (x[2].val()==2) && (x[3].val()==3) &&
00338 (x[4].val()==0) && (x[5].val()==1));
00339 case HTC_BAL_GR:
00340 return ((x[0].val()==4) && (x[1].val()==5) &&
00341 (x[2].val()==3) && (x[3].val()==2) &&
00342 (x[4].val()==0) && (x[5].val()==1));
00343 default: GECODE_NEVER;
00344 }
00345 return false;
00346 }
00348 static std::string name(void) {
00349 return "Sol";
00350 }
00351 };
00352
00354 class Test : public Base {
00355 public:
00357 HowToBranch htb1, htb2, htb3;
00359 HowToConstrain htc;
00361 static std::string str(unsigned int i) {
00362 std::stringstream s;
00363 s << i;
00364 return s.str();
00365 }
00367 static std::string str(HowToBranch htb) {
00368 switch (htb) {
00369 case HTB_NONE: return "None";
00370 case HTB_UNARY: return "Unary";
00371 case HTB_BINARY: return "Binary";
00372 case HTB_NARY: return "Nary";
00373 default: GECODE_NEVER;
00374 }
00375 GECODE_NEVER;
00376 return "";
00377 }
00379 static std::string str(HowToConstrain htc) {
00380 switch (htc) {
00381 case HTC_NONE: return "None";
00382 case HTC_LEX_LE: return "LexLe";
00383 case HTC_LEX_GR: return "LexGr";
00384 case HTC_BAL_LE: return "BalLe";
00385 case HTC_BAL_GR: return "BalGr";
00386 default: GECODE_NEVER;
00387 }
00388 GECODE_NEVER;
00389 return "";
00390 }
00392 Test(const std::string& s,
00393 HowToBranch _htb1, HowToBranch _htb2, HowToBranch _htb3,
00394 HowToConstrain _htc=HTC_NONE)
00395 : Base("Search::"+s),
00396 htb1(_htb1), htb2(_htb2), htb3(_htb3), htc(_htc) {}
00397 };
00398
00400 template <class Model>
00401 class DFS : public Test {
00402 private:
00404 unsigned int c_d;
00406 unsigned int a_d;
00407 public:
00409 DFS(HowToBranch htb1, HowToBranch htb2, HowToBranch htb3,
00410 unsigned int c_d0, unsigned int a_d0)
00411 : Test("DFS::"+Model::name()+"::"+
00412 str(htb1)+"::"+str(htb2)+"::"+str(htb3)+"::"+
00413 str(c_d0)+"::"+str(a_d0),
00414 htb1,htb2,htb3), c_d(c_d0), a_d(a_d0) {}
00416 virtual bool run(void) {
00417 Model* m = new Model(htb1,htb2,htb3);
00418 Gecode::Search::FailStop f(2);
00419 Gecode::Search::Options o;
00420 o.c_d = c_d;
00421 o.a_d = a_d;
00422 o.stop = &f;
00423 Gecode::DFS<Model> dfs(m,o);
00424 int n = m->solutions();
00425 delete m;
00426 while (true) {
00427 Model* s = dfs.next();
00428 if (s != NULL) {
00429 n--; delete s;
00430 }
00431 if ((s == NULL) && !dfs.stopped())
00432 break;
00433 f.limit(f.limit()+2);
00434 }
00435 return n == 0;
00436 }
00437 };
00438
00440 template <class Model>
00441 class LDS : public Test {
00442 public:
00444 LDS(HowToBranch htb1, HowToBranch htb2, HowToBranch htb3)
00445 : Test("LDS::"+Model::name()+"::"+
00446 str(htb1)+"::"+str(htb2)+"::"+str(htb3),
00447 htb1,htb2,htb3) {}
00449 virtual bool run(void) {
00450 Model* m = new Model(htb1,htb2,htb3);
00451 Gecode::Search::FailStop f(2);
00452 Gecode::Search::Options o;
00453 o.stop = &f;
00454 Gecode::LDS<Model> lds(m,50,o);
00455 int n = m->solutions();
00456 delete m;
00457 while (true) {
00458 Model* s = lds.next();
00459 if (s != NULL) {
00460 n--; delete s;
00461 }
00462 if ((s == NULL) && !lds.stopped())
00463 break;
00464 f.limit(f.limit()+2);
00465 }
00466 return n == 0;
00467 }
00468 };
00469
00471 template <class Model, template<class> class Engine>
00472 class Best : public Test {
00473 private:
00475 unsigned int c_d;
00477 unsigned int a_d;
00478 public:
00480 Best(const std::string& b, HowToConstrain htc,
00481 HowToBranch htb1, HowToBranch htb2, HowToBranch htb3,
00482 unsigned int c_d0, unsigned int a_d0)
00483 : Test(b+"::"+Model::name()+"::"+str(htc)+"::"+
00484 str(htb1)+"::"+str(htb2)+"::"+str(htb3)+"::"+
00485 str(c_d0)+"::"+str(a_d0),
00486 htb1,htb2,htb3,htc), c_d(c_d0), a_d(a_d0) {}
00488 virtual bool run(void) {
00489 Model* m = new Model(htb1,htb2,htb3,htc);
00490 Gecode::Search::FailStop f(2);
00491 Gecode::Search::Options o;
00492 o.c_d = c_d;
00493 o.a_d = a_d;
00494 o.stop = &f;
00495 Engine<Model> best(m,o);
00496 delete m;
00497 Model* b = NULL;
00498 while (true) {
00499 Model* s = best.next();
00500 if (s != NULL) {
00501 delete b; b=s;
00502 }
00503 if ((s == NULL) && !best.stopped())
00504 break;
00505 f.limit(f.limit()+2);
00506 }
00507 bool ok = (b == NULL) || b->best();
00508 delete b;
00509 return ok;
00510 }
00511 };
00512
00514 class BranchTypes {
00515 private:
00517 static const HowToBranch htbs[3];
00519 int i;
00520 public:
00522 BranchTypes(void) : i(0) {}
00524 bool operator()(void) const {
00525 return i<3;
00526 }
00528 void operator++(void) {
00529 i++;
00530 }
00532 HowToBranch htb(void) const {
00533 return htbs[i];
00534 }
00535 };
00536
00537 const HowToBranch BranchTypes::htbs[3] = {HTB_UNARY, HTB_BINARY, HTB_NARY};
00538
00540 class ConstrainTypes {
00541 private:
00543 static const HowToConstrain htcs[4];
00545 int i;
00546 public:
00548 ConstrainTypes(void) : i(0) {}
00550 bool operator()(void) const {
00551 return i<4;
00552 }
00554 void operator++(void) {
00555 i++;
00556 }
00558 HowToConstrain htc(void) const {
00559 return htcs[i];
00560 }
00561 };
00562
00563 const HowToConstrain ConstrainTypes::htcs[4] =
00564 {HTC_LEX_LE, HTC_LEX_GR, HTC_BAL_LE, HTC_BAL_GR};
00565
00566
00568 class Create {
00569 public:
00571 Create(void) {
00572
00573 for (unsigned int c_d = 1; c_d<10; c_d++)
00574 for (unsigned int a_d = 1; a_d<=c_d; a_d++) {
00575 for (BranchTypes htb1; htb1(); ++htb1)
00576 for (BranchTypes htb2; htb2(); ++htb2)
00577 for (BranchTypes htb3; htb3(); ++htb3)
00578 (void) new DFS<HasSolutions>(htb1.htb(),htb2.htb(),htb3.htb(),
00579 c_d, a_d);
00580 new DFS<FailImmediate>(HTB_NONE, HTB_NONE, HTB_NONE, c_d, a_d);
00581 new DFS<HasSolutions>(HTB_NONE, HTB_NONE, HTB_NONE, c_d, a_d);
00582 }
00583
00584
00585 for (BranchTypes htb1; htb1(); ++htb1)
00586 for (BranchTypes htb2; htb2(); ++htb2)
00587 for (BranchTypes htb3; htb3(); ++htb3)
00588 (void) new LDS<HasSolutions>(htb1.htb(),htb2.htb(),htb3.htb());
00589 new LDS<FailImmediate>(HTB_NONE, HTB_NONE, HTB_NONE);
00590 new LDS<HasSolutions>(HTB_NONE, HTB_NONE, HTB_NONE);
00591
00592
00593 for (unsigned int c_d = 1; c_d<10; c_d++)
00594 for (unsigned int a_d = 1; a_d<=c_d; a_d++) {
00595 for (ConstrainTypes htc; htc(); ++htc)
00596 for (BranchTypes htb1; htb1(); ++htb1)
00597 for (BranchTypes htb2; htb2(); ++htb2)
00598 for (BranchTypes htb3; htb3(); ++htb3) {
00599 (void) new Best<HasSolutions,BAB>
00600 ("BAB",htc.htc(),htb1.htb(),htb2.htb(),htb3.htb(),c_d,a_d);
00601 (void) new Best<HasSolutions,Restart>
00602 ("Restart",htc.htc(),htb1.htb(),htb2.htb(),htb3.htb(),c_d,a_d);
00603 }
00604 (void) new Best<FailImmediate,BAB>
00605 ("BAB",HTC_NONE,HTB_NONE,HTB_NONE,HTB_NONE,c_d,a_d);
00606 (void) new Best<HasSolutions,BAB>
00607 ("BAB",HTC_NONE,HTB_NONE,HTB_NONE,HTB_NONE,c_d,a_d);
00608 }
00609
00610 }
00611 };
00612
00613 Create c;
00614 }
00615
00616 }
00617
00618