Generated on Tue Apr 18 10:21:43 2017 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: 2016-10-20 17:25:30 +0200 (Thu, 20 Oct 2016) $ by $Author: schulte $
00015  *     $Revision: 15217 $
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::enable(void) {
00191     Gecode::PropagatorGroup::all.enable(*this);
00192   }
00193 
00194   void
00195   TestSpace::disable(void) {
00196     Gecode::PropagatorGroup::all.disable(*this);
00197     (void) status();
00198   }
00199 
00200   void
00201   TestSpace::dropUntil(const Assignment& a) {
00202     for (int i = x.size(); i--; )
00203       Gecode::rel(*this, x[i], Gecode::FRT_GQ, a[i].min());
00204   }
00205 
00206   bool
00207   TestSpace::assigned(void) const {
00208     for (int i=x.size(); i--; )
00209       if (!x[i].assigned())
00210         return false;
00211     return true;
00212   }
00213 
00214   bool
00215   TestSpace::matchAssignment(const Assignment& a) const {
00216     for (int i=x.size(); i--; )
00217       if ((x[i].min() < a[i].min()) && (x[i].max() > a[i].max()))
00218         return false;
00219     return true;
00220   }
00221 
00222   void
00223   TestSpace::post(void) {
00224     if (reified){
00225       test->post(*this,x,r);
00226       if (opt.log)
00227         olog << ind(3) << "Posting reified propagator" << std::endl;
00228     } else {
00229       test->post(*this,x);
00230       if (opt.log)
00231         olog << ind(3) << "Posting propagator" << std::endl;
00232     }
00233   }
00234 
00235   bool
00236   TestSpace::failed(void) {
00237     if (opt.log) {
00238       olog << ind(3) << "Fixpoint: " << x;
00239       bool f=(status() == Gecode::SS_FAILED);
00240       olog << std::endl << ind(3) << "     -->  " << x << std::endl;
00241       return f;
00242     } else {
00243       return status() == Gecode::SS_FAILED;
00244     }
00245   }
00246 
00247   void
00248   TestSpace::rel(int i, Gecode::FloatRelType frt, Gecode::FloatVal n) {
00249     if (opt.log) {
00250       olog << ind(4) << "x[" << i << "] ";
00251       switch (frt) {
00252       case Gecode::FRT_EQ: olog << "="; break;
00253       case Gecode::FRT_NQ: olog << "!="; break;
00254       case Gecode::FRT_LQ: olog << "<="; break;
00255       case Gecode::FRT_LE: olog << "<"; break;
00256       case Gecode::FRT_GQ: olog << ">="; break;
00257       case Gecode::FRT_GR: olog << ">"; break;
00258       }
00259       olog << " [" << n.min() << "," << n.max() << "]" << std::endl;
00260     }
00261     Gecode::rel(*this, x[i], frt, n);
00262   }
00263 
00264   void
00265   TestSpace::rel(bool sol) {
00266     int n = sol ? 1 : 0;
00267     assert(reified);
00268     if (opt.log)
00269       olog << ind(4) << "b = " << n << std::endl;
00270     Gecode::rel(*this, r.var(), Gecode::IRT_EQ, n);
00271   }
00272 
00273   void
00274   TestSpace::assign(const Assignment& a, MaybeType& sol, bool skip) {
00275     using namespace Gecode;
00276     int i = skip ? static_cast<int>(Base::rand(a.size())) : -1;
00277 
00278     for (int j=a.size(); j--; )
00279       if (i != j) {
00280         if ((x[j].min() == a[j].max()) || (x[j].max() == a[j].min()))
00281         {
00282           sol = MT_MAYBE;
00283           return;
00284         }
00285         rel(j, FRT_EQ, a[j]);
00286         if (Base::fixpoint() && failed())
00287           return;
00288       }
00289   }
00290 
00291   void
00292   TestSpace::bound(void) {
00293     using namespace Gecode;
00294     // Select variable to be assigned
00295     int i = Base::rand(x.size());
00296     while (x[i].assigned()) {
00297       i = (i+1) % x.size();
00298     }
00299     bool min = Base::rand(2);
00300     if (min)
00301       rel(i, FRT_LQ, nextafter(x[i].min(), x[i].max()));
00302     else
00303       rel(i, FRT_GQ, nextafter(x[i].max(), x[i].min()));
00304   }
00305 
00306   Gecode::FloatNum
00307   TestSpace::cut(int* cutDirections) {
00308     using namespace Gecode;
00309     using namespace Gecode::Float;
00310     // Select variable to be cut
00311     int i = 0;
00312     while (x[i].assigned()) i++;
00313     for (int j=x.size(); j--; ) {
00314       if (!x[j].assigned() && (x[j].size() > x[i].size())) i = j;
00315     }
00316     Rounding r;
00317     if (cutDirections[i]) {
00318       FloatNum m = r.div_up(r.add_up(x[i].min(),x[i].max()),2);
00319       FloatNum n = nextafter(x[i].min(), x[i].max());
00320       if (m > n)
00321         rel(i, FRT_LQ, m);
00322       else
00323         rel(i, FRT_LQ, n);
00324     } else {
00325       FloatNum m = r.div_down(r.add_down(x[i].min(),x[i].max()),2);
00326       FloatNum n = nextafter(x[i].max(), x[i].min());
00327       if (m < n)
00328         rel(i, FRT_GQ, m);
00329       else
00330         rel(i, FRT_GQ, n);
00331     }
00332     return x[i].size();
00333   }
00334 
00335   void
00336   TestSpace::prune(int i) {
00337     using namespace Gecode;
00338     // Prune values
00339     if (Base::rand(2) && !x[i].assigned()) {
00340       Gecode::FloatNum v=randFValUp(x[i].min(),x[i].max());
00341       assert((v >= x[i].min()) && (v <= x[i].max()));
00342       rel(i, Gecode::FRT_LQ, v);
00343     }
00344     if (Base::rand(2) && !x[i].assigned()) {
00345       Gecode::FloatNum v=randFValDown(x[i].min(),x[i].max());
00346       assert((v <= x[i].max()) && (v >= x[i].min()));
00347       rel(i, Gecode::FRT_GQ, v);
00348     }
00349   }
00350 
00351   void
00352   TestSpace::prune(void) {
00353     using namespace Gecode;
00354     // Select variable to be pruned
00355     int i = Base::rand(x.size());
00356     while (x[i].assigned()) {
00357       i = (i+1) % x.size();
00358     }
00359     prune(i);
00360   }
00361 
00362   bool
00363   TestSpace::prune(const Assignment& a, bool testfix) {
00364     // Select variable to be pruned
00365     int i = Base::rand(x.size());
00366     while (x[i].assigned())
00367       i = (i+1) % x.size();
00368     // Select mode for pruning
00369     switch (Base::rand(2)) {
00370     case 0:
00371       if (a[i].max() < x[i].max()) {
00372         Gecode::FloatNum v=randFValDown(a[i].max(),x[i].max());
00373         if (v==x[i].max())
00374           v = a[i].max();
00375         assert((v >= a[i].max()) && (v <= x[i].max()));
00376         rel(i, Gecode::FRT_LQ, v);
00377       }
00378       break;
00379     case 1:
00380       if (a[i].min() > x[i].min()) {
00381         Gecode::FloatNum v=randFValUp(x[i].min(),a[i].min());
00382         if (v==x[i].min())
00383           v = a[i].min();
00384         assert((v <= a[i].min()) && (v >= x[i].min()));
00385         rel(i, Gecode::FRT_GQ, v);
00386       }
00387       break;
00388     }
00389     if (Base::fixpoint()) {
00390       if (failed() || !testfix)
00391         return true;
00392       TestSpace* c = static_cast<TestSpace*>(clone());
00393       if (opt.log)
00394         olog << ind(3) << "Testing fixpoint on copy" << std::endl;
00395       c->post();
00396       if (c->failed()) {
00397         delete c; return false;
00398       }
00399       for (int i=x.size(); i--; )
00400         if (x[i].size() != c->x[i].size()) {
00401           delete c; return false;
00402         }
00403       if (reified && (r.var().size() != c->r.var().size())) {
00404         delete c; return false;
00405       }
00406       if (opt.log)
00407         olog << ind(3) << "Finished testing fixpoint on copy" << std::endl;
00408       delete c;
00409     }
00410     return true;
00411   }
00412 
00413   unsigned int
00414   TestSpace::propagators(void) {
00415     return Gecode::PropagatorGroup::all.size(*this);
00416   }
00417 
00418 
00419   const Gecode::FloatRelType FloatRelTypes::frts[] =
00420     {Gecode::FRT_EQ,Gecode::FRT_NQ,Gecode::FRT_LQ,Gecode::FRT_LE,
00421      Gecode::FRT_GQ,Gecode::FRT_GR};
00422 
00423   Assignment*
00424   Test::assignment(void) const {
00425     switch (assigmentType) {
00426     case CPLT_ASSIGNMENT:
00427       return new CpltAssignment(arity,dom,step);
00428     case RANDOM_ASSIGNMENT:
00429       return new RandomAssignment(arity,dom,step);
00430     case EXTEND_ASSIGNMENT:
00431       return new ExtAssignment(arity,dom,step,this);
00432     default :
00433       GECODE_NEVER;
00434     }
00435     return NULL; // Avoid compiler warnings
00436   }
00437 
00438   bool
00439   Test::extendAssignement(Assignment&) const {
00440     GECODE_NEVER;
00441     return false;
00442   }
00443 
00444   bool
00445   Test::subsumed(const TestSpace& ts) const {
00446     if (!testsubsumed) return true;
00447     if (const_cast<TestSpace&>(ts).propagators() == 0) return true;
00448     if (assigmentType == EXTEND_ASSIGNMENT) return true;
00449     return false;
00450   }
00451 
00453 #define CHECK_TEST(T,M)                                         \
00454 if (opt.log)                                                    \
00455   olog << ind(3) << "Check: " << (M) << std::endl;              \
00456 if (!(T)) {                                                     \
00457   problem = (M); delete s; goto failed;                         \
00458 }
00459 
00461 #define START_TEST(T)                                           \
00462   if (opt.log) {                                                \
00463      olog.str("");                                              \
00464      olog << ind(2) << "Testing: " << (T) << std::endl;         \
00465   }                                                             \
00466   test = (T);
00467 
00468   bool
00469   Test::ignore(const Assignment&) const {
00470     return false;
00471   }
00472 
00473   void
00474   Test::post(Gecode::Space&, Gecode::FloatVarArray&,
00475              Gecode::Reify) {}
00476 
00477   bool
00478   Test::run(void) {
00479     using namespace Gecode;
00480     const char* test    = "NONE";
00481     const char* problem = "NONE";
00482 
00483     // Set up assignments
00484     Assignment* ap = assignment();
00485     Assignment& a = *ap;
00486 
00487     // Set up space for all solution search
00488     TestSpace* search_s = new TestSpace(arity,dom,step,this);
00489     post(*search_s,search_s->x);
00490     branch(*search_s,search_s->x,FLOAT_VAR_NONE(),FLOAT_VAL_SPLIT_MIN());
00491     Search::Options search_o;
00492     search_o.threads = 1;
00493     DFS<TestSpace> * e_s = new DFS<TestSpace>(search_s,search_o);
00494     while (a()) {
00495       MaybeType sol = solution(a);
00496       if (opt.log) {
00497         olog << ind(1) << "Assignment: " << a;
00498         switch (sol) {
00499         case MT_TRUE: olog << " (solution)"; break;
00500         case MT_FALSE: olog << " (no solution)"; break;
00501         case MT_MAYBE: olog << " (maybe)"; break;
00502         }
00503         olog << std::endl;
00504       }
00505       START_TEST("Assignment (after posting)");
00506       {
00507         TestSpace* s = new TestSpace(arity,dom,step,this);
00508         TestSpace* sc = NULL;
00509         s->post();
00510         switch (Base::rand(3)) {
00511           case 0:
00512             if (opt.log)
00513               olog << ind(3) << "No copy" << std::endl;
00514             sc = s;
00515             s = NULL;
00516             break;
00517           case 1:
00518             if (opt.log)
00519               olog << ind(3) << "Unshared copy" << std::endl;
00520             if (s->status() != SS_FAILED) {
00521               sc = static_cast<TestSpace*>(s->clone(false));
00522             } else {
00523               sc = s; s = NULL;
00524             }
00525             break;
00526           case 2:
00527             if (opt.log)
00528               olog << ind(3) << "Shared copy" << std::endl;
00529             if (s->status() != SS_FAILED) {
00530               sc = static_cast<TestSpace*>(s->clone(true));
00531             } else {
00532               sc = s; s = NULL;
00533             }
00534             break;
00535           default: assert(false);
00536         }
00537         sc->assign(a,sol);
00538         if (sol == MT_TRUE) {
00539           CHECK_TEST(!sc->failed(), "Failed on solution");
00540           CHECK_TEST(subsumed(*sc), "No subsumption");
00541         } else if (sol == MT_FALSE) {
00542           CHECK_TEST(sc->failed(), "Solved on non-solution");
00543         }
00544         delete s; delete sc;
00545       }
00546       START_TEST("Partial assignment (after posting)");
00547       {
00548         TestSpace* s = new TestSpace(arity,dom,step,this);
00549         s->post();
00550         s->assign(a,sol,true);
00551         (void) s->failed();
00552         s->assign(a,sol);
00553         if (sol == MT_TRUE) {
00554           CHECK_TEST(!s->failed(), "Failed on solution");
00555           CHECK_TEST(subsumed(*s), "No subsumption");
00556         } else if (sol == MT_FALSE) {
00557           CHECK_TEST(s->failed(), "Solved on non-solution");
00558         }
00559         delete s;
00560       }
00561       START_TEST("Assignment (after posting, disable)");
00562       {
00563         TestSpace* s = new TestSpace(arity,dom,step,this);
00564         s->post();
00565         s->disable();
00566         s->enable();
00567         s->assign(a,sol);
00568         if (sol == MT_TRUE) {
00569           CHECK_TEST(!s->failed(), "Failed on solution");
00570           CHECK_TEST(subsumed(*s), "No subsumption");
00571         } else if (sol == MT_FALSE) {
00572           CHECK_TEST(s->failed(), "Solved on non-solution");
00573         }
00574         delete s;
00575       }
00576       START_TEST("Partial assignment (after posting, disable)");
00577       {
00578         TestSpace* s = new TestSpace(arity,dom,step,this);
00579         s->post();
00580         s->disable();
00581         s->enable();
00582         s->assign(a,sol,true);
00583         (void) s->failed();
00584         s->assign(a,sol);
00585         if (sol == MT_TRUE) {
00586           CHECK_TEST(!s->failed(), "Failed on solution");
00587           CHECK_TEST(subsumed(*s), "No subsumption");
00588         } else if (sol == MT_FALSE) {
00589           CHECK_TEST(s->failed(), "Solved on non-solution");
00590         }
00591         delete s;
00592       }
00593       START_TEST("Assignment (before posting)");
00594       {
00595         TestSpace* s = new TestSpace(arity,dom,step,this);
00596         s->assign(a,sol);
00597         s->post();
00598         if (sol == MT_TRUE) {
00599           CHECK_TEST(!s->failed(), "Failed on solution");
00600           CHECK_TEST(subsumed(*s), "No subsumption");
00601         } else if (sol == MT_FALSE) {
00602           CHECK_TEST(s->failed(), "Solved on non-solution");
00603         }
00604         delete s;
00605       }
00606       START_TEST("Partial assignment (before posting)");
00607       {
00608         TestSpace* s = new TestSpace(arity,dom,step,this);
00609         s->assign(a,sol,true);
00610         s->post();
00611         (void) s->failed();
00612         s->assign(a,sol);
00613         if (sol == MT_TRUE) {
00614           CHECK_TEST(!s->failed(), "Failed on solution");
00615           CHECK_TEST(subsumed(*s), "No subsumption");
00616         } else if (sol == MT_FALSE) {
00617           CHECK_TEST(s->failed(), "Solved on non-solution");
00618         }
00619         delete s;
00620       }
00621       START_TEST("Prune");
00622       {
00623         TestSpace* s = new TestSpace(arity,dom,step,this);
00624         s->post();
00625         while (!s->failed() && !s->assigned() && !s->matchAssignment(a))
00626           if (!s->prune(a,testfix)) {
00627             problem = "No fixpoint";
00628             delete s;
00629             goto failed;
00630           }
00631         s->assign(a,sol);
00632         if (sol == MT_TRUE) {
00633           CHECK_TEST(!s->failed(), "Failed on solution");
00634           CHECK_TEST(subsumed(*s), "No subsumption");
00635         } else if (sol == MT_FALSE) {
00636           CHECK_TEST(s->failed(), "Solved on non-solution");
00637         }
00638         delete s;
00639       }
00640       if (reified && !ignore(a) && (sol != MT_MAYBE)) {
00641         if (eqv()) {
00642           START_TEST("Assignment reified (rewrite after post, <=>)");
00643           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00644           s->post();
00645           s->rel(sol == MT_TRUE);
00646           s->assign(a,sol);
00647           CHECK_TEST(!s->failed(), "Failed");
00648           CHECK_TEST(subsumed(*s), "No subsumption");
00649           delete s;
00650         }
00651         if (imp()) {
00652           START_TEST("Assignment reified (rewrite after post, =>)");
00653           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00654           s->post();
00655           s->rel(sol == MT_TRUE);
00656           s->assign(a,sol);
00657           CHECK_TEST(!s->failed(), "Failed");
00658           CHECK_TEST(subsumed(*s), "No subsumption");
00659           delete s;
00660         }
00661         if (pmi()) {
00662           START_TEST("Assignment reified (rewrite after post, <=)");
00663           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00664           s->post();
00665           s->rel(sol == MT_TRUE);
00666           s->assign(a,sol);
00667           CHECK_TEST(!s->failed(), "Failed");
00668           CHECK_TEST(subsumed(*s), "No subsumption");
00669           delete s;
00670         }
00671         if (eqv()) {
00672           START_TEST("Assignment reified (immediate rewrite, <=>)");
00673           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00674           s->rel(sol == MT_TRUE);
00675           s->post();
00676           s->assign(a,sol);
00677           CHECK_TEST(!s->failed(), "Failed");
00678           CHECK_TEST(subsumed(*s), "No subsumption");
00679           delete s;
00680         }
00681         if (imp()) {
00682           START_TEST("Assignment reified (immediate rewrite, =>)");
00683           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00684           s->rel(sol == MT_TRUE);
00685           s->post();
00686           s->assign(a,sol);
00687           CHECK_TEST(!s->failed(), "Failed");
00688           CHECK_TEST(subsumed(*s), "No subsumption");
00689           delete s;
00690         }
00691         if (pmi()) {
00692           START_TEST("Assignment reified (immediate rewrite, <=)");
00693           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00694           s->rel(sol == MT_TRUE);
00695           s->post();
00696           s->assign(a,sol);
00697           CHECK_TEST(!s->failed(), "Failed");
00698           CHECK_TEST(subsumed(*s), "No subsumption");
00699           delete s;
00700         }
00701         if (eqv()) {
00702           START_TEST("Assignment reified (before posting, <=>)");
00703           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00704           s->assign(a,sol);
00705           s->post();
00706           CHECK_TEST(!s->failed(), "Failed");
00707           CHECK_TEST(subsumed(*s), "No subsumption");
00708           if (s->r.var().assigned()) {
00709             if (sol == MT_TRUE) {
00710               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00711             } else if (sol == MT_FALSE) {
00712               CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00713             }
00714           }
00715           delete s;
00716         }
00717         if (imp()) {
00718           START_TEST("Assignment reified (before posting, =>)");
00719           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00720           s->assign(a,sol);
00721           s->post();
00722           CHECK_TEST(!s->failed(), "Failed");
00723           CHECK_TEST(subsumed(*s), "No subsumption");
00724           if (sol == MT_TRUE) {
00725             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00726           } else if ((sol = MT_FALSE) && s->r.var().assigned()) {
00727             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00728           }
00729           delete s;
00730         }
00731         if (pmi()) {
00732           START_TEST("Assignment reified (before posting, <=)");
00733           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00734           s->assign(a,sol);
00735           s->post();
00736           CHECK_TEST(!s->failed(), "Failed");
00737           CHECK_TEST(subsumed(*s), "No subsumption");
00738           if (sol == MT_TRUE) {
00739             if (s->r.var().assigned()) {
00740               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00741             }
00742           } else if (sol == MT_FALSE) {
00743             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00744           }
00745           delete s;
00746         }
00747         if (eqv()) {
00748           START_TEST("Assignment reified (after posting, <=>)");
00749           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00750           s->post();
00751           s->assign(a,sol);
00752           CHECK_TEST(!s->failed(), "Failed");
00753           CHECK_TEST(subsumed(*s), "No subsumption");
00754           if (s->r.var().assigned()) {
00755             if (sol == MT_TRUE) {
00756               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00757             } else if (sol == MT_FALSE) {
00758               CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00759             }
00760           }
00761           delete s;
00762         }
00763         if (imp()) {
00764           START_TEST("Assignment reified (after posting, =>)");
00765           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00766           s->post();
00767           s->assign(a,sol);
00768           CHECK_TEST(!s->failed(), "Failed");
00769           CHECK_TEST(subsumed(*s), "No subsumption");
00770           if (sol == MT_TRUE) {
00771             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00772           } else if (s->r.var().assigned()) {
00773             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00774           }
00775           delete s;
00776         }
00777         if (pmi()) {
00778           START_TEST("Assignment reified (after posting, <=)");
00779           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00780           s->post();
00781           s->assign(a,sol);
00782           CHECK_TEST(!s->failed(), "Failed");
00783           CHECK_TEST(subsumed(*s), "No subsumption");
00784           if (sol == MT_TRUE) {
00785             if (s->r.var().assigned()) {
00786               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00787             }
00788           } else if (sol == MT_FALSE) {
00789             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00790           }
00791           delete s;
00792         }
00793         if (eqv()) {
00794           START_TEST("Prune reified, <=>");
00795           TestSpace* s = new TestSpace(arity,dom,step,this,RM_EQV);
00796           s->post();
00797           while (!s->failed() && !s->matchAssignment(a) &&
00798                  (!s->assigned() || !s->r.var().assigned()))
00799             if (!s->prune(a,testfix)) {
00800               problem = "No fixpoint";
00801               delete s;
00802               goto failed;
00803             }
00804           CHECK_TEST(!s->failed(), "Failed");
00805           CHECK_TEST(subsumed(*s), "No subsumption");
00806           if (s->r.var().assigned()) {
00807             if (sol == MT_TRUE) {
00808               CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00809             } else if (sol == MT_FALSE) {
00810               CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00811             }
00812           }
00813           delete s;
00814         }
00815         if (imp()) {
00816           START_TEST("Prune reified, =>");
00817           TestSpace* s = new TestSpace(arity,dom,step,this,RM_IMP);
00818           s->post();
00819           while (!s->failed() && !s->matchAssignment(a) &&
00820                  (!s->assigned() || ((sol == MT_FALSE) &&
00821                                      !s->r.var().assigned())))
00822             if (!s->prune(a,testfix)) {
00823               problem = "No fixpoint";
00824               delete s;
00825               goto failed;
00826             }
00827           CHECK_TEST(!s->failed(), "Failed");
00828           CHECK_TEST(subsumed(*s), "No subsumption");
00829           if (sol == MT_TRUE) {
00830             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00831           } else if ((sol == MT_FALSE) && s->r.var().assigned()) {
00832             CHECK_TEST(s->r.var().val()==0, "One on non-solution");
00833           }
00834           delete s;
00835         }
00836         if (pmi()) {
00837           START_TEST("Prune reified, <=");
00838           TestSpace* s = new TestSpace(arity,dom,step,this,RM_PMI);
00839           s->post();
00840           while (!s->failed() && !s->matchAssignment(a) &&
00841                  (!s->assigned() || ((sol == MT_TRUE) &&
00842                                      !s->r.var().assigned())))
00843             if (!s->prune(a,testfix)) {
00844               problem = "No fixpoint";
00845               delete s;
00846               goto failed;
00847             }
00848           CHECK_TEST(!s->failed(), "Failed");
00849           CHECK_TEST(subsumed(*s), "No subsumption");
00850           if ((sol == MT_TRUE) && s->r.var().assigned()) {
00851             CHECK_TEST(s->r.var().val()==1, "Zero on solution");
00852           } else if (sol == MT_FALSE) {
00853             CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
00854           }
00855           delete s;
00856         }
00857       }
00858 
00859       if (testsearch) {
00860         if (sol == MT_TRUE) {
00861           START_TEST("Search");
00862           if (!search_s->failed()) {
00863             TestSpace* ss = static_cast<TestSpace*>(search_s->clone(false));
00864             ss->dropUntil(a);
00865             delete e_s;
00866             e_s = new DFS<TestSpace>(ss,search_o);
00867             delete ss;
00868           }
00869           TestSpace* s = e_s->next();
00870           CHECK_TEST(s != NULL, "Solutions exhausted");
00871           CHECK_TEST(subsumed(*s), "No subsumption");
00872           for (int i=a.size(); i--; ) {
00873             CHECK_TEST(s->x[i].assigned(), "Unassigned variable");
00874             CHECK_TEST(Gecode::Float::overlap(a[i], s->x[i].val()), "Wrong value in solution");
00875           }
00876           delete s;
00877         }
00878       }
00879 
00880       ++a;
00881     }
00882 
00883     if (testsearch) {
00884       test = "Search";
00885       if (!search_s->failed()) {
00886         TestSpace* ss = static_cast<TestSpace*>(search_s->clone(false));
00887         ss->dropUntil(a);
00888         delete e_s;
00889         e_s = new DFS<TestSpace>(ss,search_o);
00890         delete ss;
00891       }
00892       if (e_s->next() != NULL) {
00893         problem = "Excess solutions";
00894         goto failed;
00895       }
00896     }
00897 
00898     delete ap;
00899     delete search_s;
00900     delete e_s;
00901     return true;
00902 
00903   failed:
00904     if (opt.log)
00905       olog << "FAILURE" << std::endl
00906            << ind(1) << "Test:       " << test << std::endl
00907            << ind(1) << "Problem:    " << problem << std::endl;
00908     if (a() && opt.log)
00909       olog << ind(1) << "Assignment: " << a << std::endl;
00910     delete ap;
00911     delete search_s;
00912     delete e_s;
00913 
00914     return false;
00915   }
00916 
00917 }}
00918 
00919 #undef START_TEST
00920 #undef CHECK_TEST
00921 
00922 // STATISTICS: test-float