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
00035
00036
00037
00038 #include <cfloat>
00039 #include <algorithm>
00040
00041 #include "gecode/int/rel.hh"
00042 #include "gecode/int/linear.hh"
00043
00044 namespace Gecode { namespace Int { namespace Linear {
00045
00047 const double double_max = 9007199254740991.0;
00049 const double double_min = -9007199254740991.0;
00050
00052 inline void
00053 eliminate(Term<IntView>* t, int &n, double& d) {
00054 for (int i=n; i--; )
00055 if (t[i].x.assigned()) {
00056 d -= t[i].a * static_cast<double>(t[i].x.val());
00057 t[i]=t[--n];
00058 }
00059 if ((d < double_min) || (d > double_max))
00060 throw OutOfLimits("Int::linear");
00061 }
00062
00064 inline void
00065 rewrite(IntRelType &r, double &d,
00066 Term<IntView>* &t_p, int &n_p,
00067 Term<IntView>* &t_n, int &n_n) {
00068 switch (r) {
00069 case IRT_EQ: case IRT_NQ: case IRT_LQ:
00070 break;
00071 case IRT_LE:
00072 d--; r = IRT_LQ; break;
00073 case IRT_GR:
00074 d++;
00075 case IRT_GQ:
00076 r = IRT_LQ;
00077 std::swap(n_p,n_n); std::swap(t_p,t_n); d = -d;
00078 break;
00079 default:
00080 throw UnknownRelation("Int::linear");
00081 }
00082 }
00083
00085 inline bool
00086 precision(Term<IntView>* t_p, int n_p,
00087 Term<IntView>* t_n, int n_n,
00088 double d) {
00089 double sl = 0.0;
00090 double su = 0.0;
00091
00092 for (int i = n_p; i--; ) {
00093 sl += t_p[i].a * static_cast<double>(t_p[i].x.min());
00094 su += t_p[i].a * static_cast<double>(t_p[i].x.max());
00095 }
00096 for (int i = n_n; i--; ) {
00097 sl -= t_n[i].a * static_cast<double>(t_n[i].x.max());
00098 su -= t_n[i].a * static_cast<double>(t_n[i].x.min());
00099 }
00100 sl -= d;
00101 su -= d;
00102
00103 if ((sl < double_min) || (su > double_max))
00104 throw OutOfLimits("Int::linear");
00105
00106 bool is_ip = (sl >= Limits::min) && (su <= Limits::max);
00107
00108 for (int i = n_p; i--; ) {
00109 if (sl - t_p[i].a * static_cast<double>(t_p[i].x.min()) < double_min)
00110 throw OutOfLimits("Int::linear");
00111 if (sl - t_p[i].a * static_cast<double>(t_p[i].x.min()) < Limits::min)
00112 is_ip = false;
00113 if (su - t_p[i].a * static_cast<double>(t_p[i].x.max()) > double_max)
00114 throw OutOfLimits("Int::linear");
00115 if (su - t_p[i].a * static_cast<double>(t_p[i].x.max()) > Limits::max)
00116 is_ip = false;
00117 }
00118 for (int i = n_n; i--; ) {
00119 if (sl + t_n[i].a * static_cast<double>(t_n[i].x.min()) < double_min)
00120 throw OutOfLimits("Int::linear");
00121 if (sl + t_n[i].a * static_cast<double>(t_n[i].x.min()) < Limits::min)
00122 is_ip = false;
00123 if (su + t_n[i].a * static_cast<double>(t_n[i].x.max()) > double_max)
00124 throw OutOfLimits("Int::linear");
00125 if (su + t_n[i].a * static_cast<double>(t_n[i].x.max()) > Limits::max)
00126 is_ip = false;
00127 }
00128 return is_ip;
00129 }
00130
00135 template <class Val, class View>
00136 forceinline void
00137 post_nary(Space* home,
00138 ViewArray<View>& x, ViewArray<View>& y, IntRelType r, Val c) {
00139 switch (r) {
00140 case IRT_EQ:
00141 GECODE_ES_FAIL(home,(Eq<Val,View,View >::post(home,x,y,c)));
00142 break;
00143 case IRT_NQ:
00144 GECODE_ES_FAIL(home,(Nq<Val,View,View >::post(home,x,y,c)));
00145 break;
00146 case IRT_LQ:
00147 GECODE_ES_FAIL(home,(Lq<Val,View,View >::post(home,x,y,c)));
00148 break;
00149 default: GECODE_NEVER;
00150 }
00151 }
00152
00153
00155 #define GECODE_INT_PL_BIN(CLASS) \
00156 switch (n_p) { \
00157 case 2: \
00158 GECODE_ES_FAIL(home,(CLASS<int,IntView,IntView>::post \
00159 (home,t_p[0].x,t_p[1].x,c))); \
00160 break; \
00161 case 1: \
00162 GECODE_ES_FAIL(home,(CLASS<int,IntView,MinusView>::post \
00163 (home,t_p[0].x,t_n[0].x,c))); \
00164 break; \
00165 case 0: \
00166 GECODE_ES_FAIL(home,(CLASS<int,MinusView,MinusView>::post \
00167 (home,t_n[0].x,t_n[1].x,c))); \
00168 break; \
00169 default: GECODE_NEVER; \
00170 }
00171
00173 #define GECODE_INT_PL_TER(CLASS) \
00174 switch (n_p) { \
00175 case 3: \
00176 GECODE_ES_FAIL(home,(CLASS<int,IntView,IntView,IntView>::post \
00177 (home,t_p[0].x,t_p[1].x,t_p[2].x,c))); \
00178 break; \
00179 case 2: \
00180 GECODE_ES_FAIL(home,(CLASS<int,IntView,IntView,MinusView>::post \
00181 (home,t_p[0].x,t_p[1].x,t_n[0].x,c))); \
00182 break; \
00183 case 1: \
00184 GECODE_ES_FAIL(home,(CLASS<int,IntView,MinusView,MinusView>::post \
00185 (home,t_p[0].x,t_n[0].x,t_n[1].x,c))); \
00186 break; \
00187 case 0: \
00188 GECODE_ES_FAIL(home,(CLASS<int,MinusView,MinusView,MinusView>::post \
00189 (home,t_n[0].x,t_n[1].x,t_n[2].x,c))); \
00190 break; \
00191 default: GECODE_NEVER; \
00192 }
00193
00194 void
00195 post(Space* home, Term<IntView>* t, int n, IntRelType r, int c,
00196 IntConLevel icl, PropKind) {
00197
00198 Limits::check(c,"Int::linear");
00199
00200 double d = c;
00201
00202 eliminate(t,n,d);
00203
00204 Term<IntView> *t_p, *t_n;
00205 int n_p, n_n;
00206 bool is_unit = normalize<IntView>(t,n,t_p,n_p,t_n,n_n);
00207
00208 rewrite(r,d,t_p,n_p,t_n,n_n);
00209
00210 if (n == 0) {
00211 switch (r) {
00212 case IRT_EQ: if (d != 0.0) home->fail(); break;
00213 case IRT_NQ: if (d == 0.0) home->fail(); break;
00214 case IRT_LQ: if (d < 0.0) home->fail(); break;
00215 default: GECODE_NEVER;
00216 }
00217 return;
00218 }
00219
00220 if (n == 1) {
00221 if (n_p == 1) {
00222 DoubleScaleView y(t_p[0].a,t_p[0].x);
00223 switch (r) {
00224 case IRT_EQ: GECODE_ME_FAIL(home,y.eq(home,d)); break;
00225 case IRT_NQ: GECODE_ME_FAIL(home,y.nq(home,d)); break;
00226 case IRT_LQ: GECODE_ME_FAIL(home,y.lq(home,d)); break;
00227 default: GECODE_NEVER;
00228 }
00229 } else {
00230 DoubleScaleView y(t_n[0].a,t_n[0].x);
00231 switch (r) {
00232 case IRT_EQ: GECODE_ME_FAIL(home,y.eq(home,-d)); break;
00233 case IRT_NQ: GECODE_ME_FAIL(home,y.nq(home,-d)); break;
00234 case IRT_LQ: GECODE_ME_FAIL(home,y.gq(home,-d)); break;
00235 default: GECODE_NEVER;
00236 }
00237 }
00238 return;
00239 }
00240
00241 bool is_ip = precision(t_p,n_p,t_n,n_n,d);
00242
00243 if (is_unit && is_ip && (icl != ICL_DOM)) {
00244
00245 c = static_cast<int>(d);
00246 if (n == 2) {
00247 switch (r) {
00248 case IRT_EQ: GECODE_INT_PL_BIN(EqBin); break;
00249 case IRT_NQ: GECODE_INT_PL_BIN(NqBin); break;
00250 case IRT_LQ: GECODE_INT_PL_BIN(LqBin); break;
00251 default: GECODE_NEVER;
00252 }
00253 } else if (n == 3) {
00254 switch (r) {
00255 case IRT_EQ: GECODE_INT_PL_TER(EqTer); break;
00256 case IRT_NQ: GECODE_INT_PL_TER(NqTer); break;
00257 case IRT_LQ: GECODE_INT_PL_TER(LqTer); break;
00258 default: GECODE_NEVER;
00259 }
00260 } else {
00261 ViewArray<IntView> x(home,n_p);
00262 for (int i = n_p; i--; )
00263 x[i] = t_p[i].x;
00264 ViewArray<IntView> y(home,n_n);
00265 for (int i = n_n; i--; )
00266 y[i] = t_n[i].x;
00267 post_nary<int,IntView>(home,x,y,r,c);
00268 }
00269 } else if (is_ip) {
00270
00271 c = static_cast<int>(d);
00272 ViewArray<IntScaleView> x(home,n_p);
00273 for (int i = n_p; i--; )
00274 x[i].init(t_p[i].a,t_p[i].x);
00275 ViewArray<IntScaleView> y(home,n_n);
00276 for (int i = n_n; i--; )
00277 y[i].init(t_n[i].a,t_n[i].x);
00278 if ((icl == ICL_DOM) && (r == IRT_EQ)) {
00279 GECODE_ES_FAIL(home,(DomEq<int,IntScaleView>::post(home,x,y,c)));
00280 } else {
00281 post_nary<int,IntScaleView>(home,x,y,r,c);
00282 }
00283 } else {
00284
00285 ViewArray<DoubleScaleView> x(home,n_p);
00286 for (int i = n_p; i--; )
00287 x[i].init(t_p[i].a,t_p[i].x);
00288 ViewArray<DoubleScaleView> y(home,n_n);
00289 for (int i = n_n; i--; )
00290 y[i].init(t_n[i].a,t_n[i].x);
00291 if ((icl == ICL_DOM) && (r == IRT_EQ)) {
00292 GECODE_ES_FAIL(home,(DomEq<double,DoubleScaleView>::post(home,x,y,d)));
00293 } else {
00294 post_nary<double,DoubleScaleView>(home,x,y,r,d);
00295 }
00296 }
00297 }
00298
00299 #undef GECODE_INT_PL_BIN
00300 #undef GECODE_INT_PL_TER
00301
00302
00307 template <class Val, class View>
00308 forceinline void
00309 post_nary(Space* home,
00310 ViewArray<View>& x, ViewArray<View>& y,
00311 IntRelType r, Val c, BoolView b) {
00312 switch (r) {
00313 case IRT_EQ:
00314 GECODE_ES_FAIL(home,(ReEq<Val,View,View,BoolView>::post(home,x,y,c,b)));
00315 break;
00316 case IRT_NQ:
00317 {
00318 NegBoolView n(b);
00319 GECODE_ES_FAIL(home,(ReEq<Val,View,View,NegBoolView>::post
00320 (home,x,y,c,n)));
00321 }
00322 break;
00323 case IRT_LQ:
00324 GECODE_ES_FAIL(home,(ReLq<Val,View,View>::post(home,x,y,c,b)));
00325 break;
00326 default: GECODE_NEVER;
00327 }
00328 }
00329
00330 void
00331 post(Space* home,
00332 Term<IntView>* t, int n, IntRelType r, int c, BoolView b,
00333 IntConLevel,PropKind) {
00334
00335 Limits::check(c,"Int::linear");
00336
00337 double d = c;
00338
00339 eliminate(t,n,d);
00340
00341 Term<IntView> *t_p, *t_n;
00342 int n_p, n_n;
00343 bool is_unit = normalize<IntView>(t,n,t_p,n_p,t_n,n_n);
00344
00345 rewrite(r,d,t_p,n_p,t_n,n_n);
00346
00347 if (n == 0) {
00348 bool fail = false;
00349 switch (r) {
00350 case IRT_EQ: fail = (d != 0.0); break;
00351 case IRT_NQ: fail = (d == 0.0); break;
00352 case IRT_LQ: fail = (0.0 > d); break;
00353 default: GECODE_NEVER;
00354 }
00355 if ((fail ? b.zero(home) : b.one(home)) == ME_INT_FAILED)
00356 home->fail();
00357 return;
00358 }
00359
00360 bool is_ip = precision(t_p,n_p,t_n,n_n,d);
00361
00362 if (is_unit && is_ip) {
00363 c = static_cast<int>(d);
00364 if (n == 1) {
00365 switch (r) {
00366 case IRT_EQ:
00367 if (n_p == 1) {
00368 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,BoolView>::post
00369 (home,t_p[0].x,c,b)));
00370 } else {
00371 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,BoolView>::post
00372 (home,t_n[0].x,-c,b)));
00373 }
00374 break;
00375 case IRT_NQ:
00376 {
00377 NegBoolView nb(b);
00378 if (n_p == 1) {
00379 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,NegBoolView>::post
00380 (home,t_p[0].x,c,nb)));
00381 } else {
00382 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,NegBoolView>::post
00383 (home,t_n[0].x,-c,nb)));
00384 }
00385 }
00386 break;
00387 case IRT_LQ:
00388 if (n_p == 1) {
00389 GECODE_ES_FAIL(home,(Rel::ReLqInt<IntView,BoolView>::post
00390 (home,t_p[0].x,c,b)));
00391 } else {
00392 NegBoolView nb(b);
00393 GECODE_ES_FAIL(home,(Rel::ReLqInt<IntView,NegBoolView>::post
00394 (home,t_n[0].x,-c-1,nb)));
00395 }
00396 break;
00397 default: GECODE_NEVER;
00398 }
00399 } else if (n == 2) {
00400 switch (r) {
00401 case IRT_EQ:
00402 switch (n_p) {
00403 case 2:
00404 GECODE_ES_FAIL(home,(ReEqBin<int,IntView,IntView,BoolView>::post
00405 (home,t_p[0].x,t_p[1].x,c,b)));
00406 break;
00407 case 1:
00408 GECODE_ES_FAIL(home,(ReEqBin<int,IntView,MinusView,BoolView>::post
00409 (home,t_p[0].x,t_n[0].x,c,b)));
00410 break;
00411 case 0:
00412 GECODE_ES_FAIL(home,(ReEqBin<int,IntView,IntView,BoolView>::post
00413 (home,t_n[0].x,t_n[1].x,-c,b)));
00414 break;
00415 default: GECODE_NEVER;
00416 }
00417 break;
00418 case IRT_NQ:
00419 {
00420 NegBoolView nb(b);
00421 switch (n_p) {
00422 case 2:
00423 GECODE_ES_FAIL(home,
00424 (ReEqBin<int,IntView,IntView,NegBoolView>::post
00425 (home,t_p[0].x,t_p[1].x,c,nb)));
00426 break;
00427 case 1:
00428 GECODE_ES_FAIL(home,
00429 (ReEqBin<int,IntView,MinusView,NegBoolView>::post
00430 (home,t_p[0].x,t_n[0].x,c,b)));
00431 break;
00432 case 0:
00433 GECODE_ES_FAIL(home,
00434 (ReEqBin<int,IntView,IntView,NegBoolView>::post
00435 (home,t_p[0].x,t_p[1].x,-c,b)));
00436 break;
00437 default: GECODE_NEVER;
00438 }
00439 }
00440 break;
00441 case IRT_LQ:
00442 switch (n_p) {
00443 case 2:
00444 GECODE_ES_FAIL(home,(ReLqBin<int,IntView,IntView>::post
00445 (home,t_p[0].x,t_p[1].x,c,b)));
00446 break;
00447 case 1:
00448 GECODE_ES_FAIL(home,(ReLqBin<int,IntView,MinusView>::post
00449 (home,t_p[0].x,t_n[0].x,c,b)));
00450 break;
00451 case 0:
00452 GECODE_ES_FAIL(home,(ReLqBin<int,MinusView,MinusView>::post
00453 (home,t_n[0].x,t_n[1].x,c,b)));
00454 break;
00455 default: GECODE_NEVER;
00456 }
00457 break;
00458 default: GECODE_NEVER;
00459 }
00460 } else {
00461 ViewArray<IntView> x(home,n_p);
00462 for (int i = n_p; i--; )
00463 x[i] = t_p[i].x;
00464 ViewArray<IntView> y(home,n_n);
00465 for (int i = n_n; i--; )
00466 y[i] = t_n[i].x;
00467 post_nary<int,IntView>(home,x,y,r,c,b);
00468 }
00469 } else if (is_ip) {
00470
00471 c = static_cast<int>(d);
00472 ViewArray<IntScaleView> x(home,n_p);
00473 for (int i = n_p; i--; )
00474 x[i].init(t_p[i].a,t_p[i].x);
00475 ViewArray<IntScaleView> y(home,n_n);
00476 for (int i = n_n; i--; )
00477 y[i].init(t_n[i].a,t_n[i].x);
00478 post_nary<int,IntScaleView>(home,x,y,r,c,b);
00479 } else {
00480
00481 ViewArray<DoubleScaleView> x(home,n_p);
00482 for (int i = n_p; i--; )
00483 x[i].init(t_p[i].a,t_p[i].x);
00484 ViewArray<DoubleScaleView> y(home,n_n);
00485 for (int i = n_n; i--; )
00486 y[i].init(t_n[i].a,t_n[i].x);
00487 post_nary<double,DoubleScaleView>(home,x,y,r,d,b);
00488 }
00489 }
00490
00491 }}}
00492
00493