/* * Main authors: * Christian Schulte * * Contributing authors: * Mikael Lagerkvist * * Copyright: * Christian Schulte, 2006 * Mikael Lagerkvist, 2006 * * Last modified: * $Date: 2006-08-04 16:03:26 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $ * $Revision: 3512 $ * * 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. * */ #include "gecode/iter.hh" namespace Gecode { namespace Int { namespace Channel { /** * \brief Combine view with information for value propagation * */ template class ValInfo { public: /// The view View view; /// Whether it has been propagated that view is assigned bool a; /// Allocate memory from space \a home for \a n elements static ValInfo* allocate(Space* home, int n); /// Initialize void init(View x, int n); /// Update during cloning void update(Space* home, bool share, ValInfo& vi); /// Check whether propagation for assignment is to be done bool doval(void) const; /// Check whether propagation for domain is to be done bool dodom(void) const; /// Record that view got assigned void assigned(void); /// Record that one value got removed void removed(int i); /// Update the cardinality and bounds information after pruning void done(void); }; template forceinline ValInfo* ValInfo::allocate(Space* home, int n) { return reinterpret_cast*> (home->alloc(n*sizeof(ValInfo))); } template forceinline void ValInfo::init(View x, int) { view = x; a = false; } template forceinline void ValInfo::update(Space* home, bool share, ValInfo& vi) { view.update(home,share,vi.view); a = vi.a; } template forceinline bool ValInfo::doval(void) const { return !a && view.assigned(); } template forceinline bool ValInfo::dodom(void) const { return false; } template forceinline void ValInfo::assigned(void) { a = true; } template forceinline void ValInfo::removed(int) {} template forceinline void ValInfo::done(void) {} // Propagate assigned views for x template ExecStatus doprop_val(Space* home, int n, Info* x, Info* y, int& n_na, ProcessStack& xa, ProcessStack& ya) { do { int i = xa.pop(); int j = x[i].view.val(); // Assign the y variable to i (or test if already assigned!) { ModEvent me = y[j].view.eq(home,i); if (me_failed(me)) return ES_FAILED; // Record that y[j] has been assigned and must be propagated if (me_modified(me)) ya.push(j); } // Prune the value j from all x variables for (int k=i; k--; ) { ModEvent me = x[k].view.nq(home,j); if (me_failed(me)) return ES_FAILED; if (me_modified(me)) if (me == ME_INT_VAL) { // Record that x[k] has been assigned and must be propagated xa.push(k); } else { // One value has been removed and this removal does not need // to be propagated again: after all y[j] = i, so it holds // that y[j] != k. x[k].removed(j); } } // The same for the other views for (int k=i+1; k forceinline ExecStatus prop_val(Space* home, int n, Info* x, Info* y, int& n_na, ProcessStack& xa, ProcessStack& ya) { if (xa.empty()) return ES_OK; return doprop_val(home,n,x,y,n_na,xa,ya); } /* * The actual propagator * */ template forceinline Val::Val(Space* home, int n, ValInfo* xy) : Base,PC_INT_VAL>(home,n,xy) {} template forceinline Val::Val(Space* home, bool share, Val& p) : Base,PC_INT_VAL>(home,share,p) {} template Actor* Val::copy(Space* home, bool share) { return new (home) Val(home,share,*this); } template ExecStatus Val::propagate(Space* home) { GECODE_AUTOARRAY(int, __xa, n+1); GECODE_AUTOARRAY(int, __ya, n+1); ProcessStack xa(__xa); ProcessStack ya(__ya); ValInfo* x = xy; ValInfo* y = xy+n; // Scan x and y for assigned but not yet propagated views for (int i = n; i--; ) { if (x[i].doval()) xa.push(i); if (y[i].doval()) ya.push(i); } do { // Propagate assigned views for x if (prop_val >(home,n,x,y,n_na,xa,ya) == ES_FAILED) return ES_FAILED; // Propagate assigned views for y if (prop_val >(home,n,y,x,n_na,ya,xa) == ES_FAILED) return ES_FAILED; assert(ya.empty()); } while (!xa.empty()); return (n_na == 0) ? ES_SUBSUMED : ES_FIX; } template ExecStatus Val::post(Space* home, int n, ValInfo* xy) { assert(n > 0); if (n == 1) { GECODE_ME_CHECK(xy[0].view.eq(home,0)); GECODE_ME_CHECK(xy[1].view.eq(home,0)); return ES_OK; } for (int i=2*n; i--; ) { GECODE_ME_CHECK(xy[i].view.gq(home,0)); GECODE_ME_CHECK(xy[i].view.le(home,n)); } (void) new (home) Val(home,n,xy); return ES_OK; } }}} // STATISTICS: int-prop