Generated on Tue Apr 18 10:22:08 2017 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  *     Vincent Barichard <Vincent.Barichard@univ-angers.fr>
00007  *
00008  *  Copyright:
00009  *     Guido Tack, 2004
00010  *     Christian Schulte, 2004
00011  *     Vincent Barichard, 2012
00012  *
00013  *  Last modified:
00014  *     $Date: 2016-08-08 16:24:17 +0200 (Mon, 08 Aug 2016) $ by $Author: schulte $
00015  *     $Revision: 15141 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */
00041 
00042 #include <gecode/minimodel.hh>
00043 
00044 namespace Gecode {
00045 
00047   class BoolExpr::Node {
00048   public:
00050     unsigned int use;
00052     int same;
00054     NodeType t;
00056     Node *l, *r;
00058     BoolVar x;
00060     LinIntRel rl;
00061 #ifdef GECODE_HAS_FLOAT_VARS
00062 
00063     LinFloatRel rfl;
00064 #endif
00065 #ifdef GECODE_HAS_SET_VARS
00066 
00067     SetRel rs;
00068 #endif
00069 
00070     Misc* m;
00071 
00073     Node(void);
00075     ~Node(void);
00077     GECODE_MINIMODEL_EXPORT
00078     bool decrement(void);
00080     static void* operator new(size_t size);
00082     static void  operator delete(void* p, size_t size);
00083   };
00084 
00085 
00086   /*
00087    * Operations for nodes
00088    *
00089    */
00090   BoolExpr::Node::Node(void)
00091     : use(1), l(NULL), r(NULL), m(NULL) {}
00092 
00093   BoolExpr::Node::~Node(void) {
00094     delete m;
00095   }
00096 
00097   void*
00098   BoolExpr::Node::operator new(size_t size) {
00099     return heap.ralloc(size);
00100   }
00101   void
00102   BoolExpr::Node::operator delete(void* p, size_t) {
00103     heap.rfree(p);
00104   }
00105 
00106   bool
00107   BoolExpr::Node::decrement(void) {
00108     if (--use == 0) {
00109       if ((l != NULL) && l->decrement())
00110         delete l;
00111       if ((r != NULL) && r->decrement())
00112         delete r;
00113       return true;
00114     }
00115     return false;
00116   }
00117 
00118   BoolExpr::BoolExpr(void) : n(new Node) {}
00119 
00120   BoolExpr::BoolExpr(const BoolExpr& e) : n(e.n) {
00121     n->use++;
00122   }
00123 
00124   BoolExpr::BoolExpr(const BoolVar& x) : n(new Node) {
00125     n->same = 1;
00126     n->t    = NT_VAR;
00127     n->l    = NULL;
00128     n->r    = NULL;
00129     n->x    = x;
00130   }
00131 
00132   BoolExpr::BoolExpr(const BoolExpr& l, NodeType t, const BoolExpr& r)
00133     : n(new Node) {
00134     int ls = ((l.n->t == t) || (l.n->t == NT_VAR)) ? l.n->same : 1;
00135     int rs = ((r.n->t == t) || (r.n->t == NT_VAR)) ? r.n->same : 1;
00136     n->same = ls+rs;
00137     n->t    = t;
00138     n->l    = l.n;
00139     n->l->use++;
00140     n->r    = r.n;
00141     n->r->use++;
00142   }
00143 
00144   BoolExpr::BoolExpr(const BoolExpr& l, NodeType t) {
00145     (void) t;
00146     assert(t == NT_NOT);
00147     if (l.n->t == NT_NOT) {
00148       n = l.n->l;
00149       n->use++;
00150     } else {
00151       n = new Node;
00152       n->same = 1;
00153       n->t    = NT_NOT;
00154       n->l    = l.n;
00155       n->l->use++;
00156       n->r    = NULL;
00157     }
00158   }
00159 
00160   BoolExpr::BoolExpr(const LinIntRel& rl)
00161     : n(new Node) {
00162     n->same = 1;
00163     n->t    = NT_RLIN;
00164     n->l    = NULL;
00165     n->r    = NULL;
00166     n->rl   = rl;
00167   }
00168 
00169 #ifdef GECODE_HAS_FLOAT_VARS
00170   BoolExpr::BoolExpr(const LinFloatRel& rfl)
00171     : n(new Node) {
00172     n->same  = 1;
00173     n->t     = NT_RLINFLOAT;
00174     n->l     = NULL;
00175     n->r     = NULL;
00176     n->rfl   = rfl;
00177   }
00178 #endif
00179 
00180 #ifdef GECODE_HAS_SET_VARS
00181   BoolExpr::BoolExpr(const SetRel& rs)
00182     : n(new Node) {
00183     n->same = 1;
00184     n->t    = NT_RSET;
00185     n->l    = NULL;
00186     n->r    = NULL;
00187     n->rs   = rs;
00188   }
00189 
00190   BoolExpr::BoolExpr(const SetCmpRel& rs)
00191     : n(new Node) {
00192     n->same = 1;
00193     n->t    = NT_RSET;
00194     n->l    = NULL;
00195     n->r    = NULL;
00196     n->rs   = rs;
00197   }
00198 #endif
00199 
00200   BoolExpr::BoolExpr(BoolExpr::Misc* m)
00201     : n(new Node) {
00202     n->same = 1;
00203     n->t    = NT_MISC;
00204     n->l    = NULL;
00205     n->r    = NULL;
00206     n->m    = m;
00207   }
00208 
00209   const BoolExpr&
00210   BoolExpr::operator =(const BoolExpr& e) {
00211     if (this != &e) {
00212       if (n->decrement())
00213         delete n;
00214       n = e.n;
00215       n->use++;
00216     }
00217     return *this;
00218   }
00219 
00220   BoolExpr::Misc::~Misc(void) {}
00221 
00222   BoolExpr::~BoolExpr(void) {
00223     if (n->decrement())
00224       delete n;
00225   }
00226 
00227   namespace {
00229     class NNF {
00230     public:
00231       typedef BoolExpr::NodeType NodeType;
00232       typedef BoolExpr::Node Node;
00234       NodeType t;
00236       int p;
00238       int n;
00240       union {
00242         struct {
00244           NNF* l;
00246           NNF* r;
00247         } b;
00249         struct {
00251           bool neg;
00253           Node* x;
00254         } a;
00255       } u;
00257       GECODE_MINIMODEL_EXPORT
00258       static NNF* nnf(Region& r, Node* n, bool neg);
00260       GECODE_MINIMODEL_EXPORT
00261       void post(Home home, NodeType t,
00262                 BoolVarArgs& bp, BoolVarArgs& bn,
00263                 int& ip, int& in,
00264                 IntPropLevel ipl) const;
00266       GECODE_MINIMODEL_EXPORT
00267       BoolVar expr(Home home, IntPropLevel ipl) const;
00269       GECODE_MINIMODEL_EXPORT
00270       void rel(Home home, IntPropLevel ipl) const;
00272       static void* operator new(size_t s, Region& r);
00274       static void operator delete(void*);
00276       static void operator delete(void*, Region&);
00277     };
00278 
00279     /*
00280      * Operations for negation normalform
00281      *
00282      */
00283     forceinline void
00284     NNF::operator delete(void*) {}
00285 
00286     forceinline void
00287     NNF::operator delete(void*, Region&) {}
00288 
00289     forceinline void*
00290     NNF::operator new(size_t s, Region& r) {
00291       return r.ralloc(s);
00292     }
00293 
00294     BoolVar
00295     NNF::expr(Home home, IntPropLevel ipl) const {
00296       if ((t == BoolExpr::NT_VAR) && !u.a.neg)
00297         return u.a.x->x;
00298       BoolVar b(home,0,1);
00299       switch (t) {
00300       case BoolExpr::NT_VAR:
00301         assert(u.a.neg);
00302         Gecode::rel(home, u.a.x->x, IRT_NQ, b);
00303         break;
00304       case BoolExpr::NT_RLIN:
00305         u.a.x->rl.post(home, b, !u.a.neg, ipl);
00306         break;
00307 #ifdef GECODE_HAS_FLOAT_VARS
00308       case BoolExpr::NT_RLINFLOAT:
00309         u.a.x->rfl.post(home, b, !u.a.neg);
00310         break;
00311 #endif
00312 #ifdef GECODE_HAS_SET_VARS
00313       case BoolExpr::NT_RSET:
00314         u.a.x->rs.post(home, b, !u.a.neg);
00315         break;
00316 #endif
00317       case BoolExpr::NT_MISC:
00318         u.a.x->m->post(home, b, u.a.neg, ipl);
00319         break;
00320       case BoolExpr::NT_AND:
00321         {
00322           BoolVarArgs bp(p), bn(n);
00323           int ip=0, in=0;
00324           post(home, BoolExpr::NT_AND, bp, bn, ip, in, ipl);
00325           clause(home, BOT_AND, bp, bn, b);
00326         }
00327         break;
00328       case BoolExpr::NT_OR:
00329         {
00330           BoolVarArgs bp(p), bn(n);
00331           int ip=0, in=0;
00332           post(home, BoolExpr::NT_OR, bp, bn, ip, in, ipl);
00333           clause(home, BOT_OR, bp, bn, b);
00334         }
00335         break;
00336       case BoolExpr::NT_EQV:
00337         {
00338           bool n = false;
00339           BoolVar l;
00340           if (u.b.l->t == BoolExpr::NT_VAR) {
00341             l = u.b.l->u.a.x->x;
00342             if (u.b.l->u.a.neg) n = !n;
00343           } else {
00344             l = u.b.l->expr(home,ipl);
00345           }
00346           BoolVar r;
00347           if (u.b.r->t == BoolExpr::NT_VAR) {
00348             r = u.b.r->u.a.x->x;
00349             if (u.b.r->u.a.neg) n = !n;
00350           } else {
00351             r = u.b.r->expr(home,ipl);
00352           }
00353           Gecode::rel(home, l, n ? BOT_XOR : BOT_EQV, r, b, ipl);
00354         }
00355         break;
00356       default:
00357         GECODE_NEVER;
00358       }
00359       return b;
00360     }
00361 
00362     void
00363     NNF::post(Home home, NodeType t,
00364               BoolVarArgs& bp, BoolVarArgs& bn,
00365               int& ip, int& in,
00366               IntPropLevel ipl) const {
00367       if (this->t != t) {
00368         switch (this->t) {
00369         case BoolExpr::NT_VAR:
00370           if (u.a.neg) {
00371             bn[in++]=u.a.x->x;
00372           } else {
00373             bp[ip++]=u.a.x->x;
00374           }
00375           break;
00376         case BoolExpr::NT_RLIN:
00377           {
00378             BoolVar b(home,0,1);
00379             u.a.x->rl.post(home, b, !u.a.neg, ipl);
00380             bp[ip++]=b;
00381           }
00382           break;
00383 #ifdef GECODE_HAS_FLOAT_VARS
00384         case BoolExpr::NT_RLINFLOAT:
00385           {
00386             BoolVar b(home,0,1);
00387             u.a.x->rfl.post(home, b, !u.a.neg);
00388             bp[ip++]=b;
00389           }
00390           break;
00391 #endif
00392 #ifdef GECODE_HAS_SET_VARS
00393         case BoolExpr::NT_RSET:
00394           {
00395             BoolVar b(home,0,1);
00396             u.a.x->rs.post(home, b, !u.a.neg);
00397             bp[ip++]=b;
00398           }
00399           break;
00400 #endif
00401         case BoolExpr::NT_MISC:
00402           {
00403             BoolVar b(home,0,1);
00404             u.a.x->m->post(home, b, u.a.neg, ipl);
00405             bp[ip++]=b;
00406           }
00407           break;
00408         default:
00409           bp[ip++] = expr(home, ipl);
00410           break;
00411         }
00412       } else {
00413         u.b.l->post(home, t, bp, bn, ip, in, ipl);
00414         u.b.r->post(home, t, bp, bn, ip, in, ipl);
00415       }
00416     }
00417 
00418     void
00419     NNF::rel(Home home, IntPropLevel ipl) const {
00420       switch (t) {
00421       case BoolExpr::NT_VAR:
00422         Gecode::rel(home, u.a.x->x, IRT_EQ, u.a.neg ? 0 : 1);
00423         break;
00424       case BoolExpr::NT_RLIN:
00425         u.a.x->rl.post(home, !u.a.neg, ipl);
00426         break;
00427 #ifdef GECODE_HAS_FLOAT_VARS
00428       case BoolExpr::NT_RLINFLOAT:
00429         u.a.x->rfl.post(home, !u.a.neg);
00430         break;
00431 #endif
00432 #ifdef GECODE_HAS_SET_VARS
00433       case BoolExpr::NT_RSET:
00434         u.a.x->rs.post(home, !u.a.neg);
00435         break;
00436 #endif
00437       case BoolExpr::NT_MISC:
00438         {
00439           BoolVar b(home,!u.a.neg,!u.a.neg);
00440           u.a.x->m->post(home, b, false, ipl);
00441         }
00442         break;
00443       case BoolExpr::NT_AND:
00444         u.b.l->rel(home, ipl);
00445         u.b.r->rel(home, ipl);
00446         break;
00447       case BoolExpr::NT_OR:
00448         {
00449           BoolVarArgs bp(p), bn(n);
00450           int ip=0, in=0;
00451           post(home, BoolExpr::NT_OR, bp, bn, ip, in, ipl);
00452           clause(home, BOT_OR, bp, bn, 1);
00453         }
00454         break;
00455       case BoolExpr::NT_EQV:
00456         if (u.b.l->t==BoolExpr::NT_VAR &&
00457             u.b.r->t==BoolExpr::NT_RLIN) {
00458           u.b.r->u.a.x->rl.post(home, u.b.l->u.a.x->x,
00459                                 u.b.l->u.a.neg==u.b.r->u.a.neg, ipl);
00460         } else if (u.b.r->t==BoolExpr::NT_VAR &&
00461                    u.b.l->t==BoolExpr::NT_RLIN) {
00462           u.b.l->u.a.x->rl.post(home, u.b.r->u.a.x->x,
00463                                 u.b.l->u.a.neg==u.b.r->u.a.neg, ipl);
00464         } else if (u.b.l->t==BoolExpr::NT_RLIN) {
00465           u.b.l->u.a.x->rl.post(home, u.b.r->expr(home,ipl),
00466                                 !u.b.l->u.a.neg,ipl);
00467         } else if (u.b.r->t==BoolExpr::NT_RLIN) {
00468           u.b.r->u.a.x->rl.post(home, u.b.l->expr(home,ipl),
00469                                 !u.b.r->u.a.neg,ipl);
00470 #ifdef GECODE_HAS_FLOAT_VARS
00471         } else if (u.b.l->t==BoolExpr::NT_VAR &&
00472                    u.b.r->t==BoolExpr::NT_RLINFLOAT) {
00473           u.b.r->u.a.x->rfl.post(home, u.b.l->u.a.x->x,
00474                                  u.b.l->u.a.neg==u.b.r->u.a.neg);
00475         } else if (u.b.r->t==BoolExpr::NT_VAR &&
00476                    u.b.l->t==BoolExpr::NT_RLINFLOAT) {
00477           u.b.l->u.a.x->rfl.post(home, u.b.r->u.a.x->x,
00478                                  u.b.l->u.a.neg==u.b.r->u.a.neg);
00479         } else if (u.b.l->t==BoolExpr::NT_RLINFLOAT) {
00480           u.b.l->u.a.x->rfl.post(home, u.b.r->expr(home,ipl),
00481                                  !u.b.l->u.a.neg);
00482         } else if (u.b.r->t==BoolExpr::NT_RLINFLOAT) {
00483           u.b.r->u.a.x->rfl.post(home, u.b.l->expr(home,ipl),
00484                                  !u.b.r->u.a.neg);
00485 #endif
00486 #ifdef GECODE_HAS_SET_VARS
00487         } else if (u.b.l->t==BoolExpr::NT_VAR &&
00488                    u.b.r->t==BoolExpr::NT_RSET) {
00489           u.b.r->u.a.x->rs.post(home, u.b.l->u.a.x->x,
00490                                 u.b.l->u.a.neg==u.b.r->u.a.neg);
00491         } else if (u.b.r->t==BoolExpr::NT_VAR &&
00492                    u.b.l->t==BoolExpr::NT_RSET) {
00493           u.b.l->u.a.x->rs.post(home, u.b.r->u.a.x->x,
00494                                 u.b.l->u.a.neg==u.b.r->u.a.neg);
00495         } else if (u.b.l->t==BoolExpr::NT_RSET) {
00496           u.b.l->u.a.x->rs.post(home, u.b.r->expr(home,ipl),
00497                                 !u.b.l->u.a.neg);
00498         } else if (u.b.r->t==BoolExpr::NT_RSET) {
00499           u.b.r->u.a.x->rs.post(home, u.b.l->expr(home,ipl),
00500                                 !u.b.r->u.a.neg);
00501 #endif
00502         } else {
00503           Gecode::rel(home, expr(home, ipl), IRT_EQ, 1);
00504         }
00505         break;
00506       default:
00507         GECODE_NEVER;
00508       }
00509     }
00510 
00511     NNF*
00512     NNF::nnf(Region& r, Node* n, bool neg) {
00513       switch (n->t) {
00514       case BoolExpr::NT_VAR:
00515       case BoolExpr::NT_RLIN:
00516       case BoolExpr::NT_MISC:
00517   #ifdef GECODE_HAS_FLOAT_VARS
00518       case BoolExpr::NT_RLINFLOAT:
00519   #endif
00520   #ifdef GECODE_HAS_SET_VARS
00521       case BoolExpr::NT_RSET:
00522   #endif
00523         {
00524           NNF* x = new (r) NNF;
00525           x->t = n->t; x->u.a.neg = neg; x->u.a.x = n;
00526           if (neg) {
00527             x->p = 0; x->n = 1;
00528           } else {
00529             x->p = 1; x->n = 0;
00530           }
00531           return x;
00532         }
00533       case BoolExpr::NT_NOT:
00534         return nnf(r,n->l,!neg);
00535       case BoolExpr::NT_AND: case BoolExpr::NT_OR:
00536         {
00537           NodeType t = ((n->t == BoolExpr::NT_AND) == neg) ?
00538             BoolExpr::NT_OR : BoolExpr::NT_AND;
00539           NNF* x = new (r) NNF;
00540           x->t = t;
00541           x->u.b.l = nnf(r,n->l,neg);
00542           x->u.b.r = nnf(r,n->r,neg);
00543           int p_l, n_l;
00544           if ((x->u.b.l->t == t) ||
00545               (x->u.b.l->t == BoolExpr::NT_VAR)) {
00546             p_l=x->u.b.l->p; n_l=x->u.b.l->n;
00547           } else {
00548             p_l=1; n_l=0;
00549           }
00550           int p_r, n_r;
00551           if ((x->u.b.r->t == t) ||
00552               (x->u.b.r->t == BoolExpr::NT_VAR)) {
00553             p_r=x->u.b.r->p; n_r=x->u.b.r->n;
00554           } else {
00555             p_r=1; n_r=0;
00556           }
00557           x->p = p_l+p_r;
00558           x->n = n_l+n_r;
00559           return x;
00560         }
00561       case BoolExpr::NT_EQV:
00562         {
00563           NNF* x = new (r) NNF;
00564           x->t = BoolExpr::NT_EQV;
00565           x->u.b.l = nnf(r,n->l,neg);
00566           x->u.b.r = nnf(r,n->r,false);
00567           x->p = 2; x->n = 0;
00568           return x;
00569         }
00570       default:
00571         GECODE_NEVER;
00572       }
00573       GECODE_NEVER;
00574       return NULL;
00575     }
00576   }
00577 
00578   BoolVar
00579   BoolExpr::expr(Home home, IntPropLevel ipl) const {
00580     Region r(home);
00581     return NNF::nnf(r,n,false)->expr(home,ipl);
00582   }
00583 
00584   void
00585   BoolExpr::rel(Home home, IntPropLevel ipl) const {
00586     Region r(home);
00587     return NNF::nnf(r,n,false)->rel(home,ipl);
00588   }
00589 
00590 
00591   BoolExpr
00592   operator &&(const BoolExpr& l, const BoolExpr& r) {
00593     return BoolExpr(l,BoolExpr::NT_AND,r);
00594   }
00595   BoolExpr
00596   operator ||(const BoolExpr& l, const BoolExpr& r) {
00597     return BoolExpr(l,BoolExpr::NT_OR,r);
00598   }
00599   BoolExpr
00600   operator ^(const BoolExpr& l, const BoolExpr& r) {
00601     return BoolExpr(BoolExpr(l,BoolExpr::NT_EQV,r),BoolExpr::NT_NOT);
00602   }
00603 
00604   BoolExpr
00605   operator !(const BoolExpr& e) {
00606     return BoolExpr(e,BoolExpr::NT_NOT);
00607   }
00608 
00609   BoolExpr
00610   operator !=(const BoolExpr& l, const BoolExpr& r) {
00611     return !BoolExpr(l, BoolExpr::NT_EQV, r);
00612   }
00613   BoolExpr
00614   operator ==(const BoolExpr& l, const BoolExpr& r) {
00615     return BoolExpr(l, BoolExpr::NT_EQV, r);
00616   }
00617   BoolExpr
00618   operator >>(const BoolExpr& l, const BoolExpr& r) {
00619     return BoolExpr(BoolExpr(l,BoolExpr::NT_NOT),
00620                     BoolExpr::NT_OR,r);
00621   }
00622   BoolExpr
00623   operator <<(const BoolExpr& l, const BoolExpr& r) {
00624     return BoolExpr(BoolExpr(r,BoolExpr::NT_NOT),
00625                     BoolExpr::NT_OR,l);
00626   }
00627   /*
00628    * Posting Boolean expressions and relations
00629    *
00630    */
00631   BoolVar
00632   expr(Home home, const BoolExpr& e, IntPropLevel ipl) {
00633     PostInfo pi(home);
00634     if (!home.failed())
00635       return e.expr(home,ipl);
00636     BoolVar x(home,0,1);
00637     return x;
00638   }
00639 
00640   void
00641   rel(Home home, const BoolExpr& e, IntPropLevel ipl) {
00642     GECODE_POST;
00643     if (home.failed()) return;
00644     e.rel(home,ipl);
00645   }
00646 
00647   /*
00648    * Boolean element constraints
00649    *
00650    */
00651 
00653   class BElementExpr : public BoolExpr::Misc {
00654   protected:
00656     BoolExpr* a;
00658     int n;
00660     LinIntExpr idx;
00661   public:
00663     BElementExpr(const BoolVarArgs& b, const LinIntExpr& idx);
00665     virtual ~BElementExpr(void);
00667     virtual void post(Home home, BoolVar b, bool neg, IntPropLevel ipl);
00668   };
00669 
00670   BElementExpr::BElementExpr(const BoolVarArgs& b, const LinIntExpr& idx)
00671     : a(static_cast<BoolExpr*>(heap.ralloc(sizeof(BoolExpr)*b.size()))), n(b.size()), idx(idx) {
00672     for (int i=b.size(); i--;)
00673       new (&a[i]) BoolExpr(b[i]);
00674   }
00675 
00676   BElementExpr::~BElementExpr(void) {
00677     heap.free<BoolExpr>(a,n);
00678   }
00679 
00680   void
00681   BElementExpr::post(Home home, BoolVar b, bool neg, IntPropLevel ipl) {
00682     IntVar z = idx.post(home, ipl);
00683     if (z.assigned() && (z.val() >= 0) && (z.val() < n)) {
00684       BoolExpr be = neg ? (a[z.val()] == !b) : (a[z.val()] == b);
00685       be.rel(home,ipl);
00686     } else {
00687       BoolVarArgs x(n);
00688       for (int i=n; i--;)
00689         x[i] = a[i].expr(home,ipl);
00690       BoolVar res = neg ? (!b).expr(home,ipl) : b;
00691       element(home, x, z, res, ipl);
00692     }
00693   }
00694 
00695   BoolExpr
00696   element(const BoolVarArgs& b, const LinIntExpr& idx) {
00697     return BoolExpr(new BElementExpr(b,idx));
00698   }
00699 
00700 }
00701 
00702 // STATISTICS: minimodel-any