/* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2004 * * 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/int/rel.hh" namespace Gecode { namespace Int { namespace Arithmetic { /* * Ternary bounds-consistent maximum * */ template forceinline Max::Max(Space* home, View x0, View x1, View x2) : TernaryPropagator(home,x0,x1,x2) {} template ExecStatus Max::post(Space* home, View x0, View x1, View x2) { if (same(x0,x1)) return Rel::EqBnd::post(home,x0,x2); if (same(x0,x2)) return Rel::Lq::post(home,x1,x2); if (same(x1,x2)) return Rel::Lq::post(home,x0,x2); (void) new (home) Max(home,x0,x1,x2); return ES_OK; } template forceinline Max::Max(Space* home, bool share, Max& p) : TernaryPropagator(home,share,p) {} template forceinline Max::Max(Space* home, bool share, Propagator& p, View x0, View x1, View x2) : TernaryPropagator(home,share,p,x0,x1,x2) {} template Actor* Max::copy(Space* home, bool share) { return new (home) Max(home,share,*this); } template ExecStatus Max::propagate(Space* home) { bool mod = false; do { mod = false; { ModEvent me = x2.lq(home,std::max(x0.max(),x1.max())); if (me_failed(me)) return ES_FAILED; mod |= me_modified(me); } { ModEvent me = x2.gq(home,std::max(x0.min(),x1.min())); if (me_failed(me)) return ES_FAILED; mod |= me_modified(me); } { ModEvent me = x0.lq(home,x2.max()); if (me_failed(me)) return ES_FAILED; mod |= me_modified(me); } { ModEvent me = x1.lq(home,x2.max()); if (me_failed(me)) return ES_FAILED; mod |= me_modified(me); } } while (mod); if (x0.max() <= x1.min()) { GECODE_ES_CHECK((Rel::EqBnd::post(home,x1,x2))); return ES_SUBSUMED; } if (x1.max() <= x0.min()) { GECODE_ES_CHECK((Rel::EqBnd::post(home,x0,x2))); return ES_SUBSUMED; } return x0.assigned() && x1.assigned() && x2.assigned() ? ES_SUBSUMED : ES_FIX; } /* * Nary bounds-consistent maximum * */ template forceinline NaryMax::NaryMax(Space* home, ViewArray& x, View y) : NaryOnePropagator(home,x,y) {} template ExecStatus NaryMax::post(Space* home, ViewArray& x, View y) { assert(x.size() > 0); x.unique(); if (x.size() == 1) return Rel::EqBnd::post(home,x[0],y); if (x.size() == 2) return Max::post(home,x[0],x[1],y); if (x.same(y)) { // Check whether y occurs in x for (int i=x.size(); i--; ) GECODE_ES_CHECK(Rel::Lq::post(home,x[i],y)); } else { (void) new (home) NaryMax(home,x,y); } return ES_OK; } template forceinline NaryMax::NaryMax(Space* home, bool share, NaryMax& p) : NaryOnePropagator(home,share,p) {} template Actor* NaryMax::copy(Space* home, bool share) { if (x.size() == 1) return new (home) Rel::EqBnd(home,share,*this,x[0],y); if (x.size() == 2) return new (home) Max(home,share,*this,x[0],x[1],y); return new (home) NaryMax(home,share,*this); } /// Status of propagation for nary max enum MaxPropStatus { MPS_ASSIGNED = 1<<0, ///< All views are assigned MPS_REMOVED = 1<<1, ///< A view is removed MPS_NEW_BOUND = 1<<2 ///< Telling has found a new upper bound }; template ExecStatus NaryMax::propagate(Space* home) { rerun: int maxmax = Limits::Int::int_min-1; int maxmin = Limits::Int::int_min-1; for (int i = x.size(); i--; ) { maxmax = std::max(x[i].max(),maxmax); maxmin = std::max(x[i].min(),maxmin); } GECODE_ME_CHECK(y.lq(home,maxmax)); GECODE_ME_CHECK(y.gq(home,maxmin)); maxmin = y.min(); maxmax = y.max(); int status = MPS_ASSIGNED; for (int i = x.size(); i--; ) { ModEvent me = x[i].lq(home,maxmax); if (me == ME_INT_FAILED) return ES_FAILED; if (me_modified(me) && (x[i].max() != maxmax)) status |= MPS_NEW_BOUND; if (x[i].max() < maxmin) { x.move_lst(i,home,this,PC_INT_BND); status |= MPS_REMOVED; } else if (!x[i].assigned()) status &= ~MPS_ASSIGNED; } if (x.size() == 0) return ES_FAILED; if ((status & MPS_REMOVED) != 0) goto rerun; if (((status & MPS_ASSIGNED) != 0) && y.assigned()) return ES_SUBSUMED; return ((status & MPS_NEW_BOUND) != 0) ? ES_NOFIX : ES_FIX; } }}} // STATISTICS: int-prop