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 : Brancher {
00099 protected:
00101 ViewArray<Int::IntView> x;
00103 mutable int start;
00105 class Choice : public Gecode::Choice {
00106 public:
00108 int pos;
00110 int val;
00114 Choice(const Brancher& b, int pos0, int val0)
00115 : Gecode::Choice(b,2), pos(pos0), val(val0) {}
00117 virtual size_t size(void) const {
00118 return sizeof(Choice);
00119 }
00121 virtual void archive(Archive& e) const {
00122 Gecode::Choice::archive(e);
00123 e << pos << val;
00124 }
00125 };
00126
00128 BlackHoleBranch(Home home, ViewArray<Int::IntView>& xv)
00129 : Brancher(home), x(xv), start(0) {}
00131 BlackHoleBranch(Space& home, bool share, BlackHoleBranch& b)
00132 : Brancher(home, share, b), start(b.start) {
00133 x.update(home, share, b.x);
00134 }
00135
00136 public:
00138 virtual bool status(const Space&) const {
00139 for (int i = start; i < x.size(); ++i)
00140 if (!x[i].assigned()) {
00141 start = i;
00142 return true;
00143 }
00144
00145 return false;
00146 }
00148 virtual Choice* choice(Space&) {
00149 int val = -1;
00150 int w = 4;
00151 for (Int::ViewValues<Int::IntView> vals(x[start]); vals(); ++vals)
00152 if (layer[vals.val()] < w) {
00153 val = vals.val();
00154 if ((w = layer[vals.val()]) == 0) break;
00155 }
00156
00157 assert(val >= 1 && val < 52);
00158 return new Choice(*this, start, val);
00159 }
00161 virtual Choice* choice(const Space&, Archive& e) {
00162 int pos, val;
00163 e >> pos >> val;
00164 return new Choice(*this, pos, val);
00165 }
00167 virtual ExecStatus commit(Space& home, const Gecode::Choice& _c,
00168 unsigned int a) {
00169 const Choice& c = static_cast<const Choice&>(_c);
00170 if (a)
00171 return me_failed(x[c.pos].nq(home, c.val)) ? ES_FAILED : ES_OK;
00172 else
00173 return me_failed(x[c.pos].eq(home, c.val)) ? ES_FAILED : ES_OK;
00174 }
00176 virtual Actor* copy(Space& home, bool share) {
00177 return new (home) BlackHoleBranch(home, share, *this);
00178 }
00180 static void post(Home home, IntVarArgs x) {
00181 ViewArray<Int::IntView> xv(home, x);
00182 (void) new (home) BlackHoleBranch(home, xv);
00183 }
00185 virtual size_t dispose(Space&) {
00186 return sizeof(*this);
00187 }
00188 };
00189
00190
00207 class BlackHole : public Script {
00208 protected:
00209 IntVarArray x,
00210 y;
00211
00213 std::string
00214 card(int val) const {
00215 const char* suit = "SCHD";
00216 std::ostringstream o;
00217 o << std::setw(2) << (1 + (val%13)) << suit[val/13];
00218 return o.str();
00219 }
00220
00221 public:
00223 enum {
00224 SYMMETRY_NONE,
00225 SYMMETRY_CONDITIONAL
00226 };
00228 enum {
00229 PROPAGATION_REIFIED,
00230 PROPAGATION_DFA,
00231 PROPAGATION_TUPLE_SET
00232 };
00234 BlackHole(const SizeOptions& opt)
00235 : x(*this, 52, 0,51), y(*this, 52, 0,51)
00236 {
00237
00238 rel(*this, x[0], IRT_EQ, 0);
00239
00240
00241 channel(*this, x, y, opt.icl());
00242
00243
00244
00245 if (opt.propagation() == PROPAGATION_REIFIED) {
00246
00247 IntArgs modtable(52);
00248 for (int i = 0; i < 52; ++i) {
00249 modtable[i] = i%13;
00250 }
00251 for (int i = 0; i < 51; ++i) {
00252 IntVar x1(*this, 0, 12), x2(*this, 0, 12);
00253 element(*this, modtable, x[i], x1);
00254 element(*this, modtable, x[i+1], x2);
00255 const int dr[2] = {1, 12};
00256 IntVar diff(*this, IntSet(dr, 2));
00257 rel(*this, abs(x1-x2) == diff, ICL_DOM);
00258 }
00259 } else if (opt.propagation() == PROPAGATION_DFA) {
00260
00261 REG expression;
00262 for (int r = 13; r--; ) {
00263 for (int s1 = 4; s1--; ) {
00264 for (int s2 = 4; s2--; ) {
00265 for (int i = -1; i <= 1; i+=2) {
00266 REG r1 = REG(r+13*s1);
00267 REG r2 = REG((r+i+52+13*s2)%52);
00268 REG r = r1 + r2;
00269 expression |= r;
00270 }
00271 }
00272 }
00273 }
00274 DFA table(expression);
00275
00276 for (int i = 51; i--; )
00277 extensional(*this, IntVarArgs() << x[i] << x[i+1], table);
00278
00279 } else {
00280
00281 TupleSet tupleSet;
00282 for (int r = 13; r--; )
00283 for (int s1 = 4; s1--; )
00284 for (int s2 = 4; s2--; )
00285 for (int i = -1; i <= 1; i+=2) {
00286 tupleSet.add(IntArgs(2, r+13*s1, (r+i+52+13*s2)%52));
00287 }
00288 tupleSet.finalize();
00289
00290 for (int i = 51; i--; )
00291 extensional(*this, IntVarArgs() << x[i] << x[i+1], tupleSet);
00292 }
00293
00294
00295 for (int i = 17; i--; )
00296 for (int j = 2; j--; )
00297 rel(*this, y[layout[i][j]] < y[layout[i][j+1]]);
00298
00299
00300
00301
00302
00303
00304 if (opt.symmetry() == SYMMETRY_CONDITIONAL) {
00305
00306 for (int r = 13; r--; ) {
00307
00308 for (int s1 = 4; s1--; ) {
00309 for (int s2 = s1; s2--; ) {
00310 int c1 = 13*s1 + r,
00311 c2 = 13*s2 + r;
00312
00313 if (c1 == 0 || c2 == 0) continue;
00314
00315 if (pile[c1] == pile[c2]) continue;
00316
00317 int o1 = c1, o2 = c2;
00318 if (pile[c1] > pile[c2] && layer[c2] >= layer[c1])
00319 std::swap(o1, o2);
00320
00321 BoolVarArgs ba;
00322
00323 for (int i = 0; i < layer[o1]; ++i)
00324 ba << expr(*this, (y[layout[pile[o1]][i]] < y[o2]));
00325 for (int i = 0; i < layer[o2]; ++i)
00326 ba << expr(*this, (y[layout[pile[o2]][i]] < y[o1]));
00327
00328 for (int i = layer[o1]+1; i < 3; ++i)
00329 ba << expr(*this, (y[o2] < y[layout[pile[o1]][i]]));
00330 for (int i = layer[o2]+1; i < 3; ++i)
00331 ba << expr(*this, (y[o1] < y[layout[pile[o2]][i]]));
00332
00333 BoolVar cond(*this, 0, 1);
00334 rel(*this, BOT_AND, ba, cond);
00335
00336
00337
00338 rel(*this, !cond || (y[o1] < y[o2]));
00339 }
00340 }
00341 }
00342 }
00343
00344
00345 BlackHoleBranch::post(*this, x);
00346 }
00347
00349 virtual void
00350 print(std::ostream& os) const {
00351 os << "Layout:" << std::endl;
00352 for (int i = 0; i < 17; i++) {
00353 for (int j = 0; j < 3; j++)
00354 os << card(layout[i][j]) << " ";
00355 if ((i+1) % 3 == 0)
00356 os << std::endl;
00357 else
00358 os << " \t";
00359 }
00360 os << std::endl << std::endl;
00361
00362 os << "Solution:" << std::endl;
00363 for (int i = 0; i < 52; ++i) {
00364 if (x[i].assigned())
00365 os << card(x[i].val()) << " ";
00366 else
00367 os << " ";
00368 if ((i + 1) % 13 == 0)
00369 os << std::endl;
00370 }
00371 os << std::endl;
00372 os << std::endl;
00373 }
00374
00376 BlackHole(bool share, BlackHole& s) : Script(share,s) {
00377 x.update(*this, share, s.x);
00378 y.update(*this, share, s.y);
00379 }
00381 virtual Space*
00382 copy(bool share) {
00383 return new BlackHole(share,*this);
00384 }
00385 };
00386
00390 int
00391 main(int argc, char* argv[]) {
00392 SizeOptions opt("Black Hole patience");
00393 opt.symmetry(BlackHole::SYMMETRY_CONDITIONAL);
00394 opt.symmetry(BlackHole::SYMMETRY_NONE,"none",
00395 "no symmetry breaking");
00396 opt.symmetry(BlackHole::SYMMETRY_CONDITIONAL,"conditional",
00397 "break conditional symmetries");
00398 opt.propagation(BlackHole::PROPAGATION_DFA);
00399 opt.propagation(BlackHole::PROPAGATION_REIFIED,
00400 "reified", "use reified propagation");
00401 opt.propagation(BlackHole::PROPAGATION_DFA,
00402 "dfa", "use DFA-based extensional propagation");
00403 opt.propagation(BlackHole::PROPAGATION_TUPLE_SET,
00404 "tuple-set", "use TupleSet-based extensional propagation");
00405 opt.icl(ICL_DOM);
00406 opt.parse(argc,argv);
00407
00408 generate(opt.size());
00409 Script::run<BlackHole,DFS,SizeOptions>(opt);
00410 return 0;
00411 }
00412
00413