/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Mikael Lagerkvist * * Copyright: * Mikael Lagerkvist, 2007 * * 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 Extensional { /* * The propagator proper * */ template forceinline Basic::Basic(Space* home, ViewArray& x, const TupleSet& t) : Base(home,x,t) { } template ExecStatus Basic::post(Space* home, ViewArray& x, const TupleSet& t) { (void) new (home) Basic(home,x,t); return ES_OK; } template forceinline Basic::Basic(Space* home, bool share, Basic& p) : Base(home,share,p) { } template PropCost Basic::cost(ModEventDelta med) const { return (View::me(med) == ME_INT_VAL) ? PC_QUADRATIC_HI : PC_CUBIC_HI; } template Actor* Basic::copy(Space* home, bool share) { return new (home) Basic(home,share,*this); } template Gecode::Support::Symbol Basic::ati(void) { return Reflection::mangle("Gecode::Int::Extensional::Basic"); } template Reflection::ActorSpec Basic::spec(const Space* home, Reflection::VarMap& m) const { Reflection::ActorSpec s(ati()); return s << x.spec(home, m) << tupleSet.spec(m); } template void Basic::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(2); ViewArray x(home, vars, spec[0]); TupleSet tupleSet(vars, spec[1]); (void) new (home) Basic(home,x,tupleSet); } template ExecStatus Basic::propagate(Space* home, ModEventDelta) { ///// Domain consistent propagation //// Set up datastructures /// Bit-sets for amortized O(1) access to domains GECODE_AUTOARRAY(BitSet, dom, x.size()); init_dom(home, dom); /// Bit-sets for processed values. GECODE_AUTOARRAY(BitSet, has_support, x.size()); for (int i = x.size(); i--; ) has_support[i].init(home, ts()->domsize); /// Values to prune GECODE_AUTOARRAY(int,nq, ts()->domsize*x.size()); int n_nq = 0; ExecStatus es = ES_FIX; //// Run algorithm /// Check consistency for each variable-value pair for (int var = x.size(); var--; ) { for (ViewValues vv(x[var]); vv(); ++vv) { // Value offset for indexing int val = vv.val() - ts()->min; if (!has_support[var].get(val)) { // Find support for value vv.val() in variable var Tuple l = find_support(dom, var, val); if (l == NULL) { // No possible supports left nq[n_nq] = vv.val(); n_nq++; } else { // Mark values as supported // Only forward direction marking is needed since all // previous values have been checked for (int i = var; i--; ) { has_support[i].set(l[i]- ts()->min); assert(has_support[i].get(l[i]- ts()->min)); } } } } // Prune values for var which do not have support anymore while (n_nq-- > 0) { ModEvent me = x[var].nq(home,nq[n_nq]); if (me_failed(me)) return ES_FAILED; if (me_modified(me)) es = ES_NOFIX; } n_nq = 0; } for (int i = x.size(); i--; ) if (!x[i].assigned()) return es; return ES_SUBSUMED(this, home); } }}} // STATISTICS: int-prop