Generated on Fri Mar 20 15:56:11 2015 for Gecode by doxygen 1.6.3

int-nary.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2003
00008  *
00009  *  Last modified:
00010  *     $Date: 2012-10-18 16:02:42 +0200 (Thu, 18 Oct 2012) $ by $Author: schulte $
00011  *     $Revision: 13154 $
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 <gecode/int/linear/int-noview.hpp>
00039 
00040 namespace Gecode { namespace Int { namespace Linear {
00041 
00046   template<class P, class N>
00047   forceinline bool
00048   isunit(ViewArray<P>&, ViewArray<N>&) { return false; }
00049   template<>
00050   forceinline bool
00051   isunit(ViewArray<IntView>&, ViewArray<IntView>&) { return true; }
00052   template<>
00053   forceinline bool
00054   isunit(ViewArray<IntView>&, ViewArray<NoView>&) { return true; }
00055   template<>
00056   forceinline bool
00057   isunit(ViewArray<NoView>&, ViewArray<IntView>&) { return true; }
00058 
00059   /*
00060    * Linear propagators
00061    *
00062    */
00063   template<class Val, class P, class N, PropCond pc>
00064   forceinline
00065   Lin<Val,P,N,pc>::Lin(Home home, ViewArray<P>& x0, ViewArray<N>& y0, Val c0)
00066     : Propagator(home), x(x0), y(y0), c(c0) {
00067     x.subscribe(home,*this,pc);
00068     y.subscribe(home,*this,pc);
00069   }
00070 
00071   template<class Val, class P, class N, PropCond pc>
00072   forceinline
00073   Lin<Val,P,N,pc>::Lin(Space& home, bool share, Lin<Val,P,N,pc>& p)
00074     : Propagator(home,share,p), c(p.c) {
00075     x.update(home,share,p.x);
00076     y.update(home,share,p.y);
00077   }
00078 
00079   template<class Val, class P, class N, PropCond pc>
00080   PropCost
00081   Lin<Val,P,N,pc>::cost(const Space&, const ModEventDelta&) const {
00082     return PropCost::linear(PropCost::LO, x.size()+y.size());
00083   }
00084 
00085   template<class Val, class P, class N, PropCond pc>
00086   forceinline size_t
00087   Lin<Val,P,N,pc>::dispose(Space& home) {
00088     x.cancel(home,*this,pc);
00089     y.cancel(home,*this,pc);
00090     (void) Propagator::dispose(home);
00091     return sizeof(*this);
00092   }
00093 
00094   /*
00095    * Reified linear propagators
00096    *
00097    */
00098   template<class Val, class P, class N, PropCond pc, class Ctrl>
00099   forceinline
00100   ReLin<Val,P,N,pc,Ctrl>::ReLin
00101   (Home home, ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b0)
00102     : Lin<Val,P,N,pc>(home,x,y,c), b(b0) {
00103     b.subscribe(home,*this,PC_INT_VAL);
00104   }
00105 
00106   template<class Val, class P, class N, PropCond pc, class Ctrl>
00107   forceinline
00108   ReLin<Val,P,N,pc,Ctrl>::ReLin
00109   (Space& home, bool share, ReLin<Val,P,N,pc,Ctrl>& p)
00110     : Lin<Val,P,N,pc>(home,share,p) {
00111     b.update(home,share,p.b);
00112   }
00113 
00114   template<class Val, class P, class N, PropCond pc, class Ctrl>
00115   forceinline size_t
00116   ReLin<Val,P,N,pc,Ctrl>::dispose(Space& home) {
00117     b.cancel(home,*this,PC_BOOL_VAL);
00118     (void) Lin<Val,P,N,pc>::dispose(home);
00119     return sizeof(*this);
00120   }
00121 
00122   /*
00123    * Computing bounds
00124    *
00125    */
00126 
00127   template<class Val, class View>
00128   void
00129   bounds_p(ModEventDelta med, ViewArray<View>& x, Val& c, Val& sl, Val& su) {
00130     int n = x.size();
00131     if (IntView::me(med) == ME_INT_VAL) {
00132       for (int i = n; i--; ) {
00133         Val m = x[i].min();
00134         if (x[i].assigned()) {
00135           c -= m; x[i] = x[--n];
00136         } else {
00137           sl -= m; su -= x[i].max();
00138         }
00139       }
00140       x.size(n);
00141     } else {
00142       for (int i = n; i--; ) {
00143         sl -= x[i].min(); su -= x[i].max();
00144       }
00145     }
00146   }
00147 
00148   template<class Val, class View>
00149   void
00150   bounds_n(ModEventDelta med, ViewArray<View>& y, Val& c, Val& sl, Val& su) {
00151     int n = y.size();
00152     if (IntView::me(med) == ME_INT_VAL) {
00153       for (int i = n; i--; ) {
00154         Val m = y[i].max();
00155         if (y[i].assigned()) {
00156           c += m; y[i] = y[--n];
00157         } else {
00158           sl += m; su += y[i].min();
00159         }
00160       }
00161       y.size(n);
00162     } else {
00163       for (int i = n; i--; ) {
00164         sl += y[i].max(); su += y[i].min();
00165       }
00166     }
00167   }
00168 
00169 
00170   template<class Val, class P, class N>
00171   ExecStatus
00172   prop_bnd(Space& home, ModEventDelta med, Propagator& p,
00173            ViewArray<P>& x, ViewArray<N>& y, Val& c) {
00174     // Eliminate singletons
00175     Val sl = 0;
00176     Val su = 0;
00177 
00178     bounds_p<Val,P>(med, x, c, sl, su);
00179     bounds_n<Val,N>(med, y, c, sl, su);
00180 
00181     if ((IntView::me(med) == ME_INT_VAL) && ((x.size() + y.size()) <= 1)) {
00182       if (x.size() == 1) {
00183         GECODE_ME_CHECK(x[0].eq(home,c));
00184         return home.ES_SUBSUMED(p);
00185       }
00186       if (y.size() == 1) {
00187         GECODE_ME_CHECK(y[0].eq(home,-c));
00188         return home.ES_SUBSUMED(p);
00189       }
00190       return (c == static_cast<Val>(0)) ?
00191         home.ES_SUBSUMED(p) : ES_FAILED;
00192     }
00193 
00194     sl += c; su += c;
00195 
00196     const int mod_sl = 1;
00197     const int mod_su = 2;
00198 
00199     int mod = mod_sl | mod_su;
00200 
00201     do {
00202       if (mod & mod_sl) {
00203         mod -= mod_sl;
00204         // Propagate upper bound for positive variables
00205         for (int i = x.size(); i--; ) {
00206           const Val xi_max = x[i].max();
00207           ModEvent me = x[i].lq(home,sl + x[i].min());
00208           if (me_failed(me))
00209             return ES_FAILED;
00210           if (me_modified(me)) {
00211             su += xi_max - x[i].max();
00212             mod |= mod_su;
00213           }
00214         }
00215         // Propagate lower bound for negative variables
00216         for (int i = y.size(); i--; ) {
00217           const Val yi_min = y[i].min();
00218           ModEvent me = y[i].gq(home,y[i].max() - sl);
00219           if (me_failed(me))
00220             return ES_FAILED;
00221           if (me_modified(me)) {
00222             su += y[i].min() - yi_min;
00223             mod |= mod_su;
00224           }
00225         }
00226       }
00227       if (mod & mod_su) {
00228         mod -= mod_su;
00229         // Propagate lower bound for positive variables
00230         for (int i = x.size(); i--; ) {
00231           const Val xi_min = x[i].min();
00232           ModEvent me = x[i].gq(home,su + x[i].max());
00233           if (me_failed(me))
00234             return ES_FAILED;
00235           if (me_modified(me)) {
00236             sl += xi_min - x[i].min();
00237             mod |= mod_sl;
00238           }
00239         }
00240         // Propagate upper bound for negative variables
00241         for (int i = y.size(); i--; ) {
00242           const Val yi_max = y[i].max();
00243           ModEvent me = y[i].lq(home,y[i].min() - su);
00244           if (me_failed(me))
00245             return ES_FAILED;
00246           if (me_modified(me)) {
00247             sl += y[i].max() - yi_max;
00248             mod |= mod_sl;
00249           }
00250         }
00251       }
00252     } while (mod);
00253 
00254     return (sl == su) ? home.ES_SUBSUMED(p) : ES_FIX;
00255   }
00256 
00257   /*
00258    * Bound consistent linear equation
00259    *
00260    */
00261 
00262   template<class Val, class P, class N>
00263   forceinline
00264   Eq<Val,P,N>::Eq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c)
00265     : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {}
00266 
00267   template<class Val, class P, class N>
00268   ExecStatus
00269   Eq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
00270     ViewArray<NoView> nva;
00271     if (y.size() == 0) {
00272       (void) new (home) Eq<Val,P,NoView>(home,x,nva,c);
00273     } else if (x.size() == 0) {
00274       (void) new (home) Eq<Val,N,NoView>(home,y,nva,-c);
00275     } else {
00276       (void) new (home) Eq<Val,P,N>(home,x,y,c);
00277     }
00278     return ES_OK;
00279   }
00280 
00281 
00282   template<class Val, class P, class N>
00283   forceinline
00284   Eq<Val,P,N>::Eq(Space& home, bool share, Eq<Val,P,N>& p)
00285     : Lin<Val,P,N,PC_INT_BND>(home,share,p) {}
00286 
00291   template<class Val, class P, class N>
00292   forceinline Actor*
00293   eqtobin(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00294     return NULL;
00295   }
00296   template<class Val>
00297   forceinline Actor*
00298   eqtobin(Space& home, bool share, Propagator& p,
00299           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00300     assert(x.size() == 2);
00301     return new (home) EqBin<Val,IntView,IntView>
00302       (home,share,p,x[0],x[1],c);
00303   }
00304   template<class Val>
00305   forceinline Actor*
00306   eqtobin(Space& home, bool share, Propagator& p,
00307           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00308     assert(y.size() == 2);
00309     return new (home) EqBin<Val,IntView,IntView>
00310       (home,share,p,y[0],y[1],-c);
00311   }
00312   template<class Val>
00313   forceinline Actor*
00314   eqtobin(Space& home, bool share, Propagator& p,
00315           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00316     if (x.size() == 2)
00317       return new (home) EqBin<Val,IntView,IntView>
00318         (home,share,p,x[0],x[1],c);
00319     if (x.size() == 1)
00320       return new (home) EqBin<Val,IntView,MinusView>
00321         (home,share,p,x[0],MinusView(y[0]),c);
00322     return new (home) EqBin<Val,IntView,IntView>
00323       (home,share,p,y[0],y[1],-c);
00324   }
00325 
00330   template<class Val, class P, class N>
00331   forceinline Actor*
00332   eqtoter(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00333     return NULL;
00334   }
00335   template<class Val>
00336   forceinline Actor*
00337   eqtoter(Space& home, bool share, Propagator& p,
00338           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00339     assert(x.size() == 3);
00340     return new (home) EqTer<Val,IntView,IntView,IntView>
00341       (home,share,p,x[0],x[1],x[2],c);
00342   }
00343   template<class Val>
00344   forceinline Actor*
00345   eqtoter(Space& home, bool share, Propagator& p,
00346           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00347     assert(y.size() == 3);
00348     return new (home) EqTer<Val,IntView,IntView,IntView>
00349       (home,share,p,y[0],y[1],y[2],-c);
00350   }
00351   template<class Val>
00352   forceinline Actor*
00353   eqtoter(Space& home, bool share, Propagator& p,
00354           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00355     if (x.size() == 3)
00356       return new (home) EqTer<Val,IntView,IntView,IntView>
00357         (home,share,p,x[0],x[1],x[2],c);
00358     if (x.size() == 2)
00359       return new (home) EqTer<Val,IntView,IntView,MinusView>
00360         (home,share,p,x[0],x[1],MinusView(y[0]),c);
00361     if (x.size() == 1)
00362       return new (home) EqTer<Val,IntView,IntView,MinusView>
00363         (home,share,p,y[0],y[1],MinusView(x[0]),-c);
00364     return new (home) EqTer<Val,IntView,IntView,IntView>
00365       (home,share,p,y[0],y[1],y[2],-c);
00366   }
00367 
00368   template<class Val, class P, class N>
00369   Actor*
00370   Eq<Val,P,N>::copy(Space& home, bool share) {
00371     if (isunit(x,y)) {
00372       // Check whether rewriting is possible
00373       if (x.size() + y.size() == 2)
00374         return eqtobin(home,share,*this,x,y,c);
00375       if (x.size() + y.size() == 3)
00376         return eqtoter(home,share,*this,x,y,c);
00377     }
00378     return new (home) Eq<Val,P,N>(home,share,*this);
00379   }
00380 
00381   template<class Val, class P, class N>
00382   ExecStatus
00383   Eq<Val,P,N>::propagate(Space& home, const ModEventDelta& med) {
00384     return prop_bnd<Val,P,N>(home,med,*this,x,y,c);
00385   }
00386 
00387   /*
00388    * Reified bound consistent linear equation
00389    *
00390    */
00391 
00392   template<class Val, class P, class N, class Ctrl, ReifyMode rm>
00393   forceinline
00394   ReEq<Val,P,N,Ctrl,rm>::ReEq(Home home,
00395                               ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b)
00396     : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,x,y,c,b) {}
00397 
00398   template<class Val, class P, class N, class Ctrl, ReifyMode rm>
00399   ExecStatus
00400   ReEq<Val,P,N,Ctrl,rm>::post(Home home,
00401                               ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b) {
00402     ViewArray<NoView> nva;
00403     if (y.size() == 0) {
00404       (void) new (home) ReEq<Val,P,NoView,Ctrl,rm>(home,x,nva,c,b);
00405     } else if (x.size() == 0) {
00406       (void) new (home) ReEq<Val,N,NoView,Ctrl,rm>(home,y,nva,-c,b);
00407     } else {
00408       (void) new (home) ReEq<Val,P,N,Ctrl,rm>(home,x,y,c,b);
00409     }
00410     return ES_OK;
00411   }
00412 
00413 
00414   template<class Val, class P, class N, class Ctrl, ReifyMode rm>
00415   forceinline
00416   ReEq<Val,P,N,Ctrl,rm>::ReEq(Space& home, bool share, 
00417                               ReEq<Val,P,N,Ctrl,rm>& p)
00418     : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,share,p) {}
00419 
00420   template<class Val, class P, class N, class Ctrl, ReifyMode rm>
00421   Actor*
00422   ReEq<Val,P,N,Ctrl,rm>::copy(Space& home, bool share) {
00423     return new (home) ReEq<Val,P,N,Ctrl,rm>(home,share,*this);
00424   }
00425 
00426   template<class Val, class P, class N, class Ctrl, ReifyMode rm>
00427   ExecStatus
00428   ReEq<Val,P,N,Ctrl,rm>::propagate(Space& home, const ModEventDelta& med) {
00429     if (b.zero()) {
00430       if (rm == RM_IMP)
00431         return home.ES_SUBSUMED(*this);        
00432       GECODE_REWRITE(*this,(Nq<Val,P,N>::post(home(*this),x,y,c)));
00433     }
00434     if (b.one()) {
00435       if (rm == RM_PMI)
00436         return home.ES_SUBSUMED(*this);        
00437       GECODE_REWRITE(*this,(Eq<Val,P,N>::post(home(*this),x,y,c)));
00438     }
00439 
00440     Val sl = 0;
00441     Val su = 0;
00442 
00443     bounds_p<Val,P>(med, x, c, sl, su);
00444     bounds_n<Val,N>(med, y, c, sl, su);
00445 
00446     if ((-sl == c) && (-su == c)) {
00447       if (rm != RM_IMP)
00448         GECODE_ME_CHECK(b.one_none(home));
00449       return home.ES_SUBSUMED(*this);
00450     }
00451     if ((-sl > c) || (-su < c)) {
00452       if (rm != RM_PMI)
00453         GECODE_ME_CHECK(b.zero_none(home));
00454       return home.ES_SUBSUMED(*this);
00455     }
00456     return ES_FIX;
00457   }
00458 
00459 
00460   /*
00461    * Domain consistent linear disequation
00462    *
00463    */
00464 
00465   template<class Val, class P, class N>
00466   forceinline
00467   Nq<Val,P,N>::Nq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c)
00468     : Lin<Val,P,N,PC_INT_VAL>(home,x,y,c) {}
00469 
00470   template<class Val, class P, class N>
00471   ExecStatus
00472   Nq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
00473     ViewArray<NoView> nva;
00474     if (y.size() == 0) {
00475       (void) new (home) Nq<Val,P,NoView>(home,x,nva,c);
00476     } else if (x.size() == 0) {
00477       (void) new (home) Nq<Val,N,NoView>(home,y,nva,-c);
00478     } else {
00479       (void) new (home) Nq<Val,P,N>(home,x,y,c);
00480     }
00481     return ES_OK;
00482   }
00483 
00484 
00485   template<class Val, class P, class N>
00486   forceinline
00487   Nq<Val,P,N>::Nq(Space& home, bool share, Nq<Val,P,N>& p)
00488     : Lin<Val,P,N,PC_INT_VAL>(home,share,p) {}
00489 
00494   template<class Val, class P, class N>
00495   forceinline Actor*
00496   nqtobin(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00497     return NULL;
00498   }
00499   template<class Val>
00500   forceinline Actor*
00501   nqtobin(Space& home, bool share, Propagator& p,
00502           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00503     assert(x.size() == 2);
00504     return new (home) NqBin<Val,IntView,IntView>
00505       (home,share,p,x[0],x[1],c);
00506   }
00507   template<class Val>
00508   forceinline Actor*
00509   nqtobin(Space& home, bool share, Propagator& p,
00510           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00511     assert(y.size() == 2);
00512     return new (home) NqBin<Val,IntView,IntView>
00513       (home,share,p,y[0],y[1],-c);
00514   }
00515   template<class Val>
00516   forceinline Actor*
00517   nqtobin(Space& home, bool share, Propagator& p,
00518           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00519     if (x.size() == 2)
00520       return new (home) NqBin<Val,IntView,IntView>
00521         (home,share,p,x[0],x[1],c);
00522     if (x.size() == 1)
00523       return new (home) NqBin<Val,IntView,MinusView>
00524         (home,share,p,x[0],MinusView(y[0]),c);
00525     return new (home) NqBin<Val,IntView,IntView>
00526       (home,share,p,y[0],y[1],-c);
00527   }
00528 
00533   template<class Val, class P, class N>
00534   forceinline Actor*
00535   nqtoter(Space&, bool, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) {
00536     return NULL;
00537   }
00538   template<class Val>
00539   forceinline Actor*
00540   nqtoter(Space& home, bool share, Propagator& p,
00541           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00542     assert(x.size() == 3);
00543     return new (home) NqTer<Val,IntView,IntView,IntView>
00544       (home,share,p,x[0],x[1],x[2],c);
00545   }
00546   template<class Val>
00547   forceinline Actor*
00548   nqtoter(Space& home, bool share, Propagator& p,
00549           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00550     assert(y.size() == 3);
00551     return new (home) NqTer<Val,IntView,IntView,IntView>
00552       (home,share,p,y[0],y[1],y[2],-c);
00553   }
00554   template<class Val>
00555   forceinline Actor*
00556   nqtoter(Space& home, bool share, Propagator& p,
00557           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00558     if (x.size() == 3)
00559       return new (home) NqTer<Val,IntView,IntView,IntView>
00560         (home,share,p,x[0],x[1],x[2],c);
00561     if (x.size() == 2)
00562       return new (home) NqTer<Val,IntView,IntView,MinusView>
00563         (home,share,p,x[0],x[1],MinusView(y[0]),c);
00564     if (x.size() == 1)
00565       return new (home) NqTer<Val,IntView,IntView,MinusView>
00566         (home,share,p,y[0],y[1],MinusView(x[0]),-c);
00567     return new (home) NqTer<Val,IntView,IntView,IntView>
00568       (home,share,p,y[0],y[1],y[2],-c);
00569   }
00570 
00571   template<class Val, class P, class N>
00572   Actor*
00573   Nq<Val,P,N>::copy(Space& home, bool share) {
00574     if (isunit(x,y)) {
00575       // Check whether rewriting is possible
00576       if (x.size() + y.size() == 2)
00577         return nqtobin(home,share,*this,x,y,c);
00578       if (x.size() + y.size() == 3)
00579         return nqtoter(home,share,*this,x,y,c);
00580     }
00581     return new (home) Nq<Val,P,N>(home,share,*this);
00582   }
00583 
00584   template<class Val, class P, class N>
00585   ExecStatus
00586   Nq<Val,P,N>::propagate(Space& home, const ModEventDelta&) {
00587     for (int i = x.size(); i--; )
00588       if (x[i].assigned()) {
00589         c -= x[i].val();  x.move_lst(i);
00590       }
00591     for (int i = y.size(); i--; )
00592       if (y[i].assigned()) {
00593         c += y[i].val();  y.move_lst(i);
00594       }
00595     if (x.size() + y.size() <= 1) {
00596       if (x.size() == 1) {
00597         GECODE_ME_CHECK(x[0].nq(home,c)); return home.ES_SUBSUMED(*this);
00598       }
00599       if (y.size() == 1) {
00600         GECODE_ME_CHECK(y[0].nq(home,-c)); return home.ES_SUBSUMED(*this);
00601       }
00602       return (c == static_cast<Val>(0)) ?
00603         ES_FAILED : home.ES_SUBSUMED(*this);
00604     }
00605     return ES_FIX;
00606   }
00607 
00608 
00609   /*
00610    * Bound consistent linear inequation
00611    *
00612    */
00613 
00614   template<class Val, class P, class N>
00615   forceinline
00616   Lq<Val,P,N>::Lq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c)
00617     : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {}
00618 
00619   template<class Val, class P, class N>
00620   ExecStatus
00621   Lq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
00622     ViewArray<NoView> nva;
00623     if (y.size() == 0) {
00624       (void) new (home) Lq<Val,P,NoView>(home,x,nva,c);
00625     } else if (x.size() == 0) {
00626       (void) new (home) Lq<Val,NoView,N>(home,nva,y,c);
00627     } else {
00628       (void) new (home) Lq<Val,P,N>(home,x,y,c);
00629     }
00630     return ES_OK;
00631   }
00632 
00633 
00634   template<class Val, class P, class N>
00635   forceinline
00636   Lq<Val,P,N>::Lq(Space& home, bool share, Lq<Val,P,N>& p)
00637     : Lin<Val,P,N,PC_INT_BND>(home,share,p) {}
00638 
00643   template<class Val, class P, class N>
00644   forceinline Actor*
00645   lqtobin(Space&, bool, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) {
00646     return NULL;
00647   }
00648   template<class Val>
00649   forceinline Actor*
00650   lqtobin(Space& home, bool share, Propagator& p,
00651           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00652     assert(x.size() == 2);
00653     return new (home) LqBin<Val,IntView,IntView>
00654       (home,share,p,x[0],x[1],c);
00655   }
00656   template<class Val>
00657   forceinline Actor*
00658   lqtobin(Space& home, bool share, Propagator& p,
00659           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00660     assert(y.size() == 2);
00661     return new (home) LqBin<Val,MinusView,MinusView>
00662       (home,share,p,MinusView(y[0]),MinusView(y[1]),c);
00663   }
00664   template<class Val>
00665   forceinline Actor*
00666   lqtobin(Space& home, bool share, Propagator& p,
00667           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00668     if (x.size() == 2)
00669       return new (home) LqBin<Val,IntView,IntView>
00670         (home,share,p,x[0],x[1],c);
00671     if (x.size() == 1)
00672       return new (home) LqBin<Val,IntView,MinusView>
00673         (home,share,p,x[0],MinusView(y[0]),c);
00674     return new (home) LqBin<Val,MinusView,MinusView>
00675       (home,share,p,MinusView(y[0]),MinusView(y[1]),c);
00676   }
00677 
00682   template<class Val, class P, class N>
00683   forceinline Actor*
00684   lqtoter(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00685     return NULL;
00686   }
00687   template<class Val>
00688   forceinline Actor*
00689   lqtoter(Space& home, bool share, Propagator& p,
00690           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00691     assert(x.size() == 3);
00692     return new (home) LqTer<Val,IntView,IntView,IntView>
00693       (home,share,p,x[0],x[1],x[2],c);
00694   }
00695   template<class Val>
00696   forceinline Actor*
00697   lqtoter(Space& home, bool share, Propagator& p,
00698           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00699     assert(y.size() == 3);
00700     return new (home) LqTer<Val,MinusView,MinusView,MinusView>
00701       (home,share,p,MinusView(y[0]),MinusView(y[1]),MinusView(y[2]),c);
00702   }
00703   template<class Val>
00704   forceinline Actor*
00705   lqtoter(Space& home, bool share, Propagator& p,
00706           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00707     if (x.size() == 3)
00708       return new (home) LqTer<Val,IntView,IntView,IntView>
00709         (home,share,p,x[0],x[1],x[2],c);
00710     if (x.size() == 2)
00711       return new (home) LqTer<Val,IntView,IntView,MinusView>
00712         (home,share,p,x[0],x[1],MinusView(y[0]),c);
00713     if (x.size() == 1)
00714       return new (home) LqTer<Val,IntView,MinusView,MinusView>
00715         (home,share,p,x[0],MinusView(y[0]),MinusView(y[1]),c);
00716     return new (home) LqTer<Val,MinusView,MinusView,MinusView>
00717       (home,share,p,MinusView(y[0]),MinusView(y[1]),MinusView(y[2]),c);
00718   }
00719 
00720   template<class Val, class P, class N>
00721   Actor*
00722   Lq<Val,P,N>::copy(Space& home, bool share) {
00723     if (isunit(x,y)) {
00724       // Check whether rewriting is possible
00725       if (x.size() + y.size() == 2)
00726         return lqtobin(home,share,*this,x,y,c);
00727       if (x.size() + y.size() == 3)
00728         return lqtoter(home,share,*this,x,y,c);
00729     }
00730     return new (home) Lq<Val,P,N>(home,share,*this);
00731   }
00732 
00733   template<class Val, class P, class N>
00734   ExecStatus
00735   Lq<Val,P,N>::propagate(Space& home, const ModEventDelta& med) {
00736     // Eliminate singletons
00737     Val sl = 0;
00738 
00739     if (IntView::me(med) == ME_INT_VAL) {
00740       for (int i = x.size(); i--; ) {
00741         Val m = x[i].min();
00742         if (x[i].assigned()) {
00743           c  -= m;  x.move_lst(i);
00744         } else {
00745           sl -= m;
00746         }
00747       }
00748       for (int i = y.size(); i--; ) {
00749         Val m = y[i].max();
00750         if (y[i].assigned()) {
00751           c  += m;  y.move_lst(i);
00752         } else {
00753           sl += m;
00754         }
00755       }
00756       if ((x.size() + y.size()) <= 1) {
00757         if (x.size() == 1) {
00758           GECODE_ME_CHECK(x[0].lq(home,c));
00759           return home.ES_SUBSUMED(*this);
00760         }
00761         if (y.size() == 1) {
00762           GECODE_ME_CHECK(y[0].gq(home,-c));
00763           return home.ES_SUBSUMED(*this);
00764         }
00765         return (c >= static_cast<Val>(0)) ?
00766           home.ES_SUBSUMED(*this) : ES_FAILED;
00767       }
00768     } else {
00769       for (int i = x.size(); i--; )
00770         sl -= x[i].min();
00771       for (int i = y.size(); i--; )
00772         sl += y[i].max();
00773     }
00774 
00775     sl += c;
00776 
00777     ExecStatus es = ES_FIX;
00778     bool assigned = true;
00779     for (int i = x.size(); i--; ) {
00780       assert(!x[i].assigned());
00781       Val slx = sl + x[i].min();
00782       ModEvent me = x[i].lq(home,slx);
00783       if (me == ME_INT_FAILED)
00784         return ES_FAILED;
00785       if (me != ME_INT_VAL)
00786         assigned = false;
00787       if (me_modified(me) && (slx != x[i].max()))
00788         es = ES_NOFIX;
00789     }
00790 
00791     for (int i = y.size(); i--; ) {
00792       assert(!y[i].assigned());
00793       Val sly = y[i].max() - sl;
00794       ModEvent me = y[i].gq(home,sly);
00795       if (me == ME_INT_FAILED)
00796         return ES_FAILED;
00797       if (me != ME_INT_VAL)
00798         assigned = false;
00799       if (me_modified(me) && (sly != y[i].min()))
00800         es = ES_NOFIX;
00801     }
00802     return assigned ? home.ES_SUBSUMED(*this) : es;
00803   }
00804 
00805   /*
00806    * Reified bound consistent linear inequation
00807    *
00808    */
00809 
00810   template<class Val, class P, class N, ReifyMode rm>
00811   forceinline
00812   ReLq<Val,P,N,rm>::ReLq(Home home, 
00813                       ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b)
00814     : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,x,y,c,b) {}
00815 
00816   template<class Val, class P, class N, ReifyMode rm>
00817   ExecStatus
00818   ReLq<Val,P,N,rm>::post(Home home, 
00819                          ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b) {
00820     ViewArray<NoView> nva;
00821     if (y.size() == 0) {
00822       (void) new (home) ReLq<Val,P,NoView,rm>(home,x,nva,c,b);
00823     } else if (x.size() == 0) {
00824       (void) new (home) ReLq<Val,NoView,N,rm>(home,nva,y,c,b);
00825     } else {
00826       (void) new (home) ReLq<Val,P,N,rm>(home,x,y,c,b);
00827     }
00828     return ES_OK;
00829   }
00830 
00831 
00832   template<class Val, class P, class N, ReifyMode rm>
00833   forceinline
00834   ReLq<Val,P,N,rm>::ReLq(Space& home, bool share, ReLq<Val,P,N,rm>& p)
00835     : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,share,p) {}
00836 
00837   template<class Val, class P, class N, ReifyMode rm>
00838   Actor*
00839   ReLq<Val,P,N,rm>::copy(Space& home, bool share) {
00840     return new (home) ReLq<Val,P,N,rm>(home,share,*this);
00841   }
00842 
00843   template<class Val, class P, class N, ReifyMode rm>
00844   ExecStatus
00845   ReLq<Val,P,N,rm>::propagate(Space& home, const ModEventDelta& med) {
00846     if (b.zero()) {
00847       if (rm == RM_IMP)
00848         return home.ES_SUBSUMED(*this);              
00849       GECODE_REWRITE(*this,(Lq<Val,N,P>::post(home(*this),y,x,-c-1)));
00850     }
00851     if (b.one()) {
00852       if (rm == RM_PMI)
00853         return home.ES_SUBSUMED(*this);        
00854       GECODE_REWRITE(*this,(Lq<Val,P,N>::post(home(*this),x,y,c)));
00855     }
00856 
00857     // Eliminate singletons
00858     Val sl = 0;
00859     Val su = 0;
00860 
00861     bounds_p<Val,P>(med,x,c,sl,su);
00862     bounds_n<Val,N>(med,y,c,sl,su);
00863 
00864     if (-sl > c) {
00865       if (rm != RM_PMI)
00866         GECODE_ME_CHECK(b.zero_none(home));
00867       return home.ES_SUBSUMED(*this);
00868     }
00869     if (-su <= c) {
00870       if (rm != RM_IMP)
00871         GECODE_ME_CHECK(b.one_none(home));
00872       return home.ES_SUBSUMED(*this);
00873     }
00874 
00875     return ES_FIX;
00876   }
00877 
00878 }}}
00879 
00880 // STATISTICS: int-prop
00881