this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Mikael Lagerkvist <lagerkvist@gecode.org> 5 * Christian Schulte <schulte@gecode.org> 6 * 7 * Copyright: 8 * Mikael Lagerkvist, 2008 9 * Christian Schulte, 2001 10 * 11 * This file is part of Gecode, the generic constraint 12 * development environment: 13 * http://www.gecode.org 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining 16 * a copy of this software and associated documentation files (the 17 * "Software"), to deal in the Software without restriction, including 18 * without limitation the rights to use, copy, modify, merge, publish, 19 * distribute, sublicense, and/or sell copies of the Software, and to 20 * permit persons to whom the Software is furnished to do so, subject to 21 * the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 * 34 */ 35 36#include <gecode/driver.hh> 37#include <gecode/int.hh> 38#include <gecode/minimodel.hh> 39 40#if defined(GECODE_HAS_QT) && defined(GECODE_HAS_GIST) 41#include <QtGui> 42#if QT_VERSION >= 0x050000 43#include <QtWidgets> 44#endif 45#endif 46 47using namespace Gecode; 48 49 50/** \brief Custom brancher for knight's tours using Warnsdorff's rule 51 * 52 * This class implements Warnsdorff's rule for finding knight's 53 * tours. The next position is choosen by taking the jump that 54 * minimizes the number of alternatives in the next step. 55 * 56 * \relates Knights 57 */ 58class Warnsdorff : public Brancher { 59protected: 60 /// Views of the brancher 61 ViewArray<Int::IntView> x; 62 /// Next variable to branch on 63 mutable int start; 64 /// %Choice 65 class Choice : public Gecode::Choice { 66 public: 67 /// Position of variable 68 int pos; 69 /// Value of variable 70 int val; 71 /** Initialize choice for brancher \a b, position \a pos0, 72 * and value \a val0. 73 */ 74 Choice(const Brancher& b, int pos0, int val0) 75 : Gecode::Choice(b,2), pos(pos0), val(val0) {} 76 /// Archive into \a e 77 virtual void archive(Archive& e) const { 78 Gecode::Choice::archive(e); 79 e << pos << val; 80 } 81 }; 82 83 /// Construct brancher 84 Warnsdorff(Home home, ViewArray<Int::IntView>& xv) 85 : Brancher(home), x(xv), start(0) {} 86 /// Copy constructor 87 Warnsdorff(Space& home, Warnsdorff& b) 88 : Brancher(home, b), start(b.start) { 89 x.update(home, b.x); 90 } 91public: 92 /// Check status of brancher, return true if alternatives left 93 virtual bool status(const Space&) const { 94 // A path to follow can be at most x.size() long 95 for (int n=x.size(); n--; ) { 96 if (!x[start].assigned()) 97 return true; 98 // Follow path of assigned variables 99 start = x[start].val(); 100 } 101 return false; 102 } 103 /// Return choice 104 virtual Gecode::Choice* choice(Space&) { 105 Int::ViewValues<Int::IntView> iv(x[start]); 106 int n = iv.val(); 107 unsigned int min = x[n].size(); 108 ++iv; 109 // Choose the value with the fewest neighbors 110 while (iv()) { 111 if (x[iv.val()].size() < min) { 112 n = iv.val(); 113 min = x[n].size(); 114 } 115 ++iv; 116 } 117 return new Choice(*this, start, n); 118 } 119 /// Return choice 120 virtual Choice* choice(const Space&, Archive& e) { 121 int pos, val; 122 e >> pos >> val; 123 return new Choice(*this, pos, val); 124 } 125 /// Perform commit for choice \a _c and alternative \a a 126 virtual ExecStatus commit(Space& home, const Gecode::Choice& _c, 127 unsigned int a) { 128 const Choice& c = static_cast<const Choice&>(_c); 129 if (a == 0) 130 return me_failed(x[c.pos].eq(home, c.val)) ? ES_FAILED : ES_OK; 131 else 132 return me_failed(x[c.pos].nq(home, c.val)) ? ES_FAILED : ES_OK; 133 } 134 /// Print explanation 135 virtual void print(const Space&, const Gecode::Choice& _c, 136 unsigned int a, 137 std::ostream& o) const { 138 const Choice& c = static_cast<const Choice&>(_c); 139 o << "x[" << c.pos << "] " 140 << ((a == 0) ? "=" : "!=") 141 << " " << c.val; 142 } 143 /// Copy brancher 144 virtual Actor* copy(Space& home) { 145 return new (home) Warnsdorff(home, *this); 146 } 147 /// Post brancher 148 static void post(Home home, const IntVarArgs& x) { 149 ViewArray<Int::IntView> xv(home, x); 150 (void) new (home) Warnsdorff(home, xv); 151 } 152 /// Delete brancher and return its size 153 virtual size_t dispose(Space&) { 154 return sizeof(*this); 155 } 156}; 157 158 159/// Base-class for knight's tour example 160class Knights : public Script { 161public: 162 /// Size of board 163 const int n; 164 /// Maps board field to successor field 165 IntVarArray succ; 166 /// Propagation to use for model 167 enum { 168 PROP_REIFIED, ///< Use reified constraints 169 PROP_CIRCUIT ///< Use single circuit constraints 170 }; 171 /// Branching to use for model 172 enum { 173 BRANCH_NAIVE, ///< Use naive, lexicographical branching 174 BRANCH_WARNSDORFF, ///< Use Warnsdorff's rule 175 }; 176 /// Return field at position \a x, \a y 177 int f(int x, int y) const { 178 return x + y*n; 179 } 180 /// Return x coordinate at field \a f 181 int x(int f) const { 182 return f % n; 183 } 184 /// Return y coordinate at field \a f 185 int y(int f) const { 186 return f / n; 187 } 188 /// Compute set of neighbour fields 189 IntSet neighbors(int i) { 190 static const int moves[8][2] = { 191 {-2,-1}, {-2,1}, {-1,-2}, {-1,2}, {1,-2}, {1,2}, {2,-1}, {2,1} 192 }; 193 int nbs[8]; int n_nbs = 0; 194 for (int m=0; m<8; m++) { 195 int nx = x(i) + moves[m][0], ny = y(i) + moves[m][1]; 196 if ((nx >= 0) && (nx < n) && (ny >= 0) && (ny < n)) 197 nbs[n_nbs++] = f(nx,ny); 198 } 199 return IntSet(nbs,n_nbs); 200 } 201 /// Constructor 202 Knights(const SizeOptions& opt) 203 : Script(opt), n(opt.size()), succ(*this,n*n,0,n*n-1) { 204 switch (opt.branching()) { 205 case BRANCH_NAIVE: 206 branch(*this, succ, INT_VAR_NONE(), INT_VAL_MIN()); 207 break; 208 case BRANCH_WARNSDORFF: 209 Warnsdorff::post(*this, succ); 210 break; 211 } 212 } 213 /// Constructor for cloning \a s 214 Knights(Knights& s) : Script(s), n(s.n) { 215 succ.update(*this, s.succ); 216 } 217 /// Print board 218 virtual void 219 print(std::ostream& os) const { 220 int* jump = new int[n*n]; 221 { 222 int j=0; 223 for (int i=0; i<n*n; i++) { 224 jump[j]=i; j=succ[j].min(); 225 } 226 } 227 os << "\t"; 228 for (int i = 0; i < n; i++) { 229 for (int j = 0; j < n; j++) { 230 os.width(3); 231 os << jump[f(i,j)] << " "; 232 } 233 os << std::endl << "\t"; 234 } 235 os << std::endl; 236 delete [] jump; 237 } 238}; 239 240/** 241 * \brief %Example: n-Knight's tour (simple model) 242 * 243 * Fill an n times n chess board with knight's moves such that 244 * the knight does a full tour (last move reaches first move 245 * again). The formulation is due to Gert Smolka. 246 * 247 * \ingroup Example 248 * 249 */ 250class KnightsReified : public Knights { 251public: 252 KnightsReified(const SizeOptions& opt) : Knights(opt) { 253 const int nn = n*n; 254 255 // Map knight to its predecessor of succesor on board 256 IntVarArgs jump(nn); 257 IntVarArgs pred(nn); 258 259 for (int i = nn; i--; ) { 260 IntVar p(*this,0,nn-1); pred[i]=p; 261 IntVar j(*this,0,nn-1); jump[i]=j; 262 } 263 264 // Place the first two knights 265 rel(*this, jump[f(0,0)], IRT_EQ, 0); 266 rel(*this, jump[f(1,2)], IRT_EQ, 1); 267 268 distinct(*this, jump, opt.ipl()); 269 channel(*this, succ, pred, opt.ipl()); 270 271 for (int f = 0; f < nn; f++) { 272 IntSet ds = neighbors(f); 273 for (IntSetValues i(ds); i(); ++i) 274 rel(*this, 275 expr(*this, (jump[i.val()]-jump[f] == 1)), 276 BOT_XOR, 277 expr(*this, (jump[i.val()]-jump[f] == 1-nn)), 278 expr(*this, (succ[f] == i.val()))); 279 dom(*this, pred[f], ds); 280 dom(*this, succ[f], ds); 281 rel(*this, succ[f], IRT_NQ, pred[f]); 282 } 283 } 284 /// Constructor for cloning \a s 285 KnightsReified(KnightsReified& s) : Knights(s) {} 286 /// Copy during cloning 287 virtual Space* 288 copy(void) { 289 return new KnightsReified(*this); 290 } 291}; 292 293/** 294 * \brief %Example: n-%Knights tour (model using circuit) 295 * 296 * Fill an n times n chess board with knights such that the 297 * knights do a full tour by knights move (last knight reaches 298 * first knight again). 299 * 300 * \ingroup Example 301 * 302 */ 303class KnightsCircuit : public Knights { 304public: 305 KnightsCircuit(const SizeOptions& opt) : Knights(opt) { 306 // Fix the first move 307 rel(*this, succ[0], IRT_EQ, f(1,2)); 308 309 circuit(*this, succ, opt.ipl()); 310 311 for (int f = 0; f < n*n; f++) 312 dom(*this, succ[f], neighbors(f)); 313 } 314 /// Constructor for cloning \a s 315 KnightsCircuit(KnightsCircuit& s) : Knights(s) {} 316 /// Copy during cloning 317 virtual Space* 318 copy(void) { 319 return new KnightsCircuit(*this); 320 } 321}; 322 323/* 324 * Just to fool some scripts: 325 * \brief %Example: n-Knight's tour 326 * 327 */ 328 329#if defined(GECODE_HAS_QT) && defined(GECODE_HAS_GIST) 330/// Inspector showing knight moves on a chess board 331class KnightsInspector : public Gist::Inspector { 332protected: 333 /// The graphics scene displaying the board 334 QGraphicsScene* scene; 335 /// The window containing the graphics scene 336 QMainWindow* mw; 337 /// The size of a field on the board 338 static const int unit = 30; 339public: 340 /// Constructor 341 KnightsInspector(void) : scene(nullptr), mw(nullptr) {} 342 /// Inspect space \a s 343 virtual void inspect(const Space& s) { 344 const Knights& k = static_cast<const Knights&>(s); 345 346 if (!scene) 347 initialize(); 348 QList <QGraphicsItem*> itemList = scene->items(); 349 foreach (QGraphicsItem* i, scene->items()) { 350 scene->removeItem(i); 351 delete i; 352 } 353 354 for (int i=0; i<k.n; i++) { 355 for (int j=0; j<k.n; j++) { 356 scene->addRect(i*unit,j*unit,unit,unit); 357 358 QPen pen(Qt::black, 2); 359 if (!k.succ[i*k.n+j].assigned()) { 360 pen.setColor(Qt::red); 361 pen.setStyle(Qt::DotLine); 362 pen.setWidth(0); 363 } 364 for (IntVarValues xv(k.succ[i*k.n+j]); xv(); ++xv) { 365 int ky = xv.val() % k.n; 366 int kx = xv.val() / k.n; 367 scene->addLine(i*unit+unit/2,j*unit+unit/2, 368 kx*unit+unit/2,ky*unit+unit/2, 369 pen); 370 } 371 372 } 373 } 374 mw->show(); 375 } 376 377 /// Set up main window 378 void initialize(void) { 379 mw = new QMainWindow(); 380 scene = new QGraphicsScene(); 381 QGraphicsView* view = new QGraphicsView(scene); 382 view->setRenderHints(QPainter::Antialiasing); 383 mw->setCentralWidget(view); 384 mw->setAttribute(Qt::WA_QuitOnClose, false); 385 mw->setAttribute(Qt::WA_DeleteOnClose, false); 386 QAction* closeWindow = new QAction("Close window", mw); 387 closeWindow->setShortcut(QKeySequence("Ctrl+W")); 388 mw->connect(closeWindow, SIGNAL(triggered()), 389 mw, SLOT(close())); 390 mw->addAction(closeWindow); 391 } 392 393 /// Name of the inspector 394 virtual std::string name(void) { return "Board"; } 395 /// Finalize inspector 396 virtual void finalize(void) { 397 delete mw; 398 mw = nullptr; 399 } 400}; 401#endif 402 403/** \brief Main-function 404 * \relates Knights 405 */ 406int 407main(int argc, char* argv[]) { 408 SizeOptions opt("Knights"); 409 opt.iterations(100); 410 opt.size(8); 411 opt.propagation(Knights::PROP_CIRCUIT); 412 opt.propagation(Knights::PROP_REIFIED, "reified"); 413 opt.propagation(Knights::PROP_CIRCUIT, "circuit"); 414 opt.branching(Knights::BRANCH_NAIVE); 415 opt.branching(Knights::BRANCH_NAIVE, "naive"); 416 opt.branching(Knights::BRANCH_WARNSDORFF, "warnsdorff"); 417 418#if defined(GECODE_HAS_QT) && defined(GECODE_HAS_GIST) 419 KnightsInspector ki; 420 opt.inspect.click(&ki); 421#endif 422 423 opt.parse(argc,argv); 424 425 if (opt.propagation() == Knights::PROP_REIFIED) { 426 Script::run<KnightsReified,DFS,SizeOptions>(opt); 427 } else { 428 Script::run<KnightsCircuit,DFS,SizeOptions>(opt); 429 } 430 return 0; 431} 432 433// STATISTICS: example-any 434