00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <gecode/driver.hh>
00039 #include <gecode/int.hh>
00040
00041 #include <vector>
00042 #include <algorithm>
00043 #include <sstream>
00044
00045 using namespace Gecode;
00046
00047 namespace {
00048 using std::vector;
00049
00051 vector<vector<int> > layout;
00053 vector<int> layer, pile;
00054
00061 void generate(int seed) {
00062
00063 layout = vector<vector<int> >(17, vector<int>(3));
00064
00065 vector<int> deck(51);
00066 for (int i = 51; i--; ) deck[i] = i+1;
00067 Support::RandomGenerator rnd(seed+1);
00068 std::random_shuffle(deck.begin(), deck.end(), rnd);
00069
00070
00071 int pos = 0;
00072 for (int i = 17; i--; )
00073 for (int j = 3; j--; )
00074 layout[i][j] = deck[pos++];
00075
00076
00077 layer = vector<int>(52);
00078 pile = vector<int>(52);
00079 for (int i = 17; i--; ) {
00080 for (int j = 3; j--; ) {
00081 layer[layout[i][j]] = j;
00082 pile[ layout[i][j]] = i;
00083 }
00084 }
00085 }
00086 }
00087
00088
00089
00098 class BlackHoleBranch : Branching {
00100 ViewArray<Int::IntView> x;
00102 mutable int pos, val;
00104 class Description : public BranchingDesc {
00105 public:
00107 int pos;
00109 int val;
00113 Description(const Branching& b, unsigned int a, int pos0, int val0)
00114 : BranchingDesc(b,a), pos(pos0), val(val0) {}
00116 virtual size_t size(void) const {
00117 return sizeof(Description);
00118 }
00119 };
00120
00122 BlackHoleBranch(Space& home, ViewArray<Int::IntView>& xv)
00123 : Branching(home), x(xv), pos(-1), val(-1) {}
00125 BlackHoleBranch(Space& home, bool share, BlackHoleBranch& b)
00126 : Branching(home, share, b), pos(b.pos), val(b.val) {
00127 x.update(home, share, b.x);
00128 }
00129
00130 public:
00132 virtual bool status(const Space&) const {
00133 for (pos = 0; pos < x.size(); ++pos) {
00134 if (!x[pos].assigned()) {
00135 int w = 4;
00136 for (Int::ViewValues<Int::IntView> vals(x[pos]); vals(); ++vals) {
00137 if (layer[vals.val()] < w) {
00138 val = vals.val();
00139 if ((w = layer[vals.val()]) == 0) break;
00140 }
00141 }
00142 return true;
00143 }
00144 }
00145
00146 return false;
00147 }
00149 virtual BranchingDesc* description(Space&) {
00150 assert(pos >= 0 && pos < x.size() && val >= 1 && val < 52);
00151 return new Description(*this, 2, pos, val);
00152 }
00154 virtual ExecStatus commit(Space& home, const BranchingDesc& d,
00155 unsigned int a) {
00156 const Description& desc =
00157 static_cast<const Description&>(d);
00158 pos = val = -1;
00159 if (a)
00160 return me_failed(x[desc.pos].nq(home, desc.val))
00161 ? ES_FAILED : ES_OK;
00162 else
00163 return me_failed(x[desc.pos].eq(home, desc.val))
00164 ? ES_FAILED : ES_OK;
00165 }
00167 virtual Actor* copy(Space& home, bool share) {
00168 return new (home) BlackHoleBranch(home, share, *this);
00169 }
00171 static void post(Space& home, IntVarArgs x) {
00172 ViewArray<Int::IntView> xv(home, x);
00173 (void) new (home) BlackHoleBranch(home, xv);
00174 }
00175 };
00176
00177
00194 class BlackHole : public Script {
00195 protected:
00196 IntVarArray x,
00197 y;
00198
00200 std::string
00201 card(int val) const {
00202 const char* suit = "SCHD";
00203 std::ostringstream o;
00204 o << std::setw(2) << (1 + (val%13)) << suit[val/13];
00205 return o.str();
00206 }
00207
00208 public:
00210 enum {
00211 MODEL_NONE,
00212 MODEL_SYMMETRY
00213 };
00215 enum {
00216 PROPAGATION_REIFIED,
00217 PROPAGATION_DFA,
00218 PROPAGATION_TUPLE_SET
00219 };
00221 BlackHole(const SizeOptions& opt)
00222 : x(*this, 52, 0,51), y(*this, 52, 0,51)
00223 {
00224
00225 rel(*this, x[0], IRT_EQ, 0);
00226
00227
00228 channel(*this, x, y, opt.icl());
00229
00230
00231
00232 if (opt.propagation() == PROPAGATION_REIFIED) {
00233
00234 IntArgs modtable(52);
00235 for (int i = 0; i < 52; ++i) {
00236 modtable[i] = i%13;
00237 }
00238 for (int i = 0; i < 51; ++i) {
00239 IntVar x1(*this, 0, 12), x2(*this, 0, 12);
00240 element(*this, modtable, x[i], x1);
00241 element(*this, modtable, x[i+1], x2);
00242 const int dr[2] = {1, 12};
00243 IntVar diff(*this, IntSet(dr, 2));
00244 post(*this, abs(*this, minus(*this, x1, x2, ICL_DOM), ICL_DOM)
00245 == diff, ICL_DOM);
00246 }
00247 } else if (opt.propagation() == PROPAGATION_DFA) {
00248
00249 REG expression;
00250 for (int r = 13; r--; ) {
00251 for (int s1 = 4; s1--; ) {
00252 for (int s2 = 4; s2--; ) {
00253 for (int i = -1; i <= 1; i+=2) {
00254 REG r1 = REG(r+13*s1);
00255 REG r2 = REG((r+i+52+13*s2)%52);
00256 REG r = r1 + r2;
00257 expression |= r;
00258 }
00259 }
00260 }
00261 }
00262 DFA table(expression);
00263
00264 for (int i = 51; i--; ) {
00265 IntVarArgs iva(2);
00266 iva[0] = x[i]; iva[1] = x[i+1];
00267 extensional(*this, iva, table);
00268 }
00269
00270 } else {
00271
00272 TupleSet tupleSet;
00273 for (int r = 13; r--; )
00274 for (int s1 = 4; s1--; )
00275 for (int s2 = 4; s2--; )
00276 for (int i = -1; i <= 1; i+=2) {
00277 IntArgs t(2);
00278 t[0] = r+13*s1;
00279 t[1] = (r+i+52+13*s2)%52;
00280 tupleSet.add(t);
00281 }
00282 tupleSet.finalize();
00283 for (int i = 51; i--; ) {
00284 IntVarArgs iva(2);
00285 iva[0] = x[i]; iva[1] = x[i+1];
00286 extensional(*this, iva, tupleSet, EPK_DEF, ICL_DOM);
00287 }
00288 }
00289
00290 for (int i = 17; i--; )
00291 for (int j = 2; j--; )
00292 post(*this, y[layout[i][j]] < y[layout[i][j+1]]);
00293
00294
00295
00296 if (opt.model() == MODEL_SYMMETRY) {
00297
00298 for (int r = 13; r--; ) {
00299
00300 for (int s1 = 4; s1--; ) {
00301 for (int s2 = s1; s2--; ) {
00302 int c1 = 13*s1 + r,
00303 c2 = 13*s2 + r;
00304
00305 if (c1 == 0 || c2 == 0) continue;
00306
00307 if (pile[c1] == pile[c2]) continue;
00308
00309 int o1 = c1, o2 = c2;
00310 if (pile[c1] > pile[c2] && layer[c2] >= layer[c1])
00311 std::swap(o1, o2);
00312
00313 BoolVarArgs ba(4);
00314 int pos = 0;
00315
00316 for (int i = 0; i < layer[o1]; ++i)
00317 ba[pos++] = post(*this, ~(y[layout[pile[o1]][i]] < y[o2]));
00318 for (int i = 0; i < layer[o2]; ++i)
00319 ba[pos++] = post(*this, ~(y[layout[pile[o2]][i]] < y[o1]));
00320
00321 for (int i = layer[o1]+1; i < 3; ++i)
00322 ba[pos++] = post(*this, ~(y[o2] < y[layout[pile[o1]][i]]));
00323 for (int i = layer[o2]+1; i < 3; ++i)
00324 ba[pos++] = post(*this, ~(y[o1] < y[layout[pile[o2]][i]]));
00325
00326 BoolVar cond(*this, 0, 1);
00327 rel(*this, BOT_AND, ba, cond);
00328
00329
00330
00331 post(*this, tt(!cond || ~(y[o1] < y[o2])));
00332 }
00333 }
00334 }
00335 }
00336
00337
00338 BlackHoleBranch::post(*this, x);
00339 }
00340
00342 virtual void
00343 print(std::ostream& os) const {
00344 os << "Layout:" << std::endl;
00345 for (int i = 0; i < 17; i++) {
00346 for (int j = 0; j < 3; j++)
00347 os << card(layout[i][j]) << " ";
00348 if ((i+1) % 3 == 0)
00349 os << std::endl;
00350 else
00351 os << " \t";
00352 }
00353 os << std::endl << std::endl;
00354
00355 os << "Solution:" << std::endl;
00356 for (int i = 0; i < 52; ++i) {
00357 if (x[i].assigned())
00358 os << card(x[i].val()) << " ";
00359 else
00360 os << " ";
00361 if ((i + 1) % 13 == 0)
00362 os << std::endl;
00363 }
00364 os << std::endl;
00365 os << std::endl;
00366 }
00367
00369 BlackHole(bool share, BlackHole& s) : Script(share,s) {
00370 x.update(*this, share, s.x);
00371 y.update(*this, share, s.y);
00372 }
00374 virtual Space*
00375 copy(bool share) {
00376 return new BlackHole(share,*this);
00377 }
00378 };
00379
00383 int
00384 main(int argc, char* argv[]) {
00385 SizeOptions opt("Black Hole patience");
00386 opt.model(BlackHole::MODEL_SYMMETRY);
00387 opt.model(BlackHole::MODEL_NONE,"none");
00388 opt.model(BlackHole::MODEL_SYMMETRY,"symmetry");
00389 opt.propagation(BlackHole::PROPAGATION_DFA);
00390 opt.propagation(BlackHole::PROPAGATION_REIFIED,
00391 "reified", "use reified propagation");
00392 opt.propagation(BlackHole::PROPAGATION_DFA,
00393 "dfa", "use DFA-based extensional propagation");
00394 opt.propagation(BlackHole::PROPAGATION_TUPLE_SET,
00395 "tuple-set", "use TupleSet-based extensional propagation");
00396 opt.icl(ICL_DOM);
00397 opt.parse(argc,argv);
00398
00399 generate(opt.size());
00400 Script::run<BlackHole,DFS,SizeOptions>(opt);
00401 return 0;
00402 }
00403
00404