Generated on Sat May 25 2013 18:00:40 for Gecode by doxygen 1.8.3.1
int-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  *
6  * Copyright:
7  * Christian Schulte, 2006
8  *
9  * Last modified:
10  * $Date: 2013-01-22 13:48:12 +0100 (Tue, 22 Jan 2013) $ by $Author: schulte $
11  * $Revision: 13227 $
12  *
13  * This file is part of Gecode, the generic constraint
14  * development environment:
15  * http://www.gecode.org
16  *
17  * Permission is hereby granted, free of charge, to any person obtaining
18  * a copy of this software and associated documentation files (the
19  * "Software"), to deal in the Software without restriction, including
20  * without limitation the rights to use, copy, modify, merge, publish,
21  * distribute, sublicense, and/or sell copies of the Software, and to
22  * permit persons to whom the Software is furnished to do so, subject to
23  * the following conditions:
24  *
25  * The above copyright notice and this permission notice shall be
26  * included in all copies or substantial portions of the Software.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35  *
36  */
37 
38 #include <gecode/minimodel.hh>
39 
40 namespace Gecode { namespace MiniModel {
41 
44  public:
57  ANLE_ELMNT
58  } t;
62  int n;
64  int aInt;
67  : t(t0), a(heap.alloc<LinIntExpr>(n0)), n(n0) {}
70  : t(t0), a(heap.alloc<LinIntExpr>(n0)), n(n0), aInt(a0) {}
73  heap.free<LinIntExpr>(a,n);
74  }
76  virtual IntVar post(Home home, IntVar* ret, IntConLevel icl) const {
77  IntVar y;
78  switch (t) {
79  case ANLE_ABS:
80  {
81  IntVar x = a[0].post(home, icl);
82  if (x.min() >= 0)
83  y = result(home,ret,x);
84  else {
85  y = result(home,ret);
86  abs(home, x, y, icl);
87  }
88  }
89  break;
90  case ANLE_MIN:
91  if (n==1) {
92  y = result(home,ret, a[0].post(home, icl));
93  } else if (n==2) {
94  IntVar x0 = a[0].post(home, icl);
95  IntVar x1 = a[1].post(home, icl);
96  if (x0.max() <= x1.min())
97  y = result(home,ret,x0);
98  else if (x1.max() <= x0.min())
99  y = result(home,ret,x1);
100  else {
101  y = result(home,ret);
102  min(home, x0, x1, y, icl);
103  }
104  } else {
105  IntVarArgs x(n);
106  for (int i=n; i--;)
107  x[i] = a[i].post(home, icl);
108  y = result(home,ret);
109  min(home, x, y, icl);
110  }
111  break;
112  case ANLE_MAX:
113  if (n==1) {
114  y = result(home,ret,a[0].post(home, icl));
115  } else if (n==2) {
116  IntVar x0 = a[0].post(home, icl);
117  IntVar x1 = a[1].post(home, icl);
118  if (x0.max() <= x1.min())
119  y = result(home,ret,x1);
120  else if (x1.max() <= x0.min())
121  y = result(home,ret,x0);
122  else {
123  y = result(home,ret);
124  max(home, x0, x1, y, icl);
125  }
126  } else {
127  IntVarArgs x(n);
128  for (int i=n; i--;)
129  x[i] = a[i].post(home, icl);
130  y = result(home,ret);
131  max(home, x, y, icl);
132  }
133  break;
134  case ANLE_MULT:
135  {
136  assert(n == 2);
137  IntVar x0 = a[0].post(home, icl);
138  IntVar x1 = a[1].post(home, icl);
139  if (x0.assigned() && (x0.val() == 0))
140  y = result(home,ret,x0);
141  else if (x0.assigned() && (x0.val() == 1))
142  y = result(home,ret,x1);
143  else if (x1.assigned() && (x1.val() == 0))
144  y = result(home,ret,x1);
145  else if (x1.assigned() && (x1.val() == 1))
146  y = result(home,ret,x0);
147  else {
148  y = result(home,ret);
149  mult(home, x0, x1, y, icl);
150  }
151  }
152  break;
153  case ANLE_DIV:
154  {
155  assert(n == 2);
156  IntVar x0 = a[0].post(home, icl);
157  IntVar x1 = a[1].post(home, icl);
158  rel(home, x1, IRT_NQ, 0);
159  if (x1.assigned() && (x1.val() == 1))
160  y = result(home,ret,x0);
161  else if (x0.assigned() && (x0.val() == 0))
162  y = result(home,ret,x0);
163  else {
164  y = result(home,ret);
165  div(home, x0, x1, y, icl);
166  }
167  }
168  break;
169  case ANLE_MOD:
170  {
171  assert(n == 2);
172  IntVar x0 = a[0].post(home, icl);
173  IntVar x1 = a[1].post(home, icl);
174  y = result(home,ret);
175  mod(home, x0, x1, y, icl);
176  }
177  break;
178  case ANLE_SQR:
179  {
180  assert(n == 1);
181  IntVar x = a[0].post(home, icl);
182  if (x.assigned() && ((x.val() == 0) || (x.val() == 1)))
183  y = x;
184  else {
185  y = result(home,ret);
186  sqr(home, x, y, icl);
187  }
188  }
189  break;
190  case ANLE_SQRT:
191  {
192  assert(n == 1);
193  IntVar x = a[0].post(home, icl);
194  if (x.assigned() && ((x.val() == 0) || (x.val() == 1)))
195  y = result(home,ret,x);
196  else {
197  y = result(home,ret);
198  sqrt(home, x, y, icl);
199  }
200  }
201  break;
202  case ANLE_POW:
203  {
204  assert(n == 1);
205  IntVar x = a[0].post(home, icl);
206  if (x.assigned() && (aInt > 0) &&
207  ((x.val() == 0) || (x.val() == 1)))
208  y = x;
209  else {
210  y = result(home,ret);
211  pow(home, x, aInt, y, icl);
212  }
213  }
214  break;
215  case ANLE_NROOT:
216  {
217  assert(n == 1);
218  IntVar x = a[0].post(home, icl);
219  if (x.assigned() && (aInt > 0) &&
220  ((x.val() == 0) || (x.val() == 1)))
221  y = result(home,ret,x);
222  else {
223  y = result(home,ret);
224  nroot(home, x, aInt, y, icl);
225  }
226  }
227  break;
228  case ANLE_ELMNT:
229  {
230  IntVar z = a[n-1].post(home, icl);
231  if (z.assigned() && z.val() >= 0 && z.val() < n-1) {
232  y = result(home,ret,a[z.val()].post(home, icl));
233  } else {
234  IntVarArgs x(n-1);
235  bool assigned = true;
236  for (int i=n-1; i--;) {
237  x[i] = a[i].post(home, icl);
238  if (!x[i].assigned())
239  assigned = false;
240  }
241  y = result(home,ret);
242  if (assigned) {
243  IntArgs xa(n-1);
244  for (int i=n-1; i--;)
245  xa[i] = x[i].val();
246  element(home, xa, z, y, icl);
247  } else {
248  element(home, x, z, y, icl);
249  }
250  }
251  }
252  break;
253  default:
254  GECODE_NEVER;
255  }
256  return y;
257  }
258  virtual void post(Home home, IntRelType irt, int c,
259  IntConLevel icl) const {
260  if ( (t == ANLE_MIN && (irt == IRT_GQ || irt == IRT_GR)) ||
261  (t == ANLE_MAX && (irt == IRT_LQ || irt == IRT_LE)) ) {
262  IntVarArgs x(n);
263  for (int i=n; i--;)
264  x[i] = a[i].post(home, icl);
265  rel(home, x, irt, c);
266  } else {
267  rel(home, post(home,NULL,icl), irt, c);
268  }
269  }
270  virtual void post(Home home, IntRelType irt, int c,
271  BoolVar b, IntConLevel icl) const {
272  rel(home, post(home,NULL,icl), irt, c, b);
273  }
274  };
277  return e.nle() &&
278  dynamic_cast<ArithNonLinIntExpr*>(e.nle()) != NULL &&
279  dynamic_cast<ArithNonLinIntExpr*>(e.nle())->t == t;
280  }
281 
282 }}
283 
284 namespace Gecode {
285 
286  LinIntExpr
287  abs(const LinIntExpr& e) {
288  using namespace MiniModel;
290  return e;
291  ArithNonLinIntExpr* ae =
292  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_ABS,1);
293  ae->a[0] = e;
294  return LinIntExpr(ae);
295  }
296 
297  LinIntExpr
298  min(const LinIntExpr& e0, const LinIntExpr& e1) {
299  using namespace MiniModel;
300  int n = 0;
302  n += static_cast<ArithNonLinIntExpr*>(e0.nle())->n;
303  else
304  n += 1;
306  n += static_cast<ArithNonLinIntExpr*>(e1.nle())->n;
307  else
308  n += 1;
309  ArithNonLinIntExpr* ae =
310  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MIN,n);
311  int i=0;
313  ArithNonLinIntExpr* e0e = static_cast<ArithNonLinIntExpr*>(e0.nle());
314  for (; i<e0e->n; i++)
315  ae->a[i] = e0e->a[i];
316  } else {
317  ae->a[i++] = e0;
318  }
320  ArithNonLinIntExpr* e1e = static_cast<ArithNonLinIntExpr*>(e1.nle());
321  int curN = i;
322  for (; i<curN+e1e->n; i++)
323  ae->a[i] = e1e->a[i-curN];
324  } else {
325  ae->a[i++] = e1;
326  }
327  return LinIntExpr(ae);
328  }
329 
330  LinIntExpr
331  max(const LinIntExpr& e0, const LinIntExpr& e1) {
332  using namespace MiniModel;
333  int n = 0;
335  n += static_cast<ArithNonLinIntExpr*>(e0.nle())->n;
336  else
337  n += 1;
339  n += static_cast<ArithNonLinIntExpr*>(e1.nle())->n;
340  else
341  n += 1;
342  ArithNonLinIntExpr* ae =
343  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MAX,n);
344  int i=0;
346  ArithNonLinIntExpr* e0e = static_cast<ArithNonLinIntExpr*>(e0.nle());
347  for (; i<e0e->n; i++)
348  ae->a[i] = e0e->a[i];
349  } else {
350  ae->a[i++] = e0;
351  }
353  ArithNonLinIntExpr* e1e = static_cast<ArithNonLinIntExpr*>(e1.nle());
354  int curN = i;
355  for (; i<curN+e1e->n; i++)
356  ae->a[i] = e1e->a[i-curN];
357  } else {
358  ae->a[i++] = e1;
359  }
360  return LinIntExpr(ae);
361  }
362 
363  LinIntExpr
364  min(const IntVarArgs& x) {
365  using namespace MiniModel;
366  ArithNonLinIntExpr* ae =
367  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MIN,x.size());
368  for (int i=x.size(); i--;)
369  ae->a[i] = x[i];
370  return LinIntExpr(ae);
371  }
372 
373  LinIntExpr
374  max(const IntVarArgs& x) {
375  using namespace MiniModel;
376  ArithNonLinIntExpr* ae =
377  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MAX,x.size());
378  for (int i=x.size(); i--;)
379  ae->a[i] = x[i];
380  return LinIntExpr(ae);
381  }
382 
383  LinIntExpr
384  operator *(const LinIntExpr& e0, const LinIntExpr& e1) {
385  using namespace MiniModel;
386  ArithNonLinIntExpr* ae =
387  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MULT,2);
388  ae->a[0] = e0;
389  ae->a[1] = e1;
390  return LinIntExpr(ae);
391  }
392 
393  LinIntExpr
394  sqr(const LinIntExpr& e) {
395  using namespace MiniModel;
396  ArithNonLinIntExpr* ae =
397  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_SQR,1);
398  ae->a[0] = e;
399  return LinIntExpr(ae);
400  }
401 
402  LinIntExpr
403  sqrt(const LinIntExpr& e) {
404  using namespace MiniModel;
405  ArithNonLinIntExpr* ae =
406  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_SQRT,1);
407  ae->a[0] = e;
408  return LinIntExpr(ae);
409  }
410 
411  LinIntExpr
412  pow(const LinIntExpr& e, int n) {
413  using namespace MiniModel;
414  ArithNonLinIntExpr* ae =
415  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_POW,1,n);
416  ae->a[0] = e;
417  return LinIntExpr(ae);
418  }
419 
420  LinIntExpr
421  nroot(const LinIntExpr& e, int n) {
422  using namespace MiniModel;
423  ArithNonLinIntExpr* ae =
424  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_NROOT,1,n);
425  ae->a[0] = e;
426  return LinIntExpr(ae);
427  }
428 
429  LinIntExpr
430  operator /(const LinIntExpr& e0, const LinIntExpr& e1) {
431  using namespace MiniModel;
432  ArithNonLinIntExpr* ae =
433  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_DIV,2);
434  ae->a[0] = e0;
435  ae->a[1] = e1;
436  return LinIntExpr(ae);
437  }
438 
439  LinIntExpr
440  operator %(const LinIntExpr& e0, const LinIntExpr& e1) {
441  using namespace MiniModel;
442  ArithNonLinIntExpr* ae =
443  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MOD,2);
444  ae->a[0] = e0;
445  ae->a[1] = e1;
446  return LinIntExpr(ae);
447  }
448 
449  LinIntExpr
450  element(const IntVarArgs& x, const LinIntExpr& e) {
451  using namespace MiniModel;
452  ArithNonLinIntExpr* ae =
453  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_ELMNT,x.size()+1);
454  for (int i=x.size(); i--;)
455  ae->a[i] = x[i];
456  ae->a[x.size()] = e;
457  return LinIntExpr(ae);
458  }
459 
460  LinIntExpr
461  element(const IntArgs& x, const LinIntExpr& e) {
462  using namespace MiniModel;
463  ArithNonLinIntExpr* ae =
464  new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_ELMNT,x.size()+1);
465  for (int i=x.size(); i--;)
466  ae->a[i] = x[i];
467  ae->a[x.size()] = e;
468  return LinIntExpr(ae);
469  }
470 
471 }
472 
473 // STATISTICS: minimodel-any