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

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