/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2003 * * Last modified: * $Date: 2010-03-04 03:32:21 +1100 (Thu, 04 Mar 2010) $ by $Author: schulte $ * $Revision: 10364 $ * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ namespace Gecode { namespace Int { namespace Linear { /* * Ternary linear propagators * */ template forceinline LinTer::LinTer(Home 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(const Space&, const ModEventDelta&) const { return PropCost::ternary(PropCost::LO); } template forceinline size_t LinTer::dispose(Space& home) { 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(Home home, A x0, B x1, C x2, Val c) : LinTer(home,x0,x1,x2,c) {} template ExecStatus EqTer::post(Home 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, const ModEventDelta&) { 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()) ? home.ES_SUBSUMED(*this) : ES_FIX; } #undef GECODE_INT_PV /* * Disequality propagator * */ template forceinline NqTer::NqTer(Home home, A x0, B x1, C x2, Val c) : LinTer(home,x0,x1,x2,c) {} template ExecStatus NqTer::post(Home 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, const ModEventDelta&) { if (x0.assigned() && x1.assigned()) { GECODE_ME_CHECK(x2.nq(home,c-x0.val()-x1.val())); return home.ES_SUBSUMED(*this); } if (x0.assigned() && x2.assigned()) { GECODE_ME_CHECK(x1.nq(home,c-x0.val()-x2.val())); return home.ES_SUBSUMED(*this); } if (x1.assigned() && x2.assigned()) { GECODE_ME_CHECK(x0.nq(home,c-x1.val()-x2.val())); return home.ES_SUBSUMED(*this); } return ES_FIX; } /* * Inequality propagator * */ template forceinline LqTer::LqTer(Home home, A x0, B x1, C x2, Val c) : LinTer(home,x0,x1,x2,c) {} template ExecStatus LqTer::post(Home 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, const ModEventDelta&) { 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) ? home.ES_SUBSUMED(*this) : ES_FIX; } }}} // STATISTICS: int-prop