00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <cmath>
00039
00040 namespace Gecode { namespace Int { namespace Arithmetic {
00041
00042
00043
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
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
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
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
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
00464