Generated on Mon Jul 6 18:09:01 2009 for Gecode by doxygen 1.5.9

knights.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2001
00008  *
00009  *  Last modified:
00010  *     $Date: 2009-04-02 20:58:46 +0200 (Thu, 02 Apr 2009) $ by $Author: schulte $
00011  *     $Revision: 8649 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/driver.hh>
00039 #include <gecode/int.hh>
00040 #include <gecode/minimodel.hh>
00041 
00042 using namespace Gecode;
00043 
00045 class Knights : public Script {
00046 protected:
00048   const int n;
00050   IntVarArray succ;
00051 public:
00053   enum {
00054     PROP_REIFIED, 
00055     PROP_CIRCUIT  
00056   };
00058   int
00059   field(int x, int y) const {
00060     return x*n+y;
00061   }
00063   void
00064   neighbours(int f, int nbs[8], int& n_nbs) {
00065     n_nbs=0;
00066     int x = f / n;
00067     int y = f % n;
00068     for (int i=0;i<8;i++) {
00069       static const int moves[8][2] = {
00070         {-2,-1}, {-2,1}, {-1,-2}, {-1,2}, {1,-2}, {1,2}, {2,-1}, {2,1}
00071       };
00072       int nx=x+moves[i][0];
00073       int ny=y+moves[i][1];
00074       if ((nx >= 0) && (nx < n) && (ny >= 0) && (ny < n))
00075         nbs[n_nbs++]=field(nx,ny);
00076     }
00077   }
00079   Knights(const SizeOptions& opt)
00080     : n(opt.size()), succ(*this,n*n,0,n*n-1) {}
00082   Knights(bool share, Knights& s) : Script(share,s), n(s.n) {
00083     succ.update(*this, share, s.succ);
00084   }
00086   virtual void
00087   print(std::ostream& os) const {
00088     int* jump = new int[n*n];
00089     {
00090       int j=0;
00091       for (int i=0; i<n*n; i++) {
00092         jump[j]=i; j=succ[j].min();
00093       }
00094     }
00095     os << "\t";
00096     for (int i = 0; i < n; i++) {
00097       for (int j = 0; j < n; j++) {
00098         os.width(3);
00099         os << jump[field(i,j)] << " ";
00100         }
00101         os << std::endl << "\t";
00102     }
00103     os << std::endl;
00104     delete [] jump;
00105   }
00106 };
00107 
00118 class KnightsReified : public Knights {
00119 public:
00120   KnightsReified(const SizeOptions& opt) : Knights(opt) {
00121     const int nn = n*n;
00122 
00123     // Map knight to its predecessor of succesor on board
00124     IntVarArgs jump(nn);
00125     IntVarArgs pred(nn);
00126 
00127     for (int i = nn; i--; ) {
00128       IntVar p(*this,0,nn-1); pred[i]=p;
00129       IntVar j(*this,0,nn-1); jump[i]=j;
00130     }
00131 
00132     // Place the first two knights
00133     rel(*this, jump[field(0,0)], IRT_EQ, 0);
00134     rel(*this, jump[field(1,2)], IRT_EQ, 1);
00135 
00136     distinct(*this, jump, opt.icl());
00137     channel(*this, succ, pred, opt.icl());
00138 
00139     for (int f = 0; f < nn; f++) {
00140       // Array of neighbours
00141       int nbs[8]; int n_nbs = 0;
00142       neighbours(f, nbs, n_nbs);
00143       for (int i=n_nbs; i--; )
00144         rel(*this,
00145             post(*this, ~(jump[nbs[i]]-jump[f] == 1)),
00146             BOT_XOR,
00147             post(*this, ~(jump[nbs[i]]-jump[f] == 1-nn)),
00148             post(*this, ~(succ[f] == nbs[i])));
00149 
00150       IntSet ds(nbs, n_nbs);
00151       dom(*this, pred[f], ds);
00152       dom(*this, succ[f], ds);
00153       rel(*this, succ[f], IRT_NQ, pred[f]);
00154     }
00155     branch(*this, succ, INT_VAR_NONE, INT_VAL_MIN);
00156   }
00158   KnightsReified(bool share, KnightsReified& s) : Knights(share,s) {}
00160   virtual Space*
00161   copy(bool share) {
00162     return new KnightsReified(share,*this);
00163   }
00164 };
00165 
00176 class KnightsCircuit : public Knights {
00177 public:
00178   KnightsCircuit(const SizeOptions& opt) : Knights(opt) {
00179     // Fix the first move
00180     rel(*this, succ[0], IRT_EQ, field(1,2));
00181 
00182     circuit(*this, succ, opt.icl());
00183 
00184     for (int f = 0; f < n*n; f++) {
00185       // Array of neighbours
00186       int nbs[8]; int n_nbs = 0;
00187       neighbours(f, nbs, n_nbs);
00188       IntSet ds(nbs, n_nbs);
00189       dom(*this, succ[f], ds);
00190     }
00191     branch(*this, succ, INT_VAR_NONE, INT_VAL_MIN);
00192   }
00194   KnightsCircuit(bool share, KnightsCircuit& s) : Knights(share,s) {}
00196   virtual Space*
00197   copy(bool share) {
00198     return new KnightsCircuit(share,*this);
00199   }
00200 };
00201 
00205 int
00206 main(int argc, char* argv[]) {
00207   SizeOptions opt("Knights");
00208   opt.iterations(100);
00209   opt.size(8);
00210   opt.propagation(Knights::PROP_CIRCUIT);
00211   opt.propagation(Knights::PROP_REIFIED, "reified");
00212   opt.propagation(Knights::PROP_CIRCUIT, "circuit");
00213   opt.parse(argc,argv);
00214   if (opt.propagation() == Knights::PROP_REIFIED) {
00215     Script::run<KnightsReified,DFS,SizeOptions>(opt);
00216   } else {
00217     Script::run<KnightsCircuit,DFS,SizeOptions>(opt);
00218   }
00219   return 0;
00220 }
00221 
00222 // STATISTICS: example-any
00223