00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
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
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
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
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
00223