Generated on Mon Aug 25 11:35:34 2008 for Gecode by doxygen 1.5.6

cpltset.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Guido Tack <tack@gecode.org>
00004  *     Christian Schulte <schulte@gecode.org>
00005  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Guido Tack, 2005
00009  *     Christian Schulte, 2005
00010  *     Mikael Lagerkvist, 2005
00011  *
00012  *  Last modified:
00013  *     $Date: 2008-02-13 18:45:15 +0100 (Wed, 13 Feb 2008) $ by $Author: nikopp $
00014  *     $Revision: 6155 $
00015  *
00016  *  This file is part of Gecode, the generic constraint
00017  *  development environment:
00018  *     http://www.gecode.org
00019  *
00020  *  Permission is hereby granted, free of charge, to any person obtaining
00021  *  a copy of this software and associated documentation files (the
00022  *  "Software"), to deal in the Software without restriction, including
00023  *  without limitation the rights to use, copy, modify, merge, publish,
00024  *  distribute, sublicense, and/or sell copies of the Software, and to
00025  *  permit persons to whom the Software is furnished to do so, subject to
00026  *  the following conditions:
00027  *
00028  *  The above copyright notice and this permission notice shall be
00029  *  included in all copies or substantial portions of the Software.
00030  *
00031  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00032  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00033  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00034  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00035  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00036  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00037  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00038  *
00039  */
00040 
00041 #include "test/cpltset.hh"
00042 
00043 #include "gecode/int.hh"
00044 #include "gecode/iter.hh"
00045 #include <algorithm>
00046 
00048 #define CHECK_TEST(T,M)                                         \
00049 if (opt.log)                                                    \
00050   olog << ind(3) << "Check: " << (M) << std::endl;              \
00051 if (!(T)) {                                                     \
00052   problem = (M); delete s; goto failed;                         \
00053 }
00054 
00056 #define START_TEST(T)                                           \
00057   if (opt.log) {                                                \
00058      olog.str("");                                              \
00059      olog << ind(2) << "Testing: " << (T) << std::endl;         \
00060   }                                                             \
00061   test = (T);
00062 
00063 namespace Test { namespace CpltSet {
00064 
00066   class CpltSetTestSpace : public Gecode::Space {
00067   public:
00069     Gecode::CpltSetVarArray x;
00071     Gecode::IntVarArray y;
00073     int withInt;
00075     Gecode::BoolVar b;
00077     bool reified;
00079     CpltSetTest* test;
00081     const Options opt;
00082 
00083   public:
00093     CpltSetTestSpace(int n, Gecode::IntSet& d, int i, bool r, CpltSetTest* t,
00094                      const Options& o, bool log=true)
00095       : x(this, n, Gecode::IntSet::empty, d), y(this, i, d), withInt(i),
00096         b(this, 0, 1), reified(r), test(t), opt(o) {
00097       if (opt.log && log) {
00098         olog << ind(2) << "Initial: x[]=" << x;
00099         olog << " y[]=" << y;
00100         if (reified)
00101           olog << " b=" << b;
00102         olog << std::endl;
00103       }
00104     }
00105 
00107     CpltSetTestSpace(bool share, CpltSetTestSpace& s) 
00108       : Space(share,s), withInt(s.withInt), reified(s.reified), test(s.test), 
00109         opt(s.opt) {
00110       x.update(this, share, s.x);
00111       y.update(this, share, s.y);
00112       b.update(this, share, s.b);
00113     }
00114   
00116     virtual Space* copy(bool share) {
00117       return new CpltSetTestSpace(share,*this);
00118     }
00119 
00121     void post(void) {
00122       if (reified){
00123         test->post(this,x,y,b);
00124         if (opt.log)
00125           olog << ind(3) << "Posting reified propagator" << std::endl;
00126       } else {
00127         test->post(this,x,y);
00128         if (opt.log)
00129           olog << ind(3) << "Posting propagator" << std::endl;
00130       }
00131     }
00133     bool failed(void) {
00134       if (opt.log) {
00135         olog << ind(3) << "Fixpoint: x[]=" << x
00136              << " y[]=" << y << std::endl;
00137         bool f=(status() == Gecode::SS_FAILED);
00138         olog << ind(3) << "     -->  x[]=" << x 
00139              << " y[]=" << y << std::endl;
00140         return f;
00141       } else {
00142         return status() == Gecode::SS_FAILED;
00143       }
00144     }
00145 
00147     void rel(int i, Gecode::SetRelType srt, const Gecode::IntSet& is) {
00148       if (opt.log) {
00149         olog << ind(4) << "x[" << i << "] ";
00150         switch (srt) {
00151         case Gecode::SRT_EQ: olog << "="; break;
00152         case Gecode::SRT_NQ: olog << "!="; break;
00153         case Gecode::SRT_SUB: olog << "<="; break;
00154         case Gecode::SRT_SUP: olog << ">="; break;
00155         case Gecode::SRT_DISJ: olog << "||"; break;
00156         case Gecode::SRT_CMPL: olog << "^-1 = "; break;
00157         }
00158         olog << is << std::endl;
00159       }
00160       Gecode::dom(this, x[i], srt, is);
00161     }
00163     void cardinality(int i, int cmin, int cmax) {
00164       if (opt.log) {
00165         olog << ind(4) << cmin << " <= #(x[" << i << "]) <= " << cmax
00166              << std::endl;
00167       }
00168       Gecode::cardinality(this, x[i], cmin, cmax);
00169     }
00171     void rel(int i, Gecode::IntRelType irt, int n) {
00172       if (opt.log) {
00173         olog << ind(4) << "y[" << i << "] ";
00174         switch (irt) {
00175         case Gecode::IRT_EQ: olog << "="; break;
00176         case Gecode::IRT_NQ: olog << "!="; break;
00177         case Gecode::IRT_LQ: olog << "<="; break;
00178         case Gecode::IRT_LE: olog << "<"; break;
00179         case Gecode::IRT_GQ: olog << ">="; break;
00180         case Gecode::IRT_GR: olog << ">"; break;
00181         }
00182         olog << " " << n << std::endl;
00183       }
00184       Gecode::rel(this, y[i], irt, n);
00185     }
00187     void rel(bool sol) {
00188       int n = sol ? 1 : 0;
00189       assert(reified);
00190       if (opt.log) 
00191         olog << ind(4) << "b = " << n << std::endl;
00192       Gecode::rel(this, b, Gecode::IRT_EQ, n);
00193     }
00194 
00196     void assign(const Test::Set::SetAssignment& a) {
00197       for (int i=a.size(); i--; ) {
00198         Test::Set::CountableSetRanges csv(a.lub, a[i]);
00199         Gecode::IntSet ai(csv);
00200         rel(i, Gecode::SRT_EQ, ai);
00201         if (Base::fixpoint() && failed())
00202           return;
00203       }
00204       for (int i=withInt; i--; ) {
00205         rel(i, Gecode::IRT_EQ, a.ints()[i]);
00206         if (Base::fixpoint() && failed())
00207           return;
00208       }
00209     }
00210 
00212     bool assigned(void) const {
00213       for (int i=x.size(); i--; )
00214         if (!x[i].assigned())
00215           return false;
00216       for (int i=y.size(); i--; )
00217         if (!y[i].assigned())
00218           return false;
00219       return true;
00220     }
00221 
00222     void removeFromLub(int v, int i, const Test::Set::SetAssignment& a) {
00223       Gecode::CpltSetVarUnknownRanges ur(x[i]);
00224       Test::Set::CountableSetRanges air(a.lub, a[i]);
00225       Gecode::Iter::Ranges::Diff<Gecode::CpltSetVarUnknownRanges, 
00226         Test::Set::CountableSetRanges> diff(ur, air);
00227       Gecode::Iter::Ranges::ToValues<Gecode::Iter::Ranges::Diff
00228         <Gecode::CpltSetVarUnknownRanges, Test::Set::CountableSetRanges> > 
00229           diffV(diff);
00230       for (int j=0; j<v; j++, ++diffV);
00231       rel(i, Gecode::SRT_DISJ, Gecode::IntSet(diffV.val(), diffV.val()));
00232     }
00233 
00234     void addToGlb(int v, int i, const Test::Set::SetAssignment& a) {
00235       Gecode::CpltSetVarUnknownRanges ur(x[i]);
00236       Test::Set::CountableSetRanges air(a.lub, a[i]);
00237       Gecode::Iter::Ranges::Inter<Gecode::CpltSetVarUnknownRanges, 
00238         Test::Set::CountableSetRanges> inter(ur, air);
00239       Gecode::Iter::Ranges::ToValues<Gecode::Iter::Ranges::Inter
00240         <Gecode::CpltSetVarUnknownRanges, Test::Set::CountableSetRanges> > 
00241           interV(inter);
00242       for (int j=0; j<v; j++, ++interV);
00243       rel(i, Gecode::SRT_SUP, Gecode::IntSet(interV.val(), interV.val()));
00244     }
00245 
00246     bool fixprob(void) {
00247       if (failed())
00248         return true;
00249       CpltSetTestSpace* c = static_cast<CpltSetTestSpace*>(clone());
00250       if (opt.log)
00251         olog << ind(3) << "Testing fixpoint on copy" << std::endl;
00252       c->post();
00253       if (c->failed()) {
00254         delete c; return false;
00255       }
00256 
00257       for (int i=x.size(); i--; )
00258         if (Gecode::CpltSet::CpltSetView(x[i]).dom() != 
00259             Gecode::CpltSet::CpltSetView(c->x[i]).dom()) {
00260           delete c;
00261           return false;
00262         }
00263       for (int i=y.size(); i--; )
00264         if (y[i].size() != c->y[i].size()) {
00265           delete c; return false;
00266         }
00267       if (reified && (b.size() != c->b.size())) {
00268         delete c; return false;
00269       }
00270       if (opt.log)
00271         olog << ind(3) << "Finished testing fixpoint on copy" << std::endl;
00272       delete c;
00273       return true;
00274     }
00275 
00276     bool prune(const Test::Set::SetAssignment& a) {
00277       bool setsAssigned = true;
00278       for (int j=x.size(); j--; )
00279         if (!x[j].assigned()) {
00280           setsAssigned = false;
00281           break;
00282         }
00283       bool intsAssigned = true;
00284       for (int j=y.size(); j--; )
00285         if (!y[j].assigned()) {
00286           intsAssigned = false;
00287           break;
00288         }
00289 
00290       // Select variable to be pruned
00291       int i;
00292       if (intsAssigned) {
00293         i = Base::rand(x.size());
00294       } else if (setsAssigned) {
00295         i = Base::rand(y.size());
00296       } else {
00297         i = Base::rand(x.size()+y.size());
00298       }
00299 
00300       if (setsAssigned || i>=x.size()) {
00301         if (i>=x.size())
00302           i = i-x.size();
00303         while (y[i].assigned()) {
00304           i = (i+1) % y.size();
00305         }
00306         // Prune int var
00307 
00308         // Select mode for pruning
00309         switch (Base::rand(3)) {
00310         case 0:
00311           if (a.ints()[i] < y[i].max()) {
00312             int v=a.ints()[i]+1+
00313               Base::rand(static_cast<unsigned int>(y[i].max()-a.ints()[i]));
00314             assert((v > a.ints()[i]) && (v <= y[i].max()));
00315             rel(i, Gecode::IRT_LE, v);
00316           }
00317           break;
00318         case 1:
00319           if (a.ints()[i] > y[i].min()) {
00320             int v=y[i].min()+
00321               Base::rand(static_cast<unsigned int>(a.ints()[i]-y[i].min()));
00322             assert((v < a.ints()[i]) && (v >= y[i].min()));
00323             rel(i, Gecode::IRT_GR, v);
00324           }
00325           break;
00326         default:
00327           int v;
00328           Gecode::Int::ViewRanges<Gecode::Int::IntView> it(y[i]);
00329           unsigned int skip = Base::rand(y[i].size()-1);
00330           while (true) {
00331             if (it.width() > skip) {
00332               v = it.min() + skip;
00333               if (v == a.ints()[i]) {
00334                 if (it.width() == 1) {
00335                   ++it; v = it.min();
00336                 } else if (v < it.max()) {
00337                   ++v;
00338                 } else {
00339                   --v;
00340                 }
00341               }
00342               break;
00343             }
00344             skip -= it.width();
00345             ++it;
00346           }
00347           rel(i, Gecode::IRT_NQ, v);
00348         }
00349         return (!Base::fixpoint() || fixprob());
00350       }
00351       while (x[i].assigned()) {
00352         i = (i+1) % x.size();
00353       }
00354       Gecode::CpltSetVarUnknownRanges ur1(x[i]);
00355       Test::Set::CountableSetRanges air1(a.lub, a[i]);
00356       Gecode::Iter::Ranges::Diff<Gecode::CpltSetVarUnknownRanges, 
00357         Test::Set::CountableSetRanges> diff(ur1, air1);
00358       Gecode::CpltSetVarUnknownRanges ur2(x[i]);
00359       Test::Set::CountableSetRanges air2(a.lub, a[i]);
00360       Gecode::Iter::Ranges::Inter<Gecode::CpltSetVarUnknownRanges, 
00361         Test::Set::CountableSetRanges> inter(ur2, air2);
00362 
00363       Test::Set::CountableSetRanges aisizer(a.lub, a[i]);
00364       unsigned int aisize = Gecode::Iter::Ranges::size(aisizer);
00365 
00366       // Select mode for pruning
00367       switch (Base::rand(5)) {
00368       case 0:
00369         if (inter()) {
00370           int v = Base::rand(Gecode::Iter::Ranges::size(inter));
00371           addToGlb(v, i, a);
00372         }
00373         break;
00374       case 1:
00375         if (diff()) {
00376           int v = Base::rand(Gecode::Iter::Ranges::size(diff));
00377           removeFromLub(v, i, a);
00378         }
00379         break;
00380       case 2:
00381         if (x[i].cardMin() < aisize) {
00382           unsigned int newc = x[i].cardMin() + 1 +
00383             Base::rand(aisize - x[i].cardMin());
00384           assert( newc > x[i].cardMin() );
00385           assert( newc <= aisize );
00386           cardinality(i, newc, Gecode::Set::Limits::card);
00387         }
00388         break;
00389       case 3:
00390         if (x[i].cardMax() > aisize) {
00391           unsigned int newc = x[i].cardMax() - 1 -
00392             Base::rand(x[i].cardMax() - aisize);
00393           assert( newc < x[i].cardMax() );
00394           assert( newc >= aisize );
00395           cardinality(i, 0, newc);
00396         }
00397         break;
00398       default:
00399         if (inter()) {
00400           int v = Base::rand(Gecode::Iter::Ranges::size(inter));
00401           addToGlb(v, i, a);
00402         } else {
00403           int v = Base::rand(Gecode::Iter::Ranges::size(diff));
00404           removeFromLub(v, i, a);
00405         }      
00406       }
00407       return (!Base::fixpoint() || fixprob());
00408     }
00409   };
00410 
00411   bool 
00412   CpltSetTest::run(void) {
00413     const char* test    = "NONE";
00414     const char* problem = "NONE";
00415 
00416     Test::Set::SetAssignment* ap =
00417       new Test::Set::SetAssignment(arity,lub,withInt);
00418     Test::Set::SetAssignment& a = *ap;
00419 
00420     int an = 0;
00421   
00422     while (a()) {
00423       bool is_sol = solution(a);
00424       if (opt.log)
00425         olog << ind(1) << "Assignment: " << a 
00426              << (is_sol ? " (solution)" : " (no solution)")
00427              << std::endl;
00428     
00429       START_TEST("Assignment (after posting)");
00430       {
00431         Gecode::CpltSet::manager.dispose();
00432         Gecode::CpltSet::manager.init(10000,10000);
00433         CpltSetTestSpace* s =
00434           new CpltSetTestSpace(arity,lub,withInt,false,this,opt);
00435         s->post();
00436         s->assign(a);
00437         if (is_sol) {
00438           CHECK_TEST(!s->failed(), "Failed on solution");
00439           CHECK_TEST(s->propagators()==0, "No subsumption");
00440         } else {
00441           CHECK_TEST(s->failed(), "Solved on non-solution");
00442         }
00443         delete s;
00444       }
00445     
00446       START_TEST("Assignment (before posting)");
00447       {
00448         Gecode::CpltSet::manager.dispose();
00449         Gecode::CpltSet::manager.init(10000,10000);
00450         CpltSetTestSpace* s =
00451           new CpltSetTestSpace(arity,lub,withInt,false,this,opt);
00452         s->assign(a);
00453         s->post();
00454         if (is_sol) {
00455           CHECK_TEST(!s->failed(), "Failed on solution");
00456           CHECK_TEST(s->propagators()==0, "No subsumption");
00457         } else {
00458           CHECK_TEST(s->failed(), "Solved on non-solution");
00459         }
00460         delete s;
00461       }
00462     
00463       if (reified) {
00464         START_TEST("Assignment reified (before posting)");
00465         Gecode::CpltSet::manager.dispose();
00466         Gecode::CpltSet::manager.init(10000,10000);
00467         CpltSetTestSpace* s =
00468           new CpltSetTestSpace(arity,lub,withInt,true,this,opt);
00469         s->assign(a);
00470         s->post();
00471         CHECK_TEST(!s->failed(), "Failed");
00472         CHECK_TEST(s->propagators()==0, "No subsumption");
00473         CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00474         if (is_sol) {
00475           CHECK_TEST(s->b.val()==1, "Zero on solution");
00476         } else {
00477           CHECK_TEST(s->b.val()==0, "One on non-solution");
00478         }
00479         delete s;
00480       }
00481     
00482       if (reified) {
00483         START_TEST("Assignment reified (after posting)");
00484         Gecode::CpltSet::manager.dispose();
00485         Gecode::CpltSet::manager.init(10000,10000);
00486         CpltSetTestSpace* s =
00487           new CpltSetTestSpace(arity,lub,withInt,true,this,opt);
00488         s->post();
00489         s->assign(a);
00490         CHECK_TEST(!s->failed(), "Failed");
00491         CHECK_TEST(s->propagators()==0, "No subsumption");
00492         CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00493         if (is_sol) {
00494           CHECK_TEST(s->b.val()==1, "Zero on solution");
00495         } else {
00496           CHECK_TEST(s->b.val()==0, "One on non-solution");
00497         }
00498         delete s;
00499       }
00500     
00501       START_TEST("Prune");
00502       {
00503         Gecode::CpltSet::manager.dispose();
00504         Gecode::CpltSet::manager.init(10000,10000);
00505         CpltSetTestSpace* s =
00506           new CpltSetTestSpace(arity,lub,withInt,false,this,opt);
00507         s->post();
00508         while (!s->failed() && !s->assigned())
00509            if (!s->prune(a)) {
00510              problem = "No fixpoint";
00511              delete s;
00512              goto failed;
00513            }
00514         s->assign(a);
00515         if (is_sol) {
00516           CHECK_TEST(!s->failed(), "Failed on solution");
00517           CHECK_TEST(s->propagators()==0, "No subsumption");
00518         } else {
00519           CHECK_TEST(s->failed(), "Solved on non-solution");
00520         }
00521         delete s;
00522       }
00523     
00524       if (reified) {
00525         START_TEST("Prune reified");
00526         Gecode::CpltSet::manager.dispose();
00527         Gecode::CpltSet::manager.init(10000,10000);
00528         CpltSetTestSpace* s =
00529           new CpltSetTestSpace(arity,lub,withInt,true,this,opt);
00530         s->post();
00531         while (!s->assigned() && !s->b.assigned())
00532            if (!s->prune(a)) {
00533              problem = "No fixpoint";
00534              delete s;
00535              goto failed;
00536            }
00537         CHECK_TEST(!s->failed(), "Failed");
00538         CHECK_TEST(s->propagators()==0, "No subsumption");
00539         CHECK_TEST(s->b.assigned(), "Control variable unassigned");
00540         if (is_sol) {
00541           CHECK_TEST(s->b.val()==1, "Zero on solution");
00542         } else {
00543           CHECK_TEST(s->b.val()==0, "One on non-solution");
00544         }
00545         delete s;
00546       }
00547 
00548       ++an;
00549       ++a;
00550     }
00551 
00552     delete ap;
00553     return true;
00554    failed:
00555     if (opt.log)
00556       olog << "FAILURE" << std::endl
00557            << ind(1) << "Test:       " << test << std::endl
00558            << ind(1) << "Problem:    " << problem << std::endl;
00559     if (a() && opt.log)
00560       olog << ind(1) << "Assignment: " << a << std::endl;
00561     delete ap;
00562 
00563     return false;
00564   }
00565 
00566 }}
00567 
00568 // STATISTICS: test-cpltset