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, 2003 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 <gecode/int/linear/int-noview.hpp> 00039 00040 namespace Gecode { namespace Int { namespace Linear { 00041 00046 template<class P, class N> 00047 forceinline bool 00048 isunit(ViewArray<P>&, ViewArray<N>&) { return false; } 00049 template<> 00050 forceinline bool 00051 isunit(ViewArray<IntView>&, ViewArray<IntView>&) { return true; } 00052 template<> 00053 forceinline bool 00054 isunit(ViewArray<IntView>&, ViewArray<NoView>&) { return true; } 00055 template<> 00056 forceinline bool 00057 isunit(ViewArray<NoView>&, ViewArray<IntView>&) { return true; } 00058 00059 /* 00060 * Linear propagators 00061 * 00062 */ 00063 template<class Val, class P, class N, PropCond pc> 00064 forceinline 00065 Lin<Val,P,N,pc>::Lin(Home home, ViewArray<P>& x0, ViewArray<N>& y0, Val c0) 00066 : Propagator(home), x(x0), y(y0), c(c0) { 00067 x.subscribe(home,*this,pc); 00068 y.subscribe(home,*this,pc); 00069 } 00070 00071 template<class Val, class P, class N, PropCond pc> 00072 forceinline 00073 Lin<Val,P,N,pc>::Lin(Space& home, bool share, Lin<Val,P,N,pc>& p) 00074 : Propagator(home,share,p), c(p.c) { 00075 x.update(home,share,p.x); 00076 y.update(home,share,p.y); 00077 } 00078 00079 template<class Val, class P, class N, PropCond pc> 00080 PropCost 00081 Lin<Val,P,N,pc>::cost(const Space&, const ModEventDelta&) const { 00082 return PropCost::linear(PropCost::LO, x.size()+y.size()); 00083 } 00084 00085 template<class Val, class P, class N, PropCond pc> 00086 forceinline size_t 00087 Lin<Val,P,N,pc>::dispose(Space& home) { 00088 assert(!home.failed()); 00089 x.cancel(home,*this,pc); 00090 y.cancel(home,*this,pc); 00091 (void) Propagator::dispose(home); 00092 return sizeof(*this); 00093 } 00094 00095 /* 00096 * Reified linear propagators 00097 * 00098 */ 00099 template<class Val, class P, class N, PropCond pc, class Ctrl> 00100 forceinline 00101 ReLin<Val,P,N,pc,Ctrl>::ReLin 00102 (Home home, ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b0) 00103 : Lin<Val,P,N,pc>(home,x,y,c), b(b0) { 00104 b.subscribe(home,*this,PC_INT_VAL); 00105 } 00106 00107 template<class Val, class P, class N, PropCond pc, class Ctrl> 00108 forceinline 00109 ReLin<Val,P,N,pc,Ctrl>::ReLin 00110 (Space& home, bool share, ReLin<Val,P,N,pc,Ctrl>& p) 00111 : Lin<Val,P,N,pc>(home,share,p) { 00112 b.update(home,share,p.b); 00113 } 00114 00115 template<class Val, class P, class N, PropCond pc, class Ctrl> 00116 forceinline size_t 00117 ReLin<Val,P,N,pc,Ctrl>::dispose(Space& home) { 00118 assert(!home.failed()); 00119 b.cancel(home,*this,PC_BOOL_VAL); 00120 (void) Lin<Val,P,N,pc>::dispose(home); 00121 return sizeof(*this); 00122 } 00123 00124 /* 00125 * Computing bounds 00126 * 00127 */ 00128 00129 template<class Val, class View> 00130 void 00131 bounds_p(ModEventDelta med, ViewArray<View>& x, Val& c, Val& sl, Val& su) { 00132 int n = x.size(); 00133 if (IntView::me(med) == ME_INT_VAL) { 00134 for (int i = n; i--; ) { 00135 Val m = x[i].min(); 00136 if (x[i].assigned()) { 00137 c -= m; x[i] = x[--n]; 00138 } else { 00139 sl -= m; su -= x[i].max(); 00140 } 00141 } 00142 x.size(n); 00143 } else { 00144 for (int i = n; i--; ) { 00145 sl -= x[i].min(); su -= x[i].max(); 00146 } 00147 } 00148 } 00149 00150 template<class Val, class View> 00151 void 00152 bounds_n(ModEventDelta med, ViewArray<View>& y, Val& c, Val& sl, Val& su) { 00153 int n = y.size(); 00154 if (IntView::me(med) == ME_INT_VAL) { 00155 for (int i = n; i--; ) { 00156 Val m = y[i].max(); 00157 if (y[i].assigned()) { 00158 c += m; y[i] = y[--n]; 00159 } else { 00160 sl += m; su += y[i].min(); 00161 } 00162 } 00163 y.size(n); 00164 } else { 00165 for (int i = n; i--; ) { 00166 sl += y[i].max(); su += y[i].min(); 00167 } 00168 } 00169 } 00170 00171 00172 template<class Val, class P, class N> 00173 ExecStatus 00174 prop_bnd(Space& home, ModEventDelta med, Propagator& p, 00175 ViewArray<P>& x, ViewArray<N>& y, Val& c) { 00176 // Eliminate singletons 00177 Val sl = 0; 00178 Val su = 0; 00179 00180 bounds_p<Val,P>(med, x, c, sl, su); 00181 bounds_n<Val,N>(med, y, c, sl, su); 00182 00183 if ((IntView::me(med) == ME_INT_VAL) && ((x.size() + y.size()) <= 1)) { 00184 if (x.size() == 1) { 00185 GECODE_ME_CHECK(x[0].eq(home,c)); 00186 return ES_SUBSUMED(p,sizeof(p)); 00187 } 00188 if (y.size() == 1) { 00189 GECODE_ME_CHECK(y[0].eq(home,-c)); 00190 return ES_SUBSUMED(p,sizeof(p)); 00191 } 00192 return (c == static_cast<Val>(0)) ? 00193 ES_SUBSUMED(p,sizeof(p)) : ES_FAILED; 00194 } 00195 00196 sl += c; su += c; 00197 00198 const int mod_sl = 1; 00199 const int mod_su = 2; 00200 00201 int mod = mod_sl | mod_su; 00202 00203 do { 00204 if (mod & mod_sl) { 00205 mod -= mod_sl; 00206 // Propagate upper bound for positive variables 00207 for (int i = x.size(); i--; ) { 00208 const Val xi_max = x[i].max(); 00209 ModEvent me = x[i].lq(home,sl + x[i].min()); 00210 if (me_failed(me)) 00211 return ES_FAILED; 00212 if (me_modified(me)) { 00213 su += xi_max - x[i].max(); 00214 mod |= mod_su; 00215 } 00216 } 00217 // Propagate lower bound for negative variables 00218 for (int i = y.size(); i--; ) { 00219 const Val yi_min = y[i].min(); 00220 ModEvent me = y[i].gq(home,y[i].max() - sl); 00221 if (me_failed(me)) 00222 return ES_FAILED; 00223 if (me_modified(me)) { 00224 su += y[i].min() - yi_min; 00225 mod |= mod_su; 00226 } 00227 } 00228 } 00229 if (mod & mod_su) { 00230 mod -= mod_su; 00231 // Propagate lower bound for positive variables 00232 for (int i = x.size(); i--; ) { 00233 const Val xi_min = x[i].min(); 00234 ModEvent me = x[i].gq(home,su + x[i].max()); 00235 if (me_failed(me)) 00236 return ES_FAILED; 00237 if (me_modified(me)) { 00238 sl += xi_min - x[i].min(); 00239 mod |= mod_sl; 00240 } 00241 } 00242 // Propagate upper bound for negative variables 00243 for (int i = y.size(); i--; ) { 00244 const Val yi_max = y[i].max(); 00245 ModEvent me = y[i].lq(home,y[i].min() - su); 00246 if (me_failed(me)) 00247 return ES_FAILED; 00248 if (me_modified(me)) { 00249 sl += y[i].max() - yi_max; 00250 mod |= mod_sl; 00251 } 00252 } 00253 } 00254 } while (mod); 00255 00256 return (sl == su) ? ES_SUBSUMED(p,sizeof(p)) : ES_FIX; 00257 } 00258 00259 /* 00260 * Bound consistent linear equation 00261 * 00262 */ 00263 00264 template<class Val, class P, class N> 00265 forceinline 00266 Eq<Val,P,N>::Eq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) 00267 : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {} 00268 00269 template<class Val, class P, class N> 00270 ExecStatus 00271 Eq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) { 00272 ViewArray<NoView> nva; 00273 if (y.size() == 0) { 00274 (void) new (home) Eq<Val,P,NoView>(home,x,nva,c); 00275 } else if (x.size() == 0) { 00276 (void) new (home) Eq<Val,N,NoView>(home,y,nva,-c); 00277 } else { 00278 (void) new (home) Eq<Val,P,N>(home,x,y,c); 00279 } 00280 return ES_OK; 00281 } 00282 00283 00284 template<class Val, class P, class N> 00285 forceinline 00286 Eq<Val,P,N>::Eq(Space& home, bool share, Eq<Val,P,N>& p) 00287 : Lin<Val,P,N,PC_INT_BND>(home,share,p) {} 00288 00293 template<class Val, class P, class N> 00294 forceinline Actor* 00295 eqtobin(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) { 00296 return NULL; 00297 } 00298 template<class Val> 00299 forceinline Actor* 00300 eqtobin(Space& home, bool share, Propagator& p, 00301 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) { 00302 assert(x.size() == 2); 00303 return new (home) EqBin<Val,IntView,IntView> 00304 (home,share,p,x[0],x[1],c); 00305 } 00306 template<class Val> 00307 forceinline Actor* 00308 eqtobin(Space& home, bool share, Propagator& p, 00309 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) { 00310 assert(y.size() == 2); 00311 return new (home) EqBin<Val,IntView,IntView> 00312 (home,share,p,y[0],y[1],-c); 00313 } 00314 template<class Val> 00315 forceinline Actor* 00316 eqtobin(Space& home, bool share, Propagator& p, 00317 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) { 00318 if (x.size() == 2) 00319 return new (home) EqBin<Val,IntView,IntView> 00320 (home,share,p,x[0],x[1],c); 00321 if (x.size() == 1) 00322 return new (home) EqBin<Val,IntView,MinusView> 00323 (home,share,p,x[0],MinusView(y[0]),c); 00324 return new (home) EqBin<Val,IntView,IntView> 00325 (home,share,p,y[0],y[1],-c); 00326 } 00327 00332 template<class Val, class P, class N> 00333 forceinline Actor* 00334 eqtoter(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) { 00335 return NULL; 00336 } 00337 template<class Val> 00338 forceinline Actor* 00339 eqtoter(Space& home, bool share, Propagator& p, 00340 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) { 00341 assert(x.size() == 3); 00342 return new (home) EqTer<Val,IntView,IntView,IntView> 00343 (home,share,p,x[0],x[1],x[2],c); 00344 } 00345 template<class Val> 00346 forceinline Actor* 00347 eqtoter(Space& home, bool share, Propagator& p, 00348 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) { 00349 assert(y.size() == 3); 00350 return new (home) EqTer<Val,IntView,IntView,IntView> 00351 (home,share,p,y[0],y[1],y[2],-c); 00352 } 00353 template<class Val> 00354 forceinline Actor* 00355 eqtoter(Space& home, bool share, Propagator& p, 00356 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) { 00357 if (x.size() == 3) 00358 return new (home) EqTer<Val,IntView,IntView,IntView> 00359 (home,share,p,x[0],x[1],x[2],c); 00360 if (x.size() == 2) 00361 return new (home) EqTer<Val,IntView,IntView,MinusView> 00362 (home,share,p,x[0],x[1],MinusView(y[0]),c); 00363 if (x.size() == 1) 00364 return new (home) EqTer<Val,IntView,IntView,MinusView> 00365 (home,share,p,y[0],y[1],MinusView(x[0]),-c); 00366 return new (home) EqTer<Val,IntView,IntView,IntView> 00367 (home,share,p,y[0],y[1],y[2],-c); 00368 } 00369 00370 template<class Val, class P, class N> 00371 Actor* 00372 Eq<Val,P,N>::copy(Space& home, bool share) { 00373 if (isunit(x,y)) { 00374 // Check whether rewriting is possible 00375 if (x.size() + y.size() == 2) 00376 return eqtobin(home,share,*this,x,y,c); 00377 if (x.size() + y.size() == 3) 00378 return eqtoter(home,share,*this,x,y,c); 00379 } 00380 return new (home) Eq<Val,P,N>(home,share,*this); 00381 } 00382 00383 template<class Val, class P, class N> 00384 ExecStatus 00385 Eq<Val,P,N>::propagate(Space& home, const ModEventDelta& med) { 00386 return prop_bnd<Val,P,N>(home,med,*this,x,y,c); 00387 } 00388 00389 /* 00390 * Reified bound consistent linear equation 00391 * 00392 */ 00393 00394 template<class Val, class P, class N, class Ctrl> 00395 forceinline 00396 ReEq<Val,P,N,Ctrl>::ReEq(Home home, 00397 ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b) 00398 : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,x,y,c,b) {} 00399 00400 template<class Val, class P, class N, class Ctrl> 00401 ExecStatus 00402 ReEq<Val,P,N,Ctrl>::post(Home home, 00403 ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b) { 00404 ViewArray<NoView> nva; 00405 if (y.size() == 0) { 00406 (void) new (home) ReEq<Val,P,NoView,Ctrl>(home,x,nva,c,b); 00407 } else if (x.size() == 0) { 00408 (void) new (home) ReEq<Val,N,NoView,Ctrl>(home,y,nva,-c,b); 00409 } else { 00410 (void) new (home) ReEq<Val,P,N,Ctrl>(home,x,y,c,b); 00411 } 00412 return ES_OK; 00413 } 00414 00415 00416 template<class Val, class P, class N, class Ctrl> 00417 forceinline 00418 ReEq<Val,P,N,Ctrl>::ReEq(Space& home, bool share, ReEq<Val,P,N,Ctrl>& p) 00419 : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,share,p) {} 00420 00421 template<class Val, class P, class N, class Ctrl> 00422 Actor* 00423 ReEq<Val,P,N,Ctrl>::copy(Space& home, bool share) { 00424 return new (home) ReEq<Val,P,N,Ctrl>(home,share,*this); 00425 } 00426 00427 template<class Val, class P, class N, class Ctrl> 00428 ExecStatus 00429 ReEq<Val,P,N,Ctrl>::propagate(Space& home, const ModEventDelta& med) { 00430 if (b.zero()) 00431 GECODE_REWRITE(*this,(Nq<Val,P,N>::post(home(*this),x,y,c))); 00432 if (b.one()) 00433 GECODE_REWRITE(*this,(Eq<Val,P,N>::post(home(*this),x,y,c))); 00434 00435 Val sl = 0; 00436 Val su = 0; 00437 00438 bounds_p<Val,P>(med, x, c, sl, su); 00439 bounds_n<Val,N>(med, y, c, sl, su); 00440 00441 if ((-sl == c) && (-su == c)) { 00442 GECODE_ME_CHECK(b.one_none(home)); 00443 return ES_SUBSUMED(*this,sizeof(*this)); 00444 } 00445 if ((-sl > c) || (-su < c)) { 00446 GECODE_ME_CHECK(b.zero_none(home)); 00447 return ES_SUBSUMED(*this,home); 00448 } 00449 return ES_FIX; 00450 } 00451 00452 00453 /* 00454 * Domain consistent linear disequation 00455 * 00456 */ 00457 00458 template<class Val, class P, class N> 00459 forceinline 00460 Nq<Val,P,N>::Nq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) 00461 : Lin<Val,P,N,PC_INT_VAL>(home,x,y,c) {} 00462 00463 template<class Val, class P, class N> 00464 ExecStatus 00465 Nq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) { 00466 ViewArray<NoView> nva; 00467 if (y.size() == 0) { 00468 (void) new (home) Nq<Val,P,NoView>(home,x,nva,c); 00469 } else if (x.size() == 0) { 00470 (void) new (home) Nq<Val,N,NoView>(home,y,nva,-c); 00471 } else { 00472 (void) new (home) Nq<Val,P,N>(home,x,y,c); 00473 } 00474 return ES_OK; 00475 } 00476 00477 00478 template<class Val, class P, class N> 00479 forceinline 00480 Nq<Val,P,N>::Nq(Space& home, bool share, Nq<Val,P,N>& p) 00481 : Lin<Val,P,N,PC_INT_VAL>(home,share,p) {} 00482 00487 template<class Val, class P, class N> 00488 forceinline Actor* 00489 nqtobin(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) { 00490 return NULL; 00491 } 00492 template<class Val> 00493 forceinline Actor* 00494 nqtobin(Space& home, bool share, Propagator& p, 00495 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) { 00496 assert(x.size() == 2); 00497 return new (home) NqBin<Val,IntView,IntView> 00498 (home,share,p,x[0],x[1],c); 00499 } 00500 template<class Val> 00501 forceinline Actor* 00502 nqtobin(Space& home, bool share, Propagator& p, 00503 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) { 00504 assert(y.size() == 2); 00505 return new (home) NqBin<Val,IntView,IntView> 00506 (home,share,p,y[0],y[1],-c); 00507 } 00508 template<class Val> 00509 forceinline Actor* 00510 nqtobin(Space& home, bool share, Propagator& p, 00511 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) { 00512 if (x.size() == 2) 00513 return new (home) NqBin<Val,IntView,IntView> 00514 (home,share,p,x[0],x[1],c); 00515 if (x.size() == 1) 00516 return new (home) NqBin<Val,IntView,MinusView> 00517 (home,share,p,x[0],MinusView(y[0]),c); 00518 return new (home) NqBin<Val,IntView,IntView> 00519 (home,share,p,y[0],y[1],-c); 00520 } 00521 00526 template<class Val, class P, class N> 00527 forceinline Actor* 00528 nqtoter(Space&, bool, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) { 00529 return NULL; 00530 } 00531 template<class Val> 00532 forceinline Actor* 00533 nqtoter(Space& home, bool share, Propagator& p, 00534 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) { 00535 assert(x.size() == 3); 00536 return new (home) NqTer<Val,IntView,IntView,IntView> 00537 (home,share,p,x[0],x[1],x[2],c); 00538 } 00539 template<class Val> 00540 forceinline Actor* 00541 nqtoter(Space& home, bool share, Propagator& p, 00542 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) { 00543 assert(y.size() == 3); 00544 return new (home) NqTer<Val,IntView,IntView,IntView> 00545 (home,share,p,y[0],y[1],y[2],-c); 00546 } 00547 template<class Val> 00548 forceinline Actor* 00549 nqtoter(Space& home, bool share, Propagator& p, 00550 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) { 00551 if (x.size() == 3) 00552 return new (home) NqTer<Val,IntView,IntView,IntView> 00553 (home,share,p,x[0],x[1],x[2],c); 00554 if (x.size() == 2) 00555 return new (home) NqTer<Val,IntView,IntView,MinusView> 00556 (home,share,p,x[0],x[1],MinusView(y[0]),c); 00557 if (x.size() == 1) 00558 return new (home) NqTer<Val,IntView,IntView,MinusView> 00559 (home,share,p,y[0],y[1],MinusView(x[0]),-c); 00560 return new (home) NqTer<Val,IntView,IntView,IntView> 00561 (home,share,p,y[0],y[1],y[2],-c); 00562 } 00563 00564 template<class Val, class P, class N> 00565 Actor* 00566 Nq<Val,P,N>::copy(Space& home, bool share) { 00567 if (isunit(x,y)) { 00568 // Check whether rewriting is possible 00569 if (x.size() + y.size() == 2) 00570 return nqtobin(home,share,*this,x,y,c); 00571 if (x.size() + y.size() == 3) 00572 return nqtoter(home,share,*this,x,y,c); 00573 } 00574 return new (home) Nq<Val,P,N>(home,share,*this); 00575 } 00576 00577 template<class Val, class P, class N> 00578 ExecStatus 00579 Nq<Val,P,N>::propagate(Space& home, const ModEventDelta&) { 00580 for (int i = x.size(); i--; ) 00581 if (x[i].assigned()) { 00582 c -= x[i].val(); x.move_lst(i); 00583 } 00584 for (int i = y.size(); i--; ) 00585 if (y[i].assigned()) { 00586 c += y[i].val(); y.move_lst(i); 00587 } 00588 if (x.size() + y.size() <= 1) { 00589 if (x.size() == 1) { 00590 GECODE_ME_CHECK(x[0].nq(home,c)); return ES_SUBSUMED(*this,home); 00591 } 00592 if (y.size() == 1) { 00593 GECODE_ME_CHECK(y[0].nq(home,-c)); return ES_SUBSUMED(*this,home); 00594 } 00595 return (c == static_cast<Val>(0)) ? 00596 ES_FAILED : ES_SUBSUMED(*this,sizeof(*this)); 00597 } 00598 return ES_FIX; 00599 } 00600 00601 00602 /* 00603 * Bound consistent linear inequation 00604 * 00605 */ 00606 00607 template<class Val, class P, class N> 00608 forceinline 00609 Lq<Val,P,N>::Lq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) 00610 : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {} 00611 00612 template<class Val, class P, class N> 00613 ExecStatus 00614 Lq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) { 00615 ViewArray<NoView> nva; 00616 if (y.size() == 0) { 00617 (void) new (home) Lq<Val,P,NoView>(home,x,nva,c); 00618 } else if (x.size() == 0) { 00619 (void) new (home) Lq<Val,NoView,N>(home,nva,y,c); 00620 } else { 00621 (void) new (home) Lq<Val,P,N>(home,x,y,c); 00622 } 00623 return ES_OK; 00624 } 00625 00626 00627 template<class Val, class P, class N> 00628 forceinline 00629 Lq<Val,P,N>::Lq(Space& home, bool share, Lq<Val,P,N>& p) 00630 : Lin<Val,P,N,PC_INT_BND>(home,share,p) {} 00631 00636 template<class Val, class P, class N> 00637 forceinline Actor* 00638 lqtobin(Space&, bool, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) { 00639 return NULL; 00640 } 00641 template<class Val> 00642 forceinline Actor* 00643 lqtobin(Space& home, bool share, Propagator& p, 00644 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) { 00645 assert(x.size() == 2); 00646 return new (home) LqBin<Val,IntView,IntView> 00647 (home,share,p,x[0],x[1],c); 00648 } 00649 template<class Val> 00650 forceinline Actor* 00651 lqtobin(Space& home, bool share, Propagator& p, 00652 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) { 00653 assert(y.size() == 2); 00654 return new (home) LqBin<Val,MinusView,MinusView> 00655 (home,share,p,MinusView(y[0]),MinusView(y[1]),c); 00656 } 00657 template<class Val> 00658 forceinline Actor* 00659 lqtobin(Space& home, bool share, Propagator& p, 00660 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) { 00661 if (x.size() == 2) 00662 return new (home) LqBin<Val,IntView,IntView> 00663 (home,share,p,x[0],x[1],c); 00664 if (x.size() == 1) 00665 return new (home) LqBin<Val,IntView,MinusView> 00666 (home,share,p,x[0],MinusView(y[0]),c); 00667 return new (home) LqBin<Val,MinusView,MinusView> 00668 (home,share,p,MinusView(y[0]),MinusView(y[1]),c); 00669 } 00670 00675 template<class Val, class P, class N> 00676 forceinline Actor* 00677 lqtoter(Space&, bool, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) { 00678 return NULL; 00679 } 00680 template<class Val> 00681 forceinline Actor* 00682 lqtoter(Space& home, bool share, Propagator& p, 00683 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) { 00684 assert(x.size() == 3); 00685 return new (home) LqTer<Val,IntView,IntView,IntView> 00686 (home,share,p,x[0],x[1],x[2],c); 00687 } 00688 template<class Val> 00689 forceinline Actor* 00690 lqtoter(Space& home, bool share, Propagator& p, 00691 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) { 00692 assert(y.size() == 3); 00693 return new (home) LqTer<Val,MinusView,MinusView,MinusView> 00694 (home,share,p,MinusView(y[0]),MinusView(y[1]),MinusView(y[2]),c); 00695 } 00696 template<class Val> 00697 forceinline Actor* 00698 lqtoter(Space& home, bool share, Propagator& p, 00699 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) { 00700 if (x.size() == 3) 00701 return new (home) LqTer<Val,IntView,IntView,IntView> 00702 (home,share,p,x[0],x[1],x[2],c); 00703 if (x.size() == 2) 00704 return new (home) LqTer<Val,IntView,IntView,MinusView> 00705 (home,share,p,x[0],x[1],MinusView(y[0]),c); 00706 if (x.size() == 1) 00707 return new (home) LqTer<Val,IntView,MinusView,MinusView> 00708 (home,share,p,x[0],MinusView(y[0]),MinusView(y[1]),c); 00709 return new (home) LqTer<Val,MinusView,MinusView,MinusView> 00710 (home,share,p,MinusView(y[0]),MinusView(y[1]),MinusView(y[2]),c); 00711 } 00712 00713 template<class Val, class P, class N> 00714 Actor* 00715 Lq<Val,P,N>::copy(Space& home, bool share) { 00716 if (isunit(x,y)) { 00717 // Check whether rewriting is possible 00718 if (x.size() + y.size() == 2) 00719 return lqtobin(home,share,*this,x,y,c); 00720 if (x.size() + y.size() == 3) 00721 return lqtoter(home,share,*this,x,y,c); 00722 } 00723 return new (home) Lq<Val,P,N>(home,share,*this); 00724 } 00725 00726 template<class Val, class P, class N> 00727 ExecStatus 00728 Lq<Val,P,N>::propagate(Space& home, const ModEventDelta& med) { 00729 // Eliminate singletons 00730 Val sl = 0; 00731 00732 if (IntView::me(med) == ME_INT_VAL) { 00733 for (int i = x.size(); i--; ) { 00734 Val m = x[i].min(); 00735 if (x[i].assigned()) { 00736 c -= m; x.move_lst(i); 00737 } else { 00738 sl -= m; 00739 } 00740 } 00741 for (int i = y.size(); i--; ) { 00742 Val m = y[i].max(); 00743 if (y[i].assigned()) { 00744 c += m; y.move_lst(i); 00745 } else { 00746 sl += m; 00747 } 00748 } 00749 if ((x.size() + y.size()) <= 1) { 00750 if (x.size() == 1) { 00751 GECODE_ME_CHECK(x[0].lq(home,c)); 00752 return ES_SUBSUMED(*this,home); 00753 } 00754 if (y.size() == 1) { 00755 GECODE_ME_CHECK(y[0].gq(home,-c)); 00756 return ES_SUBSUMED(*this,home); 00757 } 00758 return (c >= static_cast<Val>(0)) ? 00759 ES_SUBSUMED(*this,sizeof(*this)) : ES_FAILED; 00760 } 00761 } else { 00762 for (int i = x.size(); i--; ) 00763 sl -= x[i].min(); 00764 for (int i = y.size(); i--; ) 00765 sl += y[i].max(); 00766 } 00767 00768 sl += c; 00769 00770 ExecStatus es = ES_FIX; 00771 bool assigned = true; 00772 for (int i = x.size(); i--; ) { 00773 assert(!x[i].assigned()); 00774 Val slx = sl + x[i].min(); 00775 ModEvent me = x[i].lq(home,slx); 00776 if (me == ME_INT_FAILED) 00777 return ES_FAILED; 00778 if (me != ME_INT_VAL) 00779 assigned = false; 00780 if (me_modified(me) && (slx != x[i].max())) 00781 es = ES_NOFIX; 00782 } 00783 00784 for (int i = y.size(); i--; ) { 00785 assert(!y[i].assigned()); 00786 Val sly = y[i].max() - sl; 00787 ModEvent me = y[i].gq(home,sly); 00788 if (me == ME_INT_FAILED) 00789 return ES_FAILED; 00790 if (me != ME_INT_VAL) 00791 assigned = false; 00792 if (me_modified(me) && (sly != y[i].min())) 00793 es = ES_NOFIX; 00794 } 00795 return assigned ? ES_SUBSUMED(*this,sizeof(*this)) : es; 00796 } 00797 00798 /* 00799 * Reified bound consistent linear inequation 00800 * 00801 */ 00802 00803 template<class Val, class P, class N> 00804 forceinline 00805 ReLq<Val,P,N>::ReLq 00806 (Home home, ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b) 00807 : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,x,y,c,b) {} 00808 00809 template<class Val, class P, class N> 00810 ExecStatus 00811 ReLq<Val,P,N>::post 00812 (Home home, ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b) { 00813 ViewArray<NoView> nva; 00814 if (y.size() == 0) { 00815 (void) new (home) ReLq<Val,P,NoView>(home,x,nva,c,b); 00816 } else if (x.size() == 0) { 00817 (void) new (home) ReLq<Val,NoView,N>(home,nva,y,c,b); 00818 } else { 00819 (void) new (home) ReLq<Val,P,N>(home,x,y,c,b); 00820 } 00821 return ES_OK; 00822 } 00823 00824 00825 template<class Val, class P, class N> 00826 forceinline 00827 ReLq<Val,P,N>::ReLq(Space& home, bool share, ReLq<Val,P,N>& p) 00828 : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,share,p) {} 00829 00830 template<class Val, class P, class N> 00831 Actor* 00832 ReLq<Val,P,N>::copy(Space& home, bool share) { 00833 return new (home) ReLq<Val,P,N>(home,share,*this); 00834 } 00835 00836 template<class Val, class P, class N> 00837 ExecStatus 00838 ReLq<Val,P,N>::propagate(Space& home, const ModEventDelta& med) { 00839 if (b.zero()) 00840 GECODE_REWRITE(*this,(Lq<Val,N,P>::post(home(*this),y,x,-c-1))); 00841 if (b.one()) 00842 GECODE_REWRITE(*this,(Lq<Val,P,N>::post(home(*this),x,y,c))); 00843 00844 // Eliminate singletons 00845 Val sl = 0; 00846 Val su = 0; 00847 00848 bounds_p<Val,P>(med,x,c,sl,su); 00849 bounds_n<Val,N>(med,y,c,sl,su); 00850 00851 if (-sl > c) { 00852 GECODE_ME_CHECK(b.zero_none(home)); 00853 return ES_SUBSUMED(*this,home); 00854 } 00855 if (-su <= c) { 00856 GECODE_ME_CHECK(b.one_none(home)); 00857 return ES_SUBSUMED(*this,home); 00858 } 00859 00860 return ES_FIX; 00861 } 00862 00863 }}} 00864 00865 // STATISTICS: int-prop 00866