Generated on Wed Mar 19 07:29:56 2008 for Gecode by doxygen 1.5.5

eq.icc

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: 2008-02-18 09:40:04 +0100 (Mon, 18 Feb 2008) $ by $Author: nikopp $
00011  *     $Revision: 6207 $
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(Space* 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(Space* 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       (void) new (home) EqBnd<View0,View1>(home,x0,x1);
00059     }
00060     return ES_OK;
00061   }
00062 
00063   template <class View0, class View1>
00064   forceinline
00065   EqBnd<View0,View1>::EqBnd(Space* home, bool share, EqBnd<View0,View1>& p)
00066     : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,share,p) {}
00067 
00068   template <class View0, class View1>
00069   forceinline
00070   EqBnd<View0,View1>::EqBnd(Space* home, bool share, Propagator& p,
00071                             View0 x0, View1 x1)
00072     : MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>(home,share,p,
00073                                                              x0,x1) {}
00074 
00075   template <class View0, class View1>
00076   Actor*
00077   EqBnd<View0,View1>::copy(Space* home, bool share) {
00078     return new (home) EqBnd<View0,View1>(home,share,*this);
00079   }
00080 
00081   template <class View0, class View1>
00082   inline Support::Symbol
00083   EqBnd<View0,View1>::ati(void) {
00084     return Reflection::mangle<View0,View1>("Gecode::Int::Rel::EqBnd");
00085   }
00086 
00087   template <class View0, class View1>
00088   Reflection::ActorSpec
00089   EqBnd<View0,View1>::spec(const Space* home, Reflection::VarMap& m) const {
00090     return MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>
00091       ::spec(home, m, ati());
00092   }
00093 
00094   template <class View0, class View1>
00095   void
00096   EqBnd<View0,View1>::post(Space* home, Reflection::VarMap& vars,
00097                            const Reflection::ActorSpec& spec) {
00098     spec.checkArity(2);
00099     View0 x0(home, vars, spec[0]);
00100     View1 x1(home, vars, spec[1]);
00101     (void) new (home) EqBnd<View0,View1>(home, x0, x1);
00102   } 
00103 
00104   template <class View0, class View1>
00105   ExecStatus
00106   EqBnd<View0,View1>::propagate(Space* home, ModEventDelta) {
00107     if (x0.assigned()) {
00108       GECODE_ME_CHECK(x1.eq(home,x0.val()));
00109     } else if (x1.assigned()) {
00110       GECODE_ME_CHECK(x0.eq(home,x1.val()));
00111     } else {
00112       do {
00113         GECODE_ME_CHECK(x0.gq(home,x1.min()));
00114         GECODE_ME_CHECK(x1.gq(home,x0.min()));
00115       } while (x0.min() != x1.min());
00116       do {
00117         GECODE_ME_CHECK(x0.lq(home,x1.max()));
00118         GECODE_ME_CHECK(x1.lq(home,x0.max()));
00119       } while (x0.max() != x1.max());
00120       if (!x0.assigned())
00121         return ES_FIX;
00122     }
00123     assert(x0.assigned() && x1.assigned());
00124     return ES_SUBSUMED(this,sizeof(*this));
00125   }
00126 
00127   /*
00128    * Binary domain consistent equality
00129    *
00130    */
00131 
00132   template <class View0, class View1>
00133   forceinline
00134   EqDom<View0,View1>::EqDom(Space* home, View0 x0, View1 x1)
00135     : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,x0,x1) {}
00136 
00137   template <class View0, class View1>
00138   ExecStatus
00139   EqDom<View0,View1>::post(Space* home, View0 x0, View1 x1){
00140     if (x0.assigned()) {
00141       GECODE_ME_CHECK(x1.eq(home,x0.val()));
00142     } else if (x1.assigned()) {
00143       GECODE_ME_CHECK(x0.eq(home,x1.val()));
00144     } else if (!same(x0,x1)) {
00145       (void) new (home) EqDom<View0,View1>(home,x0,x1);
00146     }
00147     return ES_OK;
00148   }
00149 
00150 
00151   template <class View0, class View1>
00152   forceinline
00153   EqDom<View0,View1>::EqDom(Space* home, bool share, EqDom<View0,View1>& p)
00154     : MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>(home,share,p) {}
00155 
00156   template <class View0, class View1>
00157   Actor*
00158   EqDom<View0,View1>::copy(Space* home, bool share) {
00159     return new (home) EqDom<View0,View1>(home,share,*this);
00160   }
00161 
00162   template <class View0, class View1>
00163   inline Support::Symbol
00164   EqDom<View0,View1>::ati(void) {
00165     return Reflection::mangle<View0,View1>("Gecode::Int::Rel::EqDom");
00166   }
00167 
00168   template <class View0, class View1>
00169   Reflection::ActorSpec
00170   EqDom<View0,View1>::spec(const Space* home, Reflection::VarMap& m) const {
00171     return MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>
00172       ::spec(home, m, ati());
00173   }
00174 
00175   template <class View0, class View1>
00176   void
00177   EqDom<View0,View1>::post(Space* home, Reflection::VarMap& vars,
00178                            const Reflection::ActorSpec& spec) {
00179     spec.checkArity(2);
00180     View0 x0(home, vars, spec[0]);
00181     View1 x1(home, vars, spec[1]);
00182     (void) new (home) EqDom<View0,View1>(home, x0, x1);
00183   } 
00184 
00185   template <class View0, class View1>
00186   PropCost
00187   EqDom<View0,View1>::cost(ModEventDelta med) const {
00188     if ((View0::me(med) == ME_INT_VAL) || (View1::me(med) == ME_INT_VAL))
00189       return PC_UNARY_LO;
00190     if ((View0::me(med) == ME_INT_DOM) || (View1::me(med) == ME_INT_DOM))
00191       return PC_BINARY_HI;
00192     return PC_BINARY_LO;
00193   }
00194 
00195   template <class View0, class View1>
00196   ExecStatus
00197   EqDom<View0,View1>::propagate(Space* home, ModEventDelta med) {
00198     if (x0.assigned()) {
00199       GECODE_ME_CHECK(x1.eq(home,x0.val()));
00200       return ES_SUBSUMED(this,sizeof(*this));
00201     }
00202     if (x1.assigned()) {
00203       GECODE_ME_CHECK(x0.eq(home,x1.val()));
00204       return ES_SUBSUMED(this,sizeof(*this));
00205     }
00206     if ((View0::me(med) != ME_INT_DOM) && (View1::me(med) != ME_INT_DOM)) {
00207       do {
00208         GECODE_ME_CHECK(x0.gq(home,x1.min()));
00209         GECODE_ME_CHECK(x1.gq(home,x0.min()));
00210       } while (x0.min() != x1.min());
00211       do {
00212         GECODE_ME_CHECK(x0.lq(home,x1.max()));
00213         GECODE_ME_CHECK(x1.lq(home,x0.max()));
00214       } while (x0.max() != x1.max());
00215       if (x0.assigned())
00216         return ES_SUBSUMED(this,sizeof(*this));
00217       if (x0.range() && x1.range())
00218         return ES_FIX;
00219       return ES_FIX_PARTIAL(this,View0::med(ME_INT_DOM));
00220     }
00221     ViewRanges<View0> r0(x0);
00222     GECODE_ME_CHECK(x1.inter_r(home,r0,false));
00223     ViewRanges<View1> r1(x1);
00224     GECODE_ME_CHECK(x0.narrow_r(home,r1,false));
00225     if (x0.assigned())
00226       return ES_SUBSUMED(this,sizeof(*this));
00227     return ES_FIX;
00228   }
00229 
00230 
00231 
00232   /*
00233    * Nary domain consistent equality
00234    *
00235    */
00236 
00237   template <class View>
00238   forceinline
00239   NaryEqDom<View>::NaryEqDom(Space* home, ViewArray<View>& x)
00240     : NaryPropagator<View,PC_INT_DOM>(home,x) {}
00241 
00242   template <class View>
00243   ExecStatus
00244   NaryEqDom<View>::post(Space* home, ViewArray<View>& x) {
00245     x.unique();
00246     if (x.size() == 2)
00247       return EqDom<View,View>::post(home,x[0],x[1]);
00248     else if (x.size() > 2)
00249       (void) new (home) NaryEqDom<View>(home,x);
00250     return ES_OK;
00251   }
00252 
00253   template <class View>
00254   forceinline
00255   NaryEqDom<View>::NaryEqDom(Space* home, bool share, NaryEqDom<View>& p)
00256     : NaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00257 
00258   template <class View>
00259   Actor*
00260   NaryEqDom<View>::copy(Space* home, bool share) {
00261     return new (home) NaryEqDom<View>(home,share,*this);
00262   }
00263 
00264   template <class View>
00265   inline Support::Symbol
00266   NaryEqDom<View>::ati(void) {
00267     return Reflection::mangle<View>("Gecode::Int::Rel::NaryEqDom");
00268   }
00269 
00270   template <class View>
00271   Reflection::ActorSpec
00272   NaryEqDom<View>::spec(const Space* home, Reflection::VarMap& m) const {
00273     return NaryPropagator<View,PC_INT_DOM>
00274       ::spec(home, m, ati());
00275   }
00276 
00277   template <class View>
00278   void
00279   NaryEqDom<View>::post(Space* home, Reflection::VarMap& vars,
00280                         const Reflection::ActorSpec& spec) {
00281     spec.checkArity(1);
00282     ViewArray<View> x(home, vars, spec[0]);
00283     (void) new (home) NaryEqDom<View>(home, x);
00284   }
00285 
00286   template <class View>
00287   PropCost
00288   NaryEqDom<View>::cost(ModEventDelta med) const {
00289     if (View::me(med) == ME_INT_VAL)
00290       return PC_UNARY_LO;
00291     if (View::me(med) == ME_INT_DOM)
00292       return cost_hi(x.size(),PC_LINEAR_HI);
00293     return cost_lo(x.size(),PC_LINEAR_LO);
00294   }
00295 
00296   template <class View>
00297   ExecStatus
00298   NaryEqDom<View>::propagate(Space* home, ModEventDelta med) {
00299     assert(x.size() > 2);
00300 
00301     ModEvent me = View::me(med);
00302     if (me == ME_INT_VAL) {
00303       // One of the variables is assigned
00304       for (int i = 0; ; i++)
00305         if (x[i].assigned()) {
00306           int n = x[i].val();
00307           x.move_lst(i);
00308           for (int i = x.size(); i--; )
00309             GECODE_ME_CHECK(x[i].eq(home,n));
00310           return ES_SUBSUMED(this,sizeof(*this));
00311         }
00312       GECODE_NEVER;
00313       return ES_SUBSUMED(this,sizeof(*this));
00314     }
00315 
00316     if (me == ME_INT_BND) {
00317       {
00318         // One of the mins has changed
00319         int mn = x[0].min();
00320       restart_min:
00321         for (int i = x.size(); i--; ) {
00322           GECODE_ME_CHECK(x[i].gq(home,mn));
00323           if (mn < x[i].min()) {
00324             mn = x[i].min();
00325             goto restart_min;
00326           }
00327         }
00328       }
00329       {
00330         // One of the maxs has changed
00331         int mx = x[0].max();
00332       restart_max:
00333         for (int i = x.size(); i--; ) {
00334           GECODE_ME_CHECK(x[i].lq(home,mx));
00335           if (mx > x[i].max()) {
00336             mx = x[i].max();
00337             goto restart_max;
00338           }
00339         }
00340       }
00341       if (x[0].assigned())
00342         return ES_SUBSUMED(this,sizeof(*this));
00343       return ES_FIX_PARTIAL(this,View::med(ME_INT_DOM));
00344     }
00345 
00346     int n = x.size();
00347 
00348     GECODE_AUTOARRAY(ViewRanges<View>, i_x, n);
00349     for (int i = n; i--; ) {
00350       ViewRanges<View> i_xi(x[i]);
00351       i_x[i] = i_xi;
00352     }
00353     Iter::Ranges::NaryInter<ViewRanges<View> > r(i_x,n);
00354     Iter::Ranges::Cache<Iter::Ranges::NaryInter<ViewRanges<View> > > rc(r);
00355 
00356     if (!rc())
00357       return ES_FAILED;
00358     ++rc;
00359     if (!rc()) {
00360       rc.reset();
00361       for (int i = n; i--; ) {
00362         GECODE_ME_CHECK(x[i].gq(home,rc.min()));
00363         GECODE_ME_CHECK(x[i].lq(home,rc.max()));
00364       }
00365     } else {
00366       for (int i = n; i--; ) {
00367         rc.reset();
00368         GECODE_ME_CHECK(x[i].narrow_r(home,rc,false));
00369       }
00370     }
00371     return ES_FIX;
00372   }
00373 
00374 
00375 
00376   /*
00377    * Nary bound consistent equality
00378    *
00379    */
00380 
00381   template <class View>
00382   forceinline
00383   NaryEqBnd<View>::NaryEqBnd(Space* home, ViewArray<View>& x)
00384     : NaryPropagator<View,PC_INT_BND>(home,x) {}
00385 
00386   template <class View>
00387   ExecStatus
00388   NaryEqBnd<View>::post(Space* home, ViewArray<View>& x) {
00389     if (x.size() == 2)
00390       return EqBnd<View,View>::post(home,x[0],x[1]);
00391     else if (x.size() > 2)
00392       (void) new (home) NaryEqBnd<View>(home,x);
00393     return ES_OK;
00394   }
00395 
00396   template <class View>
00397   forceinline
00398   NaryEqBnd<View>::NaryEqBnd(Space* home, bool share, NaryEqBnd<View>& p)
00399     : NaryPropagator<View,PC_INT_BND>(home,share,p) {}
00400 
00401   template <class View>
00402   Actor*
00403   NaryEqBnd<View>::copy(Space* home, bool share) {
00404     return new (home) NaryEqBnd<View>(home,share,*this);
00405   }
00406 
00407   template <class View>
00408   PropCost
00409   NaryEqBnd<View>::cost(ModEventDelta med) const {
00410     if (View::me(med) == ME_INT_VAL)
00411       return PC_UNARY_LO;
00412     return cost_lo(x.size(),PC_LINEAR_LO);
00413   }
00414 
00415   template <class View>
00416   inline Support::Symbol
00417   NaryEqBnd<View>::ati(void) {
00418     return Reflection::mangle<View>("Gecode::Int::Rel::NaryEqBnd");
00419   }
00420 
00421   template <class View>
00422   Reflection::ActorSpec
00423   NaryEqBnd<View>::spec(const Space* home, Reflection::VarMap& m) const {
00424     return NaryPropagator<View,PC_INT_BND>
00425       ::spec(home, m, ati());
00426   }
00427 
00428   template <class View>
00429   void
00430   NaryEqBnd<View>::post(Space* home, Reflection::VarMap& vars,
00431                         const Reflection::ActorSpec& spec) {
00432     spec.checkArity(1);
00433     ViewArray<View> x(home, vars, spec[0]);
00434     (void) new (home) NaryEqBnd<View>(home, x);
00435   }
00436 
00437   template <class View>
00438   ExecStatus
00439   NaryEqBnd<View>::propagate(Space* home, ModEventDelta med) {
00440     assert(x.size() > 2);
00441     if (View::me(med) == ME_INT_VAL) {
00442       // One of the variables is assigned
00443       for (int i = 0; ; i++)
00444         if (x[i].assigned()) {
00445           int n = x[i].val();
00446           x.move_lst(i);
00447           for (int i = x.size(); i--; )
00448             GECODE_ME_CHECK(x[i].eq(home,n));
00449           return ES_SUBSUMED(this,sizeof(*this));
00450         }
00451       GECODE_NEVER;
00452       return ES_SUBSUMED(this,sizeof(*this));
00453     }
00454 
00455     int mn = x[0].min();
00456   restart_min:
00457     for (int i = x.size(); i--; ) {
00458       GECODE_ME_CHECK(x[i].gq(home,mn));
00459       if (mn < x[i].min()) {
00460         mn = x[i].min();
00461         goto restart_min;
00462       }
00463     }
00464     int mx = x[0].max();
00465   restart_max:
00466     for (int i = x.size(); i--; ) {
00467       GECODE_ME_CHECK(x[i].lq(home,mx));
00468       if (mx > x[i].max()) {
00469         mx = x[i].max();
00470         goto restart_max;
00471       }
00472     }
00473     return x[0].assigned() ? ES_SUBSUMED(this,sizeof(*this)) : ES_FIX;
00474   }
00475 
00476 
00477 
00478   /*
00479    * Reified domain-consistent equality
00480    *
00481    */
00482 
00483   template <class View, class CtrlView>
00484   forceinline
00485   ReEqDom<View,CtrlView>::ReEqDom(Space* home, View x0, View x1, CtrlView b)
00486     : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,x0,x1,b) {}
00487 
00488   template <class View, class CtrlView>
00489   ExecStatus
00490   ReEqDom<View,CtrlView>::post(Space* home, View x0, View x1, CtrlView b) {
00491     if (b.one())
00492       return EqDom<View,View>::post(home,x0,x1);
00493     if (b.zero())
00494       return Nq<View>::post(home,x0,x1);
00495     if (!same(x0,x1)) {
00496       (void) new (home) ReEqDom(home,x0,x1,b);
00497     } else {
00498       GECODE_ME_CHECK(b.one(home));
00499     }
00500     return ES_OK;
00501   }
00502 
00503 
00504   template <class View, class CtrlView>
00505   forceinline
00506   ReEqDom<View,CtrlView>::ReEqDom(Space* home, bool share, ReEqDom& p)
00507     : ReBinaryPropagator<View,PC_INT_DOM,CtrlView>(home,share,p) {}
00508 
00509   template <class View, class CtrlView>
00510   Actor*
00511   ReEqDom<View,CtrlView>::copy(Space* home, bool share) {
00512     return new (home) ReEqDom<View,CtrlView>(home,share,*this);
00513   }
00514 
00515   template <class View, class CtrlView>
00516   inline Support::Symbol
00517   ReEqDom<View,CtrlView>::ati(void) {
00518     return Reflection::mangle<View,CtrlView>("Gecode::Int::Rel::ReEqDom");
00519   }
00520 
00521   template <class View, class CtrlView>
00522   Reflection::ActorSpec
00523   ReEqDom<View,CtrlView>::spec(const Space* home,
00524                                Reflection::VarMap& m) const {
00525     return ReBinaryPropagator<View,PC_INT_DOM,CtrlView>
00526       ::spec(home, m, ati());
00527   }
00528 
00529   template <class View, class CtrlView>
00530   void
00531   ReEqDom<View,CtrlView>::post(Space* home, Reflection::VarMap& vars,
00532                                const Reflection::ActorSpec& spec) {
00533     spec.checkArity(3);
00534     View x0(home, vars, spec[0]);
00535     View x1(home, vars, spec[1]);
00536     CtrlView b(home, vars, spec[2]);
00537     (void) new (home) ReEqDom<View,CtrlView>(home, x0, x1, b);
00538   }
00539 
00540   template <class View, class CtrlView>
00541   ExecStatus
00542   ReEqDom<View,CtrlView>::propagate(Space* home, ModEventDelta) {
00543     if (b.one())
00544       GECODE_REWRITE(this,(EqDom<View,View>::post(home,x0,x1)));
00545     if (b.zero())
00546       GECODE_REWRITE(this,Nq<View>::post(home,x0,x1));
00547     switch (rtest_eq_dom(x0,x1)) {
00548     case RT_TRUE:
00549       GECODE_ME_CHECK(b.one_none(home)); return ES_SUBSUMED(this,home);
00550     case RT_FALSE:
00551       GECODE_ME_CHECK(b.zero_none(home)); return ES_SUBSUMED(this,home);
00552     case RT_MAYBE:
00553       break;
00554     default: GECODE_NEVER;
00555     }
00556     return ES_FIX;
00557   }
00558 
00559 
00560 
00561   /*
00562    * Reified bounds-consistent equality
00563    *
00564    */
00565 
00566   template <class View, class CtrlView>
00567   forceinline
00568   ReEqBnd<View,CtrlView>::ReEqBnd(Space* home, View x0, View x1, CtrlView b)
00569     : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,x0,x1,b) {}
00570 
00571   template <class View, class CtrlView>
00572   ExecStatus
00573   ReEqBnd<View,CtrlView>::post(Space* home, View x0, View x1, CtrlView b){
00574     if (b.one())
00575       return EqBnd<View,View>::post(home,x0,x1);
00576     if (b.zero())
00577       return Nq<View>::post(home,x0,x1);
00578     if (!same(x0,x1)) {
00579       (void) new (home) ReEqBnd(home,x0,x1,b);
00580     } else {
00581       GECODE_ME_CHECK(b.one(home));
00582     }
00583     return ES_OK;
00584   }
00585 
00586 
00587   template <class View, class CtrlView>
00588   forceinline
00589   ReEqBnd<View,CtrlView>::ReEqBnd(Space* home, bool share, ReEqBnd& p)
00590     : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p) {}
00591 
00592   template <class View, class CtrlView>
00593   Actor*
00594   ReEqBnd<View,CtrlView>::copy(Space* home, bool share) {
00595     return new (home) ReEqBnd<View,CtrlView>(home,share,*this);
00596   }
00597 
00598   template <class View, class CtrlView>
00599   inline Support::Symbol
00600   ReEqBnd<View,CtrlView>::ati(void) {
00601     return Reflection::mangle<View,CtrlView>("Gecode::Int::Rel::ReEqBnd");
00602   }
00603 
00604   template <class View, class CtrlView>
00605   Reflection::ActorSpec
00606   ReEqBnd<View,CtrlView>::spec(const Space* home,
00607                                Reflection::VarMap& m) const {
00608     return ReBinaryPropagator<View,PC_INT_BND,CtrlView>
00609       ::spec(home, m, ati());
00610   }
00611 
00612   template <class View, class CtrlView>
00613   void
00614   ReEqBnd<View,CtrlView>::post(Space* home, Reflection::VarMap& vars,
00615                                const Reflection::ActorSpec& spec) {
00616     spec.checkArity(3);
00617     View x0(home, vars, spec[0]);
00618     View x1(home, vars, spec[1]);
00619     CtrlView b(home, vars, spec[2]);
00620     (void) new (home) ReEqBnd<View,CtrlView>(home, x0, x1, b);
00621   }
00622 
00623   template <class View, class CtrlView>
00624   ExecStatus
00625   ReEqBnd<View,CtrlView>::propagate(Space* home, ModEventDelta) {
00626     if (b.one())
00627       GECODE_REWRITE(this,(EqBnd<View,View>::post(home,x0,x1)));
00628     if (b.zero())
00629       GECODE_REWRITE(this,Nq<View>::post(home,x0,x1));
00630     switch (rtest_eq_bnd(x0,x1)) {
00631     case RT_TRUE:
00632       GECODE_ME_CHECK(b.one_none(home));  return ES_SUBSUMED(this,home);
00633     case RT_FALSE:
00634       GECODE_ME_CHECK(b.zero_none(home)); return ES_SUBSUMED(this,home);
00635     case RT_MAYBE:
00636       break;
00637     default: GECODE_NEVER;
00638     }
00639     return ES_FIX;
00640   }
00641 
00642 
00643 
00644 
00645   /*
00646    * Reified domain-consistent equality (one variable)
00647    *
00648    */
00649 
00650   template <class View, class CtrlView>
00651   forceinline
00652   ReEqDomInt<View,CtrlView>::ReEqDomInt
00653   (Space* home, View x, int c0, CtrlView b)
00654     : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,x,b), c(c0) {}
00655 
00656   template <class View, class CtrlView>
00657   ExecStatus
00658   ReEqDomInt<View,CtrlView>::post(Space* home, View x, int c, CtrlView b) {
00659     if (b.one()) {
00660       GECODE_ME_CHECK(x.eq(home,c));
00661     } else if (b.zero()) {
00662       GECODE_ME_CHECK(x.nq(home,c));
00663     } else if (x.assigned()) {
00664       assert(b.none());
00665       if (x.val() == c) {
00666         GECODE_ME_CHECK(b.one_none(home));
00667       } else {
00668         GECODE_ME_CHECK(b.zero_none(home));
00669       }
00670     } else {
00671       (void) new (home) ReEqDomInt(home,x,c,b);        
00672     }
00673     return ES_OK;
00674   }
00675 
00676 
00677   template <class View, class CtrlView>
00678   forceinline
00679   ReEqDomInt<View,CtrlView>::ReEqDomInt(Space* home, bool share, ReEqDomInt& p)
00680     : ReUnaryPropagator<View,PC_INT_DOM,CtrlView>(home,share,p), c(p.c) {}
00681 
00682   template <class View, class CtrlView>
00683   Actor*
00684   ReEqDomInt<View,CtrlView>::copy(Space* home, bool share) {
00685     return new (home) ReEqDomInt<View,CtrlView>(home,share,*this);
00686   }
00687 
00688   template <class View, class CtrlView>
00689   inline Support::Symbol
00690   ReEqDomInt<View,CtrlView>::ati(void) {
00691     return Reflection::mangle<View,CtrlView>("Gecode::Int::Rel::ReEqDomInt");
00692   }
00693 
00694   template <class View, class CtrlView>
00695   Reflection::ActorSpec
00696   ReEqDomInt<View,CtrlView>::spec(const Space* home,
00697                                   Reflection::VarMap& m) const {
00698     return ReUnaryPropagator<View,PC_INT_DOM,CtrlView>
00699       ::spec(home, m, ati()) << c;
00700   }
00701 
00702   template <class View, class CtrlView>
00703   void
00704   ReEqDomInt<View,CtrlView>::post(Space* home, Reflection::VarMap& vars,
00705                                   const Reflection::ActorSpec& spec) {
00706     spec.checkArity(3);
00707     View x0(home, vars, spec[0]);
00708     CtrlView b(home, vars, spec[1]);
00709     int c = spec[2]->toInt();
00710     (void) new (home) ReEqDomInt<View,CtrlView>(home, x0, c, b);
00711   }
00712 
00713   template <class View, class CtrlView>
00714   ExecStatus
00715   ReEqDomInt<View,CtrlView>::propagate(Space* home, ModEventDelta) {
00716     if (b.one()) {
00717       GECODE_ME_CHECK(x0.eq(home,c)); 
00718       assert(x0.assigned());
00719       goto subsumed;
00720     }
00721     if (b.zero()) {
00722       GECODE_ME_CHECK(x0.nq(home,c)); 
00723       x0.cancel(home,this,PC_INT_DOM);
00724       goto subsumed;
00725     }
00726     switch (rtest_eq_dom(x0,c)) {
00727     case RT_TRUE:
00728       GECODE_ME_CHECK(b.one_none(home)); 
00729       assert(x0.assigned());
00730       goto subsumed;
00731     case RT_FALSE:
00732       GECODE_ME_CHECK(b.zero_none(home)); 
00733       x0.cancel(home,this,PC_INT_DOM);
00734       goto subsumed;
00735     case RT_MAYBE:
00736       break;
00737     default: GECODE_NEVER;
00738     }
00739     return ES_FIX;
00740   subsumed:
00741     return ES_SUBSUMED(this,sizeof(*this));    
00742   }
00743 
00744 
00745 
00746 
00747   /*
00748    * Reified bounds-consistent equality (one variable)
00749    *
00750    */
00751 
00752   template <class View, class CtrlView>
00753   forceinline
00754   ReEqBndInt<View,CtrlView>::ReEqBndInt
00755   (Space* home, View x, int c0, CtrlView b)
00756     : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,x,b), c(c0) {}
00757 
00758   template <class View, class CtrlView>
00759   ExecStatus
00760   ReEqBndInt<View,CtrlView>::post(Space* home, View x, int c, CtrlView b) {
00761     if (b.one()) {
00762       GECODE_ME_CHECK(x.eq(home,c));
00763     } else if (b.zero()) {
00764       GECODE_ME_CHECK(x.nq(home,c));
00765     } else if (x.assigned()) {
00766       assert(b.none());
00767       if (x.val() == c) {
00768         GECODE_ME_CHECK(b.one_none(home));
00769       } else {
00770         GECODE_ME_CHECK(b.zero_none(home));
00771       }
00772     } else {
00773       (void) new (home) ReEqBndInt(home,x,c,b);        
00774     }
00775     return ES_OK;
00776   }
00777 
00778 
00779   template <class View, class CtrlView>
00780   forceinline
00781   ReEqBndInt<View,CtrlView>::ReEqBndInt(Space* home, bool share, ReEqBndInt& p)
00782     : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p), c(p.c) {}
00783 
00784   template <class View, class CtrlView>
00785   Actor*
00786   ReEqBndInt<View,CtrlView>::copy(Space* home, bool share) {
00787     return new (home) ReEqBndInt<View,CtrlView>(home,share,*this);
00788   }
00789 
00790   template <class View, class CtrlView>
00791   inline Support::Symbol
00792   ReEqBndInt<View,CtrlView>::ati(void) {
00793     return Reflection::mangle<View,CtrlView>("Gecode::Int::Rel::ReEqBndInt");
00794   }
00795 
00796   template <class View, class CtrlView>
00797   Reflection::ActorSpec
00798   ReEqBndInt<View,CtrlView>::spec(const Space* home,
00799                                   Reflection::VarMap& m) const {
00800     return ReUnaryPropagator<View,PC_INT_BND,CtrlView>
00801       ::spec(home, m, ati()) << c;
00802   }
00803 
00804   template <class View, class CtrlView>
00805   void
00806   ReEqBndInt<View,CtrlView>::post(Space* home, Reflection::VarMap& vars,
00807                                   const Reflection::ActorSpec& spec) {
00808     spec.checkArity(3);
00809     View x0(home, vars, spec[0]);
00810     CtrlView b(home, vars, spec[1]);
00811     int c = spec[2]->toInt();
00812     (void) new (home) ReEqBndInt<View,CtrlView>(home, x0, c, b);
00813   }
00814 
00815   template <class View, class CtrlView>
00816   ExecStatus
00817   ReEqBndInt<View,CtrlView>::propagate(Space* home, ModEventDelta) {
00818     if (b.one()) {
00819       GECODE_ME_CHECK(x0.eq(home,c)); 
00820       assert(x0.assigned());
00821       goto subsumed;
00822     }
00823     if (b.zero()) {
00824       GECODE_ME_CHECK(x0.nq(home,c)); 
00825       x0.cancel(home,this,PC_INT_BND);
00826       goto subsumed;
00827     }
00828     switch (rtest_eq_bnd(x0,c)) {
00829     case RT_TRUE:
00830       GECODE_ME_CHECK(b.one_none(home)); 
00831       assert(x0.assigned());
00832       goto subsumed;
00833     case RT_FALSE:
00834       GECODE_ME_CHECK(b.zero_none(home)); 
00835       x0.cancel(home,this,PC_INT_BND);
00836       goto subsumed;
00837     case RT_MAYBE:
00838       break;
00839     default: GECODE_NEVER;
00840     }
00841     return ES_FIX;
00842   subsumed:
00843     return ES_SUBSUMED(this,sizeof(*this));
00844   }
00845 
00846 }}}
00847 
00848 // STATISTICS: int-prop