Generated on Fri Mar 20 15:56:24 2015 for Gecode by doxygen 1.6.3

search.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2008
00008  *
00009  *  Last modified:
00010  *     $Date: 2014-10-21 17:09:50 +0200 (Tue, 21 Oct 2014) $ by $Author: schulte $
00011  *     $Revision: 14258 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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         // Depth-first search
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         // Best solution search
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         // Restart-based search
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 // STATISTICS: test-search