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 unary(Home home, const IntVarArgs& s, const IntVarArgs& p, const IntVarArgs& e, const BoolVarArgs& m, IntConLevel icl) { using namespace Gecode::Int; using namespace Gecode::Int::Unary; if ((s.size() != p.size()) || (s.size() != m.size()) || (s.size() != e.size())) throw Int::ArgumentSizeMismatch("Int::unary"); if (home.failed()) return; for (int i=p.size(); i--; ) { rel(home, p[i], IRT_GQ, 0); } bool allMandatory = true; for (int i=m.size(); i--;) { if (!m[i].one()) { allMandatory = false; break; } } if (allMandatory) { unary(home,s,p,e,icl); } else { TaskArray<OptFlexTask> t(home,s.size()); for (int i=s.size(); i--; ) t[i].init(s[i],p[i],e[i],m[i]); GECODE_ES_FAIL(OptProp<OptFlexTask>::post(home,t)); } }
void unary(Home home, const IntVarArgs& s, const IntArgs& p, const BoolVarArgs& m, IntConLevel icl) { using namespace Gecode::Int; using namespace Gecode::Int::Unary; if (s.same(home)) throw Int::ArgumentSame("Int::unary"); if ((s.size() != p.size()) || (s.size() != m.size())) throw Int::ArgumentSizeMismatch("Int::unary"); for (int i=p.size(); i--; ) { Int::Limits::nonnegative(p[i],"Int::unary"); Int::Limits::check(static_cast<double>(s[i].max()) + p[i], "Int::unary"); } bool allMandatory = true; for (int i=m.size(); i--;) { if (!m[i].one()) { allMandatory = false; break; } } if (allMandatory) { unary(home,s,p,icl); } else { if (home.failed()) return; TaskArray<OptFixPTask> t(home,s.size()); for (int i=s.size(); i--; ) t[i].init(s[i],p[i],m[i]); GECODE_ES_FAIL(OptProp<OptFixPTask>::post(home,t)); } }
void extensional(Home home, const BoolVarArgs& x, const TupleSet& t, ExtensionalPropKind epk, IntConLevel) { using namespace Int; if (!t.finalized()) throw NotYetFinalized("Int::extensional"); if (t.arity() != x.size()) throw ArgumentSizeMismatch("Int::extensional"); if (home.failed()) return; // Construct view array ViewArray<BoolView> xv(home,x); switch (epk) { case EPK_SPEED: GECODE_ES_FAIL((Extensional::Incremental<BoolView> ::post(home,xv,t))); break; default: 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))); } break; } }
BoolExpr element(const BoolVarArgs& b, const LinExpr& idx) { BElementExpr* be = new BElementExpr(b.size()); for (int i=b.size(); i--;) new (&be->a[i]) BoolExpr(b[i]); be->idx = idx; return BoolExpr(be); }
void cumulative(Home home, Cap c, const TaskTypeArgs& t, const IntVarArgs& s, const IntArgs& p, const IntArgs& u, const BoolVarArgs& m, IntConLevel icl) { using namespace Gecode::Int; using namespace Gecode::Int::Cumulative; if ((s.size() != p.size()) || (s.size() != u.size()) || (s.size() != t.size()) || (s.size() != m.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; bool allMandatory = true; for (int i=m.size(); i--;) { if (!m[i].one()) { allMandatory = false; break; } } if (allMandatory) { cumulative(home,c,t,s,p,u,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<OptFixPTask> 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],m[i]); GECODE_ES_FAIL((OptProp<OptFixPTask,Cap>::post(home,c,tasks))); } else { TaskArray<OptFixPSETask> 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],m[i]); GECODE_ES_FAIL((OptProp<OptFixPSETask,Cap>::post(home,c,tasks))); } } }
void nooverlap(Home home, const IntVarArgs& x0, const IntVarArgs& w, const IntVarArgs& x1, const IntVarArgs& y0, const IntVarArgs& h, const IntVarArgs& y1, const BoolVarArgs& m, 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()) || (x0.size() != m.size())) throw ArgumentSizeMismatch("Int::nooverlap"); if (x0.same(home) || w.same(home) || x1.same(home) || y0.same(home) || h.same(home) || y1.same(home) || m.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, m); } else if (optional(m)) { OptBox<FlexDim,2>* b = static_cast<Space&>(home).alloc<OptBox<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]); b[i].optional(m[i]); } GECODE_ES_FAIL((NoOverlap::OptProp<FlexDim,2>::post(home,b,x0.size()))); } else { ManBox<FlexDim,2>* b = static_cast<Space&>(home).alloc<ManBox<FlexDim,2> >(x0.size()); int n = 0; for (int i=0; i<x0.size(); i++) if (m[i].one()) { b[n][0] = FlexDim(x0[i],w[i],x1[i]); b[n][1] = FlexDim(y0[i],h[i],y1[i]); n++; } GECODE_ES_FAIL((NoOverlap::ManProp<FlexDim,2>::post(home,b,n))); } }
void dom(Home home, const BoolVarArgs& x, const BoolVarArgs& d, IntConLevel) { using namespace Int; if (x.size() != d.size()) throw ArgumentSizeMismatch("Int::dom"); for (int i=x.size(); i--; ) { if (home.failed()) return; if (d[i].one()) GECODE_ME_FAIL(BoolView(x[i]).one(home)); else if (d[i].zero()) GECODE_ME_FAIL(BoolView(x[i]).zero(home)); } }
LinExpr::LinExpr(const BoolVarArgs& x) : n(new Node) { n->n_int = 0; n->n_bool = x.size(); n->t = NT_SUM_BOOL; n->l = n->r = NULL; if (x.size() > 0) { n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size()); for (int i=x.size(); i--; ) { n->sum.tb[i].x = x[i]; n->sum.tb[i].a = 1; } } }
bool optional(const BoolVarArgs& m) { for (int i=m.size(); i--; ) if (m[i].none()) return true; return false; }
LinExpr::LinExpr(const IntArgs& a, const BoolVarArgs& x) : n(new Node) { if (a.size() != x.size()) throw Int::ArgumentSizeMismatch("MiniModel::LinExpr"); n->n_int = 0; n->n_bool = x.size(); n->t = NT_SUM_BOOL; n->l = n->r = NULL; if (x.size() > 0) { n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size()); for (int i=x.size(); i--; ) { n->sum.tb[i].x = x[i]; n->sum.tb[i].a = a[i]; } } }
void nooverlap(Home home, const IntVarArgs& x, const IntArgs& w, const IntVarArgs& y, const IntArgs& h, const BoolVarArgs& m, IntConLevel) { using namespace Int; using namespace NoOverlap; if (x.same(home) || y.same(home) || m.same(home)) throw ArgumentSame("Int::nooverlap"); if ((x.size() != w.size()) || (x.size() != y.size()) || (x.size() != h.size()) || (x.size() != m.size())) throw ArgumentSizeMismatch("Int::nooverlap"); for (int i=x.size(); i--; ) { Limits::nonnegative(w[i],"Int::nooverlap"); Limits::nonnegative(h[i],"Int::nooverlap"); Limits::check(static_cast<double>(x[i].max()) + w[i], "Int::nooverlap"); Limits::check(static_cast<double>(y[i].max()) + h[i], "Int::nooverlap"); } if (home.failed()) return; if (optional(m)) { OptBox<FixDim,2>* b = static_cast<Space&>(home).alloc<OptBox<FixDim,2> >(x.size()); for (int i=x.size(); i--; ) { b[i][0] = FixDim(x[i],w[i]); b[i][1] = FixDim(y[i],h[i]); b[i].optional(m[i]); } GECODE_ES_FAIL((NoOverlap::OptProp<FixDim,2>::post(home,b,x.size()))); } else { ManBox<FixDim,2>* b = static_cast<Space&>(home).alloc<ManBox<FixDim,2> >(x.size()); int n = 0; for (int i=0; i<x.size(); i++) if (m[i].one()) { b[n][0] = FixDim(x[i],w[i]); b[n][1] = FixDim(y[i],h[i]); n++; } GECODE_ES_FAIL((NoOverlap::ManProp<FixDim,2>::post(home,b,n))); } }
void extensional(Home home, const BoolVarArgs& x, DFA dfa, IntPropLevel) { using namespace Int; if (x.same(home)) throw ArgumentSame("Int::extensional"); GECODE_POST; GECODE_ES_FAIL(Extensional::post_lgp(home,x,dfa)); }
void extensional(Home home, const BoolVarArgs& x, DFA dfa, IntConLevel) { using namespace Int; if (x.same(home)) throw ArgumentSame("Int::extensional"); if (home.failed()) return; GECODE_ES_FAIL(Extensional::post_lgp(home,x,dfa)); }
void linear(Home home, const IntArgs& a, const BoolVarArgs& x, IntRelType irt, IntVar y, Reify r, IntPropLevel ipl) { if (a.size() != x.size()) throw ArgumentSizeMismatch("Int::linear"); GECODE_POST; int n=x.size(); Region re(home); Linear::Term<BoolView>* t = re.alloc<Linear::Term<BoolView> >(n); for (int i=n; i--; ) { t[i].a=a[i]; t[i].x=x[i]; } Linear::post(home,t,n,irt,y,r,ipl); }
void cumulative(Home home, Cap c, const IntVarArgs& s, const IntVarArgs& p, const IntVarArgs& e, const IntArgs& u, const BoolVarArgs& m, IntConLevel icl) { using namespace Gecode::Int; using namespace Gecode::Int::Cumulative; if ((s.size() != p.size()) || (s.size() != u.size()) || (s.size() != e.size()) || (s.size() != m.size())) throw Int::ArgumentSizeMismatch("Int::cumulative"); for (int i=p.size(); i--; ) { rel(home, p[i], IRT_GQ, 0); } long long int w = 0; for (int i=p.size(); i--; ) { Limits::nonnegative(u[i],"Int::cumulative"); Limits::check(static_cast<long long int>(s[i].max()) + p[i].max(), "Int::cumulative"); mul_check(p[i].max(),u[i]); w += s[i].width(); } mul_check(c.max(),w,s.size()); if (home.failed()) return; bool allMandatory = true; for (int i=m.size(); i--;) { if (!m[i].one()) { allMandatory = false; break; } } if (allMandatory) { cumulative(home,c,s,p,e,u,icl); } else { int nonOptionals = 0; for (unsigned int i=u.size(); i--;) if (u[i]>0) nonOptionals++; TaskArray<OptFlexTask> t(home,nonOptionals); int cur = 0; for (int i=s.size(); i--; ) if (u[i]>0) t[cur++].init(s[i],p[i],e[i],u[i],m[i]); GECODE_ES_FAIL((OptProp<OptFlexTask,Cap>::post(home,c,t))); } }
void unary(Home home, const TaskTypeArgs& t, const IntVarArgs& flex, const IntArgs& fix, const BoolVarArgs& m, IntConLevel icl) { using namespace Gecode::Int; using namespace Gecode::Int::Unary; if ((flex.size() != fix.size()) || (flex.size() != t.size()) || (flex.size() != m.size())) throw Int::ArgumentSizeMismatch("Int::unary"); bool fixp = true; for (int i=fix.size(); i--; ) { if (t[i] == TT_FIXP) { Int::Limits::nonnegative(fix[i],"Int::unary"); } else { fixp = false; Int::Limits::check(fix[i],"Int::unary"); } Int::Limits::check(static_cast<double>(flex[i].max()) + fix[i], "Int::unary"); } if (home.failed()) return; bool allMandatory = true; for (int i=m.size(); i--;) { if (!m[i].one()) { allMandatory = false; break; } } if (allMandatory) { unary(home,t,flex,fix,icl); } else { if (fixp) { TaskArray<OptFixPTask> tasks(home,flex.size()); for (int i=flex.size(); i--; ) tasks[i].init(flex[i],fix[i],m[i]); GECODE_ES_FAIL(OptProp<OptFixPTask>::post(home,tasks)); } else { TaskArray<OptFixPSETask> tasks(home,flex.size()); for (int i=flex.size(); i--;) tasks[i].init(t[i],flex[i],fix[i],m[i]); GECODE_ES_FAIL(OptProp<OptFixPSETask>::post(home,tasks)); } } }
void distinct(Home home, const BoolVarArgs& b, const IntVarArgs& x, IntPropLevel ipl) { using namespace Int; if (x.same(home)) throw ArgumentSame("Int::distinct"); if (b.size() != x.size()) throw ArgumentSizeMismatch("Int::distinct"); GECODE_POST; int n = x.size(); int min = Limits::max; int max = Limits::min; int m = 0; for (int i=n; i--; ) if (!b[i].zero()) { min = std::min(min,x[i].min()); max = std::max(max,x[i].max()); m++; } if (m < 2) return; int start; if (max < Limits::max-m) start = max+1; else if (min > Limits::min+m) start = min-(m+1); else throw OutOfLimits("Int::distinct"); ViewArray<IntView> y(home,m); int j = 0; for (int i=n; i--; ) if (b[i].one()) { y[j] = x[i]; j++; } else if (b[i].none()) { y[j] = IntVar(home, Limits::min, Limits::max); GECODE_ES_FAIL((Bool::IteDom<IntView,ConstIntView,IntView>::post (home, b[i], x[i], start+j, y[j]))); j++; } assert(j == m); switch (vbd(ipl)) { case IPL_BND: GECODE_ES_FAIL(Distinct::Bnd<IntView>::post(home,y)); break; case IPL_DOM: GECODE_ES_FAIL(Distinct::Dom<IntView>::post(home,y)); break; default: GECODE_ES_FAIL(Distinct::Val<IntView>::post(home,y)); } }
void element(Home home, const BoolVarArgs& a, IntVar x, int w, IntVar y, int h, BoolVar z, IntConLevel icl) { using namespace Int; if (a.size() != w*h) throw Int::ArgumentSizeMismatch("Int::element"); if (home.failed()) return; element(home, a, pair(home,x,w,y,h), z, icl); }
void channel(Home home, const BoolVarArgs& x, IntVar y, int o, IntConLevel) { using namespace Int; if (x.same(home)) throw ArgumentSame("Int::channel"); Limits::check(o,"Int::channel"); if (home.failed()) return; ViewArray<BoolView> xv(home,x); GECODE_ES_FAIL(Channel::LinkMulti::post(home,xv,y,o)); }
void element(Home home, const BoolVarArgs& c, IntVar x0, BoolVar x1, IntConLevel) { using namespace Int; if (c.size() == 0) throw TooFewArguments("Int::element"); if (home.failed()) return; IdxViewArray<BoolView> iv(home,c); GECODE_ES_FAIL((Element::ViewBnd<BoolView,IntView,BoolView> ::post(home,iv,x0,x1))); }
void linear(Home home, const IntArgs& a, const BoolVarArgs& x, IntRelType irt, IntVar y, IntPropLevel ipl) { if (a.size() != x.size()) throw ArgumentSizeMismatch("Int::linear"); GECODE_POST; int n=x.size(); Region re(home); Linear::Term<BoolView>* t = re.alloc<Linear::Term<BoolView> >(n); for (int i=n; i--; ) { t[i].a=a[i]; t[i].x=x[i]; } int min, max; estimate(t,n,0,min,max); IntView v(y); switch (irt) { case IRT_EQ: GECODE_ME_FAIL(v.gq(home,min)); GECODE_ME_FAIL(v.lq(home,max)); break; case IRT_GQ: GECODE_ME_FAIL(v.lq(home,max)); break; case IRT_LQ: GECODE_ME_FAIL(v.gq(home,min)); break; default: ; } if (home.failed()) return; Linear::post(home,t,n,irt,y,0,ipl); }
void linear(Home home, const BoolVarArgs& x, IntRelType irt, IntVar y, IntPropLevel ipl) { GECODE_POST; int n=x.size(); Region re(home); Linear::Term<BoolView>* t = re.alloc<Linear::Term<BoolView> >(n); for (int i=n; i--; ) { t[i].a=1; t[i].x=x[i]; } Linear::post(home,t,n,irt,y,0,ipl); }
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))); }
//@+node:gcross.20101224191604.2770: ** Functions //@+node:gcross.20110114154616.2017: *3* channelMatrix IntMatrix channelMatrix(Space& space, const BoolMatrix& matrix) { BoolVarArgs vars = matrix.get_array(); IntVarArgs vars_as_ints(space,vars.size(),0,1); BOOST_FOREACH(const unsigned int i, irange(0u,(unsigned int)vars.size())) { channel(space,vars[i],vars_as_ints[i]); } return IntMatrix(vars_as_ints,matrix.width(),matrix.height()); }