/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2008 * * 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 Bool { /* * Boolean clause propagator (disjunctive, true) * */ template forceinline ClauseTrue::ClauseTrue(Home home, ViewArray& x0, ViewArray& y0) : MixBinaryPropagator (home,x0[x0.size()-1],y0[y0.size()-1]), x(x0), y(y0) { assert((x.size() > 0) && (y.size() > 0)); x.size(x.size()-1); y.size(y.size()-1); } template PropCost ClauseTrue::cost(const Space&, const ModEventDelta&) const { return PropCost::binary(PropCost::LO); } template forceinline ClauseTrue::ClauseTrue(Space& home, ClauseTrue& p) : MixBinaryPropagator(home,p) { x.update(home,p.x); y.update(home,p.y); } template Actor* ClauseTrue::copy(Space& home) { { int n = x.size(); if (n > 0) { // Eliminate all zeros and find a one for (int i=n; i--; ) if (x[i].one()) { // Only keep the one x[0]=x[i]; n=1; break; } else if (x[i].zero()) { // Eliminate the zero x[i]=x[--n]; } x.size(n); } } { int n = y.size(); if (n > 0) { // Eliminate all zeros and find a one for (int i=n; i--; ) if (y[i].one()) { // Only keep the one y[0]=y[i]; n=1; break; } else if (y[i].zero()) { // Eliminate the zero y[i]=y[--n]; } y.size(n); } } if ((x.size() == 0) && (y.size() == 0)) return new (home) BinOrTrue(home,*this,x0,x1); else return new (home) ClauseTrue(home,*this); } template inline ExecStatus ClauseTrue::post(Home home, ViewArray& x, ViewArray& y) { for (int i=x.size(); i--; ) if (x[i].one()) return ES_OK; else if (x[i].zero()) x.move_lst(i); if (x.size() == 0) return NaryOrTrue::post(home,y); for (int i=y.size(); i--; ) if (y[i].one()) return ES_OK; else if (y[i].zero()) y.move_lst(i); if (y.size() == 0) return NaryOrTrue::post(home,x); if ((x.size() == 1) && (y.size() == 1)) { return BinOrTrue::post(home,x[0],y[0]); } else if (!shared(x,y)) { (void) new (home) ClauseTrue(home,x,y); } return ES_OK; } template forceinline size_t ClauseTrue::dispose(Space& home) { (void) MixBinaryPropagator::dispose(home); return sizeof(*this); } template forceinline ExecStatus resubscribe(Space& home, Propagator& p, VX& x0, ViewArray& x, VY& x1, ViewArray& y) { if (x0.zero()) { int n = x.size(); for (int i=n; i--; ) if (x[i].one()) { x.size(n); return home.ES_SUBSUMED(p); } else if (x[i].zero()) { x[i] = x[--n]; } else { // Rewrite if there is just one view left if ((i == 0) && (y.size() == 0)) { VX z = x[0]; x.size(0); GECODE_REWRITE(p,(BinOrTrue::post(home(p),z,x1))); } // Move to x0 and subscribe x0=x[i]; x[i]=x[--n]; x.size(n); x0.subscribe(home,p,PC_BOOL_VAL,false); return ES_FIX; } // All x-views have been assigned! ViewArray z(home,y.size()+1); for (int i=0; i::post(home(p),z))); } return ES_FIX; } template ExecStatus ClauseTrue::propagate(Space& home, const ModEventDelta&) { if (x0.one() || x1.one()) return home.ES_SUBSUMED(*this); GECODE_ES_CHECK(resubscribe(home,*this,x0,x,x1,y)); GECODE_ES_CHECK(resubscribe(home,*this,x1,y,x0,x)); return ES_FIX; } /* * Boolean clause propagator (disjunctive) * */ /* * Index advisors * */ template forceinline Clause::Tagged::Tagged(Space& home, Propagator& p, Council& c, bool x0) : Advisor(home,p,c), x(x0) {} template forceinline Clause::Tagged::Tagged(Space& home, Tagged& a) : Advisor(home,a), x(a.x) {} template forceinline Clause::Clause(Home home, ViewArray& x0, ViewArray& y0, VX z0) : Propagator(home), x(x0), y(y0), z(z0), n_zero(0), c(home) { x.subscribe(home,*new (home) Tagged(home,*this,c,true)); y.subscribe(home,*new (home) Tagged(home,*this,c,false)); z.subscribe(home,*this,PC_BOOL_VAL); } template forceinline Clause::Clause(Space& home, Clause& p) : Propagator(home,p), n_zero(p.n_zero) { x.update(home,p.x); y.update(home,p.y); z.update(home,p.z); c.update(home,p.c); } template forceinline void eliminate_zero(ViewArray& x, int& n_zero) { if (n_zero > 0) { int n=x.size(); // Eliminate all zeros for (int i=n; i--; ) if (x[i].zero()) { x[i]=x[--n]; n_zero--; } x.size(n); } } template Actor* Clause::copy(Space& home) { eliminate_zero(x,n_zero); eliminate_zero(y,n_zero); return new (home) Clause(home,*this); } template inline ExecStatus Clause::post(Home home, ViewArray& x, ViewArray& y, VX z) { assert(!shared(x) && !shared(y)); if (z.one()) return ClauseTrue::post(home,x,y); if (z.zero()) { for (int i=0; i::post(home,y,z); for (int i=y.size(); i--; ) if (y[i].one()) { GECODE_ME_CHECK(z.one_none(home)); return ES_OK; } else if (y[i].zero()) { y.move_lst(i); } if (y.size() == 0) return NaryOr::post(home,x,z); if ((x.size() == 1) && (y.size() == 1)) { return Or::post(home,x[0],y[0],z); } else if (shared(x,y)) { GECODE_ME_CHECK(z.one_none(home)); } else { (void) new (home) Clause(home,x,y,z); } return ES_OK; } template PropCost Clause::cost(const Space&, const ModEventDelta&) const { return PropCost::unary(PropCost::LO); } template forceinline void Clause::cancel(Space& home) { for (Advisors as(c); as(); ++as) { if (as.advisor().x) x.cancel(home,as.advisor()); else y.cancel(home,as.advisor()); as.advisor().dispose(home,c); } c.dispose(home); z.cancel(home,*this,PC_BOOL_VAL); } template forceinline size_t Clause::dispose(Space& home) { cancel(home); (void) Propagator::dispose(home); return sizeof(*this); } template ExecStatus Clause::advise(Space&, Advisor& _a, const Delta& d) { Tagged& a = static_cast(_a); // Decides whether the propagator must be run if ((a.x && VX::zero(d)) || (!a.x && VY::zero(d))) if (++n_zero < x.size() + y.size()) return ES_FIX; return ES_NOFIX; } template void Clause::reschedule(Space& home) { z.reschedule(home,*this,PC_BOOL_VAL); if (n_zero == x.size() + y.size()) VX::schedule(home,*this,ME_BOOL_VAL); for (int i=0; i ExecStatus Clause::propagate(Space& home, const ModEventDelta&) { if (z.one()) GECODE_REWRITE(*this,(ClauseTrue::post(home(*this),x,y))); if (z.zero()) { for (int i=0; i