00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "examples/support.hh"
00023 #include "gecode/minimodel.hh"
00024 #include "gecode/support/random.hh"
00025
00026 #include <vector>
00027 #include <algorithm>
00028 #include <sstream>
00029
00030 namespace {
00031 using std::vector;
00032
00034 vector<vector<int> > layout;
00036 vector<int> layer, pile;
00037
00039 void generate(int seed) {
00040
00041 layout = vector<vector<int> >(17, vector<int>(3));
00042 vector<int> nums(51);
00043 for (int i = 51; i--; ) nums[i] = i+1;
00044 Support::RandomGenerator rnd(seed+1);
00045 std::random_shuffle(nums.begin(), nums.end(), rnd);
00046 int pos = 0;
00047 for (int i = 17; i--; )
00048 for (int j = 3; j--; )
00049 layout[i][j] = nums[pos++];
00050
00051
00052 layer = vector<int>(52);
00053 pile = vector<int>(52);
00054 for (int i = 17; i--; ) {
00055 for (int j = 3; j--; ) {
00056 layer[layout[i][j]] = j;
00057 pile[ layout[i][j]] = i;
00058 }
00059 }
00060 }
00061 }
00062
00063
00067 class BlackHoleBranch : Branching {
00068 ViewArray<Int::IntView> x;
00069 mutable int pos, val;
00070
00071 BlackHoleBranch(Space* home, ViewArray<Int::IntView>& xv)
00072 : Branching(home), x(xv), pos(-1), val(-1) {}
00073 BlackHoleBranch(Space* home, bool share, BlackHoleBranch& b)
00074 : Branching(home, share, b), pos(b.pos), val(b.val) {
00075 x.update(home, share, b.x);
00076 }
00077
00078 public:
00079 virtual bool status(const Space* home) const {
00080 for (pos = 0; pos < x.size(); ++pos) {
00081 if (!x[pos].assigned()) {
00082 int w = 4;
00083 for (Int::ViewValues<Int::IntView> vals(x[pos]); vals(); ++vals) {
00084 if (layer[vals.val()] < w) {
00085 val = vals.val();
00086 if ((w = layer[vals.val()]) == 0) break;
00087 }
00088 }
00089 return true;
00090 }
00091 }
00092
00093 return false;
00094 }
00095 virtual BranchingDesc* description(const Space* home) const {
00096 assert(pos >= 0 && pos < x.size() && val >= 1 && val < 52);
00097 return new PosValDesc<int>(this, pos, val);
00098 }
00099 virtual ExecStatus commit(Space* home, const BranchingDesc* d, unsigned int a) {
00100 const PosValDesc<int> *desc = static_cast<const PosValDesc<int>*>(d);
00101 pos = val = -1;
00102 if (a)
00103 return me_failed(x[desc->pos()].nq(home, desc->val())) ? ES_FAILED : ES_OK;
00104 else
00105 return me_failed(x[desc->pos()].eq(home, desc->val())) ? ES_FAILED : ES_OK;
00106 }
00107 virtual Actor* copy(Space *home, bool share) {
00108 return new (home) BlackHoleBranch(home, share, *this);
00109 }
00110 static void post(Space* home, IntVarArgs x) {
00111 ViewArray<Int::IntView> xv(home, x);
00112 (void) new (home) BlackHoleBranch(home, xv);
00113 }
00114 };
00115
00116
00133 class BlackHole : public Example {
00134 protected:
00135 IntVarArray x,
00136 y;
00137
00139 std::string
00140 card(int val) {
00141 const char* suit = "SCHD";
00142 std::ostringstream o;
00143 o << std::setw(2) << (1 + (val%13)) << suit[val/13];
00144 return o.str();
00145 }
00146
00147 public:
00149 BlackHole(const Options& opt)
00150 : x(this, 52, 0,51), y(this, 52, 0,51)
00151 {
00152
00153 rel(this, x[0], IRT_EQ, 0);
00154
00155
00156 channel(this, x, y, opt.icl);
00157
00158
00159 IntArgs modtable(52);
00160 for (int i = 0; i < 52; ++i) {
00161 modtable[i] = i%13;
00162 }
00163
00164
00165 for (int i = 0; i < 51; ++i) {
00166 IntVar x1(this, 0, 12), x2(this, 0, 12);
00167 element(this, modtable, x[i], x1, ICL_DOM);
00168 element(this, modtable, x[i+1], x2, ICL_DOM);
00169 const int dr[2] = {1, 12};
00170 IntVar diff(this, IntSet(dr, 2));
00171 post(this, abs(this, minus(this, x1, x2, ICL_DOM), ICL_DOM)
00172 == diff, ICL_DOM);
00173 }
00174
00175
00176 for (int i = 17; i--; ) {
00177 for (int j = 2; j--; ) {
00178
00179 post(this, y[layout[i][j]] < y[layout[i][j+1]]);
00180 }
00181 }
00182
00183
00184
00185 if (!opt.naive) {
00186
00187 for (int r = 13; r--; ) {
00188
00189 for (int s1 = 4; s1--; ) {
00190 for (int s2 = s1; s2--; ) {
00191 int c1 = 13*s1 + r,
00192 c2 = 13*s2 + r;
00193
00194 if (c1 == 0 || c2 == 0) continue;
00195
00196 if (pile[c1] == pile[c2]) continue;
00197
00198 int o1 = c1, o2 = c2;
00199 if (pile[c1] > pile[c2] && layer[c2] >= layer[c1])
00200 std::swap(o1, o2);
00201
00202 BoolVarArgs ba(4);
00203 int pos = 0;
00204
00205 for (int i = 0; i < layer[o1]; ++i)
00206 ba[pos++] = post(this, ~(y[layout[pile[o1]][i]] < y[o2]));
00207 for (int i = 0; i < layer[o2]; ++i)
00208 ba[pos++] = post(this, ~(y[layout[pile[o2]][i]] < y[o1]));
00209
00210 for (int i = layer[o1]+1; i < 3; ++i)
00211 ba[pos++] = post(this, ~(y[o2] < y[layout[pile[o1]][i]]));
00212 for (int i = layer[o2]+1; i < 3; ++i)
00213 ba[pos++] = post(this, ~(y[o1] < y[layout[pile[o2]][i]]));
00214
00215 BoolVar cond(this, 0, 1);
00216 bool_and(this, ba, cond);
00217
00218
00219
00220 post(this, tt(!cond || ~(y[o1] < y[o2])));
00221 }
00222 }
00223 }
00224 }
00225
00226
00227 BlackHoleBranch::post(this, x);
00228 }
00230 virtual void
00231 print(void) {
00232 std::cout << "Layout:" << std::endl;
00233 for (int i = 0; i < 17; i++) {
00234 for (int j = 0; j < 3; j++)
00235 std::cout << card(layout[i][j]) << " ";
00236 if ((i+1) % 3 == 0)
00237 std::cout << std::endl;
00238 else
00239 std::cout << "\t";
00240 }
00241 std::cout << std::endl << std::endl;
00242
00243 std::cout << "Solution:" << std::endl;
00244 for (int i = 0; i < 52; ++i) {
00245 std::cout << card(x[i].min()) << " ";
00246 if ((i + 1) % 13 == 0)
00247 std::cout << std::endl;
00248 }
00249 std::cout << std::endl;
00250 std::cout << std::endl;
00251 }
00252
00254 BlackHole(bool share, BlackHole& s) : Example(share,s) {
00255 x.update(this, share, s.x);
00256 y.update(this, share, s.y);
00257 }
00259 virtual Space*
00260 copy(bool share) {
00261 return new BlackHole(share,*this);
00262 }
00263 };
00264
00268 int
00269 main(int argc, char** argv) {
00270 Options opt("Black Hole patience");
00271 opt.solutions = 1;
00272 opt.naive = false;
00273 opt.icl = ICL_DOM;
00274 opt.parse(argc,argv);
00275
00276 generate(opt.size);
00277 Example::run<BlackHole,DFS>(opt);
00278 return 0;
00279 }
00280
00281