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

sqr.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, 2008
00008  *
00009  *  Last modified:
00010  *     $Date: 2009-02-03 11:13:22 +0100 (Tue, 03 Feb 2009) $ by $Author: schulte $
00011  *     $Revision: 8129 $
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
00091   SqrPlusBnd<VA,VB>::SqrPlusBnd(Space& home, bool share, SqrPlusBnd<VA,VB>& p)
00092     : MixBinaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND>(home,share,p) {}
00093 
00094   template <class VA, class VB>
00095   Actor*
00096   SqrPlusBnd<VA,VB>::copy(Space& home, bool share) {
00097     return new (home) SqrPlusBnd<VA,VB>(home,share,*this);
00098   }
00099 
00100   template <class VA, class VB>
00101   ExecStatus
00102   SqrPlusBnd<VA,VB>::propagate(Space& home, const ModEventDelta&) {
00103     GECODE_ES_CHECK(prop_sqr_plus_bnd(home,x0,x1));
00104     return x0.assigned() ? ES_SUBSUMED(*this,sizeof(*this)) : ES_FIX;
00105   }
00106 
00107 
00108 
00109   /*
00110    * Bounds consistent squaring
00111    *
00112    */
00113 
00114   template <class View>
00115   forceinline
00116   SqrBnd<View>::SqrBnd(Space& home, View x0, View x1)
00117     : BinaryPropagator<View,PC_INT_BND>(home,x0,x1) {}
00118 
00119   template <class View>
00120   forceinline ExecStatus
00121   SqrBnd<View>::post(Space& home, View x0, View x1) {
00122     GECODE_ME_CHECK(x1.gq(home,0));
00123     if (same(x0,x1)) {
00124       GECODE_ME_CHECK(x1.lq(home,1));
00125     } else {
00126       GECODE_ME_CHECK(x0.lq(home,floor(::sqrt(static_cast<double>
00127                                               (Limits::max)))));
00128       GECODE_ME_CHECK(x0.gq(home,-floor(::sqrt(static_cast<double>
00129                                                (-Limits::min)))));
00130       if (x0.min() >= 0)
00131         return SqrPlusBnd<IntView,IntView>::post(home,x0,x1);
00132       if (x0.max() <= 0)
00133         return SqrPlusBnd<MinusView,IntView>::post(home,x0,x1);
00134       GECODE_ME_CHECK(x1.lq(home,
00135                             std::max(x0.min()*x0.min(),x0.max()*x0.max())));
00136       (void) new (home) SqrBnd<View>(home,x0,x1);
00137     }
00138     return ES_OK;
00139   }
00140 
00141   template <class View>
00142   forceinline
00143   SqrBnd<View>::SqrBnd(Space& home, bool share, SqrBnd<View>& p)
00144     : BinaryPropagator<View,PC_INT_BND>(home,share,p) {}
00145 
00146   template <class View>
00147   Actor*
00148   SqrBnd<View>::copy(Space& home, bool share) {
00149     return new (home) SqrBnd<View>(home,share,*this);
00150   }
00151 
00152   template <class View>
00153   ExecStatus
00154   SqrBnd<View>::propagate(Space& home, const ModEventDelta&) {
00155     assert(x1.min() >= 0);
00156     if (x0.min() >= 0)
00157       GECODE_REWRITE(*this,(SqrPlusBnd<IntView,IntView>::post(home,x0,x1)));
00158     if (x0.max() <= 0)
00159       GECODE_REWRITE(*this,(SqrPlusBnd<MinusView,IntView>::post(home,x0,x1)));
00160 
00161     GECODE_ME_CHECK(x1.lq(home,std::max(x0.min()*x0.min(),
00162                                         x0.max()*x0.max())));
00163 
00164     int s = static_cast<int>(floor(::sqrt(static_cast<double>(x1.max()))));
00165 
00166     GECODE_ME_CHECK(x0.gq(home,-s));
00167     GECODE_ME_CHECK(x0.lq(home,s));
00168 
00169     if (x0.assigned() && x1.assigned())
00170       return (x0.val()*x0.val() == x1.val()) ?
00171         ES_SUBSUMED(*this,sizeof(*this)) : ES_FAILED;
00172 
00173     return ES_NOFIX;
00174   }
00175 
00176   /*
00177    * Value mappings for squaring and square root
00178    *
00179    */
00180 
00182   class ValuesMapSqr {
00183   public:
00185     forceinline int val(int n) const {
00186       return n*n;
00187     }
00188   };
00189 
00191   class ValuesMapSqrt {
00192   public:
00194     forceinline int val(int n) const {
00195       return static_cast<int>(floor(::sqrt(static_cast<double>(n))));
00196     }
00197   };
00198 
00199 
00200   /*
00201    * Positive domain consistent squaring
00202    *
00203    */
00204   template <class VA, class VB>
00205   forceinline
00206   SqrPlusDom<VA,VB>::SqrPlusDom(Space& home, VA x0, VB x1)
00207     : MixBinaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM>(home,x0,x1) {}
00208 
00209   template <class VA, class VB>
00210   forceinline ExecStatus
00211   SqrPlusDom<VA,VB>::post(Space& home, VA x0, VB x1) {
00212     GECODE_ES_CHECK(prop_sqr_plus_bnd(home,x0,x1));
00213     (void) new (home) SqrPlusDom<VA,VB>(home,x0,x1);
00214     return ES_OK;
00215   }
00216 
00217   template <class VA, class VB>
00218   forceinline
00219   SqrPlusDom<VA,VB>::SqrPlusDom(Space& home, bool share, SqrPlusDom<VA,VB>& p)
00220     : MixBinaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM>(home,share,p) {}
00221 
00222   template <class VA, class VB>
00223   Actor*
00224   SqrPlusDom<VA,VB>::copy(Space& home, bool share) {
00225     return new (home) SqrPlusDom<VA,VB>(home,share,*this);
00226   }
00227 
00228   template <class VA, class VB>
00229   PropCost
00230   SqrPlusDom<VA,VB>::cost(const Space&, const ModEventDelta& med) const {
00231     if (VA::me(med) == ME_INT_VAL)
00232       return PropCost::unary(PropCost::LO);
00233     else if (VA::me(med) == ME_INT_DOM)
00234       return PropCost::binary(PropCost::HI);
00235     else
00236       return PropCost::binary(PropCost::LO);
00237   }
00238 
00239   template <class VA, class VB>
00240   ExecStatus
00241   SqrPlusDom<VA,VB>::propagate(Space& home, const ModEventDelta& med) {
00242     if (VA::me(med) != ME_INT_DOM) {
00243       GECODE_ES_CHECK(prop_sqr_plus_bnd(home,x0,x1));
00244       return x0.assigned() ?
00245         ES_SUBSUMED(*this,sizeof(*this))
00246         : ES_NOFIX_PARTIAL(*this,VA::med(ME_INT_DOM));
00247     }
00248 
00249     {
00250       ViewValues<VA> v0(x0);
00251       Iter::Values::Map<ViewValues<VA>,ValuesMapSqr> s0(v0);
00252       GECODE_ME_CHECK(x1.inter_v(home,s0,false));
00253     }
00254 
00255     {
00256       ViewValues<VB> v1(x1);
00257       Iter::Values::Map<ViewValues<VB>,ValuesMapSqrt> s1(v1);
00258       GECODE_ME_CHECK(x0.inter_v(home,s1,false));
00259     }
00260 
00261     return x0.assigned() ? ES_SUBSUMED(*this,sizeof(*this)) : ES_FIX;
00262   }
00263 
00264 
00265   /*
00266    * Domain consistent squaring
00267    *
00268    */
00269 
00270   template <class View>
00271   forceinline
00272   SqrDom<View>::SqrDom(Space& home, View x0, View x1)
00273     : BinaryPropagator<View,PC_INT_DOM>(home,x0,x1) {}
00274 
00275   template <class View>
00276   forceinline ExecStatus
00277   SqrDom<View>::post(Space& home, View x0, View x1) {
00278     GECODE_ME_CHECK(x1.gq(home,0));
00279     if (same(x0,x1)) {
00280       GECODE_ME_CHECK(x1.lq(home,1));
00281     } else {
00282       GECODE_ME_CHECK(x0.lq(home,floor(::sqrt(static_cast<double>
00283                                               (Limits::max)))));
00284       GECODE_ME_CHECK(x0.gq(home,-floor(::sqrt(static_cast<double>
00285                                                (-Limits::min)))));
00286       if (x0.min() >= 0)
00287         return SqrPlusDom<IntView,IntView>::post(home,x0,x1);
00288       if (x0.max() <= 0)
00289         return SqrPlusDom<MinusView,IntView>::post(home,x0,x1);
00290       GECODE_ME_CHECK(x1.lq(home,
00291                             std::max(x0.min()*x0.min(),x0.max()*x0.max())));
00292       (void) new (home) SqrDom<View>(home,x0,x1);
00293     }
00294     return ES_OK;
00295   }
00296 
00297   template <class View>
00298   forceinline
00299   SqrDom<View>::SqrDom(Space& home, bool share, SqrDom<View>& p)
00300     : BinaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00301 
00302   template <class View>
00303   Actor*
00304   SqrDom<View>::copy(Space& home, bool share) {
00305     return new (home) SqrDom<View>(home,share,*this);
00306   }
00307 
00308   template <class View>
00309   PropCost
00310   SqrDom<View>::cost(const Space&, const ModEventDelta& med) const {
00311     if (View::me(med) == ME_INT_VAL)
00312       return PropCost::unary(PropCost::LO);
00313     else if (View::me(med) == ME_INT_DOM)
00314       return PropCost::binary(PropCost::HI);
00315     else
00316       return PropCost::binary(PropCost::LO);
00317   }
00318 
00319   template <class View>
00320   ExecStatus
00321   SqrDom<View>::propagate(Space& home, const ModEventDelta& med) {
00322     assert(x1.min() >= 0);
00323     if (View::me(med) != ME_INT_DOM) {
00324       if (x0.min() >= 0)
00325         GECODE_REWRITE(*this,(SqrPlusDom<IntView,IntView>::post(home,x0,x1)));
00326       if (x0.max() <= 0)
00327         GECODE_REWRITE(*this,(SqrPlusDom<MinusView,IntView>::post(home,x0,x1)));
00328 
00329       GECODE_ME_CHECK(x1.lq(home,std::max(x0.min()*x0.min(),
00330                                           x0.max()*x0.max())));
00331 
00332       int s = static_cast<int>(floor(::sqrt(static_cast<double>(x1.max()))));
00333 
00334       GECODE_ME_CHECK(x0.gq(home,-s));
00335       GECODE_ME_CHECK(x0.lq(home,s));
00336 
00337       if (x0.assigned() && x1.assigned())
00338         return (x0.val()*x0.val() == x1.val()) ?
00339           ES_SUBSUMED(*this,sizeof(*this)) : ES_FAILED;
00340       return ES_NOFIX_PARTIAL(*this,View::med(ME_INT_DOM));
00341 
00342     }
00343 
00344     {
00345       ViewValues<View> i(x0), j(x0);
00346       using namespace Iter::Values;
00347       Positive<ViewValues<View> > p(i);
00348       Negative<ViewValues<View> > n(j);
00349       Minus<Negative<ViewValues<View> > > m(n);
00350 
00351       Map<Positive<ViewValues<View> >,ValuesMapSqr,true> sp(p);
00352       Map<Minus<Negative<ViewValues<View> > >,ValuesMapSqr,true> sm(m);
00353       Union<Map<Positive<ViewValues<View> >,ValuesMapSqr,true>,
00354         Map<Minus<Negative<ViewValues<View> > >,ValuesMapSqr,true> > u(sp,sm);
00355       GECODE_ME_CHECK(x1.inter_v(home,u,false));
00356     }
00357 
00358     {
00359       ViewValues<View> i(x1), j(x1);
00360       using namespace Iter::Values;
00361       Map<ViewValues<View>,ValuesMapSqrt,true> si(i), sj(j);
00362       Minus<Map<ViewValues<View>,ValuesMapSqrt,true> > mi(si);
00363       Union<Minus<Map<ViewValues<View>,ValuesMapSqrt,true> >,
00364         Map<ViewValues<View>,ValuesMapSqrt,true> > u(mi,sj);
00365       GECODE_ME_CHECK(x0.inter_v(home,u,false));
00366     }
00367 
00368     return x0.assigned() ? ES_SUBSUMED(*this,sizeof(*this)) : ES_FIX;
00369   }
00370 
00371 }}}
00372 
00373 // STATISTICS: int-prop
00374