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

sqr.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, 2008
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-07-11 10:49:55 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00011  *     $Revision: 7348 $
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 <cmath>
00039 
00040 namespace Gecode { namespace Int { namespace Arithmetic {
00041 
00042   /*
00043    * Positive bounds consistent squaring
00044    *
00045    */
00046   template <class VA, class VB>
00047   forceinline ExecStatus
00048   prop_sqr_plus_bnd(Space* home, VA x0, VB x1) {
00049     bool mod;
00050     do {
00051       mod = false;
00052       {
00053         ModEvent me = x0.lq(home,floor(::sqrt(static_cast<double>(x1.max()))));
00054         if (me_failed(me)) return ES_FAILED;
00055         mod |= me_modified(me);
00056       }
00057       {
00058         ModEvent me = x0.gq(home,ceil(::sqrt(static_cast<double>(x1.min()))));
00059         if (me_failed(me)) return ES_FAILED;
00060         mod |= me_modified(me);
00061       }
00062       {
00063         ModEvent me = x1.lq(home,x0.max()*x0.max());
00064         if (me_failed(me)) return ES_FAILED;
00065         mod |= me_modified(me);
00066       }
00067       {
00068         ModEvent me = x1.gq(home,x0.min()*x0.min());
00069         if (me_failed(me)) return ES_FAILED;
00070         mod |= me_modified(me);
00071       }
00072     } while (mod);
00073     return ES_OK;
00074   }
00075 
00076   template <class VA, class VB>
00077   forceinline
00078   SqrPlusBnd<VA,VB>::SqrPlusBnd(Space* home, VA x0, VB x1)
00079     : MixBinaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND>(home,x0,x1) {}
00080 
00081   template <class VA, class VB>
00082   forceinline ExecStatus
00083   SqrPlusBnd<VA,VB>::post(Space* home, VA x0, VB x1) {
00084     GECODE_ES_CHECK(prop_sqr_plus_bnd(home,x0,x1));
00085     (void) new (home) SqrPlusBnd<VA,VB>(home,x0,x1);
00086     return ES_OK;
00087   }
00088 
00089   template <class VA, class VB>
00090   forceinline void
00091   SqrPlusBnd<VA,VB>::post(Space* home, Reflection::VarMap& vars,
00092                      const Reflection::ActorSpec& spec) {
00093      spec.checkArity(2);
00094      VA x0(home, vars, spec[0]);
00095      VB x1(home, vars, spec[1]);
00096      (void) new (home) SqrPlusBnd<VA,VB>(home,x0,x1);
00097   }
00098 
00099   template <class VA, class VB>
00100   forceinline
00101   SqrPlusBnd<VA,VB>::SqrPlusBnd(Space* home, bool share, SqrPlusBnd<VA,VB>& p)
00102     : MixBinaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND>(home,share,p) {}
00103 
00104   template <class VA, class VB>
00105   Actor*
00106   SqrPlusBnd<VA,VB>::copy(Space* home, bool share) {
00107     return new (home) SqrPlusBnd<VA,VB>(home,share,*this);
00108   }
00109 
00110   template <class VA, class VB>
00111   ExecStatus
00112   SqrPlusBnd<VA,VB>::propagate(Space* home, ModEventDelta) {
00113     GECODE_ES_CHECK(prop_sqr_plus_bnd(home,x0,x1));
00114     return x0.assigned() ? ES_SUBSUMED(this,sizeof(*this)) : ES_FIX;
00115   }
00116 
00117   template <class VA, class VB>
00118   Support::Symbol
00119   SqrPlusBnd<VA,VB>::ati(void) {
00120     return Reflection::mangle<VA,VB>("Gecode::Int::Arithmetic::SqrPlusBnd");
00121   }
00122 
00123   template <class VA, class VB>
00124   Reflection::ActorSpec
00125   SqrPlusBnd<VA,VB>::spec(const Space* home, Reflection::VarMap& m) const {
00126     return MixBinaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND>
00127       ::spec(home, m, ati());
00128   }
00129 
00130 
00131 
00132   /*
00133    * Bounds consistent squaring
00134    *
00135    */
00136 
00137   template <class View>
00138   forceinline
00139   SqrBnd<View>::SqrBnd(Space* home, View x0, View x1)
00140     : BinaryPropagator<View,PC_INT_BND>(home,x0,x1) {}
00141 
00142   template <class View>
00143   forceinline ExecStatus
00144   SqrBnd<View>::post(Space* home, View x0, View x1) {
00145     GECODE_ME_CHECK(x1.gq(home,0));
00146     if (same(x0,x1)) {
00147       GECODE_ME_CHECK(x1.lq(home,1));
00148     } else {
00149       GECODE_ME_CHECK(x0.lq(home,floor(::sqrt(static_cast<double>
00150                                               (Limits::max)))));
00151       GECODE_ME_CHECK(x0.gq(home,-floor(::sqrt(static_cast<double>
00152                                                (-Limits::min)))));
00153       if (x0.min() >= 0)
00154         return SqrPlusBnd<IntView,IntView>::post(home,x0,x1);
00155       if (x0.max() <= 0)
00156         return SqrPlusBnd<MinusView,IntView>::post(home,x0,x1);
00157       GECODE_ME_CHECK(x1.lq(home,
00158                             std::max(x0.min()*x0.min(),x0.max()*x0.max())));
00159       (void) new (home) SqrBnd<View>(home,x0,x1);
00160     }
00161     return ES_OK;
00162   }
00163 
00164   template <class View>
00165   forceinline void
00166   SqrBnd<View>::post(Space* home, Reflection::VarMap& vars,
00167                      const Reflection::ActorSpec& spec) {
00168      spec.checkArity(2);
00169      View x0(home, vars, spec[0]);
00170      View x1(home, vars, spec[1]);
00171      (void) new (home) SqrBnd<View>(home,x0,x1);
00172   }
00173 
00174   template <class View>
00175   forceinline
00176   SqrBnd<View>::SqrBnd(Space* home, bool share, SqrBnd<View>& p)
00177     : BinaryPropagator<View,PC_INT_BND>(home,share,p) {}
00178 
00179   template <class View>
00180   Actor*
00181   SqrBnd<View>::copy(Space* home, bool share) {
00182     return new (home) SqrBnd<View>(home,share,*this);
00183   }
00184 
00185   template <class View>
00186   ExecStatus
00187   SqrBnd<View>::propagate(Space* home, ModEventDelta) {
00188     assert(x1.min() >= 0);
00189     if (x0.min() >= 0)
00190       GECODE_REWRITE(this,(SqrPlusBnd<IntView,IntView>::post(home,x0,x1)));
00191     if (x0.max() <= 0)
00192       GECODE_REWRITE(this,(SqrPlusBnd<MinusView,IntView>::post(home,x0,x1)));
00193 
00194     GECODE_ME_CHECK(x1.lq(home,std::max(x0.min()*x0.min(),
00195                                         x0.max()*x0.max())));
00196 
00197     int s = static_cast<int>(floor(::sqrt(static_cast<double>(x1.max()))));
00198 
00199     GECODE_ME_CHECK(x0.gq(home,-s));
00200     GECODE_ME_CHECK(x0.lq(home,s));
00201 
00202     if (x0.assigned() && x1.assigned())
00203       return (x0.val()*x0.val() == x1.val()) ? 
00204         ES_SUBSUMED(this,sizeof(*this)) : ES_FAILED;
00205 
00206     return ES_NOFIX;
00207   }
00208 
00209   template <class View>
00210   Support::Symbol
00211   SqrBnd<View>::ati(void) {
00212     return Reflection::mangle<View>("Gecode::Int::Arithmetic::SqrBnd");
00213   }
00214 
00215   template <class View>
00216   Reflection::ActorSpec
00217   SqrBnd<View>::spec(const Space* home, Reflection::VarMap& m) const {
00218     return BinaryPropagator<View,PC_INT_BND>::spec(home, m, ati());
00219   }
00220 
00221 
00222   /*
00223    * Value mappings for squaring and square root
00224    *
00225    */
00226 
00228   class ValuesMapSqr {
00229   public:
00231     forceinline int val(int n) const {
00232       return n*n;
00233     }
00234   };
00235 
00237   class ValuesMapSqrt {
00238   public:
00240     forceinline int val(int n) const {
00241       return static_cast<int>(floor(::sqrt(static_cast<double>(n))));
00242     }
00243   };
00244 
00245 
00246   /*
00247    * Positive domain consistent squaring
00248    *
00249    */
00250   template <class VA, class VB>
00251   forceinline
00252   SqrPlusDom<VA,VB>::SqrPlusDom(Space* home, VA x0, VB x1)
00253     : MixBinaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM>(home,x0,x1) {}
00254 
00255   template <class VA, class VB>
00256   forceinline ExecStatus
00257   SqrPlusDom<VA,VB>::post(Space* home, VA x0, VB x1) {
00258     GECODE_ES_CHECK(prop_sqr_plus_bnd(home,x0,x1));
00259     (void) new (home) SqrPlusDom<VA,VB>(home,x0,x1);
00260     return ES_OK;
00261   }
00262 
00263   template <class VA, class VB>
00264   forceinline void
00265   SqrPlusDom<VA,VB>::post(Space* home, Reflection::VarMap& vars,
00266                      const Reflection::ActorSpec& spec) {
00267      spec.checkArity(2);
00268      VA x0(home, vars, spec[0]);
00269      VB x1(home, vars, spec[1]);
00270      (void) new (home) SqrPlusDom<VA,VB>(home,x0,x1);
00271   }
00272 
00273   template <class VA, class VB>
00274   forceinline
00275   SqrPlusDom<VA,VB>::SqrPlusDom(Space* home, bool share, SqrPlusDom<VA,VB>& p)
00276     : MixBinaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM>(home,share,p) {}
00277 
00278   template <class VA, class VB>
00279   Actor*
00280   SqrPlusDom<VA,VB>::copy(Space* home, bool share) {
00281     return new (home) SqrPlusDom<VA,VB>(home,share,*this);
00282   }
00283 
00284   template <class VA, class VB>
00285   PropCost
00286   SqrPlusDom<VA,VB>::cost(ModEventDelta med) const {
00287     if (VA::me(med) == ME_INT_VAL)
00288       return PC_UNARY_LO;
00289     if (VA::me(med) == ME_INT_DOM)
00290       return PC_BINARY_HI;
00291     return PC_BINARY_LO;
00292   }
00293 
00294   template <class VA, class VB>
00295   ExecStatus
00296   SqrPlusDom<VA,VB>::propagate(Space* home, ModEventDelta med) {
00297     if (VA::me(med) != ME_INT_DOM) {
00298       GECODE_ES_CHECK(prop_sqr_plus_bnd(home,x0,x1));
00299       return x0.assigned() ? 
00300         ES_SUBSUMED(this,sizeof(*this)) 
00301         : ES_NOFIX_PARTIAL(this,VA::med(ME_INT_DOM));
00302     }
00303     
00304     {
00305       ViewValues<VA> v0(x0);
00306       Iter::Values::Map<ViewValues<VA>,ValuesMapSqr> s0(v0);
00307       GECODE_ME_CHECK(x1.inter_v(home,s0,false));
00308     }
00309 
00310     {
00311       ViewValues<VB> v1(x1);
00312       Iter::Values::Map<ViewValues<VB>,ValuesMapSqrt> s1(v1);
00313       GECODE_ME_CHECK(x0.inter_v(home,s1,false));
00314     }
00315 
00316     return x0.assigned() ? ES_SUBSUMED(this,sizeof(*this)) : ES_FIX;
00317   }
00318 
00319   template <class VA, class VB>
00320   Support::Symbol
00321   SqrPlusDom<VA,VB>::ati(void) {
00322     return Reflection::mangle<VA,VB>("Gecode::Int::Arithmetic::SqrPlusDom");
00323   }
00324 
00325   template <class VA, class VB>
00326   Reflection::ActorSpec
00327   SqrPlusDom<VA,VB>::spec(const Space* home, Reflection::VarMap& m) const {
00328     return MixBinaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM>
00329       ::spec(home, m, ati());
00330   }
00331 
00332 
00333 
00334   /*
00335    * Domain consistent squaring
00336    *
00337    */
00338 
00339   template <class View>
00340   forceinline
00341   SqrDom<View>::SqrDom(Space* home, View x0, View x1)
00342     : BinaryPropagator<View,PC_INT_DOM>(home,x0,x1) {}
00343 
00344   template <class View>
00345   forceinline ExecStatus
00346   SqrDom<View>::post(Space* home, View x0, View x1) {
00347     GECODE_ME_CHECK(x1.gq(home,0));
00348     if (same(x0,x1)) {
00349       GECODE_ME_CHECK(x1.lq(home,1));
00350     } else {
00351       GECODE_ME_CHECK(x0.lq(home,floor(::sqrt(static_cast<double>
00352                                               (Limits::max)))));
00353       GECODE_ME_CHECK(x0.gq(home,-floor(::sqrt(static_cast<double>
00354                                                (-Limits::min)))));
00355       if (x0.min() >= 0)
00356         return SqrPlusDom<IntView,IntView>::post(home,x0,x1);
00357       if (x0.max() <= 0)
00358         return SqrPlusDom<MinusView,IntView>::post(home,x0,x1);
00359       GECODE_ME_CHECK(x1.lq(home,
00360                             std::max(x0.min()*x0.min(),x0.max()*x0.max())));
00361       (void) new (home) SqrDom<View>(home,x0,x1);
00362     }
00363     return ES_OK;
00364   }
00365 
00366   template <class View>
00367   forceinline void
00368   SqrDom<View>::post(Space* home, Reflection::VarMap& vars,
00369                      const Reflection::ActorSpec& spec) {
00370      spec.checkArity(2);
00371      View x0(home, vars, spec[0]);
00372      View x1(home, vars, spec[1]);
00373      (void) new (home) SqrDom<View>(home,x0,x1);
00374   }
00375 
00376   template <class View>
00377   forceinline
00378   SqrDom<View>::SqrDom(Space* home, bool share, SqrDom<View>& p)
00379     : BinaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00380 
00381   template <class View>
00382   Actor*
00383   SqrDom<View>::copy(Space* home, bool share) {
00384     return new (home) SqrDom<View>(home,share,*this);
00385   }
00386 
00387   template <class View>
00388   PropCost
00389   SqrDom<View>::cost(ModEventDelta med) const {
00390     if (View::me(med) == ME_INT_VAL)
00391       return PC_UNARY_LO;
00392     if (View::me(med) == ME_INT_DOM)
00393       return PC_BINARY_HI;
00394     return PC_BINARY_LO;
00395   }
00396 
00397   template <class View>
00398   ExecStatus
00399   SqrDom<View>::propagate(Space* home, ModEventDelta med) {
00400     assert(x1.min() >= 0);
00401     if (View::me(med) != ME_INT_DOM) {
00402       if (x0.min() >= 0)
00403         GECODE_REWRITE(this,(SqrPlusDom<IntView,IntView>::post(home,x0,x1)));
00404       if (x0.max() <= 0)
00405         GECODE_REWRITE(this,(SqrPlusDom<MinusView,IntView>::post(home,x0,x1)));
00406 
00407       GECODE_ME_CHECK(x1.lq(home,std::max(x0.min()*x0.min(),
00408                                           x0.max()*x0.max())));
00409 
00410       int s = static_cast<int>(floor(::sqrt(static_cast<double>(x1.max()))));
00411 
00412       GECODE_ME_CHECK(x0.gq(home,-s));
00413       GECODE_ME_CHECK(x0.lq(home,s));
00414       
00415       if (x0.assigned() && x1.assigned())
00416         return (x0.val()*x0.val() == x1.val()) ? 
00417           ES_SUBSUMED(this,sizeof(*this)) : ES_FAILED;
00418       return ES_NOFIX_PARTIAL(this,View::med(ME_INT_DOM));
00419 
00420     }
00421     
00422     {
00423       ViewValues<View> i(x0), j(x0);
00424       using namespace Iter::Values;
00425       Positive<ViewValues<View> > p(i);
00426       Negative<ViewValues<View> > n(j);
00427       Minus<Negative<ViewValues<View> > > m(n);
00428       
00429       Map<Positive<ViewValues<View> >,ValuesMapSqr,true> sp(p);
00430       Map<Minus<Negative<ViewValues<View> > >,ValuesMapSqr,true> sm(m);
00431       Union<Map<Positive<ViewValues<View> >,ValuesMapSqr,true>,
00432         Map<Minus<Negative<ViewValues<View> > >,ValuesMapSqr,true> > u(sp,sm);
00433       GECODE_ME_CHECK(x1.inter_v(home,u,false));
00434     }
00435 
00436     {
00437       ViewValues<View> i(x1), j(x1);
00438       using namespace Iter::Values;
00439       Map<ViewValues<View>,ValuesMapSqrt,true> si(i), sj(j);
00440       Minus<Map<ViewValues<View>,ValuesMapSqrt,true> > mi(si);
00441       Union<Minus<Map<ViewValues<View>,ValuesMapSqrt,true> >,
00442         Map<ViewValues<View>,ValuesMapSqrt,true> > u(mi,sj);
00443       GECODE_ME_CHECK(x0.inter_v(home,u,false));
00444     }
00445 
00446     return x0.assigned() ? ES_SUBSUMED(this,sizeof(*this)) : ES_FIX;
00447   }
00448 
00449   template <class View>
00450   Support::Symbol
00451   SqrDom<View>::ati(void) {
00452     return Reflection::mangle<View>("Gecode::Int::Arithmetic::SqrDom");
00453   }
00454 
00455   template <class View>
00456   Reflection::ActorSpec
00457   SqrDom<View>::spec(const Space* home, Reflection::VarMap& m) const {
00458     return BinaryPropagator<View,PC_INT_DOM>::spec(home, m, ati());
00459   }
00460 
00461 }}}
00462 
00463 // STATISTICS: int-prop
00464