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

bool-int.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  *     Tias Guns <tias.guns@cs.kuleuven.be>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2006
00009  *     Tias Guns, 2009
00010  *
00011  *  Last modified:
00012  *     $Date: 2016-06-29 17:28:17 +0200 (Wed, 29 Jun 2016) $ by $Author: schulte $
00013  *     $Revision: 15137 $
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 <algorithm>
00041 
00042 #include <gecode/int/bool.hh>
00043 
00044 namespace Gecode { namespace Int { namespace Linear {
00045 
00046   /*
00047    * Baseclass for integer Boolean sum using dependencies
00048    *
00049    */
00050   template<class VX>
00051   forceinline
00052   LinBoolInt<VX>::LinBoolInt(Home home, ViewArray<VX>& x0,
00053                              int n_s, int c0)
00054     : Propagator(home), co(home), x(x0), n_as(n_s), n_hs(n_s), c(c0) {
00055     Advisor* a = new (home) Advisor(home,*this,co);
00056     for (int i=n_as; i--; )
00057       x[i].subscribe(home,*a);
00058   }
00059 
00060   template<class VX>
00061   forceinline void
00062   LinBoolInt<VX>::normalize(void) {
00063     if (n_as != n_hs) {
00064       // Remove views for which no more subscriptions exist
00065       int n_x = x.size();
00066       for (int i=n_hs; i--; )
00067         if (!x[i].none()) {
00068           x[i]=x[--n_hs]; x[n_hs]=x[--n_x];
00069         }
00070       x.size(n_x);
00071     }
00072     assert(n_as == n_hs);
00073     // Remove assigned yet unsubscribed views
00074     {
00075       int n_x = x.size();
00076       for (int i=n_x-1; i>=n_hs; i--)
00077         if (x[i].one()) {
00078           c--; x[i]=x[--n_x];
00079         } else if (x[i].zero()) {
00080           x[i]=x[--n_x];
00081         }
00082       x.size(n_x);
00083     }
00084   }
00085 
00086   template<class VX>
00087   forceinline
00088   LinBoolInt<VX>::LinBoolInt(Space& home, bool share, LinBoolInt<VX>& p)
00089     : Propagator(home,share,p), n_as(p.n_as), n_hs(n_as) {
00090     p.normalize();
00091     c=p.c;
00092     co.update(home,share,p.co);
00093     x.update(home,share,p.x);
00094   }
00095 
00096   template<class VX>
00097   PropCost
00098   LinBoolInt<VX>::cost(const Space&, const ModEventDelta&) const {
00099     return PropCost::unary(PropCost::HI);
00100   }
00101 
00102   template<class VX>
00103   forceinline size_t
00104   LinBoolInt<VX>::dispose(Space& home) {
00105     Advisors<Advisor> as(co);
00106     for (int i=n_hs; i--; )
00107       x[i].cancel(home,as.advisor());
00108     co.dispose(home);
00109     (void) Propagator::dispose(home);
00110     return sizeof(*this);
00111   }
00112 
00113   /*
00114    * Greater or equal propagator (integer rhs)
00115    *
00116    */
00117   template<class VX>
00118   forceinline
00119   GqBoolInt<VX>::GqBoolInt(Home home, ViewArray<VX>& x, int c)
00120     : LinBoolInt<VX>(home,x,c+1,c) {}
00121 
00122   template<class VX>
00123   forceinline
00124   GqBoolInt<VX>::GqBoolInt(Space& home, bool share, GqBoolInt<VX>& p)
00125     : LinBoolInt<VX>(home,share,p) {}
00126 
00127   template<class VX>
00128   Actor*
00129   GqBoolInt<VX>::copy(Space& home, bool share) {
00130     return new (home) GqBoolInt<VX>(home,share,*this);
00131   }
00132 
00133   template<class VX>
00134   ExecStatus
00135   GqBoolInt<VX>::advise(Space& home, Advisor& a, const Delta& d) {
00136     // Check whether propagator is running
00137     if (n_as == 0)
00138       return ES_FIX;
00139 
00140     if (VX::one(d)) {
00141       c--; goto check;
00142     }
00143     if (c+1 < n_as)
00144       goto check;
00145     // Find a new subscription
00146     for (int i = x.size()-1; i>=n_hs; i--)
00147       if (x[i].none()) {
00148         std::swap(x[i],x[n_hs]);
00149         x[n_hs++].subscribe(home,a);
00150         x.size(i+1);
00151         return ES_FIX;
00152       } else if (x[i].one()) {
00153         c--;
00154         if (c+1 < n_as) {
00155           x.size(i);
00156           assert(n_hs <= x.size());
00157           goto check;
00158         }
00159       }
00160     // No view left for subscription
00161     x.size(n_hs);
00162   check:
00163     // Do not update subscription
00164     n_as--;
00165     int n = x.size()-n_hs+n_as;
00166     if ((n < c) && !disabled())
00167       return ES_FAILED;
00168     if ((c <= 0) || (c == n))
00169       return ES_NOFIX;
00170     else
00171       return ES_FIX;
00172   }
00173 
00174   template<class VX>
00175   void
00176   GqBoolInt<VX>::reschedule(Space& home) {
00177     int n = x.size()-n_hs+n_as;
00178     if ((c <= 0) || (c >= n))
00179       VX::schedule(home,*this,ME_INT_VAL);
00180   }
00181 
00182   template<class VX>
00183   ExecStatus
00184   GqBoolInt<VX>::propagate(Space& home, const ModEventDelta&) {
00185     // Check for failure due to a disabled propagator
00186     if (x.size() - n_hs + n_as < c)
00187       return ES_FAILED;
00188     if (c > 0) {
00189       assert((n_as == c) && (x.size() == n_hs));
00190       // Signal that propagator is running
00191       n_as = 0;
00192       // All views must be one to satisfy inequality
00193       for (int i=n_hs; i--; )
00194         if (x[i].none())
00195           GECODE_ME_CHECK(x[i].one_none(home));
00196     }
00197     return home.ES_SUBSUMED(*this);
00198   }
00199 
00200   template<class VX>
00201   ExecStatus
00202   GqBoolInt<VX>::post(Home home, ViewArray<VX>& x, int c) {
00203     // Eliminate assigned views
00204     int n_x = x.size();
00205     for (int i=n_x; i--; )
00206       if (x[i].zero()) {
00207         x[i] = x[--n_x];
00208       } else if (x[i].one()) {
00209         x[i] = x[--n_x]; c--;
00210       }
00211     x.size(n_x);
00212     // RHS too large
00213     if (n_x < c)
00214       return ES_FAILED;
00215     // Whatever the x[i] take for values, the inequality is subsumed
00216     if (c <= 0)
00217       return ES_OK;
00218     // Use Boolean disjunction for this special case
00219     if (c == 1)
00220       return Bool::NaryOrTrue<VX>::post(home,x);
00221     // All views must be one to satisfy inequality
00222     if (c == n_x) {
00223       for (int i=n_x; i--; )
00224         GECODE_ME_CHECK(x[i].one_none(home));
00225       return ES_OK;
00226     }
00227     // This is the needed invariant as c+1 subscriptions must be created
00228     assert(n_x > c);
00229     (void) new (home) GqBoolInt<VX>(home,x,c);
00230     return ES_OK;
00231   }
00232 
00233 
00234 
00235 
00236   /*
00237    * Equal propagator (integer rhs)
00238    *
00239    */
00240   template<class VX>
00241   forceinline
00242   EqBoolInt<VX>::EqBoolInt(Home home, ViewArray<VX>& x, int c)
00243     : LinBoolInt<VX>(home,x,std::max(c,x.size()-c)+1,c) {}
00244 
00245   template<class VX>
00246   forceinline
00247   EqBoolInt<VX>::EqBoolInt(Space& home, bool share, EqBoolInt<VX>& p)
00248     : LinBoolInt<VX>(home,share,p) {}
00249 
00250   template<class VX>
00251   Actor*
00252   EqBoolInt<VX>::copy(Space& home, bool share) {
00253     return new (home) EqBoolInt<VX>(home,share,*this);
00254   }
00255 
00256   template<class VX>
00257   ExecStatus
00258   EqBoolInt<VX>::advise(Space& home, Advisor& a, const Delta& d) {
00259     // Check whether propagator is running
00260     if (n_as == 0)
00261       return ES_FIX;
00262 
00263     if (VX::one(d))
00264       c--;
00265     if ((c+1 < n_as) && (x.size()-n_hs < c))
00266       goto check;
00267     // Find a new subscription
00268     for (int i = x.size()-1; i>=n_hs; i--)
00269       if (x[i].none()) {
00270         std::swap(x[i],x[n_hs]);
00271         x[n_hs++].subscribe(home,a);
00272         x.size(i+1);
00273         return ES_FIX;
00274       } else if (x[i].one()) {
00275         c--;
00276       }
00277     // No view left for subscription
00278     x.size(n_hs);
00279   check:
00280     // Do not update subscription
00281     n_as--;
00282     int n = x.size()-n_hs+n_as;
00283     if (((c < 0) || (c > n)) && !disabled())
00284       return ES_FAILED;
00285     if ((c == 0) || (c == n))
00286       return ES_NOFIX;
00287     else
00288       return ES_FIX;
00289   }
00290 
00291   template<class VX>
00292   void
00293   EqBoolInt<VX>::reschedule(Space& home) {
00294     int n = x.size()-n_hs+n_as;
00295     if ((c <= 0) || (c >= n))
00296       VX::schedule(home,*this,ME_INT_VAL);
00297   }
00298 
00299   template<class VX>
00300   ExecStatus
00301   EqBoolInt<VX>::propagate(Space& home, const ModEventDelta&) {
00302     // Check for failure due to being disabled before
00303     if ((c < 0) || (c > x.size()-n_hs+n_as))
00304       return ES_FAILED;
00305 
00306     assert(x.size() == n_hs);
00307     // Signal that propagator is running
00308     n_as = 0;
00309     if (c == 0) {
00310       // All views must be zero to satisfy equality
00311       for (int i=n_hs; i--; )
00312         if (x[i].none())
00313           GECODE_ME_CHECK(x[i].zero_none(home));
00314     } else {
00315       // All views must be one to satisfy equality
00316       for (int i=n_hs; i--; )
00317         if (x[i].none())
00318           GECODE_ME_CHECK(x[i].one_none(home));
00319     }
00320     return home.ES_SUBSUMED(*this);
00321   }
00322 
00323   template<class VX>
00324   ExecStatus
00325   EqBoolInt<VX>::post(Home home, ViewArray<VX>& x, int c) {
00326     // Eliminate assigned views
00327     int n_x = x.size();
00328     for (int i=n_x; i--; )
00329       if (x[i].zero()) {
00330         x[i] = x[--n_x];
00331       } else if (x[i].one()) {
00332         x[i] = x[--n_x]; c--;
00333       }
00334     x.size(n_x);
00335     // RHS too small or too large
00336     if ((c < 0) || (c > n_x))
00337       return ES_FAILED;
00338     // All views must be zero to satisfy equality
00339     if (c == 0) {
00340       for (int i=n_x; i--; )
00341         GECODE_ME_CHECK(x[i].zero_none(home));
00342       return ES_OK;
00343     }
00344     // All views must be one to satisfy equality
00345     if (c == n_x) {
00346       for (int i=n_x; i--; )
00347         GECODE_ME_CHECK(x[i].one_none(home));
00348       return ES_OK;
00349     }
00350     (void) new (home) EqBoolInt<VX>(home,x,c);
00351     return ES_OK;
00352   }
00353 
00354 
00355   /*
00356    * Integer disequal to Boolean sum
00357    *
00358    */
00359 
00360   template<class VX>
00361   forceinline
00362   NqBoolInt<VX>::NqBoolInt(Home home, ViewArray<VX>& b, int c0)
00363     : BinaryPropagator<VX,PC_INT_VAL>(home,
00364                                       b[b.size()-2],
00365                                       b[b.size()-1]), x(b), c(c0) {
00366     assert(x.size() >= 2);
00367     x.size(x.size()-2);
00368   }
00369 
00370   template<class VX>
00371   forceinline size_t
00372   NqBoolInt<VX>::dispose(Space& home) {
00373     (void) BinaryPropagator<VX,PC_INT_VAL>::dispose(home);
00374     return sizeof(*this);
00375   }
00376 
00377   template<class VX>
00378   forceinline
00379   NqBoolInt<VX>::NqBoolInt(Space& home, bool share, NqBoolInt<VX>& p)
00380     : BinaryPropagator<VX,PC_INT_VAL>(home,share,p), x(home,p.x.size()) {
00381     // Eliminate all zeros and ones in original and update
00382     int n = p.x.size();
00383     int p_c = p.c;
00384     for (int i=n; i--; )
00385       if (p.x[i].zero()) {
00386         n--; p.x[i]=p.x[n]; x[i]=x[n];
00387       } else if (p.x[i].one()) {
00388         n--; p_c--; p.x[i]=p.x[n]; x[i]=x[n];
00389       } else {
00390         x[i].update(home,share,p.x[i]);
00391       }
00392     c = p_c; p.c = p_c;
00393     x.size(n); p.x.size(n);
00394   }
00395 
00396   template<class VX>
00397   forceinline ExecStatus
00398   NqBoolInt<VX>::post(Home home, ViewArray<VX>& x, int c) {
00399     int n = x.size();
00400     for (int i=n; i--; )
00401       if (x[i].one()) {
00402         x[i]=x[--n]; c--;
00403       } else if (x[i].zero()) {
00404         x[i]=x[--n];
00405       }
00406     x.size(n);
00407     if ((n < c) || (c < 0))
00408       return ES_OK;
00409     if (n == 0)
00410       return (c == 0) ? ES_FAILED : ES_OK;
00411     if (n == 1) {
00412       if (c == 1) {
00413         GECODE_ME_CHECK(x[0].zero_none(home));
00414       } else {
00415         GECODE_ME_CHECK(x[0].one_none(home));
00416       }
00417       return ES_OK;
00418     }
00419     (void) new (home) NqBoolInt(home,x,c);
00420     return ES_OK;
00421   }
00422 
00423   template<class VX>
00424   Actor*
00425   NqBoolInt<VX>::copy(Space& home, bool share) {
00426     return new (home) NqBoolInt<VX>(home,share,*this);
00427   }
00428 
00429   template<class VX>
00430   PropCost
00431   NqBoolInt<VX>::cost(const Space&, const ModEventDelta&) const {
00432     return PropCost::linear(PropCost::LO, x.size());
00433   }
00434 
00435   template<class VX>
00436   forceinline bool
00437   NqBoolInt<VX>::resubscribe(Space& home, VX& y) {
00438     if (y.one())
00439       c--;
00440     int n = x.size();
00441     for (int i=n; i--; )
00442       if (x[i].one()) {
00443         c--; x[i]=x[--n];
00444       } else if (x[i].zero()) {
00445         x[i] = x[--n];
00446       } else {
00447         // New unassigned view found
00448         assert(!x[i].zero() && !x[i].one());
00449         // Move to y and subscribe
00450         y=x[i]; x[i]=x[--n];
00451         x.size(n);
00452         y.subscribe(home,*this,PC_INT_VAL,false);
00453         return true;
00454       }
00455     // All views have been assigned!
00456     x.size(0);
00457     return false;
00458   }
00459 
00460   template<class VX>
00461   ExecStatus
00462   NqBoolInt<VX>::propagate(Space& home, const ModEventDelta&) {
00463     bool s0 = true;
00464     if (x0.zero() || x0.one())
00465       s0 = resubscribe(home,x0);
00466     bool s1 = true;
00467     if (x1.zero() || x1.one())
00468       s1 = resubscribe(home,x1);
00469     int n = x.size() + s0 + s1;
00470     if ((n < c) || (c < 0))
00471       return home.ES_SUBSUMED(*this);
00472     if (n == 0)
00473       return (c == 0) ? ES_FAILED : home.ES_SUBSUMED(*this);
00474     if (n == 1) {
00475       if (s0) {
00476         if (c == 1) {
00477           GECODE_ME_CHECK(x0.zero_none(home));
00478         } else {
00479           GECODE_ME_CHECK(x0.one_none(home));
00480         }
00481       } else {
00482         assert(s1);
00483         if (c == 1) {
00484           GECODE_ME_CHECK(x1.zero_none(home));
00485         } else {
00486           GECODE_ME_CHECK(x1.one_none(home));
00487         }
00488       }
00489       return home.ES_SUBSUMED(*this);
00490     }
00491     return ES_FIX;
00492   }
00493 
00494   /*
00495    * Baseclass for reified integer Boolean sum
00496    *
00497    */
00498   template<class VX, class VB>
00499   forceinline
00500   ReLinBoolInt<VX,VB>::ReLinBoolInt(Home home, ViewArray<VX>& x0,
00501                                     int c0, VB b0)
00502     : Propagator(home), co(home), x(x0), n_s(x.size()), c(c0), b(b0) {
00503     x.subscribe(home,*new (home) Advisor(home,*this,co));
00504     b.subscribe(home,*this,PC_BOOL_VAL);
00505   }
00506 
00507   template<class VX, class VB>
00508   forceinline void
00509   ReLinBoolInt<VX,VB>::normalize(void) {
00510     if (n_s != x.size()) {
00511       int n_x = x.size();
00512       for (int i=n_x; i--; )
00513         if (!x[i].none())
00514           x[i] = x[--n_x];
00515       x.size(n_x);
00516       assert(x.size() == n_s);
00517     }
00518   }
00519 
00520   template<class VX, class VB>
00521   forceinline
00522   ReLinBoolInt<VX,VB>::ReLinBoolInt(Space& home, bool share,
00523                                     ReLinBoolInt<VX,VB>& p)
00524     : Propagator(home,share,p), n_s(p.n_s), c(p.c) {
00525     p.normalize();
00526     co.update(home,share,p.co);
00527     x.update(home,share,p.x);
00528     b.update(home,share,p.b);
00529   }
00530 
00531   template<class VX, class VB>
00532   forceinline size_t
00533   ReLinBoolInt<VX,VB>::dispose(Space& home) {
00534     Advisors<Advisor> as(co);
00535     x.cancel(home,as.advisor());
00536     co.dispose(home);
00537     b.cancel(home,*this,PC_BOOL_VAL);
00538     (void) Propagator::dispose(home);
00539     return sizeof(*this);
00540   }
00541 
00542   template<class VX, class VB>
00543   PropCost
00544   ReLinBoolInt<VX,VB>::cost(const Space&, const ModEventDelta&) const {
00545     return PropCost::unary(PropCost::HI);
00546   }
00547 
00548   template<>
00550   class BoolNegTraits<BoolView> {
00551   public:
00553     typedef NegBoolView NegView;
00555     static NegBoolView neg(BoolView x) {
00556       NegBoolView y(x); return y;
00557     }
00558   };
00559 
00560   template<>
00562   class BoolNegTraits<NegBoolView> {
00563   public:
00565     typedef BoolView NegView;
00567     static BoolView neg(NegBoolView x) {
00568       return x.base();
00569     }
00570   };
00571 
00572 
00573   /*
00574    * Reified greater or equal propagator (integer rhs)
00575    *
00576    */
00577   template<class VX, class VB, ReifyMode rm>
00578   forceinline
00579   ReGqBoolInt<VX,VB,rm>::ReGqBoolInt(Home home, ViewArray<VX>& x, int c, VB b)
00580     : ReLinBoolInt<VX,VB>(home,x,c,b) {}
00581 
00582   template<class VX, class VB, ReifyMode rm>
00583   forceinline
00584   ReGqBoolInt<VX,VB,rm>::ReGqBoolInt(Space& home, bool share,
00585                                      ReGqBoolInt<VX,VB,rm>& p)
00586     : ReLinBoolInt<VX,VB>(home,share,p) {}
00587 
00588   template<class VX, class VB, ReifyMode rm>
00589   Actor*
00590   ReGqBoolInt<VX,VB,rm>::copy(Space& home, bool share) {
00591     return new (home) ReGqBoolInt<VX,VB,rm>(home,share,*this);
00592   }
00593 
00594   template<class VX, class VB, ReifyMode rm>
00595   ExecStatus
00596   ReGqBoolInt<VX,VB,rm>::advise(Space&, Advisor&, const Delta& d) {
00597     if (VX::one(d))
00598       c--;
00599     n_s--;
00600     if ((n_s < c) || (c <= 0))
00601       return ES_NOFIX;
00602     else
00603       return ES_FIX;
00604   }
00605 
00606   template<class VX, class VB, ReifyMode rm>
00607   void
00608   ReGqBoolInt<VX,VB,rm>::reschedule(Space& home) {
00609     b.reschedule(home,*this,PC_BOOL_VAL);
00610     if ((n_s < c) || (c <= 0))
00611       VX::schedule(home,*this,ME_BOOL_VAL);
00612   }
00613 
00614   template<class VX, class VB, ReifyMode rm>
00615   ExecStatus
00616   ReGqBoolInt<VX,VB,rm>::propagate(Space& home, const ModEventDelta&) {
00617     if (b.none()) {
00618       if (c <= 0) {
00619         if (rm != RM_IMP)
00620           GECODE_ME_CHECK(b.one_none(home));
00621       } else {
00622         if (rm != RM_PMI)
00623           GECODE_ME_CHECK(b.zero_none(home));
00624       }
00625     } else {
00626       normalize();
00627       if (b.one()) {
00628         if (rm != RM_PMI)
00629           GECODE_REWRITE(*this,(GqBoolInt<VX>::post(home(*this),x,c)));
00630       } else {
00631         if (rm != RM_IMP) {
00632           ViewArray<typename BoolNegTraits<VX>::NegView> nx(home,x.size());
00633           for (int i=x.size(); i--; )
00634             nx[i]=BoolNegTraits<VX>::neg(x[i]);
00635           GECODE_REWRITE(*this,GqBoolInt<typename BoolNegTraits<VX>::NegView>
00636                          ::post(home(*this),nx,x.size()-c+1));
00637         }
00638       }
00639     }
00640     return home.ES_SUBSUMED(*this);
00641   }
00642 
00643   template<class VX, class VB, ReifyMode rm>
00644   ExecStatus
00645   ReGqBoolInt<VX,VB,rm>::post(Home home, ViewArray<VX>& x, int c, VB b) {
00646     assert(!b.assigned()); // checked before posting
00647 
00648     // Eliminate assigned views
00649     int n_x = x.size();
00650     for (int i=n_x; i--; )
00651       if (x[i].zero()) {
00652         x[i] = x[--n_x];
00653       } else if (x[i].one()) {
00654         x[i] = x[--n_x]; c--;
00655       }
00656     x.size(n_x);
00657     if (n_x < c) {
00658       // RHS too large
00659       if (rm != RM_PMI)
00660         GECODE_ME_CHECK(b.zero_none(home));
00661     } else if (c <= 0) {
00662       // Whatever the x[i] take for values, the inequality is subsumed
00663       if (rm != RM_IMP)
00664         GECODE_ME_CHECK(b.one_none(home));
00665     } else if ((c == 1) && (rm == RM_EQV)) {
00666       // Equivalent to Boolean disjunction
00667       return Bool::NaryOr<VX,VB>::post(home,x,b);
00668     } else if ((c == n_x) && (rm == RM_EQV)) {
00669       // Equivalent to Boolean conjunction, transform to Boolean disjunction
00670       ViewArray<typename BoolNegTraits<VX>::NegView> nx(home,n_x);
00671       for (int i=n_x; i--; )
00672         nx[i]=BoolNegTraits<VX>::neg(x[i]);
00673       return Bool::NaryOr
00674         <typename BoolNegTraits<VX>::NegView,
00675          typename BoolNegTraits<VB>::NegView>
00676         ::post(home,nx,BoolNegTraits<VB>::neg(b));
00677     } else {
00678       (void) new (home) ReGqBoolInt<VX,VB,rm>(home,x,c,b);
00679     }
00680     return ES_OK;
00681   }
00682 
00683   /*
00684    * Reified equal propagator (integer rhs)
00685    *
00686    */
00687   template<class VX, class VB, ReifyMode rm>
00688   forceinline
00689   ReEqBoolInt<VX,VB,rm>::ReEqBoolInt(Home home, ViewArray<VX>& x, int c, VB b)
00690     : ReLinBoolInt<VX,VB>(home,x,c,b) {}
00691 
00692   template<class VX, class VB, ReifyMode rm>
00693   forceinline
00694   ReEqBoolInt<VX,VB,rm>::ReEqBoolInt(Space& home, bool share,
00695                                      ReEqBoolInt<VX,VB,rm>& p)
00696     : ReLinBoolInt<VX,VB>(home,share,p) {}
00697 
00698   template<class VX, class VB, ReifyMode rm>
00699   Actor*
00700   ReEqBoolInt<VX,VB,rm>::copy(Space& home, bool share) {
00701     return new (home) ReEqBoolInt<VX,VB,rm>(home,share,*this);
00702   }
00703 
00704   template<class VX, class VB, ReifyMode rm>
00705   ExecStatus
00706   ReEqBoolInt<VX,VB,rm>::advise(Space&, Advisor&, const Delta& d) {
00707     if (VX::one(d))
00708       c--;
00709     n_s--;
00710 
00711     if ((c < 0) || (c > n_s) || (n_s == 0))
00712       return ES_NOFIX;
00713     else
00714       return ES_FIX;
00715   }
00716 
00717   template<class VX, class VB, ReifyMode rm>
00718   void
00719   ReEqBoolInt<VX,VB,rm>::reschedule(Space& home) {
00720     b.reschedule(home,*this,PC_BOOL_VAL);
00721     if ((c < 0) || (c > n_s) || (n_s == 0))
00722       VX::schedule(home,*this,ME_BOOL_VAL);
00723   }
00724 
00725   template<class VX, class VB, ReifyMode rm>
00726   ExecStatus
00727   ReEqBoolInt<VX,VB,rm>::propagate(Space& home, const ModEventDelta&) {
00728     if (b.none()) {
00729       if ((c == 0) && (n_s == 0)) {
00730         if (rm != RM_IMP)
00731           GECODE_ME_CHECK(b.one_none(home));
00732       } else {
00733         if (rm != RM_PMI)
00734           GECODE_ME_CHECK(b.zero_none(home));
00735       }
00736     } else {
00737       normalize();
00738       if (b.one()) {
00739         if (rm != RM_PMI)
00740           GECODE_REWRITE(*this,(EqBoolInt<VX>::post(home(*this),x,c)));
00741       } else {
00742         if (rm != RM_IMP)
00743           GECODE_REWRITE(*this,(NqBoolInt<VX>::post(home(*this),x,c)));
00744       }
00745     }
00746     return home.ES_SUBSUMED(*this);
00747   }
00748 
00749   template<class VX, class VB, ReifyMode rm>
00750   ExecStatus
00751   ReEqBoolInt<VX,VB,rm>::post(Home home, ViewArray<VX>& x, int c, VB b) {
00752     assert(!b.assigned()); // checked before posting
00753 
00754     // Eliminate assigned views
00755     int n_x = x.size();
00756     for (int i=n_x; i--; )
00757       if (x[i].zero()) {
00758         x[i] = x[--n_x];
00759       } else if (x[i].one()) {
00760         x[i] = x[--n_x]; c--;
00761       }
00762     x.size(n_x);
00763     if ((n_x < c) || (c < 0)) {
00764       // RHS too large
00765       if (rm != RM_PMI)
00766         GECODE_ME_CHECK(b.zero_none(home));
00767     } else if ((c == 0) && (n_x == 0)) {
00768       // all variables set, and c == 0: equality
00769       if (rm != RM_IMP)
00770         GECODE_ME_CHECK(b.one_none(home));
00771     } else if ((c == 0) && (rm == RM_EQV)) {
00772       // Equivalent to Boolean disjunction
00773       return Bool::NaryOr<VX,typename BoolNegTraits<VB>::NegView>
00774         ::post(home,x,BoolNegTraits<VB>::neg(b));
00775     } else if ((c == n_x) && (rm == RM_EQV)) {
00776       // Equivalent to Boolean conjunction, transform to Boolean disjunction
00777       ViewArray<typename BoolNegTraits<VX>::NegView> nx(home,n_x);
00778       for (int i=n_x; i--; )
00779         nx[i]=BoolNegTraits<VX>::neg(x[i]);
00780       return Bool::NaryOr
00781         <typename BoolNegTraits<VX>::NegView,
00782          typename BoolNegTraits<VB>::NegView>
00783         ::post(home,nx,BoolNegTraits<VB>::neg(b));
00784     } else {
00785       (void) new (home) ReEqBoolInt<VX,VB,rm>(home,x,c,b);
00786     }
00787     return ES_OK;
00788   }
00789 
00790 
00791 }}}
00792 
00793 // STATISTICS: int-prop
00794