Generated on Tue Apr 18 10:21:56 2017 for Gecode by doxygen 1.6.3

bool-scale.hpp

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: 2016-06-29 17:28:17 +0200 (Wed, 29 Jun 2016) $ by $Author: schulte $
00011  *     $Revision: 15137 $
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 = home.alloc<ScaleBool>(n);
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::reschedule(Space& home, Propagator& p) {
00067     for (ScaleBool* f = _fst; f < _lst; f++)
00068       f->x.reschedule(home,p,PC_BOOL_VAL);
00069   }
00070   forceinline void
00071   ScaleBoolArray::update(Space& home, bool share, ScaleBoolArray& sba) {
00072     int n = static_cast<int>(sba._lst - sba._fst);
00073     if (n > 0) {
00074       _fst = home.alloc<ScaleBool>(n);
00075       _lst = _fst+n;
00076       for (int i=n; i--; ) {
00077         _fst[i].a = sba._fst[i].a;
00078         _fst[i].x.update(home,share,sba._fst[i].x);
00079       }
00080     } else {
00081       _fst = _lst = NULL;
00082     }
00083   }
00084   forceinline ScaleBool*
00085   ScaleBoolArray::fst(void) const {
00086     return _fst;
00087   }
00088   forceinline ScaleBool*
00089   ScaleBoolArray::lst(void) const {
00090     return _lst;
00091   }
00092   forceinline void
00093   ScaleBoolArray::fst(ScaleBool* f) {
00094     _fst = f;
00095   }
00096   forceinline void
00097   ScaleBoolArray::lst(ScaleBool* l) {
00098     _lst = l;
00099   }
00100   forceinline bool
00101   ScaleBoolArray::empty(void) const {
00102     return _fst == _lst;
00103   }
00104   forceinline int
00105   ScaleBoolArray::size(void) const {
00106     return static_cast<int>(_lst - _fst);
00107   }
00108   forceinline bool
00109   ScaleBoolArray::ScaleDec::operator ()(const ScaleBool& x,
00110                                        const ScaleBool& y) {
00111     return x.a > y.a;
00112   }
00113 
00114   inline void
00115   ScaleBoolArray::sort(void) {
00116     ScaleDec scale_dec;
00117     Support::quicksort<ScaleBool,ScaleDec>(fst(), size(), scale_dec);
00118   }
00119 
00120 
00121   /*
00122    * Empty array of scale Boolean views
00123    *
00124    */
00125   forceinline
00126   EmptyScaleBoolArray::EmptyScaleBoolArray(void) {}
00127   forceinline
00128   EmptyScaleBoolArray::EmptyScaleBoolArray(Space&, int) {}
00129   forceinline void
00130   EmptyScaleBoolArray::subscribe(Space&, Propagator&) {}
00131   forceinline void
00132   EmptyScaleBoolArray::cancel(Space&, Propagator&) {}
00133   forceinline void
00134   EmptyScaleBoolArray::reschedule(Space&, Propagator&) {}
00135   forceinline void
00136   EmptyScaleBoolArray::update(Space&, bool, EmptyScaleBoolArray&) {}
00137   forceinline ScaleBool*
00138   EmptyScaleBoolArray::fst(void) const { return NULL; }
00139   forceinline ScaleBool*
00140   EmptyScaleBoolArray::lst(void) const { return NULL; }
00141   forceinline void
00142   EmptyScaleBoolArray::fst(ScaleBool*) {}
00143   forceinline void
00144   EmptyScaleBoolArray::lst(ScaleBool*) {}
00145   forceinline bool
00146   EmptyScaleBoolArray::empty(void) const { return true; }
00147   forceinline int
00148   EmptyScaleBoolArray::size(void) const { return 0; }
00149   forceinline void
00150   EmptyScaleBoolArray::sort(void) {}
00151 
00152 
00153   /*
00154    * Base-class for Boolean constraints with coefficients
00155    *
00156    */
00157 
00158   template<class SBAP, class SBAN, class VX, PropCond pcx>
00159   forceinline
00160   LinBoolScale<SBAP,SBAN,VX,pcx>::LinBoolScale(Home home,
00161                                                SBAP& p0, SBAN& n0,
00162                                                VX x0, int c0)
00163     : Propagator(home), p(p0), n(n0), x(x0), c(c0) {
00164     x.subscribe(home,*this,pcx);
00165     p.subscribe(home,*this);
00166     n.subscribe(home,*this);
00167   }
00168 
00169   template<class SBAP, class SBAN, class VX, PropCond pcx>
00170   PropCost
00171   LinBoolScale<SBAP,SBAN,VX,pcx>::cost(const Space&,
00172                                        const ModEventDelta&) const {
00173     return PropCost::linear(PropCost::LO, p.size() + n.size());
00174   }
00175 
00176   template<class SBAP, class SBAN, class VX, PropCond pcx>
00177   void
00178   LinBoolScale<SBAP,SBAN,VX,pcx>::reschedule(Space& home) {
00179     x.reschedule(home,*this,pcx);
00180     p.reschedule(home,*this);
00181     n.reschedule(home,*this);
00182   }
00183 
00184   template<class SBAP, class SBAN, class VX, PropCond pcx>
00185   forceinline size_t
00186   LinBoolScale<SBAP,SBAN,VX,pcx>::dispose(Space& home) {
00187     x.cancel(home,*this,pcx);
00188     p.cancel(home,*this);
00189     n.cancel(home,*this);
00190     (void) Propagator::dispose(home);
00191     return sizeof(*this);
00192   }
00193 
00194   template<class SBAP, class SBAN, class VX, PropCond pcx>
00195   forceinline
00196   LinBoolScale<SBAP,SBAN,VX,pcx>::LinBoolScale(Space& home, bool share,
00197                                                Propagator& pr,
00198                                                SBAP& p0, SBAN& n0,
00199                                                VX x0, int c0)
00200     : Propagator(home,share,pr), c(c0) {
00201     x.update(home,share,x0);
00202     p.update(home,share,p0);
00203     n.update(home,share,n0);
00204   }
00205 
00206   /*
00207    * Boolean equality with coefficients
00208    *
00209    */
00210 
00211   template<class SBAP, class SBAN, class VX>
00212   forceinline
00213   EqBoolScale<SBAP,SBAN,VX>::EqBoolScale(Home home,
00214                                          SBAP& p, SBAN& n,
00215                                          VX x, int c)
00216     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,p,n,x,c) {}
00217 
00218   template<class SBAP, class SBAN, class VX>
00219   forceinline
00220   EqBoolScale<SBAP,SBAN,VX>::EqBoolScale(Space& home, bool share,
00221                                          Propagator& pr,
00222                                          SBAP& p, SBAN& n,
00223                                          VX x, int c)
00224     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,share,pr,p,n,x,c) {}
00225 
00226   template<class SBAP, class SBAN, class VX>
00227   Actor*
00228   EqBoolScale<SBAP,SBAN,VX>::copy(Space& home, bool share) {
00229     if (p.empty()) {
00230       EmptyScaleBoolArray ep;
00231       if (x.assigned()) {
00232         ZeroIntView z;
00233         return new (home) EqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView>
00234           (home,share,*this,ep,n,z,c+x.val());
00235       } else {
00236         return new (home) EqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00237           (home,share,*this,ep,n,x,c);
00238       }
00239     } else if (n.empty()) {
00240       EmptyScaleBoolArray en;
00241       if (x.assigned()) {
00242         ZeroIntView z;
00243         return new (home) EqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView>
00244           (home,share,*this,p,en,z,c+x.val());
00245       } else {
00246         return new (home) EqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00247           (home,share,*this,p,en,x,c);
00248       }
00249     } else {
00250       return new (home) EqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c);
00251     }
00252   }
00253 
00254   template<class SBAP, class SBAN, class VX>
00255   ExecStatus
00256   EqBoolScale<SBAP,SBAN,VX>::propagate(Space& home, const ModEventDelta& med) {
00257     int sl_p = 0; // Lower bound, computed positive
00258     int su_n = 0; // Upper bound, computed negative
00259     if (BoolView::me(med) == ME_BOOL_VAL) {
00260       // Eliminate assigned positive views while keeping order
00261       {
00262         // Skip not assigned views
00263         ScaleBool* f = p.fst();
00264         ScaleBool* l = p.lst();
00265         while ((f < l) && f->x.none()) {
00266           su_n += f->a; f++;
00267         }
00268         // Copy unassigned views to t
00269         ScaleBool* t = f;
00270         while (f < l) {
00271           if (f->x.one()) {
00272             c -= f->a;
00273           } else if (f->x.none()) {
00274             su_n += f->a; *t = *f; t++;
00275           }
00276           f++;
00277         }
00278         p.lst(t);
00279       }
00280       // Eliminate assigned negative views while keeping order
00281       {
00282         // Skip not assigned views
00283         ScaleBool* f = n.fst();
00284         ScaleBool* l = n.lst();
00285         while ((f < l) && f->x.none()) {
00286           sl_p += f->a; f++;
00287         }
00288         // Copy unassigned views to t
00289         ScaleBool* t = f;
00290         while (f < l) {
00291           if (f->x.one()) {
00292             c += f->a;
00293           } else if (f->x.none()) {
00294             sl_p += f->a; *t = *f; t++;
00295           }
00296           f++;
00297         }
00298         n.lst(t);
00299       }
00300     } else {
00301       for (ScaleBool* f=p.fst(); f<p.lst(); f++)
00302         su_n += f->a;
00303       for (ScaleBool* f=n.fst(); f<n.lst(); f++)
00304         sl_p += f->a;
00305     }
00306 
00307     if (p.empty() && n.empty()) {
00308       GECODE_ME_CHECK(x.eq(home,-c));
00309       return home.ES_SUBSUMED(*this);
00310     }
00311 
00312     sl_p += x.max() + c;
00313     su_n -= x.min() + c;
00314 
00315     const int MOD_SL = 1 << 0;
00316     const int MOD_SU = 1 << 1;
00317 
00318     int mod = MOD_SL | MOD_SU;
00319 
00320     do {
00321       if ((mod & MOD_SL) != 0) {
00322         mod -= MOD_SL;
00323         // Propagate lower bound for positive Boolean views
00324         {
00325           ScaleBool* f=p.fst();
00326           for (ScaleBool* l=p.lst(); (f < l) && (f->a > sl_p); f++) {
00327             GECODE_ME_CHECK(f->x.zero_none(home));
00328             su_n -= f->a;
00329           }
00330           if (f > p.fst()) {
00331             p.fst(f); mod |= MOD_SU;
00332           }
00333         }
00334         // Propagate lower bound for negative Boolean views
00335         {
00336           ScaleBool* f=n.fst();
00337           for (ScaleBool* l=n.lst(); (f < l) && (f->a > sl_p); f++) {
00338             GECODE_ME_CHECK(f->x.one_none(home)); c += f->a;
00339             su_n -= f->a;
00340           }
00341           if (f > n.fst()) {
00342             n.fst(f); mod |= MOD_SU;
00343           }
00344         }
00345         // Propagate lower bound for integer view
00346         {
00347           const int x_min = x.min();
00348           ModEvent me = x.gq(home,x.max() - sl_p);
00349           if (me_failed(me))
00350             return ES_FAILED;
00351           if (me_modified(me)) {
00352             su_n -= x.min() - x_min;
00353             mod |= MOD_SU;
00354           }
00355         }
00356       }
00357       if ((mod & MOD_SU) != 0) {
00358         mod -= MOD_SU;
00359         // Propagate upper bound for positive Boolean views
00360         {
00361           ScaleBool* f=p.fst();
00362           for (ScaleBool* l=p.lst(); (f < l) && (f->a > su_n); f++) {
00363             GECODE_ME_CHECK(f->x.one_none(home)); c -= f->a;
00364             sl_p -= f->a;
00365           }
00366           if (f > p.fst()) {
00367             p.fst(f); mod |= MOD_SL;;
00368           }
00369         }
00370         // Propagate upper bound for negative Boolean views
00371         {
00372           ScaleBool* f=n.fst();
00373           for (ScaleBool* l=n.lst(); (f < l) && (f->a > su_n); f++) {
00374             GECODE_ME_CHECK(f->x.zero_none(home));
00375             sl_p -= f->a;
00376           }
00377           if (f > n.fst()) {
00378             n.fst(f); mod |= MOD_SL;;
00379           }
00380         }
00381         // Propagate upper bound for integer view
00382         {
00383           const int x_max = x.max();
00384           ModEvent me = x.lq(home,x.min() + su_n);
00385           if (me_failed(me))
00386             return ES_FAILED;
00387           if (me_modified(me)) {
00388             sl_p += x.max() - x_max;
00389             mod |= MOD_SL;;
00390           }
00391         }
00392       }
00393     } while (mod != 0);
00394 
00395     return (sl_p == -su_n) ? home.ES_SUBSUMED(*this) : ES_FIX;
00396   }
00397 
00398 
00399 
00400   template<class SBAP, class SBAN, class VX>
00401   ExecStatus
00402   EqBoolScale<SBAP,SBAN,VX>::post(Home home,
00403                                   SBAP& p, SBAN& n, VX x, int c) {
00404     p.sort(); n.sort();
00405     if (p.empty()) {
00406       EmptyScaleBoolArray ep;
00407       (void) new (home) EqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00408         (home,ep,n,x,c);
00409     } else if (n.empty()) {
00410       EmptyScaleBoolArray en;
00411       (void) new (home) EqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00412         (home,p,en,x,c);
00413     } else {
00414       (void) new (home) EqBoolScale<SBAP,SBAN,VX>
00415         (home,p,n,x,c);
00416     }
00417     return ES_OK;
00418   }
00419 
00420 
00421   /*
00422    * Boolean inequality with coefficients
00423    *
00424    */
00425 
00426   template<class SBAP, class SBAN, class VX>
00427   forceinline
00428   LqBoolScale<SBAP,SBAN,VX>::LqBoolScale(Home home,
00429                                          SBAP& p, SBAN& n,
00430                                          VX x, int c)
00431     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,p,n,x,c) {}
00432 
00433   template<class SBAP, class SBAN, class VX>
00434   forceinline
00435   LqBoolScale<SBAP,SBAN,VX>::LqBoolScale(Space& home, bool share,
00436                                          Propagator& pr,
00437                                          SBAP& p, SBAN& n,
00438                                          VX x, int c)
00439     : LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,share,pr,p,n,x,c) {}
00440 
00441   template<class SBAP, class SBAN, class VX>
00442   Actor*
00443   LqBoolScale<SBAP,SBAN,VX>::copy(Space& home, bool share) {
00444     if (p.empty()) {
00445       EmptyScaleBoolArray ep;
00446       if (x.assigned()) {
00447         ZeroIntView z;
00448         return new (home) LqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView>
00449           (home,share,*this,ep,n,z,c+x.val());
00450       } else {
00451         return new (home) LqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00452           (home,share,*this,ep,n,x,c);
00453       }
00454     } else if (n.empty()) {
00455       EmptyScaleBoolArray en;
00456       if (x.assigned()) {
00457         ZeroIntView z;
00458         return new (home) LqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView>
00459           (home,share,*this,p,en,z,c+x.val());
00460       } else {
00461         return new (home) LqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00462           (home,share,*this,p,en,x,c);
00463       }
00464     } else {
00465       return new (home) LqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c);
00466     }
00467   }
00468 
00469   template<class SBAP, class SBAN, class VX>
00470   ExecStatus
00471   LqBoolScale<SBAP,SBAN,VX>::propagate(Space& home, const ModEventDelta& med) {
00472     int sl = 0;
00473     if (BoolView::me(med) == ME_BOOL_VAL) {
00474       // Eliminate assigned positive views while keeping order
00475       {
00476         // Skip not assigned views
00477         ScaleBool* f = p.fst();
00478         ScaleBool* l = p.lst();
00479         while ((f < l) && f->x.none())
00480           f++;
00481         // Copy unassigned views to t
00482         ScaleBool* t = f;
00483         while (f < l) {
00484           if (f->x.one()) {
00485             c -= f->a;
00486           } else if (f->x.none()) {
00487             *t = *f; t++;
00488           }
00489           f++;
00490         }
00491         p.lst(t);
00492       }
00493       // Eliminate assigned negative views while keeping order
00494       {
00495         // Skip not assigned views
00496         ScaleBool* f = n.fst();
00497         ScaleBool* l = n.lst();
00498         while ((f < l) && f->x.none()) {
00499           sl += f->a; f++;
00500         }
00501         // Copy unassigned views to t
00502         ScaleBool* t = f;
00503         while (f < l) {
00504           if (f->x.one()) {
00505             c += f->a;
00506           } else if (f->x.none()) {
00507             sl += f->a; *t = *f; t++;
00508           }
00509           f++;
00510         }
00511         n.lst(t);
00512       }
00513     } else {
00514       for (ScaleBool* f=n.fst(); f<n.lst(); f++)
00515         sl += f->a;
00516     }
00517 
00518     sl += x.max() + c;
00519 
00520     // Propagate upper bound for positive Boolean views
00521     {
00522       ScaleBool* f=p.fst();
00523       for (ScaleBool* l=p.lst(); (f < l) && (f->a > sl); f++)
00524         GECODE_ME_CHECK(f->x.zero_none(home));
00525       p.fst(f);
00526     }
00527     // Propagate lower bound for negative Boolean views
00528     {
00529       ScaleBool* f=n.fst();
00530       for (ScaleBool* l=n.lst(); (f < l) && (f->a > sl); f++) {
00531         c += f->a;
00532         GECODE_ME_CHECK(f->x.one_none(home));
00533       }
00534       n.fst(f);
00535     }
00536     ExecStatus es = ES_FIX;
00537     // Propagate lower bound for integer view
00538     {
00539       const int slx = x.max() - sl;
00540       ModEvent me = x.gq(home,slx);
00541       if (me_failed(me))
00542         return ES_FAILED;
00543       if (me_modified(me) && (slx != x.min()))
00544         es = ES_NOFIX;
00545     }
00546 
00547     if (p.empty() && n.empty())
00548       return home.ES_SUBSUMED(*this);
00549 
00550     return es;
00551   }
00552 
00553 
00554 
00555   template<class SBAP, class SBAN, class VX>
00556   ExecStatus
00557   LqBoolScale<SBAP,SBAN,VX>::post(Home home,
00558                                   SBAP& p, SBAN& n, VX x, int c) {
00559     p.sort(); n.sort();
00560     if (p.empty()) {
00561       EmptyScaleBoolArray ep;
00562       (void) new (home) LqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00563         (home,ep,n,x,c);
00564     } else if (n.empty()) {
00565       EmptyScaleBoolArray en;
00566       (void) new (home) LqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00567         (home,p,en,x,c);
00568     } else {
00569       (void) new (home) LqBoolScale<SBAP,SBAN,VX>
00570         (home,p,n,x,c);
00571     }
00572     return ES_OK;
00573   }
00574 
00575   /*
00576    * Boolean disequality with coefficients
00577    *
00578    */
00579 
00580   template<class SBAP, class SBAN, class VX>
00581   forceinline
00582   NqBoolScale<SBAP,SBAN,VX>::NqBoolScale(Home home,
00583                                          SBAP& p, SBAN& n,
00584                                          VX x, int c)
00585     : LinBoolScale<SBAP,SBAN,VX,PC_INT_VAL>(home,p,n,x,c) {}
00586 
00587   template<class SBAP, class SBAN, class VX>
00588   forceinline
00589   NqBoolScale<SBAP,SBAN,VX>::NqBoolScale(Space& home, bool share,
00590                                          Propagator& pr,
00591                                          SBAP& p, SBAN& n,
00592                                          VX x, int c)
00593     : LinBoolScale<SBAP,SBAN,VX,PC_INT_VAL>(home,share,pr,p,n,x,c) {}
00594 
00595   template<class SBAP, class SBAN, class VX>
00596   Actor*
00597   NqBoolScale<SBAP,SBAN,VX>::copy(Space& home, bool share) {
00598     if (p.empty()) {
00599       EmptyScaleBoolArray ep;
00600       if (x.assigned()) {
00601         ZeroIntView z;
00602         return new (home) NqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView>
00603           (home,share,*this,ep,n,z,c+x.val());
00604       } else {
00605         return new (home) NqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00606           (home,share,*this,ep,n,x,c);
00607       }
00608     } else if (n.empty()) {
00609       EmptyScaleBoolArray en;
00610       if (x.assigned()) {
00611         ZeroIntView z;
00612         return new (home) NqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView>
00613           (home,share,*this,p,en,z,c+x.val());
00614       } else {
00615         return new (home) NqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00616           (home,share,*this,p,en,x,c);
00617       }
00618     } else {
00619       return new (home) NqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c);
00620     }
00621   }
00622 
00623   template<class SBAP, class SBAN, class VX>
00624   ExecStatus
00625   NqBoolScale<SBAP,SBAN,VX>::propagate(Space& home, const ModEventDelta& med) {
00626     if (BoolView::me(med) == ME_BOOL_VAL) {
00627       // Eliminate assigned positive views
00628       {
00629         ScaleBool* f = p.fst();
00630         ScaleBool* t = f;
00631         ScaleBool* l = p.lst();
00632         while (f < l) {
00633           if (f->x.one()) {
00634             c -= f->a; *f = *(t++);
00635           } else if (f->x.zero()) {
00636             *f = *(t++);
00637           }
00638           f++;
00639         }
00640         p.fst(t);
00641       }
00642       // Eliminate assigned negative views
00643       {
00644         ScaleBool* f = n.fst();
00645         ScaleBool* t = f;
00646         ScaleBool* l = n.lst();
00647         while (f < l) {
00648           if (f->x.one()) {
00649             c += f->a; *f = *(t++);
00650           } else if (f->x.zero()) {
00651             *f = *(t++);
00652           }
00653           f++;
00654         }
00655         n.fst(t);
00656       }
00657     }
00658 
00659     if (p.empty() && n.empty()) {
00660       GECODE_ME_CHECK(x.nq(home,-c));
00661       return home.ES_SUBSUMED(*this);
00662     }
00663 
00664     if (x.assigned()) {
00665       int r = x.val()+c;
00666       if (p.empty() && (n.size() == 1)) {
00667         if (r == -n.fst()->a) {
00668           GECODE_ME_CHECK(n.fst()->x.zero_none(home));
00669         } else if (r == 0) {
00670           GECODE_ME_CHECK(n.fst()->x.one_none(home));
00671         }
00672         return home.ES_SUBSUMED(*this);
00673       }
00674       if ((p.size() == 1) && n.empty()) {
00675         if (r == p.fst()->a) {
00676           GECODE_ME_CHECK(p.fst()->x.zero_none(home));
00677         } else if (r == 0) {
00678           GECODE_ME_CHECK(p.fst()->x.one_none(home));
00679         }
00680         return home.ES_SUBSUMED(*this);
00681       }
00682     }
00683     return ES_FIX;
00684   }
00685 
00686 
00687 
00688   template<class SBAP, class SBAN, class VX>
00689   ExecStatus
00690   NqBoolScale<SBAP,SBAN,VX>::post(Home home,
00691                                   SBAP& p, SBAN& n, VX x, int c) {
00692     if (p.empty()) {
00693       EmptyScaleBoolArray ep;
00694       (void) new (home) NqBoolScale<EmptyScaleBoolArray,SBAN,VX>
00695         (home,ep,n,x,c);
00696     } else if (n.empty()) {
00697       EmptyScaleBoolArray en;
00698       (void) new (home) NqBoolScale<SBAP,EmptyScaleBoolArray,VX>
00699         (home,p,en,x,c);
00700     } else {
00701       (void) new (home) NqBoolScale<SBAP,SBAN,VX>
00702         (home,p,n,x,c);
00703     }
00704     return ES_OK;
00705   }
00706 
00707 }}}
00708 
00709 // STATISTICS: int-prop
00710