Generated on Wed Nov 1 15:04:27 2006 for Gecode by doxygen 1.4.5

crowded-chess.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2001
00008  *     Mikael Lagerkvist, 2005
00009  *
00010  *  Last modified:
00011  *     $Date: 2006-08-04 16:06:52 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00012  *     $Revision: 3517 $
00013  *
00014  *  This file is part of Gecode, the generic constraint
00015  *  development environment:
00016  *     http://www.gecode.org
00017  *
00018  *  See the file "LICENSE" for information on usage and
00019  *  redistribution of this file, and for a
00020  *     DISCLAIMER OF ALL WARRANTIES.
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   // Is (i,j) a valid position on the board?
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     // Basic model
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     // Integer variables for use with the element constraint
00171     IntVar queen(this, Q, Q), rook(this, R, R);
00172 
00173     // Collect rows and columns for handling rooks and queens.
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       //Connect (queens|rooks)[i] to the row it is in
00183       element(this, aa, queens[i], queen, ICL_DOM);
00184       element(this, aa,  rooks[i],  rook, ICL_DOM);
00185     }
00186 
00187     // N-queens constraints
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     // N-rooks constraints
00196     distinct(this,  rooks, ICL_DOM);
00197 
00198     // Collect diagonals for handling queens and bishops
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     // Handle knigths
00220     //Connect knigths to board
00221     for(int i = n*n; i--; )
00222       knights[i] = post(this, ~(s[i] == K));
00223     knight_constraints();
00224 
00225 
00226     // ***********************
00227     // Redundant constraints
00228     // ***********************
00229 
00230     // Queens and rooks not in the same place
00231     // Faster than going through the channeled board-connection
00232     for (int i = n; i--; ) {
00233       rel(this, queens[i], IRT_NQ, rooks[i]);
00234     }
00235 
00236     // Place bishops in two corners (from Schimpf and Hansens solution)
00237     // Avoids some symmetries of the problem
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     // Branchings
00244     // ***********************
00245     //Place each piece in turn
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       // Print main board
00275       std::cout << '\t';
00276       for (int c = 0; c < n; ++c) {
00277         std::cout << names[m(r, c).val()];
00278       }
00279       // Print each piece on its own
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 // STATISTICS: example-any
00312