eq.hpp
Go to the documentation of this file.
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, 2004 00008 * 00009 * Last modified: 00010 * $Date: 2010-07-28 16:13:53 +0200 (Wed, 28 Jul 2010) $ by $Author: schulte $ 00011 * $Revision: 11292 $ 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 namespace Gecode { namespace Int { namespace Rel { 00039 00040 /* 00041 * Binary bounds consistent equality 00042 * 00043 */ 00044 00045 template<class View0, class View1> 00046 forceinline 00047 EqBnd<View0,View1>::EqBnd(Home home, View0 x0, View1 x1) 00048 : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,x0,x1) {} 00049 00050 template<class View0, class View1> 00051 ExecStatus 00052 EqBnd<View0,View1>::post(Home home, View0 x0, View1 x1){ 00053 if (x0.assigned()) { 00054 GECODE_ME_CHECK(x1.eq(home,x0.val())); 00055 } else if (x1.assigned()) { 00056 GECODE_ME_CHECK(x0.eq(home,x1.val())); 00057 } else if (!same(x0,x1)) { 00058 GECODE_ME_CHECK(x0.lq(home,x1.max())); 00059 GECODE_ME_CHECK(x1.lq(home,x0.max())); 00060 GECODE_ME_CHECK(x0.gq(home,x1.min())); 00061 GECODE_ME_CHECK(x1.gq(home,x0.min())); 00062 (void) new (home) EqBnd<View0,View1>(home,x0,x1); 00063 } 00064 return ES_OK; 00065 } 00066 00067 template<class View0, class View1> 00068 forceinline 00069 EqBnd<View0,View1>::EqBnd(Space& home, bool share, EqBnd<View0,View1>& p) 00070 : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,share,p) {} 00071 00072 template<class View0, class View1> 00073 forceinline 00074 EqBnd<View0,View1>::EqBnd(Space& home, bool share, Propagator& p, 00075 View0 x0, View1 x1) 00076 : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,share,p, 00077 x0,x1) {} 00078 00079 template<class View0, class View1> 00080 Actor* 00081 EqBnd<View0,View1>::copy(Space& home, bool share) { 00082 return new (home) EqBnd<View0,View1>(home,share,*this); 00083 } 00084 00085 template<class View0, class View1> 00086 ExecStatus 00087 EqBnd<View0,View1>::propagate(Space& home, const ModEventDelta&) { 00088 if (x0.assigned()) { 00089 GECODE_ME_CHECK(x1.eq(home,x0.val())); 00090 } else if (x1.assigned()) { 00091 GECODE_ME_CHECK(x0.eq(home,x1.val())); 00092 } else { 00093 do { 00094 GECODE_ME_CHECK(x0.gq(home,x1.min())); 00095 GECODE_ME_CHECK(x1.gq(home,x0.min())); 00096 } while (x0.min() != x1.min()); 00097 do { 00098 GECODE_ME_CHECK(x0.lq(home,x1.max())); 00099 GECODE_ME_CHECK(x1.lq(home,x0.max())); 00100 } while (x0.max() != x1.max()); 00101 if (!x0.assigned()) 00102 return ES_FIX; 00103 } 00104 assert(x0.assigned() && x1.assigned()); 00105 return home.ES_SUBSUMED(*this); 00106 } 00107 00108 /* 00109 * Binary domain consistent equality 00110 * 00111 */ 00112 00113 template<class View0, class View1> 00114 forceinline 00115 EqDom<View0,View1>::EqDom(Home home, View0 x0, View1 x1) 00116 : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,x0,x1) {} 00117 00118 template<class View0, class View1> 00119 ExecStatus 00120 EqDom<View0,View1>::post(Home home, View0 x0, View1 x1){ 00121 if (x0.assigned()) { 00122 GECODE_ME_CHECK(x1.eq(home,x0.val())); 00123 } else if (x1.assigned()) { 00124 GECODE_ME_CHECK(x0.eq(home,x1.val())); 00125 } else if (!same(x0,x1)) { 00126 GECODE_ME_CHECK(x0.lq(home,x1.max())); 00127 GECODE_ME_CHECK(x1.lq(home,x0.max())); 00128 GECODE_ME_CHECK(x0.gq(home,x1.min())); 00129 GECODE_ME_CHECK(x1.gq(home,x0.min())); 00130 (void) new (home) EqDom<View0,View1>(home,x0,x1); 00131 } 00132 return ES_OK; 00133 } 00134 00135 00136 template<class View0, class View1> 00137 forceinline 00138 EqDom<View0,View1>::EqDom(Space& home, bool share, EqDom<View0,View1>& p) 00139 : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,share,p) {} 00140 00141 template<class View0, class View1> 00142 forceinline 00143 EqDom<View0,View1>::EqDom(Space& home, bool share, Propagator& p, 00144 View0 x0, View1 x1) 00145 : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,share,p, 00146 x0,x1) {} 00147 00148 template<class View0, class View1> 00149 Actor* 00150 EqDom<View0,View1>::copy(Space& home, bool share) { 00151 return new (home) EqDom<View0,View1>(home,share,*this); 00152 } 00153 00154 template<class View0, class View1> 00155 PropCost 00156 EqDom<View0,View1>::cost(const Space&, const ModEventDelta& med) const { 00157 if ((View0::me(med) == ME_INT_VAL) || (View1::me(med) == ME_INT_VAL)) 00158 return PropCost::unary(PropCost::LO); 00159 else if ((View0::me(med) == ME_INT_DOM) || (View1::me(med) == ME_INT_DOM)) 00160 return PropCost::binary(PropCost::LO); 00161 else 00162 return PropCost::binary(PropCost::HI); 00163 } 00164 00165 template<class View0, class View1> 00166 ExecStatus 00167 EqDom<View0,View1>::propagate(Space& home, const ModEventDelta& med) { 00168 if (x0.assigned()) { 00169 GECODE_ME_CHECK(x1.eq(home,x0.val())); 00170 return home.ES_SUBSUMED(*this); 00171 } 00172 if (x1.assigned()) { 00173 GECODE_ME_CHECK(x0.eq(home,x1.val())); 00174 return home.ES_SUBSUMED(*this); 00175 } 00176 if ((View0::me(med) != ME_INT_DOM) && (View1::me(med) != ME_INT_DOM)) { 00177 do { 00178 GECODE_ME_CHECK(x0.gq(home,x1.min())); 00179 GECODE_ME_CHECK(x1.gq(home,x0.min())); 00180 } while (x0.min() != x1.min()); 00181 do { 00182 GECODE_ME_CHECK(x0.lq(home,x1.max())); 00183 GECODE_ME_CHECK(x1.lq(home,x0.max())); 00184 } while (x0.max() != x1.max()); 00185 if (x0.assigned()) 00186 return home.ES_SUBSUMED(*this); 00187 if (x0.range() && x1.range()) 00188 return ES_FIX; 00189 return home.ES_FIX_PARTIAL(*this,View0::med(ME_INT_DOM)); 00190 } 00191 ViewRanges<View0> r0(x0); 00192 GECODE_ME_CHECK(x1.inter_r(home,r0,shared(x0,x1))); 00193 ViewRanges<View1> r1(x1); 00194 GECODE_ME_CHECK(x0.narrow_r(home,r1,shared(x0,x1))); 00195 if (x0.assigned()) 00196 return home.ES_SUBSUMED(*this); 00197 return ES_FIX; 00198 } 00199 00200 00201 00202 /* 00203 * Nary domain consistent equality 00204 * 00205 */ 00206 00207 template<class View> 00208 forceinline 00209 NaryEqDom<View>::NaryEqDom(Home home, ViewArray<View>& x) 00210 : NaryPropagator<View,PC_INT_DOM>(home,x) {} 00211 00212 template<class View> 00213 ExecStatus 00214 NaryEqDom<View>::post(Home home, ViewArray<View>& x) { 00215 x.unique(home); 00216 if (x.size() == 2) { 00217 return EqDom<View,View>::post(home,x[0],x[1]); 00218 } else if (x.size() > 2) { 00219 int l = x[0].min(); 00220 int u = x[0].max(); 00221 for (int i=x.size(); i-- > 1; ) { 00222 l = std::max(l,x[i].min()); 00223 u = std::min(u,x[i].max()); 00224 } 00225 for (int i=x.size(); i--; ) { 00226 GECODE_ME_CHECK(x[i].gq(home,l)); 00227 GECODE_ME_CHECK(x[i].lq(home,u)); 00228 } 00229 (void) new (home) NaryEqDom<View>(home,x); 00230 } 00231 return ES_OK; 00232 } 00233 00234 template<class View> 00235 forceinline 00236 NaryEqDom<View>::NaryEqDom(Space& home, bool share, NaryEqDom<View>& p) 00237 : NaryPropagator<View,PC_INT_DOM>(home,share,p) {} 00238 00239 template<class View> 00240 Actor* 00241 NaryEqDom<View>::copy(Space& home, bool share) { 00242 return new (home) NaryEqDom<View>(home,share,*this); 00243 } 00244 00245 template<class View> 00246 PropCost 00247 NaryEqDom<View>::cost(const Space&, const ModEventDelta& med) const { 00248 if (View::me(med) == ME_INT_VAL) 00249 return PropCost::unary(PropCost::LO); 00250 else 00251 return PropCost::linear((View::me(med) == ME_INT_DOM) ? 00252 PropCost::LO : PropCost::HI, x.size()); 00253 } 00254 00255 template<class View> 00256 ExecStatus 00257 NaryEqDom<View>::propagate(Space& home, const ModEventDelta& med) { 00258 assert(x.size() > 2); 00259 00260 ModEvent me = View::me(med); 00261 if (me == ME_INT_VAL) { 00262 // One of the variables is assigned 00263 for (int i = 0; ; i++) 00264 if (x[i].assigned()) { 00265 int n = x[i].val(); 00266 x.move_lst(i); 00267 for (int j = x.size(); j--; ) 00268 GECODE_ME_CHECK(x[j].eq(home,n)); 00269 return home.ES_SUBSUMED(*this); 00270 } 00271 GECODE_NEVER; 00272 } 00273 00274 if (me == ME_INT_BND) { 00275 { 00276 // One of the mins has changed 00277 int mn = x[0].min(); 00278 restart_min: 00279 for (int i = x.size(); i--; ) { 00280 GECODE_ME_CHECK(x[i].gq(home,mn)); 00281 if (mn < x[i].min()) { 00282 mn = x[i].min(); 00283 goto restart_min; 00284 } 00285 } 00286 } 00287 { 00288 // One of the maxs has changed 00289 int mx = x[0].max(); 00290 restart_max: 00291 for (int i = x.size(); i--; ) { 00292 GECODE_ME_CHECK(x[i].lq(home,mx)); 00293 if (mx > x[i].max()) { 00294 mx = x[i].max(); 00295 goto restart_max; 00296 } 00297 } 00298 } 00299 if (x[0].assigned()) 00300 return home.ES_SUBSUMED(*this); 00301 return home.ES_FIX_PARTIAL(*this,View::med(ME_INT_DOM)); 00302 } 00303 00304 int n = x.size(); 00305 00306 Region re(home); 00307 ViewRanges<View>* i_x = re.alloc<ViewRanges<View> >(n); 00308 for (int i = n; i--; ) { 00309 ViewRanges<View> i_xi(x[i]); 00310 i_x[i] = i_xi; 00311 } 00312 Iter::Ranges::NaryInter<ViewRanges<View> > r(i_x,n); 00313 Iter::Ranges::Cache<Iter::Ranges::NaryInter<ViewRanges<View> > > 00314 rc(re,r); 00315 00316 if (!rc()) 00317 return ES_FAILED; 00318 ++rc; 00319 if (!rc()) { 00320 rc.reset(); 00321 for (int i = n; i--; ) { 00322 GECODE_ME_CHECK(x[i].gq(home,rc.min())); 00323 GECODE_ME_CHECK(x[i].lq(home,rc.max())); 00324 } 00325 } else { 00326 for (int i = n; i--; ) { 00327 rc.reset(); 00328 GECODE_ME_CHECK(x[i].narrow_r(home,rc,false)); 00329 } 00330 } 00331 return ES_FIX; 00332 } 00333 00334 00335 00336 /* 00337 * Nary bound consistent equality 00338 * 00339 */ 00340 00341 template<class View> 00342 forceinline 00343 NaryEqBnd<View>::NaryEqBnd(Home home, ViewArray<View>& x) 00344 : NaryPropagator<View,PC_INT_BND>(home,x) {} 00345 00346 template<class View> 00347 ExecStatus 00348 NaryEqBnd<View>::post(Home home, ViewArray<View>& x) { 00349 if (x.size() == 2) { 00350 return EqBnd<View,View>::post(home,x[0],x[1]); 00351 } else if (x.size() > 2) { 00352 int l = x[0].min(); 00353 int u = x[0].max(); 00354 for (int i=x.size(); i-- > 1; ) { 00355 l = std::max(l,x[i].min()); 00356 u = std::min(u,x[i].max()); 00357 } 00358 for (int i=x.size(); i--; ) { 00359 GECODE_ME_CHECK(x[i].gq(home,l)); 00360 GECODE_ME_CHECK(x[i].lq(home,u)); 00361 } 00362 (void) new (home) NaryEqBnd<View>(home,x); 00363 } 00364 return ES_OK; 00365 } 00366 00367 template<class View> 00368 forceinline 00369 NaryEqBnd<View>::NaryEqBnd(Space& home, bool share, NaryEqBnd<View>& p) 00370 : NaryPropagator<View,PC_INT_BND>(home,share,p) {} 00371 00372 template<class View> 00373 Actor* 00374 NaryEqBnd<View>::copy(Space& home, bool share) { 00375 return new (home) NaryEqBnd<View>(home,share,*this); 00376 } 00377 00378 template<class View> 00379 PropCost 00380 NaryEqBnd<View>::cost(const Space&, const ModEventDelta& med) const { 00381 if (View::me(med) == ME_INT_VAL) 00382 return PropCost::unary(PropCost::LO); 00383 else 00384 return PropCost::linear(PropCost::LO, x.size()); 00385 } 00386 00387 template<class View> 00388 ExecStatus 00389 NaryEqBnd<View>::propagate(Space& home, const ModEventDelta& med) { 00390 assert(x.size() > 2); 00391 if (View::me(med) == ME_INT_VAL) { 00392 // One of the variables is assigned 00393 for (int i = 0; ; i++) 00394 if (x[i].assigned()) { 00395 int n = x[i].val(); 00396 x.move_lst(i); 00397 for (int j = x.size(); j--; ) 00398 GECODE_ME_CHECK(x[j].eq(home,n)); 00399 return home.ES_SUBSUMED(*this); 00400 } 00401 GECODE_NEVER; 00402 } 00403 00404 int mn = x[0].min(); 00405 restart_min: 00406 for (int i = x.size(); i--; ) { 00407 GECODE_ME_CHECK(x[i].gq(home,mn)); 00408 if (mn < x[i].min()) { 00409 mn = x[i].min(); 00410 goto restart_min; 00411 } 00412 } 00413 int mx = x[0].max(); 00414 restart_max: 00415 for (int i = x.size(); i--; ) { 00416 GECODE_ME_CHECK(x[i].lq(home,mx)); 00417 if (mx > x[i].max()) { 00418 mx = x[i].max(); 00419 goto restart_max; 00420 } 00421 } 00422 return x[0].assigned() ? home.ES_SUBSUMED(*this) : ES_FIX; 00423 } 00424 00425 00426 00427 /* 00428 * Reified domain consistent equality 00429 * 00430 */ 00431 00432 template<class View, class CtrlView> 00433 forceinline 00434 ReEqDom<View,CtrlView>::ReEqDom(Home home, View x0, View x1, CtrlView b) 00435 : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,x0,x1,b) {} 00436 00437 template<class View, class CtrlView> 00438 ExecStatus 00439 ReEqDom<View,CtrlView>::post(Home home, View x0, View x1, CtrlView b) { 00440 if (b.one()) 00441 return EqDom<View,View>::post(home,x0,x1); 00442 if (b.zero()) 00443 return Nq<View>::post(home,x0,x1); 00444 if (!same(x0,x1)) { 00445 (void) new (home) ReEqDom(home,x0,x1,b); 00446 } else { 00447 GECODE_ME_CHECK(b.one(home)); 00448 } 00449 return ES_OK; 00450 } 00451 00452 00453 template<class View, class CtrlView> 00454 forceinline 00455 ReEqDom<View,CtrlView>::ReEqDom(Space& home, bool share, ReEqDom& p) 00456 : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,share,p) {} 00457 00458 template<class View, class CtrlView> 00459 Actor* 00460 ReEqDom<View,CtrlView>::copy(Space& home, bool share) { 00461 return new (home) ReEqDom<View,CtrlView>(home,share,*this); 00462 } 00463 00464 template<class View, class CtrlView> 00465 ExecStatus 00466 ReEqDom<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00467 if (b.one()) 00468 GECODE_REWRITE(*this,(EqDom<View,View>::post(home(*this),x0,x1))); 00469 if (b.zero()) 00470 GECODE_REWRITE(*this,Nq<View>::post(home(*this),x0,x1)); 00471 switch (rtest_eq_dom(x0,x1)) { 00472 case RT_TRUE: 00473 GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); 00474 case RT_FALSE: 00475 GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); 00476 case RT_MAYBE: 00477 break; 00478 default: GECODE_NEVER; 00479 } 00480 return ES_FIX; 00481 } 00482 00483 00484 00485 /* 00486 * Reified bounds consistent equality 00487 * 00488 */ 00489 00490 template<class View, class CtrlView> 00491 forceinline 00492 ReEqBnd<View,CtrlView>::ReEqBnd(Home home, View x0, View x1, CtrlView b) 00493 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,x0,x1,b) {} 00494 00495 template<class View, class CtrlView> 00496 ExecStatus 00497 ReEqBnd<View,CtrlView>::post(Home home, View x0, View x1, CtrlView b){ 00498 if (b.one()) 00499 return EqBnd<View,View>::post(home,x0,x1); 00500 if (b.zero()) 00501 return Nq<View>::post(home,x0,x1); 00502 if (!same(x0,x1)) { 00503 (void) new (home) ReEqBnd(home,x0,x1,b); 00504 } else { 00505 GECODE_ME_CHECK(b.one(home)); 00506 } 00507 return ES_OK; 00508 } 00509 00510 00511 template<class View, class CtrlView> 00512 forceinline 00513 ReEqBnd<View,CtrlView>::ReEqBnd(Space& home, bool share, ReEqBnd& p) 00514 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p) {} 00515 00516 template<class View, class CtrlView> 00517 Actor* 00518 ReEqBnd<View,CtrlView>::copy(Space& home, bool share) { 00519 return new (home) ReEqBnd<View,CtrlView>(home,share,*this); 00520 } 00521 00522 template<class View, class CtrlView> 00523 ExecStatus 00524 ReEqBnd<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00525 if (b.one()) 00526 GECODE_REWRITE(*this,(EqBnd<View,View>::post(home(*this),x0,x1))); 00527 if (b.zero()) 00528 GECODE_REWRITE(*this,Nq<View>::post(home(*this),x0,x1)); 00529 switch (rtest_eq_bnd(x0,x1)) { 00530 case RT_TRUE: 00531 GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); 00532 case RT_FALSE: 00533 GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); 00534 case RT_MAYBE: 00535 break; 00536 default: GECODE_NEVER; 00537 } 00538 return ES_FIX; 00539 } 00540 00541 00542 00543 00544 /* 00545 * Reified domain consistent equality (one variable) 00546 * 00547 */ 00548 00549 template<class View, class CtrlView> 00550 forceinline 00551 ReEqDomInt<View,CtrlView>::ReEqDomInt 00552 (Home home, View x, int c0, CtrlView b) 00553 : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,x,b), c(c0) {} 00554 00555 template<class View, class CtrlView> 00556 ExecStatus 00557 ReEqDomInt<View,CtrlView>::post(Home home, View x, int c, CtrlView b) { 00558 if (b.one()) { 00559 GECODE_ME_CHECK(x.eq(home,c)); 00560 } else if (b.zero()) { 00561 GECODE_ME_CHECK(x.nq(home,c)); 00562 } else if (x.assigned()) { 00563 assert(b.none()); 00564 if (x.val() == c) { 00565 GECODE_ME_CHECK(b.one_none(home)); 00566 } else { 00567 GECODE_ME_CHECK(b.zero_none(home)); 00568 } 00569 } else { 00570 (void) new (home) ReEqDomInt(home,x,c,b); 00571 } 00572 return ES_OK; 00573 } 00574 00575 00576 template<class View, class CtrlView> 00577 forceinline 00578 ReEqDomInt<View,CtrlView>::ReEqDomInt(Space& home, bool share, ReEqDomInt& p) 00579 : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,share,p), c(p.c) {} 00580 00581 template<class View, class CtrlView> 00582 Actor* 00583 ReEqDomInt<View,CtrlView>::copy(Space& home, bool share) { 00584 return new (home) ReEqDomInt<View,CtrlView>(home,share,*this); 00585 } 00586 00587 template<class View, class CtrlView> 00588 ExecStatus 00589 ReEqDomInt<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00590 if (b.one()) { 00591 GECODE_ME_CHECK(x0.eq(home,c)); 00592 } else if (b.zero()) { 00593 GECODE_ME_CHECK(x0.nq(home,c)); 00594 } else { 00595 switch (rtest_eq_dom(x0,c)) { 00596 case RT_TRUE: 00597 GECODE_ME_CHECK(b.one_none(home)); break; 00598 case RT_FALSE: 00599 GECODE_ME_CHECK(b.zero_none(home)); break; 00600 case RT_MAYBE: 00601 return ES_FIX; 00602 default: GECODE_NEVER; 00603 } 00604 } 00605 return home.ES_SUBSUMED(*this); 00606 } 00607 00608 00609 00610 00611 /* 00612 * Reified bounds consistent equality (one variable) 00613 * 00614 */ 00615 00616 template<class View, class CtrlView> 00617 forceinline 00618 ReEqBndInt<View,CtrlView>::ReEqBndInt 00619 (Home home, View x, int c0, CtrlView b) 00620 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,x,b), c(c0) {} 00621 00622 template<class View, class CtrlView> 00623 ExecStatus 00624 ReEqBndInt<View,CtrlView>::post(Home home, View x, int c, CtrlView b) { 00625 if (b.one()) { 00626 GECODE_ME_CHECK(x.eq(home,c)); 00627 } else if (b.zero()) { 00628 GECODE_ME_CHECK(x.nq(home,c)); 00629 } else if (x.assigned()) { 00630 assert(b.none()); 00631 if (x.val() == c) { 00632 GECODE_ME_CHECK(b.one_none(home)); 00633 } else { 00634 GECODE_ME_CHECK(b.zero_none(home)); 00635 } 00636 } else { 00637 (void) new (home) ReEqBndInt(home,x,c,b); 00638 } 00639 return ES_OK; 00640 } 00641 00642 00643 template<class View, class CtrlView> 00644 forceinline 00645 ReEqBndInt<View,CtrlView>::ReEqBndInt(Space& home, bool share, ReEqBndInt& p) 00646 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p), c(p.c) {} 00647 00648 template<class View, class CtrlView> 00649 Actor* 00650 ReEqBndInt<View,CtrlView>::copy(Space& home, bool share) { 00651 return new (home) ReEqBndInt<View,CtrlView>(home,share,*this); 00652 } 00653 00654 template<class View, class CtrlView> 00655 ExecStatus 00656 ReEqBndInt<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00657 if (b.one()) { 00658 GECODE_ME_CHECK(x0.eq(home,c)); 00659 } else if (b.zero()) { 00660 GECODE_ME_CHECK(x0.nq(home,c)); 00661 } else { 00662 switch (rtest_eq_bnd(x0,c)) { 00663 case RT_TRUE: 00664 GECODE_ME_CHECK(b.one_none(home)); break; 00665 case RT_FALSE: 00666 GECODE_ME_CHECK(b.zero_none(home)); break; 00667 case RT_MAYBE: 00668 return ES_FIX; 00669 default: GECODE_NEVER; 00670 } 00671 } 00672 return home.ES_SUBSUMED(*this); 00673 } 00674 00675 }}} 00676 00677 // STATISTICS: int-prop