Generated on Tue Apr 18 10:21:55 2017 for Gecode by doxygen 1.6.3

ldsb.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christopher Mears <chris.mears@monash.edu>
00005  *
00006  *  Copyright:
00007  *     Christopher Mears, 2012
00008  *
00009  *  Last modified:
00010  *     $Date: 2017-02-22 04:53:03 +0100 (Wed, 22 Feb 2017) $ by $Author: schulte $
00011  *     $Revision: 15469 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/kernel.hh>
00039 #include <gecode/int.hh>
00040 #include <gecode/int/branch.hh>
00041 
00042 #ifdef GECODE_HAS_SET_VARS
00043 #include <gecode/set.hh>
00044 #include <gecode/set/branch.hh>
00045 #endif
00046 
00047 #include <gecode/minimodel.hh>
00048 
00049 #include "test/test.hh"
00050 
00051 #include <vector>
00052 
00057 namespace Test { namespace LDSB {
00058 
00059   using namespace Gecode;
00060 
00063   bool
00064   equal(const IntArgs& a, const IntArgs& b) {
00065     if (a.size() != b.size()) return false;
00066     for (int i = 0 ; i < a.size() ; ++i)
00067       if (a[i] != b[i])
00068         return false;
00069     return true;
00070   }
00071 
00072 #ifdef GECODE_HAS_SET_VARS
00073 
00074 
00075   bool
00076   equal(const IntSetArgs& a, const IntSetArgs& b) {
00077     if (a.size() != b.size()) return false;
00078     for (int i = 0 ; i < a.size() ; ++i) {
00079       // Compare the two sets a[i] and b[i].
00080       // Perhaps TODO: use Iter::Ranges::equal instead.
00081       if (a[i].size() != b[i].size()) return false;
00082       IntSetValues x(a[i]);
00083       IntSetValues y(b[i]);
00084       while (x() && y()) {
00085         if (x.val() != y.val()) return false;
00086         ++x;
00087         ++y;
00088       }
00089     }
00090     return true;
00091   }
00092 #endif
00093 
00103   template <class T, class VarArgsType>
00104   bool
00105   check(DFS<T>& e, std::vector<VarArgsType> expected) {
00106     int nexpected = expected.size();
00107     for (int i = 0 ; i < nexpected ; ++i) {
00108       T* s = e.next();
00109       if (s == NULL) {
00110         if (opt.log) {
00111           olog << "Expected a solution but there are no more solutions." << std::endl;
00112           olog << "(Expected " << nexpected << " but only found " << i << ")" << std::endl;
00113           olog << "Expected: " << expected[i] << std::endl;
00114         }
00115         return false;
00116       }
00117       if (!equal(s->solution(), expected[i])) {
00118         if (opt.log) {
00119           olog << "Solution does not match expected." << std::endl;
00120           olog << "Solution: " << s->solution() << std::endl;
00121           olog << "Expected: " << expected[i] << std::endl;
00122         }
00123         return false;
00124       }
00125       delete s;
00126     }
00127     T* s = e.next();
00128     if (s != NULL) {
00129       if (opt.log) {
00130         olog << "More solutions than expected:" << std::endl;
00131         olog << "(Expected only " << nexpected << ")" << std::endl;
00132         olog << s->solution() << std::endl;
00133       }
00134       return false;
00135     }
00136 
00137     // Nothing went wrong.
00138     return true;
00139   }
00140 
00141 
00143   class OneArray : public Space {
00144   public:
00146     IntVarArray xs;
00148     OneArray(int n, int l, int u) : xs(*this,n,l,u) {
00149     }
00151     OneArray(bool share, OneArray& s) : Space(share,s) {
00152       xs.update(*this,share,s.xs);
00153     }
00155     virtual Space* copy(bool share) {
00156       return new OneArray(share,*this);
00157     }
00159     IntArgs solution(void) {
00160       IntArgs a(xs.size());
00161       for (int i = 0 ; i < a.size() ; ++i)
00162         a[i] = xs[i].val();
00163       return a;
00164     }
00166     virtual IntArgs* expectedSolutions(void) { return NULL; }
00167   };
00168 
00169 #ifdef GECODE_HAS_SET_VARS
00170 
00171   class OneArraySet : public Space {
00172   public:
00174     SetVarArray xs;
00176     OneArraySet(int n, int l, int u) : xs(*this,n, IntSet::empty, l,u) {
00177     }
00179     OneArraySet(bool share, OneArraySet& s) : Space(share,s) {
00180       xs.update(*this,share,s.xs);
00181     }
00183     virtual Space* copy(bool share) {
00184       return new OneArraySet(share,*this);
00185     }
00187     IntSetArgs solution(void) {
00188       IntSetArgs a(xs.size());
00189       for (int i = 0 ; i < a.size() ; ++i) {
00190         SetVarGlbRanges glbranges(xs[i]);
00191         a[i] = IntSet(glbranges);
00192       }
00193       return a;
00194     }
00196     virtual IntSetArgs* expectedSolutions(void) { return NULL; }
00197   };
00198 #endif
00199 
00201   template <class T>
00202   class LDSB : public Base {
00203   public:
00205     unsigned int c_d;
00207     unsigned int a_d;
00209     LDSB(std::string label, unsigned int c=0, unsigned int a=0)
00210       : Test::Base("LDSB::" + label),
00211         c_d(c), a_d(a) {}
00213     bool run(void) {
00214       OneArray *s = new OneArray(T::n, T::l, T::u);
00215       T::setup(*s, s->xs);
00216       Search::Options o = Search::Options::def;
00217       if (c_d != 0) o.c_d = c_d;
00218       if (a_d != 0) o.a_d = a_d;
00219       DFS<OneArray> e(s,o);
00220       bool r = check(e, T::expectedSolutions());
00221       delete s;
00222       return r;
00223     }
00224   };
00225 
00226 #ifdef GECODE_HAS_SET_VARS
00227 
00228   template <class T>
00229   class LDSBSet : public Base {
00230   public:
00232     unsigned int c_d;
00234     unsigned int a_d;
00236     LDSBSet(std::string label, unsigned int c=0, unsigned int a=0)
00237       : Test::Base("LDSB::" + label),
00238         c_d(c), a_d(a) {}
00240     bool run(void) {
00241       OneArraySet *s = new OneArraySet(T::n, T::l, T::u);
00242       T::setup(*s, s->xs);
00243       Search::Options o = Search::Options::def;
00244       if (c_d != 0) o.c_d = c_d;
00245       if (a_d != 0) o.a_d = a_d;
00246       DFS<OneArraySet> e(s,o);
00247       bool r = check(e, T::expectedSolutions());
00248       delete s;
00249       return r;
00250     }
00251   };
00252 #endif
00253 
00254   // Test cases
00255 
00257   class VarSym1 {
00258   public:
00260     static const int n = 4;
00262     static const int l = 0;
00264     static const int u = 3;
00266     static void setup(Home home, IntVarArray& xs) {
00267       Symmetries syms;
00268       IntArgs indices(4, 0,1,2,3);
00269       syms << VariableSymmetry(xs, indices);
00270       distinct(home, xs);
00271       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
00272     }
00274     static std::vector<IntArgs> expectedSolutions(void) {
00275       static std::vector<IntArgs> expected;
00276       expected.clear();
00277       expected.push_back(IntArgs(4, 0,1,2,3));
00278       return expected;
00279     }
00280   };
00281 
00283   class VarSym1b {
00284   public:
00286     static const int n = 4;
00288     static const int l = 0;
00290     static const int u = 3;
00292     static void setup(Home home, IntVarArray& xs) {
00293       distinct(home, xs);
00294       Symmetries syms;
00295       syms << VariableSymmetry(xs);
00296       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
00297     }
00299     static std::vector<IntArgs> expectedSolutions(void) {
00300       static std::vector<IntArgs> expected;
00301       expected.clear();
00302       expected.push_back(IntArgs(4, 0,1,2,3));
00303       return expected;
00304     }
00305   };
00306 
00308   class VarSym2 {
00309   public:
00311     static const int n = 4;
00313     static const int l = 0;
00315     static const int u = 3;
00317     static void setup(Home home, IntVarArray& xs) {
00318       Symmetries syms;
00319       IntArgs indices(4, 0,1,2,3);
00320       syms << VariableSymmetry(xs);
00321       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
00322     }
00324     static std::vector<IntArgs> expectedSolutions(void) {
00325       static std::vector<IntArgs> expected;
00326       expected.clear();
00327       expected.push_back(IntArgs(4, 0,0,0,0));
00328       expected.push_back(IntArgs(4, 0,0,0,1));
00329       expected.push_back(IntArgs(4, 0,0,0,2));
00330       expected.push_back(IntArgs(4, 0,0,0,3));
00331       expected.push_back(IntArgs(4, 0,0,1,1));
00332       expected.push_back(IntArgs(4, 0,0,1,2));
00333       expected.push_back(IntArgs(4, 0,0,1,3));
00334       expected.push_back(IntArgs(4, 0,0,2,2));
00335       expected.push_back(IntArgs(4, 0,0,2,3));
00336       expected.push_back(IntArgs(4, 0,0,3,3));
00337       expected.push_back(IntArgs(4, 0,1,1,1));
00338       expected.push_back(IntArgs(4, 0,1,1,2));
00339       expected.push_back(IntArgs(4, 0,1,1,3));
00340       expected.push_back(IntArgs(4, 0,1,2,2));
00341       expected.push_back(IntArgs(4, 0,1,2,3));
00342       expected.push_back(IntArgs(4, 0,1,3,3));
00343       expected.push_back(IntArgs(4, 0,2,2,2));
00344       expected.push_back(IntArgs(4, 0,2,2,3));
00345       expected.push_back(IntArgs(4, 0,2,3,3));
00346       expected.push_back(IntArgs(4, 0,3,3,3));
00347       expected.push_back(IntArgs(4, 1,1,1,1));
00348       expected.push_back(IntArgs(4, 1,1,1,2));
00349       expected.push_back(IntArgs(4, 1,1,1,3));
00350       expected.push_back(IntArgs(4, 1,1,2,2));
00351       expected.push_back(IntArgs(4, 1,1,2,3));
00352       expected.push_back(IntArgs(4, 1,1,3,3));
00353       expected.push_back(IntArgs(4, 1,2,2,2));
00354       expected.push_back(IntArgs(4, 1,2,2,3));
00355       expected.push_back(IntArgs(4, 1,2,3,3));
00356       expected.push_back(IntArgs(4, 1,3,3,3));
00357       expected.push_back(IntArgs(4, 2,2,2,2));
00358       expected.push_back(IntArgs(4, 2,2,2,3));
00359       expected.push_back(IntArgs(4, 2,2,3,3));
00360       expected.push_back(IntArgs(4, 2,3,3,3));
00361       expected.push_back(IntArgs(4, 3,3,3,3));
00362       return expected;
00363     }
00364   };
00365 
00367   class VarSym3 {
00368   public:
00370     static const int n = 4;
00372     static const int l = 0;
00374     static const int u = 3;
00376     static void setup(Home home, IntVarArray& xs) {
00377       Symmetries syms;
00378       distinct(home, xs);
00379       syms << VariableSymmetry(IntVarArgs() << xs[0] << xs[1]);
00380       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
00381     }
00383     static std::vector<IntArgs> expectedSolutions(void) {
00384       static std::vector<IntArgs> expected;
00385       expected.clear();
00386       expected.push_back(IntArgs(4, 0,1,2,3));
00387       expected.push_back(IntArgs(4, 0,1,3,2));
00388       expected.push_back(IntArgs(4, 0,2,1,3));
00389       expected.push_back(IntArgs(4, 0,2,3,1));
00390       expected.push_back(IntArgs(4, 0,3,1,2));
00391       expected.push_back(IntArgs(4, 0,3,2,1));
00392       expected.push_back(IntArgs(4, 1,2,0,3));
00393       expected.push_back(IntArgs(4, 1,2,3,0));
00394       expected.push_back(IntArgs(4, 1,3,0,2));
00395       expected.push_back(IntArgs(4, 1,3,2,0));
00396       expected.push_back(IntArgs(4, 2,3,0,1));
00397       expected.push_back(IntArgs(4, 2,3,1,0));
00398       return expected;
00399     }
00400   };
00401 
00403   class VarSym4 {
00404   public:
00406     static const int n = 3;
00408     static const int l = 0;
00410     static const int u = 2;
00412     static void setup(Home home, IntVarArray& xs) {
00413       distinct(home, xs);
00414       Symmetries s;
00415       IntVarArgs symvars;
00416       symvars << xs[0];
00417       s << VariableSymmetry(symvars);
00418       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00419     }
00421     static std::vector<IntArgs> expectedSolutions(void) {
00422       static std::vector<IntArgs> expected;
00423       expected.clear();
00424       expected.push_back(IntArgs(3, 0,1,2));
00425       expected.push_back(IntArgs(3, 0,2,1));
00426       expected.push_back(IntArgs(3, 1,0,2));
00427       expected.push_back(IntArgs(3, 1,2,0));
00428       expected.push_back(IntArgs(3, 2,0,1));
00429       expected.push_back(IntArgs(3, 2,1,0));
00430       return expected;
00431     }
00432   };
00433 
00435   class VarSym5 {
00436   public:
00438     static const int n = 4;
00440     static const int l = 0;
00442     static const int u = 3;
00444     static void setup(Home home, IntVarArray& xs) {
00445       distinct(home, xs);
00446       Matrix<IntVarArray> m(xs, 4, 1);
00447       Symmetries s;
00448       s << VariableSymmetry(m.slice(0,2, 0,1));
00449       s << VariableSymmetry(m.slice(2,4, 0,1));
00450       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00451     }
00453     static std::vector<IntArgs> expectedSolutions(void) {
00454       static std::vector<IntArgs> expected;
00455       expected.clear();
00456       expected.push_back(IntArgs(4, 0,1,2,3));
00457       expected.push_back(IntArgs(4, 0,2,1,3));
00458       expected.push_back(IntArgs(4, 0,3,1,2));
00459       expected.push_back(IntArgs(4, 1,2,0,3));
00460       expected.push_back(IntArgs(4, 1,3,0,2));
00461       expected.push_back(IntArgs(4, 2,3,0,1));
00462       return expected;
00463     }
00464   };
00465 
00467   class MatSym1 {
00468   public:
00470     static const int n = 6;
00472     static const int l = 0;
00474     static const int u = 1;
00476     static void setup(Home home, IntVarArray& xs) {
00477       Matrix<IntVarArray> m(xs, 2, 3);
00478       Symmetries s;
00479       s << rows_interchange(m);
00480       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00481     }
00483     static std::vector<IntArgs> expectedSolutions(void) {
00484       static std::vector<IntArgs> expected;
00485       expected.clear();
00486       expected.push_back(IntArgs(6, 0,0, 0,0, 0,0));
00487       expected.push_back(IntArgs(6, 0,0, 0,0, 0,1));
00488       expected.push_back(IntArgs(6, 0,0, 0,0, 1,0));
00489       expected.push_back(IntArgs(6, 0,0, 0,0, 1,1));
00490       expected.push_back(IntArgs(6, 0,0, 0,1, 0,0));
00491       expected.push_back(IntArgs(6, 0,0, 0,1, 0,1));
00492       expected.push_back(IntArgs(6, 0,0, 0,1, 1,0));
00493       expected.push_back(IntArgs(6, 0,0, 0,1, 1,1));
00494       expected.push_back(IntArgs(6, 0,0, 1,0, 1,0));
00495       expected.push_back(IntArgs(6, 0,0, 1,0, 1,1));
00496       expected.push_back(IntArgs(6, 0,0, 1,1, 1,1));
00497       expected.push_back(IntArgs(6, 0,1, 0,0, 0,0));
00498       expected.push_back(IntArgs(6, 0,1, 0,0, 0,1));
00499       expected.push_back(IntArgs(6, 0,1, 0,0, 1,0));
00500       expected.push_back(IntArgs(6, 0,1, 0,0, 1,1));
00501       expected.push_back(IntArgs(6, 0,1, 0,1, 0,0));
00502       expected.push_back(IntArgs(6, 0,1, 0,1, 0,1));
00503       expected.push_back(IntArgs(6, 0,1, 0,1, 1,0));
00504       expected.push_back(IntArgs(6, 0,1, 0,1, 1,1));
00505       expected.push_back(IntArgs(6, 0,1, 1,0, 1,0));
00506       expected.push_back(IntArgs(6, 0,1, 1,0, 1,1));
00507       expected.push_back(IntArgs(6, 0,1, 1,1, 1,1));
00508       expected.push_back(IntArgs(6, 1,0, 1,0, 1,0));
00509       expected.push_back(IntArgs(6, 1,0, 1,0, 1,1));
00510       expected.push_back(IntArgs(6, 1,0, 1,1, 1,1));
00511       expected.push_back(IntArgs(6, 1,1, 1,1, 1,1));
00512       return expected;
00513     }
00514   };
00515 
00517   class MatSym2 {
00518   public:
00520     static const int n = 6;
00522     static const int l = 0;
00524     static const int u = 1;
00526     static void setup(Home home, IntVarArray& xs) {
00527       Matrix<IntVarArray> m(xs, 2, 3);
00528       Symmetries s;
00529       s << columns_interchange(m);
00530       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00531     }
00533     static std::vector<IntArgs> expectedSolutions(void) {
00534       static std::vector<IntArgs> expected;
00535       expected.clear();
00536       expected.push_back(IntArgs(6, 0,0, 0,0, 0,0));
00537       expected.push_back(IntArgs(6, 0,0, 0,0, 0,1));
00538       expected.push_back(IntArgs(6, 0,0, 0,0, 1,1));
00539       expected.push_back(IntArgs(6, 0,0, 0,1, 0,0));
00540       expected.push_back(IntArgs(6, 0,0, 0,1, 0,1));
00541       expected.push_back(IntArgs(6, 0,0, 0,1, 1,0));
00542       expected.push_back(IntArgs(6, 0,0, 0,1, 1,1));
00543       expected.push_back(IntArgs(6, 0,0, 1,1, 0,0));
00544       expected.push_back(IntArgs(6, 0,0, 1,1, 0,1));
00545       expected.push_back(IntArgs(6, 0,0, 1,1, 1,1));
00546       expected.push_back(IntArgs(6, 0,1, 0,0, 0,0));
00547       expected.push_back(IntArgs(6, 0,1, 0,0, 0,1));
00548       expected.push_back(IntArgs(6, 0,1, 0,0, 1,0));
00549       expected.push_back(IntArgs(6, 0,1, 0,0, 1,1));
00550       expected.push_back(IntArgs(6, 0,1, 0,1, 0,0));
00551       expected.push_back(IntArgs(6, 0,1, 0,1, 0,1));
00552       expected.push_back(IntArgs(6, 0,1, 0,1, 1,0));
00553       expected.push_back(IntArgs(6, 0,1, 0,1, 1,1));
00554       expected.push_back(IntArgs(6, 0,1, 1,0, 0,0));
00555       expected.push_back(IntArgs(6, 0,1, 1,0, 0,1));
00556       expected.push_back(IntArgs(6, 0,1, 1,0, 1,0));
00557       expected.push_back(IntArgs(6, 0,1, 1,0, 1,1));
00558       expected.push_back(IntArgs(6, 0,1, 1,1, 0,0));
00559       expected.push_back(IntArgs(6, 0,1, 1,1, 0,1));
00560       expected.push_back(IntArgs(6, 0,1, 1,1, 1,0));
00561       expected.push_back(IntArgs(6, 0,1, 1,1, 1,1));
00562       expected.push_back(IntArgs(6, 1,1, 0,0, 0,0));
00563       expected.push_back(IntArgs(6, 1,1, 0,0, 0,1));
00564       expected.push_back(IntArgs(6, 1,1, 0,0, 1,1));
00565       expected.push_back(IntArgs(6, 1,1, 0,1, 0,0));
00566       expected.push_back(IntArgs(6, 1,1, 0,1, 0,1));
00567       expected.push_back(IntArgs(6, 1,1, 0,1, 1,0));
00568       expected.push_back(IntArgs(6, 1,1, 0,1, 1,1));
00569       expected.push_back(IntArgs(6, 1,1, 1,1, 0,0));
00570       expected.push_back(IntArgs(6, 1,1, 1,1, 0,1));
00571       expected.push_back(IntArgs(6, 1,1, 1,1, 1,1));
00572       return expected;
00573     }
00574   };
00575 
00577   class MatSym3 {
00578   public:
00580     static const int n = 6;
00582     static const int l = 0;
00584     static const int u = 1;
00586     static void setup(Home home, IntVarArray& xs) {
00587       Matrix<IntVarArray> m(xs, 2, 3);
00588       Symmetries s;
00589       s << rows_interchange(m);
00590       s << columns_interchange(m);
00591       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00592     }
00594     static std::vector<IntArgs> expectedSolutions(void) {
00595       static std::vector<IntArgs> expected;
00596       expected.clear();
00597       expected.push_back(IntArgs(6, 0,0, 0,0, 0,0));
00598       expected.push_back(IntArgs(6, 0,0, 0,0, 0,1));
00599       expected.push_back(IntArgs(6, 0,0, 0,0, 1,1));
00600       expected.push_back(IntArgs(6, 0,0, 0,1, 0,0));
00601       expected.push_back(IntArgs(6, 0,0, 0,1, 0,1));
00602       expected.push_back(IntArgs(6, 0,0, 0,1, 1,0));
00603       expected.push_back(IntArgs(6, 0,0, 0,1, 1,1));
00604       expected.push_back(IntArgs(6, 0,0, 1,1, 1,1));
00605       expected.push_back(IntArgs(6, 0,1, 0,0, 0,0));
00606       expected.push_back(IntArgs(6, 0,1, 0,0, 0,1));
00607       expected.push_back(IntArgs(6, 0,1, 0,0, 1,0));
00608       expected.push_back(IntArgs(6, 0,1, 0,0, 1,1));
00609       expected.push_back(IntArgs(6, 0,1, 0,1, 0,0));
00610       expected.push_back(IntArgs(6, 0,1, 0,1, 0,1));
00611       expected.push_back(IntArgs(6, 0,1, 0,1, 1,0));
00612       expected.push_back(IntArgs(6, 0,1, 0,1, 1,1));
00613       expected.push_back(IntArgs(6, 0,1, 1,0, 1,0));
00614       expected.push_back(IntArgs(6, 0,1, 1,0, 1,1));
00615       expected.push_back(IntArgs(6, 0,1, 1,1, 1,1));
00616       expected.push_back(IntArgs(6, 1,1, 1,1, 1,1));
00617       return expected;
00618     }
00619   };
00620 
00622   class MatSym4 {
00623   public:
00625     static const int n = 4;
00627     static const int l = 0;
00629     static const int u = 1;
00631     static void setup(Home home, IntVarArray& xs) {
00632       Matrix<IntVarArray> m(xs, 1, 4);
00633       Symmetries s;
00634       s << rows_reflect(m);
00635       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00636     }
00638     static std::vector<IntArgs> expectedSolutions(void) {
00639       static std::vector<IntArgs> expected;
00640       expected.clear();
00641       expected.push_back(IntArgs(4, 0, 0, 0, 0));
00642       expected.push_back(IntArgs(4, 0, 0, 0, 1));
00643       expected.push_back(IntArgs(4, 0, 0, 1, 0));
00644       expected.push_back(IntArgs(4, 0, 0, 1, 1));
00645       expected.push_back(IntArgs(4, 0, 1, 0, 0));
00646       expected.push_back(IntArgs(4, 0, 1, 0, 1));
00647       expected.push_back(IntArgs(4, 0, 1, 1, 0));
00648       expected.push_back(IntArgs(4, 0, 1, 1, 1));
00649       expected.push_back(IntArgs(4, 1, 0, 0, 1));
00650       expected.push_back(IntArgs(4, 1, 0, 1, 1));
00651       expected.push_back(IntArgs(4, 1, 1, 1, 1));
00652       return expected;
00653     }
00654   };
00655 
00657   class SimIntVarSym1 {
00658   public:
00660     static const int n = 12;
00662     static const int l = 0;
00664     static const int u = 3;
00666     static void setup(Home home, IntVarArray& xs) {
00667       Matrix<IntVarArray> m(xs, 3, 4);
00668       // The values in the first column are distinct.
00669       distinct(home, m.col(0));
00670       // Each row sums to 3.
00671       for (int i = 0 ; i < 4 ; ++i)
00672         linear(home, m.row(i), IRT_EQ, 3);
00673 
00674       // Rows are interchangeable.
00675       Symmetries s;
00676       s << VariableSequenceSymmetry(xs, 3);
00677       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00678     }
00680     static std::vector<IntArgs> expectedSolutions(void) {
00681       static std::vector<IntArgs> expected;
00682       expected.clear();
00683       expected.push_back(IntArgs(12, 0,0,3, 1,0,2, 2,0,1, 3,0,0));
00684       expected.push_back(IntArgs(12, 0,0,3, 1,0,2, 2,1,0, 3,0,0));
00685       expected.push_back(IntArgs(12, 0,0,3, 1,1,1, 2,0,1, 3,0,0));
00686       expected.push_back(IntArgs(12, 0,0,3, 1,1,1, 2,1,0, 3,0,0));
00687       expected.push_back(IntArgs(12, 0,0,3, 1,2,0, 2,0,1, 3,0,0));
00688       expected.push_back(IntArgs(12, 0,0,3, 1,2,0, 2,1,0, 3,0,0));
00689       expected.push_back(IntArgs(12, 0,1,2, 1,0,2, 2,0,1, 3,0,0));
00690       expected.push_back(IntArgs(12, 0,1,2, 1,0,2, 2,1,0, 3,0,0));
00691       expected.push_back(IntArgs(12, 0,1,2, 1,1,1, 2,0,1, 3,0,0));
00692       expected.push_back(IntArgs(12, 0,1,2, 1,1,1, 2,1,0, 3,0,0));
00693       expected.push_back(IntArgs(12, 0,1,2, 1,2,0, 2,0,1, 3,0,0));
00694       expected.push_back(IntArgs(12, 0,1,2, 1,2,0, 2,1,0, 3,0,0));
00695       expected.push_back(IntArgs(12, 0,2,1, 1,0,2, 2,0,1, 3,0,0));
00696       expected.push_back(IntArgs(12, 0,2,1, 1,0,2, 2,1,0, 3,0,0));
00697       expected.push_back(IntArgs(12, 0,2,1, 1,1,1, 2,0,1, 3,0,0));
00698       expected.push_back(IntArgs(12, 0,2,1, 1,1,1, 2,1,0, 3,0,0));
00699       expected.push_back(IntArgs(12, 0,2,1, 1,2,0, 2,0,1, 3,0,0));
00700       expected.push_back(IntArgs(12, 0,2,1, 1,2,0, 2,1,0, 3,0,0));
00701       expected.push_back(IntArgs(12, 0,3,0, 1,0,2, 2,0,1, 3,0,0));
00702       expected.push_back(IntArgs(12, 0,3,0, 1,0,2, 2,1,0, 3,0,0));
00703       expected.push_back(IntArgs(12, 0,3,0, 1,1,1, 2,0,1, 3,0,0));
00704       expected.push_back(IntArgs(12, 0,3,0, 1,1,1, 2,1,0, 3,0,0));
00705       expected.push_back(IntArgs(12, 0,3,0, 1,2,0, 2,0,1, 3,0,0));
00706       expected.push_back(IntArgs(12, 0,3,0, 1,2,0, 2,1,0, 3,0,0));
00707       return expected;
00708     }
00709   };
00710 
00712   class SimIntVarSym2 {
00714     static const int nrows = 4;
00716     static const int ncols = 3;
00717   public:
00719     static const int n = nrows*ncols;
00721     static const int l = 0;
00723     static const int u = 3;
00725     static void setup(Home home, IntVarArray& xs) {
00726       Matrix<IntVarArray> m(xs, 3, 4);
00727       // The values in the first column are distinct.
00728       distinct(home, m.col(0));
00729       // Each row sums to 3.
00730       for (int i = 0 ; i < nrows ; ++i)
00731         linear(home, m.row(i), IRT_EQ, 3);
00732 
00733       Symmetries s;
00734 
00735       IntArgs a = IntArgs::create(n, 0);
00736       // Rows are interchangeable.
00737       s << VariableSequenceSymmetry(xs, 3);
00738       // Elements (i,1) and (i,2) in row i are interchangeable,
00739       // separately for each row.
00740       for (int i = 0 ; i < nrows ; i++) {
00741         IntVarArgs symvars;
00742         symvars << m(1,i) << m(2,i);
00743         s << VariableSymmetry(symvars);
00744       }
00745       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00746     }
00748     static std::vector<IntArgs> expectedSolutions(void) {
00749       static std::vector<IntArgs> expected;
00750       expected.clear();
00751       expected.push_back(IntArgs(12, 0,0,3, 1,0,2, 2,0,1, 3,0,0));
00752       expected.push_back(IntArgs(12, 0,0,3, 1,1,1, 2,0,1, 3,0,0));
00753       expected.push_back(IntArgs(12, 0,1,2, 1,0,2, 2,0,1, 3,0,0));
00754       expected.push_back(IntArgs(12, 0,1,2, 1,1,1, 2,0,1, 3,0,0));
00755       return expected;
00756     }
00757   };
00758 
00760   class SimIntValSym1 {
00761   public:
00763     static const int n = 2;
00765     static const int l = 0;
00767     static const int u = 6;
00769     static void setup(Home home, IntVarArray& xs) {
00770       rel(home, xs[0] + xs[1] == 6);
00771       // Values 0,1,2 are symmetric with 6,5,4.
00772       IntArgs values(6, 0,1,2, 6,5,4);
00773       Symmetries s;
00774       s << ValueSequenceSymmetry(values, 3);
00775       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00776     }
00778     static std::vector<IntArgs> expectedSolutions(void) {
00779       static std::vector<IntArgs> expected;
00780       expected.clear();
00781       expected.push_back(IntArgs(2, 0,6));
00782       expected.push_back(IntArgs(2, 1,5));
00783       expected.push_back(IntArgs(2, 2,4));
00784       expected.push_back(IntArgs(2, 3,3));
00785       return expected;
00786     }
00787   };
00788 
00790   class SimIntValSym2 {
00791   public:
00793     static const int n = 3;
00795     static const int l = 0;
00797     static const int u = 8;
00799     static void setup(Home home, IntVarArray& xs) {
00800       TupleSet tuples;
00801       tuples.add(IntArgs(3, 1,1,1));
00802       tuples.add(IntArgs(3, 4,4,4));
00803       tuples.add(IntArgs(3, 7,7,7));
00804       tuples.add(IntArgs(3, 0,1,5));
00805       tuples.add(IntArgs(3, 0,1,8));
00806       tuples.add(IntArgs(3, 3,4,2));
00807       tuples.add(IntArgs(3, 3,4,8));
00808       tuples.add(IntArgs(3, 6,7,2));
00809       tuples.add(IntArgs(3, 6,7,5));
00810       tuples.finalize();
00811       extensional(home, xs, tuples);
00812 
00813       // Values 0,1,2 are symmetric with 3,4,5, and with 6,7,8.
00814       IntArgs values(9, 0,1,2, 3,4,5, 6,7,8);
00815       Symmetries s;
00816       s << ValueSequenceSymmetry(values, 3);
00817       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00818     }
00820     static std::vector<IntArgs> expectedSolutions(void) {
00821       static std::vector<IntArgs> expected;
00822       expected.clear();
00823       expected.push_back(IntArgs(3, 0,1,5));
00824       expected.push_back(IntArgs(3, 1,1,1));
00825       return expected;
00826     }
00827   };
00828 
00830   class SimIntValSym3 {
00831   public:
00833     static const int n = 2;
00835     static const int l = 0;
00837     static const int u = 6;
00839     static void setup(Home home, IntVarArray& xs) {
00840       rel(home, xs[0] + xs[1] == 6);
00841       Symmetries s;
00842       // Values 0,1,2 are symmetric with 6,5,4.
00843       s << values_reflect(0,6);
00844       branch(home, xs, INT_VAR_NONE(), INT_VAL_MED(), s);
00845     }
00847     static std::vector<IntArgs> expectedSolutions(void) {
00848       static std::vector<IntArgs> expected;
00849       expected.clear();
00850       expected.push_back(IntArgs(2, 3,3));
00851       expected.push_back(IntArgs(2, 2,4));
00852       expected.push_back(IntArgs(2, 1,5));
00853       expected.push_back(IntArgs(2, 0,6));
00854       return expected;
00855     }
00856   };
00857 
00859   class ValSym1 {
00860   public:
00862     static const int n = 4;
00864     static const int l = 0;
00866     static const int u = 3;
00868     static void setup(Home home, IntVarArray& xs) {
00869       distinct(home, xs);
00870       Symmetries s;
00871       IntArgs indices(4, 0,1,2,3);
00872       s << ValueSymmetry(indices);
00873       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00874     }
00876     static std::vector<IntArgs> expectedSolutions(void) {
00877       static std::vector<IntArgs> expected;
00878       expected.clear();
00879       expected.push_back(IntArgs(4, 0,1,2,3));
00880       return expected;
00881     }
00882   };
00883 
00885   class ValSym1b {
00886   public:
00888     static const int n = 4;
00890     static const int l = 0;
00892     static const int u = 3;
00894     static void setup(Home home, IntVarArray& xs) {
00895       distinct(home, xs);
00896       Symmetries s;
00897       s << ValueSymmetry(xs[0]);
00898       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00899     }
00901     static std::vector<IntArgs> expectedSolutions(void) {
00902       static std::vector<IntArgs> expected;
00903       expected.clear();
00904       expected.push_back(IntArgs(4, 0,1,2,3));
00905       return expected;
00906     }
00907   };
00908 
00910   class ValSym1c {
00911   public:
00913     static const int n = 4;
00915     static const int l = 0;
00917     static const int u = 3;
00919     static void setup(Home home, IntVarArray& xs) {
00920       distinct(home, xs);
00921       Symmetries s;
00922       s << ValueSymmetry(xs[0]);
00923       branch(home, xs, INT_VAR_NONE(), INT_VAL_MAX(), s);
00924     }
00926     static std::vector<IntArgs> expectedSolutions(void) {
00927       static std::vector<IntArgs> expected;
00928       expected.clear();
00929       expected.push_back(IntArgs(4, 3,2,1,0));
00930       return expected;
00931     }
00932   };
00933 
00935   class ValSym2 {
00936   public:
00938     static const int n = 4;
00940     static const int l = 0;
00942     static const int u = 3;
00944     static void setup(Home home, IntVarArray& xs) {
00945       Symmetries s;
00946       IntArgs indices(4, 0,1,2,3);
00947       s << ValueSymmetry(indices);
00948       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00949     }
00951     static std::vector<IntArgs> expectedSolutions(void) {
00952       static std::vector<IntArgs> expected;
00953       expected.clear();
00954       expected.push_back(IntArgs(4, 0,0,0,0));
00955       expected.push_back(IntArgs(4, 0,0,0,1));
00956       expected.push_back(IntArgs(4, 0,0,1,0));
00957       expected.push_back(IntArgs(4, 0,0,1,1));
00958       expected.push_back(IntArgs(4, 0,0,1,2));
00959       expected.push_back(IntArgs(4, 0,1,0,0));
00960       expected.push_back(IntArgs(4, 0,1,0,1));
00961       expected.push_back(IntArgs(4, 0,1,0,2));
00962       expected.push_back(IntArgs(4, 0,1,1,0));
00963       expected.push_back(IntArgs(4, 0,1,1,1));
00964       expected.push_back(IntArgs(4, 0,1,1,2));
00965       expected.push_back(IntArgs(4, 0,1,2,0));
00966       expected.push_back(IntArgs(4, 0,1,2,1));
00967       expected.push_back(IntArgs(4, 0,1,2,2));
00968       expected.push_back(IntArgs(4, 0,1,2,3));
00969       return expected;
00970     }
00971   };
00972 
00974   class ValSym2b {
00975   public:
00977     static const int n = 4;
00979     static const int l = 0;
00981     static const int u = 3;
00983     static void setup(Home home, IntVarArray& xs) {
00984       Symmetries s;
00985       s << ValueSymmetry(xs[0]);
00986       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
00987     }
00989     static std::vector<IntArgs> expectedSolutions(void) {
00990       static std::vector<IntArgs> expected;
00991       expected.clear();
00992       expected.push_back(IntArgs(4, 0,0,0,0));
00993       expected.push_back(IntArgs(4, 0,0,0,1));
00994       expected.push_back(IntArgs(4, 0,0,1,0));
00995       expected.push_back(IntArgs(4, 0,0,1,1));
00996       expected.push_back(IntArgs(4, 0,0,1,2));
00997       expected.push_back(IntArgs(4, 0,1,0,0));
00998       expected.push_back(IntArgs(4, 0,1,0,1));
00999       expected.push_back(IntArgs(4, 0,1,0,2));
01000       expected.push_back(IntArgs(4, 0,1,1,0));
01001       expected.push_back(IntArgs(4, 0,1,1,1));
01002       expected.push_back(IntArgs(4, 0,1,1,2));
01003       expected.push_back(IntArgs(4, 0,1,2,0));
01004       expected.push_back(IntArgs(4, 0,1,2,1));
01005       expected.push_back(IntArgs(4, 0,1,2,2));
01006       expected.push_back(IntArgs(4, 0,1,2,3));
01007       return expected;
01008     }
01009   };
01010 
01012   class ValSym3 {
01013   public:
01015     static const int n = 4;
01017     static const int l = 0;
01019     static const int u = 3;
01021     static void setup(Home home, IntVarArray& xs) {
01022       distinct(home, xs);
01023       Symmetries s;
01024       IntArgs indices(2, 0,1);
01025       s << ValueSymmetry(indices);
01026       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
01027     }
01029     static std::vector<IntArgs> expectedSolutions(void) {
01030       static std::vector<IntArgs> expected;
01031       expected.clear();
01032       expected.push_back(IntArgs(4, 0,1,2,3));
01033       expected.push_back(IntArgs(4, 0,1,3,2));
01034       expected.push_back(IntArgs(4, 0,2,1,3));
01035       expected.push_back(IntArgs(4, 0,2,3,1));
01036       expected.push_back(IntArgs(4, 0,3,1,2));
01037       expected.push_back(IntArgs(4, 0,3,2,1));
01038       expected.push_back(IntArgs(4, 2,0,1,3));
01039       expected.push_back(IntArgs(4, 2,0,3,1));
01040       expected.push_back(IntArgs(4, 2,3,0,1));
01041       expected.push_back(IntArgs(4, 3,0,1,2));
01042       expected.push_back(IntArgs(4, 3,0,2,1));
01043       expected.push_back(IntArgs(4, 3,2,0,1));
01044       return expected;
01045     }
01046   };
01047 
01049   class ValSym4 {
01050   public:
01052     static const int n = 3;
01054     static const int l = 0;
01056     static const int u = 2;
01058     static void setup(Home home, IntVarArray& xs) {
01059       distinct(home, xs);
01060       Symmetries s;
01061       IntArgs indices(1, 0);
01062       s << ValueSymmetry(indices);
01063       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
01064     }
01066     static std::vector<IntArgs> expectedSolutions(void) {
01067       static std::vector<IntArgs> expected;
01068       expected.clear();
01069       expected.push_back(IntArgs(3, 0,1,2));
01070       expected.push_back(IntArgs(3, 0,2,1));
01071       expected.push_back(IntArgs(3, 1,0,2));
01072       expected.push_back(IntArgs(3, 1,2,0));
01073       expected.push_back(IntArgs(3, 2,0,1));
01074       expected.push_back(IntArgs(3, 2,1,0));
01075       return expected;
01076     }
01077   };
01078 
01080   class ValSym5 {
01081   public:
01083     static const int n = 4;
01085     static const int l = 0;
01087     static const int u = 3;
01089     static void setup(Home home, IntVarArray& xs) {
01090       distinct(home, xs);
01091       Symmetries s;
01092       IntArgs indices0(2, 0,1);
01093       IntArgs indices1(2, 2,3);
01094       s << ValueSymmetry(indices0);
01095       s << ValueSymmetry(indices1);
01096       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
01097     }
01099     static std::vector<IntArgs> expectedSolutions(void) {
01100       static std::vector<IntArgs> expected;
01101       expected.clear();
01102       expected.push_back(IntArgs(4, 0,1,2,3));
01103       expected.push_back(IntArgs(4, 0,2,1,3));
01104       expected.push_back(IntArgs(4, 0,2,3,1));
01105       expected.push_back(IntArgs(4, 2,0,1,3));
01106       expected.push_back(IntArgs(4, 2,0,3,1));
01107       expected.push_back(IntArgs(4, 2,3,0,1));
01108       return expected;
01109     }
01110   };
01111 
01113   class VarValSym1 {
01114   public:
01116     static const int n = 4;
01118     static const int l = 0;
01120     static const int u = 3;
01122     static void setup(Home home, IntVarArray& xs) {
01123       Symmetries s;
01124       s << VariableSymmetry(xs);
01125       s << ValueSymmetry(IntArgs::create(4,0));
01126       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
01127     }
01129     static std::vector<IntArgs> expectedSolutions(void) {
01130       static std::vector<IntArgs> expected;
01131       expected.clear();
01132       expected.push_back(IntArgs(4, 0,0,0,0));
01133       expected.push_back(IntArgs(4, 0,0,0,1));
01134       expected.push_back(IntArgs(4, 0,0,1,1));
01135       expected.push_back(IntArgs(4, 0,0,1,2));
01136       expected.push_back(IntArgs(4, 0,1,1,1));
01137       expected.push_back(IntArgs(4, 0,1,1,2));
01138       expected.push_back(IntArgs(4, 0,1,2,2));  // This solution is symmetric to the previous one.
01139       expected.push_back(IntArgs(4, 0,1,2,3));
01140       return expected;
01141     }
01142   };
01143 
01145   class LDSBLatin : public Base {
01146   public:
01148     class Latin : public Space {
01149     public:
01150       IntVarArray xs;
01151       Latin(int n = 4) : xs(*this, n*n, 1, n)
01152       {
01153         Matrix<IntVarArray> m(xs, n, n);
01154         for (int i = 0 ; i < n ; i++) {
01155           distinct(*this, m.col(i));
01156           distinct(*this, m.row(i));
01157         }
01158         Symmetries s;
01159         s << rows_interchange(m);
01160         s << columns_interchange(m);
01161         s << ValueSymmetry(IntSet(1,n));
01162         branch(*this, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
01163       }
01164       // Search support.
01165       Latin(bool share, Latin& s) : Space(share, s)
01166       { xs.update(*this, share, s.xs); }
01167       virtual Space* copy(bool share)
01168       { return new Latin(share,*this); }
01169       IntArgs solution(void) {
01170         IntArgs a(xs.size());
01171         for (int i = 0 ; i < a.size() ; ++i)
01172           a[i] = xs[i].val();
01173         return a;
01174       }
01175 
01177       static std::vector<IntArgs> expectedSolutions(void) {
01178         static std::vector<IntArgs> expected;
01179         expected.clear();
01180         expected.push_back(IntArgs(16, 1,2,3,4, 2,1,4,3, 3,4,1,2, 4,3,2,1));
01181         expected.push_back(IntArgs(16, 1,2,3,4, 2,1,4,3, 3,4,2,1, 4,3,1,2));
01182         expected.push_back(IntArgs(16, 1,2,3,4, 2,3,4,1, 3,4,1,2, 4,1,2,3));
01183         expected.push_back(IntArgs(16, 1,2,3,4, 2,4,1,3, 3,1,4,2, 4,3,2,1));
01184         return expected;
01185       }
01186     };
01188     LDSBLatin(std::string label) : Test::Base("LDSB::" + label) {}
01190     bool run(void) {
01191       Latin *s = new Latin();
01192       DFS<Latin> e(s);
01193       bool r = check(e, Latin::expectedSolutions());
01194       delete s;
01195       return r;
01196     }
01197   };
01198 
01199   /* This test should fail if the recomputation-handling does not work
01200    * properly.
01201    *
01202    * Why recomputation can be a problem
01203    * ==================================
01204    *
01205    * Every branch point in LDSB is binary, with a left and a right
01206    * branch.  Whenever backtracking happens -- when a right branch is
01207    * explored -- LDSB computes a set of symmetric literals to
01208    * exclude.
01209    *
01210    * !!! This calculation may depend on the current domains of the
01211    * !!! variables.
01212    *
01213    * During recomputation, parts of the search tree are replayed.  To
01214    * be specific, the branching constraints are posted, but no
01215    * propagation happens.  This means that at a given branch point,
01216    * the domains during recomputation may be different (weaker) than
01217    * they were the first time during search.
01218    *
01219    * !!! This *cannot* cause solutions to be missed --- LDSB will not
01220    * !!! be incorrect --- but it *does* change what will be pruned.
01221    *
01222    * If recomputation is not handled properly, the difference in
01223    * domains will cause extra solutions to be found.  This is a result
01224    * of symmetries failing to be broken.
01225    *
01226    */
01227 
01229   class Recomputation {
01230   public:
01232     static const int n = 4;
01234     static const int l = 0;
01236     static const int u = 1;
01238     static void setup(Home home, IntVarArray& xs) {
01239       TupleSet t;
01240       t.add(IntArgs(2, 0,0));
01241       t.add(IntArgs(2, 1,1));
01242       t.finalize();
01243       IntVarArgs va;
01244       va << xs[0] << xs[2];
01245       extensional(home, va, t);
01246       Symmetries syms;
01247       syms << VariableSequenceSymmetry(xs, 2);
01248       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
01249     }
01251     static std::vector<IntArgs> expectedSolutions(void) {
01252       static std::vector<IntArgs> expected;
01253       expected.clear();
01254       expected.push_back(IntArgs(4, 0,0,0,0));
01255       expected.push_back(IntArgs(4, 0,0,0,1));
01256 
01257       // This is the solution that will be found if recomputation is
01258       // not handled.  After branching on x[0]=0, we try x[1]=0.  When
01259       // x[1]=0 backtracks, the symmetry [x[0],x[1]] <-> [x[2],x[3]]
01260       // is active --- but only after propagation!  (Without
01261       // propagation, we do not have x[2]=0.)  If propagation happens,
01262       // we know that symmetry is active and we can post x[3]!=0.  If
01263       // it doesn't, we don't use the symmetry and we find a solution
01264       // where x[3]=0.
01265 
01266       // expected.push_back(IntArgs(4, 0,1,0,0));
01267 
01268       expected.push_back(IntArgs(4, 0,1,0,1));
01269 
01270       expected.push_back(IntArgs(4, 1,0,1,0));
01271       expected.push_back(IntArgs(4, 1,0,1,1));
01272       expected.push_back(IntArgs(4, 1,1,1,1));
01273       return expected;
01274     }
01275   };
01276 
01277   double position(const Space& home, IntVar x, int i) {
01278     (void) home;
01279     (void) x;
01280     return i;
01281   }
01282 
01284   class TieBreak {
01285   public:
01287     static const int n = 4;
01289     static const int l = 0;
01291     static const int u = 3;
01293     static void setup(Home home, IntVarArray& xs) {
01294       Symmetries syms;
01295       IntArgs indices(4, 0,1,2,3);
01296       syms << VariableSymmetry(xs, indices);
01297       distinct(home, xs);
01298       // This redundant constraint is to trick the variable
01299       // heuristic.
01300       rel(home, xs[1] != xs[2]);
01301       // xs[1] and xs[2] have higher degree than the others, so they
01302       // are considered first.  xs[2] is higher than x[1] by the merit
01303       // function, so it is assigned first.  Now all remaining
01304       // variables have the same degree, so they are searched in
01305       // reverse order (according to the merit function).  So, the
01306       // solution found is {3, 2, 0, 1}.
01307       branch(home, xs, tiebreak(INT_VAR_DEGREE_MAX(), INT_VAR_MERIT_MAX(position)), INT_VAL_MIN(), syms);
01308     }
01310     static std::vector<IntArgs> expectedSolutions(void) {
01311       static std::vector<IntArgs> expected;
01312       expected.clear();
01313       expected.push_back(IntArgs(4, 3,2,0,1));
01314       return expected;
01315     }
01316   };
01317 
01318 #ifdef GECODE_HAS_SET_VARS
01319 
01320   IntSetArgs ISA(int n, ...) {
01321     IntSetArgs sets;
01322     va_list args;
01323     va_start(args, n);
01324     int i = 0;
01325     IntArgs a;
01326     while (i < n) {
01327       int x = va_arg(args,int);
01328       if (x == -1) {
01329         i++;
01330         sets << IntSet(a);
01331         a = IntArgs();
01332       } else {
01333         a << x;
01334       }
01335     }
01336     va_end(args);
01337     return sets;
01338   }
01339 
01341   class SetVarSym1 {
01342   public:
01344     static const int n = 2;
01346     static const int l = 0;
01348     static const int u = 1;
01350     static void setup(Home home, SetVarArray& xs) {
01351       Symmetries syms;
01352       syms << VariableSymmetry(xs);
01353       branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
01354     }
01356     static std::vector<IntSetArgs> expectedSolutions(void) {
01357       static std::vector<IntSetArgs> expected;
01358       expected.clear();
01359       expected.push_back(ISA(2, 0,1,-1, 0,1,-1));
01360       expected.push_back(ISA(2, 0,1,-1, 0,  -1));
01361       expected.push_back(ISA(2, 0,1,-1,   1,-1));
01362       expected.push_back(ISA(2, 0,1,-1,     -1));
01363       expected.push_back(ISA(2, 0,  -1, 0,1,-1));
01364       expected.push_back(ISA(2, 0,  -1, 0,  -1));
01365       expected.push_back(ISA(2, 0,  -1,   1,-1));
01366       expected.push_back(ISA(2, 0,  -1,     -1));
01367       // expected.push_back(ISA(2,   1,-1, 0,1,-1));
01368       // expected.push_back(ISA(2,   1,-1, 0,  -1));
01369       expected.push_back(ISA(2,   1,-1,   1,-1));
01370       expected.push_back(ISA(2,   1,-1,     -1));
01371       // expected.push_back(ISA(2,     -1, 0,1,-1));
01372       // expected.push_back(ISA(2,     -1, 0,  -1));
01373       // expected.push_back(ISA(2,     -1,   1,-1));
01374       expected.push_back(ISA(2,     -1,     -1));
01375       return expected;
01376     }
01377   };
01378 
01379   /*
01380    * This tests the special handling of value symmetries on set
01381    * values.  Look at the third solution (commented out) below.  The
01382    * first variable has been assigned to {0,1}.  If the value symmetry
01383    * is not handled specially, then we will consider the value
01384    * symmetry broken because the search has touched each value.
01385    * However, because both values have been assigned to the same
01386    * variable, 0 and 1 are still symmetric.  Therefore, the third
01387    * solution is symmetric to the second one and should be excluded.
01388    */
01389 
01391   class SetValSym1 {
01392   public:
01394     static const int n = 2;
01396     static const int l = 0;
01398     static const int u = 1;
01400     static void setup(Home home, SetVarArray& xs) {
01401       Symmetries syms;
01402       syms << ValueSymmetry(IntArgs(2, 0,1));
01403       branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
01404     }
01406     static std::vector<IntSetArgs> expectedSolutions(void) {
01407       static std::vector<IntSetArgs> expected;
01408       expected.clear();
01409       expected.push_back(ISA(2, 0,1,-1, 0,1,-1));
01410       expected.push_back(ISA(2, 0,1,-1, 0,  -1));
01411       // expected.push_back(ISA(2, 0,1,-1,   1,-1)); // XXXXX bad solution
01412       expected.push_back(ISA(2, 0,1,-1,     -1));
01413       expected.push_back(ISA(2, 0,  -1, 0,1,-1));
01414       expected.push_back(ISA(2, 0,  -1, 0,  -1));
01415       expected.push_back(ISA(2, 0,  -1,   1,-1));
01416       expected.push_back(ISA(2, 0,  -1,     -1));
01417       // expected.push_back(ISA(2,   1,-1, 0,1,-1));
01418       // expected.push_back(ISA(2,   1,-1, 0,  -1));
01419       // expected.push_back(ISA(2,   1,-1,   1,-1));
01420       // expected.push_back(ISA(2,   1,-1,     -1));
01421       expected.push_back(ISA(2,     -1, 0,1,-1));
01422       expected.push_back(ISA(2,     -1, 0,  -1));
01423       // expected.push_back(ISA(2,     -1,   1,-1));
01424       expected.push_back(ISA(2,     -1,     -1));
01425       return expected;
01426     }
01427   };
01428 
01430   class SetValSym2 {
01431   public:
01433     static const int n = 3;
01435     static const int l = 1;
01437     static const int u = 4;
01439     static void setup(Home home, SetVarArray& xs) {
01440       Symmetries syms;
01441       syms << ValueSymmetry(IntArgs(4, 1,2,3,4));
01442       for (int i = 0 ; i < 3 ; i++)
01443         cardinality(home, xs[i], 1, 1);
01444       branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
01445     }
01447     static std::vector<IntSetArgs> expectedSolutions(void) {
01448       static std::vector<IntSetArgs> expected;
01449       expected.clear();
01450       expected.push_back(ISA(3, 1,-1, 1,-1, 1,-1));
01451       expected.push_back(ISA(3, 1,-1, 1,-1, 2,-1));
01452       expected.push_back(ISA(3, 1,-1, 2,-1, 1,-1));
01453       expected.push_back(ISA(3, 1,-1, 2,-1, 2,-1));
01454       expected.push_back(ISA(3, 1,-1, 2,-1, 3,-1));
01455       return expected;
01456     }
01457   };
01458 
01460   class SetVarSeqSym1 {
01461   public:
01463     static const int n = 4;
01465     static const int l = 0;
01467     static const int u = 1;
01469     static void setup(Home home, SetVarArray& xs) {
01470       Symmetries syms;
01471       syms << VariableSequenceSymmetry(xs,2);
01472       rel(home, xs[0], SOT_INTER, xs[1], SRT_EQ, IntSet::empty);
01473       rel(home, xs[2], SOT_INTER, xs[3], SRT_EQ, IntSet::empty);
01474       for (int i = 0 ; i < 4 ; i++)
01475         cardinality(home, xs[i], 1, 1);
01476       branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
01477     }
01479     static std::vector<IntSetArgs> expectedSolutions(void) {
01480       static std::vector<IntSetArgs> expected;
01481       expected.clear();
01482       expected.push_back(ISA(4, 0,-1, 1,-1, 0,-1, 1,-1));
01483       expected.push_back(ISA(4, 0,-1, 1,-1, 1,-1, 0,-1));
01484       //      expected.push_back(ISA(4, 1,-1, 0,-1, 0,-1, 1,-1));
01485       expected.push_back(ISA(4, 1,-1, 0,-1, 1,-1, 0,-1));
01486       return expected;
01487     }
01488   };
01489 
01491   class SetVarSeqSym2 {
01492   public:
01494     static const int n = 4;
01496     static const int l = 0;
01498     static const int u = 0;
01500     static void setup(Home home, SetVarArray& xs) {
01501       Symmetries syms;
01502       syms << VariableSequenceSymmetry(xs,2);
01503       rel(home, xs[0], SRT_EQ, xs[2]);
01504       branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
01505     }
01507     static std::vector<IntSetArgs> expectedSolutions(void) {
01508       static std::vector<IntSetArgs> expected;
01509       expected.clear();
01510 
01511       // Symmetric solutions are commented out.
01512       expected.push_back(ISA(4, 0, -1,0,-1,0,-1,0,-1));
01513       expected.push_back(ISA(4, 0, -1,0,-1,0,-1,  -1));
01514       // expected.push_back(ISA(4, 0, -1,0,-1,  -1,0,-1));
01515       // expected.push_back(ISA(4, 0, -1,0,-1,  -1,  -1));
01516       // expected.push_back(ISA(4, 0, -1,  -1,0,-1,0,-1));
01517       expected.push_back(ISA(4, 0, -1,  -1,0,-1,  -1));
01518       // expected.push_back(ISA(4, 0, -1,  -1,  -1,0,-1));
01519       // expected.push_back(ISA(4, 0, -1,  -1,  -1,  -1));
01520       // expected.push_back(ISA(4,    -1,0,-1,0,-1,0,-1));
01521       // expected.push_back(ISA(4,    -1,0,-1,0,-1,  -1));
01522       expected.push_back(ISA(4,    -1,0,-1,  -1,0,-1));
01523       expected.push_back(ISA(4,    -1,0,-1,  -1,  -1));
01524       // expected.push_back(ISA(4,    -1,  -1,0,-1,0,-1));
01525       // expected.push_back(ISA(4,    -1,  -1,0,-1,  -1));
01526       // expected.push_back(ISA(4,    -1,  -1,  -1,0,-1));
01527       expected.push_back(ISA(4,    -1,  -1,  -1,  -1));
01528 
01529       return expected;
01530     }
01531   };
01532 
01534   class ReflectSym1 {
01535   public:
01537     static const int n = 6;
01539     static const int l = 0;
01541     static const int u = 6;
01543     static void setup(Home home, IntVarArray& xs) {
01544       Matrix<IntVarArray> m(xs, 3, 2);
01545 
01546       distinct(home, xs);
01547       rel(home, abs(m(0,0)-m(1,0))==1);
01548       rel(home, abs(m(0,1)-m(1,1))==1);
01549       rel(home, abs(m(1,0)-m(2,0))==1);
01550       rel(home, abs(m(1,1)-m(2,1))==1);
01551 
01552       Symmetries s;
01553       s << values_reflect(l, u);
01554       s << rows_interchange(m);
01555       s << columns_reflect(m);
01556       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
01557     }
01559     static std::vector<IntArgs> expectedSolutions(void) {
01560       static std::vector<IntArgs> expected;
01561       expected.clear();
01562       expected.push_back(IntArgs(6, 0,1,2,3,4,5));
01563       expected.push_back(IntArgs(6, 0,1,2,4,5,6));
01564       expected.push_back(IntArgs(6, 0,1,2,5,4,3));
01565       expected.push_back(IntArgs(6, 0,1,2,6,5,4));
01566       return expected;
01567     }
01568   };
01569 
01571   class ReflectSym2 {
01572   public:
01574     static const int n = 2;
01576     static const int l = 0;
01578     static const int u = 3;
01580     static void setup(Home home, IntVarArray& xs) {
01581       Symmetries s;
01582       s << values_reflect(l, u);
01583       branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
01584     }
01586     static std::vector<IntArgs> expectedSolutions(void) {
01587       static std::vector<IntArgs> expected;
01588       expected.clear();
01589       expected.push_back(IntArgs(2, 0,0));
01590       expected.push_back(IntArgs(2, 0,1));
01591       expected.push_back(IntArgs(2, 0,2));
01592       expected.push_back(IntArgs(2, 0,3));
01593       expected.push_back(IntArgs(2, 1,0));
01594       expected.push_back(IntArgs(2, 1,1));
01595       expected.push_back(IntArgs(2, 1,2));
01596       expected.push_back(IntArgs(2, 1,3));
01597       return expected;
01598     }
01599   };
01600 
01602   class Action1 {
01603   public:
01605     static const int n = 4;
01607     static const int l = 0;
01609     static const int u = 3;
01611     static void setup(Home home, IntVarArray& xs) {
01612       distinct(home, xs);
01613       Symmetries s;
01614       s << VariableSymmetry(xs);
01615       s << ValueSymmetry(IntArgs::create(4,0));
01616       branch(home, xs, INT_VAR_ACTION_MIN(0.8), INT_VAL_MIN(), s);
01617     }
01619     static std::vector<IntArgs> expectedSolutions(void) {
01620       static std::vector<IntArgs> expected;
01621       expected.clear();
01622       expected.push_back(IntArgs(4, 0,1,2,3));
01623       return expected;
01624     }
01625   };
01626 
01627 #endif
01628 
01629   LDSB<VarSym1> varsym1("VarSym1");
01630   LDSB<VarSym1b> varsym1b("VarSym1b");
01631   LDSB<VarSym2> varsym2("VarSym2");
01632   LDSB<VarSym3> varsym3("VarSym3");
01633   LDSB<VarSym4> varsym4("VarSym4");
01634   LDSB<VarSym5> varsym5("VarSym5");
01635   LDSB<MatSym1> matsym1("MatSym1");
01636   LDSB<MatSym2> matsym2("MatSym2");
01637   LDSB<MatSym3> matsym3("MatSym3");
01638   LDSB<MatSym4> matsym4("MatSym4");
01639   LDSB<SimIntVarSym1> simintvarsym1("SimIntVarSym1");
01640   LDSB<SimIntVarSym2> simintvarsym2("SimIntVarSym2");
01641   LDSB<SimIntValSym1> simintvalsym1("SimIntValSym1");
01642   LDSB<SimIntValSym2> simintvalsym2("SimIntValSym2");
01643   LDSB<SimIntValSym3> simintvalsym3("SimIntValSym3");
01644   LDSB<ValSym1> valsym1("ValSym1");
01645   LDSB<ValSym1b> valsym1b("ValSym1b");
01646   LDSB<ValSym1c> valsym1c("ValSym1c");
01647   LDSB<ValSym2> valsym2("ValSym2");
01648   LDSB<ValSym2b> valsym2b("ValSym2b");
01649   LDSB<ValSym3> valsym3("ValSym3");
01650   LDSB<ValSym4> valsym4("ValSym4");
01651   LDSB<ValSym5> valsym5("ValSym5");
01652   LDSB<VarValSym1> varvalsym1("VarValSym1");
01653   LDSBLatin latin("Latin");
01654   LDSB<Recomputation> recomp("Recomputation", 999,999);
01655   LDSB<TieBreak> tiebreak("TieBreak");
01656 
01657 #ifdef GECODE_HAS_SET_VARS
01658   LDSB<ReflectSym1> reflectsym1("ReflectSym1");
01659   LDSB<ReflectSym2> reflectsym2("ReflectSym2");
01660   LDSB<Action1> action1("Action1");
01661 
01662   LDSBSet<SetVarSym1> setvarsym1("SetVarSym1");
01663   LDSBSet<SetValSym1> setvalsym1("SetValSym1");
01664   LDSBSet<SetValSym2> setvalsym2("SetValSym2", 0, 1);
01665   LDSBSet<SetVarSeqSym1> setvarseqsym1("SetVarSeqSym1");
01666   LDSBSet<SetVarSeqSym2> setvarseqsym2("SetVarSeqSym2");
01667 #endif
01668 }}
01669 
01670 // STATISTICS: test-core