this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * Vincent Barichard <Vincent.Barichard@univ-angers.fr> 6 * 7 * Copyright: 8 * Christian Schulte, 2006 9 * Vincent Barichard, 2012 10 * 11 * This file is part of Gecode, the generic constraint 12 * development environment: 13 * http://www.gecode.org 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining 16 * a copy of this software and associated documentation files (the 17 * "Software"), to deal in the Software without restriction, including 18 * without limitation the rights to use, copy, modify, merge, publish, 19 * distribute, sublicense, and/or sell copies of the Software, and to 20 * permit persons to whom the Software is furnished to do so, subject to 21 * the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 * 34 */ 35 36#include <gecode/minimodel.hh> 37 38#ifdef GECODE_HAS_FLOAT_VARS 39 40namespace Gecode { namespace MiniModel { 41 42 /// Non-linear float arithmetic expressions 43 class GECODE_MINIMODEL_EXPORT ArithNonLinFloatExpr : 44 public NonLinFloatExpr { 45 public: 46 /// The expression type 47 enum ArithNonLinFloatExprType { 48 ANLFE_ABS, ///< Absolute value expression 49 ANLFE_MIN, ///< Minimum expression 50 ANLFE_MAX, ///< Maximum expression 51 ANLFE_MULT, ///< Multiplication expression 52 ANLFE_DIV, ///< Division expression 53 ANLFE_SQR, ///< Square expression 54 ANLFE_SQRT, ///< Square root expression 55#ifdef GECODE_HAS_MPFR 56 ANLFE_EXP, ///< Exponential expression 57 ANLFE_LOG, ///< Logarithm root expression 58 ANLFE_ASIN, ///< expression 59 ANLFE_SIN, ///< expression 60 ANLFE_ACOS, ///< expression 61 ANLFE_COS, ///< expression 62 ANLFE_ATAN, ///< expression 63 ANLFE_TAN, ///< expression 64#endif 65 ANLFE_POW, ///< Pow expression 66 ANLFE_NROOT ///< Nth root expression 67 } t; 68 /// Expressions 69 LinFloatExpr* a; 70 /// Size of variable array 71 int n; 72 /// Integer argument (used in nroot for example) 73 int aInt; 74 /// Constructors 75 ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0) 76 : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(-1) {} 77 ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0, int a0) 78 : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(a0) {} 79 /// Destructor 80 ~ArithNonLinFloatExpr(void) { heap.free<LinFloatExpr>(a,n); } 81 /// Post expression 82 virtual FloatVar post(Home home, FloatVar* ret) const { 83 FloatVar y; 84 switch (t) { 85 case ANLFE_ABS: 86 { 87 FloatVar x = a[0].post(home); 88 if (x.min() >= 0) 89 y = result(home,ret,x); 90 else { 91 y = result(home,ret); 92 abs(home, x, y); 93 } 94 } 95 break; 96 case ANLFE_MIN: 97 if (n==1) { 98 y = result(home,ret, a[0].post(home)); 99 } else if (n==2) { 100 FloatVar x0 = a[0].post(home); 101 FloatVar x1 = a[1].post(home); 102 if (x0.max() <= x1.min()) 103 y = result(home,ret,x0); 104 else if (x1.max() <= x0.min()) 105 y = result(home,ret,x1); 106 else { 107 y = result(home,ret); 108 min(home, x0, x1, y); 109 } 110 } else { 111 FloatVarArgs x(n); 112 for (int i=n; i--;) 113 x[i] = a[i].post(home); 114 y = result(home,ret); 115 min(home, x, y); 116 } 117 break; 118 case ANLFE_MAX: 119 if (n==1) { 120 y = result(home,ret,a[0].post(home)); 121 } else if (n==2) { 122 FloatVar x0 = a[0].post(home); 123 FloatVar x1 = a[1].post(home); 124 if (x0.max() <= x1.min()) 125 y = result(home,ret,x1); 126 else if (x1.max() <= x0.min()) 127 y = result(home,ret,x0); 128 else { 129 y = result(home,ret); 130 max(home, x0, x1, y); 131 } 132 } else { 133 FloatVarArgs x(n); 134 for (int i=n; i--;) 135 x[i] = a[i].post(home); 136 y = result(home,ret); 137 max(home, x, y); 138 } 139 break; 140 case ANLFE_MULT: 141 { 142 assert(n == 2); 143 FloatVar x0 = a[0].post(home); 144 FloatVar x1 = a[1].post(home); 145 if (x0.assigned() && (x0.val() == 0.0)) 146 y = result(home,ret,x0); 147 else if (x0.assigned() && (x0.val() == 1.0)) 148 y = result(home,ret,x1); 149 else if (x1.assigned() && (x1.val() == 0.0)) 150 y = result(home,ret,x1); 151 else if (x1.assigned() && (x1.val() == 1.0)) 152 y = result(home,ret,x0); 153 else { 154 y = result(home,ret); 155 mult(home, x0, x1, y); 156 } 157 } 158 break; 159 case ANLFE_DIV: 160 { 161 assert(n == 2); 162 FloatVar x0 = a[0].post(home); 163 FloatVar x1 = a[1].post(home); 164 if (x1.assigned() && (x1.val() == 1.0)) 165 y = result(home,ret,x0); 166 else if (x0.assigned() && (x0.val() == 0.0)) 167 y = result(home,ret,x0); 168 else { 169 y = result(home,ret); 170 div(home, x0, x1, y); 171 } 172 } 173 break; 174 case ANLFE_SQR: 175 { 176 assert(n == 1); 177 FloatVar x = a[0].post(home); 178 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0))) 179 y = x; 180 else { 181 y = result(home,ret); 182 sqr(home, x, y); 183 } 184 } 185 break; 186 case ANLFE_SQRT: 187 { 188 assert(n == 1); 189 FloatVar x = a[0].post(home); 190 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0))) 191 y = result(home,ret,x); 192 else { 193 y = result(home,ret); 194 sqrt(home, x, y); 195 } 196 } 197 break; 198 case ANLFE_POW: 199 { 200 assert(n == 1); 201 FloatVar x = a[0].post(home); 202 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)) && 203 (aInt >= 0)) 204 y = result(home,ret,x); 205 else { 206 y = result(home,ret); 207 pow(home, x, aInt, y); 208 } 209 } 210 break; 211 case ANLFE_NROOT: 212 { 213 assert(n == 1); 214 FloatVar x = a[0].post(home); 215 if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)) && 216 (aInt >= 0)) 217 y = result(home,ret,x); 218 else { 219 y = result(home,ret); 220 nroot(home, x, aInt, y); 221 } 222 } 223 break; 224#ifdef GECODE_HAS_MPFR 225 case ANLFE_EXP: 226 { 227 assert(n == 1); 228 FloatVar x = a[0].post(home); 229 if (x.assigned() && (x.val() == 0.0)) { 230 FloatVar one(home,1.0,1.0); 231 y = result(home,ret,one); 232 } else { 233 y = result(home,ret); 234 exp(home, x, y); 235 } 236 } 237 break; 238 case ANLFE_LOG: 239 { 240 assert(n == 1); 241 FloatVar x = a[0].post(home); 242 y = result(home,ret); 243 log(home, x, y); 244 } 245 break; 246 case ANLFE_ASIN: 247 { 248 assert(n == 1); 249 FloatVar x = a[0].post(home); 250 y = result(home,ret); 251 asin(home, x, y); 252 } 253 break; 254 case ANLFE_SIN: 255 { 256 assert(n == 1); 257 FloatVar x = a[0].post(home); 258 y = result(home,ret); 259 sin(home, x, y); 260 } 261 break; 262 case ANLFE_ACOS: 263 { 264 assert(n == 1); 265 FloatVar x = a[0].post(home); 266 y = result(home,ret); 267 acos(home, x, y); 268 } 269 break; 270 case ANLFE_COS: 271 { 272 assert(n == 1); 273 FloatVar x = a[0].post(home); 274 y = result(home,ret); 275 cos(home, x, y); 276 } 277 break; 278 case ANLFE_ATAN: 279 { 280 assert(n == 1); 281 FloatVar x = a[0].post(home); 282 y = result(home,ret); 283 atan(home, x, y); 284 } 285 break; 286 case ANLFE_TAN: 287 { 288 assert(n == 1); 289 FloatVar x = a[0].post(home); 290 y = result(home,ret); 291 tan(home, x, y); 292 } 293 break; 294#endif 295 default: 296 GECODE_NEVER; 297 } 298 return y; 299 } 300 virtual void post(Home home, FloatRelType frt, FloatVal c) const { 301 if ((t == ANLFE_MIN && frt == FRT_GQ) || 302 (t == ANLFE_MAX && frt == FRT_LQ)) { 303 FloatVarArgs x(n); 304 for (int i=n; i--;) 305 x[i] = a[i].post(home); 306 rel(home, x, frt, c); 307 } else { 308 rel(home, post(home,nullptr), frt, c); 309 } 310 } 311 virtual void post(Home home, FloatRelType frt, FloatVal c, 312 BoolVar b) const { 313 rel(home, post(home,nullptr), frt, c, b); 314 } 315 }; 316 /// Check if \a e is of type \a t 317 bool hasType(const LinFloatExpr& e, ArithNonLinFloatExpr::ArithNonLinFloatExprType t) { 318 return e.nlfe() && 319 dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe()) != nullptr && 320 dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe())->t == t; 321 } 322 323}} 324 325namespace Gecode { 326 327 LinFloatExpr 328 abs(const LinFloatExpr& e) { 329 using namespace MiniModel; 330 if (hasType(e, ArithNonLinFloatExpr::ANLFE_ABS)) 331 return e; 332 ArithNonLinFloatExpr* ae = 333 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ABS,1); 334 ae->a[0] = e; 335 return LinFloatExpr(ae); 336 } 337 338 LinFloatExpr 339 min(const LinFloatExpr& e0, const LinFloatExpr& e1) { 340 using namespace MiniModel; 341 int n = 0; 342 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN)) 343 n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n; 344 else 345 n += 1; 346 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN)) 347 n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n; 348 else 349 n += 1; 350 ArithNonLinFloatExpr* ae = 351 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,n); 352 int i=0; 353 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN)) { 354 ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe()); 355 for (; i<e0e->n; i++) 356 ae->a[i] = e0e->a[i]; 357 } else { 358 ae->a[i++] = e0; 359 } 360 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN)) { 361 ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe()); 362 int curN = i; 363 for (; i<curN+e1e->n; i++) 364 ae->a[i] = e1e->a[i-curN]; 365 } else { 366 ae->a[i++] = e1; 367 } 368 return LinFloatExpr(ae); 369 } 370 371 LinFloatExpr 372 min(const FloatVarArgs& x) { 373 using namespace MiniModel; 374 ArithNonLinFloatExpr* ae = 375 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,x.size()); 376 for (int i=x.size(); i--;) 377 ae->a[i] = x[i]; 378 return LinFloatExpr(ae); 379 } 380 381 LinFloatExpr 382 max(const LinFloatExpr& e0, const LinFloatExpr& e1) { 383 using namespace MiniModel; 384 int n = 0; 385 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX)) 386 n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n; 387 else 388 n += 1; 389 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX)) 390 n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n; 391 else 392 n += 1; 393 ArithNonLinFloatExpr* ae = 394 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,n); 395 int i=0; 396 if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX)) { 397 ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe()); 398 for (; i<e0e->n; i++) 399 ae->a[i] = e0e->a[i]; 400 } else { 401 ae->a[i++] = e0; 402 } 403 if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX)) { 404 ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe()); 405 int curN = i; 406 for (; i<curN+e1e->n; i++) 407 ae->a[i] = e1e->a[i-curN]; 408 } else { 409 ae->a[i++] = e1; 410 } 411 return LinFloatExpr(ae); 412 } 413 414 LinFloatExpr 415 max(const FloatVarArgs& x) { 416 using namespace MiniModel; 417 ArithNonLinFloatExpr* ae = 418 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,x.size()); 419 for (int i=x.size(); i--;) 420 ae->a[i] = x[i]; 421 return LinFloatExpr(ae); 422 } 423 424 LinFloatExpr 425 operator *(const FloatVar& e0, const FloatVar& e1) { 426 using namespace MiniModel; 427 ArithNonLinFloatExpr* ae = 428 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2); 429 ae->a[0] = e0; 430 ae->a[1] = e1; 431 return LinFloatExpr(ae); 432 } 433 434 LinFloatExpr 435 operator *(const LinFloatExpr& e0, const FloatVar& e1) { 436 using namespace MiniModel; 437 ArithNonLinFloatExpr* ae = 438 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2); 439 ae->a[0] = e0; 440 ae->a[1] = e1; 441 return LinFloatExpr(ae); 442 } 443 444 LinFloatExpr 445 operator *(const FloatVar& e0, const LinFloatExpr& e1) { 446 using namespace MiniModel; 447 ArithNonLinFloatExpr* ae = 448 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2); 449 ae->a[0] = e0; 450 ae->a[1] = e1; 451 return LinFloatExpr(ae); 452 } 453 454 LinFloatExpr 455 operator *(const LinFloatExpr& e0, const LinFloatExpr& e1) { 456 using namespace MiniModel; 457 ArithNonLinFloatExpr* ae = 458 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2); 459 ae->a[0] = e0; 460 ae->a[1] = e1; 461 return LinFloatExpr(ae); 462 } 463 464 LinFloatExpr 465 operator /(const LinFloatExpr& e0, const LinFloatExpr& e1) { 466 using namespace MiniModel; 467 ArithNonLinFloatExpr* ae = 468 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_DIV,2); 469 ae->a[0] = e0; 470 ae->a[1] = e1; 471 return LinFloatExpr(ae); 472 } 473 474 LinFloatExpr 475 sqr(const LinFloatExpr& e) { 476 using namespace MiniModel; 477 ArithNonLinFloatExpr* ae = 478 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQR,1); 479 ae->a[0] = e; 480 return LinFloatExpr(ae); 481 } 482 483 LinFloatExpr 484 sqrt(const LinFloatExpr& e) { 485 using namespace MiniModel; 486 ArithNonLinFloatExpr* ae = 487 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQRT,1); 488 ae->a[0] = e; 489 return LinFloatExpr(ae); 490 } 491 492 LinFloatExpr 493 pow(const LinFloatExpr& e, int exp) { 494 using namespace MiniModel; 495 ArithNonLinFloatExpr* ae = 496 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_POW,1,exp); 497 ae->a[0] = e; 498 return LinFloatExpr(ae); 499 } 500 501 LinFloatExpr 502 nroot(const LinFloatExpr& e, int exp) { 503 using namespace MiniModel; 504 ArithNonLinFloatExpr* ae = 505 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_NROOT,1,exp); 506 ae->a[0] = e; 507 return LinFloatExpr(ae); 508 } 509 510#ifdef GECODE_HAS_MPFR 511 512 LinFloatExpr 513 exp(const LinFloatExpr& e) { 514 using namespace MiniModel; 515 ArithNonLinFloatExpr* ae = 516 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_EXP,1); 517 ae->a[0] = e; 518 return LinFloatExpr(ae); 519 } 520 521 LinFloatExpr 522 log(const LinFloatExpr& e) { 523 using namespace MiniModel; 524 ArithNonLinFloatExpr* ae = 525 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_LOG,1); 526 ae->a[0] = e; 527 return LinFloatExpr(ae); 528 } 529 530 LinFloatExpr 531 asin(const LinFloatExpr& e) { 532 using namespace MiniModel; 533 ArithNonLinFloatExpr* ae = 534 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ASIN,1); 535 ae->a[0] = e; 536 return LinFloatExpr(ae); 537 } 538 539 LinFloatExpr 540 sin(const LinFloatExpr& e) { 541 using namespace MiniModel; 542 ArithNonLinFloatExpr* ae = 543 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SIN,1); 544 ae->a[0] = e; 545 return LinFloatExpr(ae); 546 } 547 548 LinFloatExpr 549 acos(const LinFloatExpr& e) { 550 using namespace MiniModel; 551 ArithNonLinFloatExpr* ae = 552 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ACOS,1); 553 ae->a[0] = e; 554 return LinFloatExpr(ae); 555 } 556 557 LinFloatExpr 558 cos(const LinFloatExpr& e) { 559 using namespace MiniModel; 560 ArithNonLinFloatExpr* ae = 561 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_COS,1); 562 ae->a[0] = e; 563 return LinFloatExpr(ae); 564 } 565 566 LinFloatExpr 567 atan(const LinFloatExpr& e) { 568 using namespace MiniModel; 569 ArithNonLinFloatExpr* ae = 570 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ATAN,1); 571 ae->a[0] = e; 572 return LinFloatExpr(ae); 573 } 574 575 LinFloatExpr 576 tan(const LinFloatExpr& e) { 577 using namespace MiniModel; 578 ArithNonLinFloatExpr* ae = 579 new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_TAN,1); 580 ae->a[0] = e; 581 return LinFloatExpr(ae); 582 } 583 584#endif 585 586} 587 588#endif 589 590// STATISTICS: minimodel-any