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 #include "gecode/set/projectors.hh"
00039
00040 #include "gecode/support/buddy/bdd.h"
00041 #include <set>
00042
00043 using namespace Gecode::Set;
00044
00045 namespace Gecode {
00046
00050 class Formula::Node {
00051 private:
00053 unsigned int use;
00055 Node *left, *right;
00057 int signLeft, signRight;
00059 int x;
00061 Operator r;
00063 void fv(std::set<int>& s);
00064 public:
00066 Node(const int x);
00068 Node(Node* n0, int s0, Operator r, Node* n1, int s1);
00069
00071 void increment(void);
00073 bool decrement(void);
00074
00076 std::set<int> fv(void);
00078 bdd toBdd(void);
00079
00081 static void* operator new(size_t size);
00083 static void operator delete(void* p,size_t size);
00084 };
00085
00086
00087
00088
00089
00090
00091 forceinline void*
00092 Formula::Node::operator new(size_t size) {
00093 return Memory::malloc(size);
00094 }
00095
00096 forceinline void
00097 Formula::Node::operator delete(void* p, size_t) {
00098 Memory::free(p);
00099 }
00100
00101
00102 forceinline void
00103 Formula::Node::increment(void) {
00104 ++use;
00105 }
00106
00107 forceinline
00108 Formula::Node::Node(const int x) :
00109 use(1),
00110 left(NULL), right(NULL), signLeft(0), signRight(0), x(x) {}
00111
00112 forceinline
00113 Formula::Node::Node(Node* l, int sL, Operator o, Node* r, int sR) :
00114 use(1),
00115 left(l), right(r), signLeft(sL), signRight(sR), r(o) {
00116 if (left != NULL)
00117 left->increment();
00118 if (right != NULL)
00119 right->increment();
00120 }
00121
00122 bool
00123 Formula::Node::decrement(void) {
00124 if (--use == 0) {
00125 if (left != NULL && left->decrement())
00126 delete left;
00127 if (right != NULL && right->decrement())
00128 delete right;
00129 return true;
00130 }
00131 return false;
00132 }
00133
00134 void
00135 Formula::Node::fv(std::set<int>& s) {
00136 if (left==NULL)
00137 s.insert(x);
00138 else {
00139 left->fv(s);
00140 right->fv(s);
00141 }
00142 }
00143
00144 inline
00145 std::set<int>
00146 Formula::Node::fv(void) {
00147 std::set<int> s;
00148 fv(s);
00149 return s;
00150 }
00151
00152 bdd
00153 Formula::Node::toBdd(void) {
00154 if (left==NULL) {
00155 return bdd_ithvar(x);
00156 } else {
00157 bdd bl = left->toBdd(); bdd br = right->toBdd();
00158 if (signLeft == -1)
00159 bl = !bl;
00160 if (signRight == -1)
00161 br = !br;
00162
00163 switch (r) {
00164 case OR:
00165 return bl | br;
00166 case AND:
00167 return bl & br;
00168 case IMPL:
00169 return bl >> br;
00170 case EQUIV:
00171 return (bl >> br) & (br >> bl);
00172 default:
00173 assert(false);
00174 return bdd_false();
00175 }
00176 }
00177 }
00178
00179
00180
00181
00182
00183
00184 Formula::Formula(int v) : ax(new Node(v)), sign(1) {}
00185
00186 Formula::Formula(const Formula& f, int sf,
00187 Operator r,
00188 const Formula& g, int sg)
00189 : ax(new Node(f.ax,f.sign*sf,r,g.ax,g.sign*sg)), sign(1) {}
00190
00191 Formula::Formula(const Formula& f, int sign)
00192 : ax(f.ax), sign(f.sign*sign) {
00193 if (ax != NULL)
00194 ax->increment();
00195 }
00196
00197 Formula::Formula(const Formula& f)
00198 : ax(f.ax), sign(f.sign) {
00199 if (ax != NULL)
00200 ax->increment();
00201 }
00202
00203 const Formula&
00204 Formula::operator=(const Formula& f) {
00205 if (this != &f) {
00206 if ((ax != NULL) && ax->decrement())
00207 delete ax;
00208 ax = f.ax;
00209 sign = f.sign;
00210 if (ax != NULL)
00211 ax->increment();
00212 }
00213 return *this;
00214 }
00215
00216 Formula::~Formula(void) {
00217 if ((ax != NULL) && ax->decrement())
00218 delete ax;
00219 }
00220
00221 namespace {
00222
00224 SetExpr bddToSetExpr(const bdd& b) {
00225 if (b == bdd_true())
00226 return SetExpr(SetExpr(), -1);
00227 else if (b == bdd_false())
00228 return SetExpr();
00229
00230 SetExpr right = bddToSetExpr(bdd_high(b));
00231 SetExpr left = bddToSetExpr(bdd_low(b));
00232
00233 SetExpr selfRight, selfLeft;
00234
00235 int var = bdd_var(b);
00236
00237 if (bdd_high(b) == bdd_true()) {
00238 selfRight = SetExpr(var);
00239 selfLeft = left;
00240 } else if (bdd_low(b) == bdd_true()) {
00241 selfLeft = SetExpr(SetExpr(var), -1);
00242 selfRight = right;
00243 } else {
00244 selfRight = SetExpr(var) && right;
00245 selfLeft = SetExpr(SetExpr(var), -1) && left;
00246 }
00247
00248 if (bdd_high(b) == bdd_false())
00249 return selfLeft;
00250 if (bdd_low(b) == bdd_false())
00251 return selfRight;
00252
00253 return selfLeft || selfRight;
00254 }
00255
00256 }
00257
00258 ProjectorSet
00259 Formula::projectors(void) {
00260
00261
00262 if (ax == NULL)
00263 return ProjectorSet(0);
00264
00265
00266 std::set<int> s = ax->fv();
00267 int maxVar=0;
00268 for (std::set<int>::const_iterator i=s.begin(); i != s.end(); ++i) {
00269 maxVar = std::max(maxVar, *i);
00270 }
00271
00272 bool bddWasRunning = true;
00273
00274 if (!bdd_isrunning()) {
00275 bddWasRunning = false;
00276 bdd_init(1000, 1000);
00277 }
00278 if (bdd_varnum() < maxVar+1)
00279 bdd_setvarnum(maxVar+1);
00280
00281
00282 bdd f = ax->toBdd();
00283
00284 ProjectorSet p(s.size());
00285
00286
00287 for (std::set<int>::const_iterator i=s.begin(); i != s.end(); ++i) {
00288 bdd x = bdd_ithvar(*i);
00289
00290
00291 bdd psi1 = bdd_exist((! bdd_exist( ((!x) & f), x)) & f, x);
00292
00293 SetExpr glbExpr = bddToSetExpr(psi1);
00294
00295
00296 bdd psi2 = bdd_exist( x & f, x);
00297
00298 SetExpr lubExpr = bddToSetExpr(psi2);
00299
00300 Projector proj(*i, glbExpr, lubExpr);
00301 p.add(proj);
00302 }
00303
00304 if (!bddWasRunning)
00305 bdd_done();
00306
00307 return p;
00308 }
00309
00310 }
00311
00312