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 #include <gecode/minimodel.hh>
00037
00038 #ifdef GECODE_HAS_FLOAT_VARS
00039
00040 namespace Gecode { namespace MiniModel {
00041
00043 class GECODE_MINIMODEL_EXPORT ArithNonLinFloatExpr :
00044 public NonLinFloatExpr {
00045 public:
00047 enum ArithNonLinFloatExprType {
00048 ANLFE_ABS,
00049 ANLFE_MIN,
00050 ANLFE_MAX,
00051 ANLFE_MULT,
00052 ANLFE_DIV,
00053 ANLFE_SQR,
00054 ANLFE_SQRT,
00055 #ifdef GECODE_HAS_MPFR
00056 ANLFE_EXP,
00057 ANLFE_LOG,
00058 ANLFE_ASIN,
00059 ANLFE_SIN,
00060 ANLFE_ACOS,
00061 ANLFE_COS,
00062 ANLFE_ATAN,
00063 ANLFE_TAN,
00064 #endif
00065 ANLFE_POW,
00066 ANLFE_NROOT
00067 } t;
00069 LinFloatExpr* a;
00071 int n;
00073 int aInt;
00075 ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0)
00076 : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(-1) {}
00077 ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0, int a0)
00078 : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(a0) {}
00080 ~ArithNonLinFloatExpr(void) { heap.free<LinFloatExpr>(a,n); }
00082 virtual FloatVar post(Home home, FloatVar* ret) const {
00083 FloatVar y;
00084 switch (t) {
00085 case ANLFE_ABS:
00086 {
00087 FloatVar x = a[0].post(home);
00088 if (x.min() >= 0)
00089 y = result(home,ret,x);
00090 else {
00091 y = result(home,ret);
00092 abs(home, x, y);
00093 }
00094 }
00095 break;
00096 case ANLFE_MIN:
00097 if (n==1) {
00098 y = result(home,ret, a[0].post(home));
00099 } else if (n==2) {
00100 FloatVar x0 = a[0].post(home);
00101 FloatVar x1 = a[1].post(home);
00102 if (x0.max() <= x1.min())
00103 y = result(home,ret,x0);
00104 else if (x1.max() <= x0.min())
00105 y = result(home,ret,x1);
00106 else {
00107 y = result(home,ret);
00108 min(home, x0, x1, y);
00109 }
00110 } else {
00111 FloatVarArgs x(n);
00112 for (int i=n; i--;)
00113 x[i] = a[i].post(home);
00114 y = result(home,ret);
00115 min(home, x, y);
00116 }
00117 break;
00118 case ANLFE_MAX:
00119 if (n==1) {
00120 y = result(home,ret,a[0].post(home));
00121 } else if (n==2) {
00122 FloatVar x0 = a[0].post(home);
00123 FloatVar x1 = a[1].post(home);
00124 if (x0.max() <= x1.min())
00125 y = result(home,ret,x1);
00126 else if (x1.max() <= x0.min())
00127 y = result(home,ret,x0);
00128 else {
00129 y = result(home,ret);
00130 max(home, x0, x1, y);
00131 }
00132 } else {
00133 FloatVarArgs x(n);
00134 for (int i=n; i--;)
00135 x[i] = a[i].post(home);
00136 y = result(home,ret);
00137 max(home, x, y);
00138 }
00139 break;
00140 case ANLFE_MULT:
00141 {
00142 assert(n == 2);
00143 FloatVar x0 = a[0].post(home);
00144 FloatVar x1 = a[1].post(home);
00145 if (x0.assigned() && (x0.val() == 0.0))
00146 y = result(home,ret,x0);
00147 else if (x0.assigned() && (x0.val() == 1.0))
00148 y = result(home,ret,x1);
00149 else if (x1.assigned() && (x1.val() == 0.0))
00150 y = result(home,ret,x1);
00151 else if (x1.assigned() && (x1.val() == 1.0))
00152 y = result(home,ret,x0);
00153 else {
00154 y = result(home,ret);
00155 mult(home, x0, x1, y);
00156 }
00157 }
00158 break;
00159 case ANLFE_DIV:
00160 {
00161 assert(n == 2);
00162 FloatVar x0 = a[0].post(home);
00163 FloatVar x1 = a[1].post(home);
00164 if (x1.assigned() && (x1.val() == 1.0))
00165 y = result(home,ret,x0);
00166 else if (x0.assigned() && (x0.val() == 0.0))
00167 y = result(home,ret,x0);
00168 else {
00169 y = result(home,ret);
00170 div(home, x0, x1, y);
00171 }
00172 }
00173 break;
00174 case ANLFE_SQR:
00175 {
00176 assert(n == 1);
00177 FloatVar x = a[0].post(home);
00178 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)))
00179 y = x;
00180 else {
00181 y = result(home,ret);
00182 sqr(home, x, y);
00183 }
00184 }
00185 break;
00186 case ANLFE_SQRT:
00187 {
00188 assert(n == 1);
00189 FloatVar x = a[0].post(home);
00190 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)))
00191 y = result(home,ret,x);
00192 else {
00193 y = result(home,ret);
00194 sqrt(home, x, y);
00195 }
00196 }
00197 break;
00198 case ANLFE_POW:
00199 {
00200 assert(n == 1);
00201 FloatVar x = a[0].post(home);
00202 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)) &&
00203 (aInt >= 0))
00204 y = result(home,ret,x);
00205 else {
00206 y = result(home,ret);
00207 pow(home, x, aInt, y);
00208 }
00209 }
00210 break;
00211 case ANLFE_NROOT:
00212 {
00213 assert(n == 1);
00214 FloatVar x = a[0].post(home);
00215 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)) &&
00216 (aInt >= 0))
00217 y = result(home,ret,x);
00218 else {
00219 y = result(home,ret);
00220 nroot(home, x, aInt, y);
00221 }
00222 }
00223 break;
00224 #ifdef GECODE_HAS_MPFR
00225 case ANLFE_EXP:
00226 {
00227 assert(n == 1);
00228 FloatVar x = a[0].post(home);
00229 if (x.assigned() && (x.val() == 0.0)) {
00230 FloatVar one(home,1.0,1.0);
00231 y = result(home,ret,one);
00232 } else {
00233 y = result(home,ret);
00234 exp(home, x, y);
00235 }
00236 }
00237 break;
00238 case ANLFE_LOG:
00239 {
00240 assert(n == 1);
00241 FloatVar x = a[0].post(home);
00242 y = result(home,ret);
00243 log(home, x, y);
00244 }
00245 break;
00246 case ANLFE_ASIN:
00247 {
00248 assert(n == 1);
00249 FloatVar x = a[0].post(home);
00250 y = result(home,ret);
00251 asin(home, x, y);
00252 }
00253 break;
00254 case ANLFE_SIN:
00255 {
00256 assert(n == 1);
00257 FloatVar x = a[0].post(home);
00258 y = result(home,ret);
00259 sin(home, x, y);
00260 }
00261 break;
00262 case ANLFE_ACOS:
00263 {
00264 assert(n == 1);
00265 FloatVar x = a[0].post(home);
00266 y = result(home,ret);
00267 acos(home, x, y);
00268 }
00269 break;
00270 case ANLFE_COS:
00271 {
00272 assert(n == 1);
00273 FloatVar x = a[0].post(home);
00274 y = result(home,ret);
00275 cos(home, x, y);
00276 }
00277 break;
00278 case ANLFE_ATAN:
00279 {
00280 assert(n == 1);
00281 FloatVar x = a[0].post(home);
00282 y = result(home,ret);
00283 atan(home, x, y);
00284 }
00285 break;
00286 case ANLFE_TAN:
00287 {
00288 assert(n == 1);
00289 FloatVar x = a[0].post(home);
00290 y = result(home,ret);
00291 tan(home, x, y);
00292 }
00293 break;
00294 #endif
00295 default:
00296 GECODE_NEVER;
00297 }
00298 return y;
00299 }
00300 virtual void post(Home home, FloatRelType frt, FloatVal c) const {
00301 if ((t == ANLFE_MIN && frt == FRT_GQ) ||
00302 (t == ANLFE_MAX && frt == FRT_LQ)) {
00303 FloatVarArgs x(n);
00304 for (int i=n; i--;)
00305 x[i] = a[i].post(home);
00306 rel(home, x, frt, c);
00307 } else {
00308 rel(home, post(home,nullptr), frt, c);
00309 }
00310 }
00311 virtual void post(Home home, FloatRelType frt, FloatVal c,
00312 BoolVar b) const {
00313 rel(home, post(home,nullptr), frt, c, b);
00314 }
00315 };
00317 bool hasType(const LinFloatExpr& e, ArithNonLinFloatExpr::ArithNonLinFloatExprType t) {
00318 return e.nlfe() &&
00319 dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe()) != nullptr &&
00320 dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe())->t == t;
00321 }
00322
00323 }}
00324
00325 namespace Gecode {
00326
00327 LinFloatExpr
00328 abs(const LinFloatExpr& e) {
00329 using namespace MiniModel;
00330 if (hasType(e, ArithNonLinFloatExpr::ANLFE_ABS))
00331 return e;
00332 ArithNonLinFloatExpr* ae =
00333 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ABS,1);
00334 ae->a[0] = e;
00335 return LinFloatExpr(ae);
00336 }
00337
00338 LinFloatExpr
00339 min(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00340 using namespace MiniModel;
00341 int n = 0;
00342 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN))
00343 n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00344 else
00345 n += 1;
00346 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN))
00347 n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00348 else
00349 n += 1;
00350 ArithNonLinFloatExpr* ae =
00351 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,n);
00352 int i=0;
00353 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN)) {
00354 ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00355 for (; i<e0e->n; i++)
00356 ae->a[i] = e0e->a[i];
00357 } else {
00358 ae->a[i++] = e0;
00359 }
00360 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN)) {
00361 ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00362 int curN = i;
00363 for (; i<curN+e1e->n; i++)
00364 ae->a[i] = e1e->a[i-curN];
00365 } else {
00366 ae->a[i++] = e1;
00367 }
00368 return LinFloatExpr(ae);
00369 }
00370
00371 LinFloatExpr
00372 min(const FloatVarArgs& x) {
00373 using namespace MiniModel;
00374 ArithNonLinFloatExpr* ae =
00375 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,x.size());
00376 for (int i=x.size(); i--;)
00377 ae->a[i] = x[i];
00378 return LinFloatExpr(ae);
00379 }
00380
00381 LinFloatExpr
00382 max(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00383 using namespace MiniModel;
00384 int n = 0;
00385 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX))
00386 n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00387 else
00388 n += 1;
00389 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX))
00390 n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00391 else
00392 n += 1;
00393 ArithNonLinFloatExpr* ae =
00394 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,n);
00395 int i=0;
00396 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX)) {
00397 ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00398 for (; i<e0e->n; i++)
00399 ae->a[i] = e0e->a[i];
00400 } else {
00401 ae->a[i++] = e0;
00402 }
00403 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX)) {
00404 ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00405 int curN = i;
00406 for (; i<curN+e1e->n; i++)
00407 ae->a[i] = e1e->a[i-curN];
00408 } else {
00409 ae->a[i++] = e1;
00410 }
00411 return LinFloatExpr(ae);
00412 }
00413
00414 LinFloatExpr
00415 max(const FloatVarArgs& x) {
00416 using namespace MiniModel;
00417 ArithNonLinFloatExpr* ae =
00418 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,x.size());
00419 for (int i=x.size(); i--;)
00420 ae->a[i] = x[i];
00421 return LinFloatExpr(ae);
00422 }
00423
00424 LinFloatExpr
00425 operator *(const FloatVar& e0, const FloatVar& e1) {
00426 using namespace MiniModel;
00427 ArithNonLinFloatExpr* ae =
00428 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00429 ae->a[0] = e0;
00430 ae->a[1] = e1;
00431 return LinFloatExpr(ae);
00432 }
00433
00434 LinFloatExpr
00435 operator *(const LinFloatExpr& e0, const FloatVar& e1) {
00436 using namespace MiniModel;
00437 ArithNonLinFloatExpr* ae =
00438 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00439 ae->a[0] = e0;
00440 ae->a[1] = e1;
00441 return LinFloatExpr(ae);
00442 }
00443
00444 LinFloatExpr
00445 operator *(const FloatVar& e0, const LinFloatExpr& e1) {
00446 using namespace MiniModel;
00447 ArithNonLinFloatExpr* ae =
00448 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00449 ae->a[0] = e0;
00450 ae->a[1] = e1;
00451 return LinFloatExpr(ae);
00452 }
00453
00454 LinFloatExpr
00455 operator *(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00456 using namespace MiniModel;
00457 ArithNonLinFloatExpr* ae =
00458 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00459 ae->a[0] = e0;
00460 ae->a[1] = e1;
00461 return LinFloatExpr(ae);
00462 }
00463
00464 LinFloatExpr
00465 operator /(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00466 using namespace MiniModel;
00467 ArithNonLinFloatExpr* ae =
00468 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_DIV,2);
00469 ae->a[0] = e0;
00470 ae->a[1] = e1;
00471 return LinFloatExpr(ae);
00472 }
00473
00474 LinFloatExpr
00475 sqr(const LinFloatExpr& e) {
00476 using namespace MiniModel;
00477 ArithNonLinFloatExpr* ae =
00478 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQR,1);
00479 ae->a[0] = e;
00480 return LinFloatExpr(ae);
00481 }
00482
00483 LinFloatExpr
00484 sqrt(const LinFloatExpr& e) {
00485 using namespace MiniModel;
00486 ArithNonLinFloatExpr* ae =
00487 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQRT,1);
00488 ae->a[0] = e;
00489 return LinFloatExpr(ae);
00490 }
00491
00492 LinFloatExpr
00493 pow(const LinFloatExpr& e, int exp) {
00494 using namespace MiniModel;
00495 ArithNonLinFloatExpr* ae =
00496 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_POW,1,exp);
00497 ae->a[0] = e;
00498 return LinFloatExpr(ae);
00499 }
00500
00501 LinFloatExpr
00502 nroot(const LinFloatExpr& e, int exp) {
00503 using namespace MiniModel;
00504 ArithNonLinFloatExpr* ae =
00505 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_NROOT,1,exp);
00506 ae->a[0] = e;
00507 return LinFloatExpr(ae);
00508 }
00509
00510 #ifdef GECODE_HAS_MPFR
00511
00512 LinFloatExpr
00513 exp(const LinFloatExpr& e) {
00514 using namespace MiniModel;
00515 ArithNonLinFloatExpr* ae =
00516 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_EXP,1);
00517 ae->a[0] = e;
00518 return LinFloatExpr(ae);
00519 }
00520
00521 LinFloatExpr
00522 log(const LinFloatExpr& e) {
00523 using namespace MiniModel;
00524 ArithNonLinFloatExpr* ae =
00525 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_LOG,1);
00526 ae->a[0] = e;
00527 return LinFloatExpr(ae);
00528 }
00529
00530 LinFloatExpr
00531 asin(const LinFloatExpr& e) {
00532 using namespace MiniModel;
00533 ArithNonLinFloatExpr* ae =
00534 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ASIN,1);
00535 ae->a[0] = e;
00536 return LinFloatExpr(ae);
00537 }
00538
00539 LinFloatExpr
00540 sin(const LinFloatExpr& e) {
00541 using namespace MiniModel;
00542 ArithNonLinFloatExpr* ae =
00543 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SIN,1);
00544 ae->a[0] = e;
00545 return LinFloatExpr(ae);
00546 }
00547
00548 LinFloatExpr
00549 acos(const LinFloatExpr& e) {
00550 using namespace MiniModel;
00551 ArithNonLinFloatExpr* ae =
00552 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ACOS,1);
00553 ae->a[0] = e;
00554 return LinFloatExpr(ae);
00555 }
00556
00557 LinFloatExpr
00558 cos(const LinFloatExpr& e) {
00559 using namespace MiniModel;
00560 ArithNonLinFloatExpr* ae =
00561 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_COS,1);
00562 ae->a[0] = e;
00563 return LinFloatExpr(ae);
00564 }
00565
00566 LinFloatExpr
00567 atan(const LinFloatExpr& e) {
00568 using namespace MiniModel;
00569 ArithNonLinFloatExpr* ae =
00570 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ATAN,1);
00571 ae->a[0] = e;
00572 return LinFloatExpr(ae);
00573 }
00574
00575 LinFloatExpr
00576 tan(const LinFloatExpr& e) {
00577 using namespace MiniModel;
00578 ArithNonLinFloatExpr* ae =
00579 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_TAN,1);
00580 ae->a[0] = e;
00581 return LinFloatExpr(ae);
00582 }
00583
00584 #endif
00585
00586 }
00587
00588 #endif
00589
00590