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

int.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  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2005
00009  *     Mikael Lagerkvist, 2005
00010  *
00011  *  Last modified:
00012  *     $Date: 2013-03-05 14:40:46 +0100 (Tue, 05 Mar 2013) $ by $Author: schulte $
00013  *     $Revision: 13435 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 #include "test/int.hh"
00041 
00042 #include <algorithm>
00043 
00044 namespace Test { namespace Int {
00045 
00046 
00047   /*
00048    * Complete assignments
00049    *
00050    */
00051   void
00052   CpltAssignment::operator++(void) {
00053     int i = n-1;
00054     while (true) {
00055       ++dsv[i];
00056       if (dsv[i]() || (i == 0))
00057         return;
00058       dsv[i--].init(d);
00059     }
00060   }
00061 
00062   /*
00063    * Random assignments
00064    *
00065    */
00066   void
00067   RandomAssignment::operator++(void) {
00068     for (int i = n; i--; )
00069       vals[i]=randval();
00070     a--;
00071   }
00072 
00073   void
00074   RandomMixAssignment::operator++(void) {
00075     for (int i=n-_n1; i--; )
00076       vals[i] = randval(d);
00077     for (int i=_n1; i--; )
00078       vals[n-_n1+i] = randval(_d1);
00079     a--;
00080   }
00081 
00082 }}
00083 
00084 std::ostream&
00085 operator<<(std::ostream& os, const Test::Int::Assignment& a) {
00086   int n = a.size();
00087   os << "{";
00088   for (int i=0; i<n; i++)
00089     os << a[i] << ((i!=n-1) ? "," : "}");
00090   return os;
00091 }
00092 
00093 namespace Test { namespace Int {
00094 
00095   TestSpace::TestSpace(int n, Gecode::IntSet& d0, Test* t)
00096     : d(d0), x(*this,n,Gecode::Int::Limits::min,Gecode::Int::Limits::max), 
00097       test(t), reified(false) {
00098     Gecode::IntVarArgs _x(*this,n,d);
00099     if (x.size() == 1)
00100       Gecode::dom(*this,x[0],_x[0]);
00101     else
00102       Gecode::dom(*this,x,_x);
00103     Gecode::BoolVar b(*this,0,1);
00104     r = Gecode::Reify(b,Gecode::RM_EQV);
00105     if (opt.log)
00106       olog << ind(2) << "Initial: x[]=" << x
00107            << std::endl;
00108   }
00109 
00110   TestSpace::TestSpace(int n, Gecode::IntSet& d0, Test* t,
00111                        Gecode::ReifyMode rm)
00112     : d(d0), x(*this,n,Gecode::Int::Limits::min,Gecode::Int::Limits::max), 
00113       test(t), reified(true) {
00114     Gecode::IntVarArgs _x(*this,n,d);
00115     if (x.size() == 1)
00116       Gecode::dom(*this,x[0],_x[0]);
00117     else
00118       Gecode::dom(*this,x,_x);    
00119     Gecode::BoolVar b(*this,0,1);
00120     r = Gecode::Reify(b,rm);
00121     if (opt.log)
00122       olog << ind(2) << "Initial: x[]=" << x
00123            << " b=" << r.var() << std::endl;
00124   }
00125 
00126   TestSpace::TestSpace(bool share, TestSpace& s)
00127     : Gecode::Space(share,s), d(s.d), test(s.test), reified(s.reified) {
00128     x.update(*this, share, s.x);
00129     Gecode::BoolVar b;
00130     Gecode::BoolVar sr(s.r.var());
00131     b.update(*this, share, sr);
00132     r.var(b); r.mode(s.r.mode());
00133   }
00134 
00135   Gecode::Space* 
00136   TestSpace::copy(bool share) {
00137     return new TestSpace(share,*this);
00138   }
00139 
00140   bool 
00141   TestSpace::assigned(void) const {
00142     for (int i=x.size(); i--; )
00143       if (!x[i].assigned())
00144         return false;
00145     return true;
00146   }
00147 
00148   void 
00149   TestSpace::post(void) {
00150     if (reified){
00151       test->post(*this,x,r);
00152       if (opt.log)
00153         olog << ind(3) << "Posting reified propagator" << std::endl;
00154     } else {
00155       test->post(*this,x);
00156       if (opt.log)
00157         olog << ind(3) << "Posting propagator" << std::endl;
00158     }
00159   }
00160 
00161   bool 
00162   TestSpace::failed(void) {
00163     if (opt.log) {
00164       olog << ind(3) << "Fixpoint: " << x;
00165       bool f=(status() == Gecode::SS_FAILED);
00166       olog << std::endl << ind(3) << "     -->  " << x << std::endl;
00167       return f;
00168     } else {
00169       return status() == Gecode::SS_FAILED;
00170     }
00171   }
00172 
00173   void 
00174   TestSpace::rel(int i, Gecode::IntRelType irt, int n) {
00175     if (opt.log) {
00176       olog << ind(4) << "x[" << i << "] ";
00177       switch (irt) {
00178       case Gecode::IRT_EQ: olog << "="; break;
00179       case Gecode::IRT_NQ: olog << "!="; break;
00180       case Gecode::IRT_LQ: olog << "<="; break;
00181       case Gecode::IRT_LE: olog << "<"; break;
00182       case Gecode::IRT_GQ: olog << ">="; break;
00183       case Gecode::IRT_GR: olog << ">"; break;
00184       }
00185       olog << " " << n << std::endl;
00186     }
00187     Gecode::rel(*this, x[i], irt, n);
00188   }
00189 
00190   void 
00191   TestSpace::rel(bool sol) {
00192     int n = sol ? 1 : 0;
00193     assert(reified);
00194     if (opt.log)
00195       olog << ind(4) << "b = " << n << std::endl;
00196     Gecode::rel(*this, r.var(), Gecode::IRT_EQ, n);
00197   }
00198 
00199   void 
00200   TestSpace::assign(const Assignment& a, bool skip) {
00201     using namespace Gecode;
00202     int i = skip ? static_cast<int>(Base::rand(a.size())) : -1;
00203     for (int j=a.size(); j--; )
00204       if (i != j) {
00205         rel(j, IRT_EQ, a[j]);
00206         if (Base::fixpoint() && failed())
00207           return;
00208       }
00209   }
00210 
00211   void 
00212   TestSpace::bound(void) {
00213     using namespace Gecode;
00214     // Select variable to be assigned
00215     int i = Base::rand(x.size());
00216     while (x[i].assigned()) {
00217       i = (i+1) % x.size();
00218     }
00219     bool min = Base::rand(2);
00220     rel(i, IRT_EQ, min ? x[i].min() : x[i].max());
00221   }
00222 
00223   void 
00224   TestSpace::prune(int i, bool bounds_only) {
00225     using namespace Gecode;
00226     // Prune values
00227     if (bounds_only) {
00228       if (Base::rand(2) && !x[i].assigned()) {
00229         int v=x[i].min()+1+Base::rand(static_cast
00230                                       <unsigned int>(x[i].max()-x[i].min()));
00231         assert((v > x[i].min()) && (v <= x[i].max()));
00232         rel(i, Gecode::IRT_LE, v);
00233       }
00234       if (Base::rand(2) && !x[i].assigned()) {
00235         int v=x[i].min()+Base::rand(static_cast
00236                                     <unsigned int>(x[i].max()-x[i].min()));
00237         assert((v < x[i].max()) && (v >= x[i].min()));
00238         rel(i, Gecode::IRT_GR, v);
00239       }
00240     } else {
00241       for (int vals = Base::rand(x[i].size()-1)+1; vals--; ) {
00242         int v;
00243         Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]);
00244         unsigned int skip = Base::rand(x[i].size()-1);
00245         while (true) {
00246           if (it.width() > skip) {
00247             v = it.min() + skip; break;
00248           }
00249           skip -= it.width(); ++it;
00250         }
00251         rel(i, IRT_NQ, v);
00252       }
00253     }
00254   }
00255 
00256   void 
00257   TestSpace::prune(void) {
00258     using namespace Gecode;
00259     // Select variable to be pruned
00260     int i = Base::rand(x.size());
00261     while (x[i].assigned()) {
00262       i = (i+1) % x.size();
00263     }
00264     prune(i, false);
00265   }
00266 
00267   bool 
00268   TestSpace::prune(const Assignment& a, bool testfix) {
00269     // Select variable to be pruned
00270     int i = Base::rand(x.size());
00271     while (x[i].assigned())
00272       i = (i+1) % x.size();
00273     // Select mode for pruning
00274     switch (Base::rand(3)) {
00275     case 0:
00276       if (a[i] < x[i].max()) {
00277         int v=a[i]+1+Base::rand(static_cast
00278                                 <unsigned int>(x[i].max()-a[i]));
00279         assert((v > a[i]) && (v <= x[i].max()));
00280         rel(i, Gecode::IRT_LE, v);
00281       }
00282       break;
00283     case 1:
00284       if (a[i] > x[i].min()) {
00285         int v=x[i].min()+Base::rand(static_cast
00286                                     <unsigned int>(a[i]-x[i].min()));
00287         assert((v < a[i]) && (v >= x[i].min()));
00288         rel(i, Gecode::IRT_GR, v);
00289       }
00290       break;
00291     default:
00292       {
00293         int v;
00294         Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]);
00295         unsigned int skip = Base::rand(x[i].size()-1);
00296         while (true) {
00297           if (it.width() > skip) {
00298             v = it.min() + skip;
00299             if (v == a[i]) {
00300               if (it.width() == 1) {
00301                 ++it; v = it.min();
00302               } else if (v < it.max()) {
00303                 ++v;
00304               } else {
00305                 --v;
00306               }
00307             }
00308             break;
00309           }
00310           skip -= it.width(); ++it;
00311         }
00312         rel(i, Gecode::IRT_NQ, v);
00313         break;
00314       }
00315     }
00316     if (Base::fixpoint()) {
00317       if (failed() || !testfix)
00318         return true;
00319       TestSpace* c = static_cast<TestSpace*>(clone());
00320       if (opt.log)
00321         olog << ind(3) << "Testing fixpoint on copy" << std::endl;
00322       c->post();
00323       if (c->failed()) {
00324         if (opt.log)
00325           olog << ind(4) << "Copy failed after posting" << std::endl;
00326         delete c; return false;
00327       }
00328       for (int i=x.size(); i--; )
00329         if (x[i].size() != c->x[i].size()) {
00330           if (opt.log)
00331             olog << ind(4) << "Different domain size" << std::endl;
00332           delete c; return false;
00333         }
00334       if (reified && (r.var().size() != c->r.var().size())) {
00335         if (opt.log)
00336           olog << ind(4) << "Different control variable" << std::endl;
00337         delete c; return false;
00338       }
00339       if (opt.log)
00340         olog << ind(3) << "Finished testing fixpoint on copy" << std::endl;
00341       delete c;
00342     }
00343     return true;
00344   }
00345 
00346 
00347   const Gecode::IntConLevel IntConLevels::icls[] =
00348     {Gecode::ICL_DOM,Gecode::ICL_BND,Gecode::ICL_VAL};
00349 
00350   const Gecode::IntRelType IntRelTypes::irts[] =
00351     {Gecode::IRT_EQ,Gecode::IRT_NQ,Gecode::IRT_LQ,
00352      Gecode::IRT_LE,Gecode::IRT_GQ,Gecode::IRT_GR};
00353 
00354   const Gecode::BoolOpType BoolOpTypes::bots[] =
00355     {Gecode::BOT_AND,Gecode::BOT_OR,Gecode::BOT_IMP,
00356      Gecode::BOT_EQV,Gecode::BOT_XOR};
00357 
00358   Assignment*
00359   Test::assignment(void) const {
00360     return new CpltAssignment(arity,dom);
00361   }
00362 
00363 
00365 #define CHECK_TEST(T,M)                                         \
00366 if (opt.log)                                                    \
00367   olog << ind(3) << "Check: " << (M) << std::endl;              \
00368 if (!(T)) {                                                     \
00369   problem = (M); delete s; goto failed;                         \
00370 }
00371 
00373 #define START_TEST(T)                                           \
00374   if (opt.log) {                                                \
00375      olog.str("");                                              \
00376      olog << ind(2) << "Testing: " << (T) << std::endl;         \
00377   }                                                             \
00378   test = (T);
00379 
00380   bool
00381   Test::ignore(const Assignment&) const {
00382     return false;
00383   }
00384 
00385   void
00386   Test::post(Gecode::Space&, Gecode::IntVarArray&,
00387              Gecode::Reify) {}
00388 
00389   bool
00390   Test::run(void) {
00391     using namespace Gecode;
00392     const char* test    = "NONE";
00393     const char* problem = "NONE";
00394 
00395     // Set up assignments
00396     Assignment* ap = assignment();
00397     Assignment& a = *ap;
00398 
00399     // Set up space for all solution search
00400     TestSpace* search_s = new TestSpace(arity,dom,this);
00401     post(*search_s,search_s->x);
00402     branch(*search_s,search_s->x,INT_VAR_NONE(),INT_VAL_MIN());
00403     Search::Options search_o;
00404     search_o.threads = 1;
00405     DFS<TestSpace> e_s(search_s,search_o);
00406     delete search_s;
00407 
00408     while (a()) {
00409       bool sol = solution(a);
00410       if (opt.log) {
00411         olog << ind(1) << "Assignment: " << a
00412              << (sol ? " (solution)" : " (no solution)")
00413              << std::endl;
00414       }
00415 
00416       START_TEST("Assignment (after posting)");
00417       {
00418         TestSpace* s = new TestSpace(arity,dom,this);
00419         TestSpace* sc = NULL;
00420         s->post();
00421         switch (Base::rand(3)) {
00422           case 0:
00423             if (opt.log)
00424               olog << ind(3) << "No copy" << std::endl;
00425             sc = s;
00426             s = NULL;
00427             break;
00428           case 1:
00429             if (opt.log)
00430               olog << ind(3) << "Unshared copy" << std::endl;
00431             if (s->status() != SS_FAILED) {
00432               sc = static_cast<TestSpace*>(s->clone(false));
00433             } else {
00434               sc = s; s = NULL;
00435             }
00436             break;
00437           case 2:
00438             if (opt.log)
00439               olog << ind(3) << "Shared copy" << std::endl;
00440             if (s->status() != SS_FAILED) {
00441               sc = static_cast<TestSpace*>(s->clone(true));
00442             } else {
00443               sc = s; s = NULL;
00444             }
00445             break;
00446           default: assert(false);
00447         }
00448         sc->assign(a);
00449         if (sol) {
00450           CHECK_TEST(!sc->failed(), "Failed on solution");
00451           CHECK_TEST(sc->propagators()==0, "No subsumption");
00452         } else {
00453           CHECK_TEST(sc->failed(), "Solved on non-solution");
00454         }
00455         delete s; delete sc;
00456       }
00457       START_TEST("Partial assignment (after posting)");
00458       {
00459         TestSpace* s = new TestSpace(arity,dom,this);
00460         s->post();
00461         s->assign(a,true);
00462         (void) s->failed();
00463         s->assign(a);
00464         if (sol) {
00465           CHECK_TEST(!s->failed(), "Failed on solution");
00466           CHECK_TEST(s->propagators()==0, "No subsumption");
00467         } else {
00468           CHECK_TEST(s->failed(), "Solved on non-solution");
00469         }
00470         delete s;
00471       }
00472       START_TEST("Assignment (before posting)");
00473       {
00474         TestSpace* s = new TestSpace(arity,dom,this);
00475         s->assign(a);
00476         s->post();
00477         if (sol) {
00478           CHECK_TEST(!s->failed(), "Failed on solution");
00479           CHECK_TEST(s->propagators()==0, "No subsumption");
00480         } else {
00481           CHECK_TEST(s->failed(), "Solved on non-solution");
00482         }
00483         delete s;
00484       }
00485       START_TEST("Partial assignment (before posting)");
00486       {
00487         TestSpace* s = new TestSpace(arity,dom,this);
00488         s->assign(a,true);
00489         s->post();
00490         (void) s->failed();
00491         s->assign(a);
00492         if (sol) {
00493           CHECK_TEST(!s->failed(), "Failed on solution");
00494           CHECK_TEST(s->propagators()==0, "No subsumption");
00495         } else {
00496           CHECK_TEST(s->failed(), "Solved on non-solution");
00497         }
00498         delete s;
00499       }
00500       START_TEST("Prune");
00501       {
00502         TestSpace* s = new TestSpace(arity,dom,this);
00503         s->post();
00504         while (!s->failed() && !s->assigned())
00505           if (!s->prune(a,testfix)) {
00506             problem = "No fixpoint";
00507             delete s;
00508             goto failed;
00509           }
00510         s->assign(a);
00511         if (sol) {
00512           CHECK_TEST(!s->failed(), "Failed on solution");
00513           CHECK_TEST(s->propagators()==0, "No subsumption");
00514         } else {
00515           CHECK_TEST(s->failed(), "Solved on non-solution");
00516         }
00517         delete s;
00518       }
00519 
00520       if (!ignore(a)) {
00521         if (eqv()) {
00522           START_TEST("Assignment reified (rewrite after post, <=>)");
00523           TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
00524           s->post();
00525           s->rel(sol);
00526           s->assign(a);
00527           CHECK_TEST(!s->failed(), "Failed");
00528           CHECK_TEST(s->propagators()==0, "No subsumption");
00529           delete s;
00530         }
00531         if (imp()) {
00532           START_TEST("Assignment reified (rewrite after post, =>)");
00533           TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
00534           s->post();
00535           s->rel(sol);
00536           s->assign(a);
00537           CHECK_TEST(!s->failed(), "Failed");
00538           CHECK_TEST(s->propagators()==0, "No subsumption");
00539           delete s;
00540         }
00541         if (pmi()) {
00542           START_TEST("Assignment reified (rewrite after post, <=)");
00543           TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
00544           s->post();
00545           s->rel(sol);
00546           s->assign(a);
00547           CHECK_TEST(!s->failed(), "Failed");
00548           CHECK_TEST(s->propagators()==0, "No subsumption");
00549           delete s;
00550         }
00551         if (eqv()) {
00552           START_TEST("Assignment reified (rewrite failure, <=>)");
00553           TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
00554           s->post();
00555           s->rel(!sol);
00556           s->assign(a);
00557           CHECK_TEST(s->failed(), "Not failed");
00558           delete s;
00559         }
00560         if (imp()) {
00561           START_TEST("Assignment reified (rewrite failure, =>)");
00562           TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
00563           s->post();
00564           s->rel(!sol);
00565           s->assign(a);
00566           if (sol) {
00567             CHECK_TEST(!s->failed(), "Failed");
00568             CHECK_TEST(s->propagators()==0, "No subsumption");
00569           } else {
00570             CHECK_TEST(s->failed(), "Not failed");
00571           }
00572           delete s;
00573         }
00574         if (pmi()) {
00575           START_TEST("Assignment reified (rewrite failure, <=)");
00576           TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
00577           s->post();
00578           s->rel(!sol);
00579           s->assign(a);
00580           if (sol) {
00581             CHECK_TEST(s->failed(), "Not failed");
00582           } else {
00583             CHECK_TEST(!s->failed(), "Failed");
00584             CHECK_TEST(s->propagators()==0, "No subsumption");
00585           }
00586           delete s;
00587         }
00588         if (eqv()) {
00589           START_TEST("Assignment reified (immediate rewrite, <=>)");
00590           TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
00591           s->rel(sol);
00592           s->post();
00593           s->assign(a);
00594           CHECK_TEST(!s->failed(), "Failed");
00595           CHECK_TEST(s->propagators()==0, "No subsumption");
00596           delete s;
00597         }
00598         if (imp()) {
00599           START_TEST("Assignment reified (immediate rewrite, =>)");
00600           TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
00601           s->rel(sol);
00602           s->post();
00603           s->assign(a);
00604           CHECK_TEST(!s->failed(), "Failed");
00605           CHECK_TEST(s->propagators()==0, "No subsumption");
00606           delete s;
00607         }
00608         if (pmi()) {
00609           START_TEST("Assignment reified (immediate rewrite, <=)");
00610           TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
00611           s->rel(sol);
00612           s->post();
00613           s->assign(a);
00614           CHECK_TEST(!s->failed(), "Failed");
00615           CHECK_TEST(s->propagators()==0, "No subsumption");
00616           delete s;
00617         }
00618         if (eqv()) {
00619           START_TEST("Assignment reified (immediate failure, <=>)");
00620           TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
00621           s->rel(!sol);
00622           s->post();
00623           s->assign(a);
00624           CHECK_TEST(s->failed(), "Not failed");
00625           delete s;
00626         }
00627         if (imp()) {
00628           START_TEST("Assignment reified (immediate failure, =>)");
00629           TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
00630           s->rel(!sol);
00631           s->post();
00632           s->assign(a);
00633           if (sol) {
00634             CHECK_TEST(!s->failed(), "Failed");
00635             CHECK_TEST(s->propagators()==0, "No subsumption");
00636           } else {
00637             CHECK_TEST(s->failed(), "Not failed");
00638           }
00639           delete s;
00640         }
00641         if (pmi()) {
00642           START_TEST("Assignment reified (immediate failure, <=)");
00643           TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
00644           s->rel(!sol);
00645           s->post();
00646           s->assign(a);
00647           if (sol) {
00648             CHECK_TEST(s->failed(), "Not failed");
00649           } else {
00650             CHECK_TEST(!s->failed(), "Failed");
00651             CHECK_TEST(s->propagators()==0, "No subsumption");
00652           }
00653           delete s;
00654         }
00655         if (eqv()) {
00656           START_TEST("Assignment reified (before posting, <=>)");
00657           TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
00658           s->assign(a);
00659           s->post();
00660           CHECK_TEST(!s->failed(), "Failed");
00661           CHECK_TEST(s->propagators()==0, "No subsumption");
00662           CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00663           if (sol) {
00664             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00665           } else {
00666             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00667           }
00668           delete s;
00669         }
00670         if (imp()) {
00671           START_TEST("Assignment reified (before posting, =>)");
00672           TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
00673           s->assign(a);
00674           s->post();
00675           CHECK_TEST(!s->failed(), "Failed");
00676           CHECK_TEST(s->propagators()==0, "No subsumption");
00677           if (sol) {
00678             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00679           } else {
00680             CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00681             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00682           }
00683           delete s;
00684         }
00685         if (pmi()) {
00686           START_TEST("Assignment reified (before posting, <=)");
00687           TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
00688           s->assign(a);
00689           s->post();
00690           CHECK_TEST(!s->failed(), "Failed");
00691           CHECK_TEST(s->propagators()==0, "No subsumption");
00692           if (sol) {
00693             CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00694             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00695           } else {
00696             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00697           }
00698           delete s;
00699         }
00700         if (eqv()) {
00701           START_TEST("Assignment reified (after posting, <=>)");
00702           TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
00703           s->post();
00704           s->assign(a);
00705           CHECK_TEST(!s->failed(), "Failed");
00706           CHECK_TEST(s->propagators()==0, "No subsumption");
00707           CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00708           if (sol) {
00709             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00710           } else {
00711             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00712           }
00713           delete s;
00714         }
00715         if (imp()) {
00716           START_TEST("Assignment reified (after posting, =>)");
00717           TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
00718           s->post();
00719           s->assign(a);
00720           CHECK_TEST(!s->failed(), "Failed");
00721           CHECK_TEST(s->propagators()==0, "No subsumption");
00722           if (sol) {
00723             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00724           } else {
00725             CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00726             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00727           }
00728           delete s;
00729         }
00730         if (pmi()) {
00731           START_TEST("Assignment reified (after posting, <=)");
00732           TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
00733           s->post();
00734           s->assign(a);
00735           CHECK_TEST(!s->failed(), "Failed");
00736           CHECK_TEST(s->propagators()==0, "No subsumption");
00737           if (sol) {
00738             CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00739             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00740           } else {
00741             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00742           }
00743           delete s;
00744         }
00745         if (eqv()) {
00746           START_TEST("Prune reified, <=>");
00747           TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
00748           s->post();
00749           while (!s->failed() && 
00750                  (!s->assigned() || !s->r.var().assigned()))
00751             if (!s->prune(a,testfix)) {
00752               problem = "No fixpoint";
00753               delete s;
00754               goto failed;
00755             }
00756           CHECK_TEST(!s->failed(), "Failed");
00757           CHECK_TEST(s->propagators()==0, "No subsumption");
00758           CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00759           if (sol) {
00760             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00761           } else {
00762             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00763           }
00764           delete s;
00765         }
00766         if (imp()) {
00767           START_TEST("Prune reified, =>");
00768           TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
00769           s->post();
00770           while (!s->failed() && 
00771                  (!s->assigned() || (!sol && !s->r.var().assigned())))
00772             if (!s->prune(a,testfix)) {
00773               problem = "No fixpoint";
00774               delete s;
00775               goto failed;
00776             }
00777           CHECK_TEST(!s->failed(), "Failed");
00778           CHECK_TEST(s->propagators()==0, "No subsumption");
00779           if (sol) {
00780             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00781           } else {
00782             CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00783             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00784           }
00785           delete s;
00786         }
00787         if (pmi()) {
00788           START_TEST("Prune reified, <=");
00789           TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
00790           s->post();
00791           while (!s->failed() && 
00792                  (!s->assigned() || (sol && !s->r.var().assigned())))
00793             if (!s->prune(a,testfix)) {
00794               problem = "No fixpoint";
00795               delete s;
00796               goto failed;
00797             }
00798           CHECK_TEST(!s->failed(), "Failed");
00799           CHECK_TEST(s->propagators()==0, "No subsumption");
00800           if (sol) {
00801             CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
00802             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00803           } else {
00804             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00805           }
00806           delete s;
00807         }
00808       }
00809 
00810       if (testsearch) {
00811         if (sol) {
00812           START_TEST("Search");
00813           TestSpace* s = e_s.next();
00814           CHECK_TEST(s != NULL, "Solutions exhausted");
00815           CHECK_TEST(s->propagators()==0, "No subsumption");
00816           for (int i=a.size(); i--; ) {
00817             CHECK_TEST(s->x[i].assigned(), "Unassigned variable");
00818             CHECK_TEST(a[i] == s->x[i].val(), "Wrong value in solution");
00819           }
00820           delete s;
00821         }
00822       }
00823 
00824       ++a;
00825     }
00826 
00827     if (testsearch) {
00828       test = "Search";
00829       if (e_s.next() != NULL) {
00830         problem = "Excess solutions";
00831         goto failed;
00832       }
00833     }
00834 
00835     switch (contest) {
00836     case CTL_NONE: break;
00837     case CTL_DOMAIN: {
00838       START_TEST("Full domain consistency");
00839       TestSpace* s = new TestSpace(arity,dom,this);
00840       s->post();
00841       if (!s->failed()) {
00842         while (!s->failed() && !s->assigned())
00843           s->prune();
00844         CHECK_TEST(!s->failed(), "Failed");
00845         CHECK_TEST(s->propagators()==0, "No subsumption");
00846       }
00847       delete s;
00848       // Fall-through -- domain implies bounds(d) and bounds(z)
00849     }
00850     case CTL_BOUNDS_D: {
00851       START_TEST("Bounds(D)-consistency");
00852       TestSpace* s = new TestSpace(arity,dom,this);
00853       s->post();
00854       for (int i = s->x.size(); i--; )
00855         s->prune(i, false);
00856       if (!s->failed()) {
00857         while (!s->failed() && !s->assigned())
00858           s->bound();
00859         CHECK_TEST(!s->failed(), "Failed");
00860         CHECK_TEST(s->propagators()==0, "No subsumption");
00861       }
00862       delete s;
00863       // Fall-through -- bounds(d) implies bounds(z)
00864     }
00865     case CTL_BOUNDS_Z: {
00866       START_TEST("Bounds(Z)-consistency");
00867       TestSpace* s = new TestSpace(arity,dom,this);
00868       s->post();
00869       for (int i = s->x.size(); i--; )
00870         s->prune(i, true);
00871       if (!s->failed()) {
00872         while (!s->failed() && !s->assigned())
00873           s->bound();
00874         CHECK_TEST(!s->failed(), "Failed");
00875         CHECK_TEST(s->propagators()==0, "No subsumption");
00876       }
00877       delete s;
00878       break;
00879     }
00880     }
00881 
00882     delete ap;
00883     return true;
00884 
00885   failed:
00886     if (opt.log)
00887       olog << "FAILURE" << std::endl
00888            << ind(1) << "Test:       " << test << std::endl
00889            << ind(1) << "Problem:    " << problem << std::endl;
00890     if (a() && opt.log)
00891       olog << ind(1) << "Assignment: " << a << std::endl;
00892     delete ap;
00893 
00894     return false;
00895   }
00896 
00897 }}
00898 
00899 #undef START_TEST
00900 #undef CHECK_TEST
00901 
00902 // STATISTICS: test-int