/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2003 * * 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, LinBin& p) : Propagator(home,p), c(p.c) { x0.update(home,p.x0); x1.update(home,p.x1); } template forceinline LinBin::LinBin(Space& home, Propagator& p, A y0, B y1, Val c0) : Propagator(home,p), c(c0) { x0.update(home,y0); x1.update(home,y1); } template PropCost LinBin::cost(const Space&, const ModEventDelta&) const { return PropCost::binary(PropCost::LO); } template void LinBin::reschedule(Space& home) { x0.reschedule(home,*this,pc); x1.reschedule(home,*this,pc); } 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, ReLinBin& p) : Propagator(home,p), c(p.c) { x0.update(home,p.x0); x1.update(home,p.x1); b.update(home,p.b); } template PropCost ReLinBin::cost(const Space&, const ModEventDelta&) const { return PropCost::binary(PropCost::LO); } template void ReLinBin::reschedule(Space& home) { x0.reschedule(home,*this,pc); x1.reschedule(home,*this,pc); b.reschedule(home,*this,PC_INT_VAL); } 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, EqBin& p) : LinBin(home,p) {} template forceinline EqBin::EqBin(Space& home, Propagator& p, A x0, B x1, Val c) : LinBin(home,p,x0,x1,c) {} template Actor* EqBin::copy(Space& home) { return new (home) EqBin(home,*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, ReEqBin& p) : ReLinBin(home,p) {} template Actor* ReEqBin::copy(Space& home) { return new (home) ReEqBin(home,*this); } template ExecStatus ReEqBin::propagate(Space& home, const ModEventDelta&) { if (b.zero()) { if (rm == RM_IMP) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(NqBin::post(home(*this),x0,x1,c))); } if (b.one()) { if (rm == RM_PMI) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(EqBin::post(home(*this),x0,x1,c))); } if ((x0.min() + x1.min() > c) || (x0.max() + x1.max() < c)) { if (rm != RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); } if (x0.assigned() && x1.assigned()) { assert(x0.val() + x1.val() == c); if (rm != RM_IMP) 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, NqBin& p) : LinBin(home,p) {} template Actor* NqBin::copy(Space& home) { return new (home) NqBin(home,*this); } template forceinline NqBin::NqBin(Space& home, Propagator& p, A x0, B x1, Val c) : LinBin(home,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, LqBin& p) : LinBin(home,p) {} template Actor* LqBin::copy(Space& home) { return new (home) LqBin(home,*this); } template forceinline LqBin::LqBin(Space& home, Propagator& p, A x0, B x1, Val c) : LinBin(home,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, GqBin& p) : LinBin(home,p) {} template Actor* GqBin::copy(Space& home) { return new (home) GqBin(home,*this); } template forceinline GqBin::GqBin(Space& home, Propagator& p, A x0, B x1, Val c) : LinBin(home,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, ReLqBin& p) : ReLinBin(home,p) {} template Actor* ReLqBin::copy(Space& home) { return new (home) ReLqBin(home,*this); } template ExecStatus ReLqBin::propagate(Space& home, const ModEventDelta&) { if (b.one()) { if (rm == RM_PMI) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(LqBin::post(home(*this),x0,x1,c))); } if (b.zero()) { if (rm == RM_IMP) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(GqBin::post(home(*this),x0,x1,c+1))); } if (x0.max() + x1.max() <= c) { if (rm != RM_IMP) GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); } if (x0.min() + x1.min() > c) { if (rm != RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); } return ES_FIX; } }}} // STATISTICS: int-prop