00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "examples/support.hh"
00025 #include "gecode/minimodel.hh"
00026
00028 const int kval[] = {
00029 0, 0, 0, 0, 5,
00030 9, 15, 21, 29, 37,
00031 47, 57, 69, 81, 94,
00032 109
00033 };
00034 const int nkval = 16;
00035
00103 class CrowdedChess : public Example {
00104 protected:
00105 const int n;
00106 IntVarArray s;
00107 IntVarArray queens,
00108 rooks;
00109 BoolVarArray knights;
00110
00114 enum
00115 {Q,
00116 R,
00117 B,
00118 K,
00119 E,
00120 PMAX
00121 } piece;
00122
00123
00124 bool valid_pos(int i, int j) {
00125 return (i >= 0 && i < n) &&
00126 (j >= 0 && j < n);
00127 }
00128
00130 void knight_constraints() {
00131 static const int kmoves[4][2] = {
00132 {-1,2}, {1,2}, {2,-1}, {2,1}
00133 };
00134 MiniModel::Matrix<BoolVarArray> kb(knights, n, n);
00135 for (int x = n; x--; )
00136 for (int y = n; y--; )
00137 for (int i = 4; i--; )
00138 if (valid_pos(x+kmoves[i][0], y+kmoves[i][1])) {
00139 IntVarArgs places(2);
00140 places[0] = kb(x, y);
00141 places[1] = kb(x+kmoves[i][0], y+kmoves[i][1]);
00142 linear(this, places, IRT_LQ, 1);
00143 }
00144 }
00145
00146
00147 public:
00149 CrowdedChess(const Options& o)
00150 : n(o.size), s(this, n*n, 0, PMAX-1), queens(this, n, 0, n-1),
00151 rooks(this, n, 0, n-1), knights(this, n*n, 0, 1) {
00152 const int nn = n*n, q = n, r = n, b = (2*n)-2,
00153 k = n <= nkval ? kval[n-1] : kval[nkval-1];
00154 const int e = nn - (q + r + b + k);
00155
00156 assert(nn == (e + q + r + b + k));
00157
00158 MiniModel::Matrix<IntVarArray> m(s, n);
00159
00160
00161
00162
00163
00164 count(this, s, E, IRT_EQ, e, o.icl);
00165 count(this, s, Q, IRT_EQ, q, o.icl);
00166 count(this, s, R, IRT_EQ, r, o.icl);
00167 count(this, s, B, IRT_EQ, b, o.icl);
00168 count(this, s, K, IRT_EQ, k, o.icl);
00169
00170
00171 IntVar queen(this, Q, Q), rook(this, R, R);
00172
00173
00174 for (int i = 0; i < n; ++i) {
00175 IntVarArgs aa = m.row(i), bb = m.col(i);
00176
00177 count(this, aa, Q, IRT_EQ, 1, o.icl);
00178 count(this, bb, Q, IRT_EQ, 1, o.icl);
00179 count(this, aa, R, IRT_EQ, 1, o.icl);
00180 count(this, bb, R, IRT_EQ, 1, o.icl);
00181
00182
00183 element(this, aa, queens[i], queen, ICL_DOM);
00184 element(this, aa, rooks[i], rook, ICL_DOM);
00185 }
00186
00187
00188 distinct(this, queens, ICL_DOM);
00189 IntArgs koff(n);
00190 for (int i = n; i--; ) koff[i] = i;
00191 distinct(this, koff, queens, ICL_DOM);
00192 for (int i = n; i--; ) koff[i] = -i;
00193 distinct(this, koff, queens, ICL_DOM);
00194
00195
00196 distinct(this, rooks, ICL_DOM);
00197
00198
00199 for (int l = n; l--; ) {
00200 const int il = (n-1) - l;
00201 IntVarArgs d1(l+1), d2(l+1), d3(l+1), d4(l+1);
00202 for (int i = 0; i <= l; ++i) {
00203 d1[i] = m(i+il, i);
00204 d2[i] = m(i, i+il);
00205 d3[i] = m((n-1)-i-il, i);
00206 d4[i] = m((n-1)-i, i+il);
00207 }
00208
00209 count(this, d1, Q, IRT_LQ, 1, o.icl);
00210 count(this, d2, Q, IRT_LQ, 1, o.icl);
00211 count(this, d3, Q, IRT_LQ, 1, o.icl);
00212 count(this, d4, Q, IRT_LQ, 1, o.icl);
00213 count(this, d1, B, IRT_LQ, 1, o.icl);
00214 count(this, d2, B, IRT_LQ, 1, o.icl);
00215 count(this, d3, B, IRT_LQ, 1, o.icl);
00216 count(this, d4, B, IRT_LQ, 1, o.icl);
00217 }
00218
00219
00220
00221 for(int i = n*n; i--; )
00222 knights[i] = post(this, ~(s[i] == K));
00223 knight_constraints();
00224
00225
00226
00227
00228
00229
00230
00231
00232 for (int i = n; i--; ) {
00233 rel(this, queens[i], IRT_NQ, rooks[i]);
00234 }
00235
00236
00237
00238 rel(this, m(n-1, 0), IRT_EQ, B);
00239 rel(this, m(n-1, n-1), IRT_EQ, B);
00240
00241
00242
00243
00244
00245
00246 branch(this, s, BVAR_MIN_MIN, BVAL_MIN);
00247 }
00248
00250 CrowdedChess(bool share, CrowdedChess& e)
00251 : Example(share,e), n(e.n) {
00252 s.update(this, share, e.s);
00253 queens.update(this, share, e.queens);
00254 rooks.update(this, share, e.rooks);
00255 knights.update(this, share, e.knights);
00256 }
00257
00259 virtual Space*
00260 copy(bool share) {
00261 return new CrowdedChess(share,*this);
00262 }
00263
00265 virtual void
00266 print(void) {
00267 MiniModel::Matrix<IntVarArray> m(s, n);
00268 char *names = static_cast<char*>(Memory::malloc(PMAX));
00269 const char *sep = n < 8 ? "\t\t" : "\t";
00270 names[E] = '.'; names[Q] = 'Q'; names[R] = 'R';
00271 names[B] = 'B'; names[K] = 'K';
00272
00273 for (int r = 0; r < n; ++r){
00274
00275 std::cout << '\t';
00276 for (int c = 0; c < n; ++c) {
00277 std::cout << names[m(r, c).val()];
00278 }
00279
00280 for (int p = 0; p < PMAX; ++p) {
00281 if (p == E) continue;
00282 std::cout << sep;
00283 for (int c = 0; c < n; ++c) {
00284 if (m(r, c).val() == p) std::cout << names[p];
00285 else std::cout << names[E];
00286 }
00287 }
00288 std::cout << std::endl;
00289 }
00290 std::cout << std::endl;
00291 }
00292 };
00293
00297 int
00298 main(int argc, char** argv) {
00299 Options o("CrowdedChess");
00300 o.icl = ICL_DOM;
00301 o.size = 7;
00302 o.parse(argc,argv);
00303 if(o.size < 5) {
00304 std::cerr << "Error: Size must be at least 5" << std::endl;
00305 return 1;
00306 }
00307 Example::run<CrowdedChess,DFS>(o);
00308 return 0;
00309 }
00310
00311
00312