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
00039 #include "examples/support.hh"
00040 #include "gecode/set.hh"
00041 #include "gecode/minimodel.hh"
00042
00043
00048 IntSet *A;
00049
00069 class QueenArmies : public Example {
00070 public:
00071 const int n;
00072 SetVar U,
00073 W;
00074 BoolVarArray w,
00075 b;
00076 IntVar q;
00077
00079 enum {
00080 BRANCH_NAIVE,
00081 BRANCH_SPECIFIC
00082 };
00084 QueenArmies(const SizeOptions& opt) :
00085 n(opt.size()),
00086 U(this, IntSet::empty, IntSet(0, n*n)),
00087 W(this, IntSet::empty, IntSet(0, n*n)),
00088 w(this, n*n, 0, 1),
00089 b(this, n*n, 0, 1),
00090 q(this, 0, n*n)
00091 {
00092
00093 for (int i = n*n; i--; ) {
00094
00095 dom(this, U, SRT_DISJ, A[i], w[i]);
00096
00097 post(this, tt(!w[i] || !b[i]));
00098
00099 dom(this, U, SRT_SUP, i, b[i]);
00100 }
00101
00102
00103 linear(this, w, IRT_EQ, q);
00104 linear(this, b, IRT_GQ, q);
00105
00106
00107 IntVar unknowns(this, 0, n*n);
00108 cardinality(this, U, unknowns);
00109 post(this, q <= unknowns);
00110 linear(this, b, IRT_EQ, unknowns);
00111
00112 if (opt.branching() == BRANCH_NAIVE) {
00113 branch(this, w, INT_VAR_NONE, INT_VAL_MAX);
00114 branch(this, b, INT_VAR_NONE, INT_VAL_MAX);
00115 } else {
00116 QueenBranch::post(this);
00117 assign(this, b, INT_ASSIGN_MAX);
00118 }
00119 }
00121 QueenArmies(bool share, QueenArmies& s)
00122 : Example(share,s), n(s.n)
00123 {
00124 U.update(this, share, s.U);
00125 W.update(this, share, s.W);
00126 w.update(this, share, s.w);
00127 b.update(this, share, s.b);
00128 q.update(this, share, s.q);
00129 }
00130
00131 virtual Space*
00132 copy(bool share) {
00133 return new QueenArmies(share,*this);
00134 }
00135
00136 void
00137 constrain(Space* s) {
00138 rel(this, q, IRT_GR, static_cast<QueenArmies*>(s)->q.val());
00139 }
00140
00141
00142 virtual void
00143 print(std::ostream& os) {
00144 os << '\t';
00145 for (int i = 0; i < n*n; ++i) {
00146 if (w[i].assigned() && w[i].val()) os << "W";
00147 else if (b[i].assigned() && b[i].val()) os << "B";
00148 else if (!w[i].assigned() && !b[i].assigned()) os << " ";
00149 else os << ".";
00150 if ((i+1)%n == 0) os << std::endl << (i!=(n*n-1)?"\t":"");
00151 }
00152 os << "Number of white queens: " << q << std::endl << std::endl;
00153 }
00154
00162 class QueenBranch : Branching {
00164 mutable int pos;
00165
00166 QueenBranch(Space* home)
00167 : Branching(home), pos(-1) {}
00168
00169 QueenBranch(Space* home, bool share, QueenBranch& b)
00170 : Branching(home, share, b), pos(b.pos) {}
00171
00172 public:
00174 virtual bool status(const Space* home) const {
00175 const QueenArmies *q = static_cast<const QueenArmies*>(home);
00176 int maxsize = -1;
00177 pos = -1;
00178
00179 for (int i = q->n*q->n; i--; ) {
00180 if (q->w[i].assigned()) continue;
00181 IntSetRanges ai(A[i]);
00182 SetVarUnknownRanges qU(q->U);
00183 Iter::Ranges::Inter<IntSetRanges, SetVarUnknownRanges> r(ai, qU);
00184 int size = Iter::Ranges::size(r);
00185 if (size > maxsize) {
00186 maxsize = size;
00187 pos = i;
00188 }
00189 }
00190 if (pos == -1) return false;
00191 return true;
00192 }
00194 virtual BranchingDesc* description(const Space*) const {
00195 assert(pos != -1);
00196 return new PosValDesc<bool,2>(this, pos, true);
00197 }
00201 virtual ExecStatus commit(Space* home, const BranchingDesc* d,
00202 unsigned int a) {
00203 QueenArmies *q = static_cast<QueenArmies*>(home);
00204 const PosValDesc<bool,2> *pvd = static_cast<const PosValDesc<bool,2>*>(d);
00205 bool val = a == 0 ? pvd->val() : !pvd->val();
00206 return me_failed(Int::BoolView(q->w[pvd->pos()]).eq(q, val))
00207 ? ES_FAILED
00208 : ES_OK;
00209 }
00211 virtual Actor* copy(Space *home, bool share) {
00212 return new (home) QueenBranch(home, share, *this);
00213 }
00215 virtual const char* name(void) const {
00216 return "QueenBranching";
00217 }
00218
00219 static void post(QueenArmies* home) {
00220 (void) new (home) QueenBranch(home);
00221 }
00222 };
00223 };
00224
00229 int pos(int i, int j, int n) {
00230 return i*n + j;
00231 }
00232
00236 int
00237 main(int argc, char* argv[]) {
00238 SizeOptions opt("QueenArmies");
00239 opt.size(6);
00240 opt.branching(QueenArmies::BRANCH_SPECIFIC);
00241 opt.branching(QueenArmies::BRANCH_NAIVE, "naive");
00242 opt.branching(QueenArmies::BRANCH_SPECIFIC, "specific");
00243 opt.solutions(0);
00244 opt.parse(argc,argv);
00245
00246
00247
00248 int n = opt.size();
00249 A = new IntSet[n*n];
00250 int *p = new int[std::max(n*n, 25)];
00251 int pn = 0;
00252 for (int i = n; i--; ) {
00253 for (int j = n; j--; ) {
00254 int dir[][2] = {
00255 { 0, 1},
00256 { 1, 1},
00257 { 1, 0},
00258 { 0, -1},
00259 {-1, -1},
00260 {-1, 0},
00261 { 1, -1},
00262 {-1, 1}
00263 };
00264 p[pn++] = pos(i, j, n);
00265 for (int k = 8; k--; ) {
00266 for (int l = 0; l < n
00267 && 0 <= (i+l*dir[k][0]) && (i+l*dir[k][0]) < n
00268 && 0 <= (j+l*dir[k][1]) && (j+l*dir[k][1]) < n; ++l) {
00269 p[pn++] = pos(i+l*dir[k][0], j+l*dir[k][1], n);
00270 }
00271 }
00272
00273 A[pos(i, j, n)] = IntSet(p, pn);
00274
00275 pn = 0;
00276 }
00277 }
00278 delete [] p;
00279
00280 Example::run<QueenArmies,BAB,SizeOptions>(opt);
00281 return 0;
00282 }
00283
00284