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 <gecode/driver.hh>
00040 #include <gecode/int.hh>
00041 #include <gecode/minimodel.hh>
00042 #include <gecode/set.hh>
00043
00044 using namespace Gecode;
00045
00050 IntSet* A;
00051
00071 class QueenArmies : public MaximizeScript {
00072 public:
00073 const int n;
00074 SetVar U,
00075 W;
00076 BoolVarArray w,
00077 b;
00078 IntVar q;
00079
00081 enum {
00082 BRANCH_NAIVE,
00083 BRANCH_SPECIFIC
00084 };
00085
00087 enum {
00088 SEARCH_BAB,
00089 SEARCH_RESTART
00090 };
00091
00093 QueenArmies(const SizeOptions& opt) :
00094 n(opt.size()),
00095 U(*this, IntSet::empty, IntSet(0, n*n)),
00096 W(*this, IntSet::empty, IntSet(0, n*n)),
00097 w(*this, n*n, 0, 1),
00098 b(*this, n*n, 0, 1),
00099 q(*this, 0, n*n)
00100 {
00101
00102 for (int i = n*n; i--; ) {
00103
00104 dom(*this, U, SRT_DISJ, A[i], w[i]);
00105
00106 post(*this, tt(!w[i] || !b[i]));
00107
00108 dom(*this, U, SRT_SUP, i, b[i]);
00109 }
00110
00111
00112 linear(*this, w, IRT_EQ, q);
00113 linear(*this, b, IRT_GQ, q);
00114
00115
00116 IntVar unknowns(*this, 0, n*n);
00117 cardinality(*this, U, unknowns);
00118 post(*this, q <= unknowns);
00119 linear(*this, b, IRT_EQ, unknowns);
00120
00121 if (opt.branching() == BRANCH_NAIVE) {
00122 branch(*this, w, INT_VAR_NONE, INT_VAL_MAX);
00123 branch(*this, b, INT_VAR_NONE, INT_VAL_MAX);
00124 } else {
00125 QueenBranch::post(*this);
00126 assign(*this, b, INT_ASSIGN_MAX);
00127 }
00128 }
00130 QueenArmies(bool share, QueenArmies& s)
00131 : MaximizeScript(share,s), n(s.n) {
00132 U.update(*this, share, s.U);
00133 W.update(*this, share, s.W);
00134 w.update(*this, share, s.w);
00135 b.update(*this, share, s.b);
00136 q.update(*this, share, s.q);
00137 }
00139 virtual Space*
00140 copy(bool share) {
00141 return new QueenArmies(share,*this);
00142 }
00144 virtual IntVar cost(void) const {
00145 return q;
00146 }
00148 virtual void
00149 print(std::ostream& os) const {
00150 os << '\t';
00151 for (int i = 0; i < n*n; ++i) {
00152 if (w[i].assigned() && w[i].val()) os << "W";
00153 else if (b[i].assigned() && b[i].val()) os << "B";
00154 else if (!w[i].assigned() && !b[i].assigned()) os << " ";
00155 else os << ".";
00156 if ((i+1)%n == 0) os << std::endl << (i!=(n*n-1)?"\t":"");
00157 }
00158 os << "Number of white queens: " << q << std::endl << std::endl;
00159 }
00160
00168 class QueenBranch : Branching {
00169 private:
00171 mutable int pos;
00173 class Description : public BranchingDesc {
00174 public:
00176 int pos;
00178 bool val;
00182 Description(const Branching& b, unsigned int a, int pos0, bool val0)
00183 : BranchingDesc(b,a), pos(pos0), val(val0) {}
00185 virtual size_t size(void) const {
00186 return sizeof(Description);
00187 }
00188 };
00189
00191 QueenBranch(Space& home)
00192 : Branching(home), pos(-1) {}
00194 QueenBranch(Space& home, bool share, QueenBranch& b)
00195 : Branching(home, share, b), pos(b.pos) {}
00196
00197 public:
00199 virtual bool status(const Space& home) const {
00200 const QueenArmies& q = static_cast<const QueenArmies&>(home);
00201 int maxsize = -1;
00202 pos = -1;
00203
00204 for (int i = q.n*q.n; i--; ) {
00205 if (q.w[i].assigned()) continue;
00206 IntSetRanges ai(A[i]);
00207 SetVarUnknownRanges qU(q.U);
00208 Iter::Ranges::Inter<IntSetRanges, SetVarUnknownRanges> r(ai, qU);
00209 int size = Iter::Ranges::size(r);
00210 if (size > maxsize) {
00211 maxsize = size;
00212 pos = i;
00213 }
00214 }
00215 if (pos == -1) return false;
00216 return true;
00217 }
00219 virtual BranchingDesc* description(Space&) {
00220 assert(pos != -1);
00221 return new Description(*this, 2, pos, true);
00222 }
00226 virtual ExecStatus commit(Space& home, const BranchingDesc& d,
00227 unsigned int a) {
00228 QueenArmies& q = static_cast<QueenArmies&>(home);
00229 const Description& pvd = static_cast<const Description&>(d);
00230 bool val = a == 0 ? pvd.val : !pvd.val;
00231 return me_failed(Int::BoolView(q.w[pvd.pos]).eq(q, val))
00232 ? ES_FAILED
00233 : ES_OK;
00234 }
00236 virtual Actor* copy(Space& home, bool share) {
00237 return new (home) QueenBranch(home, share, *this);
00238 }
00240 static void post(QueenArmies& home) {
00241 (void) new (home) QueenBranch(home);
00242 }
00243 };
00244 };
00245
00250 int pos(int i, int j, int n) {
00251 return i*n + j;
00252 }
00253
00257 int
00258 main(int argc, char* argv[]) {
00259 SizeOptions opt("QueenArmies");
00260 opt.size(6);
00261 opt.branching(QueenArmies::BRANCH_SPECIFIC);
00262 opt.branching(QueenArmies::BRANCH_NAIVE, "naive");
00263 opt.branching(QueenArmies::BRANCH_SPECIFIC, "specific");
00264 opt.search(QueenArmies::SEARCH_BAB);
00265 opt.search(QueenArmies::SEARCH_BAB, "bab");
00266 opt.search(QueenArmies::SEARCH_RESTART, "restart");
00267 opt.solutions(0);
00268 opt.parse(argc,argv);
00269
00270
00271
00272 int n = opt.size();
00273 A = new IntSet[n*n];
00274 int *p = new int[std::max(n*n, 25)];
00275 int pn = 0;
00276 for (int i = n; i--; ) {
00277 for (int j = n; j--; ) {
00278 int dir[][2] = {
00279 { 0, 1},
00280 { 1, 1},
00281 { 1, 0},
00282 { 0, -1},
00283 {-1, -1},
00284 {-1, 0},
00285 { 1, -1},
00286 {-1, 1}
00287 };
00288 p[pn++] = pos(i, j, n);
00289 for (int k = 8; k--; ) {
00290 for (int l = 0; l < n
00291 && 0 <= (i+l*dir[k][0]) && (i+l*dir[k][0]) < n
00292 && 0 <= (j+l*dir[k][1]) && (j+l*dir[k][1]) < n; ++l) {
00293 p[pn++] = pos(i+l*dir[k][0], j+l*dir[k][1], n);
00294 }
00295 }
00296
00297 A[pos(i, j, n)] = IntSet(p, pn);
00298
00299 pn = 0;
00300 }
00301 }
00302 delete [] p;
00303
00304
00305 switch (opt.search()) {
00306 case QueenArmies::SEARCH_BAB:
00307 MaximizeScript::run<QueenArmies,BAB,SizeOptions>(opt); break;
00308 case QueenArmies::SEARCH_RESTART:
00309 MaximizeScript::run<QueenArmies,Restart,SizeOptions>(opt); break;
00310 }
00311 return 0;
00312 }
00313
00314