Generated on Thu Mar 22 10:39:43 2012 for Gecode by doxygen 1.6.3

bool-expr.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *     Christian Schulte <schulte@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Guido Tack, 2004
00009  *     Christian Schulte, 2004
00010  *
00011  *  Last modified:
00012  *     $Date: 2012-02-22 06:04:20 +0100 (Wed, 22 Feb 2012) $ by $Author: tack $
00013  *     $Revision: 12537 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 #include <gecode/minimodel.hh>
00041 
00042 namespace Gecode {
00043 
00044   /*
00045    * Operations for nodes
00046    *
00047    */
00048   bool
00049   BoolExpr::Node::decrement(void) {
00050     if (--use == 0) {
00051       if ((l != NULL) && l->decrement())
00052         delete l;
00053       if ((r != NULL) && r->decrement())
00054         delete r;
00055       return true;
00056     }
00057     return false;
00058   }
00059 
00060 
00061   BoolExpr::BoolExpr(void) : n(new Node) {}
00062 
00063   BoolExpr::BoolExpr(const BoolVar& x) : n(new Node) {
00064     n->same = 1;
00065     n->t    = NT_VAR;
00066     n->l    = NULL;
00067     n->r    = NULL;
00068     n->x    = x;
00069     n->m    = NULL;
00070   }
00071 
00072   BoolExpr::BoolExpr(const BoolExpr& l, NodeType t, const BoolExpr& r)
00073     : n(new Node) {
00074     int ls = ((l.n->t == t) || (l.n->t == NT_VAR)) ? l.n->same : 1;
00075     int rs = ((r.n->t == t) || (r.n->t == NT_VAR)) ? r.n->same : 1;
00076     n->same = ls+rs;
00077     n->t    = t;
00078     n->l    = l.n;
00079     n->l->use++;
00080     n->r    = r.n;
00081     n->r->use++;
00082     n->m    = NULL;
00083   }
00084 
00085   BoolExpr::BoolExpr(const BoolExpr& l, NodeType t) {
00086     (void) t;
00087     assert(t == NT_NOT);
00088     if (l.n->t == NT_NOT) {
00089       n = l.n->l;
00090       n->use++;
00091     } else {
00092       n = new Node;
00093       n->same = 1;
00094       n->t    = NT_NOT;
00095       n->l    = l.n;
00096       n->l->use++;
00097       n->r    = NULL;
00098       n->m    = NULL;
00099     }
00100   }
00101 
00102   BoolExpr::BoolExpr(const LinRel& rl)
00103     : n(new Node) {
00104     n->same = 1;
00105     n->t    = NT_RLIN;
00106     n->l    = NULL;
00107     n->r    = NULL;
00108     n->rl   = rl;
00109     n->m    = NULL;
00110   }
00111 
00112 #ifdef GECODE_HAS_SET_VARS
00113   BoolExpr::BoolExpr(const SetRel& rs)
00114     : n(new Node) {
00115     n->same = 1;
00116     n->t    = NT_RSET;
00117     n->l    = NULL;
00118     n->r    = NULL;
00119     n->rs   = rs;
00120     n->m    = NULL;
00121   }
00122 
00123   BoolExpr::BoolExpr(const SetCmpRel& rs)
00124     : n(new Node) {
00125     n->same = 1;
00126     n->t    = NT_RSET;
00127     n->l    = NULL;
00128     n->r    = NULL;
00129     n->rs   = rs;
00130     n->m    = NULL;
00131   }
00132 #endif
00133 
00134   BoolExpr::BoolExpr(BoolExpr::MiscExpr* m)
00135     : n(new Node) {
00136     n->same = 1;
00137     n->t    = NT_MISC;
00138     n->l    = NULL;
00139     n->r    = NULL;
00140     n->m    = m;
00141   }
00142 
00143   const BoolExpr&
00144   BoolExpr::operator =(const BoolExpr& e) {
00145     if (this != &e) {
00146       if (n->decrement())
00147         delete n;
00148       n = e.n;
00149       n->use++;
00150     }
00151     return *this;
00152   }
00153 
00154   BoolExpr::MiscExpr::~MiscExpr(void) {}
00155 
00156   BoolExpr::~BoolExpr(void) {
00157     if (n->decrement())
00158       delete n;
00159   }
00160 
00161   /*
00162    * Operations for negation normalform
00163    *
00164    */
00165   forceinline void
00166   BoolExpr::NNF::operator delete(void*) {}
00167 
00168   forceinline void
00169   BoolExpr::NNF::operator delete(void*, Region&) {}
00170 
00171   forceinline void*
00172   BoolExpr::NNF::operator new(size_t s, Region& r) {
00173     return r.ralloc(s);
00174   }
00175 
00176   BoolVar
00177   BoolExpr::NNF::expr(Home home, IntConLevel icl) const {
00178     if ((t == NT_VAR) && !u.a.neg)
00179       return u.a.x->x;
00180     BoolVar b(home,0,1);
00181     switch (t) {
00182     case NT_VAR:
00183       assert(u.a.neg);
00184       Gecode::rel(home, u.a.x->x, IRT_NQ, b);
00185       break;
00186     case NT_RLIN:
00187       u.a.x->rl.post(home, b, !u.a.neg, icl);
00188       break;
00189 #ifdef GECODE_HAS_SET_VARS
00190     case NT_RSET:
00191       u.a.x->rs.post(home, b, !u.a.neg);
00192       break;
00193 #endif
00194     case NT_MISC:
00195       u.a.x->m->post(home, b, !u.a.neg, icl);
00196       break;
00197     case NT_AND:
00198       {
00199         BoolVarArgs bp(p), bn(n);
00200         int ip=0, in=0;
00201         post(home, NT_AND, bp, bn, ip, in, icl);
00202         clause(home, BOT_AND, bp, bn, b);
00203       }
00204       break;
00205     case NT_OR:
00206       {
00207         BoolVarArgs bp(p), bn(n);
00208         int ip=0, in=0;
00209         post(home, NT_OR, bp, bn, ip, in, icl);
00210         clause(home, BOT_OR, bp, bn, b);
00211       }
00212       break;
00213     case NT_EQV:
00214       {
00215         bool n = false;
00216         BoolVar l;
00217         if (u.b.l->t == NT_VAR) {
00218           l = u.b.l->u.a.x->x;
00219           if (u.b.l->u.a.neg) n = !n;
00220         } else {
00221           l = u.b.l->expr(home,icl);
00222         }
00223         BoolVar r;
00224         if (u.b.r->t == NT_VAR) {
00225           r = u.b.r->u.a.x->x;
00226           if (u.b.r->u.a.neg) n = !n;
00227         } else {
00228           r = u.b.r->expr(home,icl);
00229         }
00230         Gecode::rel(home, l, n ? BOT_XOR : BOT_EQV, r, b, icl);
00231       }
00232       break;
00233     default:
00234       GECODE_NEVER;
00235     }
00236     return b;
00237   }
00238 
00239   void
00240   BoolExpr::NNF::post(Home home, NodeType t,
00241                       BoolVarArgs& bp, BoolVarArgs& bn,
00242                       int& ip, int& in,
00243                       IntConLevel icl) const {
00244     if (this->t != t) {
00245       switch (this->t) {
00246       case NT_VAR:
00247         if (u.a.neg) {
00248           bn[in++]=u.a.x->x;
00249         } else {
00250           bp[ip++]=u.a.x->x;
00251         }
00252         break;
00253       case NT_RLIN:
00254         {
00255           BoolVar b(home,0,1);
00256           u.a.x->rl.post(home, b, !u.a.neg, icl);
00257           bp[ip++]=b;
00258         }
00259         break;
00260 #ifdef GECODE_HAS_SET_VARS
00261       case NT_RSET:
00262         {
00263           BoolVar b(home,0,1);
00264           u.a.x->rs.post(home, b, !u.a.neg);
00265           bp[ip++]=b;
00266         }
00267         break;
00268 #endif
00269       case NT_MISC:
00270         {
00271           BoolVar b(home,0,1);
00272           u.a.x->m->post(home, b, !u.a.neg, icl);
00273           bp[ip++]=b;
00274         }
00275         break;      
00276       default:
00277         bp[ip++] = expr(home, icl);
00278         break;
00279       }
00280     } else {
00281       u.b.l->post(home, t, bp, bn, ip, in, icl);
00282       u.b.r->post(home, t, bp, bn, ip, in, icl);
00283     }
00284   }
00285 
00286   void
00287   BoolExpr::NNF::rel(Home home, IntConLevel icl) const {
00288     switch (t) {
00289     case NT_VAR:
00290       Gecode::rel(home, u.a.x->x, IRT_EQ, u.a.neg ? 0 : 1);
00291       break;
00292     case NT_RLIN:
00293       u.a.x->rl.post(home, !u.a.neg, icl);
00294       break;
00295 #ifdef GECODE_HAS_SET_VARS
00296     case NT_RSET:
00297       u.a.x->rs.post(home, !u.a.neg);
00298       break;
00299 #endif
00300     case NT_MISC:
00301       {
00302         BoolVar b(home,!u.a.neg,!u.a.neg);
00303         u.a.x->m->post(home, b, false, icl);
00304       }
00305       break;
00306     case NT_AND:
00307       u.b.l->rel(home, icl);
00308       u.b.r->rel(home, icl);
00309       break;
00310     case NT_OR:
00311       {
00312         BoolVarArgs bp(p), bn(n);
00313         int ip=0, in=0;
00314         post(home, NT_OR, bp, bn, ip, in, icl);
00315         clause(home, BOT_OR, bp, bn, 1);
00316       }
00317       break;
00318     case NT_EQV:
00319       if (u.b.l->t==NT_VAR && u.b.r->t==NT_RLIN) {
00320         u.b.r->u.a.x->rl.post(home, u.b.l->u.a.x->x,
00321                               u.b.l->u.a.neg==u.b.r->u.a.neg, icl);
00322       } else if (u.b.r->t==NT_VAR && u.b.l->t==NT_RLIN) {
00323         u.b.l->u.a.x->rl.post(home, u.b.r->u.a.x->x,
00324                               u.b.l->u.a.neg==u.b.r->u.a.neg, icl);
00325       } else if (u.b.l->t==NT_RLIN) {
00326         u.b.l->u.a.x->rl.post(home, u.b.r->expr(home,icl),
00327                               !u.b.l->u.a.neg,icl);
00328       } else if (u.b.r->t==NT_RLIN) {
00329         u.b.r->u.a.x->rl.post(home, u.b.l->expr(home,icl),
00330                               !u.b.r->u.a.neg,icl);
00331 #ifdef GECODE_HAS_SET_VARS
00332       } else if (u.b.l->t==NT_VAR && u.b.r->t==NT_RSET) {
00333         u.b.r->u.a.x->rs.post(home, u.b.l->u.a.x->x,
00334                               u.b.l->u.a.neg==u.b.r->u.a.neg);
00335       } else if (u.b.r->t==NT_VAR && u.b.l->t==NT_RSET) {
00336         u.b.l->u.a.x->rs.post(home, u.b.r->u.a.x->x,
00337                               u.b.l->u.a.neg==u.b.r->u.a.neg);
00338       } else if (u.b.l->t==NT_RSET) {
00339         u.b.l->u.a.x->rs.post(home, u.b.r->expr(home,icl),
00340                               !u.b.l->u.a.neg);
00341       } else if (u.b.r->t==NT_RSET) {
00342         u.b.r->u.a.x->rs.post(home, u.b.l->expr(home,icl),
00343                               !u.b.r->u.a.neg);
00344 #endif
00345       } else {
00346         Gecode::rel(home, expr(home, icl), IRT_EQ, 1);
00347       }
00348       break;
00349     default:
00350       GECODE_NEVER;
00351     }
00352   }
00353 
00354   BoolExpr::NNF*
00355   BoolExpr::NNF::nnf(Region& r, Node* n, bool neg) {
00356     switch (n->t) {
00357     case NT_VAR: case NT_RLIN: case NT_MISC:
00358 #ifdef GECODE_HAS_SET_VARS
00359     case NT_RSET:
00360 #endif
00361       {
00362         NNF* x = new (r) NNF;
00363         x->t = n->t; x->u.a.neg = neg; x->u.a.x = n;
00364         if (neg) {
00365           x->p = 0; x->n = 1;
00366         } else {
00367           x->p = 1; x->n = 0;
00368         }
00369         return x;
00370       }
00371     case NT_NOT:
00372       return nnf(r,n->l,!neg);
00373     case NT_AND: case NT_OR:
00374       {
00375         NodeType t = ((n->t == NT_AND) == neg) ? NT_OR : NT_AND;
00376         NNF* x = new (r) NNF;
00377         x->t = t;
00378         x->u.b.l = nnf(r,n->l,neg);
00379         x->u.b.r = nnf(r,n->r,neg);
00380         int p_l, n_l;
00381         if ((x->u.b.l->t == t) || (x->u.b.l->t == NT_VAR)) {
00382           p_l=x->u.b.l->p; n_l=x->u.b.l->n;
00383         } else {
00384           p_l=1; n_l=0;
00385         }
00386         int p_r, n_r;
00387         if ((x->u.b.r->t == t) || (x->u.b.r->t == NT_VAR)) {
00388           p_r=x->u.b.r->p; n_r=x->u.b.r->n;
00389         } else {
00390           p_r=1; n_r=0;
00391         }
00392         x->p = p_l+p_r;
00393         x->n = n_l+n_r;
00394         return x;
00395       }
00396     case NT_EQV:
00397       {
00398         NNF* x = new (r) NNF;
00399         x->t = NT_EQV;
00400         x->u.b.l = nnf(r,n->l,neg);
00401         x->u.b.r = nnf(r,n->r,false);
00402         x->p = 2; x->n = 0;
00403         return x;
00404       }
00405     default:
00406       GECODE_NEVER;
00407     }
00408     GECODE_NEVER;
00409     return NULL;
00410   }
00411 
00412 
00413   BoolExpr
00414   operator &&(const BoolExpr& l, const BoolExpr& r) {
00415     return BoolExpr(l,BoolExpr::NT_AND,r);
00416   }
00417   BoolExpr
00418   operator ||(const BoolExpr& l, const BoolExpr& r) {
00419     return BoolExpr(l,BoolExpr::NT_OR,r);
00420   }
00421   BoolExpr
00422   operator ^(const BoolExpr& l, const BoolExpr& r) {
00423     return BoolExpr(BoolExpr(l,BoolExpr::NT_EQV,r),BoolExpr::NT_NOT);
00424   }
00425 
00426   BoolExpr
00427   operator !(const BoolExpr& e) {
00428     return BoolExpr(e,BoolExpr::NT_NOT);
00429   }
00430 
00431   BoolExpr
00432   operator !=(const BoolExpr& l, const BoolExpr& r) {
00433     return !BoolExpr(l, BoolExpr::NT_EQV, r);
00434   }
00435   BoolExpr
00436   operator ==(const BoolExpr& l, const BoolExpr& r) {
00437     return BoolExpr(l, BoolExpr::NT_EQV, r);
00438   }
00439   BoolExpr
00440   operator >>(const BoolExpr& l, const BoolExpr& r) {
00441     return BoolExpr(BoolExpr(l,BoolExpr::NT_NOT),
00442                     BoolExpr::NT_OR,r);
00443   }
00444   BoolExpr
00445   operator <<(const BoolExpr& l, const BoolExpr& r) {
00446     return BoolExpr(BoolExpr(r,BoolExpr::NT_NOT),
00447                     BoolExpr::NT_OR,l);
00448   }
00449   /*
00450    * Posting Boolean expressions and relations
00451    *
00452    */
00453   BoolVar
00454   expr(Home home, const BoolExpr& e, IntConLevel icl) {
00455     if (!home.failed())
00456       return e.expr(home,icl);
00457     BoolVar x(home,0,1);
00458     return x;
00459   }
00460 
00461   void
00462   rel(Home home, const BoolExpr& e, IntConLevel icl) {
00463     if (home.failed()) return;
00464     e.rel(home,icl);
00465   }
00466 
00467   /*
00468    * Boolean element constraints
00469    *
00470    */
00471   
00473   class BElementExpr : public BoolExpr::MiscExpr {
00474   public:
00476     BoolExpr* a;
00478     int n;
00480     LinExpr idx;
00482     BElementExpr(int size);
00484     virtual ~BElementExpr(void);
00486     virtual void post(Space& home, BoolVar b, bool neg, IntConLevel icl);
00487   };
00488 
00489   BElementExpr::BElementExpr(int size)
00490     : a(heap.alloc<BoolExpr>(size)), n(size) {}
00491 
00492   BElementExpr::~BElementExpr(void) {
00493     heap.free<BoolExpr>(a,n);
00494   }
00495   
00496   void
00497   BElementExpr::post(Space& home, BoolVar b, bool pos, IntConLevel icl) {
00498     IntVar z = idx.post(home, icl);
00499     if (z.assigned() && z.val() >= 0 && z.val() < n) {
00500       BoolExpr be = pos ? (a[z.val()] == b) : (a[z.val()] == !b);
00501       be.rel(home,icl);
00502     } else {
00503       BoolVarArgs x(n);
00504       for (int i=n; i--;)
00505         x[i] = a[i].expr(home,icl);
00506       BoolVar res = pos ? b : (!b).expr(home,icl);
00507       element(home, x, z, res, icl);
00508     }
00509   }
00510 
00511   BoolExpr
00512   element(const BoolVarArgs& b, const LinExpr& idx) {
00513     BElementExpr* be = new BElementExpr(b.size());
00514     for (int i=b.size(); i--;)
00515       new (&be->a[i]) BoolExpr(b[i]);
00516     be->idx = idx;
00517     return BoolExpr(be);
00518   }
00519 
00520 }
00521 
00522 // STATISTICS: minimodel-any