1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 *
6 * Copyright:
7 * Christian Schulte, 2011
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34 #include <gecode/driver.hh>
35 #include <gecode/int.hh>
36 #include <gecode/minimodel.hh>
37
38 using namespace Gecode;
39
40 /**
41 * \brief %Example: Dominating Queens
42 *
43 * Place a number of queens on a n times n chessboard such that
44 * each squares is either attacked or occupied by a queen.
45 *
46 * The model is taken from: C. Bessiere, E. Hebrard, B. Hnich,
47 * Z. Kiziltan, and T. Walsh, Filtering Algorithms for the NValue
48 * Constraint, Constraints, 11(4), 271-293, 2006.
49 *
50 * \ingroup Example
51 *
52 */
53 class DominatingQueens : public IntMinimizeScript {
54 protected:
55 /// Size of the board
56 const int n;
57 /// Fields on the board
58 IntVarArray b;
59 /// Number of queens
60 IntVar q;
61 /// Compute coordinate pair from \a x and \a y
xy(int x,int y) const62 int xy(int x, int y) const {
63 return y*n + x;
64 }
65 /// Compute x coordinate from pair \a xy
x(int xy) const66 int x(int xy) const {
67 return xy % n;
68 }
69 /// Compute y coordinate from pair \a xy
y(int xy) const70 int y(int xy) const {
71 return xy / n;
72 }
73 /// Compute set of fields that can be attacked by \a xy
attacked(int xy)74 IntSet attacked(int xy) {
75 IntArgs a;
76 for (int i=0; i<n; i++)
77 for (int j=0; j<n; j++)
78 if ((i == x(xy)) || // Same row
79 (j == y(xy)) || // Same column
80 (abs(i-x(xy)) == abs(j-y(xy)))) // Same diagonal
81 a << DominatingQueens::xy(i,j);
82 return IntSet(a);
83 }
84 public:
85 /// The actual problem
DominatingQueens(const SizeOptions & opt)86 DominatingQueens(const SizeOptions& opt)
87 : IntMinimizeScript(opt),
88 n(opt.size()), b(*this,n*n,0,n*n-1), q(*this,1,n) {
89
90 // Constrain field to the fields that can attack a field
91 for (int i=0; i<n*n; i++)
92 dom(*this, b[i], attacked(i));
93
94 // At most q queens can be placed
95 nvalues(*this, b, IRT_LQ, q);
96
97 /*
98 * According to: P. R. J. Östergard and W. D. Weakley, Values
99 * of Domination Numbers of the Queen's Graph, Electronic Journal
100 * of Combinatorics, 8:1-19, 2001, for n <= 120, the minimal number
101 * of queens is either ceil(n/2) or ceil(n/2 + 1).
102 */
103 if (n <= 120)
104 dom(*this, q, (n+1)/2, (n+1)/2 + 1);
105
106 branch(*this, b, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
107 // Try the easier solution first
108 branch(*this, q, INT_VAL_MAX());
109 }
110
111 /// Return cost
cost(void) const112 virtual IntVar cost(void) const {
113 return q;
114 }
115
116 /// Constructor for cloning \a s
DominatingQueens(DominatingQueens & s)117 DominatingQueens(DominatingQueens& s)
118 : IntMinimizeScript(s), n(s.n) {
119 b.update(*this, s.b);
120 q.update(*this, s.q);
121 }
122
123 /// Perform copying during cloning
124 virtual Space*
copy(void)125 copy(void) {
126 return new DominatingQueens(*this);
127 }
128
129 /// Print solution
130 virtual void
print(std::ostream & os) const131 print(std::ostream& os) const {
132 os << "\tNumber of Queens: " << q << std::endl;
133 os << "\tBoard: " << b << std::endl;
134 if (b.assigned()) {
135 // Print a nice board
136 bool* placed = new bool[n*n];
137 for (int i=0; i<n*n; i++)
138 placed[i] = false;
139 for (int i=0; i<n*n; i++)
140 placed[b[i].val()] = true;
141 for (int j=0; j<n; j++) {
142 std::cout << "\t\t";
143 for (int i=0; i<n; i++)
144 std::cout << (placed[xy(i,j)] ? 'Q' : '.') << ' ';
145 std::cout << std::endl;
146 }
147 delete [] placed;
148 }
149 os << std::endl;
150 }
151 };
152
153 /** \brief Main-function
154 * \relates DominatingQueens
155 */
156 int
main(int argc,char * argv[])157 main(int argc, char* argv[]) {
158 SizeOptions opt("DominatingQueens");
159 opt.size(7);
160 opt.solutions(0);
161 opt.parse(argc,argv);
162 IntMinimizeScript::run<DominatingQueens,BAB,SizeOptions>(opt);
163 return 0;
164 }
165
166 // STATISTICS: example-any
167
168