/* * Main authors: * Christian Schulte * Guido Tack * * Copyright: * Christian Schulte, 2004 * Guido Tack, 2006 * * Last modified: * $Date: 2006-08-04 16:03:26 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $ * $Revision: 3512 $ * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * See the file "LICENSE" for information on usage and * redistribution of this file, and for a * DISCLAIMER OF ALL WARRANTIES. * */ #include "gecode/iter.hh" #include namespace Gecode { namespace Int { namespace Arithmetic { template class Eq> ExecStatus prop_bnd(Space* home, View x0, View x1) { if (x0.assigned()) { GECODE_ME_CHECK(x1.eq(home,(x0.val() < 0) ? -x0.val() : x0.val())); return ES_SUBSUMED; } if (x1.assigned()) { if (x0.min() >= 0) { GECODE_ME_CHECK(x0.eq(home,x1.val())); } else if (x0.max() <= 0) { GECODE_ME_CHECK(x0.eq(home,-x1.val())); } else if (x1.val() == 0) { GECODE_ME_CHECK(x0.eq(home,0)); } else { Iter::Ranges::Array::Range r[2] = { {-x1.val(),-x1.val()}, {x1.val(),x1.val()} }; Iter::Ranges::Array i(r,2); GECODE_ME_CHECK(x0.inter(home,i)); } return ES_SUBSUMED; } if (x0.min() >= 0) { return (Eq::post(home,x0,x1) == ES_FAILED) ? ES_FAILED : ES_SUBSUMED; } if (x0.max() <= 0) { MinusView mx0(x0); return (Eq::post(home,mx0,x1) == ES_FAILED) ? ES_FAILED : ES_SUBSUMED; } GECODE_ME_CHECK(x1.lq(home,std::max(x0.max(),-x0.min()))); GECODE_ME_CHECK(x0.lq(home,x1.max())); GECODE_ME_CHECK(x0.gq(home,-x1.max())); return ES_NOFIX; } template forceinline AbsBnd::AbsBnd(Space* home, View x0, View x1) : BinaryPropagator(home,x0,x1) {} template ExecStatus AbsBnd::post(Space* home, View x0, View x1) { GECODE_ME_CHECK(x1.gq(home,0)); if (!same(x0,x1)) { (void) new (home) AbsBnd(home,x0,x1); } return ES_OK; } template forceinline AbsBnd::AbsBnd(Space* home, bool share, AbsBnd& p) : BinaryPropagator(home,share,p) {} template Actor* AbsBnd::copy(Space* home,bool share) { return new (home) AbsBnd(home,share,*this); } template PropCost AbsBnd::cost(void) const { if (View::pme(this) == ME_INT_VAL) return PC_UNARY_LO; return PC_BINARY_LO; } template ExecStatus AbsBnd::propagate(Space* home) { return prop_bnd(home, x0, x1); } template forceinline AbsDom::AbsDom(Space* home, View x0, View x1) : BinaryPropagator(home,x0,x1) {} template ExecStatus AbsDom::post(Space* home, View x0, View x1) { if (x0.min() >= 0) { return Rel::EqDom::post(home,x0,x1); } else if (x0.max() <= 0) { MinusView mx0(x0); return Rel::EqDom::post(home,mx0,x1); } GECODE_ME_CHECK(x1.gq(home,0)); if (!same(x0,x1)) { (void) new (home) AbsDom(home,x0,x1); } return ES_OK; } template forceinline AbsDom::AbsDom(Space* home, bool share, AbsDom& p) : BinaryPropagator(home,share,p) {} template Actor* AbsDom::copy(Space* home,bool share) { return new (home) AbsDom(home,share,*this); } template PropCost AbsDom::cost(void) const { if (View::pme(this) == ME_INT_VAL) return PC_UNARY_LO; if (View::pme(this) == ME_INT_DOM) return PC_BINARY_HI; return PC_BINARY_LO; } template ExecStatus AbsDom::propagate(Space* home) { if (View::pme(this) != ME_INT_DOM) { ExecStatus es = prop_bnd(home, x0, x1); if (es != ES_NOFIX) return es; return this->ES_NOFIX_PARTIAL(View::pme(ME_INT_DOM)); } Iter::Ranges::Singleton positive(0, Limits::Int::int_max); Iter::Ranges::Singleton negative(Limits::Int::int_min, 0); IntVarRanges xr1(x0); IntVarRanges xr2(x0); Iter::Ranges::Inter posInter(positive, xr1); Iter::Ranges::Inter negInter(negative, xr2); Iter::Ranges::Minus > mneg(negInter); Iter::Ranges::Union, Iter::Ranges::Minus > > u(posInter, mneg); GECODE_ME_CHECK(x1.inter(home, u)); IntVarRanges x1r1(x1); IntVarRanges x1r2(x1); Iter::Ranges::Minus x1m(x1r2); Iter::Ranges::Union > u2(x1r1,x1m); GECODE_ME_CHECK(x0.inter(home, u2)); if (x1.assigned()) return ES_SUBSUMED; if (x0.min() >= 0) { return (Rel::EqDom::post(home,x0,x1) == ES_FAILED) ? ES_FAILED : ES_SUBSUMED; } if (x0.max() <= 0) { MinusView mx0(x0); return (Rel::EqDom::post(home,mx0,x1) == ES_FAILED) ? ES_FAILED : ES_SUBSUMED; } return ES_FIX; } }}} // STATISTICS: int-prop