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

int-nary.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, 2003
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 "gecode/int/linear/int-noview.icc"
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(Space* 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(ModEventDelta) const {
00082     return cost_lo(x.size() + y.size(), PC_LINEAR_LO);
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     assert(!home->failed());
00089     x.cancel(home,this,pc);
00090     y.cancel(home,this,pc);
00091     (void) Propagator::dispose(home);
00092     return sizeof(*this);
00093   }
00094 
00095   template <class Val, class P, class N, PropCond pc>
00096   Reflection::ActorSpec
00097   Lin<Val,P,N,pc>::spec(const Space* home, Reflection::VarMap& m,
00098                         const Support::Symbol& ati) const {
00099     Reflection::ActorSpec s(ati);
00100     return s << x.spec(home, m)
00101              << y.spec(home, m)
00102              << c;
00103   }
00104 
00105   /*
00106    * Reified linear propagators
00107    *
00108    */
00109   template <class Val, class P, class N, PropCond pc, class Ctrl>
00110   forceinline
00111   ReLin<Val,P,N,pc,Ctrl>::ReLin
00112   (Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b0)
00113     : Lin<Val,P,N,pc>(home,x,y,c), b(b0) {
00114     b.subscribe(home,this,PC_INT_VAL);
00115   }
00116 
00117   template <class Val, class P, class N, PropCond pc, class Ctrl>
00118   forceinline
00119   ReLin<Val,P,N,pc,Ctrl>::ReLin
00120   (Space* home, bool share, ReLin<Val,P,N,pc,Ctrl>& p)
00121     : Lin<Val,P,N,pc>(home,share,p) {
00122     b.update(home,share,p.b);
00123   }
00124 
00125   template <class Val, class P, class N, PropCond pc, class Ctrl>
00126   forceinline size_t
00127   ReLin<Val,P,N,pc,Ctrl>::dispose(Space* home) {
00128     assert(!home->failed());
00129     b.cancel(home,this,PC_BOOL_VAL);
00130     (void) Lin<Val,P,N,pc>::dispose(home);
00131     return sizeof(*this);
00132   }
00133 
00134   template <class Val, class P, class N, PropCond pc, class Ctrl>
00135   Reflection::ActorSpec
00136   ReLin<Val,P,N,pc,Ctrl>::spec(const Space* home, Reflection::VarMap& m,
00137                                const Support::Symbol& ati) const {
00138     Reflection::ActorSpec s(ati);
00139     return s << Lin<Val,P,N,pc>::x.spec(home, m)
00140              << Lin<Val,P,N,pc>::y.spec(home, m)
00141              << Lin<Val,P,N,pc>::c
00142              << b.spec(home, m);
00143   }
00144 
00145   /*
00146    * Computing bounds
00147    *
00148    */
00149 
00150   template <class Val, class View>
00151   void
00152   bounds_p(ModEventDelta med, ViewArray<View>& x, Val& c, Val& sl, Val& su) {
00153     int n = x.size();
00154     if (IntView::me(med) == ME_INT_VAL) {
00155       for (int i = n; i--; ) {
00156         Val m = x[i].min();
00157         if (x[i].assigned()) {
00158           c -= m; x[i] = x[--n];
00159         } else {
00160           sl -= m; su -= x[i].max();
00161         }
00162       }
00163       x.size(n);
00164     } else {
00165       for (int i = n; i--; ) {
00166         sl -= x[i].min(); su -= x[i].max();
00167       }
00168     }
00169   }
00170 
00171   template <class Val, class View>
00172   void
00173   bounds_n(ModEventDelta med, ViewArray<View>& y, Val& c, Val& sl, Val& su) {
00174     int n = y.size();
00175     if (IntView::me(med) == ME_INT_VAL) {
00176       for (int i = n; i--; ) {
00177         Val m = y[i].max();
00178         if (y[i].assigned()) {
00179           c += m; y[i] = y[--n];
00180         } else {
00181           sl += m; su += y[i].min();
00182         }
00183       }
00184       y.size(n);
00185     } else {
00186       for (int i = n; i--; ) {
00187         sl += y[i].max(); su += y[i].min();
00188       }
00189     }
00190   }
00191 
00192 
00193   template <class Val, class P, class N>
00194   ExecStatus
00195   prop_bnd(Space* home, ModEventDelta med, Propagator* p,
00196            ViewArray<P>& x, ViewArray<N>& y, Val& c) {
00197     // Eliminate singletons
00198     Val sl = 0;
00199     Val su = 0;
00200 
00201     bounds_p<Val,P>(med, x, c, sl, su);
00202     bounds_n<Val,N>(med, y, c, sl, su);
00203 
00204     if ((IntView::me(med) == ME_INT_VAL) && ((x.size() + y.size()) <= 1)) {
00205       if (x.size() == 1) {
00206         GECODE_ME_CHECK(x[0].eq(home,c)); 
00207         return ES_SUBSUMED(p,sizeof(*p));
00208       }
00209       if (y.size() == 1) {
00210         GECODE_ME_CHECK(y[0].eq(home,-c)); 
00211         return ES_SUBSUMED(p,sizeof(*p));
00212       }
00213       return (c == static_cast<Val>(0)) ? 
00214         ES_SUBSUMED(p,sizeof(*p)) : ES_FAILED;
00215     }
00216 
00217     sl += c; su += c;
00218 
00219     const int mod_sl = 1;
00220     const int mod_su = 2;
00221 
00222     int mod = mod_sl | mod_su;
00223 
00224     do {
00225       if (mod & mod_sl) {
00226         mod -= mod_sl;
00227         // Propagate upper bound for positive variables
00228         for (int i = x.size(); i--; ) {
00229           const Val xi_max = x[i].max();
00230           ModEvent me = x[i].lq(home,sl + x[i].min());
00231           if (me_failed(me))
00232             return ES_FAILED;
00233           if (me_modified(me)) {
00234             su += xi_max - x[i].max();
00235             mod |= mod_su;
00236           }
00237         }
00238         // Propagate lower bound for negative variables
00239         for (int i = y.size(); i--; ) {
00240           const Val yi_min = y[i].min();
00241           ModEvent me = y[i].gq(home,y[i].max() - sl);
00242           if (me_failed(me))
00243             return ES_FAILED;
00244           if (me_modified(me)) {
00245             su += y[i].min() - yi_min;
00246             mod |= mod_su;
00247           }
00248         }
00249       }
00250       if (mod & mod_su) {
00251         mod -= mod_su;
00252         // Propagate lower bound for positive variables
00253         for (int i = x.size(); i--; ) {
00254           const Val xi_min = x[i].min();
00255           ModEvent me = x[i].gq(home,su + x[i].max());
00256           if (me_failed(me))
00257             return ES_FAILED;
00258           if (me_modified(me)) {
00259             sl += xi_min - x[i].min();
00260             mod |= mod_sl;
00261           }
00262         }
00263         // Propagate upper bound for negative variables
00264         for (int i = y.size(); i--; ) {
00265           const Val yi_max = y[i].max();
00266           ModEvent me = y[i].lq(home,y[i].min() - su);
00267           if (me_failed(me))
00268             return ES_FAILED;
00269           if (me_modified(me)) {
00270             sl += y[i].max() - yi_max;
00271             mod |= mod_sl;
00272           }
00273         }
00274       }
00275     } while (mod);
00276 
00277     return (sl == su) ? ES_SUBSUMED(p,sizeof(*p)) : ES_FIX;
00278   }
00279 
00280   /*
00281    * Bound consistent linear equation
00282    *
00283    */
00284 
00285   template <class Val, class P, class N>
00286   forceinline
00287   Eq<Val,P,N>::Eq(Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c)
00288     : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {}
00289 
00290   template <class Val, class P, class N>
00291   ExecStatus
00292   Eq<Val,P,N>::post(Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
00293     ViewArray<NoView> nva;
00294     if (y.size() == 0) {
00295       (void) new (home) Eq<Val,P,NoView>(home,x,nva,c);
00296     } else if (x.size() == 0) {
00297       (void) new (home) Eq<Val,N,NoView>(home,y,nva,-c);
00298     } else {
00299       (void) new (home) Eq<Val,P,N>(home,x,y,c);
00300     }
00301     return ES_OK;
00302   }
00303 
00304 
00305   template <class Val, class P, class N>
00306   forceinline
00307   Eq<Val,P,N>::Eq(Space* home, bool share, Eq<Val,P,N>& p)
00308     : Lin<Val,P,N,PC_INT_BND>(home,share,p) {}
00309 
00314   template <class Val, class P, class N>
00315   forceinline Actor*
00316   eqtobin(Space*, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00317     return NULL;
00318   }
00319   template <class Val>
00320   forceinline Actor*
00321   eqtobin(Space* home, bool share, Propagator& p,
00322           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00323     assert(x.size() == 2);
00324     return new (home) EqBin<Val,IntView,IntView>
00325       (home,share,p,x[0],x[1],c);
00326   }
00327   template <class Val>
00328   forceinline Actor*
00329   eqtobin(Space* home, bool share, Propagator& p,
00330           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00331     assert(y.size() == 2);
00332     return new (home) EqBin<Val,IntView,IntView>
00333       (home,share,p,y[0],y[1],-c);
00334   }
00335   template <class Val>
00336   forceinline Actor*
00337   eqtobin(Space* home, bool share, Propagator& p,
00338           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00339     if (x.size() == 2)
00340       return new (home) EqBin<Val,IntView,IntView>
00341         (home,share,p,x[0],x[1],c);
00342     if (x.size() == 1)
00343       return new (home) EqBin<Val,IntView,MinusView>
00344         (home,share,p,x[0],y[0],c);
00345     return new (home) EqBin<Val,IntView,IntView>
00346       (home,share,p,y[0],y[1],-c);
00347   }
00348 
00353   template <class Val, class P, class N>
00354   forceinline Actor*
00355   eqtoter(Space*, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00356     return NULL;
00357   }
00358   template <class Val>
00359   forceinline Actor*
00360   eqtoter(Space* home, bool share, Propagator& p,
00361           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00362     assert(x.size() == 3);
00363     return new (home) EqTer<Val,IntView,IntView,IntView>
00364       (home,share,p,x[0],x[1],x[2],c);
00365   }
00366   template <class Val>
00367   forceinline Actor*
00368   eqtoter(Space* home, bool share, Propagator& p,
00369           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00370     assert(y.size() == 3);
00371     return new (home) EqTer<Val,IntView,IntView,IntView>
00372       (home,share,p,y[0],y[1],y[2],-c);
00373   }
00374   template <class Val>
00375   forceinline Actor*
00376   eqtoter(Space* home, bool share, Propagator& p,
00377           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00378     if (x.size() == 3)
00379       return new (home) EqTer<Val,IntView,IntView,IntView>
00380         (home,share,p,x[0],x[1],x[2],c);
00381     if (x.size() == 2)
00382       return new (home) EqTer<Val,IntView,IntView,MinusView>
00383         (home,share,p,x[0],x[1],y[0],c);
00384     if (x.size() == 1)
00385       return new (home) EqTer<Val,IntView,IntView,MinusView>
00386         (home,share,p,y[0],y[1],x[0],-c);
00387     return new (home) EqTer<Val,IntView,IntView,IntView>
00388       (home,share,p,y[0],y[1],y[2],-c);
00389   }
00390 
00391   template <class Val, class P, class N>
00392   Actor*
00393   Eq<Val,P,N>::copy(Space* home, bool share) {
00394     if (isunit(x,y)) {
00395       // Check whether rewriting is possible
00396       if (x.size() + y.size() == 2)
00397         return eqtobin(home,share,*this,x,y,c);
00398       if (x.size() + y.size() == 3)
00399         return eqtoter(home,share,*this,x,y,c);
00400     }
00401     return new (home) Eq<Val,P,N>(home,share,*this);
00402   }
00403 
00404 
00405   template <class Val, class P, class N>
00406   inline Support::Symbol
00407   Eq<Val,P,N>::ati(void) {
00408     return Reflection::mangle<Val,P,N>("Gecode::Int::Linear::Eq");
00409   }
00410 
00411   template <class Val, class P, class N>
00412   Reflection::ActorSpec
00413   Eq<Val,P,N>::spec(const Space* home, Reflection::VarMap& m) const {
00414     return Lin<Val,P,N,PC_INT_BND>::spec(home, m, ati());
00415   }
00416 
00417   template <class Val, class P, class N>
00418   void
00419   Eq<Val,P,N>::post(Space* home, Reflection::VarMap& vars,
00420                     const Reflection::ActorSpec& spec) {
00421     spec.checkArity(3);
00422     ViewArray<P> x(home, vars, spec[0]);
00423     ViewArray<N> y(home, vars, spec[1]);
00424     Val c = spec[2]->toInt();
00425     (void) new (home) Eq<Val,P,N>(home, x, y, c);
00426   }  
00427 
00428   template <class Val, class P, class N>
00429   ExecStatus
00430   Eq<Val,P,N>::propagate(Space* home, ModEventDelta med) {
00431     return prop_bnd<Val,P,N>(home,med,this,x,y,c);
00432   }
00433 
00434   /*
00435    * Reified bound consistent linear equation
00436    *
00437    */
00438 
00439   template <class Val, class P, class N, class Ctrl>
00440   forceinline
00441   ReEq<Val,P,N,Ctrl>::ReEq(Space* home,
00442                            ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b)
00443     : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,x,y,c,b) {}
00444 
00445   template <class Val, class P, class N, class Ctrl>
00446   ExecStatus
00447   ReEq<Val,P,N,Ctrl>::post(Space* home,
00448                            ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b) {
00449     ViewArray<NoView> nva;
00450     if (y.size() == 0) {
00451       (void) new (home) ReEq<Val,P,NoView,Ctrl>(home,x,nva,c,b);
00452     } else if (x.size() == 0) {
00453       (void) new (home) ReEq<Val,N,NoView,Ctrl>(home,y,nva,-c,b);
00454     } else {
00455       (void) new (home) ReEq<Val,P,N,Ctrl>(home,x,y,c,b);
00456     }
00457     return ES_OK;
00458   }
00459 
00460 
00461   template <class Val, class P, class N, class Ctrl>
00462   forceinline
00463   ReEq<Val,P,N,Ctrl>::ReEq(Space* home, bool share, ReEq<Val,P,N,Ctrl>& p)
00464     : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,share,p) {}
00465 
00466   template <class Val, class P, class N, class Ctrl>
00467   Actor*
00468   ReEq<Val,P,N,Ctrl>::copy(Space* home, bool share) {
00469     return new (home) ReEq<Val,P,N,Ctrl>(home,share,*this);
00470   }
00471 
00472   template <class Val, class P, class N, class Ctrl>
00473   inline Support::Symbol
00474   ReEq<Val,P,N,Ctrl>::ati(void) {
00475     return Reflection::mangle<Val,P,N,Ctrl>("Gecode::Int::Linear::ReEq");
00476   }
00477 
00478   template <class Val, class P, class N, class Ctrl>
00479   Reflection::ActorSpec
00480   ReEq<Val,P,N,Ctrl>::spec(const Space* home, Reflection::VarMap& m) const {
00481     return ReLin<Val,P,N,PC_INT_BND,Ctrl>::spec(home, m, ati());
00482   }
00483 
00484   template <class Val, class P, class N, class Ctrl>
00485   void
00486   ReEq<Val,P,N,Ctrl>::post(Space* home, Reflection::VarMap& vars,
00487                            const Reflection::ActorSpec& spec) {
00488     spec.checkArity(4);
00489     ViewArray<P> x(home, vars, spec[0]);
00490     ViewArray<N> y(home, vars, spec[1]);
00491     Val c = spec[2]->toInt();
00492     Ctrl b(home, vars, spec[3]);
00493     (void) new (home) ReEq<Val,P,N,Ctrl>(home, x, y, c, b);
00494   }  
00495 
00496   template <class Val, class P, class N, class Ctrl>
00497   ExecStatus
00498   ReEq<Val,P,N,Ctrl>::propagate(Space* home, ModEventDelta med) {
00499     if (b.zero())
00500       GECODE_REWRITE(this,(Nq<Val,P,N>::post(home,x,y,c)));
00501     if (b.one())
00502       GECODE_REWRITE(this,(Eq<Val,P,N>::post(home,x,y,c)));
00503 
00504     Val sl = 0;
00505     Val su = 0;
00506 
00507     bounds_p<Val,P>(med, x, c, sl, su);
00508     bounds_n<Val,N>(med, y, c, sl, su);
00509 
00510     if ((-sl == c) && (-su == c)) {
00511       GECODE_ME_CHECK(b.one_none(home)); 
00512       return ES_SUBSUMED(this,sizeof(*this));
00513     }
00514     if ((-sl > c) || (-su < c)) {
00515       GECODE_ME_CHECK(b.zero_none(home)); 
00516       return ES_SUBSUMED(this,home);
00517     }
00518     return ES_FIX;
00519   }
00520 
00521 
00522   /*
00523    * Domain consistent linear disequation
00524    *
00525    */
00526 
00527   template <class Val, class P, class N>
00528   forceinline
00529   Nq<Val,P,N>::Nq(Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c)
00530     : Lin<Val,P,N,PC_INT_VAL>(home,x,y,c) {}
00531 
00532   template <class Val, class P, class N>
00533   ExecStatus
00534   Nq<Val,P,N>::post(Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
00535     ViewArray<NoView> nva;
00536     if (y.size() == 0) {
00537       (void) new (home) Nq<Val,P,NoView>(home,x,nva,c);
00538     } else if (x.size() == 0) {
00539       (void) new (home) Nq<Val,N,NoView>(home,y,nva,-c);
00540     } else {
00541       (void) new (home) Nq<Val,P,N>(home,x,y,c);
00542     }
00543     return ES_OK;
00544   }
00545 
00546 
00547   template <class Val, class P, class N>
00548   forceinline
00549   Nq<Val,P,N>::Nq(Space* home, bool share, Nq<Val,P,N>& p)
00550     : Lin<Val,P,N,PC_INT_VAL>(home,share,p) {}
00551 
00556   template <class Val, class P, class N>
00557   forceinline Actor*
00558   nqtobin(Space*, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00559     return NULL;
00560   }
00561   template <class Val>
00562   forceinline Actor*
00563   nqtobin(Space* home, bool share, Propagator& p,
00564           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00565     assert(x.size() == 2);
00566     return new (home) NqBin<Val,IntView,IntView>
00567       (home,share,p,x[0],x[1],c);
00568   }
00569   template <class Val>
00570   forceinline Actor*
00571   nqtobin(Space* home, bool share, Propagator& p,
00572           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00573     assert(y.size() == 2);
00574     return new (home) NqBin<Val,IntView,IntView>
00575       (home,share,p,y[0],y[1],-c);
00576   }
00577   template <class Val>
00578   forceinline Actor*
00579   nqtobin(Space* home, bool share, Propagator& p,
00580           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00581     if (x.size() == 2)
00582       return new (home) NqBin<Val,IntView,IntView>
00583         (home,share,p,x[0],x[1],c);
00584     if (x.size() == 1)
00585       return new (home) NqBin<Val,IntView,MinusView>
00586         (home,share,p,x[0],y[0],c);
00587     return new (home) NqBin<Val,IntView,IntView>
00588       (home,share,p,y[0],y[1],-c);
00589   }
00590 
00595   template <class Val, class P, class N>
00596   forceinline Actor*
00597   nqtoter(Space*, bool, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) {
00598     return NULL;
00599   }
00600   template <class Val>
00601   forceinline Actor*
00602   nqtoter(Space* home, bool share, Propagator& p,
00603           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00604     assert(x.size() == 3);
00605     return new (home) NqTer<Val,IntView,IntView,IntView>
00606       (home,share,p,x[0],x[1],x[2],c);
00607   }
00608   template <class Val>
00609   forceinline Actor*
00610   nqtoter(Space* home, bool share, Propagator& p,
00611           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00612     assert(y.size() == 3);
00613     return new (home) NqTer<Val,IntView,IntView,IntView>
00614       (home,share,p,y[0],y[1],y[2],-c);
00615   }
00616   template <class Val>
00617   forceinline Actor*
00618   nqtoter(Space* home, bool share, Propagator& p,
00619           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00620     if (x.size() == 3)
00621       return new (home) NqTer<Val,IntView,IntView,IntView>
00622         (home,share,p,x[0],x[1],x[2],c);
00623     if (x.size() == 2)
00624       return new (home) NqTer<Val,IntView,IntView,MinusView>
00625         (home,share,p,x[0],x[1],y[0],c);
00626     if (x.size() == 1)
00627       return new (home) NqTer<Val,IntView,IntView,MinusView>
00628         (home,share,p,y[0],y[1],x[0],-c);
00629     return new (home) NqTer<Val,IntView,IntView,IntView>
00630       (home,share,p,y[0],y[1],y[2],-c);
00631   }
00632 
00633   template <class Val, class P, class N>
00634   Actor*
00635   Nq<Val,P,N>::copy(Space* home, bool share) {
00636     if (isunit(x,y)) {
00637       // Check whether rewriting is possible
00638       if (x.size() + y.size() == 2)
00639         return nqtobin(home,share,*this,x,y,c);
00640       if (x.size() + y.size() == 3)
00641         return nqtoter(home,share,*this,x,y,c);
00642     }
00643     return new (home) Nq<Val,P,N>(home,share,*this);
00644   }
00645 
00646   template <class Val, class P, class N>
00647   Support::Symbol
00648   Nq<Val,P,N>::ati(void) {
00649     return Reflection::mangle<Val,P,N>("Gecode::Int::Linear::Nq");
00650   }
00651 
00652   template <class Val, class P, class N>
00653   Reflection::ActorSpec
00654   Nq<Val,P,N>::spec(const Space* home, Reflection::VarMap& m) const {
00655     return Lin<Val,P,N,PC_INT_VAL>::spec(home, m, ati());
00656   }
00657 
00658   template <class Val, class P, class N>
00659   void
00660   Nq<Val,P,N>::post(Space* home, Reflection::VarMap& vars,
00661                     const Reflection::ActorSpec& spec) {
00662     spec.checkArity(3);
00663     ViewArray<P> x(home, vars, spec[0]);
00664     ViewArray<N> y(home, vars, spec[1]);
00665     Val c = spec[2]->toInt();
00666     (void) new (home) Nq<Val,P,N>(home, x, y, c);
00667   }  
00668 
00669   template <class Val, class P, class N>
00670   ExecStatus
00671   Nq<Val,P,N>::propagate(Space* home, ModEventDelta) {
00672     for (int i = x.size(); i--; )
00673       if (x[i].assigned()) {
00674         c -= x[i].val();  x.move_lst(i);
00675       }
00676     for (int i = y.size(); i--; )
00677       if (y[i].assigned()) {
00678         c += y[i].val();  y.move_lst(i);
00679       }
00680     if (x.size() + y.size() <= 1) {
00681       if (x.size() == 1) {
00682         GECODE_ME_CHECK(x[0].nq(home,c)); return ES_SUBSUMED(this,home);
00683       }
00684       if (y.size() == 1) {
00685         GECODE_ME_CHECK(y[0].nq(home,-c)); return ES_SUBSUMED(this,home);
00686       }
00687       return (c == static_cast<Val>(0)) ? 
00688         ES_FAILED : ES_SUBSUMED(this,sizeof(*this));
00689     }
00690     return ES_FIX;
00691   }
00692 
00693 
00694   /*
00695    * Bound consistent linear inequation
00696    *
00697    */
00698 
00699   template <class Val, class P, class N>
00700   forceinline
00701   Lq<Val,P,N>::Lq(Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c)
00702     : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {}
00703 
00704   template <class Val, class P, class N>
00705   ExecStatus
00706   Lq<Val,P,N>::post(Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
00707     ViewArray<NoView> nva;
00708     if (y.size() == 0) {
00709       (void) new (home) Lq<Val,P,NoView>(home,x,nva,c);
00710     } else if (x.size() == 0) {
00711       (void) new (home) Lq<Val,NoView,N>(home,nva,y,c);
00712     } else {
00713       (void) new (home) Lq<Val,P,N>(home,x,y,c);
00714     }
00715     return ES_OK;
00716   }
00717 
00718 
00719   template <class Val, class P, class N>
00720   forceinline
00721   Lq<Val,P,N>::Lq(Space* home, bool share, Lq<Val,P,N>& p)
00722     : Lin<Val,P,N,PC_INT_BND>(home,share,p) {}
00723 
00728   template <class Val, class P, class N>
00729   forceinline Actor*
00730   lqtobin(Space*, bool, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) {
00731     return NULL;
00732   }
00733   template <class Val>
00734   forceinline Actor*
00735   lqtobin(Space* home, bool share, Propagator& p,
00736           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00737     assert(x.size() == 2);
00738     return new (home) LqBin<Val,IntView,IntView>
00739       (home,share,p,x[0],x[1],c);
00740   }
00741   template <class Val>
00742   forceinline Actor*
00743   lqtobin(Space* home, bool share, Propagator& p,
00744           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00745     assert(y.size() == 2);
00746     return new (home) LqBin<Val,MinusView,MinusView>
00747       (home,share,p,y[0],y[1],c);
00748   }
00749   template <class Val>
00750   forceinline Actor*
00751   lqtobin(Space* home, bool share, Propagator& p,
00752           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00753     if (x.size() == 2)
00754       return new (home) LqBin<Val,IntView,IntView>
00755         (home,share,p,x[0],x[1],c);
00756     if (x.size() == 1)
00757       return new (home) LqBin<Val,IntView,MinusView>
00758         (home,share,p,x[0],y[0],c);
00759     return new (home) LqBin<Val,MinusView,MinusView>
00760       (home,share,p,y[0],y[1],c);
00761   }
00762 
00767   template <class Val, class P, class N>
00768   forceinline Actor*
00769   lqtoter(Space*, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
00770     return NULL;
00771   }
00772   template <class Val>
00773   forceinline Actor*
00774   lqtoter(Space* home, bool share, Propagator& p,
00775           ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
00776     assert(x.size() == 3);
00777     return new (home) LqTer<Val,IntView,IntView,IntView>
00778       (home,share,p,x[0],x[1],x[2],c);
00779   }
00780   template <class Val>
00781   forceinline Actor*
00782   lqtoter(Space* home, bool share, Propagator& p,
00783           ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
00784     assert(y.size() == 3);
00785     return new (home) LqTer<Val,MinusView,MinusView,MinusView>
00786       (home,share,p,y[0],y[1],y[2],c);
00787   }
00788   template <class Val>
00789   forceinline Actor*
00790   lqtoter(Space* home, bool share, Propagator& p,
00791           ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
00792     if (x.size() == 3)
00793       return new (home) LqTer<Val,IntView,IntView,IntView>
00794         (home,share,p,x[0],x[1],x[2],c);
00795     if (x.size() == 2)
00796       return new (home) LqTer<Val,IntView,IntView,MinusView>
00797         (home,share,p,x[0],x[1],y[0],c);
00798     if (x.size() == 1)
00799       return new (home) LqTer<Val,IntView,MinusView,MinusView>
00800         (home,share,p,x[0],y[0],y[1],c);
00801     return new (home) LqTer<Val,MinusView,MinusView,MinusView>
00802       (home,share,p,y[0],y[1],y[2],c);
00803   }
00804 
00805   template <class Val, class P, class N>
00806   Actor*
00807   Lq<Val,P,N>::copy(Space* home, bool share) {
00808     if (isunit(x,y)) {
00809       // Check whether rewriting is possible
00810       if (x.size() + y.size() == 2)
00811         return lqtobin(home,share,*this,x,y,c);
00812       if (x.size() + y.size() == 3)
00813         return lqtoter(home,share,*this,x,y,c);
00814     }
00815     return new (home) Lq<Val,P,N>(home,share,*this);
00816   }
00817 
00818   template <class Val, class P, class N>
00819   inline Support::Symbol
00820   Lq<Val,P,N>::ati(void) {
00821     return Reflection::mangle<Val,P,N>("Gecode::Int::Linear::Lq");
00822   }
00823 
00824   template <class Val, class P, class N>
00825   Reflection::ActorSpec
00826   Lq<Val,P,N>::spec(const Space* home, Reflection::VarMap& m) const {
00827     return Lin<Val,P,N,PC_INT_BND>::spec(home, m, ati());
00828   }
00829 
00830   template <class Val, class P, class N>
00831   void
00832   Lq<Val,P,N>::post(Space* home, Reflection::VarMap& vars,
00833                     const Reflection::ActorSpec& spec) {
00834     spec.checkArity(3);
00835     ViewArray<P> x(home, vars, spec[0]);
00836     ViewArray<N> y(home, vars, spec[1]);
00837     Val c = spec[2]->toInt();
00838     (void) new (home) Lq<Val,P,N>(home, x, y, c);
00839   }  
00840 
00841   template <class Val, class P, class N>
00842   ExecStatus
00843   Lq<Val,P,N>::propagate(Space* home, ModEventDelta med) {
00844     // Eliminate singletons
00845     Val sl = 0;
00846 
00847     if (IntView::me(med) == ME_INT_VAL) {
00848       for (int i = x.size(); i--; ) {
00849         Val m = x[i].min();
00850         if (x[i].assigned()) {
00851           c  -= m;  x.move_lst(i);
00852         } else {
00853           sl -= m;
00854         }
00855       }
00856       for (int i = y.size(); i--; ) {
00857         Val m = y[i].max();
00858         if (y[i].assigned()) {
00859           c  += m;  y.move_lst(i);
00860         } else {
00861           sl += m;
00862         }
00863       }
00864       if ((x.size() + y.size()) <= 1) {
00865         if (x.size() == 1) {
00866           GECODE_ME_CHECK(x[0].lq(home,c));
00867           return ES_SUBSUMED(this,home);
00868         }
00869         if (y.size() == 1) {
00870           GECODE_ME_CHECK(y[0].gq(home,-c));
00871           return ES_SUBSUMED(this,home);
00872         }
00873         return (c >= static_cast<Val>(0)) ? 
00874           ES_SUBSUMED(this,sizeof(*this)) : ES_FAILED;
00875       }
00876     } else {
00877       for (int i = x.size(); i--; )
00878         sl -= x[i].min();
00879       for (int i = y.size(); i--; )
00880         sl += y[i].max();
00881     }
00882 
00883     sl += c;
00884 
00885     ExecStatus es = ES_FIX;
00886     bool assigned = true;
00887     for (int i = x.size(); i--; ) {
00888       assert(!x[i].assigned());
00889       Val slx = sl + x[i].min();
00890       ModEvent me = x[i].lq(home,slx);
00891       if (me == ME_INT_FAILED)
00892         return ES_FAILED;
00893       if (me != ME_INT_VAL)
00894         assigned = false;
00895       if (me_modified(me) && (slx != x[i].max()))
00896         es = ES_NOFIX;
00897     }
00898 
00899     for (int i = y.size(); i--; ) {
00900       assert(!y[i].assigned());
00901       Val sly = y[i].max() - sl;
00902       ModEvent me = y[i].gq(home,sly);
00903       if (me == ME_INT_FAILED)
00904         return ES_FAILED;
00905       if (me != ME_INT_VAL)
00906         assigned = false;
00907       if (me_modified(me) && (sly != y[i].min()))
00908         es = ES_NOFIX;
00909     }
00910     return assigned ? ES_SUBSUMED(this,sizeof(*this)) : es;
00911   }
00912 
00913   /*
00914    * Reified bound consistent linear inequation
00915    *
00916    */
00917 
00918   template <class Val, class P, class N>
00919   forceinline
00920   ReLq<Val,P,N>::ReLq
00921   (Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b)
00922     : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,x,y,c,b) {}
00923 
00924   template <class Val, class P, class N>
00925   ExecStatus
00926   ReLq<Val,P,N>::post
00927   (Space* home, ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b) {
00928     ViewArray<NoView> nva;
00929     if (y.size() == 0) {
00930       (void) new (home) ReLq<Val,P,NoView>(home,x,nva,c,b);
00931     } else if (x.size() == 0) {
00932       (void) new (home) ReLq<Val,NoView,N>(home,nva,y,c,b);
00933     } else {
00934       (void) new (home) ReLq<Val,P,N>(home,x,y,c,b);
00935     }
00936     return ES_OK;
00937   }
00938 
00939 
00940   template <class Val, class P, class N>
00941   forceinline
00942   ReLq<Val,P,N>::ReLq(Space* home, bool share, ReLq<Val,P,N>& p)
00943     : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,share,p) {}
00944 
00945   template <class Val, class P, class N>
00946   Actor*
00947   ReLq<Val,P,N>::copy(Space* home, bool share) {
00948     return new (home) ReLq<Val,P,N>(home,share,*this);
00949   }
00950 
00951   template <class Val, class P, class N>
00952   inline Support::Symbol
00953   ReLq<Val,P,N>::ati(void) {
00954     return Reflection::mangle<Val,P,N>("Gecode::Int::Linear::ReLq");
00955   }
00956 
00957   template <class Val, class P, class N>
00958   Reflection::ActorSpec
00959   ReLq<Val,P,N>::spec(const Space* home, Reflection::VarMap& m) const {
00960     return ReLin<Val,P,N,PC_INT_BND,BoolView>::spec(home, m, ati());
00961   }
00962 
00963   template <class Val, class P, class N>
00964   void
00965   ReLq<Val,P,N>::post(Space* home, Reflection::VarMap& vars,
00966                       const Reflection::ActorSpec& spec) {
00967     ViewArray<P> x(home, vars, spec[0]);
00968     ViewArray<N> y(home, vars, spec[1]);
00969     Val c = spec[2]->toInt();
00970     BoolView b(home, vars, spec[3]);
00971     (void) new (home) ReLq<Val,P,N>(home, x, y, c, b);
00972   }  
00973 
00974   template <class Val, class P, class N>
00975   ExecStatus
00976   ReLq<Val,P,N>::propagate(Space* home, ModEventDelta med) {
00977     if (b.zero())
00978       GECODE_REWRITE(this,(Lq<Val,N,P>::post(home,y,x,-c-1)));
00979     if (b.one())
00980       GECODE_REWRITE(this,(Lq<Val,P,N>::post(home,x,y,c)));
00981 
00982     // Eliminate singletons
00983     Val sl = 0;
00984     Val su = 0;
00985 
00986     bounds_p<Val,P>(med,x,c,sl,su);
00987     bounds_n<Val,N>(med,y,c,sl,su);
00988 
00989     if (-sl > c) {
00990       GECODE_ME_CHECK(b.zero_none(home)); 
00991       return ES_SUBSUMED(this,home);
00992     }
00993     if (-su <= c) {
00994       GECODE_ME_CHECK(b.one_none(home)); 
00995       return ES_SUBSUMED(this,home);
00996     }
00997 
00998     return ES_FIX;
00999   }
01000 
01001 }}}
01002 
01003 // STATISTICS: int-prop
01004