ExecStatus SeqU::propagateSeqUnion(Space& home, bool& modified, ViewArray<SetView>& x, SetView& y) { Region r(home); GlbRanges<SetView>* XLBs = r.alloc<GlbRanges<SetView> >(x.size()); for (int i=x.size(); i--; ){ GlbRanges<SetView> lb(x[i]); XLBs[i]=lb; } Iter::Ranges::NaryAppend<GlbRanges<SetView> > u(XLBs,x.size()); GECODE_ME_CHECK_MODIFIED(modified, y.includeI(home,u)); GLBndSet before(home); for (int i=0; i<x.size(); i++) { LubRanges<SetView> xiub(x[i]); before.includeI(home, xiub); BndSetRanges beforeR(before); GlbRanges<SetView> ylb(y); Iter::Ranges::Diff<GlbRanges<SetView>, BndSetRanges> diff(ylb, beforeR); if (diff()) { GECODE_ME_CHECK_MODIFIED(modified, x[i].exclude(home, diff.min(), Limits::max)); } } before.dispose(home); GLBndSet after(home); for (int i=x.size(); i--; ) { LubRanges<SetView> xiub(x[i]); after.includeI(home, xiub); BndSetRanges afterR(after); GlbRanges<SetView> ylb(y); Iter::Ranges::Diff<GlbRanges<SetView>, BndSetRanges> diff(ylb, afterR); if (diff()) { int max = diff.max(); for (; diff(); ++diff) max = diff.max(); GECODE_ME_CHECK_MODIFIED(modified, x[i].exclude(home, Limits::min, max)); } } after.dispose(home); return ES_FIX; }
ExecStatus Union<View0,View1,View2>::propagate(Space& home, const ModEventDelta& med) { // This propagator implements the constraint // x2 = x0 u x1 bool x0ass = x0.assigned(); bool x1ass = x1.assigned(); bool x2ass = x2.assigned(); ModEvent me0 = View0::me(med); ModEvent me1 = View1::me(med); ModEvent me2 = View2::me(med); bool x0ubmod = false; bool x1ubmod = false; bool modified = false; do { modified = false; do { // 4) lub(x2) <= lub(x0) u lub(x1) { LubRanges<View0> x0ub(x0); LubRanges<View1> x1ub(x1); Iter::Ranges::Union<LubRanges<View0>, LubRanges<View1> > u2(x0ub,x1ub); GECODE_ME_CHECK_MODIFIED(modified, x2.intersectI(home,u2) ); } if (modified || Rel::testSetEventUB(me2) ) { modified = false; // 5) x0 <= x2 LubRanges<View2> x2ub1(x2); GECODE_ME_CHECK_MODIFIED(modified, x0.intersectI(home,x2ub1) ); x0ubmod |= modified; // 6) x1 <= x2 bool modified2=false; LubRanges<View2> x2ub2(x2); GECODE_ME_CHECK_MODIFIED(modified2, x1.intersectI(home,x2ub2) ); x1ubmod |= modified2; modified |= modified2; } } while (modified); modified = false; do { bool modifiedOld = modified; modified = false; if (Rel::testSetEventLB(me2) || Rel::testSetEventUB(me0) || x0ubmod || modifiedOld) { // 1) glb(x0) \ lub(x1) <= glb(x2) GlbRanges<View2> x2lb(x2); LubRanges<View0> x0ub(x0); Iter::Ranges::Diff<GlbRanges<View2>, LubRanges<View0> > diff(x2lb, x0ub); GECODE_ME_CHECK_MODIFIED(modified, x1.includeI(home,diff) ); } if (Rel::testSetEventLB(me2) || Rel::testSetEventUB(me1) || x1ubmod || modifiedOld) { // 2) glb(x0) \ lub(x2) <= glb(x1) GlbRanges<View2> x2lb(x2); LubRanges<View1> x1ub(x1); Iter::Ranges::Diff<GlbRanges<View2>, LubRanges<View1> > diff(x2lb, x1ub); GECODE_ME_CHECK_MODIFIED(modified, x0.includeI(home,diff) ); } if (Rel::testSetEventLB(me0,me1) || modified) { // modified = false; // 3) glb(x1) u glb(x2) <= glb(x0) GlbRanges<View0> x0lb(x0); GlbRanges<View1> x1lb(x1); Iter::Ranges::Union<GlbRanges<View0>, GlbRanges<View1> > u1(x0lb,x1lb); GECODE_ME_CHECK_MODIFIED(modified, x2.includeI(home,u1) ); } } while(modified); modified = false; { // cardinality ExecStatus ret = unionCard(home,modified, x0, x1, x2); GECODE_ES_CHECK(ret); } if (x2.cardMax() == 0) { GECODE_ME_CHECK( x0.cardMax(home, 0) ); GECODE_ME_CHECK( x1.cardMax(home, 0) ); return home.ES_SUBSUMED(*this); } if (x0.cardMax() == 0) GECODE_REWRITE(*this,(Rel::Eq<View1,View2>::post(home(*this),x1,x2))); if (x1.cardMax() == 0) GECODE_REWRITE(*this,(Rel::Eq<View0,View2>::post(home(*this),x0,x2))); } while(modified); if (shared(x0,x1,x2)) { return (x0ass && x1ass && x2ass) ? home.ES_SUBSUMED(*this) : ES_NOFIX; } else { if (x0ass && x1ass && x2ass) return home.ES_SUBSUMED(*this); if (x0ass != x0.assigned() || x1ass != x1.assigned() || x2ass != x2.assigned()) { return ES_NOFIX; } else { return ES_FIX; } } }
ExecStatus SuperOfInter<View0,View1,View2>::propagate(Space& home, const ModEventDelta& med) { bool allassigned = x0.assigned() && x1.assigned() && x2.assigned(); ModEvent me0 = View0::me(med); ModEvent me1 = View1::me(med); ModEvent me2 = View2::me(med); bool modified = false; do { // glb(x2) >= glb(x0) ^ glb(x1) if ( modified || Rel::testSetEventLB(me0,me1)) { GlbRanges<View0> lb0(x0); GlbRanges<View1> lb1(x1); Iter::Ranges::Inter<GlbRanges<View0>,GlbRanges<View1> > is(lb0, lb1); GECODE_ME_CHECK_MODIFIED(modified,x2.includeI(home,is)); } // lub(x0) -= glb(x1)-lub(x2) // lub(x1) -= glb(x0)-lub(x2) if ( modified || Rel::testSetEventAnyB(me0,me1,me2)) { modified = false; GlbRanges<View1> lb12(x1); LubRanges<View2> ub22(x2); Iter::Ranges::Diff<GlbRanges<View1>, LubRanges<View2> > diff1(lb12, ub22); GECODE_ME_CHECK_MODIFIED(modified, x0.excludeI(home,diff1)); GlbRanges<View0> lb01(x0); LubRanges<View2> ub23(x2); Iter::Ranges::Diff<GlbRanges<View0>, LubRanges<View2> > diff2(lb01, ub23); GECODE_ME_CHECK_MODIFIED(modified, x1.excludeI(home,diff2)); } else { modified = false; } // Cardinality propagation if ( modified || Rel::testSetEventCard(me0,me1,me2) || Rel::testSetEventUB(me0,me1) ) { LubRanges<View0> ub0(x0); LubRanges<View1> ub1(x1); Iter::Ranges::Union<LubRanges<View0>, LubRanges<View1> > u(ub0,ub1); unsigned int m = Iter::Ranges::size(u); if (m < x0.cardMin() + x1.cardMin()) { GECODE_ME_CHECK_MODIFIED(modified, x2.cardMin( home, x0.cardMin()+x1.cardMin() - m ) ); } if (m + x2.cardMax() > x1.cardMin()) { GECODE_ME_CHECK_MODIFIED(modified, x0.cardMax( home, m+x2.cardMax()-x1.cardMin() ) ); } if (m + x2.cardMax() > x0.cardMin()) { GECODE_ME_CHECK_MODIFIED(modified, x1.cardMax( home, m+x2.cardMax()-x0.cardMin() ) ); } } } while (modified); if (shared(x0,x1,x2)) { if (allassigned) { return home.ES_SUBSUMED(*this); } else { return ES_NOFIX; } } else { if (x0.assigned() + x1.assigned() + x2.assigned() >= 2) { return home.ES_SUBSUMED(*this); } else { return ES_FIX; } } }
ExecStatus Match<View>::propagate(Space& home, const ModEventDelta&) { int xs_size = xs.size(); bool loopFlag; do { loopFlag = false; // Order int vars in xs GECODE_ME_CHECK(xs[0].gq(home,x0.lubMin())); for (int i=xs_size-1; i--; ) { GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i+1].gq(home,xs[i].min() + 1)); } GECODE_ME_CHECK_MODIFIED(loopFlag, xs[xs_size-1].lq(home,x0.lubMax())); for (int i=xs_size-2; i--; ) { GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].lq(home,xs[i+1].max() - 1)); } // if y from xs is assigned, add to glb(x0) for (int i=xs_size; i--; ) { if (xs[i].assigned()) { GECODE_ME_CHECK_MODIFIED(loopFlag, x0.include(home,xs[i].val())); } } // intersect every y in xs with lub(x0) for (int i=xs_size; i--; ) { LubRanges<View> ub(x0); GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].inter_r(home,ub,false)); } // remove gaps between vars in xs from lub(x0) GECODE_ME_CHECK_MODIFIED(loopFlag, x0.exclude(home,Limits::min,xs[0].min()-1)); GECODE_ME_CHECK_MODIFIED(loopFlag, x0.exclude(home,xs[xs_size-1].max()+1, Limits::max)); for (int i=xs_size-1; i--; ) { int start = xs[i].max() + 1; int end = xs[i+1].min() - 1; if (start<=end) { GECODE_ME_CHECK_MODIFIED(loopFlag, x0.exclude(home,start,end)); } } // try to assign vars in xs from glb(x0) if (x0.glbSize()>0) { LubRanges<View> ub(x0); Iter::Ranges::ToValues<LubRanges<View> > ubv(ub); GlbRanges<View> lb(x0); Iter::Ranges::ToValues<GlbRanges<View> > lbv(lb); int i=0; for (; ubv() && lbv() && ubv.val()==lbv.val(); ++ubv, ++lbv, i++) { GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].eq(home,lbv.val())); } if (i<xs_size-1 && x0.lubMax()==x0.glbMax()) { LubRanges<View> lbx0(x0); GlbRanges<View> ubx0(x0); Iter::Ranges::Inter<LubRanges<View>,GlbRanges<View> > inter(lbx0, ubx0); int to = x0.glbMax(); int from = to; while (inter()) { from = inter.min(); ++inter; } int i=xs_size-1; for (int j=to; j>=from;j--,i--) { GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].eq(home,j)); } } } } while (loopFlag); for (int i=xs_size; i--; ) if (!xs[i].assigned()) return ES_FIX; return home.ES_SUBSUMED(*this); }