Generated on Tue Jan 19 2021 06:15:49 for Gecode by doxygen 1.8.13
float-arith.cpp
Go to the documentation of this file.
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 
40 namespace Gecode { namespace MiniModel {
41 
44  public NonLinFloatExpr {
45  public:
55 #ifdef GECODE_HAS_MPFR
64 #endif
66  ANLFE_NROOT
67  } t;
71  int n;
73  int aInt;
76  : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(-1) {}
78  : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(a0) {}
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  y = result(home,ret,x);
231  else {
232  y = result(home,ret);
233  exp(home, x, y);
234  }
235  }
236  break;
237  case ANLFE_LOG:
238  {
239  assert(n == 1);
240  FloatVar x = a[0].post(home);
241  y = result(home,ret);
242  log(home, x, y);
243  }
244  break;
245  case ANLFE_ASIN:
246  {
247  assert(n == 1);
248  FloatVar x = a[0].post(home);
249  y = result(home,ret);
250  asin(home, x, y);
251  }
252  break;
253  case ANLFE_SIN:
254  {
255  assert(n == 1);
256  FloatVar x = a[0].post(home);
257  y = result(home,ret);
258  sin(home, x, y);
259  }
260  break;
261  case ANLFE_ACOS:
262  {
263  assert(n == 1);
264  FloatVar x = a[0].post(home);
265  y = result(home,ret);
266  acos(home, x, y);
267  }
268  break;
269  case ANLFE_COS:
270  {
271  assert(n == 1);
272  FloatVar x = a[0].post(home);
273  y = result(home,ret);
274  cos(home, x, y);
275  }
276  break;
277  case ANLFE_ATAN:
278  {
279  assert(n == 1);
280  FloatVar x = a[0].post(home);
281  y = result(home,ret);
282  atan(home, x, y);
283  }
284  break;
285  case ANLFE_TAN:
286  {
287  assert(n == 1);
288  FloatVar x = a[0].post(home);
289  y = result(home,ret);
290  tan(home, x, y);
291  }
292  break;
293 #endif
294  default:
295  GECODE_NEVER;
296  }
297  return y;
298  }
299  virtual void post(Home home, FloatRelType frt, FloatVal c) const {
300  if ((t == ANLFE_MIN && frt == FRT_GQ) ||
301  (t == ANLFE_MAX && frt == FRT_LQ)) {
302  FloatVarArgs x(n);
303  for (int i=n; i--;)
304  x[i] = a[i].post(home);
305  rel(home, x, frt, c);
306  } else {
307  rel(home, post(home,NULL), frt, c);
308  }
309  }
310  virtual void post(Home home, FloatRelType frt, FloatVal c,
311  BoolVar b) const {
312  rel(home, post(home,NULL), frt, c, b);
313  }
314  };
317  return e.nlfe() &&
318  dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe()) != NULL &&
319  dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe())->t == t;
320  }
321 
322 }}
323 
324 namespace Gecode {
325 
327  abs(const LinFloatExpr& e) {
328  using namespace MiniModel;
330  return e;
331  ArithNonLinFloatExpr* ae =
332  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ABS,1);
333  ae->a[0] = e;
334  return LinFloatExpr(ae);
335  }
336 
338  min(const LinFloatExpr& e0, const LinFloatExpr& e1) {
339  using namespace MiniModel;
340  int n = 0;
342  n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
343  else
344  n += 1;
346  n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
347  else
348  n += 1;
349  ArithNonLinFloatExpr* ae =
350  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,n);
351  int i=0;
353  ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
354  for (; i<e0e->n; i++)
355  ae->a[i] = e0e->a[i];
356  } else {
357  ae->a[i++] = e0;
358  }
360  ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
361  int curN = i;
362  for (; i<curN+e1e->n; i++)
363  ae->a[i] = e1e->a[i-curN];
364  } else {
365  ae->a[i++] = e1;
366  }
367  return LinFloatExpr(ae);
368  }
369 
371  min(const FloatVarArgs& x) {
372  using namespace MiniModel;
373  ArithNonLinFloatExpr* ae =
374  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,x.size());
375  for (int i=x.size(); i--;)
376  ae->a[i] = x[i];
377  return LinFloatExpr(ae);
378  }
379 
381  max(const LinFloatExpr& e0, const LinFloatExpr& e1) {
382  using namespace MiniModel;
383  int n = 0;
385  n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
386  else
387  n += 1;
389  n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
390  else
391  n += 1;
392  ArithNonLinFloatExpr* ae =
393  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,n);
394  int i=0;
396  ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
397  for (; i<e0e->n; i++)
398  ae->a[i] = e0e->a[i];
399  } else {
400  ae->a[i++] = e0;
401  }
403  ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
404  int curN = i;
405  for (; i<curN+e1e->n; i++)
406  ae->a[i] = e1e->a[i-curN];
407  } else {
408  ae->a[i++] = e1;
409  }
410  return LinFloatExpr(ae);
411  }
412 
414  max(const FloatVarArgs& x) {
415  using namespace MiniModel;
416  ArithNonLinFloatExpr* ae =
417  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,x.size());
418  for (int i=x.size(); i--;)
419  ae->a[i] = x[i];
420  return LinFloatExpr(ae);
421  }
422 
424  operator *(const FloatVar& e0, const FloatVar& e1) {
425  using namespace MiniModel;
426  ArithNonLinFloatExpr* ae =
427  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
428  ae->a[0] = e0;
429  ae->a[1] = e1;
430  return LinFloatExpr(ae);
431  }
432 
434  operator *(const LinFloatExpr& e0, const FloatVar& e1) {
435  using namespace MiniModel;
436  ArithNonLinFloatExpr* ae =
437  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
438  ae->a[0] = e0;
439  ae->a[1] = e1;
440  return LinFloatExpr(ae);
441  }
442 
444  operator *(const FloatVar& e0, const LinFloatExpr& e1) {
445  using namespace MiniModel;
446  ArithNonLinFloatExpr* ae =
447  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
448  ae->a[0] = e0;
449  ae->a[1] = e1;
450  return LinFloatExpr(ae);
451  }
452 
454  operator *(const LinFloatExpr& e0, const LinFloatExpr& e1) {
455  using namespace MiniModel;
456  ArithNonLinFloatExpr* ae =
457  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
458  ae->a[0] = e0;
459  ae->a[1] = e1;
460  return LinFloatExpr(ae);
461  }
462 
464  operator /(const LinFloatExpr& e0, const LinFloatExpr& e1) {
465  using namespace MiniModel;
466  ArithNonLinFloatExpr* ae =
467  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_DIV,2);
468  ae->a[0] = e0;
469  ae->a[1] = e1;
470  return LinFloatExpr(ae);
471  }
472 
474  sqr(const LinFloatExpr& e) {
475  using namespace MiniModel;
476  ArithNonLinFloatExpr* ae =
477  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQR,1);
478  ae->a[0] = e;
479  return LinFloatExpr(ae);
480  }
481 
483  sqrt(const LinFloatExpr& e) {
484  using namespace MiniModel;
485  ArithNonLinFloatExpr* ae =
486  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQRT,1);
487  ae->a[0] = e;
488  return LinFloatExpr(ae);
489  }
490 
492  pow(const LinFloatExpr& e, int exp) {
493  using namespace MiniModel;
494  ArithNonLinFloatExpr* ae =
495  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_POW,1,exp);
496  ae->a[0] = e;
497  return LinFloatExpr(ae);
498  }
499 
501  nroot(const LinFloatExpr& e, int exp) {
502  using namespace MiniModel;
503  ArithNonLinFloatExpr* ae =
504  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_NROOT,1,exp);
505  ae->a[0] = e;
506  return LinFloatExpr(ae);
507  }
508 
509 #ifdef GECODE_HAS_MPFR
510 
512  exp(const LinFloatExpr& e) {
513  using namespace MiniModel;
514  ArithNonLinFloatExpr* ae =
515  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_EXP,1);
516  ae->a[0] = e;
517  return LinFloatExpr(ae);
518  }
519 
521  log(const LinFloatExpr& e) {
522  using namespace MiniModel;
523  ArithNonLinFloatExpr* ae =
524  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_LOG,1);
525  ae->a[0] = e;
526  return LinFloatExpr(ae);
527  }
528 
530  asin(const LinFloatExpr& e) {
531  using namespace MiniModel;
532  ArithNonLinFloatExpr* ae =
533  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ASIN,1);
534  ae->a[0] = e;
535  return LinFloatExpr(ae);
536  }
537 
539  sin(const LinFloatExpr& e) {
540  using namespace MiniModel;
541  ArithNonLinFloatExpr* ae =
542  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SIN,1);
543  ae->a[0] = e;
544  return LinFloatExpr(ae);
545  }
546 
548  acos(const LinFloatExpr& e) {
549  using namespace MiniModel;
550  ArithNonLinFloatExpr* ae =
551  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ACOS,1);
552  ae->a[0] = e;
553  return LinFloatExpr(ae);
554  }
555 
557  cos(const LinFloatExpr& e) {
558  using namespace MiniModel;
559  ArithNonLinFloatExpr* ae =
560  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_COS,1);
561  ae->a[0] = e;
562  return LinFloatExpr(ae);
563  }
564 
566  atan(const LinFloatExpr& e) {
567  using namespace MiniModel;
568  ArithNonLinFloatExpr* ae =
569  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ATAN,1);
570  ae->a[0] = e;
571  return LinFloatExpr(ae);
572  }
573 
575  tan(const LinFloatExpr& e) {
576  using namespace MiniModel;
577  ArithNonLinFloatExpr* ae =
578  new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_TAN,1);
579  ae->a[0] = e;
580  return LinFloatExpr(ae);
581  }
582 
583 #endif
584 
585 }
586 
587 #endif
588 
589 // STATISTICS: minimodel-any
NodeType t
Type of node.
Definition: bool-expr.cpp:230
void mult(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
Definition: arithmetic.cpp:88
int size(void) const
Return size of array (number of elements)
Definition: array.hpp:1569
ArithNonLinFloatExprType
The expression type.
Definition: float-arith.cpp:47
ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0, int a0)
Definition: float-arith.cpp:77
void log(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
FloatVal operator/(const FloatVal &x, const FloatVal &y)
Definition: val.hpp:213
FloatNum max(void) const
Return maximum of domain.
Definition: float.hpp:67
Less or equal ( )
Definition: float.hh:1071
void max(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
Definition: arithmetic.cpp:49
void abs(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Definition: arithmetic.cpp:41
ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0)
Constructors.
Definition: float-arith.cpp:75
bool assigned(void) const
Test whether view is assigned.
Definition: var.hpp:111
Passing float variables.
Definition: float.hh:979
void nroot(Home home, FloatVar x0, int n, FloatVar x1)
Post propagator for for $n 0$.
Definition: arithmetic.cpp:118
int aInt
Integer argument (used in nroot for example)
Definition: float-arith.cpp:73
void pow(Home home, FloatVar x0, int n, FloatVar x1)
Post propagator for for $n 0$.
Definition: arithmetic.cpp:109
Non-linear float arithmetic expressions.
Definition: float-arith.cpp:43
FloatVal val(void) const
Return assigned value.
Definition: float.hpp:53
bool hasType(const LinFloatExpr &e, ArithNonLinFloatExpr::ArithNonLinFloatExprType t)
Check if e is of type t.
FloatNum min(void) const
Return minimum of domain.
Definition: float.hpp:59
Gecode::FloatVal c(-8, 8)
Greater or equal ( )
Definition: float.hh:1073
int n
Number of negative literals for node type.
Definition: bool-expr.cpp:234
Base class for non-linear float expressions.
Definition: minimodel.hh:688
Gecode::IntArgs i({1, 2, 3, 4})
void sqr(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Definition: arithmetic.cpp:95
FloatRelType
Relation types for floats.
Definition: float.hh:1068
virtual void post(Home home, FloatRelType frt, FloatVal c) const
Post expression to be in relation frt with c.
void sqrt(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Definition: arithmetic.cpp:102
struct Gecode::@593::NNF::@62::@63 b
For binary nodes (and, or, eqv)
Float expressions
Definition: minimodel.hh:718
void asin(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Boolean integer variables.
Definition: int.hh:512
LinFloatExpr * a
Expressions.
Definition: float-arith.cpp:69
void min(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
Definition: arithmetic.cpp:67
void cos(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
virtual FloatVar post(Home home, FloatVar *ret) const
Post expression.
Definition: float-arith.cpp:82
Post propagator for SetVar SetOpType SetVar y
Definition: set.hh:767
void div(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
Definition: arithmetic.cpp:127
Float value type.
Definition: float.hh:334
FloatVal operator*(const FloatVal &x, const FloatVal &y)
Definition: val.hpp:200
void free(T *b, long unsigned int n)
Delete n objects starting at b.
Definition: heap.hpp:457
void tan(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Heap heap
The single global heap.
Definition: heap.cpp:44
void rel(Home home, FloatVar x0, FloatRelType frt, FloatVal n)
Propagates .
Definition: rel.cpp:43
Post propagator for SetVar x
Definition: set.hh:767
#define GECODE_MINIMODEL_EXPORT
Definition: minimodel.hh:78
Float variables.
Definition: float.hh:870
Gecode toplevel namespace
void sin(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
NonLinFloatExpr * nlfe(void) const
Return non-linear expression inside, or NULL if not non-linear.
Definition: float-expr.cpp:138
void acos(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
void exp(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Home class for posting propagators
Definition: core.hpp:853
#define GECODE_NEVER
Assert that this command is never executed.
Definition: macros.hpp:56
struct Gecode::@593::NNF::@62::@64 a
For atomic nodes.
void atan(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
int n
Size of variable array.
Definition: float-arith.cpp:71
TFE post(PropagatorGroup g)
Only post functions (but not propagators) from g are considered.
Definition: filter.cpp:138
T * a
Element array.
Definition: array.hpp:526
void post(Home home, FloatRelType frt) const
Post propagator.
Definition: float-expr.cpp:152
virtual void post(Home home, FloatRelType frt, FloatVal c, BoolVar b) const
Post reified expression to be in relation frt with c.