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

black-hole.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-08-25 10:45:30 +0200 (Fri, 25 Aug 2006) $ by $Author: zayenz $
00010  *     $Revision: 3569 $
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 #include "examples/support.hh"
00023 #include "gecode/minimodel.hh"
00024 #include "gecode/support/random.hh"
00025 
00026 #include <vector>
00027 #include <algorithm>
00028 #include <sstream>
00029 
00030 namespace {
00031   using std::vector;
00032 
00034   vector<vector<int> > layout;
00036   vector<int> layer, pile;
00037 
00039   void generate(int seed) {
00040     // The layout consists of 17 piles of 3 cards each
00041     layout = vector<vector<int> >(17, vector<int>(3));
00042     vector<int> nums(51);
00043     for (int i = 51; i--; ) nums[i] = i+1;
00044     Support::RandomGenerator rnd(seed+1);
00045     std::random_shuffle(nums.begin(), nums.end(), rnd);
00046     int pos = 0;
00047     for (int i = 17; i--; )
00048       for (int j = 3; j--; )
00049         layout[i][j] = nums[pos++];
00050 
00051     // Location-information for each value
00052     layer = vector<int>(52);
00053     pile  = vector<int>(52);
00054     for (int i = 17; i--; ) {
00055       for (int j = 3; j--; ) {
00056         layer[layout[i][j]] = j;
00057         pile[ layout[i][j]] = i;
00058       }
00059     }
00060   }
00061 }
00062 
00063 
00067 class BlackHoleBranch : Branching {
00068   ViewArray<Int::IntView> x;
00069   mutable int pos, val;
00070  
00071   BlackHoleBranch(Space* home, ViewArray<Int::IntView>& xv) 
00072     : Branching(home), x(xv), pos(-1), val(-1) {}
00073   BlackHoleBranch(Space* home, bool share, BlackHoleBranch& b) 
00074     : Branching(home, share, b), pos(b.pos), val(b.val) {
00075     x.update(home, share, b.x);
00076   }
00077   
00078 public:
00079   virtual bool status(const Space* home) const {
00080     for (pos = 0; pos < x.size(); ++pos) {
00081       if (!x[pos].assigned()) {
00082         int w = 4;
00083         for (Int::ViewValues<Int::IntView> vals(x[pos]); vals(); ++vals) {
00084           if (layer[vals.val()] < w) {
00085             val = vals.val();
00086             if ((w = layer[vals.val()]) == 0) break;
00087           }
00088         }
00089         return true;
00090       }
00091     }
00092     // No non-assigned variables left
00093     return false;
00094   }
00095   virtual BranchingDesc* description(const Space* home) const {
00096     assert(pos >= 0 && pos < x.size() && val >= 1 && val < 52);
00097     return new PosValDesc<int>(this, pos, val);
00098   }
00099   virtual ExecStatus commit(Space* home, const BranchingDesc* d, unsigned int a) {
00100     const PosValDesc<int> *desc = static_cast<const PosValDesc<int>*>(d);
00101     pos = val = -1;
00102     if (a)
00103       return me_failed(x[desc->pos()].nq(home, desc->val())) ? ES_FAILED : ES_OK;
00104     else 
00105       return me_failed(x[desc->pos()].eq(home, desc->val())) ? ES_FAILED : ES_OK;
00106   }
00107   virtual Actor* copy(Space *home, bool share) {
00108     return new (home) BlackHoleBranch(home, share, *this);
00109   }
00110   static void post(Space* home, IntVarArgs x) {
00111     ViewArray<Int::IntView> xv(home, x);
00112     (void) new (home) BlackHoleBranch(home, xv);
00113   }
00114 };
00115 
00116 
00133 class BlackHole : public Example {
00134 protected:
00135   IntVarArray x, 
00136     y; 
00137 
00139   std::string
00140   card(int val) {
00141     const char* suit = "SCHD";
00142     std::ostringstream o;
00143     o << std::setw(2) << (1 + (val%13)) << suit[val/13];
00144     return o.str();
00145   }
00146 
00147 public:
00149   BlackHole(const Options& opt) 
00150     : x(this, 52, 0,51), y(this, 52, 0,51) 
00151   {
00152     // Black ace at bottom
00153     rel(this, x[0], IRT_EQ, 0);
00154 
00155     // x is order and y is placement
00156     channel(this, x, y, opt.icl);
00157 
00158     // Build table for accessing the rank of a card
00159     IntArgs modtable(52);
00160     for (int i = 0; i < 52; ++i) {
00161       modtable[i] = i%13;
00162     }
00163     // The placement rules: the absolute value of the difference
00164     // between two consecutive cards is 1 or 12.
00165     for (int i = 0; i < 51; ++i) {
00166       IntVar x1(this, 0, 12), x2(this, 0, 12);
00167       element(this, modtable, x[i], x1, ICL_DOM);
00168       element(this, modtable, x[i+1], x2, ICL_DOM);
00169       const int dr[2] = {1, 12};
00170       IntVar diff(this, IntSet(dr, 2));
00171       post(this, abs(this, minus(this, x1, x2, ICL_DOM), ICL_DOM) 
00172            == diff, ICL_DOM);
00173     }
00174 
00175     // Set up instance
00176     for (int i = 17; i--; ) {
00177       for (int j = 2; j--; ) {
00178         // A card must be played before the one under it.
00179         post(this, y[layout[i][j]] < y[layout[i][j+1]]);
00180       }
00181     }
00182 
00183     // Compute and break the conditional symmetries that are dependent
00184     // on the current layout.
00185     if (!opt.naive) {
00186       // For all ranks
00187       for (int r = 13; r--; ) {
00188         // For all pairs of suits
00189         for (int s1 = 4; s1--; ) {
00190           for (int s2 = s1; s2--; ) {
00191             int c1 = 13*s1 + r,
00192               c2 = 13*s2 + r;
00193             // The ace of spades is already placed
00194             if (c1 == 0 || c2 == 0) continue;
00195             // Piles are handled by the rules of the game
00196             if (pile[c1] == pile[c2]) continue;
00197             // Get the right order of the cards
00198             int o1 = c1, o2 = c2;
00199             if (pile[c1] > pile[c2] && layer[c2] >= layer[c1]) 
00200               std::swap(o1, o2);
00201             // cond is the condition for the symmetry
00202             BoolVarArgs ba(4);
00203             int pos = 0;
00204             // Both cards played after the ones on top of them
00205             for (int i = 0; i < layer[o1]; ++i)
00206               ba[pos++] = post(this, ~(y[layout[pile[o1]][i]] < y[o2]));
00207             for (int i = 0; i < layer[o2]; ++i)
00208               ba[pos++] = post(this, ~(y[layout[pile[o2]][i]] < y[o1]));
00209             // Both cards played before the ones under them
00210             for (int i = layer[o1]+1; i < 3; ++i)
00211               ba[pos++] = post(this, ~(y[o2] < y[layout[pile[o1]][i]]));
00212             for (int i = layer[o2]+1; i < 3; ++i)
00213               ba[pos++] = post(this, ~(y[o1] < y[layout[pile[o2]][i]]));
00214             // Cond holds when all the above holds
00215             BoolVar cond(this, 0, 1);
00216             bool_and(this, ba, cond);
00217             
00218             // If cond is fulfilled, then we can order the cards
00219             // cond -> (y[o1] < y[o2])
00220             post(this, tt(!cond || ~(y[o1] < y[o2])));
00221           }
00222         }
00223       }
00224     }
00225     
00226     // Install custom branching
00227     BlackHoleBranch::post(this, x);      
00228   }
00230   virtual void
00231   print(void) {
00232     std::cout << "Layout:" << std::endl;
00233     for (int i = 0; i < 17; i++) {
00234       for (int j = 0; j < 3; j++)
00235         std::cout << card(layout[i][j]) << " ";
00236       if ((i+1) % 3 == 0) 
00237         std::cout << std::endl;
00238       else
00239         std::cout << "\t";
00240     }
00241     std::cout << std::endl << std::endl;
00242     
00243     std::cout << "Solution:" << std::endl;
00244     for (int i = 0; i < 52; ++i) {
00245       std::cout << card(x[i].min()) << " ";
00246       if ((i + 1) % 13 == 0)
00247         std::cout << std::endl;
00248     }
00249     std::cout << std::endl;
00250     std::cout << std::endl;
00251   }
00252 
00254   BlackHole(bool share, BlackHole& s) : Example(share,s) {
00255     x.update(this, share, s.x);
00256     y.update(this, share, s.y);
00257   }
00259   virtual Space*
00260   copy(bool share) {
00261     return new BlackHole(share,*this);
00262   }
00263 };
00264 
00268 int
00269 main(int argc, char** argv) {
00270   Options opt("Black Hole patience");
00271   opt.solutions  = 1;
00272   opt.naive      = false;
00273   opt.icl        = ICL_DOM;
00274   opt.parse(argc,argv);
00275   // Generates the new board
00276   generate(opt.size);
00277   Example::run<BlackHole,DFS>(opt);
00278   return 0;
00279 }
00280 
00281 // STATISTICS: example-any