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 #include <gecode/minimodel.hh>
00035
00036 namespace Gecode { namespace MiniModel {
00037
00039 class GECODE_MINIMODEL_EXPORT ArithNonLinIntExpr : public NonLinIntExpr {
00040 public:
00042 enum ArithNonLinIntExprType {
00043 ANLE_ABS,
00044 ANLE_MIN,
00045 ANLE_MAX,
00046 ANLE_MULT,
00047 ANLE_DIV,
00048 ANLE_MOD,
00049 ANLE_SQR,
00050 ANLE_SQRT,
00051 ANLE_POW,
00052 ANLE_NROOT,
00053 ANLE_ELMNT,
00054 ANLE_ITE
00055 } t;
00057 LinIntExpr* a;
00059 int n;
00061 int aInt;
00063 BoolExpr b;
00065 ArithNonLinIntExpr(ArithNonLinIntExprType t0, int n0)
00066 : t(t0), a(heap.alloc<LinIntExpr>(n0)), n(n0) {}
00068 ArithNonLinIntExpr(ArithNonLinIntExprType t0, int n0, int a0)
00069 : t(t0), a(heap.alloc<LinIntExpr>(n0)), n(n0), aInt(a0) {}
00071 ArithNonLinIntExpr(ArithNonLinIntExprType t0, int n0, const BoolExpr& b0)
00072 : t(t0), a(heap.alloc<LinIntExpr>(n0)), n(n0), b(b0) {}
00074 ~ArithNonLinIntExpr(void) {
00075 heap.free<LinIntExpr>(a,n);
00076 }
00078 virtual IntVar post(Home home, IntVar* ret, IntPropLevel ipl) const {
00079 IntVar y;
00080 switch (t) {
00081 case ANLE_ABS:
00082 {
00083 IntVar x = a[0].post(home, ipl);
00084 if (x.min() >= 0)
00085 y = result(home,ret,x);
00086 else {
00087 y = result(home,ret);
00088 abs(home, x, y, ipl);
00089 }
00090 }
00091 break;
00092 case ANLE_MIN:
00093 if (n==1) {
00094 y = result(home,ret, a[0].post(home, ipl));
00095 } else if (n==2) {
00096 IntVar x0 = a[0].post(home, ipl);
00097 IntVar x1 = a[1].post(home, ipl);
00098 if (x0.max() <= x1.min())
00099 y = result(home,ret,x0);
00100 else if (x1.max() <= x0.min())
00101 y = result(home,ret,x1);
00102 else {
00103 y = result(home,ret);
00104 min(home, x0, x1, y, ipl);
00105 }
00106 } else {
00107 IntVarArgs x(n);
00108 for (int i=n; i--;)
00109 x[i] = a[i].post(home, ipl);
00110 y = result(home,ret);
00111 min(home, x, y, ipl);
00112 }
00113 break;
00114 case ANLE_MAX:
00115 if (n==1) {
00116 y = result(home,ret,a[0].post(home, ipl));
00117 } else if (n==2) {
00118 IntVar x0 = a[0].post(home, ipl);
00119 IntVar x1 = a[1].post(home, ipl);
00120 if (x0.max() <= x1.min())
00121 y = result(home,ret,x1);
00122 else if (x1.max() <= x0.min())
00123 y = result(home,ret,x0);
00124 else {
00125 y = result(home,ret);
00126 max(home, x0, x1, y, ipl);
00127 }
00128 } else {
00129 IntVarArgs x(n);
00130 for (int i=n; i--;)
00131 x[i] = a[i].post(home, ipl);
00132 y = result(home,ret);
00133 max(home, x, y, ipl);
00134 }
00135 break;
00136 case ANLE_MULT:
00137 {
00138 assert(n == 2);
00139 IntVar x0 = a[0].post(home, ipl);
00140 IntVar x1 = a[1].post(home, ipl);
00141 if (x0.assigned() && (x0.val() == 0))
00142 y = result(home,ret,x0);
00143 else if (x0.assigned() && (x0.val() == 1))
00144 y = result(home,ret,x1);
00145 else if (x1.assigned() && (x1.val() == 0))
00146 y = result(home,ret,x1);
00147 else if (x1.assigned() && (x1.val() == 1))
00148 y = result(home,ret,x0);
00149 else {
00150 y = result(home,ret);
00151 mult(home, x0, x1, y, ipl);
00152 }
00153 }
00154 break;
00155 case ANLE_DIV:
00156 {
00157 assert(n == 2);
00158 IntVar x0 = a[0].post(home, ipl);
00159 IntVar x1 = a[1].post(home, ipl);
00160 rel(home, x1, IRT_NQ, 0);
00161 if (x1.assigned() && (x1.val() == 1))
00162 y = result(home,ret,x0);
00163 else if (x0.assigned() && (x0.val() == 0))
00164 y = result(home,ret,x0);
00165 else {
00166 y = result(home,ret);
00167 div(home, x0, x1, y, ipl);
00168 }
00169 }
00170 break;
00171 case ANLE_MOD:
00172 {
00173 assert(n == 2);
00174 IntVar x0 = a[0].post(home, ipl);
00175 IntVar x1 = a[1].post(home, ipl);
00176 y = result(home,ret);
00177 mod(home, x0, x1, y, ipl);
00178 }
00179 break;
00180 case ANLE_SQR:
00181 {
00182 assert(n == 1);
00183 IntVar x = a[0].post(home, ipl);
00184 if (x.assigned() && ((x.val() == 0) || (x.val() == 1)))
00185 y = result(home,ret,x);
00186 else {
00187 y = result(home,ret);
00188 sqr(home, x, y, ipl);
00189 }
00190 }
00191 break;
00192 case ANLE_SQRT:
00193 {
00194 assert(n == 1);
00195 IntVar x = a[0].post(home, ipl);
00196 if (x.assigned() && ((x.val() == 0) || (x.val() == 1)))
00197 y = result(home,ret,x);
00198 else {
00199 y = result(home,ret);
00200 sqrt(home, x, y, ipl);
00201 }
00202 }
00203 break;
00204 case ANLE_POW:
00205 {
00206 assert(n == 1);
00207 IntVar x = a[0].post(home, ipl);
00208 if (x.assigned() && (aInt > 0) &&
00209 ((x.val() == 0) || (x.val() == 1)))
00210 y = result(home,ret,x);
00211 else {
00212 y = result(home,ret);
00213 pow(home, x, aInt, y, ipl);
00214 }
00215 }
00216 break;
00217 case ANLE_NROOT:
00218 {
00219 assert(n == 1);
00220 IntVar x = a[0].post(home, ipl);
00221 if (x.assigned() && (aInt > 0) &&
00222 ((x.val() == 0) || (x.val() == 1)))
00223 y = result(home,ret,x);
00224 else {
00225 y = result(home,ret);
00226 nroot(home, x, aInt, y, ipl);
00227 }
00228 }
00229 break;
00230 case ANLE_ELMNT:
00231 {
00232 IntVar z = a[n-1].post(home, ipl);
00233 if (z.assigned() && z.val() >= 0 && z.val() < n-1) {
00234 y = result(home,ret,a[z.val()].post(home, ipl));
00235 } else {
00236 IntVarArgs x(n-1);
00237 bool assigned = true;
00238 for (int i=n-1; i--;) {
00239 x[i] = a[i].post(home, ipl);
00240 if (!x[i].assigned())
00241 assigned = false;
00242 }
00243 y = result(home,ret);
00244 if (assigned) {
00245 IntArgs xa(n-1);
00246 for (int i=n-1; i--;)
00247 xa[i] = x[i].val();
00248 element(home, xa, z, y, ipl);
00249 } else {
00250 element(home, x, z, y, ipl);
00251 }
00252 }
00253 }
00254 break;
00255 case ANLE_ITE:
00256 {
00257 assert(n == 2);
00258 BoolVar c = b.expr(home, ipl);
00259 IntVar x0 = a[0].post(home, ipl);
00260 IntVar x1 = a[1].post(home, ipl);
00261 y = result(home,ret);
00262 ite(home, c, x0, x1, y, ipl);
00263 }
00264 break;
00265 default:
00266 GECODE_NEVER;
00267 }
00268 return y;
00269 }
00270 virtual void post(Home home, IntRelType irt, int c,
00271 IntPropLevel ipl) const {
00272 if ( (t == ANLE_MIN && (irt == IRT_GQ || irt == IRT_GR)) ||
00273 (t == ANLE_MAX && (irt == IRT_LQ || irt == IRT_LE)) ) {
00274 IntVarArgs x(n);
00275 for (int i=n; i--;)
00276 x[i] = a[i].post(home, ipl);
00277 rel(home, x, irt, c);
00278 } else {
00279 rel(home, post(home,NULL,ipl), irt, c);
00280 }
00281 }
00282 virtual void post(Home home, IntRelType irt, int c,
00283 BoolVar b, IntPropLevel ipl) const {
00284 rel(home, post(home,NULL,ipl), irt, c, b);
00285 }
00286 };
00288 bool hasType(const LinIntExpr& e, ArithNonLinIntExpr::ArithNonLinIntExprType t) {
00289 return e.nle() &&
00290 dynamic_cast<ArithNonLinIntExpr*>(e.nle()) != NULL &&
00291 dynamic_cast<ArithNonLinIntExpr*>(e.nle())->t == t;
00292 }
00293
00294 }}
00295
00296 namespace Gecode {
00297
00298 LinIntExpr
00299 abs(const LinIntExpr& e) {
00300 using namespace MiniModel;
00301 if (hasType(e, ArithNonLinIntExpr::ANLE_ABS))
00302 return e;
00303 ArithNonLinIntExpr* ae =
00304 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_ABS,1);
00305 ae->a[0] = e;
00306 return LinIntExpr(ae);
00307 }
00308
00309 LinIntExpr
00310 min(const LinIntExpr& e0, const LinIntExpr& e1) {
00311 using namespace MiniModel;
00312 int n = 0;
00313 if (hasType(e0, ArithNonLinIntExpr::ANLE_MIN))
00314 n += static_cast<ArithNonLinIntExpr*>(e0.nle())->n;
00315 else
00316 n += 1;
00317 if (hasType(e1, ArithNonLinIntExpr::ANLE_MIN))
00318 n += static_cast<ArithNonLinIntExpr*>(e1.nle())->n;
00319 else
00320 n += 1;
00321 ArithNonLinIntExpr* ae =
00322 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MIN,n);
00323 int i=0;
00324 if (hasType(e0, ArithNonLinIntExpr::ANLE_MIN)) {
00325 ArithNonLinIntExpr* e0e = static_cast<ArithNonLinIntExpr*>(e0.nle());
00326 for (; i<e0e->n; i++)
00327 ae->a[i] = e0e->a[i];
00328 } else {
00329 ae->a[i++] = e0;
00330 }
00331 if (hasType(e1, ArithNonLinIntExpr::ANLE_MIN)) {
00332 ArithNonLinIntExpr* e1e = static_cast<ArithNonLinIntExpr*>(e1.nle());
00333 int curN = i;
00334 for (; i<curN+e1e->n; i++)
00335 ae->a[i] = e1e->a[i-curN];
00336 } else {
00337 ae->a[i++] = e1;
00338 }
00339 return LinIntExpr(ae);
00340 }
00341
00342 LinIntExpr
00343 max(const LinIntExpr& e0, const LinIntExpr& e1) {
00344 using namespace MiniModel;
00345 int n = 0;
00346 if (hasType(e0, ArithNonLinIntExpr::ANLE_MAX))
00347 n += static_cast<ArithNonLinIntExpr*>(e0.nle())->n;
00348 else
00349 n += 1;
00350 if (hasType(e1, ArithNonLinIntExpr::ANLE_MAX))
00351 n += static_cast<ArithNonLinIntExpr*>(e1.nle())->n;
00352 else
00353 n += 1;
00354 ArithNonLinIntExpr* ae =
00355 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MAX,n);
00356 int i=0;
00357 if (hasType(e0, ArithNonLinIntExpr::ANLE_MAX)) {
00358 ArithNonLinIntExpr* e0e = static_cast<ArithNonLinIntExpr*>(e0.nle());
00359 for (; i<e0e->n; i++)
00360 ae->a[i] = e0e->a[i];
00361 } else {
00362 ae->a[i++] = e0;
00363 }
00364 if (hasType(e1, ArithNonLinIntExpr::ANLE_MAX)) {
00365 ArithNonLinIntExpr* e1e = static_cast<ArithNonLinIntExpr*>(e1.nle());
00366 int curN = i;
00367 for (; i<curN+e1e->n; i++)
00368 ae->a[i] = e1e->a[i-curN];
00369 } else {
00370 ae->a[i++] = e1;
00371 }
00372 return LinIntExpr(ae);
00373 }
00374
00375 LinIntExpr
00376 min(const IntVarArgs& x) {
00377 using namespace MiniModel;
00378 ArithNonLinIntExpr* ae =
00379 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MIN,x.size());
00380 for (int i=x.size(); i--;)
00381 ae->a[i] = x[i];
00382 return LinIntExpr(ae);
00383 }
00384
00385 LinIntExpr
00386 max(const IntVarArgs& x) {
00387 using namespace MiniModel;
00388 ArithNonLinIntExpr* ae =
00389 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MAX,x.size());
00390 for (int i=x.size(); i--;)
00391 ae->a[i] = x[i];
00392 return LinIntExpr(ae);
00393 }
00394
00395 LinIntExpr
00396 operator *(const LinIntExpr& e0, const LinIntExpr& e1) {
00397 using namespace MiniModel;
00398 ArithNonLinIntExpr* ae =
00399 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MULT,2);
00400 ae->a[0] = e0;
00401 ae->a[1] = e1;
00402 return LinIntExpr(ae);
00403 }
00404
00405 LinIntExpr
00406 sqr(const LinIntExpr& e) {
00407 using namespace MiniModel;
00408 ArithNonLinIntExpr* ae =
00409 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_SQR,1);
00410 ae->a[0] = e;
00411 return LinIntExpr(ae);
00412 }
00413
00414 LinIntExpr
00415 sqrt(const LinIntExpr& e) {
00416 using namespace MiniModel;
00417 ArithNonLinIntExpr* ae =
00418 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_SQRT,1);
00419 ae->a[0] = e;
00420 return LinIntExpr(ae);
00421 }
00422
00423 LinIntExpr
00424 pow(const LinIntExpr& e, int n) {
00425 using namespace MiniModel;
00426 ArithNonLinIntExpr* ae =
00427 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_POW,1,n);
00428 ae->a[0] = e;
00429 return LinIntExpr(ae);
00430 }
00431
00432 LinIntExpr
00433 nroot(const LinIntExpr& e, int n) {
00434 using namespace MiniModel;
00435 ArithNonLinIntExpr* ae =
00436 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_NROOT,1,n);
00437 ae->a[0] = e;
00438 return LinIntExpr(ae);
00439 }
00440
00441 LinIntExpr
00442 operator /(const LinIntExpr& e0, const LinIntExpr& e1) {
00443 using namespace MiniModel;
00444 ArithNonLinIntExpr* ae =
00445 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_DIV,2);
00446 ae->a[0] = e0;
00447 ae->a[1] = e1;
00448 return LinIntExpr(ae);
00449 }
00450
00451 LinIntExpr
00452 operator %(const LinIntExpr& e0, const LinIntExpr& e1) {
00453 using namespace MiniModel;
00454 ArithNonLinIntExpr* ae =
00455 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_MOD,2);
00456 ae->a[0] = e0;
00457 ae->a[1] = e1;
00458 return LinIntExpr(ae);
00459 }
00460
00461 LinIntExpr
00462 element(const IntVarArgs& x, const LinIntExpr& e) {
00463 using namespace MiniModel;
00464 ArithNonLinIntExpr* ae =
00465 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_ELMNT,x.size()+1);
00466 for (int i=x.size(); i--;)
00467 ae->a[i] = x[i];
00468 ae->a[x.size()] = e;
00469 return LinIntExpr(ae);
00470 }
00471
00472 LinIntExpr
00473 element(const IntArgs& x, const LinIntExpr& e) {
00474 using namespace MiniModel;
00475 ArithNonLinIntExpr* ae =
00476 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_ELMNT,x.size()+1);
00477 for (int i=x.size(); i--;)
00478 ae->a[i] = x[i];
00479 ae->a[x.size()] = e;
00480 return LinIntExpr(ae);
00481 }
00482
00483 LinIntExpr
00484 ite(const BoolExpr& b, const LinIntExpr& e0, const LinIntExpr& e1) {
00485 using namespace MiniModel;
00486 ArithNonLinIntExpr* ae =
00487 new ArithNonLinIntExpr(ArithNonLinIntExpr::ANLE_ITE,2,b);
00488 ae->a[0] = e0;
00489 ae->a[1] = e1;
00490 return LinIntExpr(ae);
00491 }
00492
00493 }
00494
00495