00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "gecode/iter.hh"
00025 #include <algorithm>
00026
00027 namespace Gecode { namespace Int { namespace Arithmetic {
00028
00029 template <class View, template <class View0,class View1> class Eq>
00030 ExecStatus
00031 prop_bnd(Space* home, View x0, View x1) {
00032 if (x0.assigned()) {
00033 GECODE_ME_CHECK(x1.eq(home,(x0.val() < 0) ? -x0.val() : x0.val()));
00034 return ES_SUBSUMED;
00035 }
00036
00037 if (x1.assigned()) {
00038 if (x0.min() >= 0) {
00039 GECODE_ME_CHECK(x0.eq(home,x1.val()));
00040 } else if (x0.max() <= 0) {
00041 GECODE_ME_CHECK(x0.eq(home,-x1.val()));
00042 } else if (x1.val() == 0) {
00043 GECODE_ME_CHECK(x0.eq(home,0));
00044 } else {
00045 Iter::Ranges::Array::Range r[2]
00046 = { {-x1.val(),-x1.val()}, {x1.val(),x1.val()} };
00047 Iter::Ranges::Array i(r,2);
00048 GECODE_ME_CHECK(x0.inter(home,i));
00049 }
00050 return ES_SUBSUMED;
00051 }
00052
00053 if (x0.min() >= 0) {
00054 return (Eq<View,View>::post(home,x0,x1) == ES_FAILED)
00055 ? ES_FAILED : ES_SUBSUMED;
00056 }
00057
00058 if (x0.max() <= 0) {
00059 MinusView mx0(x0);
00060 return (Eq<MinusView,View>::post(home,mx0,x1) == ES_FAILED)
00061 ? ES_FAILED : ES_SUBSUMED;
00062 }
00063
00064 GECODE_ME_CHECK(x1.lq(home,std::max(x0.max(),-x0.min())));
00065 GECODE_ME_CHECK(x0.lq(home,x1.max()));
00066 GECODE_ME_CHECK(x0.gq(home,-x1.max()));
00067 return ES_NOFIX;
00068 }
00069
00070 template <class View>
00071 forceinline
00072 AbsBnd<View>::AbsBnd(Space* home, View x0, View x1)
00073 : BinaryPropagator<View,PC_INT_BND>(home,x0,x1) {}
00074
00075 template <class View>
00076 ExecStatus
00077 AbsBnd<View>::post(Space* home, View x0, View x1) {
00078 GECODE_ME_CHECK(x1.gq(home,0));
00079 if (!same(x0,x1)) {
00080 (void) new (home) AbsBnd<View>(home,x0,x1);
00081 }
00082 return ES_OK;
00083 }
00084
00085
00086 template <class View>
00087 forceinline
00088 AbsBnd<View>::AbsBnd(Space* home, bool share, AbsBnd<View>& p)
00089 : BinaryPropagator<View,PC_INT_BND>(home,share,p) {}
00090
00091 template <class View>
00092 Actor*
00093 AbsBnd<View>::copy(Space* home,bool share) {
00094 return new (home) AbsBnd<View>(home,share,*this);
00095 }
00096
00097 template <class View>
00098 PropCost
00099 AbsBnd<View>::cost(void) const {
00100 if (View::pme(this) == ME_INT_VAL)
00101 return PC_UNARY_LO;
00102 return PC_BINARY_LO;
00103 }
00104
00105 template <class View>
00106 ExecStatus
00107 AbsBnd<View>::propagate(Space* home) {
00108 return prop_bnd<View,Rel::EqBnd>(home, x0, x1);
00109 }
00110
00111 template <class View>
00112 forceinline
00113 AbsDom<View>::AbsDom(Space* home, View x0, View x1)
00114 : BinaryPropagator<View,PC_INT_DOM>(home,x0,x1) {}
00115
00116 template <class View>
00117 ExecStatus
00118 AbsDom<View>::post(Space* home, View x0, View x1) {
00119 if (x0.min() >= 0) {
00120 return Rel::EqDom<View,View>::post(home,x0,x1);
00121 } else if (x0.max() <= 0) {
00122 MinusView mx0(x0);
00123 return Rel::EqDom<MinusView,View>::post(home,mx0,x1);
00124 }
00125 GECODE_ME_CHECK(x1.gq(home,0));
00126 if (!same(x0,x1)) {
00127 (void) new (home) AbsDom<View>(home,x0,x1);
00128 }
00129 return ES_OK;
00130 }
00131
00132 template <class View>
00133 forceinline
00134 AbsDom<View>::AbsDom(Space* home, bool share, AbsDom<View>& p)
00135 : BinaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00136
00137 template <class View>
00138 Actor*
00139 AbsDom<View>::copy(Space* home,bool share) {
00140 return new (home) AbsDom<View>(home,share,*this);
00141 }
00142
00143 template <class View>
00144 PropCost
00145 AbsDom<View>::cost(void) const {
00146 if (View::pme(this) == ME_INT_VAL)
00147 return PC_UNARY_LO;
00148 if (View::pme(this) == ME_INT_DOM)
00149 return PC_BINARY_HI;
00150 return PC_BINARY_LO;
00151 }
00152
00153 template <class View>
00154 ExecStatus
00155 AbsDom<View>::propagate(Space* home) {
00156
00157 if (View::pme(this) != ME_INT_DOM) {
00158 ExecStatus es = prop_bnd<View,Rel::EqDom>(home, x0, x1);
00159 if (es != ES_NOFIX)
00160 return es;
00161 return this->ES_NOFIX_PARTIAL(View::pme(ME_INT_DOM));
00162 }
00163
00164 Iter::Ranges::Singleton positive(0, Limits::Int::int_max);
00165 Iter::Ranges::Singleton negative(Limits::Int::int_min, 0);
00166
00167 IntVarRanges xr1(x0);
00168 IntVarRanges xr2(x0);
00169
00170 Iter::Ranges::Inter<Iter::Ranges::Singleton,
00171 IntVarRanges> posInter(positive, xr1);
00172 Iter::Ranges::Inter<Iter::Ranges::Singleton,
00173 IntVarRanges> negInter(negative, xr2);
00174 Iter::Ranges::Minus<Iter::Ranges::Inter<Iter::Ranges::Singleton,
00175 IntVarRanges> > mneg(negInter);
00176 Iter::Ranges::Union<Iter::Ranges::Inter<Iter::Ranges::Singleton,
00177 IntVarRanges>,
00178 Iter::Ranges::Minus<Iter::Ranges::Inter<
00179 Iter::Ranges::Singleton,
00180 IntVarRanges> > >
00181 u(posInter, mneg);
00182
00183 GECODE_ME_CHECK(x1.inter(home, u));
00184
00185 IntVarRanges x1r1(x1);
00186 IntVarRanges x1r2(x1);
00187
00188 Iter::Ranges::Minus<IntVarRanges> x1m(x1r2);
00189 Iter::Ranges::Union<IntVarRanges,
00190 Iter::Ranges::Minus<IntVarRanges> > u2(x1r1,x1m);
00191 GECODE_ME_CHECK(x0.inter(home, u2));
00192
00193 if (x1.assigned())
00194 return ES_SUBSUMED;
00195
00196 if (x0.min() >= 0) {
00197 return (Rel::EqDom<View,View>::post(home,x0,x1) == ES_FAILED)
00198 ? ES_FAILED : ES_SUBSUMED;
00199 }
00200
00201 if (x0.max() <= 0) {
00202 MinusView mx0(x0);
00203 return (Rel::EqDom<MinusView,View>::post(home,mx0,x1) == ES_FAILED)
00204 ? ES_FAILED : ES_SUBSUMED;
00205 }
00206
00207 return ES_FIX;
00208 }
00209
00210 }}}
00211
00212
00213