void extensional(Home home, const BoolVarArgs& x, const TupleSet& t, IntPropLevel ipl) { using namespace Int; if (!t.finalized()) throw NotYetFinalized("Int::extensional"); if (t.arity() != x.size()) throw ArgumentSizeMismatch("Int::extensional"); GECODE_POST; if (t.tuples()==0) { if (x.size()!=0) { home.fail(); } return; } // Construct view array ViewArray<BoolView> xv(home,x); if (ipl & IPL_MEMORY) { if (x.same(home)) { GECODE_ES_FAIL((Extensional::Basic<BoolView,true> ::post(home,xv,t))); } else { GECODE_ES_FAIL((Extensional::Basic<BoolView,false> ::post(home,xv,t))); } } else { GECODE_ES_FAIL((Extensional::Incremental<BoolView> ::post(home,xv,t))); } }
void nonlinearity(Home home, const int n, const int m, const int threshold, const IntVarArgs& x) { if(DEBUG) { std::cerr << "P"; } // argument validation if(x.size() != pow(2,n)) { throw ArgumentSizeMismatch("setnonlinearity,x"); } else if(threshold > pow(2,n)) { throw ArgumentSizeMismatch("setnonlinearity,threshold,high"); } else if(!(n > 0)) { throw ArgumentSizeMismatch("setnonlinearity,n"); } else if(!(m > 0)) { throw ArgumentSizeMismatch("setnonlinearity,m"); } else if(!(threshold >= 0)) { throw ArgumentSizeMismatch("setnonlinearity,threshold,low"); } // if space is already failed, don't post the propagator if(home.failed()) { return; } // create views ViewArray<IntView> vx(home,x); // size of the a,b array, for convenience int size = numscores(n,m); // create storage for scoring int* scores = static_cast<Space&>(home).alloc<int>(size); // create storage for allocated list bool* assigned = static_cast<Space&>(home).alloc<bool>((int)pow(2,n)); // not strictly sure this is ncessary, but... for(int i=0; i<pow(2,n); i++) { assigned[i] = false; } // if posting failed, fail the space if(NonLinearity::post(home,vx,scores,assigned,n,m,threshold,size) != ES_OK) { home.fail(); } }
void rel(Home home, const IntVarArgs& x, IntRelType irt, const IntVarArgs& y, IntConLevel icl) { if (home.failed()) return; switch (irt) { case IRT_GR: { ViewArray<IntView> xv(home,x), yv(home,y); GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,yv,xv,true)); } break; case IRT_LE: { ViewArray<IntView> xv(home,x), yv(home,y); GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,xv,yv,true)); } break; case IRT_GQ: { ViewArray<IntView> xv(home,x), yv(home,y); GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,yv,xv,false)); } break; case IRT_LQ: { ViewArray<IntView> xv(home,x), yv(home,y); GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,xv,yv,false)); } break; case IRT_EQ: if (x.size() != y.size()) { home.fail(); } else if ((icl == ICL_DOM) || (icl == ICL_DEF)) for (int i=x.size(); i--; ) { GECODE_ES_FAIL((Rel::EqDom<IntView,IntView> ::post(home,x[i],y[i]))); } else for (int i=x.size(); i--; ) { GECODE_ES_FAIL((Rel::EqBnd<IntView,IntView> ::post(home,x[i],y[i]))); } break; case IRT_NQ: { ViewArray<IntView> xv(home,x), yv(home,y); GECODE_ES_FAIL(Rel::LexNq<IntView>::post(home,xv,yv)); } break; default: throw UnknownRelation("Int::rel"); } }
/* * Post the constraint that the rectangles defined by the coordinates * x and y and width w and height h do not overlap. * * This is the function that you will call from your model. The best * is to paste the entire file into your model. */ void nooverlap(Home home, const IntVarArgs& x, const IntArgs& w, const IntVarArgs& y, const IntArgs& h) { // Check whether the arguments make sense if ((x.size() != y.size()) || (x.size() != w.size()) || (y.size() != h.size())) throw ArgumentSizeMismatch("nooverlap"); // Never post a propagator in a failed space if (home.failed()) return; // Set up array of views for the coordinates ViewArray<IntView> vx(home,x); ViewArray<IntView> vy(home,y); // Set up arrays (allocated in home) for width and height and initialize int* wc = static_cast<Space&>(home).alloc<int>(x.size()); int* hc = static_cast<Space&>(home).alloc<int>(y.size()); for (int i=x.size(); i--; ) { wc[i]=w[i]; hc[i]=h[i]; } // If posting failed, fail space if (NoOverlap::post(home,vx,wc,vy,hc) != ES_OK) home.fail(); }
IntSet binpacking(Home home, int d, const IntVarArgs& l, const IntVarArgs& b, const IntArgs& s, const IntArgs& c, IntConLevel) { using namespace Int; if (l.same(home,b)) throw ArgumentSame("Int::binpacking"); // The number of items int n = b.size(); // The number of bins int m = l.size() / d; // Check input sizes if ((n*d != s.size()) || (m*d != l.size()) || (d != c.size())) throw ArgumentSizeMismatch("Int::binpacking"); for (int i=s.size(); i--; ) Limits::nonnegative(s[i],"Int::binpacking"); for (int i=c.size(); i--; ) Limits::nonnegative(c[i],"Int::binpacking"); if (home.failed()) return IntSet::empty; // Capacity constraint for each dimension for (int k=d; k--; ) for (int j=m; j--; ) { IntView li(l[j*d+k]); if (me_failed(li.lq(home,c[k]))) { home.fail(); return IntSet::empty; } } // Post a binpacking constraint for each dimension for (int k=d; k--; ) { ViewArray<OffsetView> lv(home,m); for (int j=m; j--; ) lv[j] = OffsetView(l[j*d+k],0); ViewArray<BinPacking::Item> bv(home,n); for (int i=n; i--; ) bv[i] = BinPacking::Item(b[i],s[i*d+k]); if (Int::BinPacking::Pack::post(home,lv,bv) == ES_FAILED) { home.fail(); return IntSet::empty; } } // Clique Finding and distinct posting { // First construct the conflict graph Region r(home); BinPacking::ConflictGraph cg(home,r,b,m); for (int i=0; i<n-1; i++) { for (int j=i+1; j<n; j++) { unsigned int nl = 0; unsigned int ds = 0; IntVarValues ii(b[i]), jj(b[j]); while (ii() && jj()) { if (ii.val() < jj.val()) { ++ii; } else if (ii.val() > jj.val()) { ++jj; } else { ds++; for (int k=d; k--; ) if (s[i*d+k] + s[j*d+k] > c[k]) { nl++; break; } ++ii; ++jj; } } if (nl >= ds) cg.edge(i,j); } } if (cg.post() == ES_FAILED) home.fail(); // The clique can be computed even if home is failed return cg.maxclique(); } }
void dopost(Home home, Term* t, int n, FloatRelType frt, FloatVal c) { Limits::check(c,"Float::linear"); for (int i=n; i--; ) if (t[i].x.assigned()) { c -= t[i].a * t[i].x.val(); t[i]=t[--n]; } if ((c < Limits::min) || (c > Limits::max)) throw OutOfLimits("Float::linear"); /* * Join coefficients for aliased variables: * */ { // Group same variables TermLess tl; Support::quicksort<Term,TermLess>(t,n,tl); // Join adjacent variables int i = 0; int j = 0; while (i < n) { Limits::check(t[i].a,"Float::linear"); FloatVal a = t[i].a; FloatView x = t[i].x; while ((++i < n) && same(t[i].x,x)) { a += t[i].a; Limits::check(a,"Float::linear"); } if (a != 0.0) { t[j].a = a; t[j].x = x; j++; } } n = j; } Term *t_p, *t_n; int n_p, n_n; /* * Partition into positive/negative coefficents * */ if (n > 0) { int i = 0; int j = n-1; while (true) { while ((t[j].a < 0) && (--j >= 0)) ; while ((t[i].a > 0) && (++i < n)) ; if (j <= i) break; std::swap(t[i],t[j]); } t_p = t; n_p = i; t_n = t+n_p; n_n = n-n_p; } else { t_p = t; n_p = 0; t_n = t; n_n = 0; } /* * Make all coefficients positive * */ for (int i=n_n; i--; ) t_n[i].a = -t_n[i].a; if (frt == FRT_GQ) { frt = FRT_LQ; std::swap(n_p,n_n); std::swap(t_p,t_n); c = -c; } if (n == 0) { switch (frt) { case FRT_EQ: if (!c.in(0.0)) home.fail(); break; case FRT_LQ: if (c.max() < 0.0) home.fail(); break; default: GECODE_NEVER; } return; } /* * Test for unit coefficients only * */ bool is_unit = true; for (int i=n; i--; ) if (t[i].a != 1.0) { is_unit = false; break; } if (is_unit) { // Unit coefficients ViewArray<FloatView> x(home,n_p); for (int i = n_p; i--; ) x[i] = t_p[i].x; ViewArray<FloatView> y(home,n_n); for (int i = n_n; i--; ) y[i] = t_n[i].x; post_nary<FloatView>(home,x,y,frt,c); } else { // Arbitrary coefficients ViewArray<ScaleView> x(home,n_p); for (int i = n_p; i--; ) x[i] = ScaleView(t_p[i].a,t_p[i].x); ViewArray<ScaleView> y(home,n_n); for (int i = n_n; i--; ) y[i] = ScaleView(t_n[i].a,t_n[i].x); post_nary<ScaleView>(home,x,y,frt,c); } }
void sequence(Home home, const IntVarArgs& x, const IntSet &s, int q, int l, int u, IntConLevel) { Limits::check(s.min(),"Int::sequence"); Limits::check(s.max(),"Int::sequence"); if (x.size() == 0) throw TooFewArguments("Int::sequence"); Limits::check(q,"Int::sequence"); Limits::check(l,"Int::sequence"); Limits::check(u,"Int::sequence"); if (x.same(home)) throw ArgumentSame("Int::sequence"); if ((q < 1) || (q > x.size())) throw OutOfLimits("Int::sequence"); if (home.failed()) return; // Normalize l and u l=std::max(0,l); u=std::min(q,u); // Lower bound of values taken can never exceed upper bound if (u < l) { home.fail(); return; } // Already subsumed as any number of values taken is okay if ((0 == l) && (q == u)) return; // All variables must take a value in s if (l == q) { for (int i=x.size(); i--; ) { IntView xv(x[i]); IntSetRanges ris(s); GECODE_ME_FAIL(xv.inter_r(home,ris,false)); } return; } // No variable can take a value in s if (0 == u) { for (int i=x.size(); i--; ) { IntView xv(x[i]); IntSetRanges ris(s); GECODE_ME_FAIL(xv.minus_r(home,ris,false)); } return; } ViewArray<IntView> xv(home,x); if (s.size() == 1) { GECODE_ES_FAIL( (Sequence::Sequence<IntView,int>::post (home,xv,s.min(),q,l,u))); } else { GECODE_ES_FAIL( (Sequence::Sequence<IntView,IntSet>::post (home,xv,s,q,l,u))); } }
void sequence(Home home, const BoolVarArgs& x, const IntSet& s, int q, int l, int u, IntConLevel) { if ((s.min() < 0) || (s.max() > 1)) throw NotZeroOne("Int::sequence"); if (x.size() == 0) throw TooFewArguments("Int::sequence"); Limits::check(q,"Int::sequence"); Limits::check(l,"Int::sequence"); Limits::check(u,"Int::sequence"); if (x.same(home)) throw ArgumentSame("Int::sequence"); if ((q < 1) || (q > x.size())) throw OutOfLimits("Int::sequence"); if (home.failed()) return; // Normalize l and u l=std::max(0,l); u=std::min(q,u); // Lower bound of values taken can never exceed upper bound if (u < l) { home.fail(); return; } // Already subsumed as any number of values taken is okay if ((0 == l) && (q == u)) return; // Check whether the set is {0,1}, then the number of values taken is q if ((s.min() == 0) && (s.max() == 1)) { if ((l > 0) || (u < q)) home.failed(); return; } assert(s.min() == s.max()); // All variables must take a value in s if (l == q) { if (s.min() == 0) { for (int i=x.size(); i--; ) { BoolView xv(x[i]); GECODE_ME_FAIL(xv.zero(home)); } } else { assert(s.min() == 1); for (int i=x.size(); i--; ) { BoolView xv(x[i]); GECODE_ME_FAIL(xv.one(home)); } } return; } // No variable can take a value in s if (0 == u) { if (s.min() == 0) { for (int i=x.size(); i--; ) { BoolView xv(x[i]); GECODE_ME_FAIL(xv.one(home)); } } else { assert(s.min() == 1); for (int i=x.size(); i--; ) { BoolView xv(x[i]); GECODE_ME_FAIL(xv.zero(home)); } } return; } ViewArray<BoolView> xv(home,x); GECODE_ES_FAIL( (Sequence::Sequence<BoolView,int>::post (home,xv,s.min(),q,l,u))); }