Generated on Wed Nov 1 15:04:28 2006 for Gecode by doxygen 1.4.5

queen-armies.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Mikael Lagerkvist, 2006
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-10-25 10:29:03 +0200 (Wed, 25 Oct 2006) $ by $Author: tack $
00010  *     $Revision: 3783 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
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     // Basic rules of the model
00071     for (int i = n*n; i--; ) {
00072       // w[i] means that no blacks are allowed on A[i]
00073       dom(this, U, SRT_DISJ, A[i], w[i]);
00074       // Make sure blacks and whites are disjoint.
00075       post(this, w[i] + b[i] <= 1);
00076       // If i in U, then b[i] has a piece.
00077       dom(this, U, SRT_SUP, i, b[i]);
00078     }
00079 
00080     // Connect optimization variable to number of pieces
00081     linear(this, w, IRT_EQ, q);
00082     linear(this, b, IRT_GQ, q);
00083 
00084     // Connect cardinality of U to the number of black pieces.
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   // Set up the A-sets
00203   // A[i] will contain the values attacked by a queen at position i
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 // STATISTICS: example-any