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 "examples/support.hh"
00039
00040 #include "gecode/minimodel.hh"
00041
00042 #include <vector>
00043 #include <algorithm>
00044 #include <sstream>
00045
00046 namespace {
00047 using std::vector;
00048
00050 vector<vector<int> > layout;
00052 vector<int> layer, pile;
00053
00060 void generate(int seed) {
00061
00062 layout = vector<vector<int> >(17, vector<int>(3));
00063
00064 vector<int> deck(51);
00065 for (int i = 51; i--; ) deck[i] = i+1;
00066 Support::RandomGenerator rnd(seed+1);
00067 std::random_shuffle(deck.begin(), deck.end(), rnd);
00068
00069
00070 int pos = 0;
00071 for (int i = 17; i--; )
00072 for (int j = 3; j--; )
00073 layout[i][j] = deck[pos++];
00074
00075
00076 layer = vector<int>(52);
00077 pile = vector<int>(52);
00078 for (int i = 17; i--; ) {
00079 for (int j = 3; j--; ) {
00080 layer[layout[i][j]] = j;
00081 pile[ layout[i][j]] = i;
00082 }
00083 }
00084 }
00085 }
00086
00087
00096 class BlackHoleBranch : Branching {
00098 ViewArray<Int::IntView> x;
00100 mutable int pos, val;
00101
00103 BlackHoleBranch(Space* home, ViewArray<Int::IntView>& xv)
00104 : Branching(home), x(xv), pos(-1), val(-1) {}
00106 BlackHoleBranch(Space* home, bool share, BlackHoleBranch& b)
00107 : Branching(home, share, b), pos(b.pos), val(b.val) {
00108 x.update(home, share, b.x);
00109 }
00110
00111 public:
00113 virtual bool status(const Space*) const {
00114 for (pos = 0; pos < x.size(); ++pos) {
00115 if (!x[pos].assigned()) {
00116 int w = 4;
00117 for (Int::ViewValues<Int::IntView> vals(x[pos]); vals(); ++vals) {
00118 if (layer[vals.val()] < w) {
00119 val = vals.val();
00120 if ((w = layer[vals.val()]) == 0) break;
00121 }
00122 }
00123 return true;
00124 }
00125 }
00126
00127 return false;
00128 }
00130 virtual BranchingDesc* description(const Space*) const {
00131 assert(pos >= 0 && pos < x.size() && val >= 1 && val < 52);
00132 return new PosValDesc<int,2>(this, pos, val);
00133 }
00135 virtual ExecStatus commit(Space* home, const BranchingDesc* d,
00136 unsigned int a) {
00137 const PosValDesc<int,2> *desc = static_cast<const PosValDesc<int,2>*>(d);
00138 pos = val = -1;
00139 if (a)
00140 return me_failed(x[desc->pos()].nq(home, desc->val()))
00141 ? ES_FAILED : ES_OK;
00142 else
00143 return me_failed(x[desc->pos()].eq(home, desc->val()))
00144 ? ES_FAILED : ES_OK;
00145 }
00147 virtual Actor* copy(Space *home, bool share) {
00148 return new (home) BlackHoleBranch(home, share, *this);
00149 }
00151 virtual const char* name(void) const {
00152 return "BlackHoleBranch";
00153 }
00155 static void post(Space* home, IntVarArgs x) {
00156 ViewArray<Int::IntView> xv(home, x);
00157 (void) new (home) BlackHoleBranch(home, xv);
00158 }
00159 };
00160
00161
00178 class BlackHole : public Example {
00179 protected:
00180 IntVarArray x,
00181 y;
00182
00184 std::string
00185 card(int val) {
00186 const char* suit = "SCHD";
00187 std::ostringstream o;
00188 o << std::setw(2) << (1 + (val%13)) << suit[val/13];
00189 return o.str();
00190 }
00191
00192 public:
00194 enum {
00195 MODEL_NONE,
00196 MODEL_SYMMETRY
00197 };
00199 enum {
00200 PROPAGATION_REIFIED,
00201 PROPAGATION_DFA,
00202 PROPAGATION_TUPLE_SET
00203 };
00205 BlackHole(const SizeOptions& opt)
00206 : x(this, 52, 0,51), y(this, 52, 0,51)
00207 {
00208
00209 rel(this, x[0], IRT_EQ, 0);
00210
00211
00212 channel(this, x, y, opt.icl());
00213
00214
00215
00216 if (opt.propagation() == PROPAGATION_REIFIED) {
00217
00218 IntArgs modtable(52);
00219 for (int i = 0; i < 52; ++i) {
00220 modtable[i] = i%13;
00221 }
00222 for (int i = 0; i < 51; ++i) {
00223 IntVar x1(this, 0, 12), x2(this, 0, 12);
00224 element(this, modtable, x[i], x1);
00225 element(this, modtable, x[i+1], x2);
00226 const int dr[2] = {1, 12};
00227 IntVar diff(this, IntSet(dr, 2));
00228 post(this, abs(this, minus(this, x1, x2, ICL_DOM), ICL_DOM)
00229 == diff, ICL_DOM);
00230 }
00231 } else if (opt.propagation() == PROPAGATION_DFA) {
00232
00233 REG expression;
00234 for (int r = 13; r--; ) {
00235 for (int s1 = 4; s1--; ) {
00236 for (int s2 = 4; s2--; ) {
00237 for (int i = -1; i <= 1; i+=2) {
00238 REG r1 = REG(r+13*s1);
00239 REG r2 = REG((r+i+52+13*s2)%52);
00240 REG r = r1 + r2;
00241 expression |= r;
00242 }
00243 }
00244 }
00245 }
00246 DFA table(expression);
00247
00248 for (int i = 51; i--; ) {
00249 IntVarArgs iva(2);
00250 iva[0] = x[i]; iva[1] = x[i+1];
00251 extensional(this, iva, table);
00252 }
00253
00254 } else {
00255
00256 TupleSet tupleSet;
00257 for (int r = 13; r--; ) {
00258 for (int s1 = 4; s1--; ) {
00259 for (int s2 = 4; s2--; ) {
00260 for (int i = -1; i <= 1; i+=2) {
00261 IntArgs t(2);
00262 t[0] = r+13*s1;
00263 t[1] = (r+i+52+13*s2)%52;
00264 tupleSet.add(t);
00265 }
00266 }
00267 }
00268 }
00269
00270 for (int i = 51; i--; ) {
00271 IntVarArgs iva(2);
00272 iva[0] = x[i]; iva[1] = x[i+1];
00273 extensional(this, iva, tupleSet, ICL_DOM, opt.pk());
00274 }
00275 }
00276
00277 for (int i = 17; i--; )
00278 for (int j = 2; j--; )
00279 post(this, y[layout[i][j]] < y[layout[i][j+1]]);
00280
00281
00282
00283 if (opt.model() == MODEL_SYMMETRY) {
00284
00285 for (int r = 13; r--; ) {
00286
00287 for (int s1 = 4; s1--; ) {
00288 for (int s2 = s1; s2--; ) {
00289 int c1 = 13*s1 + r,
00290 c2 = 13*s2 + r;
00291
00292 if (c1 == 0 || c2 == 0) continue;
00293
00294 if (pile[c1] == pile[c2]) continue;
00295
00296 int o1 = c1, o2 = c2;
00297 if (pile[c1] > pile[c2] && layer[c2] >= layer[c1])
00298 std::swap(o1, o2);
00299
00300 BoolVarArgs ba(4);
00301 int pos = 0;
00302
00303 for (int i = 0; i < layer[o1]; ++i)
00304 ba[pos++] = post(this, ~(y[layout[pile[o1]][i]] < y[o2]));
00305 for (int i = 0; i < layer[o2]; ++i)
00306 ba[pos++] = post(this, ~(y[layout[pile[o2]][i]] < y[o1]));
00307
00308 for (int i = layer[o1]+1; i < 3; ++i)
00309 ba[pos++] = post(this, ~(y[o2] < y[layout[pile[o1]][i]]));
00310 for (int i = layer[o2]+1; i < 3; ++i)
00311 ba[pos++] = post(this, ~(y[o1] < y[layout[pile[o2]][i]]));
00312
00313 BoolVar cond(this, 0, 1);
00314 rel(this, BOT_AND, ba, cond);
00315
00316
00317
00318 post(this, tt(!cond || ~(y[o1] < y[o2])));
00319 }
00320 }
00321 }
00322 }
00323
00324
00325 BlackHoleBranch::post(this, x);
00326 }
00327
00329 virtual void
00330 print(std::ostream& os) {
00331 os << "Layout:" << std::endl;
00332 for (int i = 0; i < 17; i++) {
00333 for (int j = 0; j < 3; j++)
00334 os << card(layout[i][j]) << " ";
00335 if ((i+1) % 3 == 0)
00336 os << std::endl;
00337 else
00338 os << "\t";
00339 }
00340 os << std::endl << std::endl;
00341
00342 os << "Solution:" << std::endl;
00343 for (int i = 0; i < 52; ++i) {
00344 os << card(x[i].min()) << " ";
00345 if ((i + 1) % 13 == 0)
00346 os << std::endl;
00347 }
00348 os << std::endl;
00349 os << std::endl;
00350 }
00351
00353 BlackHole(bool share, BlackHole& s) : Example(share,s) {
00354 x.update(this, share, s.x);
00355 y.update(this, share, s.y);
00356 }
00358 virtual Space*
00359 copy(bool share) {
00360 return new BlackHole(share,*this);
00361 }
00362 };
00363
00367 int
00368 main(int argc, char* argv[]) {
00369 SizeOptions opt("Black Hole patience");
00370 opt.model(BlackHole::MODEL_SYMMETRY);
00371 opt.model(BlackHole::MODEL_NONE,"none");
00372 opt.model(BlackHole::MODEL_SYMMETRY,"symmetry");
00373 opt.propagation(BlackHole::PROPAGATION_DFA);
00374 opt.propagation(BlackHole::PROPAGATION_REIFIED,
00375 "reified", "use reified propagation");
00376 opt.propagation(BlackHole::PROPAGATION_DFA,
00377 "dfa", "use DFA-based extensional propagation");
00378 opt.propagation(BlackHole::PROPAGATION_TUPLE_SET,
00379 "tuple-set", "use TupleSet-based extensional propagation");
00380 opt.icl(ICL_DOM);
00381 opt.pk(PK_SPEED);
00382 opt.parse(argc,argv);
00383
00384 generate(opt.size());
00385 Example::run<BlackHole,DFS,SizeOptions>(opt);
00386 return 0;
00387 }
00388
00389