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