Generated on Mon Aug 25 11:35:38 2008 for Gecode by doxygen 1.5.6

bool-scale.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2006
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-02-18 15:29:18 +0100 (Mon, 18 Feb 2008) $ by $Author: tack $
00011  *     $Revision: 6215 $
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 namespace Gecode { namespace Int { namespace Linear {
00039 
00040   /*
00041    * Array of scale Boolean views
00042    *
00043    */
00044   forceinline
00045   ScaleBoolArray::ScaleBoolArray(void) {}
00046   forceinline
00047   ScaleBoolArray::ScaleBoolArray(Space* home, int n) {
00048     if (n > 0) {
00049       _fst = static_cast<ScaleBool*>(home->alloc(n*sizeof(ScaleBool)));
00050       _lst = _fst+n;
00051     } else {
00052       _fst = _lst = NULL;
00053     }
00054   }
00055   forceinline void 
00056   ScaleBoolArray::subscribe(Space* home, Propagator* p) {
00057     for (ScaleBool* f = _fst; f < _lst; f++)
00058       f->x.subscribe(home,p,PC_BOOL_VAL);
00059   }
00060   forceinline void 
00061   ScaleBoolArray::cancel(Space* home, Propagator* p) {
00062     for (ScaleBool* f = _fst; f < _lst; f++)
00063       f->x.cancel(home,p,PC_BOOL_VAL);
00064   }
00065   forceinline void 
00066   ScaleBoolArray::update(Space* home, bool share, ScaleBoolArray& sba) {
00067     int n = sba._lst - sba._fst;
00068     if (n > 0) {
00069       _fst = static_cast<ScaleBool*>(home->alloc(n*sizeof(ScaleBool)));
00070       _lst = _fst+n;
00071       for (int i=n; i--; ) {
00072         _fst[i].a = sba._fst[i].a;
00073         _fst[i].x.update(home,share,sba._fst[i].x);
00074       }
00075     } else {
00076       _fst = _lst = NULL;
00077     }
00078   }
00079   forceinline ScaleBool* 
00080   ScaleBoolArray::fst(void) const {
00081     return _fst;
00082   }
00083   forceinline ScaleBool* 
00084   ScaleBoolArray::lst(void) const {
00085     return _lst;
00086   }
00087   forceinline void 
00088   ScaleBoolArray::fst(ScaleBool* f) {
00089     _fst = f;
00090   }
00091   forceinline void 
00092   ScaleBoolArray::lst(ScaleBool* l) {
00093     _lst = l;
00094   }
00095   forceinline bool 
00096   ScaleBoolArray::empty(void) const {
00097     return _fst == _lst;
00098   }
00099   forceinline int 
00100   ScaleBoolArray::size(void) const {
00101     return static_cast<int>(_lst - _fst);
00102   }
00103   forceinline bool
00104   ScaleBoolArray::ScaleDec::operator()(const ScaleBool& x, 
00105                                        const ScaleBool& y) {
00106     return x.a > y.a;
00107   }
00108 
00109   inline void 
00110   ScaleBoolArray::sort(void) {
00111     ScaleDec scale_dec;
00112     Support::quicksort<ScaleBool,ScaleDec>(fst(), size(), scale_dec);
00113   }
00114 
00115   inline Support::Symbol
00116   ScaleBoolArray::type(void) {
00117     return Support::Symbol("Gecode::Int::Linear::ScaleBoolArray");
00118   }
00119 
00120   /*
00121    * Empty array of scale Boolean views
00122    *
00123    */
00124   forceinline
00125   EmptyScaleBoolArray::EmptyScaleBoolArray(void) {}
00126   forceinline
00127   EmptyScaleBoolArray::EmptyScaleBoolArray(Space*, int) {}
00128   forceinline void 
00129   EmptyScaleBoolArray::subscribe(Space*, Propagator*) {}
00130   forceinline void 
00131   EmptyScaleBoolArray::cancel(Space*, Propagator*) {}
00132   forceinline void 
00133   EmptyScaleBoolArray::update(Space*, bool, EmptyScaleBoolArray&) {}
00134   forceinline ScaleBool* 
00135   EmptyScaleBoolArray::fst(void) const { return NULL; }
00136   forceinline ScaleBool* 
00137   EmptyScaleBoolArray::lst(void) const { return NULL; }
00138   forceinline void 
00139   EmptyScaleBoolArray::fst(ScaleBool*) {}
00140   forceinline void 
00141   EmptyScaleBoolArray::lst(ScaleBool*) {}
00142   forceinline bool 
00143   EmptyScaleBoolArray::empty(void) const { return true; }
00144   forceinline int 
00145   EmptyScaleBoolArray::size(void) const { return 0; }
00146   forceinline void 
00147   EmptyScaleBoolArray::sort(void) {}
00148   inline Support::Symbol
00149   EmptyScaleBoolArray::type(void) {
00150     return Support::Symbol("Gecode::Int::Linear::EmptyScaleBoolArray");
00151   }
00152 
00153 
00154   /*
00155    * Base-class for Boolean constraints with coefficients
00156    *
00157    */
00158 
00159   template<class SBAP, class SBAN, class VX, PropCond pcx>
00160   forceinline
00161   LinBoolScale<SBAP,SBAN,VX,pcx>::LinBoolScale(Space* home, 
00162                                                SBAP& p0, SBAN& n0,
00163                                                VX x0, int c0)
00164     : Propagator(home), p(p0), n(n0), x(x0), c(c0) {
00165     x.subscribe(home,this,pcx);
00166     p.subscribe(home,this);
00167     n.subscribe(home,this);
00168   }
00169 
00170   template<class SBAP, class SBAN, class VX, PropCond pcx>
00171   PropCost
00172   LinBoolScale<SBAP,SBAN,VX,pcx>::cost(ModEventDelta) const {
00173     return cost_lo(p.size() + n.size(), PC_LINEAR_LO);
00174   }
00175 
00176   template<class SBAP, class SBAN, class VX, PropCond pcx>
00177   forceinline size_t
00178   LinBoolScale<SBAP,SBAN,VX,pcx>::dispose(Space* home) {
00179     x.cancel(home,this,pcx);
00180     p.cancel(home,this);
00181     n.cancel(home,this);
00182     (void) Propagator::dispose(home);
00183     return sizeof(*this);
00184   }
00185 
00186   template<class SBAP, class SBAN, class VX, PropCond pcx>
00187   forceinline
00188   LinBoolScale<SBAP,SBAN,VX,pcx>::LinBoolScale(Space* home, bool share, 
00189                                                Propagator& pr,
00190                                                SBAP& p0, SBAN& n0,
00191                                                VX x0, int c0)
00192     : Propagator(home,share,pr), c(c0) {
00193     x.update(home,share,x0);
00194     p.update(home,share,p0);
00195     n.update(home,share,n0);
00196   }
00197 
00198   template<class SBAP, class SBAN, class VX, PropCond pcx>
00199   Reflection::ActorSpec
00200   LinBoolScale<SBAP,SBAN,VX,pcx>::spec(const Space* home,
00201                                        Reflection::VarMap& m,
00202                                        const Support::Symbol& ati) const {
00203     Reflection::ActorSpec s(ati);
00204 
00205     Reflection::IntArrayArg* c_p = Reflection::Arg::newIntArray(p.size());
00206     Reflection::ArrayArg* b_p = Reflection::Arg::newArray(p.size());
00207       
00208     int count = 0;
00209     for (ScaleBool* f = p.fst(); f != p.lst(); f++) {
00210       (*c_p)[count] = f->a;
00211       (*b_p)[count++]  = f->x.spec(home, m);
00212     }
00213 
00214     Reflection::IntArrayArg* c_n = Reflection::Arg::newIntArray(n.size());
00215     Reflection::ArrayArg* b_n = Reflection::Arg::newArray(n.size());
00216     count = 0;
00217     for (ScaleBool* f = n.fst(); f != n.lst(); f++) {
00218       (*c_n)[count] = f->a;
00219       (*b_n)[count++]  = f->x.spec(home, m);
00220     }
00221 
00222     return s << c_p << b_p
00223              << c_n << b_n << x.spec(home, m)
00224              << c;
00225   }
00226 
00227   /*
00228    * Boolean equality with coefficients
00229    *
00230    */
00231 
00232   template<class SBAP, class SBAN, class VX>
00233   forceinline
00234   EqBoolScale<SBAP,SBAN,VX>::EqBoolScale(Space* home, 
00235                                          SBAP& p, SBAN& n,
00236                                          VX x, int c)
00237     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,p,n,x,c) {}
00238 
00239   template<class SBAP, class SBAN, class VX>
00240   forceinline
00241   EqBoolScale<SBAP,SBAN,VX>::EqBoolScale(Space* home, bool share, 
00242                                          Propagator& pr,
00243                                          SBAP& p, SBAN& n,
00244                                          VX x, int c)
00245     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,share,pr,p,n,x,c) {}
00246 
00247   template<class SBAP, class SBAN, class VX>
00248   Actor*
00249   EqBoolScale<SBAP,SBAN,VX>::copy(Space* home, bool share) {
00250     if (p.empty()) {
00251       EmptyScaleBoolArray ep;
00252       if (x.assigned()) {
00253         ZeroIntView z;
00254         return new (home) EqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView>
00255           (home,share,*this,ep,n,z,c+x.val());
00256       } else {
00257         return new (home) EqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00258           (home,share,*this,ep,n,x,c);
00259       }
00260     } else if (n.empty()) {
00261       EmptyScaleBoolArray en;
00262       if (x.assigned()) {
00263         ZeroIntView z;
00264         return new (home) EqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView>
00265           (home,share,*this,p,en,z,c+x.val());
00266       } else {
00267         return new (home) EqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00268           (home,share,*this,p,en,x,c);
00269       }
00270     } else {
00271       return new (home) EqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c);
00272     }
00273   }
00274 
00275   template<class SBAP, class SBAN, class VX>
00276   inline Support::Symbol
00277   EqBoolScale<SBAP,SBAN,VX>::ati(void) {
00278     return Reflection::mangle<SBAP,SBAN,VX>("Gecode::Int::Linear::EqBoolScale");
00279   }
00280 
00281   template<class SBAP, class SBAN, class VX>
00282   Reflection::ActorSpec
00283   EqBoolScale<SBAP,SBAN,VX>::spec(const Space* home,
00284                                   Reflection::VarMap& m) const {
00285     return LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>::spec(home, m, ati());
00286   }
00287 
00288   template<class SBAP, class SBAN, class VX>
00289   void
00290   EqBoolScale<SBAP,SBAN,VX>::post(Space* home, Reflection::VarMap& vars,
00291                                   const Reflection::ActorSpec& spec) {
00292     spec.checkArity(6);
00293     Reflection::IntArrayArg* c_p = spec[0]->toIntArray();
00294     ViewArray<BoolView> b_pv(home, vars, spec[1]);
00295     Reflection::IntArrayArg* c_n = spec[2]->toIntArray();
00296     ViewArray<BoolView> b_nv(home, vars, spec[3]);
00297     VX x(home, vars, spec[4]);
00298     int c = spec[5]->toInt();
00299     SBAP b_p(home,b_pv.size());
00300     {
00301       ScaleBool* f=b_p.fst();
00302       for (int i=b_pv.size(); i--; ) {
00303         f[i].x=b_pv[i]; f[i].a=(*c_p)[i];
00304       }
00305     }
00306     SBAN b_n(home,b_nv.size());
00307     {
00308       ScaleBool* f=b_n.fst();
00309       for (int i=b_nv.size(); i--; ) {
00310         f[i].x=b_nv[i]; f[i].a=(*c_n)[i];
00311       }
00312     }
00313     (void) new (home) EqBoolScale<SBAP,SBAN,VX>(home,b_p,b_n,x,c);
00314   }
00315   
00316   template<class SBAP, class SBAN, class VX>
00317   ExecStatus
00318   EqBoolScale<SBAP,SBAN,VX>::propagate(Space* home, ModEventDelta med) {
00319     int sl_p = 0; // Lower bound, computed positive
00320     int su_n = 0; // Upper bound, computed negative
00321     if (BoolView::me(med) == ME_BOOL_VAL) {
00322       // Eliminate assigned positive views while keeping order
00323       {
00324         // Skip not assigned views
00325         ScaleBool* f = p.fst();
00326         ScaleBool* l = p.lst();
00327         while ((f < l) && f->x.none()) {
00328           su_n += f->a; f++;
00329         }
00330         // Copy unassigned views to t
00331         ScaleBool* t = f;
00332         while (f < l) {
00333           if (f->x.one()) {
00334             c -= f->a;
00335           } else if (f->x.none()) {
00336             su_n += f->a; *t = *f; t++;
00337           }
00338           f++;
00339         }
00340         p.lst(t);
00341       }
00342       // Eliminate assigned negative views while keeping order
00343       {
00344         // Skip not assigned views
00345         ScaleBool* f = n.fst();
00346         ScaleBool* l = n.lst();
00347         while ((f < l) && f->x.none()) {
00348           sl_p += f->a; f++;
00349         }
00350         // Copy unassigned views to t
00351         ScaleBool* t = f;
00352         while (f < l) {
00353           if (f->x.one()) {
00354             c += f->a;
00355           } else if (f->x.none()) {
00356             sl_p += f->a; *t = *f; t++;
00357           }
00358           f++;
00359         }
00360         n.lst(t);
00361       }
00362     } else {
00363       for (ScaleBool* f=p.fst(); f<p.lst(); f++)
00364         su_n += f->a;
00365       for (ScaleBool* f=n.fst(); f<n.lst(); f++)
00366         sl_p += f->a;
00367     }
00368     
00369     if (p.empty() && n.empty()) {
00370       GECODE_ME_CHECK(x.eq(home,-c)); 
00371       return ES_SUBSUMED(this,sizeof(*this));
00372     }
00373 
00374     sl_p += x.max() + c;
00375     su_n -= x.min() + c;
00376 
00377     const int MOD_SL = 1 << 0;
00378     const int MOD_SU = 1 << 1;
00379 
00380     int mod = MOD_SL | MOD_SU;
00381 
00382     do {
00383       if ((mod & MOD_SL) != 0) {
00384         mod -= MOD_SL;
00385         // Propagate lower bound for positive Boolean views
00386         {
00387           ScaleBool* f=p.fst();
00388           for (ScaleBool* l=p.lst(); (f < l) && (f->a > sl_p); f++) {
00389             GECODE_ME_CHECK(f->x.zero_none(home));
00390             su_n -= f->a;
00391           }
00392           if (f > p.fst()) {
00393             p.fst(f); mod |= MOD_SU;
00394           }
00395         }
00396         // Propagate lower bound for negative Boolean views
00397         {
00398           ScaleBool* f=n.fst();
00399           for (ScaleBool* l=n.lst(); (f < l) && (f->a > sl_p); f++) {
00400             GECODE_ME_CHECK(f->x.one_none(home)); c += f->a;
00401             su_n -= f->a;
00402           }
00403           if (f > n.fst()) {
00404             n.fst(f); mod |= MOD_SU;
00405           }
00406         }
00407         // Propagate lower bound for integer view
00408         {
00409           const int x_min = x.min();
00410           ModEvent me = x.gq(home,x.max() - sl_p);
00411           if (me_failed(me))
00412             return ES_FAILED;
00413           if (me_modified(me)) {
00414             su_n -= x.min() - x_min;
00415             mod |= MOD_SU;
00416           }
00417         }
00418       }
00419       if ((mod & MOD_SU) != 0) {
00420         mod -= MOD_SU;
00421         // Propagate upper bound for positive Boolean views
00422         {
00423           ScaleBool* f=p.fst();
00424           for (ScaleBool* l=p.lst(); (f < l) && (f->a > su_n); f++) {
00425             GECODE_ME_CHECK(f->x.one_none(home)); c -= f->a;
00426             sl_p -= f->a;
00427           }
00428           if (f > p.fst()) {
00429             p.fst(f); mod |= MOD_SL;;
00430           }
00431         }
00432         // Propagate upper bound for negative Boolean views
00433         {
00434           ScaleBool* f=n.fst();
00435           for (ScaleBool* l=n.lst(); (f < l) && (f->a > su_n); f++) {
00436             GECODE_ME_CHECK(f->x.zero_none(home));
00437             sl_p -= f->a;
00438           }
00439           if (f > n.fst()) {
00440             n.fst(f); mod |= MOD_SL;;
00441           }
00442         }
00443         // Propagate upper bound for integer view
00444         {
00445           const int x_max = x.max();
00446           ModEvent me = x.lq(home,x.min() + su_n);
00447           if (me_failed(me))
00448             return ES_FAILED;
00449           if (me_modified(me)) {
00450             sl_p += x.max() - x_max;
00451             mod |= MOD_SL;;
00452           }
00453         }
00454       }
00455     } while (mod != 0);
00456     
00457     return (sl_p == -su_n) ? ES_SUBSUMED(this,sizeof(*this)) : ES_FIX;
00458   }
00459 
00460 
00461 
00462   template<class SBAP, class SBAN, class VX>
00463   ExecStatus
00464   EqBoolScale<SBAP,SBAN,VX>::post(Space* home,
00465                                   SBAP& p, SBAN& n, VX x, int c) {
00466     p.sort(); n.sort();
00467     if (p.empty()) {
00468       EmptyScaleBoolArray ep;
00469       (void) new (home) EqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00470         (home,ep,n,x,c);
00471     } else if (n.empty()) {
00472       EmptyScaleBoolArray en;
00473       (void) new (home) EqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00474         (home,p,en,x,c);
00475     } else {
00476       (void) new (home) EqBoolScale<ScaleBoolArray,ScaleBoolArray,VX>
00477         (home,p,n,x,c);
00478     }
00479     return ES_OK;
00480   }
00481 
00482 
00483   /*
00484    * Boolean inequality with coefficients
00485    *
00486    */
00487 
00488   template<class SBAP, class SBAN, class VX>
00489   forceinline
00490   LqBoolScale<SBAP,SBAN,VX>::LqBoolScale(Space* home, 
00491                                          SBAP& p, SBAN& n,
00492                                          VX x, int c)
00493     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,p,n,x,c) {}
00494 
00495   template<class SBAP, class SBAN, class VX>
00496   forceinline
00497   LqBoolScale<SBAP,SBAN,VX>::LqBoolScale(Space* home, bool share, 
00498                                          Propagator& pr,
00499                                          SBAP& p, SBAN& n,
00500                                          VX x, int c)
00501     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,share,pr,p,n,x,c) {}
00502 
00503   template<class SBAP, class SBAN, class VX>
00504   Actor*
00505   LqBoolScale<SBAP,SBAN,VX>::copy(Space* home, bool share) {
00506     if (p.empty()) {
00507       EmptyScaleBoolArray ep;
00508       if (x.assigned()) {
00509         ZeroIntView z;
00510         return new (home) LqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView>
00511           (home,share,*this,ep,n,z,c+x.val());
00512       } else {
00513         return new (home) LqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00514           (home,share,*this,ep,n,x,c);
00515       }
00516     } else if (n.empty()) {
00517       EmptyScaleBoolArray en;
00518       if (x.assigned()) {
00519         ZeroIntView z;
00520         return new (home) LqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView>
00521           (home,share,*this,p,en,z,c+x.val());
00522       } else {
00523         return new (home) LqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00524           (home,share,*this,p,en,x,c);
00525       }
00526     } else {
00527       return new (home) LqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c);
00528     }
00529   }
00530 
00531   template<class SBAP, class SBAN, class VX>
00532   inline Support::Symbol
00533   LqBoolScale<SBAP,SBAN,VX>::ati(void) {
00534     return Reflection::mangle<SBAP,SBAN,VX>("Gecode::Int::Linear::LqBoolScale");
00535   }
00536 
00537   template<class SBAP, class SBAN, class VX>
00538   Reflection::ActorSpec
00539   LqBoolScale<SBAP,SBAN,VX>::spec(const Space* home,
00540                                   Reflection::VarMap& m) const {
00541     return LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>::spec(home, m, ati());
00542   }
00543 
00544   template<class SBAP, class SBAN, class VX>
00545   void
00546   LqBoolScale<SBAP,SBAN,VX>::post(Space* home, Reflection::VarMap& vars,
00547                                   const Reflection::ActorSpec& spec) {
00548     spec.checkArity(6);
00549     Reflection::IntArrayArg* c_p = spec[0]->toIntArray();
00550     ViewArray<BoolView> b_pv(home, vars, spec[1]);
00551     Reflection::IntArrayArg* c_n = spec[2]->toIntArray();
00552     ViewArray<BoolView> b_nv(home, vars, spec[3]);
00553     VX x(home, vars, spec[4]);
00554     int c = spec[5]->toInt();
00555     SBAP b_p(home,b_pv.size());
00556     {
00557       ScaleBool* f=b_p.fst();
00558       for (int i=b_pv.size(); i--; ) {
00559         f[i].x=b_pv[i]; f[i].a=(*c_p)[i];
00560       }
00561     }
00562     SBAN b_n(home,b_nv.size());
00563     {
00564       ScaleBool* f=b_n.fst();
00565       for (int i=b_nv.size(); i--; ) {
00566         f[i].x=b_nv[i]; f[i].a=(*c_n)[i];
00567       }
00568     }
00569     (void) new (home) LqBoolScale<SBAP,SBAN,VX>(home,b_p,b_n,x,c);
00570   }
00571 
00572   template<class SBAP, class SBAN, class VX>
00573   ExecStatus
00574   LqBoolScale<SBAP,SBAN,VX>::propagate(Space* home, ModEventDelta med) {
00575     int sl = 0;
00576     if (BoolView::me(med) == ME_BOOL_VAL) {
00577       // Eliminate assigned positive views while keeping order
00578       {
00579         // Skip not assigned views
00580         ScaleBool* f = p.fst();
00581         ScaleBool* l = p.lst();
00582         while ((f < l) && f->x.none())
00583           f++;
00584         // Copy unassigned views to t
00585         ScaleBool* t = f;
00586         while (f < l) {
00587           if (f->x.one()) {
00588             c -= f->a;
00589           } else if (f->x.none()) {
00590             *t = *f; t++;
00591           }
00592           f++;
00593         }
00594         p.lst(t);
00595       }
00596       // Eliminate assigned negative views while keeping order
00597       {
00598         // Skip not assigned views
00599         ScaleBool* f = n.fst();
00600         ScaleBool* l = n.lst();
00601         while ((f < l) && f->x.none()) {
00602           sl += f->a; f++;
00603         }
00604         // Copy unassigned views to t
00605         ScaleBool* t = f;
00606         while (f < l) {
00607           if (f->x.one()) {
00608             c += f->a;
00609           } else if (f->x.none()) {
00610             sl += f->a; *t = *f; t++;
00611           }
00612           f++;
00613         }
00614         n.lst(t);
00615       }
00616     } else {
00617       for (ScaleBool* f=n.fst(); f<n.lst(); f++)
00618         sl += f->a;
00619     }
00620     
00621     sl += x.max() + c;
00622 
00623     // Propagate upper bound for positive Boolean views
00624     {
00625       ScaleBool* f=p.fst();
00626       for (ScaleBool* l=p.lst(); (f < l) && (f->a > sl); f++)
00627         GECODE_ME_CHECK(f->x.zero_none(home));
00628       p.fst(f);
00629     }
00630     // Propagate lower bound for negative Boolean views
00631     {
00632       ScaleBool* f=n.fst();
00633       for (ScaleBool* l=n.lst(); (f < l) && (f->a > sl); f++) {
00634         c += f->a; 
00635         GECODE_ME_CHECK(f->x.one_none(home));
00636       }
00637       n.fst(f);
00638     }
00639     ExecStatus es = ES_FIX;
00640     // Propagate lower bound for integer view
00641     {
00642       const int slx = x.max() - sl;
00643       ModEvent me = x.gq(home,slx);
00644       if (me_failed(me))
00645         return ES_FAILED;
00646       if (me_modified(me) && (slx != x.min()))
00647         es = ES_NOFIX;
00648     }
00649 
00650     if (p.empty() && n.empty())
00651       return ES_SUBSUMED(this,home);
00652 
00653     return es;
00654   }
00655 
00656 
00657 
00658   template<class SBAP, class SBAN, class VX>
00659   ExecStatus
00660   LqBoolScale<SBAP,SBAN,VX>::post(Space* home,
00661                                   SBAP& p, SBAN& n, VX x, int c) {
00662     p.sort(); n.sort();
00663     if (p.empty()) {
00664       EmptyScaleBoolArray ep;
00665       (void) new (home) LqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00666         (home,ep,n,x,c);
00667     } else if (n.empty()) {
00668       EmptyScaleBoolArray en;
00669       (void) new (home) LqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00670         (home,p,en,x,c);
00671     } else {
00672       (void) new (home) LqBoolScale<ScaleBoolArray,ScaleBoolArray,VX>
00673         (home,p,n,x,c);
00674     }
00675     return ES_OK;
00676   }
00677 
00678   /*
00679    * Boolean disequality with coefficients
00680    *
00681    */
00682 
00683   template<class SBAP, class SBAN, class VX>
00684   forceinline
00685   NqBoolScale<SBAP,SBAN,VX>::NqBoolScale(Space* home, 
00686                                          SBAP& p, SBAN& n,
00687                                          VX x, int c)
00688     : LinBoolScale<SBAP,SBAN,VX,PC_INT_VAL>(home,p,n,x,c) {}
00689 
00690   template<class SBAP, class SBAN, class VX>
00691   forceinline
00692   NqBoolScale<SBAP,SBAN,VX>::NqBoolScale(Space* home, bool share, 
00693                                          Propagator& pr,
00694                                          SBAP& p, SBAN& n,
00695                                          VX x, int c)
00696     : LinBoolScale<SBAP,SBAN,VX,PC_INT_VAL>(home,share,pr,p,n,x,c) {}
00697 
00698   template<class SBAP, class SBAN, class VX>
00699   Actor*
00700   NqBoolScale<SBAP,SBAN,VX>::copy(Space* home, bool share) {
00701     if (p.empty()) {
00702       EmptyScaleBoolArray ep;
00703       if (x.assigned()) {
00704         ZeroIntView z;
00705         return new (home) NqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView>
00706           (home,share,*this,ep,n,z,c+x.val());
00707       } else {
00708         return new (home) NqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00709           (home,share,*this,ep,n,x,c);
00710       }
00711     } else if (n.empty()) {
00712       EmptyScaleBoolArray en;
00713       if (x.assigned()) {
00714         ZeroIntView z;
00715         return new (home) NqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView>
00716           (home,share,*this,p,en,z,c+x.val());
00717       } else {
00718         return new (home) NqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00719           (home,share,*this,p,en,x,c);
00720       }
00721     } else {
00722       return new (home) NqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c);
00723     }
00724   }
00725 
00726   template<class SBAP, class SBAN, class VX>
00727   inline Support::Symbol
00728   NqBoolScale<SBAP,SBAN,VX>::ati(void) {
00729     return Reflection::mangle<SBAP,SBAN,VX>("Gecode::Int::Linear::NqBoolScale");
00730   }
00731 
00732   template<class SBAP, class SBAN, class VX>
00733   Reflection::ActorSpec
00734   NqBoolScale<SBAP,SBAN,VX>::spec(const Space* home,
00735                                   Reflection::VarMap& m) const {
00736     return LinBoolScale<SBAP,SBAN,VX,PC_INT_VAL>::spec(home, m, ati());
00737   }
00738 
00739   template<class SBAP, class SBAN, class VX>
00740   void
00741   NqBoolScale<SBAP,SBAN,VX>::post(Space* home, Reflection::VarMap& vars,
00742                                   const Reflection::ActorSpec& spec) {
00743     spec.checkArity(6);
00744     Reflection::IntArrayArg* c_p = spec[0]->toIntArray();
00745     ViewArray<BoolView> b_pv(home, vars, spec[1]);
00746     Reflection::IntArrayArg* c_n = spec[2]->toIntArray();
00747     ViewArray<BoolView> b_nv(home, vars, spec[3]);
00748     VX x(home, vars, spec[4]);
00749     int c = spec[5]->toInt();
00750     SBAP b_p(home,b_pv.size());
00751     {
00752       ScaleBool* f=b_p.fst();
00753       for (int i=b_pv.size(); i--; ) {
00754         f[i].x=b_pv[i]; f[i].a=(*c_p)[i];
00755       }
00756     }
00757     SBAN b_n(home,b_nv.size());
00758     {
00759       ScaleBool* f=b_n.fst();
00760       for (int i=b_nv.size(); i--; ) {
00761         f[i].x=b_nv[i]; f[i].a=(*c_n)[i];
00762       }
00763     }
00764     (void) new (home) NqBoolScale<SBAP,SBAN,VX>(home,b_p,b_n,x,c);
00765   }
00766 
00767   template<class SBAP, class SBAN, class VX>
00768   ExecStatus
00769   NqBoolScale<SBAP,SBAN,VX>::propagate(Space* home, ModEventDelta med) {
00770     if (BoolView::me(med) == ME_BOOL_VAL) {
00771       // Eliminate assigned positive views
00772       {
00773         ScaleBool* f = p.fst();
00774         ScaleBool* t = f;
00775         ScaleBool* l = p.lst();
00776         while (f < l) {
00777           if (f->x.one()) {
00778             c -= f->a; *f = *(t++);
00779           } else if (f->x.zero()) {
00780             *f = *(t++);
00781           } 
00782           f++;
00783         }
00784         p.fst(t);
00785       }
00786       // Eliminate assigned negative views
00787       {
00788         ScaleBool* f = n.fst();
00789         ScaleBool* t = f;
00790         ScaleBool* l = n.lst();
00791         while (f < l) {
00792           if (f->x.one()) {
00793             c += f->a; *f = *(t++);
00794           } else if (f->x.zero()) {
00795             *f = *(t++);
00796           } 
00797           f++;
00798         }
00799         n.fst(t);
00800       }
00801     }
00802     
00803     if (p.empty() && n.empty()) {
00804       GECODE_ME_CHECK(x.nq(home,-c)); 
00805       return ES_SUBSUMED(this,home);
00806     }
00807 
00808     if (x.assigned()) {
00809       int r = x.val()+c;
00810       if (p.empty() && (n.size() == 1)) {
00811         if (r == -n.fst()->a) {
00812           GECODE_ME_CHECK(n.fst()->x.zero_none(home));
00813         } else if (r == 0) {
00814           GECODE_ME_CHECK(n.fst()->x.one_none(home));
00815         }
00816         return ES_SUBSUMED(this,home);
00817       }
00818       if ((p.size() == 1) && n.empty()) {
00819         if (r == p.fst()->a) {
00820           GECODE_ME_CHECK(p.fst()->x.zero_none(home));
00821         } else if (r == 0) {
00822           GECODE_ME_CHECK(p.fst()->x.one_none(home));
00823         }
00824         return ES_SUBSUMED(this,home);
00825       }
00826     }
00827     return ES_FIX;
00828   }
00829 
00830 
00831 
00832   template<class SBAP, class SBAN, class VX>
00833   ExecStatus
00834   NqBoolScale<SBAP,SBAN,VX>::post(Space* home,
00835                                   SBAP& p, SBAN& n, VX x, int c) {
00836     if (p.empty()) {
00837       EmptyScaleBoolArray ep;
00838       (void) new (home) NqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00839         (home,ep,n,x,c);
00840     } else if (n.empty()) {
00841       EmptyScaleBoolArray en;
00842       (void) new (home) NqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00843         (home,p,en,x,c);
00844     } else {
00845       (void) new (home) NqBoolScale<ScaleBoolArray,ScaleBoolArray,VX>
00846         (home,p,n,x,c);
00847     }
00848     return ES_OK;
00849   }
00850 
00851 }}}
00852 
00853 // STATISTICS: int-prop
00854