/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2003 * * Last modified: * $Date: 2008-07-11 09:28:48 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $ * $Revision: 7285 $ * * 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(Space* 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(ModEventDelta) const { return PC_BINARY_LO; } template Reflection::ActorSpec LinBin::spec(const Space* home, Reflection::VarMap& m, const Support::Symbol& ati) const { Reflection::ActorSpec s(ati); return s << x0.spec(home, m) << x1.spec(home, m) << c; } template forceinline size_t LinBin::dispose(Space* home) { assert(!home->failed()); 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(Space* 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(ModEventDelta) const { return PC_BINARY_LO; } template forceinline size_t ReLinBin::dispose(Space* home) { assert(!home->failed()); x0.cancel(home,this,pc); x1.cancel(home,this,pc); b.cancel(home,this,PC_BOOL_VAL); (void) Propagator::dispose(home); return sizeof(*this); } template Reflection::ActorSpec ReLinBin::spec(const Space* home, Reflection::VarMap& m, const Support::Symbol& ati) const { Reflection::ActorSpec s(ati); return s << x0.spec(home, m) << x1.spec(home, m) << c << b.spec(home, m); } /* * Binary bounds consistent linear equality * */ template forceinline EqBin::EqBin(Space* home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus EqBin::post(Space* 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); } template inline Support::Symbol EqBin::ati(void) { return Reflection::mangle("Gecode::Int::Linear::EqBin"); } template Reflection::ActorSpec EqBin::spec(const Space* home, Reflection::VarMap& m) const { return LinBin::spec(home, m, ati()); } template void EqBin::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(3); A x(home, vars, spec[0]); B y(home, vars, spec[1]); Val c = spec[2]->toInt(); (void) new (home) EqBin(home, x, y, c); } /// 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, 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() ? ES_SUBSUMED(this,sizeof(*this)) : ES_FIX; } #undef GECODE_INT_PV /* * Reified binary bounds consistent linear equality * */ template forceinline ReEqBin::ReEqBin(Space* home, A x0, B x1, Val c, Ctrl b) : ReLinBin(home,x0,x1,c,b) {} template ExecStatus ReEqBin::post(Space* 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 inline Support::Symbol ReEqBin::ati(void) { return Reflection::mangle("Gecode::Int::Linear::ReEqBin"); } template Reflection::ActorSpec ReEqBin::spec(const Space* home, Reflection::VarMap& m) const { return ReLinBin::spec(home, m, ati()); } template void ReEqBin::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(4); A x(home, vars, spec[0]); B y(home, vars, spec[1]); Val c = spec[2]->toInt(); Ctrl b(home, vars, spec[3]); (void) new (home) ReEqBin(home, x, y, c, b); } template ExecStatus ReEqBin::propagate(Space* home, ModEventDelta) { if (b.zero()) GECODE_REWRITE(this,(NqBin::post(home,x0,x1,c))); if (b.one()) GECODE_REWRITE(this,(EqBin::post(home,x0,x1,c))); if ((x0.min() + x1.min() > c) || (x0.max() + x1.max() < c)) { GECODE_ME_CHECK(b.zero_none(home)); return ES_SUBSUMED(this,home); } if (x0.assigned() && x1.assigned()) { assert(x0.val() + x1.val() == c); GECODE_ME_CHECK(b.one_none(home)); return ES_SUBSUMED(this,home); } return ES_FIX; } /* * Binary domain consistent linear disequality * */ template forceinline NqBin::NqBin(Space* home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus NqBin::post(Space* 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(ModEventDelta) const { return PC_UNARY_LO; } template inline Support::Symbol NqBin::ati(void) { return Reflection::mangle("Gecode::Int::Linear::NqBin"); } template Reflection::ActorSpec NqBin::spec(const Space* home, Reflection::VarMap& m) const { return LinBin::spec(home, m, ati()); } template void NqBin::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(3); A x(home, vars, spec[0]); B y(home, vars, spec[1]); Val c = spec[2]->toInt(); (void) new (home) NqBin(home, x, y, c); } template ExecStatus NqBin::propagate(Space* home, 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 ES_SUBSUMED(this,home); } /* * Binary domain consistent less equal * */ template forceinline LqBin::LqBin(Space* home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus LqBin::post(Space* 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 inline Support::Symbol LqBin::ati(void) { return Reflection::mangle("Gecode::Int::Linear::LqBin"); } template Reflection::ActorSpec LqBin::spec(const Space* home, Reflection::VarMap& m) const { return LinBin::spec(home, m, ati()); } template void LqBin::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(3); A x(home, vars, spec[0]); B y(home, vars, spec[1]); Val c = spec[2]->toInt(); (void) new (home) LqBin(home, x, y, c); } template ExecStatus LqBin::propagate(Space* home, 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) ? ES_SUBSUMED(this,home) : ES_FIX; } /* * Binary domain consistent greater equal * */ template forceinline GqBin::GqBin(Space* home, A x0, B x1, Val c) : LinBin(home,x0,x1,c) {} template ExecStatus GqBin::post(Space* 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 inline Support::Symbol GqBin::ati(void) { return Reflection::mangle("Gecode::Int::Linear::GqBin"); } template Reflection::ActorSpec GqBin::spec(const Space* home, Reflection::VarMap& m) const { return LinBin::spec(home, m, ati()); } template void GqBin::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(3); A x(home, vars, spec[0]); B y(home, vars, spec[1]); Val c = spec[2]->toInt(); (void) new (home) GqBin(home, x, y, c); } template ExecStatus GqBin::propagate(Space* home, 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) ? ES_SUBSUMED(this,home) : ES_FIX; } /* * Reified binary domain consistent less equal * */ template forceinline ReLqBin::ReLqBin(Space* home, A x0, B x1, Val c, BoolView b) : ReLinBin(home,x0,x1,c,b) {} template ExecStatus ReLqBin::post(Space* 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 Support::Symbol ReLqBin::ati(void) { return Reflection::mangle("Gecode::Int::Linear::ReLqBin"); } template Reflection::ActorSpec ReLqBin::spec(const Space* home, Reflection::VarMap& m) const { return ReLinBin::spec(home, m, ati()); } template void ReLqBin::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(4); A x(home, vars, spec[0]); B y(home, vars, spec[1]); Val c = spec[2]->toInt(); BoolView b(home, vars, spec[3]); (void) new (home) ReLqBin(home, x, y, c, b); } template ExecStatus ReLqBin::propagate(Space* home, ModEventDelta) { if (b.one()) GECODE_REWRITE(this,(LqBin::post(home,x0,x1,c))); if (b.zero()) GECODE_REWRITE(this,(GqBin::post(home,x0,x1,c+1))); if (x0.max() + x1.max() <= c) { GECODE_ME_CHECK(b.one_none(home)); return ES_SUBSUMED(this,home); } if (x0.min() + x1.min() > c) { GECODE_ME_CHECK(b.zero_none(home)); return ES_SUBSUMED(this,home); } return ES_FIX; } }}} // STATISTICS: int-prop