void nooverlap(Home home, const IntVarArgs& x0, const IntVarArgs& w, const IntVarArgs& x1, const IntVarArgs& y0, const IntVarArgs& h, const IntVarArgs& y1, IntConLevel) { using namespace Int; using namespace NoOverlap; if ((x0.size() != w.size()) || (x0.size() != x1.size()) || (x0.size() != y0.size()) || (x0.size() != h.size()) || (x0.size() != y1.size())) throw ArgumentSizeMismatch("Int::nooverlap"); if (x0.same(home) || w.same(home) || x1.same(home) || y0.same(home) || h.same(home) || y1.same(home)) throw ArgumentSame("Int::nooverlap"); if (home.failed()) return; for (int i=x0.size(); i--; ) { GECODE_ME_FAIL(IntView(w[i]).gq(home,0)); GECODE_ME_FAIL(IntView(h[i]).gq(home,0)); } if (w.assigned() && h.assigned()) { IntArgs wc(x0.size()), hc(x0.size()); for (int i=x0.size(); i--; ) { wc[i] = w[i].val(); hc[i] = h[i].val(); } nooverlap(home, x0, wc, y0, hc); } else { ManBox<FlexDim,2>* b = static_cast<Space&>(home).alloc<ManBox<FlexDim,2> >(x0.size()); for (int i=x0.size(); i--; ) { b[i][0] = FlexDim(x0[i],w[i],x1[i]); b[i][1] = FlexDim(y0[i],h[i],y1[i]); } GECODE_ES_FAIL((NoOverlap::ManProp<FlexDim,2>::post(home,b,x0.size()))); } }
void multibinpacking(Home home, int n, int m, int k, const IntVarArgs& y, const IntVarArgs& x, const IntSharedArray& D, const IntSharedArray& B, IntConLevel) { /// Check input sizes if (n*k != D.size() ) throw ArgumentSizeMismatch("Int::multibinpacking"); if (k != B.size() ) throw ArgumentSizeMismatch("Int::multibinpacking"); if (n != x.size() ) throw ArgumentSizeMismatch("Int::multibinpacking"); if (m*k != y.size() ) throw ArgumentSizeMismatch("Int::multibinpacking"); for (int i=B.size(); i--; ) Limits::nonnegative(B[i],"Int::multibinpacking"); if (home.failed()) return; /// Post first each single binpacking constraint /// Capacity constraint for each dimension for ( int j = 0; j < m; ++j ) for ( int l = 0; l < k; ++l ) { IntView yi(y[j*k+l]); GECODE_ME_FAIL(yi.lq(home,B[l])); } /// Post a binpacking constraints for each dimension for ( int l = 0; l < k; ++l ) { ViewArray<OffsetView> yv(home,m); for (int j=m; j--; ) yv[j] = OffsetView(y[j*k+l],0); ViewArray<BinPacking::Item> xs(home,x.size()); for (int i=xs.size(); i--; ) xs[i] = BinPacking::Item(x[i],D[i*k+l]); Support::quicksort(&xs[0], xs.size()); GECODE_ES_FAIL(Int::BinPacking::Pack::post(home,yv,xs)); } /// Clique Finding and Alldifferent posting { /// Firt construct the conflict graph graph_t* g = graph_new(n); for ( int a = 0; a < n-1; ++a ) { for ( int b = a+1; b < n; ++b ) { int v = a; /// The variable with smaller domain int w = b; unsigned int nl = 0; if ( x[a].size() > x[b].size() ) { v = b; w = a; } IntVarValues i(x[v]); IntVarValues j(x[w]); while ( i() ) { if ( i.val() != j.val() ) { if ( i.val() < j.val() ) break; else ++i; } else { for ( int l = 0; l < k; ++l ) if ( D[a*k+l] + D[b*k+l] > B[l] ) { nl++; break; } ++i; ++j; } } if ( nl >= x[v].size() ) GRAPH_ADD_EDGE(g,a,b); } } /// Consitency cheking: look for the maximum clique clique_options* opts; opts = (clique_options*) malloc (sizeof(clique_options)); opts->time_function=NULL; opts->reorder_function=reorder_by_default; opts->reorder_map=NULL; opts->user_function=NULL; opts->user_data=NULL; opts->clique_list=NULL; opts->clique_list_length=0; set_t s; s = clique_find_single ( g, 0, 0, TRUE, opts); if ( s != NULL ) { if ( set_size(s) > m ) { set_free(s); free(opts); graph_free(g); GECODE_ES_FAIL(ES_FAILED); } if ( true ) { //option == 1 ) { FIXING for ( int a = 0, j = 0; a < n; ++a ) { if ( SET_CONTAINS_FAST(s,a) ) { assert( x[a].in(j) ); IntView xi(x[a]); GECODE_ME_FAIL(xi.eq(home,j++)); } } } } if ( s!=NULL ) set_free(s); /// List every maximal clique in the conflict graph opts->user_function=record_clique_func; clique_find_all ( g, 2, 0, TRUE, opts); for ( int c = 0; c < clique_count; c++ ) { ViewArray<IntView> xv(home, set_size(clique_list[c])); for ( int a = 0, idx = 0; a < n; ++a ) if ( SET_CONTAINS_FAST(clique_list[c],a) ) xv[idx++] = x[a]; GECODE_ES_FAIL(Distinct::Dom<IntView>::post(home,xv)); set_free(clique_list[c]); } free(opts); graph_free(g); } }
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 cumulative(Home home, Cap c, const TaskTypeArgs& t, const IntVarArgs& s, const IntArgs& p, const IntArgs& u, IntConLevel icl) { using namespace Gecode::Int; using namespace Gecode::Int::Cumulative; if ((s.size() != p.size()) || (s.size() != u.size()) || (s.size() != t.size())) throw Int::ArgumentSizeMismatch("Int::cumulative"); long long int w = 0; for (int i=p.size(); i--; ) { Limits::nonnegative(p[i],"Int::cumulative"); Limits::nonnegative(u[i],"Int::cumulative"); Limits::check(static_cast<long long int>(s[i].max()) + p[i], "Int::cumulative"); mul_check(p[i],u[i]); w += s[i].width(); } mul_check(c.max(),w,s.size()); if (home.failed()) return; int minU = INT_MAX; int minU2 = INT_MAX; int maxU = INT_MIN; for (int i=u.size(); i--;) { if (u[i] < minU) { minU2 = minU; minU = u[i]; } else if (u[i] < minU2) minU2 = u[i]; if (u[i] > maxU) maxU = u[i]; } bool disjunctive = (minU > c.max()/2) || (minU2 > c.max()/2 && minU+minU2>c.max()); if (disjunctive) { GECODE_ME_FAIL(c.gq(home,maxU)); unary(home,t,s,p,icl); } else { bool fixp = true; for (int i=t.size(); i--;) if (t[i] != TT_FIXP) { fixp = false; break; } int nonOptionals = 0; for (unsigned int i=u.size(); i--;) if (u[i]>0) nonOptionals++; if (fixp) { TaskArray<ManFixPTask> tasks(home,nonOptionals); int cur = 0; for (int i=0; i<s.size(); i++) if (u[i] > 0) tasks[cur++].init(s[i],p[i],u[i]); GECODE_ES_FAIL((ManProp<ManFixPTask,Cap>::post(home,c,tasks))); } else { TaskArray<ManFixPSETask> tasks(home,nonOptionals); int cur = 0; for (int i=s.size(); i--;) if (u[i] > 0) tasks[cur++].init(t[i],s[i],p[i],u[i]); GECODE_ES_FAIL((ManProp<ManFixPSETask,Cap>::post(home,c,tasks))); } } }
void channel(Home home, const IntVarArgs& x, int xoff, const IntVarArgs& y, int yoff, IntConLevel icl) { using namespace Int; using namespace Channel; int n = x.size(); if (n != y.size()) throw ArgumentSizeMismatch("Int::channel"); if (x.same(home) || y.same(home)) throw ArgumentSame("Int::channel"); Limits::check(xoff,"Int::channel"); Limits::check(yoff,"Int::channel"); if ((xoff < 0) || (yoff < 0)) throw OutOfLimits("Int::channel"); if (home.failed()) return; if (n == 0) return; if ((xoff < 2) && (yoff < 2) && (xoff == yoff)) { if (icl == ICL_DOM) { DomInfo<IntView,NoOffset<IntView> >* di = static_cast<Space&>(home). alloc<DomInfo<IntView,NoOffset<IntView> > >(2*(n+xoff)); for (int i=n; i--; ) { di[xoff+i ].init(x[i],n+xoff); di[2*xoff+i+n].init(y[i],n+xoff); } if (xoff == 1) { IntVar x0(home,0,0); di[0].init(x0, n+xoff); IntVar y0(home,0,0); di[n+xoff].init(y0, n+xoff); } NoOffset<IntView> noff; if (x.same(home,y)) { GECODE_ES_FAIL((Dom<IntView,NoOffset<IntView>,true> ::post(home,n+xoff,di,noff,noff))); } else { GECODE_ES_FAIL((Dom<IntView,NoOffset<IntView>,false> ::post(home,n+xoff,di,noff,noff))); } } else { ValInfo<IntView>* vi = static_cast<Space&>(home).alloc<ValInfo<IntView> >(2*(n+xoff)); for (int i=n; i--; ) { vi[xoff+i ].init(x[i],n+xoff); vi[2*xoff+i+n].init(y[i],n+xoff); } if (xoff == 1) { IntVar x0(home,0,0); vi[0].init(x0, n+xoff); IntVar y0(home,0,0); vi[n+xoff].init(y0, n+xoff); } NoOffset<IntView> noff; if (x.same(home,y)) { GECODE_ES_FAIL((Val<IntView,NoOffset<IntView>,true> ::post(home,n+xoff,vi,noff,noff))); } else { GECODE_ES_FAIL((Val<IntView,NoOffset<IntView>,false> ::post(home,n+xoff,vi,noff,noff))); } } } else { if (icl == ICL_DOM) { DomInfo<IntView,Offset>* di = static_cast<Space&>(home).alloc<DomInfo<IntView,Offset> >(2*n); for (int i=n; i--; ) { di[i ].init(x[i],n); di[i+n].init(y[i],n); } Offset ox(-xoff); Offset oy(-yoff); if (x.same(home,y)) { GECODE_ES_FAIL((Dom<IntView,Offset,true> ::post(home,n,di,ox,oy))); } else { GECODE_ES_FAIL((Dom<IntView,Offset,false> ::post(home,n,di,ox,oy))); } } else { ValInfo<IntView>* vi = static_cast<Space&>(home).alloc<ValInfo<IntView> >(2*n); for (int i=n; i--; ) { vi[i ].init(x[i],n); vi[i+n].init(y[i],n); } Offset ox(-xoff); Offset oy(-yoff); if (x.same(home,y)) { GECODE_ES_FAIL((Val<IntView,Offset,true> ::post(home,n,vi,ox,oy))); } else { GECODE_ES_FAIL((Val<IntView,Offset,false> ::post(home,n,vi,ox,oy))); } } } }
// constant cards void count(Home home, const IntVarArgs& x, const IntSetArgs& _c, const IntArgs& _v, IntConLevel icl) { using namespace Int; IntSetArgs c(_c); IntArgs v(_v); if (v.size() != c.size()) throw ArgumentSizeMismatch("Int::count"); if (x.same(home)) throw ArgumentSame("Int::count"); for (int i=c.size(); i--; ) { Limits::check(v[i],"Int::count"); Limits::check(c[i].min(),"Int::count"); Limits::check(c[i].max(),"Int::count"); } if (home.failed()) return; removeDuplicates(home,c,v); ViewArray<IntView> xv(home, x); for (int i = v.size(); i--; ) { if (c[i].ranges() > 1) { // Found hole, so create temporary variables ViewArray<GCC::CardView> cv(home, v.size()); for (int j = v.size(); j--; ) cv[j].init(home,c[j],v[j]); switch (icl) { case ICL_BND: GECODE_ES_FAIL( (GCC::Bnd<GCC::CardView>::post(home, xv, cv))); break; case ICL_DOM: GECODE_ES_FAIL( (GCC::Dom<GCC::CardView>::post(home, xv, cv))); break; default: GECODE_ES_FAIL( (GCC::Val<GCC::CardView>::post(home, xv, cv))); } return; } } // No holes: create CardConsts ViewArray<GCC::CardConst> cv(home, c.size()); for (int i = c.size(); i--; ) cv[i].init(home,c[i].min(),c[i].max(),v[i]); switch (icl) { case ICL_BND: GECODE_ES_FAIL( (GCC::Bnd<GCC::CardConst>::post(home, xv, cv))); break; case ICL_DOM: GECODE_ES_FAIL( (GCC::Dom<GCC::CardConst>::post(home, xv, cv))); break; default: GECODE_ES_FAIL( (GCC::Val<GCC::CardConst>::post(home, xv, cv))); } }