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-03-03 17:32:21 +0100 (Wed, 03 Mar 2010) $ by $Author: schulte $ 00011 * $Revision: 10364 $ 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> > > rc(r); 00314 00315 if (!rc()) 00316 return ES_FAILED; 00317 ++rc; 00318 if (!rc()) { 00319 rc.reset(); 00320 for (int i = n; i--; ) { 00321 GECODE_ME_CHECK(x[i].gq(home,rc.min())); 00322 GECODE_ME_CHECK(x[i].lq(home,rc.max())); 00323 } 00324 } else { 00325 for (int i = n; i--; ) { 00326 rc.reset(); 00327 GECODE_ME_CHECK(x[i].narrow_r(home,rc,false)); 00328 } 00329 } 00330 return ES_FIX; 00331 } 00332 00333 00334 00335 /* 00336 * Nary bound consistent equality 00337 * 00338 */ 00339 00340 template<class View> 00341 forceinline 00342 NaryEqBnd<View>::NaryEqBnd(Home home, ViewArray<View>& x) 00343 : NaryPropagator<View,PC_INT_BND>(home,x) {} 00344 00345 template<class View> 00346 ExecStatus 00347 NaryEqBnd<View>::post(Home home, ViewArray<View>& x) { 00348 if (x.size() == 2) { 00349 return EqBnd<View,View>::post(home,x[0],x[1]); 00350 } else if (x.size() > 2) { 00351 int l = x[0].min(); 00352 int u = x[0].max(); 00353 for (int i=x.size(); i-- > 1; ) { 00354 l = std::max(l,x[i].min()); 00355 u = std::min(u,x[i].max()); 00356 } 00357 for (int i=x.size(); i--; ) { 00358 GECODE_ME_CHECK(x[i].gq(home,l)); 00359 GECODE_ME_CHECK(x[i].lq(home,u)); 00360 } 00361 (void) new (home) NaryEqBnd<View>(home,x); 00362 } 00363 return ES_OK; 00364 } 00365 00366 template<class View> 00367 forceinline 00368 NaryEqBnd<View>::NaryEqBnd(Space& home, bool share, NaryEqBnd<View>& p) 00369 : NaryPropagator<View,PC_INT_BND>(home,share,p) {} 00370 00371 template<class View> 00372 Actor* 00373 NaryEqBnd<View>::copy(Space& home, bool share) { 00374 return new (home) NaryEqBnd<View>(home,share,*this); 00375 } 00376 00377 template<class View> 00378 PropCost 00379 NaryEqBnd<View>::cost(const Space&, const ModEventDelta& med) const { 00380 if (View::me(med) == ME_INT_VAL) 00381 return PropCost::unary(PropCost::LO); 00382 else 00383 return PropCost::linear(PropCost::LO, x.size()); 00384 } 00385 00386 template<class View> 00387 ExecStatus 00388 NaryEqBnd<View>::propagate(Space& home, const ModEventDelta& med) { 00389 assert(x.size() > 2); 00390 if (View::me(med) == ME_INT_VAL) { 00391 // One of the variables is assigned 00392 for (int i = 0; ; i++) 00393 if (x[i].assigned()) { 00394 int n = x[i].val(); 00395 x.move_lst(i); 00396 for (int j = x.size(); j--; ) 00397 GECODE_ME_CHECK(x[j].eq(home,n)); 00398 return home.ES_SUBSUMED(*this); 00399 } 00400 GECODE_NEVER; 00401 } 00402 00403 int mn = x[0].min(); 00404 restart_min: 00405 for (int i = x.size(); i--; ) { 00406 GECODE_ME_CHECK(x[i].gq(home,mn)); 00407 if (mn < x[i].min()) { 00408 mn = x[i].min(); 00409 goto restart_min; 00410 } 00411 } 00412 int mx = x[0].max(); 00413 restart_max: 00414 for (int i = x.size(); i--; ) { 00415 GECODE_ME_CHECK(x[i].lq(home,mx)); 00416 if (mx > x[i].max()) { 00417 mx = x[i].max(); 00418 goto restart_max; 00419 } 00420 } 00421 return x[0].assigned() ? home.ES_SUBSUMED(*this) : ES_FIX; 00422 } 00423 00424 00425 00426 /* 00427 * Reified domain consistent equality 00428 * 00429 */ 00430 00431 template<class View, class CtrlView> 00432 forceinline 00433 ReEqDom<View,CtrlView>::ReEqDom(Home home, View x0, View x1, CtrlView b) 00434 : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,x0,x1,b) {} 00435 00436 template<class View, class CtrlView> 00437 ExecStatus 00438 ReEqDom<View,CtrlView>::post(Home home, View x0, View x1, CtrlView b) { 00439 if (b.one()) 00440 return EqDom<View,View>::post(home,x0,x1); 00441 if (b.zero()) 00442 return Nq<View>::post(home,x0,x1); 00443 if (!same(x0,x1)) { 00444 (void) new (home) ReEqDom(home,x0,x1,b); 00445 } else { 00446 GECODE_ME_CHECK(b.one(home)); 00447 } 00448 return ES_OK; 00449 } 00450 00451 00452 template<class View, class CtrlView> 00453 forceinline 00454 ReEqDom<View,CtrlView>::ReEqDom(Space& home, bool share, ReEqDom& p) 00455 : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,share,p) {} 00456 00457 template<class View, class CtrlView> 00458 Actor* 00459 ReEqDom<View,CtrlView>::copy(Space& home, bool share) { 00460 return new (home) ReEqDom<View,CtrlView>(home,share,*this); 00461 } 00462 00463 template<class View, class CtrlView> 00464 ExecStatus 00465 ReEqDom<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00466 if (b.one()) 00467 GECODE_REWRITE(*this,(EqDom<View,View>::post(home(*this),x0,x1))); 00468 if (b.zero()) 00469 GECODE_REWRITE(*this,Nq<View>::post(home(*this),x0,x1)); 00470 switch (rtest_eq_dom(x0,x1)) { 00471 case RT_TRUE: 00472 GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); 00473 case RT_FALSE: 00474 GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); 00475 case RT_MAYBE: 00476 break; 00477 default: GECODE_NEVER; 00478 } 00479 return ES_FIX; 00480 } 00481 00482 00483 00484 /* 00485 * Reified bounds consistent equality 00486 * 00487 */ 00488 00489 template<class View, class CtrlView> 00490 forceinline 00491 ReEqBnd<View,CtrlView>::ReEqBnd(Home home, View x0, View x1, CtrlView b) 00492 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,x0,x1,b) {} 00493 00494 template<class View, class CtrlView> 00495 ExecStatus 00496 ReEqBnd<View,CtrlView>::post(Home home, View x0, View x1, CtrlView b){ 00497 if (b.one()) 00498 return EqBnd<View,View>::post(home,x0,x1); 00499 if (b.zero()) 00500 return Nq<View>::post(home,x0,x1); 00501 if (!same(x0,x1)) { 00502 (void) new (home) ReEqBnd(home,x0,x1,b); 00503 } else { 00504 GECODE_ME_CHECK(b.one(home)); 00505 } 00506 return ES_OK; 00507 } 00508 00509 00510 template<class View, class CtrlView> 00511 forceinline 00512 ReEqBnd<View,CtrlView>::ReEqBnd(Space& home, bool share, ReEqBnd& p) 00513 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p) {} 00514 00515 template<class View, class CtrlView> 00516 Actor* 00517 ReEqBnd<View,CtrlView>::copy(Space& home, bool share) { 00518 return new (home) ReEqBnd<View,CtrlView>(home,share,*this); 00519 } 00520 00521 template<class View, class CtrlView> 00522 ExecStatus 00523 ReEqBnd<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00524 if (b.one()) 00525 GECODE_REWRITE(*this,(EqBnd<View,View>::post(home(*this),x0,x1))); 00526 if (b.zero()) 00527 GECODE_REWRITE(*this,Nq<View>::post(home(*this),x0,x1)); 00528 switch (rtest_eq_bnd(x0,x1)) { 00529 case RT_TRUE: 00530 GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); 00531 case RT_FALSE: 00532 GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); 00533 case RT_MAYBE: 00534 break; 00535 default: GECODE_NEVER; 00536 } 00537 return ES_FIX; 00538 } 00539 00540 00541 00542 00543 /* 00544 * Reified domain consistent equality (one variable) 00545 * 00546 */ 00547 00548 template<class View, class CtrlView> 00549 forceinline 00550 ReEqDomInt<View,CtrlView>::ReEqDomInt 00551 (Home home, View x, int c0, CtrlView b) 00552 : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,x,b), c(c0) {} 00553 00554 template<class View, class CtrlView> 00555 ExecStatus 00556 ReEqDomInt<View,CtrlView>::post(Home home, View x, int c, CtrlView b) { 00557 if (b.one()) { 00558 GECODE_ME_CHECK(x.eq(home,c)); 00559 } else if (b.zero()) { 00560 GECODE_ME_CHECK(x.nq(home,c)); 00561 } else if (x.assigned()) { 00562 assert(b.none()); 00563 if (x.val() == c) { 00564 GECODE_ME_CHECK(b.one_none(home)); 00565 } else { 00566 GECODE_ME_CHECK(b.zero_none(home)); 00567 } 00568 } else { 00569 (void) new (home) ReEqDomInt(home,x,c,b); 00570 } 00571 return ES_OK; 00572 } 00573 00574 00575 template<class View, class CtrlView> 00576 forceinline 00577 ReEqDomInt<View,CtrlView>::ReEqDomInt(Space& home, bool share, ReEqDomInt& p) 00578 : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,share,p), c(p.c) {} 00579 00580 template<class View, class CtrlView> 00581 Actor* 00582 ReEqDomInt<View,CtrlView>::copy(Space& home, bool share) { 00583 return new (home) ReEqDomInt<View,CtrlView>(home,share,*this); 00584 } 00585 00586 template<class View, class CtrlView> 00587 ExecStatus 00588 ReEqDomInt<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00589 if (b.one()) { 00590 GECODE_ME_CHECK(x0.eq(home,c)); 00591 } else if (b.zero()) { 00592 GECODE_ME_CHECK(x0.nq(home,c)); 00593 } else { 00594 switch (rtest_eq_dom(x0,c)) { 00595 case RT_TRUE: 00596 GECODE_ME_CHECK(b.one_none(home)); break; 00597 case RT_FALSE: 00598 GECODE_ME_CHECK(b.zero_none(home)); break; 00599 case RT_MAYBE: 00600 return ES_FIX; 00601 default: GECODE_NEVER; 00602 } 00603 } 00604 return home.ES_SUBSUMED(*this); 00605 } 00606 00607 00608 00609 00610 /* 00611 * Reified bounds consistent equality (one variable) 00612 * 00613 */ 00614 00615 template<class View, class CtrlView> 00616 forceinline 00617 ReEqBndInt<View,CtrlView>::ReEqBndInt 00618 (Home home, View x, int c0, CtrlView b) 00619 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,x,b), c(c0) {} 00620 00621 template<class View, class CtrlView> 00622 ExecStatus 00623 ReEqBndInt<View,CtrlView>::post(Home home, View x, int c, CtrlView b) { 00624 if (b.one()) { 00625 GECODE_ME_CHECK(x.eq(home,c)); 00626 } else if (b.zero()) { 00627 GECODE_ME_CHECK(x.nq(home,c)); 00628 } else if (x.assigned()) { 00629 assert(b.none()); 00630 if (x.val() == c) { 00631 GECODE_ME_CHECK(b.one_none(home)); 00632 } else { 00633 GECODE_ME_CHECK(b.zero_none(home)); 00634 } 00635 } else { 00636 (void) new (home) ReEqBndInt(home,x,c,b); 00637 } 00638 return ES_OK; 00639 } 00640 00641 00642 template<class View, class CtrlView> 00643 forceinline 00644 ReEqBndInt<View,CtrlView>::ReEqBndInt(Space& home, bool share, ReEqBndInt& p) 00645 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p), c(p.c) {} 00646 00647 template<class View, class CtrlView> 00648 Actor* 00649 ReEqBndInt<View,CtrlView>::copy(Space& home, bool share) { 00650 return new (home) ReEqBndInt<View,CtrlView>(home,share,*this); 00651 } 00652 00653 template<class View, class CtrlView> 00654 ExecStatus 00655 ReEqBndInt<View,CtrlView>::propagate(Space& home, const ModEventDelta&) { 00656 if (b.one()) { 00657 GECODE_ME_CHECK(x0.eq(home,c)); 00658 } else if (b.zero()) { 00659 GECODE_ME_CHECK(x0.nq(home,c)); 00660 } else { 00661 switch (rtest_eq_bnd(x0,c)) { 00662 case RT_TRUE: 00663 GECODE_ME_CHECK(b.one_none(home)); break; 00664 case RT_FALSE: 00665 GECODE_ME_CHECK(b.zero_none(home)); break; 00666 case RT_MAYBE: 00667 return ES_FIX; 00668 default: GECODE_NEVER; 00669 } 00670 } 00671 return home.ES_SUBSUMED(*this); 00672 } 00673 00674 }}} 00675 00676 // STATISTICS: int-prop