Generated on Mon Jul 6 18:09:10 2009 for Gecode by doxygen 1.5.9

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: 2009-03-23 20:14:21 +0100 (Mon, 23 Mar 2009) $ by $Author: schulte $
00013  *     $Revision: 8514 $
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 namespace Gecode { namespace Int { namespace Linear {
00043 
00044   /*
00045    * Baseclass for integer Boolean sum using dependencies
00046    *
00047    */
00048   template <class VX>
00049   forceinline
00050   MemoryLinBoolInt<VX>::MemoryLinBoolInt(Space& home, ViewArray<VX>& x0,
00051                                          int n_s0, int c0)
00052     : Propagator(home), x(x0), n_s(n_s0), c(c0) {
00053     for (int i=n_s; i--; )
00054       x[i].subscribe(home,*this,PC_INT_VAL);
00055   }
00056 
00057   template <class VX>
00058   forceinline size_t
00059   MemoryLinBoolInt<VX>::dispose(Space& home) {
00060     assert(!home.failed());
00061     for (int i=n_s; i--; )
00062       x[i].cancel(home,*this,PC_INT_VAL);
00063     (void) Propagator::dispose(home);
00064     return sizeof(*this);
00065   }
00066 
00067   template <class VX>
00068   forceinline
00069   MemoryLinBoolInt<VX>::MemoryLinBoolInt(Space& home, bool share,
00070                                          MemoryLinBoolInt<VX>& p)
00071     : Propagator(home,share,p), x(home,p.x.size()), n_s(p.n_s) {
00072     // Update views not assigned and subscribed to
00073     for (int i=n_s; i--; )
00074       x[i].update(home,share,p.x[i]);
00075     // Eliminate assigned but not subscribed views in original
00076     // and update remaining ones
00077     int n_x = p.x.size();
00078     int p_c = p.c;
00079     for (int i=n_x; i-- > n_s; )
00080       if (p.x[i].zero()) {
00081         n_x--;
00082         p.x[i]=p.x[n_x]; x[i]=x[n_x];
00083       } else if (p.x[i].one()) {
00084         n_x--; p_c--;
00085         p.x[i]=p.x[n_x]; x[i]=x[n_x];
00086       } else {
00087         x[i].update(home,share,p.x[i]);
00088       }
00089     p.c = p_c; c = p_c;
00090     p.x.size(n_x); x.size(n_x);
00091   }
00092 
00093   template <class VX>
00094   PropCost
00095   MemoryLinBoolInt<VX>::cost(const Space&, const ModEventDelta&) const {
00096     return PropCost::linear(PropCost::LO, x.size());
00097   }
00098 
00099   /*
00100    * Baseclass for integer Boolean sum using advisors
00101    *
00102    */
00103   template <class VX>
00104   forceinline
00105   SpeedLinBoolInt<VX>::SpeedLinBoolInt(Space& home, ViewArray<VX>& x0,
00106                                        int n_s0, int c0)
00107     : Propagator(home), x(x0), n_s(n_s0), c(c0), co(home) {
00108     int n_x = x.size() - n_s;
00109     for (int i=n_x; i<x.size(); i++)
00110       (void) new (home) ViewAdvisor<VX>(home,*this,co,x[i]);
00111     x.size(n_x);
00112   }
00113 
00114   template <class VX>
00115   forceinline size_t
00116   SpeedLinBoolInt<VX>::dispose(Space& home) {
00117     co.dispose(home);
00118     (void) Propagator::dispose(home);
00119     return sizeof(*this);
00120   }
00121 
00122   template <class VX>
00123   forceinline
00124   SpeedLinBoolInt<VX>::SpeedLinBoolInt(Space& home, bool share,
00125                                        SpeedLinBoolInt<VX>& p)
00126     : Propagator(home,share,p), x(home,p.x.size()), n_s(p.n_s) {
00127     // Eliminate assigned views in original and update remaining ones
00128     int n_x = p.x.size();
00129     int p_c = p.c;
00130     for (int i=n_x; i--; )
00131       if (p.x[i].zero()) {
00132         n_x--;
00133         p.x[i]=p.x[n_x]; x[i]=x[n_x];
00134       } else if (p.x[i].one()) {
00135         n_x--; p_c--;
00136         p.x[i]=p.x[n_x]; x[i]=x[n_x];
00137       } else {
00138         x[i].update(home,share,p.x[i]);
00139       }
00140     p.c = p_c; c = p_c;
00141     p.x.size(n_x); x.size(n_x);
00142     co.update(home,share,p.co);
00143   }
00144 
00145   template <class VX>
00146   PropCost
00147   SpeedLinBoolInt<VX>::cost(const Space&, const ModEventDelta&) const {
00148     return PropCost::unary(PropCost::HI);
00149   }
00150 
00151   /*
00152    * Greater or equal propagator (integer rhs)
00153    *
00154    */
00155 
00156   template <class VX>
00157   forceinline
00158   GqBoolInt<VX>::Memory::Memory(Space& home, ViewArray<VX>& x, int c)
00159     : MemoryLinBoolInt<VX>(home,x,c+1,c) {}
00160 
00161   template <class VX>
00162   forceinline
00163   GqBoolInt<VX>::Memory::Memory(Space& home, bool share,
00164                                 typename GqBoolInt<VX>::Memory& p)
00165     : MemoryLinBoolInt<VX>(home,share,p) {}
00166 
00167   template <class VX>
00168   Actor*
00169   GqBoolInt<VX>::Memory::copy(Space& home, bool share) {
00170     return new (home) Memory(home,share,*this);
00171   }
00172 
00173   template <class VX>
00174   ExecStatus
00175   GqBoolInt<VX>::Memory::propagate(Space& home, const ModEventDelta&) {
00176     // Eliminate assigned views from subscribed views
00177     int n_x = x.size();
00178     for (int i=n_s; i--; )
00179       if (x[i].zero()) {
00180         x[i]=x[--n_s]; x[n_s]=x[--n_x];
00181       } else if (x[i].one()) {
00182         x[i]=x[--n_s]; x[n_s]=x[--n_x]; c--;
00183       }
00184     x.size(n_x);
00185     if (n_x < c)
00186       return ES_FAILED;
00187     if (c <= 0)
00188       return ES_SUBSUMED(*this,home);
00189     // Find unassigned variables to subscribe to
00190     while ((n_s < n_x) && (n_s <= c))
00191       if (x[n_s].zero()) {
00192         x[n_s]=x[--n_x];
00193       } else if (x[n_s].one()) {
00194         x[n_s]=x[--n_x]; c--;
00195       } else {
00196         x[n_s++].subscribe(home,*this,PC_INT_VAL,false);
00197       }
00198     x.size(n_x);
00199     if (n_x < c)
00200       return ES_FAILED;
00201     if (c <= 0)
00202       return ES_SUBSUMED(*this,home);
00203     if (c == n_x) {
00204       // These are known to be not assigned
00205       for (int i=n_s; i--; )
00206         GECODE_ME_CHECK(x[i].one_none(home));
00207       // These are not known to be assigned
00208       for (int i=n_s+1; i<n_x; i++)
00209         GECODE_ME_CHECK(x[i].one(home));
00210       // Fix number of subscriptions such that cancelling subscriptions work
00211       n_s = 0;
00212       return ES_SUBSUMED(*this,sizeof(*this));
00213     }
00214     return ES_FIX;
00215   }
00216 
00217 
00218   template <class VX>
00219   forceinline
00220   GqBoolInt<VX>::Speed::Speed(Space& home, ViewArray<VX>& x, int c)
00221     : SpeedLinBoolInt<VX>(home,x,c+1,c) {}
00222 
00223   template <class VX>
00224   forceinline
00225   GqBoolInt<VX>::Speed::Speed(Space& home, bool share,
00226                               typename GqBoolInt<VX>::Speed& p)
00227     : SpeedLinBoolInt<VX>(home,share,p) {}
00228 
00229   template <class VX>
00230   Actor*
00231   GqBoolInt<VX>::Speed::copy(Space& home, bool share) {
00232     return new (home) Speed(home,share,*this);
00233   }
00234 
00235   template <class VX>
00236   ExecStatus
00237   GqBoolInt<VX>::Speed::advise(Space& home, Advisor& _a, const Delta&) {
00238     ViewAdvisor<VX>& a = static_cast<ViewAdvisor<VX>&>(_a);
00239     if (n_s == 0)
00240       return ES_SUBSUMED_FIX(a,home,co);
00241     assert(!a.view().none());
00242     if (a.view().one()) {
00243       c--; goto subsume;
00244     }
00245     if (c+1 < n_s)
00246       goto subsume;
00247     // Find a new subscription
00248     for (int i = x.size(); i--; )
00249       if (x[i].none()) {
00250         a.view(home,x[i]);
00251         x.size(i);
00252         return ES_FIX;
00253       } else if (x[i].one()) {
00254         c--;
00255         if (c+1 < n_s) {
00256           x.size(i);
00257           goto subsume;
00258         }
00259       }
00260     // No view left
00261     x.size(0);
00262   subsume:
00263     // Do not update subscription
00264     n_s--;
00265     int n = n_s+x.size();
00266     if (n < c)
00267       return ES_FAILED;
00268     if ((c <= 0) || (c == n))
00269       return ES_SUBSUMED_NOFIX(a,home,co);
00270     else
00271       return ES_SUBSUMED_FIX(a,home,co);
00272   }
00273 
00274   template <class VX>
00275   ExecStatus
00276   GqBoolInt<VX>::Speed::propagate(Space& home, const ModEventDelta&) {
00277     if (c > 0) {
00278       assert((n_s == c) && (x.size() == 0));
00279       // Signal to advisors that propagator runs
00280       n_s = 0;
00281       // All views must be one to satisfy inequality
00282       for (Advisors<ViewAdvisor<VX> > as(co); as(); ++as)
00283         GECODE_ME_CHECK(as.advisor().view().one_none(home));
00284     }
00285     return ES_SUBSUMED(*this,home);
00286   }
00287 
00288   template <class VX>
00289   ExecStatus
00290   GqBoolInt<VX>::post(Space& home, ViewArray<VX>& x, int c) {
00291     // Eliminate assigned views
00292     int n_x = x.size();
00293     for (int i=n_x; i--; )
00294       if (x[i].zero()) {
00295         x[i] = x[--n_x];
00296       } else if (x[i].one()) {
00297         x[i] = x[--n_x]; c--;
00298       }
00299     // RHS too large
00300     if (n_x < c)
00301       return ES_FAILED;
00302     // Whatever the x[i] take for values, the inequality is subsumed
00303     if (c <= 0)
00304       return ES_OK;
00305     // All views must be one to satisfy inequality
00306     if (c == n_x) {
00307       for (int i=n_x; i--; )
00308         GECODE_ME_CHECK(x[i].one_none(home));
00309       return ES_OK;
00310     }
00311     // This is the needed invariant as c+1 subscriptions must be created
00312     assert(n_x > c);
00313     x.size(n_x);
00314     if (x.size() > threshold)
00315       (void) new (home) Speed(home,x,c);
00316     else
00317       (void) new (home) Memory(home,x,c);
00318     return ES_OK;
00319   }
00320 
00321 
00322 
00323   /*
00324    * Equal propagator (integer rhs)
00325    *
00326    */
00327   template <class VX>
00328   forceinline
00329   EqBoolInt<VX>::Memory::Memory(Space& home, ViewArray<VX>& x,
00330                                 int c)
00331     : MemoryLinBoolInt<VX>(home,x,std::max(c,x.size()-c)+1,c) {}
00332 
00333   template <class VX>
00334   forceinline
00335   EqBoolInt<VX>::Memory::Memory(Space& home, bool share,
00336                                 typename EqBoolInt<VX>::Memory& p)
00337     : MemoryLinBoolInt<VX>(home,share,p) {}
00338 
00339   template <class VX>
00340   Actor*
00341   EqBoolInt<VX>::Memory::copy(Space& home, bool share) {
00342     return new (home) Memory(home,share,*this);
00343   }
00344 
00345   template <class VX>
00346   ExecStatus
00347   EqBoolInt<VX>::Memory::propagate(Space& home, const ModEventDelta&) {
00348     // Eliminate assigned views from subscribed views
00349     int n_x = x.size();
00350     for (int i=n_s; i--; )
00351       if (x[i].zero()) {
00352         x[i]=x[--n_s]; x[n_s]=x[--n_x];
00353       } else if (x[i].one()) {
00354         x[i]=x[--n_s]; x[n_s]=x[--n_x]; c--;
00355       }
00356     x.size(n_x);
00357     if ((c < 0) || (c > n_x))
00358       return ES_FAILED;
00359     // Find unassigned variables to subscribe to
00360     while ((n_s < n_x) && ((n_s <= c) || (n_s <= n_x-c)))
00361       if (x[n_s].zero()) {
00362         x[n_s]=x[--n_x];
00363       } else if (x[n_s].one()) {
00364         x[n_s]=x[--n_x]; c--;
00365       } else {
00366         x[n_s++].subscribe(home,*this,PC_INT_VAL,false);
00367       }
00368     x.size(n_x);
00369     if ((c < 0) || (c > n_x))
00370       return ES_FAILED;
00371     if (c == 0) {
00372       // These are known to be not assigned
00373       for (int i=n_s; i--; )
00374         GECODE_ME_CHECK(x[i].zero_none(home));
00375       // These are not known to be assigned
00376       for (int i=n_s+1; i<n_x; i++)
00377         GECODE_ME_CHECK(x[i].zero(home));
00378       // Fix number of subscriptions such that cancelling subscriptions work
00379       n_s = 0;
00380       return ES_SUBSUMED(*this,sizeof(*this));
00381     }
00382     if (c == n_x) {
00383       // These are known to be not assigned
00384       for (int i=n_s; i--; )
00385         GECODE_ME_CHECK(x[i].one_none(home));
00386       // These are not known to be assigned
00387       for (int i=n_s+1; i<n_x; i++)
00388         GECODE_ME_CHECK(x[i].one(home));
00389       // Fix number of subscriptions such that cancelling subscriptions work
00390       n_s = 0;
00391       return ES_SUBSUMED(*this,sizeof(*this));
00392     }
00393     return ES_FIX;
00394   }
00395 
00396 
00397 
00398   template <class VX>
00399   forceinline
00400   EqBoolInt<VX>::Speed::Speed(Space& home, ViewArray<VX>& x, int c)
00401     : SpeedLinBoolInt<VX>(home,x,std::max(c,x.size()-c)+1,c) {}
00402 
00403   template <class VX>
00404   forceinline
00405   EqBoolInt<VX>::Speed::Speed(Space& home, bool share,
00406                               typename EqBoolInt<VX>::Speed& p)
00407     : SpeedLinBoolInt<VX>(home,share,p) {}
00408 
00409   template <class VX>
00410   Actor*
00411   EqBoolInt<VX>::Speed::copy(Space& home, bool share) {
00412     return new (home) Speed(home,share,*this);
00413   }
00414 
00415   template <class VX>
00416   ExecStatus
00417   EqBoolInt<VX>::Speed::advise(Space& home, Advisor& _a, const Delta&) {
00418     ViewAdvisor<VX>& a = static_cast<ViewAdvisor<VX>&>(_a);
00419     if (n_s == 0)
00420       return ES_SUBSUMED_FIX(a,home,co);
00421     assert(!a.view().none());
00422     if (a.view().one())
00423       c--;
00424     //    std::max(c,x.size()-c)+1;
00425     if ((c+1 < n_s) && (x.size() < c))
00426       goto subsume;
00427     // Find a new subscription
00428     for (int i = x.size(); i--; )
00429       if (x[i].none()) {
00430         a.view(home,x[i]);
00431         x.size(i);
00432         return ES_FIX;
00433       } else if (x[i].one()) {
00434         c--;
00435       }
00436     // No view left
00437     x.size(0);
00438   subsume:
00439     // Do not update subscription
00440     n_s--;
00441     int n = n_s+x.size();
00442     if ((c<0) || (c > n))
00443       return ES_FAILED;
00444     if ((c == 0) || (c == n))
00445       return ES_SUBSUMED_NOFIX(a,home,co);
00446     else
00447       return ES_SUBSUMED_FIX(a,home,co);
00448   }
00449 
00450   template <class VX>
00451   ExecStatus
00452   EqBoolInt<VX>::Speed::propagate(Space& home, const ModEventDelta&) {
00453     // Signal to advisors that propagator runs
00454     assert(x.size() == 0);
00455     n_s = 0;
00456     if (c == 0) {
00457       // All views must be zero to satisfy equality
00458       for (Advisors<ViewAdvisor<VX> > as(co); as(); ++as)
00459         GECODE_ME_CHECK(as.advisor().view().zero_none(home));
00460     } else {
00461       // All views must be one to satisfy equality
00462       for (Advisors<ViewAdvisor<VX> > as(co); as(); ++as)
00463         GECODE_ME_CHECK(as.advisor().view().one_none(home));
00464     }
00465     return ES_SUBSUMED(*this,home);
00466   }
00467 
00468   template <class VX>
00469   ExecStatus
00470   EqBoolInt<VX>::post(Space& home, ViewArray<VX>& x, int c) {
00471     // Eliminate assigned views
00472     int n_x = x.size();
00473     for (int i=n_x; i--; )
00474       if (x[i].zero()) {
00475         x[i] = x[--n_x];
00476       } else if (x[i].one()) {
00477         x[i] = x[--n_x]; c--;
00478       }
00479     // RHS too small or too large
00480     if ((c < 0) || (c > n_x))
00481       return ES_FAILED;
00482     // All views must be zero to satisfy equality
00483     if (c == 0) {
00484       for (int i=n_x; i--; )
00485         GECODE_ME_CHECK(x[i].zero_none(home));
00486       return ES_OK;
00487     }
00488     // All views must be one to satisfy equality
00489     if (c == n_x) {
00490       for (int i=n_x; i--; )
00491         GECODE_ME_CHECK(x[i].one_none(home));
00492       return ES_OK;
00493     }
00494     x.size(n_x);
00495     if (x.size() > threshold)
00496       (void) new (home) Speed(home,x,c);
00497     else
00498       (void) new (home) Memory(home,x,c);
00499     return ES_OK;
00500   }
00501 
00502   template <class VX>
00503   ExecStatus
00504   EqBoolInt<VX>::Memory::post(Space& home, ViewArray<VX>& x, int c) {
00505     return EqBoolInt<VX>::post(home,x,c);
00506   }
00507 
00508 
00509   /*
00510    * Integer disequal to Boolean sum
00511    *
00512    */
00513 
00514   template<class VX>
00515   forceinline
00516   NqBoolInt<VX>::NqBoolInt(Space& home, ViewArray<VX>& b, int c0)
00517     : BinaryPropagator<VX,PC_INT_VAL>(home,
00518                                       b[b.size()-2],
00519                                       b[b.size()-1]), x(b), c(c0) {
00520     assert(x.size() >= 2);
00521     x.size(x.size()-2);
00522   }
00523 
00524   template<class VX>
00525   forceinline
00526   NqBoolInt<VX>::NqBoolInt(Space& home, bool share, NqBoolInt<VX>& p)
00527     : BinaryPropagator<VX,PC_INT_VAL>(home,share,p), x(home,p.x.size()) {
00528     // Eliminate all zeros and ones in original and update
00529     int n = p.x.size();
00530     int p_c = p.c;
00531     for (int i=n; i--; )
00532       if (p.x[i].zero()) {
00533         n--; p.x[i]=p.x[n]; x[i]=x[n];
00534       } else if (p.x[i].one()) {
00535         n--; p_c--; p.x[i]=p.x[n]; x[i]=x[n];
00536       } else {
00537         x[i].update(home,share,p.x[i]);
00538       }
00539     c = p_c; p.c = p_c;
00540     x.size(n); p.x.size(n);
00541   }
00542 
00543   template<class VX>
00544   forceinline ExecStatus
00545   NqBoolInt<VX>::post(Space& home, ViewArray<VX>& x, int c) {
00546     int n = x.size();
00547     for (int i=n; i--; )
00548       if (x[i].one()) {
00549         x[i]=x[--n]; c--;
00550       } else if (x[i].zero()) {
00551         x[i]=x[--n];
00552       }
00553     x.size(n);
00554     if ((n < c) || (c < 0))
00555       return ES_OK;
00556     if (n == 0)
00557       return (c == 0) ? ES_FAILED : ES_OK;
00558     if (n == 1) {
00559       if (c == 1) {
00560         GECODE_ME_CHECK(x[0].zero_none(home));
00561       } else {
00562         GECODE_ME_CHECK(x[0].one_none(home));
00563       }
00564       return ES_OK;
00565     }
00566     (void) new (home) NqBoolInt(home,x,c);
00567     return ES_OK;
00568   }
00569 
00570   template<class VX>
00571   Actor*
00572   NqBoolInt<VX>::copy(Space& home, bool share) {
00573     return new (home) NqBoolInt<VX>(home,share,*this);
00574   }
00575 
00576   template<class VX>
00577   PropCost
00578   NqBoolInt<VX>::cost(const Space&, const ModEventDelta&) const {
00579     return PropCost::linear(PropCost::LO, x.size());
00580   }
00581 
00582   template<class VX>
00583   forceinline bool
00584   NqBoolInt<VX>::resubscribe(Space& home, VX& y) {
00585     if (y.one())
00586       c--;
00587     int n = x.size();
00588     for (int i=n; i--; )
00589       if (x[i].one()) {
00590         c--; x[i]=x[--n];
00591       } else if (x[i].zero()) {
00592         x[i] = x[--n];
00593       } else {
00594         // New unassigned view found
00595         assert(!x[i].zero() && !x[i].one());
00596         // Move to y and subscribe
00597         y=x[i]; x[i]=x[--n];
00598         x.size(n);
00599         y.subscribe(home,*this,PC_INT_VAL,false);
00600         return true;
00601       }
00602     // All views have been assigned!
00603     x.size(0);
00604     return false;
00605   }
00606 
00607   template<class VX>
00608   ExecStatus
00609   NqBoolInt<VX>::propagate(Space& home, const ModEventDelta&) {
00610     bool s0 = true;
00611     if (x0.zero() || x0.one())
00612       s0 = resubscribe(home,x0);
00613     bool s1 = true;
00614     if (x1.zero() || x1.one())
00615       s1 = resubscribe(home,x1);
00616     int n = x.size() + s0 + s1;
00617     if ((n < c) || (c < 0))
00618       return ES_SUBSUMED(*this,home);
00619     if (n == 0)
00620       return (c == 0) ? ES_FAILED : ES_SUBSUMED(*this,sizeof(*this));
00621     if (n == 1) {
00622       if (s0) {
00623         if (c == 1) {
00624           GECODE_ME_CHECK(x0.zero_none(home));
00625         } else {
00626           GECODE_ME_CHECK(x0.one_none(home));
00627         }
00628       } else {
00629         assert(s1);
00630         if (c == 1) {
00631           GECODE_ME_CHECK(x1.zero_none(home));
00632         } else {
00633           GECODE_ME_CHECK(x1.one_none(home));
00634         }
00635       }
00636       return ES_SUBSUMED(*this,sizeof(*this));
00637     }
00638     return ES_FIX;
00639   }
00640 
00641   //** REIFIED **//
00642 
00643   /*
00644    * Baseclass for reified integer Boolean sum using dependencies
00645    *
00646    */
00647   template <class VX, class VB>
00648   forceinline
00649   MemoryReLinBoolInt<VX,VB>::MemoryReLinBoolInt(Space& home, ViewArray<VX>& x0,
00650                                          int n_s0, int c0, VB b0)
00651     : MemoryLinBoolInt<VX>(home,x0,n_s0,c0), b(b0) {
00652     b.subscribe(home,*this,PC_BOOL_VAL);
00653   }
00654 
00655   template <class VX, class VB>
00656   forceinline size_t
00657   MemoryReLinBoolInt<VX,VB>::dispose(Space& home) {
00658     assert(!home.failed());
00659     b.cancel(home,*this,PC_BOOL_VAL);
00660     (void) MemoryLinBoolInt<VX>::dispose(home);
00661     return sizeof(*this);
00662   }
00663 
00664   template <class VX, class VB>
00665   forceinline
00666   MemoryReLinBoolInt<VX,VB>::MemoryReLinBoolInt(Space& home, bool share, 
00667                                          MemoryReLinBoolInt<VX,VB>& p)
00668     : MemoryLinBoolInt<VX>(home,share,p) {
00669     b.update(home,share,p.b);
00670   }
00671 
00672   /*
00673    * Baseclass for reified integer Boolean sum using advisors
00674    *
00675    */
00676   template <class VX, class VB>
00677   forceinline
00678   SpeedReLinBoolInt<VX,VB>::SpeedReLinBoolInt(Space& home, ViewArray<VX>& x0,
00679                                          int n_s0, int c0, VB b0)
00680     : SpeedLinBoolInt<VX>(home,x0,n_s0,c0), b(b0) {
00681     b.subscribe(home,*this,PC_BOOL_VAL);
00682   }
00683 
00684   template <class VX, class VB>
00685   forceinline size_t
00686   SpeedReLinBoolInt<VX,VB>::dispose(Space& home) {
00687     assert(!home.failed());
00688     b.cancel(home,*this,PC_BOOL_VAL);
00689     (void) SpeedLinBoolInt<VX>::dispose(home);
00690     return sizeof(*this);
00691   }
00692 
00693   template <class VX, class VB>
00694   forceinline
00695   SpeedReLinBoolInt<VX,VB>::SpeedReLinBoolInt(Space& home, bool share, 
00696                                          SpeedReLinBoolInt<VX,VB>& p)
00697     : SpeedLinBoolInt<VX>(home,share,p) {
00698     b.update(home,share,p.b);
00699   }
00700 
00701 
00702   /*
00703    * Reified greater or equal propagator (integer rhs)
00704    * 
00705    */
00706 
00707   template <class VX, class VB>
00708   forceinline
00709   ReGqBoolInt<VX,VB>::Memory::Memory(Space& home, ViewArray<VX>& x, int c, VB b)
00710   // max(c,|x|-c)+1 because c might be a low number and we need to propagate to 'b' as fast as possible. min(|x|,val) to avoid overflow
00711     : MemoryReLinBoolInt<VX,VB>
00712         (home,x,std::min(x.size(),std::max(c,x.size()-c)+1),c,b) {}
00713   template <class VX, class VB>
00714   forceinline
00715   ReEqBoolInt<VX,VB>::Memory::Memory(Space& home, ViewArray<VX>& x, int c, VB b)
00716   // max(c,|x|-c)+1 because c might be a low number and we need to propagate to 'b' as fast as possible. min(|x|,val) to avoid overflow
00717     : MemoryReLinBoolInt<VX,VB>
00718         (home,x,std::min(x.size(),std::max(c,x.size()-c)+1),c,b) {}
00719 
00720   template <class VX, class VB>
00721   forceinline
00722   ReGqBoolInt<VX,VB>::Memory::Memory(Space& home, bool share, 
00723                                 typename ReGqBoolInt<VX,VB>::Memory& p)
00724     : MemoryReLinBoolInt<VX,VB>(home,share,p) {}
00725   template <class VX, class VB>
00726   forceinline
00727   ReEqBoolInt<VX,VB>::Memory::Memory(Space& home, bool share, 
00728                                 typename ReEqBoolInt<VX,VB>::Memory& p)
00729     : MemoryReLinBoolInt<VX,VB>(home,share,p) {}
00730 
00731   template <class VX, class VB>
00732   Actor*
00733   ReGqBoolInt<VX,VB>::Memory::copy(Space& home, bool share) {
00734     return new (home) Memory(home,share,*this);
00735   }
00736   template <class VX, class VB>
00737   Actor*
00738   ReEqBoolInt<VX,VB>::Memory::copy(Space& home, bool share) {
00739     return new (home) Memory(home,share,*this);
00740   }
00741 
00742   template <class VX, class VB>
00743   inline ExecStatus
00744   ReGqBoolInt<VX,VB>::Memory::rewrite_inverse(Space& home, 
00745                                               ViewArray<BoolView>& x, int c) {
00746     ViewArray<NegBoolView> y(home,x.size());
00747     for (int i=x.size(); i--; )
00748       y[i]=x[i];
00749     GECODE_REWRITE(*this,(GqBoolInt<NegBoolView>::post(home,y,x.size()-c+1)));
00750   }
00751 
00752   template <class VX, class VB>
00753   inline ExecStatus
00754   ReGqBoolInt<VX,VB>::Memory::rewrite_inverse(Space& home, 
00755                                               ViewArray<NegBoolView>& x, int c) {
00756     ViewArray<BoolView> y(home,x.size());
00757     for (int i=x.size(); i--; )
00758       y[i]=x[i].base();
00759     GECODE_REWRITE(*this,(GqBoolInt<BoolView>::post(home,y,x.size()-c+1)));
00760   }
00761 
00762 
00763   template <class VX, class VB>
00764   ExecStatus
00765   ReGqBoolInt<VX,VB>::Memory::propagate(Space& home, const ModEventDelta&) {
00766     // Eliminate assigned views from subscribed views
00767     int n_x = x.size();
00768     for (int i=n_s; i--; )
00769       if (x[i].zero()) {
00770         x[i]=x[--n_s]; x[n_s]=x[--n_x];
00771       } else if (x[i].one()) {
00772         x[i]=x[--n_s]; x[n_s]=x[--n_x]; c--;
00773       }
00774     x.size(n_x);
00775 
00776     // b got assigned, subsume or rewrite
00777     if (b.one())
00778       GECODE_REWRITE(*this,(GqBoolInt<VX>::post(home,x,c)));
00779     if (b.zero())
00780       return rewrite_inverse(home, x, c);
00781 
00782     if (n_x < c) {
00783       GECODE_ME_CHECK(b.zero_none(home));
00784       return ES_SUBSUMED(*this,home);
00785     }
00786     if (c <= 0) {
00787       GECODE_ME_CHECK(b.one_none(home));
00788       return ES_SUBSUMED(*this,home);
00789     }
00790     // Find unassigned variables to subscribe to
00791     int n_s0 = c; // minimal number of subscriptions !
00792     // max(c,|x|-c)+1 because c might be a low number and we need to propagate to 'b' as fast as possible. min(|x|,val) to avoid overflow
00793     n_s0 = std::min(x.size(),std::max(c,x.size()-c)+1);
00794 
00795     while ((n_s < n_x) && (n_s <= n_s0)) 
00796       if (x[n_s].zero()) {
00797         x[n_s]=x[--n_x];
00798       } else if (x[n_s].one()) {
00799         x[n_s]=x[--n_x]; c--;
00800       } else {
00801         x[n_s++].subscribe(home,*this,PC_INT_VAL,false);
00802       }
00803     x.size(n_x);
00804     if (n_x < c) {
00805       GECODE_ME_CHECK(b.zero_none(home));
00806       return ES_SUBSUMED(*this,home);
00807     }
00808     if (c <= 0) {
00809       GECODE_ME_CHECK(b.one_none(home));
00810       return ES_SUBSUMED(*this,home);
00811     }
00812     return ES_FIX;
00813   }
00814 
00815   template <class VX, class VB>
00816   ExecStatus
00817   ReEqBoolInt<VX,VB>::Memory::propagate(Space& home, const ModEventDelta&) {
00818     // Eliminate assigned views from subscribed views
00819     int n_x = x.size();
00820     for (int i=n_s; i--; )
00821       if (x[i].zero()) {
00822         x[i]=x[--n_s]; x[n_s]=x[--n_x];
00823       } else if (x[i].one()) {
00824         x[i]=x[--n_s]; x[n_s]=x[--n_x]; c--;
00825       }
00826     x.size(n_x);
00827 
00828     // b got assigned, subsume or rewrite
00829     if (b.one())
00830       GECODE_REWRITE(*this,(EqBoolInt<VX>::post(home,x,c)));
00831     if (b.zero())
00832       GECODE_REWRITE(*this,(NqBoolInt<VX>::post(home,x,c)));
00833 
00834     if ((c < 0) || (c > n_x)) {
00835       GECODE_ME_CHECK(b.zero_none(home));
00836       return ES_SUBSUMED(*this,home);
00837     }
00838     // Find unassigned variables to subscribe to
00839     int n_s0 = c; // minimal number of subscriptions !
00840     // max(c,|x|-c)+1 because c might be a low number and we need to propagate to 'b' as fast as possible. min(|x|,val) to avoid overflow
00841     n_s0 = std::min(x.size(),std::max(c,x.size()-c)+1);
00842 
00843     while ((n_s < n_x) && (n_s <= n_s0)) 
00844       if (x[n_s].zero()) {
00845         x[n_s]=x[--n_x];
00846       } else if (x[n_s].one()) {
00847         x[n_s]=x[--n_x]; c--;
00848       } else {
00849         x[n_s++].subscribe(home,*this,PC_INT_VAL,false);
00850       }
00851     x.size(n_x);
00852     if ((c < 0) || (c > n_x)) {
00853       GECODE_ME_CHECK(b.zero_none(home));
00854       return ES_SUBSUMED(*this,home);
00855     }
00856     if (c == 0 && n_x == 0) {
00857       GECODE_ME_CHECK(b.one_none(home));
00858       return ES_SUBSUMED(*this,home);
00859     }
00860     return ES_FIX;
00861   }
00862 
00863 
00864 
00865   template <class VX, class VB>
00866   forceinline
00867   ReGqBoolInt<VX,VB>::Speed::Speed(Space& home, ViewArray<VX>& x, int c, VB b)
00868   // max(c,|x|-c)+1 because c might be a low number and we need to propagate to 'b' as fast as possible. min(|x|,val) to avoid overflow
00869     : SpeedReLinBoolInt<VX,VB>
00870           (home,x,std::min(x.size(),std::max(c,x.size()-c)+1),c,b) {}
00871   template <class VX, class VB>
00872   forceinline
00873   ReEqBoolInt<VX,VB>::Speed::Speed(Space& home, ViewArray<VX>& x, int c, VB b)
00874   // max(c,|x|-c)+1 because c might be a low number and we need to propagate to 'b' as fast as possible. min(|x|,val) to avoid overflow
00875     : SpeedReLinBoolInt<VX,VB>
00876           (home,x,std::min(x.size(),std::max(c,x.size()-c)+1),c,b) {}
00877 
00878   template <class VX, class VB>
00879   forceinline
00880   ReGqBoolInt<VX,VB>::Speed::Speed(Space& home, bool share, 
00881                               typename ReGqBoolInt<VX,VB>::Speed& p)
00882     : SpeedReLinBoolInt<VX,VB>(home,share,p) {}
00883   template <class VX, class VB>
00884   forceinline
00885   ReEqBoolInt<VX,VB>::Speed::Speed(Space& home, bool share, 
00886                               typename ReEqBoolInt<VX,VB>::Speed& p)
00887     : SpeedReLinBoolInt<VX,VB>(home,share,p) {}
00888 
00889   template <class VX, class VB>
00890   Actor*
00891   ReGqBoolInt<VX,VB>::Speed::copy(Space& home, bool share) {
00892     return new (home) Speed(home,share,*this);
00893   }
00894   template <class VX, class VB>
00895   Actor*
00896   ReEqBoolInt<VX,VB>::Speed::copy(Space& home, bool share) {
00897     return new (home) Speed(home,share,*this);
00898   }
00899 
00900 
00901   template <class VX, class VB>
00902   inline ExecStatus
00903   ReGqBoolInt<VX,VB>::Speed::rewrite_inverse(Space& home, 
00904                                              ViewArray<BoolView>& x, int c) {
00905     ViewArray<NegBoolView> y(home,x.size());
00906     for (int i=x.size(); i--; )
00907       y[i]=x[i];
00908     GECODE_REWRITE(*this,(GqBoolInt<NegBoolView>::post(home,y,x.size()-c+1)));
00909   }
00910 
00911   template <class VX, class VB>
00912   inline ExecStatus
00913   ReGqBoolInt<VX,VB>::Speed::rewrite_inverse(Space& home, 
00914                                              ViewArray<NegBoolView>& x, int c) {
00915     ViewArray<BoolView> y(home,x.size());
00916     for (int i=x.size(); i--; )
00917       y[i]=x[i].base();
00918     GECODE_REWRITE(*this,(GqBoolInt<BoolView>::post(home,y,x.size()-c+1)));
00919   }
00920 
00921 
00922   template <class VX, class VB>
00923   ExecStatus
00924   ReGqBoolInt<VX,VB>::Speed::advise(Space& home, Advisor& _a, const Delta&) {
00925     ViewAdvisor<VX>& a = static_cast<ViewAdvisor<VX>&>(_a);
00926     if (n_s == 0)
00927       return ES_SUBSUMED_FIX(a,home,co);
00928 
00929     // elminate view
00930     assert(!a.view().none());
00931     if (a.view().one())
00932       c--;
00933     n_s--;
00934     if ((n_s+x.size() < c) || (c <= 0))
00935       return ES_SUBSUMED_NOFIX(a,home,co);
00936 
00937     // Find a new subscription
00938     int n_s0 = std::min(x.size(),std::max(c,x.size()-c)+1);
00939     if (n_s < n_s0) {
00940       assert(n_s == n_s0-1);
00941       for (int i = x.size(); i--; ) {
00942         // if (x[i].zero()) // continue
00943         if (x[i].one()) {
00944           c--;
00945         } else if (x[i].none()) {
00946           // view i is unassigned (offset 0)
00947           if ((n_s+(i+1) < c) || (c < 0)) {
00948             x.size(i+1);
00949             return ES_SUBSUMED_NOFIX(a,home,co);
00950           }
00951           a.view(home,x[i]);
00952           n_s++;
00953           x.size(i);
00954           return ES_FIX;
00955         }
00956       }
00957       // No view left
00958       x.size(0);
00959       if ((n_s+x.size() < c) || (c <= 0))
00960         return ES_SUBSUMED_NOFIX(a,home,co);
00961     }
00962     // This advisor is obsolete
00963     return ES_SUBSUMED_FIX(a,home,co);
00964   }
00965 
00966   template <class VX, class VB>
00967   ExecStatus
00968   ReEqBoolInt<VX,VB>::Speed::advise(Space& home, Advisor& _a, const Delta&) {
00969     ViewAdvisor<VX>& a = static_cast<ViewAdvisor<VX>&>(_a);
00970     if (n_s == 0)
00971       return ES_SUBSUMED_FIX(a,home,co);
00972 
00973     // elminate view
00974     assert(!a.view().none());
00975     if (a.view().one())
00976       c--;
00977     n_s--;
00978     if ((c < 0) || (n_s+x.size() < c) || (n_s+x.size() == 0))
00979     //if ((n_s+x.size() < c) || (c < 0))
00980       return ES_SUBSUMED_NOFIX(a,home,co);
00981 
00982     // Find a new subscription
00983     int n_s0 = std::min(x.size(),std::max(c,x.size()-c)+1);
00984     if (n_s < n_s0) {
00985       assert(n_s == n_s0-1);
00986       for (int i = x.size(); i--; ) {
00987         // if (x[i].zero()) // continue
00988         if (x[i].one()) {
00989           c--;
00990         } else if (x[i].none()) {
00991           // view i is unassigned (offset 0)
00992           if ((n_s+(i+1) < c) || (c < 0)) {
00993             x.size(i+1);
00994             return ES_SUBSUMED_NOFIX(a,home,co);
00995           }
00996           a.view(home,x[i]);
00997           n_s++;
00998           x.size(i);
00999           return ES_FIX;
01000         }
01001       }
01002       // No view left
01003       x.size(0);
01004       if ((c < 0) || (n_s < c) || (n_s == 0))
01005         return ES_SUBSUMED_NOFIX(a,home,co);
01006     }
01007     // This advisor is obsolete
01008     return ES_SUBSUMED_FIX(a,home,co);
01009   }
01010 
01011 
01012 
01013   template <class VX, class VB>
01014   ExecStatus
01015   ReGqBoolInt<VX,VB>::Speed::propagate(Space& home, const ModEventDelta&) {
01016     // either b got assigned, or an advisor called ES_SUBSUMED_NOFIX
01017     int real_n_s = n_s;
01018     // Signal to advisors that propagator runs
01019     n_s = 0;
01020     if (b.none()) {
01021       if (c <= 0) {
01022         GECODE_ME_CHECK(b.one_none(home));
01023       } else {
01024         GECODE_ME_CHECK(b.zero_none(home));
01025       }
01026     } else {
01027       // Problem: now we need to add all advised views back to x !
01028       int real_n = x.size();
01029       ViewArray<VX> real_x(home, real_n+real_n_s);
01030       for (int i=real_n; i--; )
01031         real_x[i] = x[i];
01032       x.size(0);
01033       for (Advisors<ViewAdvisor<VX> > as(co); as(); ++as)
01034         real_x[real_n++] = as.advisor().view();
01035 
01036       if (b.one())
01037         GECODE_REWRITE(*this,(GqBoolInt<VX>::post(home,real_x,c)));
01038       if (b.zero())
01039         return rewrite_inverse(home, real_x, c);
01040     }
01041     return ES_SUBSUMED(*this,home);
01042   }
01043 
01044   template <class VX, class VB>
01045   ExecStatus
01046   ReEqBoolInt<VX,VB>::Speed::propagate(Space& home, const ModEventDelta&) {
01047     // either b got assigned, or an advisor called ES_SUBSUMED_NOFIX
01048     int real_n_s = n_s;
01049     // Signal to advisors that propagator runs
01050     n_s = 0;
01051 
01052     if (b.none()) {
01053       if (c == 0 && real_n_s+x.size() == 0) {
01054         GECODE_ME_CHECK(b.one_none(home));
01055       } else {
01056         GECODE_ME_CHECK(b.zero_none(home));
01057       }
01058     } else {
01059       // Problem: now we need to add all advised views back to x !
01060       int real_n = x.size();
01061       ViewArray<VX> real_x(home, real_n+real_n_s);
01062       for (int i=real_n; i--; )
01063         real_x[i] = x[i];
01064       x.size(0);
01065       for (Advisors<ViewAdvisor<VX> > as(co); as(); ++as)
01066         real_x[real_n++] = as.advisor().view();
01067 
01068       if (b.one())
01069         GECODE_REWRITE(*this,(EqBoolInt<VX>::post(home,real_x,c)));
01070       if (b.zero())
01071         GECODE_REWRITE(*this,(NqBoolInt<VX>::post(home,real_x,c)));
01072     }
01073     return ES_SUBSUMED(*this,home);
01074   }
01075 
01076 
01077 
01078   template <class VX, class VB>
01079   ExecStatus
01080   ReGqBoolInt<VX,VB>::post(Space& home, ViewArray<VX>& x, int c, VB b) {
01081     assert(!b.assigned()); // checked before posting
01082 
01083     // Eliminate assigned views
01084     int n_x = x.size();
01085     for (int i=n_x; i--; )
01086       if (x[i].zero()) {
01087         x[i] = x[--n_x];
01088       } else if (x[i].one()) {
01089         x[i] = x[--n_x]; c--;
01090       }
01091     // RHS too large
01092     if (n_x < c) {
01093       GECODE_ME_CHECK(b.zero_none(home));
01094       return ES_OK;
01095     }
01096     // Whatever the x[i] take for values, the inequality is subsumed
01097     if (c <= 0) {
01098       GECODE_ME_CHECK(b.one_none(home));
01099       return ES_OK;
01100     }
01101     // This is the needed invariant as c subscriptions must be created (c+1 in non-reified)
01102     assert(n_x >= c);
01103     x.size(n_x);
01104 #if 0
01105     // The code for Speed is broken, hence disabled
01106     if (x.size() > threshold)
01107       (void) new (home) Speed(home,x,c,b);
01108     else
01109       (void) new (home) Memory(home,x,c,b);
01110 #else
01111     (void) new (home) Memory(home,x,c,b);
01112 #endif
01113     return ES_OK;
01114   }
01115 
01116   template <class VX, class VB>
01117   ExecStatus
01118   ReEqBoolInt<VX,VB>::post(Space& home, ViewArray<VX>& x, int c, VB b) {
01119     assert(!b.assigned()); // checked before posting
01120 
01121     // Eliminate assigned views
01122     int n_x = x.size();
01123     for (int i=n_x; i--; )
01124       if (x[i].zero()) {
01125         x[i] = x[--n_x];
01126       } else if (x[i].one()) {
01127         x[i] = x[--n_x]; c--;
01128       }
01129     // RHS too large || whatever the x[i] take for values, the equality is subsumed
01130     if ((n_x < c) || (c < 0)) {
01131       GECODE_ME_CHECK(b.zero_none(home));
01132       return ES_OK;
01133     }
01134     // all variables set, and c == 0: equality
01135     if ((c == 0) && (n_x == 0)) {
01136       GECODE_ME_CHECK(b.one_none(home));
01137       return ES_OK;
01138     }
01139     // This is the needed invariant as c subscriptions must be created (c+1 in non-reified)
01140     assert(n_x >= c);
01141     x.size(n_x);
01142 #if 0
01143     // The code for Speed is broken, hence disabled
01144     if (x.size() > threshold)
01145       (void) new (home) Speed(home,x,c,b);
01146     else
01147       (void) new (home) Memory(home,x,c,b);
01148 #else
01149     (void) new (home) Memory(home,x,c,b);
01150 #endif
01151     return ES_OK;
01152   }
01153 
01154 
01155 }}}
01156 
01157 // STATISTICS: int-prop
01158