/* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2003 * * Last modified: * $Date: 2006-09-07 11:57:31 +0200 (Thu, 07 Sep 2006) $ by $Author: schulte $ * $Revision: 3612 $ * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * See the file "LICENSE" for information on usage and * redistribution of this file, and for a * DISCLAIMER OF ALL WARRANTIES. * */ namespace Gecode { namespace Int { namespace Count { /* * General baseclass * */ template 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 inline 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(void) const { return cost_lo(x.size()+1, PC_LINEAR_LO); } template 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 inline 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 ExecStatus EqView::propagate(Space* home) { 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); if (z.val() == atmost()) return post_true(home,x,y); GECODE_ES_CHECK((EqInt::post(home,x,y,z.val()+c))); return ES_SUBSUMED; } 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 ExecStatus NqView::propagate(Space* home) { count(home); if (atleast() == atmost()) { GECODE_ME_CHECK(z.nq(home,atleast())); return ES_SUBSUMED; } if (z.max() < atleast()) return ES_SUBSUMED; if (z.min() > atmost()) return ES_SUBSUMED; if (z.assigned()) { GECODE_ES_CHECK((NqInt::post(home,x,y,z.val()+c))); return ES_SUBSUMED; } 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 ExecStatus LqView::propagate(Space* home) { count(home); GECODE_ME_CHECK(z.gq(home,atleast())); if (z.max() == atleast()) return post_false(home,x,y); if (x.size() == 0) return ES_SUBSUMED; if (z.assigned()) { GECODE_ES_CHECK((LqInt::post(home,x,y,z.val()+c))); return ES_SUBSUMED; } 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 ExecStatus GqView::propagate(Space* home) { count(home); GECODE_ME_CHECK(z.lq(home,atmost())); if (z.min() == atmost()) return post_true(home,x,y); if (x.size() == 0) return ES_SUBSUMED; if (z.assigned()) { GECODE_ES_CHECK((GqInt::post(home,x,y,z.val()+c))); return ES_SUBSUMED; } return shr ? ES_NOFIX : ES_FIX; } }}} // STATISTICS: int-prop