ExecStatus QXor<BVA,BVB>::propagate(Space& home, const ModEventDelta&) { #define GECODE_INT_STATUS(S0,S1) \ ((BVA::S0<<(1*BVA::BITS))|(BVB::S1<<(0*BVB::BITS))) switch ((x0.status() << (1*BVA::BITS)) | (x1.status() << (0*BVB::BITS))) { case GECODE_INT_STATUS(NONE,NONE): GECODE_NEVER; case GECODE_INT_STATUS(NONE,ZERO): if (q0 == FORALL) return ES_FAILED; GECODE_ME_CHECK(x0.one_none(home)); break; case GECODE_INT_STATUS(NONE,ONE): if (q0 == FORALL) return ES_FAILED; GECODE_ME_CHECK(x0.zero_none(home)); break; case GECODE_INT_STATUS(ZERO,NONE): if (q1 == FORALL) return ES_FAILED; GECODE_ME_CHECK(x1.one_none(home)); break; case GECODE_INT_STATUS(ZERO,ZERO): return ES_FAILED; case GECODE_INT_STATUS(ZERO,ONE): break; case GECODE_INT_STATUS(ONE,NONE): if (q1 == FORALL) return ES_FAILED; GECODE_ME_CHECK(x1.zero_none(home)); break; case GECODE_INT_STATUS(ONE,ZERO): break; case GECODE_INT_STATUS(ONE,ONE): return ES_FAILED; default: GECODE_NEVER; } return home.ES_SUBSUMED(*this); #undef GECODE_INT_STATUS }
ExecStatus ReLeFloat<View,CtrlView,rm>::post(Home home, View x, FloatVal c, CtrlView b) { if (b.one()) { if (rm != RM_PMI) { GECODE_ME_CHECK(x.lq(home,c.max())); if (x.assigned() && (x.max() >= c.min())) return ES_FAILED; (void) new (home) ReLeFloat<View,CtrlView,rm>(home,x,c,b); } } else if (b.zero()) { if (rm != RM_IMP) GECODE_ME_CHECK(x.gq(home,c.min())); } else { switch (rtest_le(x,c)) { case RT_TRUE: if (rm != RM_IMP) GECODE_ME_CHECK(b.one(home)); break; case RT_FALSE: if (rm != RM_PMI) GECODE_ME_CHECK(b.zero(home)); break; case RT_MAYBE: (void) new (home) ReLeFloat<View,CtrlView,rm>(home,x,c,b); break; default: GECODE_NEVER; } } return ES_OK; }
forceinline ExecStatus MultZeroOne<View,pc>::post(Home home, View x0, View x1) { switch (equal(x0,0)) { case RT_FALSE: GECODE_ME_CHECK(x1.eq(home,1)); break; case RT_TRUE: break; case RT_MAYBE: switch (equal(x1,1)) { case RT_FALSE: GECODE_ME_CHECK(x0.eq(home,0)); break; case RT_TRUE: break; case RT_MAYBE: (void) new (home) MultZeroOne<View,pc>(home,x0,x1); break; default: GECODE_NEVER; } break; default: GECODE_NEVER; } return ES_OK; }
ExecStatus Pack::post(Home home, ViewArray<OffsetView>& l, ViewArray<Item>& bs) { if (bs.size() == 0) { // No items to be packed for (int i=l.size(); i--; ) GECODE_ME_CHECK(l[i].eq(home,0)); return ES_OK; } else if (l.size() == 0) { // No bins available return ES_FAILED; } else { int s = 0; // Constrain bins for (int i=bs.size(); i--; ) { s += bs[i].size(); GECODE_ME_CHECK(bs[i].bin().gq(home,0)); GECODE_ME_CHECK(bs[i].bin().le(home,l.size())); } // Constrain load for (int j=l.size(); j--; ) { GECODE_ME_CHECK(l[j].gq(home,0)); GECODE_ME_CHECK(l[j].lq(home,s)); } (void) new (home) Pack(home,l,bs); return ES_OK; } }
forceinline ExecStatus LinkMulti::post(Home home, ViewArray<BoolView>& x, IntView y, int o) { int n=x.size(); GECODE_ME_CHECK(y.gq(home,o)); GECODE_ME_CHECK(y.lq(home,o+n-1)); assert(n > 0); if (n == 1) { GECODE_ME_CHECK(x[0].one(home)); assert(y.val() == o); } else if (y.assigned()) { int j=y.val()-o; GECODE_ME_CHECK(x[j].one(home)); for (int i=0; i<j; i++) GECODE_ME_CHECK(x[i].zero(home)); for (int i=j+1; i<n; i++) GECODE_ME_CHECK(x[i].zero(home)); } else { for (int i=n; i--; ) if (x[i].one()) { for (int j=0; j<i; j++) GECODE_ME_CHECK(x[j].zero(home)); for (int j=i+1; j<n; j++) GECODE_ME_CHECK(x[j].zero(home)); GECODE_ME_CHECK(y.eq(home,o+i)); return ES_OK; } else if (x[i].zero()) { GECODE_ME_CHECK(y.nq(home,o+i)); } (void) new (home) LinkMulti(home,x,y,o); } return ES_OK; }
inline ExecStatus QXor<BVA,BVB>::post(Home home, BVA b0, TQuantifier _q0, int _r0, BVB b1, TQuantifier _q1, int _r1) { switch (bool_test(b0,b1)) { case BT_SAME: return ES_FAILED; case BT_COMP: return ES_OK; case BT_NONE: if ( ((_q0 == FORALL) && (_q1 == FORALL)) || ((_r0 < _r1) && (_q1 == FORALL)) || ((_r0 > _r1) && (_q0 == FORALL)) ) return ES_FAILED; if (b0.zero()) { if (_q1 == FORALL) return ES_FAILED; GECODE_ME_CHECK(b1.one(home)); } else if (b0.one()) { if (_q1 == FORALL) return ES_FAILED; GECODE_ME_CHECK(b1.zero(home)); } else if (b1.zero()) { if (_q0 == FORALL) return ES_FAILED; GECODE_ME_CHECK(b0.one(home)); } else if (b1.one()) { if (_q0 == FORALL) return ES_FAILED; GECODE_ME_CHECK(b0.zero(home)); } else { (void) new (home) QXor<BVA,BVB>(home,b0,_q0,_r0,b1,_q1,_r1); } break; default: GECODE_NEVER; } return ES_OK; }
ExecStatus NqBoolView<XV,YV>::propagate(Space& home, const ModEventDelta&) { int n = x.size(); for (int i = n; i--; ) if (x[i].one()) { x[i]=x[--n]; c--; } else if (x[i].zero()) { x[i]=x[--n]; } x.size(n); if ((n-c < y.min() ) || (-c > y.max())) return home.ES_SUBSUMED(*this); if (n == 0) { GECODE_ME_CHECK(y.nq(home,-c)); return home.ES_SUBSUMED(*this); } if ((n == 1) && y.assigned()) { if (y.val()+c == 1) { GECODE_ME_CHECK(x[0].zero_none(home)); } else { assert(y.val()+c == 0); GECODE_ME_CHECK(x[0].one_none(home)); } return home.ES_SUBSUMED(*this); } return ES_FIX; }
ExecStatus ReLeFloat<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { if (b.one()) { if (rm != RM_PMI) { GECODE_ME_CHECK(x0.lq(home,c.max())); if (x0.assigned()) { return (x0.max() >= c.min()) ? ES_FAILED : home.ES_SUBSUMED(*this); } } } else if (b.zero()) { if (rm != RM_IMP) GECODE_ME_CHECK(x0.gq(home,c.min())); } else { switch (rtest_le(x0,c)) { case RT_TRUE: if (rm != RM_IMP) GECODE_ME_CHECK(b.one(home)); break; case RT_FALSE: if (rm != RM_PMI) GECODE_ME_CHECK(b.zero(home)); break; case RT_MAYBE: return ES_FIX; default: GECODE_NEVER; } } return home.ES_SUBSUMED(*this); }
ExecStatus EqBoolView<XV,YV>::post(Home home, ViewArray<XV>& x, YV y, int c) { if (y.assigned()) return EqBoolInt<XV>::post(home,x,y.val()+c); int n = x.size(); for (int i = n; i--; ) if (x[i].one()) { x[i]=x[--n]; c--; } else if (x[i].zero()) { x[i]=x[--n]; } x.size(n); GECODE_ME_CHECK(y.lq(home,n-c)); GECODE_ME_CHECK(y.gq(home,-c)); if (n == 0) return ES_OK; if (y.min()+c == n) { assert(y.assigned()); for (int i = n; i--; ) GECODE_ME_CHECK(x[i].one_none(home)); return ES_OK; } if (y.max()+c == 0) { assert(y.assigned()); for (int i = n; i--; ) GECODE_ME_CHECK(x[i].zero_none(home)); return ES_OK; } (void) new (home) EqBoolView<XV,YV>(home,x,y,c); return ES_OK; }
ExecStatus EqBoolView<XV,YV>::propagate(Space& home, const ModEventDelta&) { int n = x.size(); for (int i = n; i--; ) if (x[i].one()) { x[i]=x[--n]; c--; } else if (x[i].zero()) { x[i]=x[--n]; } x.size(n); GECODE_ME_CHECK(y.lq(home,n-c)); GECODE_ME_CHECK(y.gq(home,-c)); if (n == 0) return home.ES_SUBSUMED(*this); if (y.min()+c == n) { assert(y.assigned()); for (int i = n; i--; ) GECODE_ME_CHECK(x[i].one_none(home)); return home.ES_SUBSUMED(*this); } if (y.max()+c == 0) { assert(y.assigned()); for (int i = n; i--; ) GECODE_ME_CHECK(x[i].zero_none(home)); return home.ES_SUBSUMED(*this); } if (y.assigned()) GECODE_REWRITE(*this,EqBoolInt<XV>::post(home(*this),x,y.val()+c)); return ES_FIX; }
ExecStatus GqBool<VY>::propagate(Space& home, const ModEventDelta&) { if (status == (VS_ZERO | VS_ONE)) return home.ES_SUBSUMED(*this); if (c.empty()) { assert(status != 0); GECODE_ME_CHECK(y.lq(home,1)); return home.ES_SUBSUMED(*this); } if (y.max() <= 1) return home.ES_SUBSUMED(*this); if (y.min() == 2) { Advisors<ViewAdvisor<BoolView> > as(c); assert(as()); ViewAdvisor<BoolView>& a(as.advisor()); ++as; if (!as()) { // Only a single view is left if (status == VS_ZERO) { GECODE_ME_CHECK(a.view().one(home)); } else if (status == VS_ONE) { GECODE_ME_CHECK(a.view().zero(home)); } else { return ES_FAILED; } return home.ES_SUBSUMED(*this); } } return ES_FIX; }
ExecStatus ReEq<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { if (b.one()) { if (rm == RM_PMI) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(Eq<View,View>::post(home(*this),x0,x1))); } if (b.zero()) { if (rm == RM_IMP) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(Nq<View,View>::post(home(*this),x0,x1))); } switch (rtest_eq(x0,x1)) { case RT_TRUE: if (rm != RM_IMP) GECODE_ME_CHECK(b.one_none(home)); break; case RT_FALSE: if (rm != RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); break; case RT_MAYBE: return ES_FIX; default: GECODE_NEVER; } return home.ES_SUBSUMED(*this); }
ExecStatus DistinctDoit<View0>::propagate(Space& home, const ModEventDelta&) { if (x0.assigned()) { GlbRanges<View0> xi(x0); GlbRanges<ConstSetView> yi(y); if (Iter::Ranges::equal(xi,yi)) { return ES_FAILED; } else { return home.ES_SUBSUMED(*this); } } assert(x0.lubSize()-x0.glbSize() >0); if (x0.cardMin()>y.cardMax()) { return home.ES_SUBSUMED(*this); } if (x0.cardMax()<y.cardMin()) { return home.ES_SUBSUMED(*this); } //These tests are too expensive, we should only do them //in the 1 unknown left case. GlbRanges<View0> xi1(x0); LubRanges<ConstSetView> yi1(y); if (!Iter::Ranges::subset(xi1,yi1)){ return home.ES_SUBSUMED(*this); } LubRanges<View0> xi2(x0); GlbRanges<ConstSetView> yi2(y); if (!Iter::Ranges::subset(yi2,xi2)){ return home.ES_SUBSUMED(*this); } // from here, we know y\subseteq lub(x) and glb(x)\subseteq y if (x0.lubSize() == y.cardMin() && x0.lubSize() > 0) { GECODE_ME_CHECK(x0.cardMax(home, x0.lubSize() - 1)); return home.ES_SUBSUMED(*this); } if (x0.glbSize() == y.cardMin()) { GECODE_ME_CHECK(x0.cardMin(home, x0.glbSize() + 1)); return home.ES_SUBSUMED(*this); } return ES_FIX; }
inline ExecStatus Single<View>::post(Home home, ViewArray<View>& x, int s, int t) { { int alpha = 0; while ((alpha < x.size()) && !x[alpha].in(s)) GECODE_ME_CHECK(x[alpha++].nq(home,t)); x.drop_fst(alpha); if (x.size() == 0) return ES_OK; } // alpha has been normalized to 0 int beta = 0, gamma = 0; GECODE_ME_CHECK(x[0].nq(home,t)); do { gamma++; } while ((gamma < x.size()) && !assigned(x[gamma],t)); do { beta++; } while ((beta < x.size()) && !x[beta].in(s)); if (beta > gamma) { GECODE_ME_CHECK(x[0].eq(home, s)); return ES_OK; } if (gamma < x.size()) x.drop_lst(gamma); (void) new (home) Single<View>(home, x, s, t, beta, gamma); return ES_OK; }
ExecStatus ReEqBin<Val,A,B,Ctrl,rm>::propagate(Space& home, const ModEventDelta&) { if (b.zero()) { if (rm == RM_IMP) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(NqBin<Val,A,B>::post(home(*this),x0,x1,c))); } if (b.one()) { if (rm == RM_PMI) return home.ES_SUBSUMED(*this); GECODE_REWRITE(*this,(EqBin<Val,A,B>::post(home(*this),x0,x1,c))); } if ((x0.min() + x1.min() > c) || (x0.max() + x1.max() < c)) { if (rm != RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); } if (x0.assigned() && x1.assigned()) { assert(x0.val() + x1.val() == c); if (rm != RM_IMP) GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); } return ES_FIX; }
ExecStatus LqBool<VY>::propagate(Space& home, const ModEventDelta&) { if (status == (VS_ZERO | VS_ONE)) { GECODE_ME_CHECK(y.gq(home,2)); return home.ES_SUBSUMED(*this); } if (c.empty()) { assert((status != 0) && (y.min() >= 1)); return home.ES_SUBSUMED(*this); } if (y.max() == 1) { if (status == VS_ZERO) { // Mark that everything is done status = VS_ZERO | VS_ONE; for (Advisors<ViewAdvisor<BoolView> > as(c); as(); ++as) GECODE_ME_CHECK(as.advisor().view().zero(home)); return home.ES_SUBSUMED(*this); } if (status == VS_ONE) { // Mark that everything is done status = VS_ZERO | VS_ONE; for (Advisors<ViewAdvisor<BoolView> > as(c); as(); ++as) GECODE_ME_CHECK(as.advisor().view().one(home)); return home.ES_SUBSUMED(*this); } } if (y.min() == 2) return home.ES_SUBSUMED(*this); return ES_FIX; }
ExecStatus ReLq<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { if (b.one()) { if (rm != RM_PMI) GECODE_REWRITE(*this,Lq<View>::post(home(*this),x0,x1)); } else if (b.zero()) { if (rm != RM_IMP) GECODE_REWRITE(*this,Le<View>::post(home(*this),x1,x0)); } else { switch (rtest_lq(x0,x1)) { case RT_TRUE: if (rm != RM_IMP) GECODE_ME_CHECK(b.one_none(home)); break; case RT_FALSE: if (rm != RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); break; case RT_MAYBE: if (!x0.assigned() || !x1.assigned()) return ES_FIX; else { if (rm != RM_IMP) GECODE_ME_CHECK(b.one_none(home)); break; } default: GECODE_NEVER; } } return home.ES_SUBSUMED(*this); }
ExecStatus ReIntSet<View,rm>::propagate(Space& home, const ModEventDelta&) { IntSetRanges i_is(is); if (b.one()) { if (rm != RM_PMI) GECODE_ME_CHECK(x0.inter_r(home,i_is,false)); return home.ES_SUBSUMED(*this); } if (b.zero()) { if (rm != RM_IMP) GECODE_ME_CHECK(x0.minus_r(home,i_is,false)); return home.ES_SUBSUMED(*this); } { ViewRanges<View> i_x(x0); switch (Iter::Ranges::compare(i_x,i_is)) { case Iter::Ranges::CS_SUBSET: if (rm != RM_IMP) GECODE_ME_CHECK(b.one_none(home)); return home.ES_SUBSUMED(*this); case Iter::Ranges::CS_DISJOINT: if (rm != RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); return home.ES_SUBSUMED(*this); case Iter::Ranges::CS_NONE: break; default: GECODE_NEVER; } } return ES_FIX; }
forceinline ExecStatus Card<View>::post(Home home, View x0, Gecode::Int::IntView x1) { GECODE_ME_CHECK(x1.gq(home,0)); GECODE_ME_CHECK(x0.cardMax(home, Gecode::Int::Limits::max)); (void) new (home) Card(home,x0,x1); return ES_OK; }
ExecStatus Exp<A,B>::propagate(Space& home, const ModEventDelta&) { GECODE_ME_CHECK(x1.eq(home,exp(x0.domain()))); if (x1.max() == 0.0) return ES_FAILED; GECODE_ME_CHECK(x0.eq(home,log(x1.domain()))); return x0.assigned() ? home.ES_SUBSUMED(*this) : ES_FIX; }
ExecStatus Lq<View>::post(Home home, View x0, View x1) { GECODE_ME_CHECK(x0.lq(home,x1.max())); GECODE_ME_CHECK(x1.gq(home,x0.min())); if (!same(x0,x1) && (x0.max() > x1.min())) (void) new (home) Lq<View>(home,x0,x1); return ES_OK; }
ExecStatus Div<A,B,C>::propagate(Space& home, const ModEventDelta&) { if (x1.assigned() && (x1.val() == 0)) return ES_FAILED; GECODE_ME_CHECK(x2.eq(home,x0.domain() / x1.domain())); GECODE_ME_CHECK(x0.eq(home,x2.domain() * x1.domain())); if (!x2.assigned() || (x2.val() != 0)) GECODE_ME_CHECK(x1.eq(home,x0.domain() / x2.domain())); return (x0.assigned() && x1.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX; }
ExecStatus Le<View>::propagate(Space& home, const ModEventDelta&) { GECODE_ME_CHECK(x0.lq(home,x1.max())); GECODE_ME_CHECK(x1.gq(home,x0.min())); if (x0.assigned() && x1.assigned()) { return (x0.max() >= x1.min()) ? ES_FAILED : home.ES_SUBSUMED(*this); } return (x0.max() < x1.min()) ? home.ES_SUBSUMED(*this) : ES_FIX; }
forceinline ExecStatus Single<View>::updateAlpha(Space& home) { int n = x.size(); while ((alpha < n) && !x[alpha].in(s)) GECODE_ME_CHECK(x[alpha++].nq(home, t)); if (alpha < n) GECODE_ME_CHECK(x[alpha].nq(home, t)); return ES_OK; }
ExecStatus Tan<A,B>::propagate(Space& home, const ModEventDelta&) { GECODE_ME_CHECK(x1.eq(home,tan(x0.domain()))); FloatVal iv = fmod(x0.domain(),FloatVal::pi()); FloatNum offSet(Round.sub_down(x0.min(),iv.min())); GECODE_ES_CHECK(aTanProject(x1,iv)); GECODE_ME_CHECK(x0.eq(home,iv + offSet)); return (x0.assigned() && x1.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX; }
ExecStatus Nq<View>::propagate(Space& home, const ModEventDelta&) { if (x0.assigned()) { GECODE_ME_CHECK(x1.nq(home,x0.val())); } else { GECODE_ME_CHECK(x0.nq(home,x1.val())); } return home.ES_SUBSUMED(*this); }
forceinline ExecStatus MultPlus<VA,VB,VC>::post(Home home, VA x0, VB x1, VC x2) { GECODE_ME_CHECK(x0.gq(home,0.0)); GECODE_ME_CHECK(x1.gq(home,0.0)); Rounding r; GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.min()))); (void) new (home) MultPlus<VA,VB,VC>(home,x0,x1,x2); return ES_OK; }
forceinline ExecStatus MultPlusDom<VA,VB,VC>::post(Home home, VA x0, VB x1, VC x2) { GECODE_ME_CHECK(x0.gr(home,0)); GECODE_ME_CHECK(x1.gr(home,0)); GECODE_ME_CHECK(x2.gq(home,mll(x0.min(),x1.min()))); GECODE_ME_CHECK(x2.lq(home,mll(x0.max(),x1.max()))); (void) new (home) MultPlusDom<VA,VB,VC>(home,x0,x1,x2); return ES_OK; }
forceinline ExecStatus FlexDim::nooverlap(Space& home, int n, int m) { if (n <= m) { Iter::Ranges::Singleton r0(n-s.min()+1,m); GECODE_ME_CHECK(c0.minus_r(home,r0,false)); Iter::Ranges::Singleton r1(n+1,s.min()+m); GECODE_ME_CHECK(c1.minus_r(home,r1,false)); } return ES_OK; }
ExecStatus NqBin<Val,A,B>::propagate(Space& home, const ModEventDelta&) { if (x0.assigned()) { GECODE_ME_CHECK(x1.nq(home,c-x0.val())); } else { assert(x1.assigned()); GECODE_ME_CHECK(x0.nq(home,c-x1.val())); } return home.ES_SUBSUMED(*this); }