gecode » int » linear

00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 00002 /* 00003 * Main authors: 00004 * Christian Schulte <schulte@gecode.org> 00005 * 00006 * Copyright: 00007 * Christian Schulte, 2002 00008 * 00009 * Last modified: 00010 * $Date: 2009-11-04 17:06:58 +0100 (Wed, 04 Nov 2009) $ by $Author: tack $ 00011 * $Revision: 10046 $ 00012 * 00013 * This file is part of Gecode, the generic constraint 00014 * development environment: 00015 * http://www.gecode.org 00016 * 00017 * Permission is hereby granted, free of charge, to any person obtaining 00018 * a copy of this software and associated documentation files (the 00019 * "Software"), to deal in the Software without restriction, including 00020 * without limitation the rights to use, copy, modify, merge, publish, 00021 * distribute, sublicense, and/or sell copies of the Software, and to 00022 * permit persons to whom the Software is furnished to do so, subject to 00023 * the following conditions: 00024 * 00025 * The above copyright notice and this permission notice shall be 00026 * included in all copies or substantial portions of the Software. 00027 * 00028 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00029 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00030 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00031 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00032 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00033 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00034 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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++; /* fall through */ 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(Home 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,MinusView(t_n[0].x),c))); \ 00164 break; \ 00165 case 0: \ 00166 GECODE_ES_FAIL(home,(CLASS<int,MinusView,MinusView>::post \ 00167 (home,MinusView(t_n[0].x),MinusView(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, \ 00182 MinusView(t_n[0].x),c))); \ 00183 break; \ 00184 case 1: \ 00185 GECODE_ES_FAIL(home,(CLASS<int,IntView,MinusView,MinusView>::post \ 00186 (home,t_p[0].x, \ 00187 MinusView(t_n[0].x),MinusView(t_n[1].x),c))); \ 00188 break; \ 00189 case 0: \ 00190 GECODE_ES_FAIL(home,(CLASS<int,MinusView,MinusView,MinusView>::post \ 00191 (home,MinusView(t_n[0].x), \ 00192 MinusView(t_n[1].x),MinusView(t_n[2].x),c))); \ 00193 break; \ 00194 default: GECODE_NEVER; \ 00195 } 00196 00197 void 00198 post(Home home, Term<IntView>* t, int n, IntRelType r, int c, 00199 IntConLevel icl) { 00200 00201 Limits::check(c,"Int::linear"); 00202 00203 double d = c; 00204 00205 eliminate(t,n,d); 00206 00207 Term<IntView> *t_p, *t_n; 00208 int n_p, n_n; 00209 bool is_unit = normalize<IntView>(t,n,t_p,n_p,t_n,n_n); 00210 00211 rewrite(r,d,t_p,n_p,t_n,n_n); 00212 00213 if (n == 0) { 00214 switch (r) { 00215 case IRT_EQ: if (d != 0.0) home.fail(); break; 00216 case IRT_NQ: if (d == 0.0) home.fail(); break; 00217 case IRT_LQ: if (d < 0.0) home.fail(); break; 00218 default: GECODE_NEVER; 00219 } 00220 return; 00221 } 00222 00223 if (n == 1) { 00224 if (n_p == 1) { 00225 DoubleScaleView y(t_p[0].a,t_p[0].x); 00226 switch (r) { 00227 case IRT_EQ: GECODE_ME_FAIL(home,y.eq(home,d)); break; 00228 case IRT_NQ: GECODE_ME_FAIL(home,y.nq(home,d)); break; 00229 case IRT_LQ: GECODE_ME_FAIL(home,y.lq(home,d)); break; 00230 default: GECODE_NEVER; 00231 } 00232 } else { 00233 DoubleScaleView y(t_n[0].a,t_n[0].x); 00234 switch (r) { 00235 case IRT_EQ: GECODE_ME_FAIL(home,y.eq(home,-d)); break; 00236 case IRT_NQ: GECODE_ME_FAIL(home,y.nq(home,-d)); break; 00237 case IRT_LQ: GECODE_ME_FAIL(home,y.gq(home,-d)); break; 00238 default: GECODE_NEVER; 00239 } 00240 } 00241 return; 00242 } 00243 00244 bool is_ip = precision(t_p,n_p,t_n,n_n,d); 00245 00246 if (is_unit && is_ip && (icl != ICL_DOM)) { 00247 // Unit coefficients with integer precision 00248 c = static_cast<int>(d); 00249 if (n == 2) { 00250 switch (r) { 00251 case IRT_EQ: GECODE_INT_PL_BIN(EqBin); break; 00252 case IRT_NQ: GECODE_INT_PL_BIN(NqBin); break; 00253 case IRT_LQ: GECODE_INT_PL_BIN(LqBin); break; 00254 default: GECODE_NEVER; 00255 } 00256 } else if (n == 3) { 00257 switch (r) { 00258 case IRT_EQ: GECODE_INT_PL_TER(EqTer); break; 00259 case IRT_NQ: GECODE_INT_PL_TER(NqTer); break; 00260 case IRT_LQ: GECODE_INT_PL_TER(LqTer); break; 00261 default: GECODE_NEVER; 00262 } 00263 } else { 00264 ViewArray<IntView> x(home,n_p); 00265 for (int i = n_p; i--; ) 00266 x[i] = t_p[i].x; 00267 ViewArray<IntView> y(home,n_n); 00268 for (int i = n_n; i--; ) 00269 y[i] = t_n[i].x; 00270 post_nary<int,IntView>(home,x,y,r,c); 00271 } 00272 } else if (is_ip) { 00273 // Arbitrary coefficients with integer precision 00274 c = static_cast<int>(d); 00275 ViewArray<IntScaleView> x(home,n_p); 00276 for (int i = n_p; i--; ) 00277 x[i].init(t_p[i].a,t_p[i].x); 00278 ViewArray<IntScaleView> y(home,n_n); 00279 for (int i = n_n; i--; ) 00280 y[i].init(t_n[i].a,t_n[i].x); 00281 if ((icl == ICL_DOM) && (r == IRT_EQ)) { 00282 GECODE_ES_FAIL(home,(DomEq<int,IntScaleView>::post(home,x,y,c))); 00283 } else { 00284 post_nary<int,IntScaleView>(home,x,y,r,c); 00285 } 00286 } else { 00287 // Arbitrary coefficients with double precision 00288 ViewArray<DoubleScaleView> x(home,n_p); 00289 for (int i = n_p; i--; ) 00290 x[i].init(t_p[i].a,t_p[i].x); 00291 ViewArray<DoubleScaleView> y(home,n_n); 00292 for (int i = n_n; i--; ) 00293 y[i].init(t_n[i].a,t_n[i].x); 00294 if ((icl == ICL_DOM) && (r == IRT_EQ)) { 00295 GECODE_ES_FAIL(home,(DomEq<double,DoubleScaleView>::post(home,x,y,d))); 00296 } else { 00297 post_nary<double,DoubleScaleView>(home,x,y,r,d); 00298 } 00299 } 00300 } 00301 00302 #undef GECODE_INT_PL_BIN 00303 #undef GECODE_INT_PL_TER 00304 00305 00310 template<class Val, class View> 00311 forceinline void 00312 post_nary(Home home, 00313 ViewArray<View>& x, ViewArray<View>& y, 00314 IntRelType r, Val c, BoolView b) { 00315 switch (r) { 00316 case IRT_EQ: 00317 GECODE_ES_FAIL(home,(ReEq<Val,View,View,BoolView>::post(home,x,y,c,b))); 00318 break; 00319 case IRT_NQ: 00320 { 00321 NegBoolView n(b); 00322 GECODE_ES_FAIL(home,(ReEq<Val,View,View,NegBoolView>::post 00323 (home,x,y,c,n))); 00324 } 00325 break; 00326 case IRT_LQ: 00327 GECODE_ES_FAIL(home,(ReLq<Val,View,View>::post(home,x,y,c,b))); 00328 break; 00329 default: GECODE_NEVER; 00330 } 00331 } 00332 00333 void 00334 post(Home home, 00335 Term<IntView>* t, int n, IntRelType r, int c, BoolView b, 00336 IntConLevel) { 00337 00338 Limits::check(c,"Int::linear"); 00339 00340 double d = c; 00341 00342 eliminate(t,n,d); 00343 00344 Term<IntView> *t_p, *t_n; 00345 int n_p, n_n; 00346 bool is_unit = normalize<IntView>(t,n,t_p,n_p,t_n,n_n); 00347 00348 rewrite(r,d,t_p,n_p,t_n,n_n); 00349 00350 if (n == 0) { 00351 bool fail = false; 00352 switch (r) { 00353 case IRT_EQ: fail = (d != 0.0); break; 00354 case IRT_NQ: fail = (d == 0.0); break; 00355 case IRT_LQ: fail = (0.0 > d); break; 00356 default: GECODE_NEVER; 00357 } 00358 if ((fail ? b.zero(home) : b.one(home)) == ME_INT_FAILED) 00359 home.fail(); 00360 return; 00361 } 00362 00363 bool is_ip = precision(t_p,n_p,t_n,n_n,d); 00364 00365 if (is_unit && is_ip) { 00366 c = static_cast<int>(d); 00367 if (n == 1) { 00368 switch (r) { 00369 case IRT_EQ: 00370 if (n_p == 1) { 00371 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,BoolView>::post 00372 (home,t_p[0].x,c,b))); 00373 } else { 00374 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,BoolView>::post 00375 (home,t_n[0].x,-c,b))); 00376 } 00377 break; 00378 case IRT_NQ: 00379 { 00380 NegBoolView nb(b); 00381 if (n_p == 1) { 00382 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,NegBoolView>::post 00383 (home,t_p[0].x,c,nb))); 00384 } else { 00385 GECODE_ES_FAIL(home,(Rel::ReEqBndInt<IntView,NegBoolView>::post 00386 (home,t_n[0].x,-c,nb))); 00387 } 00388 } 00389 break; 00390 case IRT_LQ: 00391 if (n_p == 1) { 00392 GECODE_ES_FAIL(home,(Rel::ReLqInt<IntView,BoolView>::post 00393 (home,t_p[0].x,c,b))); 00394 } else { 00395 NegBoolView nb(b); 00396 GECODE_ES_FAIL(home,(Rel::ReLqInt<IntView,NegBoolView>::post 00397 (home,t_n[0].x,-c-1,nb))); 00398 } 00399 break; 00400 default: GECODE_NEVER; 00401 } 00402 } else if (n == 2) { 00403 switch (r) { 00404 case IRT_EQ: 00405 switch (n_p) { 00406 case 2: 00407 GECODE_ES_FAIL(home,(ReEqBin<int,IntView,IntView,BoolView>::post 00408 (home,t_p[0].x,t_p[1].x,c,b))); 00409 break; 00410 case 1: 00411 GECODE_ES_FAIL(home,(ReEqBin<int,IntView,MinusView,BoolView>::post 00412 (home,t_p[0].x,MinusView(t_n[0].x),c,b))); 00413 break; 00414 case 0: 00415 GECODE_ES_FAIL(home,(ReEqBin<int,IntView,IntView,BoolView>::post 00416 (home,t_n[0].x,t_n[1].x,-c,b))); 00417 break; 00418 default: GECODE_NEVER; 00419 } 00420 break; 00421 case IRT_NQ: 00422 { 00423 NegBoolView nb(b); 00424 switch (n_p) { 00425 case 2: 00426 GECODE_ES_FAIL(home, 00427 (ReEqBin<int,IntView,IntView,NegBoolView>::post 00428 (home,t_p[0].x,t_p[1].x,c,nb))); 00429 break; 00430 case 1: 00431 GECODE_ES_FAIL(home, 00432 (ReEqBin<int,IntView,MinusView,NegBoolView>::post 00433 (home,t_p[0].x,MinusView(t_n[0].x),c, 00434 NegBoolView(b)))); 00435 break; 00436 case 0: 00437 GECODE_ES_FAIL(home, 00438 (ReEqBin<int,IntView,IntView,NegBoolView>::post 00439 (home,t_p[0].x,t_p[1].x,-c,NegBoolView(b)))); 00440 break; 00441 default: GECODE_NEVER; 00442 } 00443 } 00444 break; 00445 case IRT_LQ: 00446 switch (n_p) { 00447 case 2: 00448 GECODE_ES_FAIL(home,(ReLqBin<int,IntView,IntView>::post 00449 (home,t_p[0].x,t_p[1].x,c,b))); 00450 break; 00451 case 1: 00452 GECODE_ES_FAIL(home,(ReLqBin<int,IntView,MinusView>::post 00453 (home,t_p[0].x,MinusView(t_n[0].x),c,b))); 00454 break; 00455 case 0: 00456 GECODE_ES_FAIL(home,(ReLqBin<int,MinusView,MinusView>::post 00457 (home,MinusView(t_n[0].x), 00458 MinusView(t_n[1].x),c,b))); 00459 break; 00460 default: GECODE_NEVER; 00461 } 00462 break; 00463 default: GECODE_NEVER; 00464 } 00465 } else { 00466 ViewArray<IntView> x(home,n_p); 00467 for (int i = n_p; i--; ) 00468 x[i] = t_p[i].x; 00469 ViewArray<IntView> y(home,n_n); 00470 for (int i = n_n; i--; ) 00471 y[i] = t_n[i].x; 00472 post_nary<int,IntView>(home,x,y,r,c,b); 00473 } 00474 } else if (is_ip) { 00475 // Arbitrary coefficients with integer precision 00476 c = static_cast<int>(d); 00477 ViewArray<IntScaleView> x(home,n_p); 00478 for (int i = n_p; i--; ) 00479 x[i].init(t_p[i].a,t_p[i].x); 00480 ViewArray<IntScaleView> y(home,n_n); 00481 for (int i = n_n; i--; ) 00482 y[i].init(t_n[i].a,t_n[i].x); 00483 post_nary<int,IntScaleView>(home,x,y,r,c,b); 00484 } else { 00485 // Arbitrary coefficients with double precision 00486 ViewArray<DoubleScaleView> x(home,n_p); 00487 for (int i = n_p; i--; ) 00488 x[i].init(t_p[i].a,t_p[i].x); 00489 ViewArray<DoubleScaleView> y(home,n_n); 00490 for (int i = n_n; i--; ) 00491 y[i].init(t_n[i].a,t_n[i].x); 00492 post_nary<double,DoubleScaleView>(home,x,y,r,d,b); 00493 } 00494 } 00495 00496 }}} 00497 00498 // STATISTICS: int-post