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

float.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  *     Vincent Barichard <Vincent.Barichard@univ-angers.fr>
00007  *
00008  *  Copyright:
00009  *     Christian Schulte, 2005
00010  *     Mikael Lagerkvist, 2005
00011  *     Vincent Barichard, 2012
00012  *
00013  *  Last modified:
00014  *     $Date: 2015-01-16 06:05:16 +0100 (Fri, 16 Jan 2015) $ by $Author: tack $
00015  *     $Revision: 14357 $
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 "test/float.hh"
00043 
00044 #include <algorithm>
00045 #include <iomanip>
00046 
00047 namespace Test { namespace Float {
00048 
00049   /*
00050    * Complete assignments
00051    *
00052    */
00053   void
00054   CpltAssignment::operator++(void) {
00055     using namespace Gecode;
00056     int i = n-1;
00057     while (true) {
00058       FloatNum ns = dsv[i].min() + step;
00059       dsv[i] = FloatVal(ns,nextafter(ns,ns+1));
00060       if ((dsv[i].max() < d.max()) || (i == 0))
00061         return;
00062       dsv[i--] = FloatVal(d.min(),nextafter(d.min(),d.max()));
00063     }
00064   }
00065 
00066   /*
00067    * Extended assignments
00068    *
00069    */
00070   void
00071   ExtAssignment::operator++(void) {
00072     using namespace Gecode;
00073     assert(n > 1);
00074     int i = n-2;
00075     while (true) {
00076       FloatNum ns = dsv[i].min() + step;
00077       dsv[i] = FloatVal(ns,nextafter(ns,ns+1));
00078       if ((dsv[i].max() < d.max()) || (i == 0)) {
00079         if (curPb->extendAssignement(*this)) return;
00080         if ((dsv[i].max() >= d.max()) && (i == 0)) return;
00081         continue;
00082       }
00083       dsv[i--] = FloatVal(d.min(),nextafter(d.min(),d.max()));
00084     }
00085   }
00086   
00087   
00088   /*
00089    * Random assignments
00090    *
00091    */
00092   void
00093   RandomAssignment::operator++(void) {
00094     for (int i = n; i--; )
00095       vals[i]=randval();
00096     a--;
00097   }
00098 
00099 }}
00100 
00101 std::ostream&
00102 operator<<(std::ostream& os, const Test::Float::Assignment& a) {
00103   int n = a.size();
00104   os << "{";
00105   for (int i=0; i<n; i++)
00106     os << "[" << a[i].min() << "," << a[i].max() << "]" << ((i!=n-1) ? "," : "}");
00107   return os;
00108 }
00109 
00110 namespace Test { namespace Float {
00111 
00112   Gecode::FloatNum randFValDown(Gecode::FloatNum l, Gecode::FloatNum u) {
00113     using namespace Gecode;
00114     using namespace Gecode::Float;
00115     Rounding r;
00116     return 
00117       r.add_down(
00118         l,
00119         r.mul_down(
00120                    r.div_down(
00121                               Base::rand(static_cast<unsigned int>(Int::Limits::max)),
00122                               static_cast<FloatNum>(Int::Limits::max)
00123                               ),
00124                    r.sub_down(u,l)
00125                    )
00126         );
00127   }
00128 
00129   Gecode::FloatNum randFValUp(Gecode::FloatNum l, Gecode::FloatNum u) {
00130     using namespace Gecode;
00131     using namespace Gecode::Float;
00132     Rounding r;
00133     return 
00134       r.sub_up(
00135         u,
00136         r.mul_down(
00137           r.div_down(
00138             Base::rand(static_cast<unsigned int>(Int::Limits::max)),
00139             static_cast<FloatNum>(Int::Limits::max)
00140           ),
00141           r.sub_down(u,l)
00142         )
00143       );
00144   }
00145 
00146 
00147   TestSpace::TestSpace(int n, Gecode::FloatVal& d0, Gecode::FloatNum s, 
00148                        Test* t)
00149     : d(d0), step(s), 
00150       x(*this,n,Gecode::Float::Limits::min,Gecode::Float::Limits::max), 
00151       test(t), reified(false) {
00152     Gecode::FloatVarArgs _x(*this,n,d.min(),d.max());
00153     if (x.size() == 1)
00154       Gecode::dom(*this,x[0],_x[0]);
00155     else
00156       Gecode::dom(*this,x,_x);
00157     Gecode::BoolVar b(*this,0,1);
00158     r = Gecode::Reify(b,Gecode::RM_EQV);
00159     if (opt.log)
00160       olog << ind(2) << "Initial: x[]=" << x
00161            << std::endl;
00162   }
00163 
00164   TestSpace::TestSpace(int n, Gecode::FloatVal& d0, Gecode::FloatNum s, 
00165                        Test* t, Gecode::ReifyMode rm)
00166     : d(d0), step(s), x(*this,n,d.min(),d.max()), test(t), reified(true) {
00167     Gecode::BoolVar b(*this,0,1);
00168     r = Gecode::Reify(b,rm);
00169     if (opt.log)
00170       olog << ind(2) << "Initial: x[]=" << x
00171            << " b=" << r.var() 
00172            << std::endl;
00173   }
00174 
00175   TestSpace::TestSpace(bool share, TestSpace& s)
00176     : Gecode::Space(share,s), d(s.d), step(s.step), test(s.test), reified(s.reified) {
00177     x.update(*this, share, s.x);
00178     Gecode::BoolVar b;
00179     Gecode::BoolVar sr(s.r.var());
00180     b.update(*this, share, sr);
00181     r.var(b); r.mode(s.r.mode());
00182   }
00183 
00184   Gecode::Space* 
00185   TestSpace::copy(bool share) {
00186     return new TestSpace(share,*this);
00187   }
00188 
00189   void 
00190   TestSpace::dropUntil(const Assignment& a) {
00191     for (int i = x.size(); i--; )
00192       Gecode::rel(*this, x[i], Gecode::FRT_GQ, a[i].min());
00193   }
00194   
00195   bool 
00196   TestSpace::assigned(void) const {
00197     for (int i=x.size(); i--; )
00198       if (!x[i].assigned())
00199         return false;
00200     return true;
00201   }
00202   
00203   bool 
00204   TestSpace::matchAssignment(const Assignment& a) const {
00205     for (int i=x.size(); i--; )
00206       if ((x[i].min() < a[i].min()) && (x[i].max() > a[i].max()))
00207         return false;
00208     return true;
00209   }
00210   
00211   void 
00212   TestSpace::post(void) {
00213     if (reified){
00214       test->post(*this,x,r);
00215       if (opt.log)
00216         olog << ind(3) << "Posting reified propagator" << std::endl;
00217     } else {
00218       test->post(*this,x);
00219       if (opt.log)
00220         olog << ind(3) << "Posting propagator" << std::endl;
00221     }
00222   }
00223 
00224   bool 
00225   TestSpace::failed(void) {
00226     if (opt.log) {
00227       olog << ind(3) << "Fixpoint: " << x;
00228       bool f=(status() == Gecode::SS_FAILED);
00229       olog << std::endl << ind(3) << "     -->  " << x << std::endl;
00230       return f;
00231     } else {
00232       return status() == Gecode::SS_FAILED;
00233     }
00234   }
00235 
00236   void 
00237   TestSpace::rel(int i, Gecode::FloatRelType frt, Gecode::FloatVal n) {
00238     if (opt.log) {
00239       olog << ind(4) << "x[" << i << "] ";
00240       switch (frt) {
00241       case Gecode::FRT_EQ: olog << "="; break;
00242       case Gecode::FRT_NQ: olog << "!="; break;
00243       case Gecode::FRT_LQ: olog << "<="; break;
00244       case Gecode::FRT_LE: olog << "<"; break;
00245       case Gecode::FRT_GQ: olog << ">="; break;
00246       case Gecode::FRT_GR: olog << ">"; break;
00247       }
00248       olog << " [" << n.min() << "," << n.max() << "]" << std::endl;
00249     }
00250     Gecode::rel(*this, x[i], frt, n);
00251   }
00252 
00253   void 
00254   TestSpace::rel(bool sol) {
00255     int n = sol ? 1 : 0;
00256     assert(reified);
00257     if (opt.log)
00258       olog << ind(4) << "b = " << n << std::endl;
00259     Gecode::rel(*this, r.var(), Gecode::IRT_EQ, n);
00260   }
00261 
00262   void 
00263   TestSpace::assign(const Assignment& a, MaybeType& sol, bool skip) {
00264     using namespace Gecode;
00265     int i = skip ? static_cast<int>(Base::rand(a.size())) : -1;
00266 
00267     for (int j=a.size(); j--; )
00268       if (i != j) {
00269         if ((x[j].min() == a[j].max()) || (x[j].max() == a[j].min()))
00270         {
00271           sol = MT_MAYBE;
00272           return;
00273         }
00274         rel(j, FRT_EQ, a[j]);
00275         if (Base::fixpoint() && failed())
00276           return;
00277       }
00278   }
00279 
00280   void 
00281   TestSpace::bound(void) {
00282     using namespace Gecode;
00283     // Select variable to be assigned
00284     int i = Base::rand(x.size());
00285     while (x[i].assigned()) {
00286       i = (i+1) % x.size();
00287     }
00288     bool min = Base::rand(2);
00289     if (min)
00290       rel(i, FRT_LQ, nextafter(x[i].min(), x[i].max()));
00291     else
00292       rel(i, FRT_GQ, nextafter(x[i].max(), x[i].min()));
00293   }
00294 
00295   Gecode::FloatNum
00296   TestSpace::cut(int* cutDirections) {
00297     using namespace Gecode;
00298     using namespace Gecode::Float;
00299     // Select variable to be cut
00300     int i = 0;
00301     while (x[i].assigned()) i++;
00302     for (int j=x.size(); j--; ) {
00303       if (!x[j].assigned() && (x[j].size() > x[i].size())) i = j;
00304     }
00305     Rounding r;
00306     if (cutDirections[i]) {
00307       FloatNum m = r.div_up(r.add_up(x[i].min(),x[i].max()),2);
00308       FloatNum n = nextafter(x[i].min(), x[i].max());
00309       if (m > n)
00310         rel(i, FRT_LQ, m);
00311       else
00312         rel(i, FRT_LQ, n);
00313     } else {
00314       FloatNum m = r.div_down(r.add_down(x[i].min(),x[i].max()),2);
00315       FloatNum n = nextafter(x[i].max(), x[i].min());
00316       if (m < n)
00317         rel(i, FRT_GQ, m);
00318       else
00319         rel(i, FRT_GQ, n);
00320     }
00321     return x[i].size();
00322   }
00323   
00324   void 
00325   TestSpace::prune(int i) {
00326     using namespace Gecode;
00327     // Prune values
00328     if (Base::rand(2) && !x[i].assigned()) {
00329       Gecode::FloatNum v=randFValUp(x[i].min(),x[i].max());
00330       assert((v >= x[i].min()) && (v <= x[i].max()));
00331       rel(i, Gecode::FRT_LQ, v);
00332     }
00333     if (Base::rand(2) && !x[i].assigned()) {
00334       Gecode::FloatNum v=randFValDown(x[i].min(),x[i].max());
00335       assert((v <= x[i].max()) && (v >= x[i].min()));
00336       rel(i, Gecode::FRT_GQ, v);
00337     }
00338   }
00339 
00340   void 
00341   TestSpace::prune(void) {
00342     using namespace Gecode;
00343     // Select variable to be pruned
00344     int i = Base::rand(x.size());
00345     while (x[i].assigned()) {
00346       i = (i+1) % x.size();
00347     }
00348     prune(i);
00349   }
00350 
00351   bool 
00352   TestSpace::prune(const Assignment& a, bool testfix) {
00353     // Select variable to be pruned
00354     int i = Base::rand(x.size());
00355     while (x[i].assigned())
00356       i = (i+1) % x.size();
00357     // Select mode for pruning
00358     switch (Base::rand(2)) {
00359     case 0:
00360       if (a[i].max() < x[i].max()) {
00361         Gecode::FloatNum v=randFValDown(a[i].max(),x[i].max());
00362         if (v==x[i].max())
00363           v = a[i].max();
00364         assert((v >= a[i].max()) && (v <= x[i].max()));
00365         rel(i, Gecode::FRT_LQ, v);
00366       }
00367       break;
00368     case 1:
00369       if (a[i].min() > x[i].min()) {
00370         Gecode::FloatNum v=randFValUp(x[i].min(),a[i].min());
00371         if (v==x[i].min())
00372           v = a[i].min();
00373         assert((v <= a[i].min()) && (v >= x[i].min()));
00374         rel(i, Gecode::FRT_GQ, v);
00375       }
00376       break;
00377     }
00378     if (Base::fixpoint()) {
00379       if (failed() || !testfix)
00380         return true;
00381       TestSpace* c = static_cast<TestSpace*>(clone());
00382       if (opt.log)
00383         olog << ind(3) << "Testing fixpoint on copy" << std::endl;
00384       c->post();
00385       if (c->failed()) {
00386         delete c; return false;
00387       }
00388       for (int i=x.size(); i--; )
00389         if (x[i].size() != c->x[i].size()) {
00390           delete c; return false;
00391         }
00392       if (reified && (r.var().size() != c->r.var().size())) {
00393         delete c; return false;
00394       }
00395       if (opt.log)
00396         olog << ind(3) << "Finished testing fixpoint on copy" << std::endl;
00397       delete c;
00398     }
00399     return true;
00400   }
00401 
00402 
00403   const Gecode::FloatRelType FloatRelTypes::frts[] =
00404     {Gecode::FRT_EQ,Gecode::FRT_NQ,Gecode::FRT_LQ,Gecode::FRT_LE,
00405      Gecode::FRT_GQ,Gecode::FRT_GR};
00406 
00407   Assignment*
00408   Test::assignment(void) const {
00409     switch (assigmentType) {
00410     case CPLT_ASSIGNMENT:
00411       return new CpltAssignment(arity,dom,step);
00412     case RANDOM_ASSIGNMENT:
00413       return new RandomAssignment(arity,dom,step);
00414     case EXTEND_ASSIGNMENT:
00415       return new ExtAssignment(arity,dom,step,this);
00416     default :
00417       GECODE_NEVER;
00418     }
00419     return NULL; // Avoid compiler warnings
00420   }
00421 
00422   bool
00423   Test::extendAssignement(Assignment&) const {
00424     GECODE_NEVER;
00425     return false;
00426   }
00427   
00428   bool
00429   Test::subsumed(const TestSpace& ts) const {
00430     if (!testsubsumed) return true;
00431     if (ts.propagators()==0) return true;
00432     if (assigmentType == EXTEND_ASSIGNMENT) return true;
00433     return false;
00434   }
00435   
00437 #define CHECK_TEST(T,M)                                         \
00438 if (opt.log)                                                    \
00439   olog << ind(3) << "Check: " << (M) << std::endl;              \
00440 if (!(T)) {                                                     \
00441   problem = (M); delete s; goto failed;                         \
00442 }
00443 
00445 #define START_TEST(T)                                           \
00446   if (opt.log) {                                                \
00447      olog.str("");                                              \
00448      olog << ind(2) << "Testing: " << (T) << std::endl;         \
00449   }                                                             \
00450   test = (T);
00451 
00452   bool
00453   Test::ignore(const Assignment&) const {
00454     return false;
00455   }
00456 
00457   void
00458   Test::post(Gecode::Space&, Gecode::FloatVarArray&,
00459              Gecode::Reify) {}
00460 
00461   bool
00462   Test::run(void) {
00463     using namespace Gecode;
00464     const char* test    = "NONE";
00465     const char* problem = "NONE";
00466 
00467     // Set up assignments
00468     Assignment* ap = assignment();
00469     Assignment& a = *ap;
00470     
00471     // Set up space for all solution search
00472     TestSpace* search_s = new TestSpace(arity,dom,step,this);
00473     post(*search_s,search_s->x);
00474     branch(*search_s,search_s->x,FLOAT_VAR_NONE(),FLOAT_VAL_SPLIT_MIN());
00475     Search::Options search_o;
00476     search_o.threads = 1;
00477     DFS<TestSpace> * e_s = new DFS<TestSpace>(search_s,search_o);
00478     while (a()) {
00479       MaybeType sol = solution(a);
00480       if (opt.log) {
00481         olog << ind(1) << "Assignment: " << a;
00482         switch (sol) {
00483         case MT_TRUE: olog << " (solution)"; break;
00484         case MT_FALSE: olog << " (no solution)"; break;
00485         case MT_MAYBE: olog << " (maybe)"; break;
00486         }
00487         olog << std::endl;
00488       }
00489       START_TEST("Assignment (after posting)");
00490       {
00491         TestSpace* s = new TestSpace(arity,dom,step,this);
00492         TestSpace* sc = NULL;
00493         s->post();
00494         switch (Base::rand(3)) {
00495           case 0:
00496             if (opt.log)
00497               olog << ind(3) << "No copy" << std::endl;
00498             sc = s;
00499             s = NULL;
00500             break;
00501           case 1:
00502             if (opt.log)
00503               olog << ind(3) << "Unshared copy" << std::endl;
00504             if (s->status() != SS_FAILED) {
00505               sc = static_cast<TestSpace*>(s->clone(false));
00506             } else {
00507               sc = s; s = NULL;
00508             }
00509             break;
00510           case 2:
00511             if (opt.log)
00512               olog << ind(3) << "Shared copy" << std::endl;
00513             if (s->status() != SS_FAILED) {
00514               sc = static_cast<TestSpace*>(s->clone(true));
00515             } else {
00516               sc = s; s = NULL;
00517             }
00518             break;
00519           default: assert(false);
00520         }
00521         sc->assign(a,sol);
00522         if (sol == MT_TRUE) {
00523           CHECK_TEST(!sc->failed(), "Failed on solution");
00524           CHECK_TEST(subsumed(*sc), "No subsumption");
00525         } else if (sol == MT_FALSE) {
00526           CHECK_TEST(sc->failed(), "Solved on non-solution");
00527         }
00528         delete s; delete sc;
00529       }
00530       START_TEST("Partial assignment (after posting)");
00531       {
00532         TestSpace* s = new TestSpace(arity,dom,step,this);
00533         s->post();
00534         s->assign(a,sol,true);
00535         (void) s->failed();
00536         s->assign(a,sol);
00537         if (sol == MT_TRUE) {
00538           CHECK_TEST(!s->failed(), "Failed on solution");
00539           CHECK_TEST(subsumed(*s), "No subsumption");
00540         } else if (sol == MT_FALSE) {
00541           CHECK_TEST(s->failed(), "Solved on non-solution");
00542         }
00543         delete s;
00544       }
00545       START_TEST("Assignment (before posting)");
00546       {
00547         TestSpace* s = new TestSpace(arity,dom,step,this);
00548         s->assign(a,sol);
00549         s->post();
00550         if (sol == MT_TRUE) {
00551           CHECK_TEST(!s->failed(), "Failed on solution");
00552           CHECK_TEST(subsumed(*s), "No subsumption");
00553         } else if (sol == MT_FALSE) {
00554           CHECK_TEST(s->failed(), "Solved on non-solution");
00555         }
00556         delete s;
00557       }
00558       START_TEST("Partial assignment (before posting)");
00559       {
00560         TestSpace* s = new TestSpace(arity,dom,step,this);
00561         s->assign(a,sol,true);
00562         s->post();
00563         (void) s->failed();
00564         s->assign(a,sol);
00565         if (sol == MT_TRUE) {
00566           CHECK_TEST(!s->failed(), "Failed on solution");
00567           CHECK_TEST(subsumed(*s), "No subsumption");
00568         } else if (sol == MT_FALSE) {
00569           CHECK_TEST(s->failed(), "Solved on non-solution");
00570         }
00571         delete s;
00572       }
00573       START_TEST("Prune");
00574       {
00575         TestSpace* s = new TestSpace(arity,dom,step,this);
00576         s->post();
00577         while (!s->failed() && !s->assigned() && !s->matchAssignment(a))
00578           if (!s->prune(a,testfix)) {
00579             problem = "No fixpoint";
00580             delete s;
00581             goto failed;
00582           }
00583         s->assign(a,sol);
00584         if (sol == MT_TRUE) {
00585           CHECK_TEST(!s->failed(), "Failed on solution");
00586           CHECK_TEST(subsumed(*s), "No subsumption");
00587         } else if (sol == MT_FALSE) {
00588           CHECK_TEST(s->failed(), "Solved on non-solution");
00589         }
00590         delete s;
00591       }
00592 
00593       if (reified && !ignore(a) && (sol != MT_MAYBE)) {
00594         if (eqv()) {
00595           START_TEST("Assignment reified (rewrite after post, <=>)");
00596           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00597           s->post();
00598           s->rel(sol == MT_TRUE);
00599           s->assign(a,sol);
00600           CHECK_TEST(!s->failed(), "Failed");
00601           CHECK_TEST(subsumed(*s), "No subsumption");
00602           delete s;
00603         }
00604         if (imp()) {
00605           START_TEST("Assignment reified (rewrite after post, =>)");
00606           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00607           s->post();
00608           s->rel(sol == MT_TRUE);
00609           s->assign(a,sol);
00610           CHECK_TEST(!s->failed(), "Failed");
00611           CHECK_TEST(subsumed(*s), "No subsumption");
00612           delete s;
00613         }
00614         if (pmi()) {
00615           START_TEST("Assignment reified (rewrite after post, <=)");
00616           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00617           s->post();
00618           s->rel(sol == MT_TRUE);
00619           s->assign(a,sol);
00620           CHECK_TEST(!s->failed(), "Failed");
00621           CHECK_TEST(subsumed(*s), "No subsumption");
00622           delete s;
00623         }
00624         if (eqv()) {
00625           START_TEST("Assignment reified (immediate rewrite, <=>)");
00626           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00627           s->rel(sol == MT_TRUE);
00628           s->post();
00629           s->assign(a,sol);
00630           CHECK_TEST(!s->failed(), "Failed");
00631           CHECK_TEST(subsumed(*s), "No subsumption");
00632           delete s;
00633         }
00634         if (imp()) {
00635           START_TEST("Assignment reified (immediate rewrite, =>)");
00636           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00637           s->rel(sol == MT_TRUE);
00638           s->post();
00639           s->assign(a,sol);
00640           CHECK_TEST(!s->failed(), "Failed");
00641           CHECK_TEST(subsumed(*s), "No subsumption");
00642           delete s;
00643         }
00644         if (pmi()) {
00645           START_TEST("Assignment reified (immediate rewrite, <=)");
00646           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00647           s->rel(sol == MT_TRUE);
00648           s->post();
00649           s->assign(a,sol);
00650           CHECK_TEST(!s->failed(), "Failed");
00651           CHECK_TEST(subsumed(*s), "No subsumption");
00652           delete s;
00653         }
00654         if (eqv()) {
00655           START_TEST("Assignment reified (before posting, <=>)");
00656           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00657           s->assign(a,sol);
00658           s->post();
00659           CHECK_TEST(!s->failed(), "Failed");
00660           CHECK_TEST(subsumed(*s), "No subsumption");
00661           if (s->r.var().assigned()) {
00662             if (sol == MT_TRUE) {
00663               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00664             } else if (sol == MT_FALSE) {
00665               CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00666             }
00667           }
00668           delete s;
00669         }
00670         if (imp()) {
00671           START_TEST("Assignment reified (before posting, =>)");
00672           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00673           s->assign(a,sol);
00674           s->post();
00675           CHECK_TEST(!s->failed(), "Failed");
00676           CHECK_TEST(subsumed(*s), "No subsumption");
00677           if (sol == MT_TRUE) {
00678             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00679           } else if ((sol = MT_FALSE) && s->r.var().assigned()) {
00680             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00681           }
00682           delete s;
00683         }
00684         if (pmi()) {
00685           START_TEST("Assignment reified (before posting, <=)");
00686           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00687           s->assign(a,sol);
00688           s->post();
00689           CHECK_TEST(!s->failed(), "Failed");
00690           CHECK_TEST(subsumed(*s), "No subsumption");
00691           if (sol == MT_TRUE) {
00692             if (s->r.var().assigned()) {
00693               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00694             } 
00695           } else if (sol == MT_FALSE) {
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,step,this,RM_EQV);
00703           s->post();
00704           s->assign(a,sol);
00705           CHECK_TEST(!s->failed(), "Failed");
00706           CHECK_TEST(subsumed(*s), "No subsumption");
00707           if (s->r.var().assigned()) {
00708             if (sol == MT_TRUE) {
00709               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00710             } else if (sol == MT_FALSE) {
00711               CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00712             }
00713           }
00714           delete s;
00715         }
00716         if (imp()) {
00717           START_TEST("Assignment reified (after posting, =>)");
00718           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00719           s->post();
00720           s->assign(a,sol);
00721           CHECK_TEST(!s->failed(), "Failed");
00722           CHECK_TEST(subsumed(*s), "No subsumption");
00723           if (sol == MT_TRUE) {
00724             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00725           } else if (s->r.var().assigned()) {
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,step,this,RM_PMI);
00733           s->post();
00734           s->assign(a,sol);
00735           CHECK_TEST(!s->failed(), "Failed");
00736           CHECK_TEST(subsumed(*s), "No subsumption");
00737           if (sol == MT_TRUE) {
00738             if (s->r.var().assigned()) {
00739               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00740             } 
00741           } else if (sol == MT_FALSE) {
00742             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00743           }
00744           delete s;
00745         }
00746         if (eqv()) {
00747           START_TEST("Prune reified, <=>");
00748           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00749           s->post();
00750           while (!s->failed() && !s->matchAssignment(a) &&
00751                  (!s->assigned() || !s->r.var().assigned()))
00752             if (!s->prune(a,testfix)) {
00753               problem = "No fixpoint";
00754               delete s;
00755               goto failed;
00756             }
00757           CHECK_TEST(!s->failed(), "Failed");
00758           CHECK_TEST(subsumed(*s), "No subsumption");
00759           if (s->r.var().assigned()) {
00760             if (sol == MT_TRUE) {
00761               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00762             } else if (sol == MT_FALSE) {
00763               CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00764             }
00765           }
00766           delete s;
00767         }
00768         if (imp()) {
00769           START_TEST("Prune reified, =>");
00770           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00771           s->post();
00772           while (!s->failed() && !s->matchAssignment(a) &&
00773                  (!s->assigned() || ((sol == MT_FALSE) && 
00774                                      !s->r.var().assigned())))
00775             if (!s->prune(a,testfix)) {
00776               problem = "No fixpoint";
00777               delete s;
00778               goto failed;
00779             }
00780           CHECK_TEST(!s->failed(), "Failed");
00781           CHECK_TEST(subsumed(*s), "No subsumption");
00782           if (sol == MT_TRUE) {
00783             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00784           } else if ((sol == MT_FALSE) && s->r.var().assigned()) {
00785             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00786           }
00787           delete s;
00788         }
00789         if (pmi()) {
00790           START_TEST("Prune reified, <=");
00791           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00792           s->post();
00793           while (!s->failed() && !s->matchAssignment(a) &&
00794                  (!s->assigned() || ((sol == MT_TRUE) && 
00795                                      !s->r.var().assigned())))
00796             if (!s->prune(a,testfix)) {
00797               problem = "No fixpoint";
00798               delete s;
00799               goto failed;
00800             }
00801           CHECK_TEST(!s->failed(), "Failed");
00802           CHECK_TEST(subsumed(*s), "No subsumption");
00803           if ((sol == MT_TRUE) && s->r.var().assigned()) {
00804             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00805           } else if (sol == MT_FALSE) {
00806             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00807           }
00808           delete s;
00809         }
00810       }
00811 
00812       if (testsearch) {
00813         if (sol == MT_TRUE) {
00814           START_TEST("Search");
00815           if (!search_s->failed()) {
00816             TestSpace* ss = static_cast<TestSpace*>(search_s->clone(false));
00817             ss->dropUntil(a);
00818             delete e_s;
00819             e_s = new DFS<TestSpace>(ss,search_o);
00820             delete ss;
00821           }
00822           TestSpace* s = e_s->next();
00823           CHECK_TEST(s != NULL, "Solutions exhausted");
00824           CHECK_TEST(subsumed(*s), "No subsumption");
00825           for (int i=a.size(); i--; ) {
00826             CHECK_TEST(s->x[i].assigned(), "Unassigned variable");
00827             CHECK_TEST(Gecode::Float::overlap(a[i], s->x[i].val()), "Wrong value in solution");
00828           }
00829           delete s;
00830         }
00831       }
00832 
00833       ++a;
00834     }
00835 
00836     if (testsearch) {
00837       test = "Search";
00838       if (!search_s->failed()) {
00839         TestSpace* ss = static_cast<TestSpace*>(search_s->clone(false));
00840         ss->dropUntil(a);
00841         delete e_s;
00842         e_s = new DFS<TestSpace>(ss,search_o);
00843         delete ss;
00844       }
00845       if (e_s->next() != NULL) {
00846         problem = "Excess solutions";
00847         goto failed;
00848       }
00849     }
00850 
00851     delete ap;
00852     delete search_s;
00853     delete e_s;
00854     return true;
00855 
00856   failed:
00857     if (opt.log)
00858       olog << "FAILURE" << std::endl
00859            << ind(1) << "Test:       " << test << std::endl
00860            << ind(1) << "Problem:    " << problem << std::endl;
00861     if (a() && opt.log)
00862       olog << ind(1) << "Assignment: " << a << std::endl;
00863     delete ap;
00864     delete search_s;
00865     delete e_s;
00866 
00867     return false;
00868   }
00869 
00870 }}
00871 
00872 #undef START_TEST
00873 #undef CHECK_TEST
00874 
00875 // STATISTICS: test-float