/* -*- 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 { /* * Binary linear propagators * */ template forceinline LinBin::LinBin(Home home, A y0, B y1, Val c0) : Propagator(home), x0(y0), x1(y1), c(c0) { x0.subscribe(home,*this,pc); x1.subscribe(home,*this,pc); } template forceinline LinBin::LinBin(Space& home, bool share, LinBin& p) : Propagator(home,share,p), c(p.c) { x0.update(home,share,p.x0); x1.update(home,share,p.x1); } template forceinline LinBin::LinBin(Space& home, bool share, Propagator& p, A y0, B y1, Val c0) : Propagator(home,share,p), c(c0) { x0.update(home,share,y0); x1.update(home,share,y1); } template PropCost LinBin::cost(const Space&, const ModEventDelta&) const { return PropCost::binary(PropCost::LO); } template forceinline size_t LinBin::dispose(Space& home) { x0.cancel(home,*this,pc); x1.cancel(home,*this,pc); (void) Propagator::dispose(home); return sizeof(*this); } /* * Binary reified linear propagators * */ template forceinline ReLinBin::ReLinBin(Home home, A y0, B y1, Val c0, Ctrl b0) : Propagator(home), x0(y0), x1(y1), c(c0), b(b0) { x0.subscribe(home,*this,pc); x1.subscribe(home,*this,pc); b.subscribe(home,*this,PC_INT_VAL); } template forceinline ReLinBin::ReLinBin(Space& home, bool share, ReLinBin& p) : Propagator(home,share,p), c(p.c) { x0.update(home,share,p.x0); x1.update(home,share,p.x1); b.update(home,share,p.b); } template PropCost ReLinBin::cost(const Space&, const ModEventDelta&) const { return PropCost::binary(PropCost::LO); } template forceinline size_t ReLinBin::dispose(Space& home) { x0.cancel(home,*this,pc); x1.cancel(home,*this,pc); b.cancel(home,*this,PC_BOOL_VAL); (void) Propagator::dispose(home); return sizeof(*this); } /* * Binary bounds consistent linear equality * */ template forceinline EqBin::EqBin(Home home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus EqBin::post(Home home, A x0, B x1, Val c) { (void) new (home) EqBin(home,x0,x1,c); return ES_OK; } template forceinline EqBin::EqBin(Space& home, bool share, EqBin& p) : LinBin(home,share,p) {} template forceinline EqBin::EqBin(Space& home, bool share, Propagator& p, A x0, B x1, Val c) : LinBin(home,share,p,x0,x1,c) {} template Actor* EqBin::copy(Space& home, bool share) { return new (home) EqBin(home,share,*this); } /// Describe which view has been modified how enum BinMod { BM_X0_MIN = 1<<0, BM_X0_MAX = 1<<1, BM_X1_MIN = 1<<2, BM_X1_MAX = 1<<3, BM_ALL = BM_X0_MIN|BM_X0_MAX|BM_X1_MIN|BM_X1_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 EqBin::propagate(Space& home, const ModEventDelta&) { int bm = BM_ALL; do { GECODE_INT_PV(BM_X0_MIN, x0.gq(home,c-x1.max()), BM_X1_MAX); GECODE_INT_PV(BM_X1_MIN, x1.gq(home,c-x0.max()), BM_X0_MAX); GECODE_INT_PV(BM_X0_MAX, x0.lq(home,c-x1.min()), BM_X1_MIN); GECODE_INT_PV(BM_X1_MAX, x1.lq(home,c-x0.min()), BM_X0_MIN); } while (bm); return x0.assigned() ? home.ES_SUBSUMED(*this) : ES_FIX; } #undef GECODE_INT_PV /* * Reified binary bounds consistent linear equality * */ template forceinline ReEqBin::ReEqBin(Home home, A x0, B x1, Val c, Ctrl b) : ReLinBin(home,x0,x1,c,b) {} template ExecStatus ReEqBin::post(Home home, A x0, B x1, Val c, Ctrl b) { (void) new (home) ReEqBin(home,x0,x1,c,b); return ES_OK; } template forceinline ReEqBin::ReEqBin(Space& home, bool share, ReEqBin& p) : ReLinBin(home,share,p) {} template Actor* ReEqBin::copy(Space& home, bool share) { return new (home) ReEqBin(home,share,*this); } template ExecStatus ReEqBin::propagate(Space& home, const ModEventDelta&) { if (b.zero()) GECODE_REWRITE(*this,(NqBin::post(home(*this),x0,x1,c))); if (b.one()) GECODE_REWRITE(*this,(EqBin::post(home(*this),x0,x1,c))); if ((x0.min() + x1.min() > c) || (x0.max() + x1.max() < c)) { GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); } if (x0.assigned() && x1.assigned()) { assert(x0.val() + x1.val() == c); GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); } return ES_FIX; } /* * Binary domain consistent linear disequality * */ template forceinline NqBin::NqBin(Home home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus NqBin::post(Home home, A x0, B x1, Val c) { (void) new (home) NqBin(home,x0,x1,c); return ES_OK; } template forceinline NqBin::NqBin(Space& home, bool share, NqBin& p) : LinBin(home,share,p) {} template Actor* NqBin::copy(Space& home, bool share) { return new (home) NqBin(home,share,*this); } template forceinline NqBin::NqBin(Space& home, bool share, Propagator& p, A x0, B x1, Val c) : LinBin(home,share,p,x0,x1,c) {} template PropCost NqBin::cost(const Space&, const ModEventDelta&) const { return PropCost::unary(PropCost::LO); } template ExecStatus NqBin::propagate(Space& home, const ModEventDelta&) { if (x0.assigned()) { GECODE_ME_CHECK(x1.nq(home,c-x0.val())); } else { assert(x1.assigned()); GECODE_ME_CHECK(x0.nq(home,c-x1.val())); } return home.ES_SUBSUMED(*this); } /* * Binary domain consistent less equal * */ template forceinline LqBin::LqBin(Home home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus LqBin::post(Home home, A x0, B x1, Val c) { (void) new (home) LqBin(home,x0,x1,c); return ES_OK; } template forceinline LqBin::LqBin(Space& home, bool share, LqBin& p) : LinBin(home,share,p) {} template Actor* LqBin::copy(Space& home, bool share) { return new (home) LqBin(home,share,*this); } template forceinline LqBin::LqBin(Space& home, bool share, Propagator& p, A x0, B x1, Val c) : LinBin(home,share,p,x0,x1,c) {} template ExecStatus LqBin::propagate(Space& home, const ModEventDelta&) { GECODE_ME_CHECK(x0.lq(home,c-x1.min())); GECODE_ME_CHECK(x1.lq(home,c-x0.min())); return (x0.max()+x1.max() <= c) ? home.ES_SUBSUMED(*this) : ES_FIX; } /* * Binary domain consistent greater equal * */ template forceinline GqBin::GqBin(Home home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus GqBin::post(Home home, A x0, B x1, Val c) { (void) new (home) GqBin(home,x0,x1,c); return ES_OK; } template forceinline GqBin::GqBin(Space& home, bool share, GqBin& p) : LinBin(home,share,p) {} template Actor* GqBin::copy(Space& home, bool share) { return new (home) GqBin(home,share,*this); } template forceinline GqBin::GqBin(Space& home, bool share, Propagator& p, A x0, B x1, Val c) : LinBin(home,share,p,x0,x1,c) {} template ExecStatus GqBin::propagate(Space& home, const ModEventDelta&) { GECODE_ME_CHECK(x0.gq(home,c-x1.max())); GECODE_ME_CHECK(x1.gq(home,c-x0.max())); return (x0.min()+x1.min() >= c) ? home.ES_SUBSUMED(*this) : ES_FIX; } /* * Reified binary domain consistent less equal * */ template forceinline ReLqBin::ReLqBin(Home home, A x0, B x1, Val c, BoolView b) : ReLinBin(home,x0,x1,c,b) {} template ExecStatus ReLqBin::post(Home home, A x0, B x1, Val c, BoolView b) { (void) new (home) ReLqBin(home,x0,x1,c,b); return ES_OK; } template forceinline ReLqBin::ReLqBin(Space& home, bool share, ReLqBin& p) : ReLinBin(home,share,p) {} template Actor* ReLqBin::copy(Space& home, bool share) { return new (home) ReLqBin(home,share,*this); } template ExecStatus ReLqBin::propagate(Space& home, const ModEventDelta&) { if (b.one()) GECODE_REWRITE(*this,(LqBin::post(home(*this),x0,x1,c))); if (b.zero()) GECODE_REWRITE(*this,(GqBin::post(home(*this),x0,x1,c+1))); if (x0.max() + x1.max() <= c) { GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); } if (x0.min() + x1.min() > c) { GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); } return ES_FIX; } }}} // STATISTICS: int-prop