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