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 #include <gecode/minimodel.hh>
00041
00042 #ifdef GECODE_HAS_SET_VARS
00043 #include <gecode/set.hh>
00044 #endif
00045
00046 #include <string>
00047 #include <cmath>
00048 #include <cctype>
00049
00050 using namespace Gecode;
00051
00052 #include <examples/sudoku-instances.hh>
00053
00055 class Sudoku : public Script {
00056 protected:
00058 const int n;
00059 public:
00060 #ifdef GECODE_HAS_SET_VARS
00061
00062 enum {
00063 MODEL_INT,
00064 MODEL_SET,
00065 MODEL_MIXED
00066 };
00067 #endif
00068
00069 enum {
00070 BRANCH_NONE,
00071 BRANCH_SIZE,
00072 BRANCH_SIZE_DEGREE,
00073 BRANCH_SIZE_AFC,
00074 BRANCH_AFC
00075 };
00076
00078 Sudoku(const SizeOptions& opt)
00079 : Script(opt),
00080 n(example_size(examples[opt.size()])) {}
00081
00083 Sudoku(Sudoku& s) : Script(s), n(s.n) {}
00084
00085 };
00086
00092 class SudokuInt : virtual public Sudoku {
00093 protected:
00095 IntVarArray x;
00096 public:
00097 #ifdef GECODE_HAS_SET_VARS
00098
00099 enum {
00100 PROP_NONE,
00101 PROP_SAME,
00102 };
00103 #endif
00104
00105 SudokuInt(const SizeOptions& opt)
00106 : Sudoku(opt), x(*this, n*n*n*n, 1, n*n) {
00107 const int nn = n*n;
00108 Matrix<IntVarArray> m(x, nn, nn);
00109
00110
00111 for (int i=0; i<nn; i++) {
00112 distinct(*this, m.row(i), opt.ipl());
00113 distinct(*this, m.col(i), opt.ipl());
00114 }
00115
00116
00117 for (int i=0; i<nn; i+=n) {
00118 for (int j=0; j<nn; j+=n) {
00119 distinct(*this, m.slice(i, i+n, j, j+n), opt.ipl());
00120 }
00121 }
00122
00123
00124 for (int i=0; i<nn; i++)
00125 for (int j=0; j<nn; j++)
00126 if (int v = sudokuField(examples[opt.size()], nn, i, j))
00127 rel(*this, m(i,j), IRT_EQ, v );
00128
00129 #ifdef GECODE_HAS_SET_VARS
00130 if (opt.propagation() == PROP_SAME) {
00131
00132 for (int b=0; b<n; b++) {
00133 int b1c = 0;
00134 int b2c = 0;
00135 IntVarArgs bc1(nn-n);
00136 IntVarArgs bc2(nn-n);
00137 IntVarArgs br1(nn-n);
00138 IntVarArgs br2(nn-n);
00139 for (int i=0; i<n; i++)
00140 for (int j=0; j<n; j++) {
00141 b1c = 0; b2c = 0;
00142 for (int k=0; k<n; k++) {
00143 if (k != j) {
00144 IntVarArgs bc1s = block_col(m, b, i, k);
00145 IntVarArgs br1s = block_row(m, b, i, k);
00146 for (int count=0; count<n; count++) {
00147 bc1[b1c] = bc1s[count];
00148 br1[b1c] = br1s[count];
00149 ++b1c;
00150 }
00151 }
00152 if (k != i) {
00153 IntVarArgs bc2s = block_col(m, b, k, j);
00154 IntVarArgs br2s = block_row(m, b, k, j);
00155 for (int count=0; count<n; count++) {
00156 bc2[b2c] = bc2s[count];
00157 br2[b2c] = br2s[count];
00158 ++b2c;
00159 }
00160 }
00161 }
00162 same(*this, nn, bc1, bc2);
00163 same(*this, nn, br1, br2);
00164 }
00165 }
00166 }
00167 #endif
00168 if (opt.branching() == BRANCH_NONE) {
00169 branch(*this, x, INT_VAR_NONE(), INT_VAL_SPLIT_MIN());
00170 } else if (opt.branching() == BRANCH_SIZE) {
00171 branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN());
00172 } else if (opt.branching() == BRANCH_SIZE_DEGREE) {
00173 branch(*this, x, INT_VAR_DEGREE_SIZE_MAX(), INT_VAL_SPLIT_MIN());
00174 } else if (opt.branching() == BRANCH_SIZE_AFC) {
00175 branch(*this, x, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_SPLIT_MIN());
00176 } else if (opt.branching() == BRANCH_AFC) {
00177 branch(*this, x, INT_VAR_AFC_MAX(opt.decay()), INT_VAL_SPLIT_MIN());
00178 }
00179 }
00180
00182 SudokuInt(SudokuInt& s) : Sudoku(s) {
00183 x.update(*this, s.x);
00184 }
00185
00187 virtual Space*
00188 copy(void) {
00189 return new SudokuInt(*this);
00190 }
00191
00193 virtual void
00194 print(std::ostream& os) const {
00195 os << " ";
00196 for (int i = 0; i<n*n*n*n; i++) {
00197 if (x[i].assigned()) {
00198 if (x[i].val()<10)
00199 os << x[i] << " ";
00200 else
00201 os << (char)(x[i].val()+'A'-10) << " ";
00202 }
00203 else
00204 os << ". ";
00205 if((i+1)%(n*n) == 0)
00206 os << std::endl << " ";
00207 }
00208 os << std::endl;
00209 }
00210
00211 #ifdef GECODE_HAS_SET_VARS
00212 private:
00214 void same(Space& home, int nn, IntVarArgs a, IntVarArgs b) {
00215 SetVar u(home, IntSet::empty, 1, nn);
00216 rel(home, SOT_DUNION, a, u);
00217 rel(home, SOT_DUNION, b, u);
00218 }
00219
00221 IntVarArgs
00222 block_col(Matrix<IntVarArray> m, int bc, int i, int j) {
00223 return m.slice(bc*n+i, bc*n+i+1, j*n, (j+1)*n);
00224 }
00225
00227 IntVarArgs
00228 block_row(Matrix<IntVarArray> m, int br, int i, int j) {
00229 return m.slice(j*n, (j+1)*n, br*n+i, br*n+i+1);
00230 }
00231 #endif
00232 };
00233
00234 #ifdef GECODE_HAS_SET_VARS
00235
00240 class SudokuSet : virtual public Sudoku {
00241 protected:
00243 SetVarArray y;
00244 public:
00246 SudokuSet(const SizeOptions& opt)
00247 : Sudoku(opt),
00248 y(*this,n*n,IntSet::empty,1,n*n*n*n,
00249 static_cast<unsigned int>(n*n),static_cast<unsigned int>(n*n)) {
00250
00251 const int nn = n*n;
00252
00253 Region r;
00254 IntSet* row = r.alloc<IntSet>(nn);
00255 IntSet* col = r.alloc<IntSet>(nn);
00256 IntSet* block = r.alloc<IntSet>(nn);
00257
00258
00259 int* dsc = r.alloc<int>(nn);
00260 for (int i=0; i<nn; i++) {
00261 row[i] = IntSet((i*nn)+1, (i+1)*nn);
00262
00263 for (int j=0; j<nn; j++) {
00264 dsc[j] = (j*nn)+1+i;
00265 }
00266 col[i] = IntSet(dsc, nn);
00267 }
00268
00269
00270 int* dsb_arr = r.alloc<int>(nn);
00271 for (int i=0; i<n; i++) {
00272 for (int j=0; j<n; j++) {
00273
00274 for (int ii=0; ii<n; ii++) {
00275 for (int jj=0; jj<n; jj++) {
00276 dsb_arr[ii*n+jj] = j*nn*n+i*n+jj*nn+ii+1;
00277 }
00278 }
00279 block[i*n+j] = IntSet(dsb_arr, nn);
00280 }
00281 }
00282
00283 IntSet full(1, nn*nn);
00284
00285 rel(*this, SOT_DUNION, y, SetVar(*this, full, full));
00286
00287
00288
00289 for (int i=0; i<nn; i++)
00290 for (int j=0; j<nn; j++) {
00291 SetVar inter_row(*this, IntSet::empty, full, 1U, 1U);
00292 rel(*this, y[i], SOT_INTER, row[j], SRT_EQ, inter_row);
00293 SetVar inter_col(*this, IntSet::empty, full, 1U, 1U);
00294 rel(*this, y[i], SOT_INTER, col[j], SRT_EQ, inter_col);
00295 SetVar inter_block(*this, IntSet::empty, full, 1U, 1U);
00296 rel(*this, y[i], SOT_INTER, block[j], SRT_EQ, inter_block);
00297 }
00298
00299
00300 for (int i=0; i<nn; i++)
00301 for (int j=0; j<nn; j++)
00302 if (int idx = sudokuField(examples[opt.size()], nn, i, j))
00303 dom(*this, y[idx-1], SRT_SUP, (i+1)+(j*nn) );
00304
00305 if (opt.branching() == BRANCH_NONE) {
00306 branch(*this, y, SET_VAR_NONE(), SET_VAL_MIN_INC());
00307 } else if (opt.branching() == BRANCH_SIZE) {
00308 branch(*this, y, SET_VAR_SIZE_MIN(), SET_VAL_MIN_INC());
00309 } else if (opt.branching() == BRANCH_SIZE_DEGREE) {
00310 branch(*this, y, SET_VAR_DEGREE_SIZE_MAX(), SET_VAL_MIN_INC());
00311 } else if (opt.branching() == BRANCH_SIZE_AFC) {
00312 branch(*this, y, SET_VAR_AFC_SIZE_MAX(opt.decay()), SET_VAL_MIN_INC());
00313 } else if (opt.branching() == BRANCH_AFC) {
00314 branch(*this, y, SET_VAR_AFC_MAX(opt.decay()), SET_VAL_MIN_INC());
00315 }
00316 }
00317
00319 SudokuSet(SudokuSet& s) : Sudoku(s) {
00320 y.update(*this, s.y);
00321 }
00322
00324 virtual Space*
00325 copy(void) {
00326 return new SudokuSet(*this);
00327 }
00328
00330 virtual void
00331 print(std::ostream& os) const {
00332 os << '\t';
00333 for (int i = 0; i<n*n*n*n; i++) {
00334 for (int j=0; j<n*n; j++) {
00335 if (y[j].contains(i+1)) {
00336 if (j+1<10)
00337 os << j+1 << " ";
00338 else
00339 os << (char)(j+1+'A'-10) << " ";
00340 break;
00341 }
00342 }
00343 if((i+1)%(n*n) == 0)
00344 os << std::endl << '\t';
00345 }
00346 os << std::endl;
00347 }
00348 };
00349
00350
00357 class SudokuMixed : public SudokuInt, public SudokuSet {
00358 public:
00360 SudokuMixed(const SizeOptions& opt)
00361 : Sudoku(opt), SudokuInt(opt), SudokuSet(opt) {
00362 const int nn = n*n;
00363
00364 IntSet is0(0,0);
00365 SetVar dummySet0(*this, is0, is0);
00366 IntVar dummyInt0(*this, 0, 0);
00367 SetVarArgs ys(nn+1);
00368 ys[0] = dummySet0;
00369 for (int i=0; i<nn; i++)
00370 ys[i+1] = y[i];
00371 IntVarArgs xs(nn*nn+1);
00372 xs[0] = dummyInt0;
00373 for (int i=0; i<nn*nn; i++)
00374 xs[i+1] = x[i];
00375
00376 channel(*this, xs, ys);
00377
00378 IntArgs values(nn);
00379 for (int i=0; i<nn; i++)
00380 values[i] = i+1;
00381 count(*this, x, IntSet(nn,nn), values, IPL_DOM);
00382 }
00383
00385 SudokuMixed(SudokuMixed& s)
00386 : Sudoku(s), SudokuInt(s), SudokuSet(s) {}
00387
00389 virtual Space*
00390 copy(void) {
00391 return new SudokuMixed(*this);
00392 }
00393
00395 virtual void print(std::ostream& os) const { SudokuInt::print(os); }
00396
00397 };
00398
00399 #endif
00400
00404 int
00405 main(int argc, char* argv[]) {
00406 SizeOptions opt("Sudoku");
00407 opt.size(0);
00408 opt.ipl(IPL_DOM);
00409 opt.solutions(1);
00410 #ifdef GECODE_HAS_SET_VARS
00411 opt.model(Sudoku::MODEL_INT);
00412 opt.model(Sudoku::MODEL_INT, "int", "use integer constraints");
00413 opt.model(Sudoku::MODEL_SET, "set", "use set constraints");
00414 opt.model(Sudoku::MODEL_MIXED, "mixed",
00415 "use both integer and set constraints");
00416 opt.propagation(SudokuInt::PROP_NONE);
00417 opt.propagation(SudokuInt::PROP_NONE, "none", "no additional constraints");
00418 opt.propagation(SudokuInt::PROP_SAME, "same",
00419 "additional \"same\" constraint for integer model");
00420 #endif
00421 opt.branching(Sudoku::BRANCH_SIZE_AFC);
00422 opt.branching(Sudoku::BRANCH_NONE, "none", "none");
00423 opt.branching(Sudoku::BRANCH_SIZE, "size", "min size");
00424 opt.branching(Sudoku::BRANCH_SIZE_DEGREE, "sizedeg", "min size over degree");
00425 opt.branching(Sudoku::BRANCH_SIZE_AFC, "sizeafc", "min size over afc");
00426 opt.branching(Sudoku::BRANCH_AFC, "afc", "maximum afc");
00427 opt.parse(argc,argv);
00428 if (opt.size() >= n_examples) {
00429 std::cerr << "Error: size must be between 0 and "
00430 << n_examples-1 << std::endl;
00431 return 1;
00432 }
00433 #ifdef GECODE_HAS_SET_VARS
00434 switch (opt.model()) {
00435 case Sudoku::MODEL_INT:
00436 Script::run<SudokuInt,DFS,SizeOptions>(opt);
00437 break;
00438 case Sudoku::MODEL_SET:
00439 Script::run<SudokuSet,DFS,SizeOptions>(opt);
00440 break;
00441 case Sudoku::MODEL_MIXED:
00442 Script::run<SudokuMixed,DFS,SizeOptions>(opt);
00443 break;
00444 }
00445 #else
00446 Script::run<SudokuInt,DFS,SizeOptions>(opt);
00447 #endif
00448 return 0;
00449 }
00450
00451