ExecStatus purge(Space& home, Propagator& p, TaskArray<OptTask>& t, Cap c) { int n=t.size(); for (int i=n; i--; ) if (t[i].excluded()) { t[i].cancel(home,p,PL::pc); t[i]=t[--n]; } t.size(n); if (t.size() == 1) { if (t[0].mandatory()) GECODE_ME_CHECK(c.gq(home, t[0].c())); else if (c.min() < t[0].c()) return ES_OK; } return (t.size() < 2) ? home.ES_SUBSUMED(p) : ES_OK; }
void cumulative(Home home, Cap c, 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())) 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,s,p,icl); } else { int nonOptionals = 0; for (unsigned int i=u.size(); i--;) if (u[i]>0) nonOptionals++; TaskArray<ManFixPTask> t(home,nonOptionals); int cur = 0; for (int i=0; i<s.size(); i++) if (u[i]>0) t[cur++].init(s[i],p[i],u[i]); GECODE_ES_FAIL((ManProp<ManFixPTask,Cap>::post(home,c,t))); } }
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))); } } }
forceinline ExecStatus ManProp<ManTask,Cap>::post(Home home, Cap c, TaskArray<ManTask>& t) { // Capacity must be nonnegative GECODE_ME_CHECK(c.gq(home, 0)); // Check that tasks do not overload resource for (int i=t.size(); i--; ) if (t[i].c() > c.max()) return ES_FAILED; if (t.size() == 1) GECODE_ME_CHECK(c.gq(home, t[0].c())); if (t.size() > 1) { if (c.assigned() && c.val()==1) { TaskArray<typename TaskTraits<ManTask>::UnaryTask> mt(home,t.size()); for (int i=t.size(); i--; ) mt[i]=t[i]; return Unary::ManProp<typename TaskTraits<ManTask>::UnaryTask> ::post(home,mt); } else { (void) new (home) ManProp<ManTask,Cap>(home,c,t); } } return ES_OK; }
void cumulative(Home home, Cap c, const IntVarArgs& s, const IntVarArgs& p, const IntVarArgs& e, const IntArgs& u, IntConLevel icl) { using namespace Gecode::Int; using namespace Gecode::Int::Cumulative; if ((s.size() != p.size()) || (s.size() != e.size()) || (s.size() != u.size())) throw Int::ArgumentSizeMismatch("Int::cumulative"); long long int w = 0; for (int i=p.size(); i--; ) { rel(home, p[i], IRT_GQ, 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 fixP = true; for (int i=p.size(); i--;) { if (!p[i].assigned()) { fixP = false; break; } } if (fixP) { IntArgs pp(p.size()); for (int i=p.size(); i--;) pp[i] = p[i].val(); cumulative(home,c,s,pp,u,icl); } else { int nonOptionals = 0; for (unsigned int i=u.size(); i--;) if (u[i]>0) nonOptionals++; TaskArray<ManFlexTask> t(home,nonOptionals); int cur = 0; for (int i=0; i<s.size(); i++) if (u[i]>0) t[cur++].init(s[i],p[i],e[i],u[i]); GECODE_ES_FAIL((ManProp<ManFlexTask,Cap>::post(home,c,t))); } }
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))); } }
forceinline ExecStatus timetabling(Space& home, Propagator& p, Cap c, TaskArray<Task>& t) { int ccur = c.max(); int cmax = ccur; int cmin = ccur; // Sort tasks by decreasing capacity TaskByDecCap<Task> tbdc; Support::quicksort(&t[0], t.size(), tbdc); Region r(home); bool assigned; if (Event* e = Event::events(r,t,assigned)) { // Set of current but not required tasks Support::BitSet<Region> tasks(r,static_cast<unsigned int>(t.size())); // Process events, use ccur as the capacity that is still free do { // Current time int time = e->time(); // Process events for completion of required part for ( ; (e->type() == Event::LRT) && (e->time() == time); e++) if (t[e->idx()].mandatory()) { tasks.set(static_cast<unsigned int>(e->idx())); ccur += t[e->idx()].c(); } // Process events for completion of task for ( ; (e->type() == Event::LCT) && (e->time() == time); e++) tasks.clear(static_cast<unsigned int>(e->idx())); // Process events for start of task for ( ; (e->type() == Event::EST) && (e->time() == time); e++) tasks.set(static_cast<unsigned int>(e->idx())); // Process events for zero-length task for ( ; (e->type() == Event::ZRO) && (e->time() == time); e++) { ccur -= t[e->idx()].c(); if (ccur < cmin) cmin=ccur; if (ccur < 0) return ES_FAILED; ccur += t[e->idx()].c(); } // norun start time int nrstime = time; // Process events for start of required part for ( ; (e->type() == Event::ERT) && (e->time() == time); e++) if (t[e->idx()].mandatory()) { tasks.clear(static_cast<unsigned int>(e->idx())); ccur -= t[e->idx()].c(); if (ccur < cmin) cmin=ccur; nrstime = time+1; if (ccur < 0) return ES_FAILED; } else if (t[e->idx()].optional() && (t[e->idx()].c() > ccur)) { GECODE_ME_CHECK(t[e->idx()].excluded(home)); } // Exploit that tasks are sorted according to capacity for (Iter::Values::BitSet<Support::BitSet<Region> > j(tasks); j() && (t[j.val()].c() > ccur); ++j) // Task j cannot run from zltime to next time - 1 if (t[j.val()].mandatory()) GECODE_ME_CHECK(t[j.val()].norun(home, nrstime, e->time() - 1)); } while (e->type() != Event::END); GECODE_ME_CHECK(c.gq(home,cmax-cmin)); } if (assigned) return home.ES_SUBSUMED(p); return ES_NOFIX; }
ExecStatus basic(Space& home, bool& subsumed, Cap c, TaskArray<Task>& t) { subsumed = false; int ccur = c.max(); int cmax = ccur; int cmin = ccur; // Sort tasks by decreasing capacity TaskByDecCap<Task> tbdc; Support::quicksort(&t[0], t.size(), tbdc); Region r(home); Event* e = r.alloc<Event>(4*t.size()+1); // Initialize events bool assigned=true; { bool required=false; int n=0; for (int i=t.size(); i--; ) if (t[i].assigned()) { // Only add required part if (t[i].pmin() > 0) { required = true; e[n++].init(Event::ERT,t[i].lst(),i); e[n++].init(Event::LRT,t[i].ect(),i); } else if (t[i].pmax() == 0) { required = true; e[n++].init(Event::ZRO,t[i].lst(),i); } } else { assigned = false; e[n++].init(Event::EST,t[i].est(),i); e[n++].init(Event::LCT,t[i].lct(),i); // Check whether task has required part if (t[i].lst() < t[i].ect()) { required = true; e[n++].init(Event::ERT,t[i].lst(),i); e[n++].init(Event::LRT,t[i].ect(),i); } } // Check whether no task has a required part if (!required) { subsumed = assigned; return ES_FIX; } // Write end marker e[n++].init(Event::END,Int::Limits::infinity,-1); // Sort events Support::quicksort(e, n); } // Set of current but not required tasks Support::BitSet<Region> tasks(r,static_cast<unsigned int>(t.size())); // Process events, use ccur as the capacity that is still free while (e->e != Event::END) { // Current time int time = e->t; // Process events for completion of required part for ( ; (e->t == time) && (e->e == Event::LRT); e++) if (t[e->i].mandatory()) { tasks.set(static_cast<unsigned int>(e->i)); ccur += t[e->i].c(); } // Process events for completion of task for ( ; (e->t == time) && (e->e == Event::LCT); e++) tasks.clear(static_cast<unsigned int>(e->i)); // Process events for start of task for ( ; (e->t == time) && (e->e == Event::EST); e++) tasks.set(static_cast<unsigned int>(e->i)); // Process events for zero-length task for ( ; (e->t == time) && (e->e == Event::ZRO); e++) { ccur -= t[e->i].c(); if (ccur < cmin) cmin=ccur; if (ccur < 0) return ES_FAILED; ccur += t[e->i].c(); } // norun start time for 0-length tasks int zltime = time; // Process events for start of required part for ( ; (e->t == time) && (e->e == Event::ERT); e++) if (t[e->i].mandatory()) { tasks.clear(static_cast<unsigned int>(e->i)); ccur -= t[e->i].c(); if (ccur < cmin) cmin=ccur; zltime = time+1; if (ccur < 0) return ES_FAILED; } else if (t[e->i].optional() && (t[e->i].c() > ccur)) { GECODE_ME_CHECK(t[e->i].excluded(home)); } // Exploit that tasks are sorted according to capacity for (Iter::Values::BitSet<Support::BitSet<Region> > j(tasks); j() && (t[j.val()].c() > ccur); ++j) // Task j cannot run from time to next time - 1 if (t[j.val()].mandatory()) { if (t[j.val()].pmin() > 0) { GECODE_ME_CHECK(t[j.val()].norun(home, time, e->t - 1)); } else { GECODE_ME_CHECK(t[j.val()].norun(home, zltime, e->t - 1)); } } } GECODE_ME_CHECK(c.gq(home,cmax-cmin)); subsumed = assigned; return ES_NOFIX; }