/* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2003 * * 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. * */ namespace Gecode { namespace Int { namespace Linear { /* * Ternary linear propagators * */ template forceinline LinTer::LinTer(Space* home, A y0, B y1, C y2, Val c0) : Propagator(home), x0(y0), x1(y1), x2(y2), c(c0) { x0.subscribe(home,this,pc); x1.subscribe(home,this,pc); x2.subscribe(home,this,pc); } template forceinline LinTer::LinTer(Space* home, bool share, LinTer& p) : Propagator(home,share,p), c(p.c) { x0.update(home,share,p.x0); x1.update(home,share,p.x1); x2.update(home,share,p.x2); } template forceinline LinTer::LinTer(Space* home, bool share, Propagator& p, A y0, B y1, C y2, Val c0) : Propagator(home,share,p), c(c0) { x0.update(home,share,y0); x1.update(home,share,y1); x2.update(home,share,y2); } template PropCost LinTer::cost(void) const { return PC_TERNARY_LO; } template size_t LinTer::dispose(Space* home) { assert(!home->failed()); x0.cancel(home,this,pc); x1.cancel(home,this,pc); x2.cancel(home,this,pc); (void) Propagator::dispose(home); return sizeof(*this); } /* * Equality propagator * */ template forceinline EqTer::EqTer(Space* home, A x0, B x1, C x2, Val c) : LinTer(home,x0,x1,x2,c) {} template ExecStatus EqTer::post(Space* home, A x0, B x1, C x2, Val c) { (void) new (home) EqTer(home,x0,x1,x2,c); return ES_OK; } template forceinline EqTer::EqTer(Space* home, bool share, EqTer& p) : LinTer(home,share,p) {} template forceinline EqTer::EqTer(Space* home, bool share, Propagator& p, A x0, B x1, C x2, Val c) : LinTer(home,share,p,x0,x1,x2,c) {} template Actor* EqTer::copy(Space* home, bool share) { return new (home) EqTer(home,share,*this); } /// Describe which view has been modified how enum TerMod { TM_X0_MIN = 1<<0, TM_X0_MAX = 1<<1, TM_X1_MIN = 1<<2, TM_X1_MAX = 1<<3, TM_X2_MIN = 1<<4, TM_X2_MAX = 1<<5, TM_ALL = TM_X0_MIN|TM_X0_MAX|TM_X1_MIN|TM_X1_MAX|TM_X2_MIN|TM_X2_MAX }; #define GECODE_INT_PV(CASE,TELL,UPDATE) \ if (bm & (CASE)) { \ bm -= (CASE); ModEvent me = (TELL); \ if (me_failed(me)) return ES_FAILED; \ if (me_modified(me)) bm |= (UPDATE); \ } template ExecStatus EqTer::propagate(Space* home) { int bm = TM_ALL; do { GECODE_INT_PV(TM_X0_MIN, x0.gq(home,c-x1.max()-x2.max()), TM_X1_MAX | TM_X2_MAX); GECODE_INT_PV(TM_X1_MIN, x1.gq(home,c-x0.max()-x2.max()), TM_X0_MAX | TM_X2_MAX); GECODE_INT_PV(TM_X2_MIN, x2.gq(home,c-x0.max()-x1.max()), TM_X0_MAX | TM_X1_MAX); GECODE_INT_PV(TM_X0_MAX, x0.lq(home,c-x1.min()-x2.min()), TM_X1_MIN | TM_X2_MIN); GECODE_INT_PV(TM_X1_MAX, x1.lq(home,c-x0.min()-x2.min()), TM_X0_MIN | TM_X2_MIN); GECODE_INT_PV(TM_X2_MAX, x2.lq(home,c-x0.min()-x1.min()), TM_X0_MIN | TM_X1_MIN); } while (bm); return (x0.assigned() && x1.assigned()) ? ES_SUBSUMED : ES_FIX; } #undef GECODE_INT_PV /* * Disequality propagator * */ template forceinline NqTer::NqTer(Space* home, A x0, B x1, C x2, Val c) : LinTer(home,x0,x1,x2,c) {} template ExecStatus NqTer::post(Space* home, A x0, B x1, C x2, Val c) { (void) new (home) NqTer(home,x0,x1,x2,c); return ES_OK; } template forceinline NqTer::NqTer(Space* home, bool share, NqTer& p) : LinTer(home,share,p) {} template Actor* NqTer::copy(Space* home, bool share) { return new (home) NqTer(home,share,*this); } template forceinline NqTer::NqTer(Space* home, bool share, Propagator& p, A x0, B x1, C x2, Val c) : LinTer(home,share,p,x0,x1,x2,c) {} template ExecStatus NqTer::propagate(Space* home) { if (x0.assigned() && x1.assigned()) { GECODE_ME_CHECK(x2.nq(home,c-x0.val()-x1.val())); return ES_SUBSUMED; } if (x0.assigned() && x2.assigned()) { GECODE_ME_CHECK(x1.nq(home,c-x0.val()-x2.val())); return ES_SUBSUMED; } if (x1.assigned() && x2.assigned()) { GECODE_ME_CHECK(x0.nq(home,c-x1.val()-x2.val())); return ES_SUBSUMED; } return ES_FIX; } /* * Inequality propagator * */ template forceinline LqTer::LqTer(Space* home, A x0, B x1, C x2, Val c) : LinTer(home,x0,x1,x2,c) {} template ExecStatus LqTer::post(Space* home, A x0, B x1, C x2, Val c) { (void) new (home) LqTer(home,x0,x1,x2,c); return ES_OK; } template forceinline LqTer::LqTer(Space* home, bool share, LqTer& p) : LinTer(home,share,p) {} template Actor* LqTer::copy(Space* home, bool share) { return new (home) LqTer(home,share,*this); } template forceinline LqTer::LqTer(Space* home, bool share, Propagator& p, A x0, B x1, C x2, Val c) : LinTer(home,share,p,x0,x1,x2,c) {} template ExecStatus LqTer::propagate(Space* home) { GECODE_ME_CHECK(x0.lq(home,c-x1.min()-x2.min())); GECODE_ME_CHECK(x1.lq(home,c-x0.min()-x2.min())); GECODE_ME_CHECK(x2.lq(home,c-x0.min()-x1.min())); return (x0.max()+x1.max()+x2.max() <= c) ? ES_SUBSUMED : ES_FIX; } }}} // STATISTICS: int-prop