Generated on Mon Jul 6 18:09:01 2009 for Gecode by doxygen 1.5.9

queen-armies.cpp

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: 2009-05-12 14:06:14 +0200 (Tue, 12 May 2009) $ by $Author: schulte $
00011  *     $Revision: 9061 $
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 <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     // Basic rules of the model
00102     for (int i = n*n; i--; ) {
00103       // w[i] means that no blacks are allowed on A[i]
00104       dom(*this, U, SRT_DISJ, A[i], w[i]);
00105       // Make sure blacks and whites are disjoint.
00106       post(*this, tt(!w[i] || !b[i]));
00107       // If i in U, then b[i] has a piece.
00108       dom(*this, U, SRT_SUP, i, b[i]);
00109     }
00110 
00111     // Connect optimization variable to number of pieces
00112     linear(*this, w, IRT_EQ, q);
00113     linear(*this, b, IRT_GQ, q);
00114 
00115     // Connect cardinality of U to the number of black pieces.
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   // Set up the A-sets
00271   // A[i] will contain the values attacked by a queen at position i
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 // STATISTICS: example-any