/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Mikael Lagerkvist * Christian Schulte * * Copyright: * Mikael Lagerkvist, 2008 * Christian Schulte, 2001 * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #include #if defined(GECODE_HAS_QT) && defined(GECODE_HAS_GIST) #include #if QT_VERSION >= 0x050000 #include #endif #endif using namespace Gecode; /** \brief Custom brancher for knight's tours using Warnsdorff's rule * * This class implements Warnsdorff's rule for finding knight's * tours. The next position is choosen by taking the jump that * minimizes the number of alternatives in the next step. * * \relates Knights */ class Warnsdorff : public Brancher { protected: /// Views of the brancher ViewArray x; /// Next variable to branch on mutable int start; /// %Choice class Choice : public Gecode::Choice { public: /// Position of variable int pos; /// Value of variable int val; /** Initialize choice for brancher \a b, position \a pos0, * and value \a val0. */ Choice(const Brancher& b, int pos0, int val0) : Gecode::Choice(b,2), pos(pos0), val(val0) {} /// Archive into \a e virtual void archive(Archive& e) const { Gecode::Choice::archive(e); e << pos << val; } }; /// Construct brancher Warnsdorff(Home home, ViewArray& xv) : Brancher(home), x(xv), start(0) {} /// Copy constructor Warnsdorff(Space& home, Warnsdorff& b) : Brancher(home, b), start(b.start) { x.update(home, b.x); } public: /// Check status of brancher, return true if alternatives left virtual bool status(const Space&) const { // A path to follow can be at most x.size() long for (int n=x.size(); n--; ) { if (!x[start].assigned()) return true; // Follow path of assigned variables start = x[start].val(); } return false; } /// Return choice virtual Gecode::Choice* choice(Space&) { Int::ViewValues iv(x[start]); int n = iv.val(); unsigned int min = x[n].size(); ++iv; // Choose the value with the fewest neighbors while (iv()) { if (x[iv.val()].size() < min) { n = iv.val(); min = x[n].size(); } ++iv; } return new Choice(*this, start, n); } /// Return choice virtual Choice* choice(const Space&, Archive& e) { int pos, val; e >> pos >> val; return new Choice(*this, pos, val); } /// Perform commit for choice \a _c and alternative \a a virtual ExecStatus commit(Space& home, const Gecode::Choice& _c, unsigned int a) { const Choice& c = static_cast(_c); if (a == 0) return me_failed(x[c.pos].eq(home, c.val)) ? ES_FAILED : ES_OK; else return me_failed(x[c.pos].nq(home, c.val)) ? ES_FAILED : ES_OK; } /// Print explanation virtual void print(const Space&, const Gecode::Choice& _c, unsigned int a, std::ostream& o) const { const Choice& c = static_cast(_c); o << "x[" << c.pos << "] " << ((a == 0) ? "=" : "!=") << " " << c.val; } /// Copy brancher virtual Actor* copy(Space& home) { return new (home) Warnsdorff(home, *this); } /// Post brancher static void post(Home home, const IntVarArgs& x) { ViewArray xv(home, x); (void) new (home) Warnsdorff(home, xv); } /// Delete brancher and return its size virtual size_t dispose(Space&) { return sizeof(*this); } }; /// Base-class for knight's tour example class Knights : public Script { public: /// Size of board const int n; /// Maps board field to successor field IntVarArray succ; /// Propagation to use for model enum { PROP_REIFIED, ///< Use reified constraints PROP_CIRCUIT ///< Use single circuit constraints }; /// Branching to use for model enum { BRANCH_NAIVE, ///< Use naive, lexicographical branching BRANCH_WARNSDORFF, ///< Use Warnsdorff's rule }; /// Return field at position \a x, \a y int f(int x, int y) const { return x + y*n; } /// Return x coordinate at field \a f int x(int f) const { return f % n; } /// Return y coordinate at field \a f int y(int f) const { return f / n; } /// Compute set of neighbour fields IntSet neighbors(int i) { static const int moves[8][2] = { {-2,-1}, {-2,1}, {-1,-2}, {-1,2}, {1,-2}, {1,2}, {2,-1}, {2,1} }; int nbs[8]; int n_nbs = 0; for (int m=0; m<8; m++) { int nx = x(i) + moves[m][0], ny = y(i) + moves[m][1]; if ((nx >= 0) && (nx < n) && (ny >= 0) && (ny < n)) nbs[n_nbs++] = f(nx,ny); } return IntSet(nbs,n_nbs); } /// Constructor Knights(const SizeOptions& opt) : Script(opt), n(opt.size()), succ(*this,n*n,0,n*n-1) { switch (opt.branching()) { case BRANCH_NAIVE: branch(*this, succ, INT_VAR_NONE(), INT_VAL_MIN()); break; case BRANCH_WARNSDORFF: Warnsdorff::post(*this, succ); break; } } /// Constructor for cloning \a s Knights(Knights& s) : Script(s), n(s.n) { succ.update(*this, s.succ); } /// Print board virtual void print(std::ostream& os) const { int* jump = new int[n*n]; { int j=0; for (int i=0; i(s); if (!scene) initialize(); QList itemList = scene->items(); foreach (QGraphicsItem* i, scene->items()) { scene->removeItem(i); delete i; } for (int i=0; iaddRect(i*unit,j*unit,unit,unit); QPen pen(Qt::black, 2); if (!k.succ[i*k.n+j].assigned()) { pen.setColor(Qt::red); pen.setStyle(Qt::DotLine); pen.setWidth(0); } for (IntVarValues xv(k.succ[i*k.n+j]); xv(); ++xv) { int ky = xv.val() % k.n; int kx = xv.val() / k.n; scene->addLine(i*unit+unit/2,j*unit+unit/2, kx*unit+unit/2,ky*unit+unit/2, pen); } } } mw->show(); } /// Set up main window void initialize(void) { mw = new QMainWindow(); scene = new QGraphicsScene(); QGraphicsView* view = new QGraphicsView(scene); view->setRenderHints(QPainter::Antialiasing); mw->setCentralWidget(view); mw->setAttribute(Qt::WA_QuitOnClose, false); mw->setAttribute(Qt::WA_DeleteOnClose, false); QAction* closeWindow = new QAction("Close window", mw); closeWindow->setShortcut(QKeySequence("Ctrl+W")); mw->connect(closeWindow, SIGNAL(triggered()), mw, SLOT(close())); mw->addAction(closeWindow); } /// Name of the inspector virtual std::string name(void) { return "Board"; } /// Finalize inspector virtual void finalize(void) { delete mw; mw = nullptr; } }; #endif /** \brief Main-function * \relates Knights */ int main(int argc, char* argv[]) { SizeOptions opt("Knights"); opt.iterations(100); opt.size(8); opt.propagation(Knights::PROP_CIRCUIT); opt.propagation(Knights::PROP_REIFIED, "reified"); opt.propagation(Knights::PROP_CIRCUIT, "circuit"); opt.branching(Knights::BRANCH_NAIVE); opt.branching(Knights::BRANCH_NAIVE, "naive"); opt.branching(Knights::BRANCH_WARNSDORFF, "warnsdorff"); #if defined(GECODE_HAS_QT) && defined(GECODE_HAS_GIST) KnightsInspector ki; opt.inspect.click(&ki); #endif opt.parse(argc,argv); if (opt.propagation() == Knights::PROP_REIFIED) { Script::run(opt); } else { Script::run(opt); } return 0; } // STATISTICS: example-any