Generated on Tue Apr 18 10:22:09 2017 for Gecode by doxygen 1.6.3

nogoods.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  *  Contributing authors:
00007  *     Guido Tack <tack@gecode.org>
00008  *
00009  *  Copyright:
00010  *     Christian Schulte, 2013
00011  *     Guido Tack, 2004
00012  *
00013  *  Last modified:
00014  *     $Date: 2016-06-17 15:43:08 +0200 (Fri, 17 Jun 2016) $ by $Author: schulte $
00015  *     $Revision: 15116 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */
00041 
00042 #include <gecode/minimodel.hh>
00043 #include <gecode/search.hh>
00044 
00045 #include "test/test.hh"
00046 
00047 namespace Test {
00048 
00050   namespace NoGoods {
00051 
00052     using namespace Gecode;
00053 
00055     void dummy(Space&) {
00056     }
00057 
00059     class Queens : public Space {
00060     public:
00062       const static int n = 18;
00064       IntVarArray q;
00066       Queens(IntValBranch ivb, bool assign, bool null)
00067         : q(*this,n,0,n-1) {
00068         distinct(*this, IntArgs::create(n,0,1), q, IPL_VAL);
00069         distinct(*this, IntArgs::create(n,0,-1), q, IPL_VAL);
00070         distinct(*this, q, IPL_VAL);
00071         if (assign) {
00072           IntVar x(*this,0,1); Gecode::assign(*this, x, INT_ASSIGN_MIN());
00073         }
00074         {
00075           IntVarArgs q1(n/2), q2(n/2);
00076           for (int i=0; i<n/2; i++) {
00077             q1[i] = q[i]; q2[i] = q[n/2 + i];
00078           }
00079           branch(*this, q1, INT_VAR_NONE(), ivb);
00080           if (null)
00081             branch(*this, &dummy);
00082           branch(*this, q2, INT_VAR_NONE(), ivb);
00083         }
00084         if (assign) {
00085           IntVar x(*this,0,1); Gecode::assign(*this, x, INT_ASSIGN_MIN());
00086         }
00087       }
00089       Queens(bool share, Queens& s) : Space(share,s) {
00090         q.update(*this, share, s.q);
00091       }
00093       virtual Space* copy(bool share) {
00094         return new Queens(share,*this);
00095       }
00097       bool same(const Queens& s) const {
00098         for (int i=0; i<q.size(); i++)
00099           if (q[i].val() != s.q[i].val())
00100             return false;
00101         return true;
00102       }
00104       static unsigned int nodeinc(void) {
00105         return 500;
00106       }
00108       static std::string name(void) {
00109         return "Queens";
00110       }
00112       static std::string val(IntValBranch ivb) {
00113         switch (ivb.select()) {
00114         case IntValBranch::SEL_MIN: return "INT_VAL_MIN";
00115         case IntValBranch::SEL_MAX: return "INT_VAL_MAX";
00116         case IntValBranch::SEL_SPLIT_MIN: return "INT_VAL_SPLIT_MIN";
00117         case IntValBranch::SEL_SPLIT_MAX: return "INT_VAL_SPLIT_MAX";
00118         case IntValBranch::SEL_VALUES_MIN: return "INT_VALUES_MIN";
00119         case IntValBranch::SEL_VALUES_MAX: return "INT_VALUES_MAX";
00120         default: GECODE_NEVER;
00121         }
00122         return "";
00123       }
00124     };
00125 
00126 #ifdef GECODE_HAS_SET_VARS
00127 
00128     class Hamming : public Space {
00129     private:
00131       static const int size = 16;
00133       static const int distance = 4;
00135       static const int bits = 8;
00137       SetVarArray x;
00138     public:
00140       Hamming(SetValBranch svb, bool assign, bool null) :
00141         x(*this,size,IntSet::empty,1,bits) {
00142         SetVarArgs cx(x.size());
00143         for (int i=x.size(); i--;)
00144           cx[i] = expr(*this, -x[i]);
00145 
00146         for (int i=0; i<x.size(); i++)
00147           for (int j=i+1; j<x.size(); j++)
00148             rel(*this,
00149                 cardinality(x[j] & cx[i]) +
00150                 cardinality(x[i] & cx[j]) >= distance);
00151 
00152         if (assign) {
00153           IntVar x(*this,0,1); Gecode::assign(*this, x, INT_ASSIGN_MIN());
00154         }
00155         {
00156           SetVarArgs x1(size/2), x2(size/2);
00157           for (int i=0; i<size/2; i++) {
00158             x1[i] = x[i]; x2[i] = x[size/2 + i];
00159           }
00160           branch(*this, x1, SET_VAR_NONE(), svb);
00161           if (null)
00162             branch(*this, &dummy);
00163           branch(*this, x2, SET_VAR_NONE(), svb);
00164         }
00165         if (assign) {
00166           IntVar x(*this,0,1); Gecode::assign(*this, x, INT_ASSIGN_MIN());
00167         }
00168       }
00170       Hamming(bool share, Hamming& s) : Space(share,s) {
00171         x.update(*this, share, s.x);
00172       }
00174       virtual Space* copy(bool share) {
00175         return new Hamming(share,*this);
00176       }
00178       bool same(const Hamming& s) const {
00179         for (int i=0; i<x.size(); i++) {
00180           SetVarGlbRanges a(x[i]), b(s.x[i]);
00181           if (!Iter::Ranges::equal(a,b))
00182             return false;
00183         }
00184         return true;
00185       }
00187       static unsigned int nodeinc(void) {
00188         return 35;
00189       }
00191       static std::string name(void) {
00192         return "Hamming";
00193       }
00195       static std::string val(SetValBranch svb) {
00196         switch (svb.select()) {
00197         case SetValBranch::SEL_MIN_INC: return "SET_VAL_MIN_INC";
00198         case SetValBranch::SEL_MAX_INC: return "SET_VAL_MAX_INC";
00199         case SetValBranch::SEL_MIN_EXC: return "SET_VAL_MIN_EXC";
00200         case SetValBranch::SEL_MAX_EXC: return "SET_VAL_MAX_EXC";
00201         default: GECODE_NEVER;
00202         }
00203         return "";
00204       }
00205     };
00206 #endif
00207 
00209     template<class Model, class ValBranch>
00210     class NoGoods : public Base {
00211     protected:
00213       ValBranch vb;
00215       unsigned int t;
00217       bool a;
00219       bool n;
00220     public:
00222       static std::string str(unsigned int i) {
00223         std::stringstream s;
00224         s << i;
00225         return s.str();
00226       }
00228       NoGoods(ValBranch vb0, unsigned int t0, bool a0, bool n0)
00229         : Base("NoGoods::"+Model::name()+"::"+Model::val(vb0)+"::"+str(t0)+
00230                "::"+(a0 ? "+" : "-")+"::"+(n0 ? "+" : "-")),
00231           vb(vb0), t(t0), a(a0), n(n0) {}
00233       virtual bool run(void) {
00234         Model* m = new Model(vb,a,n);
00235         // Solution without no-goods
00236         Model* s_plain = dfs(m);
00237         // Stop and re-start for a while to collect no-goods
00238         {
00239           Search::NodeStop ns(Model::nodeinc());
00240           Search::Options o;
00241           o.stop = &ns;
00242           o.threads = t;
00243           o.nogoods_limit = 256U;
00244           Search::Engine* e = Search::dfs(m,o);
00245           while (true) {
00246             Model* s = static_cast<Model*>(e->next());
00247             delete s;
00248             if (!e->stopped())
00249               break;
00250             // Add no-goods
00251             e->nogoods().post(*m);
00252             ns.limit(ns.limit()+Model::nodeinc());
00253           }
00254           delete e;
00255         }
00256         // Compare whether the a or the same solution is found with no-goods
00257         Model* s_nogoods = dfs(m);
00258 
00259         bool ok = ((s_nogoods != NULL) &&
00260                    ((t != 1) || s_plain->same(*s_nogoods)));
00261 
00262         delete m;
00263         delete s_nogoods;
00264         delete s_plain;
00265 
00266         return ok;
00267       }
00268     };
00269 
00270 
00272     class Create {
00273     public:
00275       Create(void) {
00276         bool a = false;
00277         do {
00278           bool n = false;
00279           do {
00280             for (unsigned int t = 1; t<=4; t++) {
00281               (void) new NoGoods<Queens,IntValBranch>(INT_VAL_MIN(),t,a,n);
00282               (void) new NoGoods<Queens,IntValBranch>(INT_VAL_MAX(),t,a,n);
00283               (void) new NoGoods<Queens,IntValBranch>(INT_VAL_SPLIT_MIN(),t,a,n);
00284               (void) new NoGoods<Queens,IntValBranch>(INT_VAL_SPLIT_MAX(),t,a,n);
00285               (void) new NoGoods<Queens,IntValBranch>(INT_VALUES_MIN(),t,a,n);
00286               (void) new NoGoods<Queens,IntValBranch>(INT_VALUES_MAX(),t,a,n);
00287 #ifdef GECODE_HAS_SET_VARS
00288               (void) new NoGoods<Hamming,SetValBranch>(SET_VAL_MIN_INC(),t,a,n);
00289               (void) new NoGoods<Hamming,SetValBranch>(SET_VAL_MIN_EXC(),t,a,n);
00290               (void) new NoGoods<Hamming,SetValBranch>(SET_VAL_MAX_INC(),t,a,n);
00291               (void) new NoGoods<Hamming,SetValBranch>(SET_VAL_MAX_EXC(),t,a,n);
00292 #endif
00293             }
00294             n = !n;
00295           } while (n);
00296           a = !a;
00297         } while (a);
00298       }
00299     };
00300 
00301     Create c;
00302   }
00303 
00304 }
00305 
00306 // STATISTICS: test-search