/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2003 * * Last modified: * $Date: 2008-01-31 18:29:16 +0100 (Thu, 31 Jan 2008) $ by $Author: tack $ * $Revision: 6017 $ * * 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 Count { /* * General baseclass * */ template forceinline BaseView::BaseView(Space* home, ViewArray& x0, VY y0, VZ z0, int c0) : Propagator(home), x(x0), y(y0), z(z0), c(c0) { x.subscribe(home,this,PC_INT_DOM); y.subscribe(home,this,PC_INT_DOM); z.subscribe(home,this,PC_INT_BND); } template forceinline BaseView::BaseView(Space* home, bool share, BaseView& p) : Propagator(home,shr,p), c(p.c) { x.update(home,share,p.x); y.update(home,share,p.y); z.update(home,share,p.z); } template PropCost BaseView::cost(ModEventDelta) const { return cost_lo(x.size()+1, PC_LINEAR_LO); } template Reflection::ActorSpec BaseView::spec(const Space* home, Reflection::VarMap& m, const Support::Symbol& ati) const { Reflection::ActorSpec s(ati); return s << x.spec(home, m) << y.spec(home, m) << z.spec(home, m) << c; } template forceinline size_t BaseView::dispose(Space* home) { assert(!home->failed()); x.cancel(home,this,PC_INT_DOM); y.cancel(home,this,PC_INT_DOM); z.cancel(home,this,PC_INT_BND); (void) Propagator::dispose(home); return sizeof(*this); } template forceinline void BaseView::count(Space* home) { int n = x.size(); for (int i=n; i--; ) switch (holds(x[i],y)) { case RT_FALSE: x[i].cancel(home,this,PC_INT_DOM); x[i]=x[--n]; break; case RT_TRUE: x[i].cancel(home,this,PC_INT_DOM); x[i]=x[--n]; c--; break; case RT_MAYBE: break; default: GECODE_NEVER; } x.size(n); } template forceinline int BaseView::atleast(void) const { return -c; } template forceinline int BaseView::atmost(void) const { return x.size()-c; } template forceinline bool BaseView::sharing(const ViewArray& x, const VY& y, const VZ& z) { if (shared(y,z)) return true; for (int i = x.size(); i--; ) if (shared(x[i],z)) return true; return false; } /* * Equality * */ template forceinline EqView::EqView(Space* home, ViewArray& x, VY y, VZ z, int c) : BaseView(home,x,y,z,c) {} template ExecStatus EqView::post(Space* home, ViewArray& x, VY y, VZ z, int c) { if (z.assigned()) return EqInt::post(home,x,y,z.val()+c); if (sharing(x,y,z)) (void) new (home) EqView(home,x,y,z,c); else (void) new (home) EqView(home,x,y,z,c); return ES_OK; } template forceinline EqView::EqView(Space* home, bool share, EqView& p) : BaseView(home,share,p) {} template Actor* EqView::copy(Space* home, bool share) { return new (home) EqView(home,share,*this); } template Support::Symbol EqView::ati(void) { return Reflection::mangle("Gecode::Int::Count::EqView"); } template Reflection::ActorSpec EqView::spec(const Space* home, Reflection::VarMap& m) const { return BaseView::spec(home, m, ati()); } template void EqView::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(4); ViewArray x(home, vars, spec[0]); VY y(home, vars, spec[1]); VZ z(home, vars, spec[2]); int c = spec[3]->toInt(); (void) new (home) EqView(home, x, y, z, c); } template ExecStatus EqView::propagate(Space* home, ModEventDelta) { count(home); GECODE_ME_CHECK(z.gq(home,atleast())); GECODE_ME_CHECK(z.lq(home,atmost())); if (z.assigned()) { if (z.val() == atleast()) return post_false(home,x,y) ? ES_FAILED : ES_SUBSUMED(this,home); if (z.val() == atmost()) return post_true(home,x,y) ? ES_FAILED : ES_SUBSUMED(this,home); GECODE_REWRITE(this,(EqInt::post(home,x,y,z.val()+c))); } return shr ? ES_NOFIX : ES_FIX; } /* * Disequality * */ template forceinline NqView::NqView(Space* home, ViewArray& x, VY y, VZ z, int c) : BaseView(home,x,y,z,c) {} template ExecStatus NqView::post(Space* home, ViewArray& x, VY y, VZ z, int c) { if (z.assigned()) return NqInt::post(home,x,y,z.val()+c); (void) new (home) NqView(home,x,y,z,c); return ES_OK; } template forceinline NqView::NqView(Space* home, bool share, NqView& p) : BaseView(home,share,p) {} template Actor* NqView::copy(Space* home, bool share) { return new (home) NqView(home,share,*this); } template Support::Symbol NqView::ati(void) { return Reflection::mangle("Gecode::Int::Count::NqView"); } template Reflection::ActorSpec NqView::spec(const Space* home, Reflection::VarMap& m) const { return BaseView::spec(home, m, ati()); } template void NqView::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(4); ViewArray x(home, vars, spec[0]); VY y(home, vars, spec[1]); VZ z(home, vars, spec[2]); int c = spec[3]->toInt(); (void) new (home) NqView(home, x, y, z, c); } template ExecStatus NqView::propagate(Space* home, ModEventDelta) { count(home); if (atleast() == atmost()) { GECODE_ME_CHECK(z.nq(home,atleast())); return ES_SUBSUMED(this,home); } if (z.max() < atleast()) return ES_SUBSUMED(this,home); if (z.min() > atmost()) return ES_SUBSUMED(this,home); if (z.assigned()) GECODE_REWRITE(this,(NqInt::post(home,x,y,z.val()+c))); return ES_FIX; } /* * Less or equal * */ template forceinline LqView::LqView(Space* home, ViewArray& x, VY y, VZ z, int c) : BaseView(home,x,y,z,c) {} template ExecStatus LqView::post(Space* home, ViewArray& x, VY y, VZ z, int c) { if (z.assigned()) return LqInt::post(home,x,y,z.val()+c); if (sharing(x,y,z)) (void) new (home) LqView(home,x,y,z,c); else (void) new (home) LqView(home,x,y,z,c); return ES_OK; } template forceinline LqView::LqView(Space* home, bool share, LqView& p) : BaseView(home,share,p) {} template Actor* LqView::copy(Space* home, bool share) { return new (home) LqView(home,share,*this); } template Support::Symbol LqView::ati(void) { return Reflection::mangle("Gecode::Int::Count::LqView"); } template Reflection::ActorSpec LqView::spec(const Space* home, Reflection::VarMap& m) const { return BaseView::spec(home, m, ati()); } template void LqView::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(4); ViewArray x(home, vars, spec[0]); VY y(home, vars, spec[1]); VZ z(home, vars, spec[2]); int c = spec[3]->toInt(); (void) new (home) LqView(home, x, y, z, c); } template ExecStatus LqView::propagate(Space* home, ModEventDelta) { count(home); GECODE_ME_CHECK(z.gq(home,atleast())); if (z.max() == atleast()) return post_false(home,x,y) ? ES_FAILED : ES_SUBSUMED(this,home); if (x.size() == 0) return ES_SUBSUMED(this,home); if (z.assigned()) GECODE_REWRITE(this,(LqInt::post(home,x,y,z.val()+c))); return shr ? ES_NOFIX : ES_FIX; } /* * Greater or equal * */ template forceinline GqView::GqView(Space* home, ViewArray& x, VY y, VZ z, int c) : BaseView(home,x,y,z,c) {} template ExecStatus GqView::post(Space* home, ViewArray& x, VY y, VZ z, int c) { if (z.assigned()) return GqInt::post(home,x,y,z.val()+c); if (sharing(x,y,z)) (void) new (home) GqView(home,x,y,z,c); else (void) new (home) GqView(home,x,y,z,c); return ES_OK; } template forceinline GqView::GqView(Space* home, bool share, GqView& p) : BaseView(home,share,p) {} template Actor* GqView::copy(Space* home, bool share) { return new (home) GqView(home,share,*this); } template Support::Symbol GqView::ati(void) { return Reflection::mangle("Gecode::Int::Count::GqView"); } template Reflection::ActorSpec GqView::spec(const Space* home, Reflection::VarMap& m) const { return BaseView::spec(home, m, ati()); } template void GqView::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(4); ViewArray x(home, vars, spec[0]); VY y(home, vars, spec[1]); VZ z(home, vars, spec[2]); int c = spec[3]->toInt(); (void) new (home) GqView(home, x, y, z, c); } template ExecStatus GqView::propagate(Space* home, ModEventDelta) { count(home); GECODE_ME_CHECK(z.lq(home,atmost())); if (z.min() == atmost()) return post_true(home,x,y) ? ES_FAILED : ES_SUBSUMED(this,home); if (x.size() == 0) return ES_SUBSUMED(this,home); if (z.assigned()) GECODE_REWRITE(this,(GqInt::post(home,x,y,z.val()+c))); return shr ? ES_NOFIX : ES_FIX; } }}} // STATISTICS: int-prop