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 y = result(home,ret,x);
00204 else {
00205 y = result(home,ret);
00206 pow(home, x, aInt, y);
00207 }
00208 }
00209 break;
00210 case ANLFE_NROOT:
00211 {
00212 assert(n == 1);
00213 FloatVar x = a[0].post(home);
00214 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)))
00215 y = result(home,ret,x);
00216 else {
00217 y = result(home,ret);
00218 nroot(home, x, aInt, y);
00219 }
00220 }
00221 break;
00222 #ifdef GECODE_HAS_MPFR
00223 case ANLFE_EXP:
00224 {
00225 assert(n == 1);
00226 FloatVar x = a[0].post(home);
00227 if (x.assigned() && (x.val() == 0.0))
00228 y = result(home,ret,x);
00229 else {
00230 y = result(home,ret);
00231 exp(home, x, y);
00232 }
00233 }
00234 break;
00235 case ANLFE_LOG:
00236 {
00237 assert(n == 1);
00238 FloatVar x = a[0].post(home);
00239 y = result(home,ret);
00240 log(home, x, y);
00241 }
00242 break;
00243 case ANLFE_ASIN:
00244 {
00245 assert(n == 1);
00246 FloatVar x = a[0].post(home);
00247 y = result(home,ret);
00248 asin(home, x, y);
00249 }
00250 break;
00251 case ANLFE_SIN:
00252 {
00253 assert(n == 1);
00254 FloatVar x = a[0].post(home);
00255 y = result(home,ret);
00256 sin(home, x, y);
00257 }
00258 break;
00259 case ANLFE_ACOS:
00260 {
00261 assert(n == 1);
00262 FloatVar x = a[0].post(home);
00263 y = result(home,ret);
00264 acos(home, x, y);
00265 }
00266 break;
00267 case ANLFE_COS:
00268 {
00269 assert(n == 1);
00270 FloatVar x = a[0].post(home);
00271 y = result(home,ret);
00272 cos(home, x, y);
00273 }
00274 break;
00275 case ANLFE_ATAN:
00276 {
00277 assert(n == 1);
00278 FloatVar x = a[0].post(home);
00279 y = result(home,ret);
00280 atan(home, x, y);
00281 }
00282 break;
00283 case ANLFE_TAN:
00284 {
00285 assert(n == 1);
00286 FloatVar x = a[0].post(home);
00287 y = result(home,ret);
00288 tan(home, x, y);
00289 }
00290 break;
00291 #endif
00292 default:
00293 GECODE_NEVER;
00294 }
00295 return y;
00296 }
00297 virtual void post(Home home, FloatRelType frt, FloatVal c) const {
00298 if ((t == ANLFE_MIN && frt == FRT_GQ) ||
00299 (t == ANLFE_MAX && frt == FRT_LQ)) {
00300 FloatVarArgs x(n);
00301 for (int i=n; i--;)
00302 x[i] = a[i].post(home);
00303 rel(home, x, frt, c);
00304 } else {
00305 rel(home, post(home,NULL), frt, c);
00306 }
00307 }
00308 virtual void post(Home home, FloatRelType frt, FloatVal c,
00309 BoolVar b) const {
00310 rel(home, post(home,NULL), frt, c, b);
00311 }
00312 };
00314 bool hasType(const LinFloatExpr& e, ArithNonLinFloatExpr::ArithNonLinFloatExprType t) {
00315 return e.nlfe() &&
00316 dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe()) != NULL &&
00317 dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe())->t == t;
00318 }
00319
00320 }}
00321
00322 namespace Gecode {
00323
00324 LinFloatExpr
00325 abs(const LinFloatExpr& e) {
00326 using namespace MiniModel;
00327 if (hasType(e, ArithNonLinFloatExpr::ANLFE_ABS))
00328 return e;
00329 ArithNonLinFloatExpr* ae =
00330 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ABS,1);
00331 ae->a[0] = e;
00332 return LinFloatExpr(ae);
00333 }
00334
00335 LinFloatExpr
00336 min(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00337 using namespace MiniModel;
00338 int n = 0;
00339 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN))
00340 n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00341 else
00342 n += 1;
00343 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN))
00344 n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00345 else
00346 n += 1;
00347 ArithNonLinFloatExpr* ae =
00348 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,n);
00349 int i=0;
00350 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN)) {
00351 ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00352 for (; i<e0e->n; i++)
00353 ae->a[i] = e0e->a[i];
00354 } else {
00355 ae->a[i++] = e0;
00356 }
00357 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN)) {
00358 ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00359 int curN = i;
00360 for (; i<curN+e1e->n; i++)
00361 ae->a[i] = e1e->a[i-curN];
00362 } else {
00363 ae->a[i++] = e1;
00364 }
00365 return LinFloatExpr(ae);
00366 }
00367
00368 LinFloatExpr
00369 min(const FloatVarArgs& x) {
00370 using namespace MiniModel;
00371 ArithNonLinFloatExpr* ae =
00372 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,x.size());
00373 for (int i=x.size(); i--;)
00374 ae->a[i] = x[i];
00375 return LinFloatExpr(ae);
00376 }
00377
00378 LinFloatExpr
00379 max(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00380 using namespace MiniModel;
00381 int n = 0;
00382 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX))
00383 n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00384 else
00385 n += 1;
00386 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX))
00387 n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00388 else
00389 n += 1;
00390 ArithNonLinFloatExpr* ae =
00391 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,n);
00392 int i=0;
00393 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX)) {
00394 ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00395 for (; i<e0e->n; i++)
00396 ae->a[i] = e0e->a[i];
00397 } else {
00398 ae->a[i++] = e0;
00399 }
00400 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX)) {
00401 ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00402 int curN = i;
00403 for (; i<curN+e1e->n; i++)
00404 ae->a[i] = e1e->a[i-curN];
00405 } else {
00406 ae->a[i++] = e1;
00407 }
00408 return LinFloatExpr(ae);
00409 }
00410
00411 LinFloatExpr
00412 max(const FloatVarArgs& x) {
00413 using namespace MiniModel;
00414 ArithNonLinFloatExpr* ae =
00415 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,x.size());
00416 for (int i=x.size(); i--;)
00417 ae->a[i] = x[i];
00418 return LinFloatExpr(ae);
00419 }
00420
00421 LinFloatExpr
00422 operator *(const FloatVar& e0, const FloatVar& e1) {
00423 using namespace MiniModel;
00424 ArithNonLinFloatExpr* ae =
00425 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00426 ae->a[0] = e0;
00427 ae->a[1] = e1;
00428 return LinFloatExpr(ae);
00429 }
00430
00431 LinFloatExpr
00432 operator *(const LinFloatExpr& e0, const FloatVar& e1) {
00433 using namespace MiniModel;
00434 ArithNonLinFloatExpr* ae =
00435 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00436 ae->a[0] = e0;
00437 ae->a[1] = e1;
00438 return LinFloatExpr(ae);
00439 }
00440
00441 LinFloatExpr
00442 operator *(const FloatVar& e0, const LinFloatExpr& e1) {
00443 using namespace MiniModel;
00444 ArithNonLinFloatExpr* ae =
00445 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00446 ae->a[0] = e0;
00447 ae->a[1] = e1;
00448 return LinFloatExpr(ae);
00449 }
00450
00451 LinFloatExpr
00452 operator *(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00453 using namespace MiniModel;
00454 ArithNonLinFloatExpr* ae =
00455 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00456 ae->a[0] = e0;
00457 ae->a[1] = e1;
00458 return LinFloatExpr(ae);
00459 }
00460
00461 LinFloatExpr
00462 operator /(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00463 using namespace MiniModel;
00464 ArithNonLinFloatExpr* ae =
00465 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_DIV,2);
00466 ae->a[0] = e0;
00467 ae->a[1] = e1;
00468 return LinFloatExpr(ae);
00469 }
00470
00471 LinFloatExpr
00472 sqr(const LinFloatExpr& e) {
00473 using namespace MiniModel;
00474 ArithNonLinFloatExpr* ae =
00475 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQR,1);
00476 ae->a[0] = e;
00477 return LinFloatExpr(ae);
00478 }
00479
00480 LinFloatExpr
00481 sqrt(const LinFloatExpr& e) {
00482 using namespace MiniModel;
00483 ArithNonLinFloatExpr* ae =
00484 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQRT,1);
00485 ae->a[0] = e;
00486 return LinFloatExpr(ae);
00487 }
00488
00489 LinFloatExpr
00490 pow(const LinFloatExpr& e, int exp) {
00491 using namespace MiniModel;
00492 ArithNonLinFloatExpr* ae =
00493 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_POW,1,exp);
00494 ae->a[0] = e;
00495 return LinFloatExpr(ae);
00496 }
00497
00498 LinFloatExpr
00499 nroot(const LinFloatExpr& e, int exp) {
00500 using namespace MiniModel;
00501 ArithNonLinFloatExpr* ae =
00502 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_NROOT,1,exp);
00503 ae->a[0] = e;
00504 return LinFloatExpr(ae);
00505 }
00506
00507 #ifdef GECODE_HAS_MPFR
00508
00509 LinFloatExpr
00510 exp(const LinFloatExpr& e) {
00511 using namespace MiniModel;
00512 ArithNonLinFloatExpr* ae =
00513 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_EXP,1);
00514 ae->a[0] = e;
00515 return LinFloatExpr(ae);
00516 }
00517
00518 LinFloatExpr
00519 log(const LinFloatExpr& e) {
00520 using namespace MiniModel;
00521 ArithNonLinFloatExpr* ae =
00522 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_LOG,1);
00523 ae->a[0] = e;
00524 return LinFloatExpr(ae);
00525 }
00526
00527 LinFloatExpr
00528 asin(const LinFloatExpr& e) {
00529 using namespace MiniModel;
00530 ArithNonLinFloatExpr* ae =
00531 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ASIN,1);
00532 ae->a[0] = e;
00533 return LinFloatExpr(ae);
00534 }
00535
00536 LinFloatExpr
00537 sin(const LinFloatExpr& e) {
00538 using namespace MiniModel;
00539 ArithNonLinFloatExpr* ae =
00540 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SIN,1);
00541 ae->a[0] = e;
00542 return LinFloatExpr(ae);
00543 }
00544
00545 LinFloatExpr
00546 acos(const LinFloatExpr& e) {
00547 using namespace MiniModel;
00548 ArithNonLinFloatExpr* ae =
00549 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ACOS,1);
00550 ae->a[0] = e;
00551 return LinFloatExpr(ae);
00552 }
00553
00554 LinFloatExpr
00555 cos(const LinFloatExpr& e) {
00556 using namespace MiniModel;
00557 ArithNonLinFloatExpr* ae =
00558 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_COS,1);
00559 ae->a[0] = e;
00560 return LinFloatExpr(ae);
00561 }
00562
00563 LinFloatExpr
00564 atan(const LinFloatExpr& e) {
00565 using namespace MiniModel;
00566 ArithNonLinFloatExpr* ae =
00567 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ATAN,1);
00568 ae->a[0] = e;
00569 return LinFloatExpr(ae);
00570 }
00571
00572 LinFloatExpr
00573 tan(const LinFloatExpr& e) {
00574 using namespace MiniModel;
00575 ArithNonLinFloatExpr* ae =
00576 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_TAN,1);
00577 ae->a[0] = e;
00578 return LinFloatExpr(ae);
00579 }
00580
00581 #endif
00582
00583 }
00584
00585 #endif
00586
00587