Generated on Mon Aug 25 11:35:33 2008 for Gecode by doxygen 1.5.6

queen-armies.cc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Mikael Lagerkvist, 2006
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-02-05 10:57:39 +0100 (Tue, 05 Feb 2008) $ by $Author: zayenz $
00011  *     $Revision: 6053 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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     // Basic rules of the model
00093     for (int i = n*n; i--; ) {
00094       // w[i] means that no blacks are allowed on A[i]
00095       dom(this, U, SRT_DISJ, A[i], w[i]);
00096       // Make sure blacks and whites are disjoint.
00097       post(this, tt(!w[i] || !b[i]));
00098       // If i in U, then b[i] has a piece.
00099       dom(this, U, SRT_SUP, i, b[i]);
00100     }
00101 
00102     // Connect optimization variable to number of pieces
00103     linear(this, w, IRT_EQ, q);
00104     linear(this, b, IRT_GQ, q);
00105 
00106     // Connect cardinality of U to the number of black pieces.
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     // Construct branching
00166     QueenBranch(Space* home)
00167       : Branching(home), pos(-1) {}
00168     // Constructor for cloning
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   // Set up the A-sets
00247   // A[i] will contain the values attacked by a queen at position i
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 // STATISTICS: example-any