00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "examples/support.hh"
00024 #include "gecode/set.hh"
00025 #include "gecode/minimodel.hh"
00026
00027
00032 IntSet *A;
00033
00053 class QueenArmies : public Example {
00054 public:
00055 const int n;
00056 SetVar U,
00057 W;
00058 BoolVarArray w,
00059 b;
00060 IntVar q;
00061
00062 QueenArmies(const Options& o) :
00063 n(o.size),
00064 U(this, IntSet::empty, IntSet(0, n*n)),
00065 W(this, IntSet::empty, IntSet(0, n*n)),
00066 w(this, n*n, 0, 1),
00067 b(this, n*n, 0, 1),
00068 q(this, 0, n*n)
00069 {
00070
00071 for (int i = n*n; i--; ) {
00072
00073 dom(this, U, SRT_DISJ, A[i], w[i]);
00074
00075 post(this, w[i] + b[i] <= 1);
00076
00077 dom(this, U, SRT_SUP, i, b[i]);
00078 }
00079
00080
00081 linear(this, w, IRT_EQ, q);
00082 linear(this, b, IRT_GQ, q);
00083
00084
00085 IntVar unknowns(this, 0, n*n);
00086 cardinality(this, U, unknowns);
00087 post(this, q <= unknowns);
00088 linear(this, b, IRT_EQ, unknowns);
00089
00090 if (o.naive) {
00091 branch(this, w, BVAR_NONE, BVAL_MAX);
00092 branch(this, b, BVAR_NONE, BVAL_MAX);
00093 } else {
00094 QueenBranch::post(this);
00095 assign(this, b, AVAL_MAX);
00096 }
00097 }
00098
00099 QueenArmies(bool share, QueenArmies& s)
00100 : Example(share,s), n(s.n)
00101 {
00102 U.update(this, share, s.U);
00103 W.update(this, share, s.W);
00104 w.update(this, share, s.w);
00105 b.update(this, share, s.b);
00106 q.update(this, share, s.q);
00107 }
00108
00109 virtual Space*
00110 copy(bool share) {
00111 return new QueenArmies(share,*this);
00112 }
00113
00114 void
00115 constrain(Space* s) {
00116 rel(this, q, IRT_GR, static_cast<QueenArmies*>(s)->q.val());
00117 }
00118
00119
00120 virtual void
00121 print(void) {
00122 std::cout << '\t';
00123 for (int i = 0; i < n*n; ++i) {
00124 if (w[i].val()) std::cout << "W";
00125 else if (b[i].val()) std::cout << "B";
00126 else std::cout << ".";
00127 if ((i+1)%n == 0) std::cout << std::endl << (i!=(n*n-1)?"\t":"");
00128 }
00129 std::cout << "Number of white queens: " << q << std::endl << std::endl;
00130 }
00131
00137 class QueenBranch : Branching {
00138 mutable int pos;
00139 QueenBranch(Space* home)
00140 : Branching(home), pos(-1) {}
00141 QueenBranch(Space* home, bool share, QueenBranch& b)
00142 : Branching(home, share, b), pos(b.pos) {}
00143
00144 public:
00145 virtual bool status(const Space* home) const {
00146 const QueenArmies *q = static_cast<const QueenArmies*>(home);
00147 int maxsize = -1;
00148 pos = -1;
00149
00150 for (int i = q->n*q->n; i--; ) {
00151 if (q->w[i].assigned()) continue;
00152 IntSetRanges ai(A[i]);
00153 SetVarUnknownRanges qU(q->U);
00154 Iter::Ranges::Inter<IntSetRanges, SetVarUnknownRanges> r(ai, qU);
00155 int size = Iter::Ranges::size(r);
00156 if (size > maxsize) {
00157 maxsize = size;
00158 pos = i;
00159 }
00160 }
00161 if (pos == -1) return false;
00162 return true;
00163 }
00164 virtual BranchingDesc* description(const Space*) const {
00165 assert(pos != -1);
00166 return new PosValDesc<bool>(this, pos, true);
00167 }
00168 virtual ExecStatus commit(Space* home, const BranchingDesc* d, unsigned int a) {
00169 QueenArmies *q = static_cast<QueenArmies*>(home);
00170 const PosValDesc<bool> *pvd = static_cast<const PosValDesc<bool>*>(d);
00171 bool val = a == 0 ? pvd->val() : !pvd->val();
00172 return me_failed(Int::BoolView(q->w[pvd->pos()]).eq(q, val))
00173 ? ES_FAILED
00174 : ES_OK;
00175 }
00176 virtual Actor* copy(Space *home, bool share) {
00177 return new (home) QueenBranch(home, share, *this);
00178 }
00179
00180 static void post(QueenArmies* home) {
00181 (void) new (home) QueenBranch(home);
00182 }
00183 };
00184 };
00185
00187 int pos(int i, int j, int n) {
00188 return i*n + j;
00189 }
00190
00194 int
00195 main(int argc, char** argv) {
00196 Options o("QueenArmies");
00197 o.size = 6;
00198 o.naive = false;
00199 o.solutions = 0;
00200 o.parse(argc,argv);
00201
00202
00203
00204 int n = o.size;
00205 A = new IntSet[n*n];
00206 int *p = new int[std::max(n*n, 25)];
00207 int pn = 0;
00208 for (int i = n; i--; ) {
00209 for (int j = n; j--; ) {
00210 int dir[][2] = {
00211 { 0, 1},
00212 { 1, 1},
00213 { 1, 0},
00214 { 0, -1},
00215 {-1, -1},
00216 {-1, 0},
00217 { 1, -1},
00218 {-1, 1}
00219 };
00220 p[pn++] = pos(i, j, n);
00221 for (int k = 8; k--; ) {
00222 for (int l = 0; l < n
00223 && 0 <= (i+l*dir[k][0]) && (i+l*dir[k][0]) < n
00224 && 0 <= (j+l*dir[k][1]) && (j+l*dir[k][1]) < n; ++l) {
00225 p[pn++] = pos(i+l*dir[k][0], j+l*dir[k][1], n);
00226 }
00227 }
00228
00229 A[pos(i, j, n)] = IntSet(p, pn);
00230
00231 pn = 0;
00232 }
00233 }
00234 delete [] p;
00235
00236 Example::run<QueenArmies,BAB>(o);
00237 return 0;
00238 }
00239
00240