00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <algorithm>
00039
00040
00041
00042
00043
00044
00045
00046
00047 namespace Gecode { namespace Int { namespace Cumulatives {
00048
00049 template<class ViewM, class ViewP, class ViewU, class View>
00050 forceinline
00051 Val<ViewM,ViewP,ViewU,View>::Val(Home home,
00052 const ViewArray<ViewM>& _m,
00053 const ViewArray<View>& _s,
00054 const ViewArray<ViewP>& _p,
00055 const ViewArray<View>& _e,
00056 const ViewArray<ViewU>& _u,
00057 const SharedArray<int>& _c,
00058 bool _at_most) :
00059 Propagator(home),
00060 m(_m), s(_s), p(_p), e(_e), u(_u), c(_c), at_most(_at_most) {
00061 home.notice(*this,AP_DISPOSE);
00062
00063 m.subscribe(home,*this,Int::PC_INT_DOM);
00064 s.subscribe(home,*this,Int::PC_INT_BND);
00065 p.subscribe(home,*this,Int::PC_INT_BND);
00066 e.subscribe(home,*this,Int::PC_INT_BND);
00067 u.subscribe(home,*this,Int::PC_INT_BND);
00068 }
00069
00070 template<class ViewM, class ViewP, class ViewU, class View>
00071 ExecStatus
00072 Val<ViewM,ViewP,ViewU,View>
00073 ::post(Home home, const ViewArray<ViewM>& m,
00074 const ViewArray<View>& s, const ViewArray<ViewP>& p,
00075 const ViewArray<View>& e, const ViewArray<ViewU>& u,
00076 const SharedArray<int>& c, bool at_most) {
00077 (void) new (home) Val(home, m,s,p,e,u,c,at_most);
00078 return ES_OK;
00079 }
00080
00081 template<class ViewM, class ViewP, class ViewU, class View>
00082 forceinline
00083 Val<ViewM,ViewP,ViewU,View>::Val(Space& home, bool share,
00084 Val<ViewM,ViewP,ViewU,View>& vp)
00085 : Propagator(home,share,vp), at_most(vp.at_most) {
00086 m.update(home,share,vp.m);
00087 s.update(home, share, vp.s);
00088 p.update(home, share, vp.p);
00089 e.update(home, share, vp.e);
00090 u.update(home, share, vp.u);
00091 c.update(home, share, vp.c);
00092 }
00093
00094 template<class ViewM, class ViewP, class ViewU, class View>
00095 size_t
00096 Val<ViewM,ViewP,ViewU,View>::dispose(Space& home) {
00097 home.ignore(*this,AP_DISPOSE);
00098 if (!home.failed()) {
00099 m.cancel(home,*this,Int::PC_INT_DOM);
00100 s.cancel(home,*this,Int::PC_INT_BND);
00101 p.cancel(home,*this,Int::PC_INT_BND);
00102 e.cancel(home,*this,Int::PC_INT_BND);
00103 u.cancel(home,*this,Int::PC_INT_BND);
00104 }
00105 c.~SharedArray();
00106 (void) Propagator::dispose(home);
00107 return sizeof(*this);
00108 }
00109
00110 template<class ViewM, class ViewP, class ViewU, class View>
00111 PropCost
00112 Val<ViewM,ViewP,ViewU,View>::cost(const Space&, const ModEventDelta&) const {
00113 return PropCost::quadratic(PropCost::LO, s.size());
00114 }
00115
00116 template<class ViewM, class ViewP, class ViewU, class View>
00117 Actor*
00118 Val<ViewM,ViewP,ViewU,View>::copy(Space& home, bool share) {
00119 return new (home) Val<ViewM,ViewP,ViewU,View>(home,share,*this);
00120 }
00121
00123 typedef enum {EVENT_CHCK, EVENT_PROF, EVENT_PRUN} ev_t;
00125 class Event
00126 {
00127 public:
00129 ev_t e;
00131 int task;
00133 int date;
00135 int inc;
00140 bool first_prof;
00141
00143 Event(ev_t _e, int _task, int _date, int _inc = 0, bool _first_prof = false)
00144 : e(_e), task(_task), date(_date), inc(_inc), first_prof(_first_prof)
00145 {}
00146
00147
00148 Event(void) {}
00149
00151 bool operator <(const Event& ev) const {
00152 if (date == ev.date) {
00153 if (e == EVENT_PROF && ev.e != EVENT_PROF) return true;
00154 if (e == EVENT_CHCK && ev.e == EVENT_PRUN) return true;
00155 return false;
00156 }
00157 return date < ev.date;
00158 }
00159 };
00160
00161 template<class ViewM, class ViewP, class ViewU, class View>
00162 ExecStatus
00163 Val<ViewM,ViewP,ViewU,View>::prune(Space& home, int low, int up, int r,
00164 int ntask, int su,
00165 int* contribution,
00166 int* prune_tasks, int& prune_tasks_size) {
00167
00168 if (ntask > 0 && (at_most ? su > c[r] : su < c[r])) {
00169 return ES_FAILED;
00170 }
00171
00172 int pti = 0;
00173 while (pti != prune_tasks_size) {
00174 int t = prune_tasks[pti];
00175
00176
00177
00178
00179 if (ntask != 0 &&
00180 (at_most ? u[t].min() < 0
00181 : u[t].max() > 0) &&
00182 (at_most ? su-contribution[t] > c[r]
00183 : su-contribution[t] < c[r])) {
00184 if (me_failed(m[t].eq(home, r))||
00185 me_failed(s[t].gq(home, up-p[t].max()+1))||
00186 me_failed(s[t].lq(home, low))||
00187 me_failed(e[t].lq(home,low+p[t].max()))||
00188 me_failed(e[t].gq(home, up+1))||
00189 me_failed(p[t].gq(home,std::min(up-s[t].max()+1,e[t].min()-low)))
00190 ) {
00191 return ES_FAILED;
00192 }
00193 }
00194
00195
00196
00197 if (at_most ? u[t].min() > std::min(0, c[r])
00198 : u[t].max() < std::max(0, c[r])) {
00199 if (at_most ? su-contribution[t]+u[t].min() > c[r]
00200 : su-contribution[t]+u[t].max() < c[r]) {
00201 if (e[t].min() > low &&
00202 s[t].max() <= up &&
00203 p[t].min() > 0) {
00204 if (me_failed(m[t].nq(home, r))) {
00205 return ES_FAILED;
00206 }
00207 } else if (m[t].assigned()) {
00208 int ptmin = p[t].min();
00209 if (ptmin > 0) {
00210 Iter::Ranges::Singleton
00211 a(low-ptmin+1, up), b(low+1, up+ptmin);
00212 if (me_failed(s[t].minus_r(home,a,false)) ||
00213 me_failed(e[t].minus_r(home, b,false)))
00214 return ES_FAILED;
00215 }
00216 if (me_failed(p[t].lq(home,std::max(std::max(low-s[t].min(),
00217 e[t].max()-up-1),
00218 0)))) {
00219 return ES_FAILED;
00220 }
00221 }
00222 }
00223 }
00224
00225
00226
00227
00228
00229
00230
00231 if (m[t].assigned() &&
00232 m[t].val() == r &&
00233 e[t].min() > low &&
00234 s[t].max() <= up &&
00235 p[t].min() > 0 ) {
00236 if (me_failed(at_most
00237 ? u[t].lq(home, c[r]-su+contribution[t])
00238 : u[t].gq(home, c[r]-su+contribution[t]))) {
00239 return ES_FAILED;
00240 }
00241 }
00242
00243
00244 if (!m[t].in(r) || (e[t].max() <= up+1)) {
00245 prune_tasks[pti] = prune_tasks[--prune_tasks_size];
00246 } else {
00247 ++pti;
00248 }
00249 }
00250
00251 return ES_OK;
00252 }
00253
00254 namespace {
00255 template<class C>
00256 class Less {
00257 public:
00258 bool operator ()(const C& lhs, const C& rhs) {
00259 return lhs < rhs;
00260 }
00261 };
00262 }
00263
00264 template<class ViewM, class ViewP, class ViewU, class View>
00265 ExecStatus
00266 Val<ViewM,ViewP,ViewU,View>::propagate(Space& home, const ModEventDelta&) {
00267
00268 bool subsumed = true;
00269 for (int t = s.size(); t--; )
00270 if (!(p[t].assigned() && e[t].assigned() &&
00271 m[t].assigned() && s[t].assigned() &&
00272 u[t].assigned())) {
00273 subsumed = false;
00274 break;
00275 }
00276
00277 Region region(home);
00278 Event *events = region.alloc<Event>(s.size()*8);
00279 int events_size;
00280 int *prune_tasks = region.alloc<int>(s.size());
00281 int prune_tasks_size;
00282 int *contribution = region.alloc<int>(s.size());
00283 for (int r = c.size(); r--; ) {
00284 events_size = 0;
00285 #define GECODE_PUSH_EVENTS(E) assert(events_size < s.size()*8); \
00286 events[events_size++] = E
00287
00288
00289 for (int t = s.size(); t--; ) {
00290 if (m[t].assigned() &&
00291 m[t].val() == r &&
00292 s[t].max() < e[t].min()) {
00293 if (at_most
00294 ? u[t].min() > std::min(0, c[r])
00295 : u[t].max() < std::max(0, c[r])) {
00296 GECODE_PUSH_EVENTS(Event(EVENT_CHCK, t, s[t].max(), 1));
00297 GECODE_PUSH_EVENTS(Event(EVENT_CHCK, t, e[t].min(), -1));
00298 }
00299 if (at_most
00300 ? u[t].min() > 0
00301 : u[t].max() < 0) {
00302 GECODE_PUSH_EVENTS(Event(EVENT_PROF, t, s[t].max(),
00303 at_most ? u[t].min() : u[t].max(), true));
00304 GECODE_PUSH_EVENTS(Event(EVENT_PROF, t, e[t].min(),
00305 at_most ? -u[t].min() : -u[t].max()));
00306 }
00307 }
00308
00309 if (m[t].in(r)) {
00310 if (at_most
00311 ? u[t].min() < 0
00312 : u[t].max() > 0) {
00313 GECODE_PUSH_EVENTS(Event(EVENT_PROF, t, s[t].min(),
00314 at_most ? u[t].min() : u[t].max(), true));
00315 GECODE_PUSH_EVENTS(Event(EVENT_PROF, t, e[t].max(),
00316 at_most ? -u[t].min() : -u[t].max()));
00317 }
00318 if (!(m[t].assigned() &&
00319 u[t].assigned() &&
00320 s[t].assigned() &&
00321 e[t].assigned())) {
00322 GECODE_PUSH_EVENTS(Event(EVENT_PRUN, t, s[t].min()));
00323 }
00324 }
00325 }
00326 #undef GECODE_PUSH_EVENTS
00327
00328
00329 if (events_size == 0) {
00330 continue;
00331 }
00332
00333
00334 Less<Event> less;
00335 Support::insertion(&events[0], events_size, less);
00336
00337
00338 int d = 0;
00339 int ntask = 0;
00340 int su = 0;
00341 int ei = 0;
00342
00343 prune_tasks_size = 0;
00344 for (int i = s.size(); i--; ) contribution[i] = 0;
00345
00346 d = events[ei].date;
00347 while (ei < events_size) {
00348 if (events[ei].e != EVENT_PRUN) {
00349 if (d != events[ei].date) {
00350 GECODE_ES_CHECK(prune(home, d, events[ei].date-1, r,
00351 ntask, su,
00352 contribution, prune_tasks, prune_tasks_size));
00353 d = events[ei].date;
00354 }
00355 if (events[ei].e == EVENT_CHCK) {
00356 ntask += events[ei].inc;
00357 } else {
00358 su += events[ei].inc;
00359 if(events[ei].first_prof)
00360 contribution[events[ei].task] = at_most
00361 ? std::max(contribution[events[ei].task], events[ei].inc)
00362 : std::min(contribution[events[ei].task], events[ei].inc);
00363 }
00364 } else {
00365 assert(prune_tasks_size<s.size());
00366 prune_tasks[prune_tasks_size++] = events[ei].task;
00367 }
00368 ei++;
00369 }
00370
00371 GECODE_ES_CHECK(prune(home, d, d, r,
00372 ntask, su,
00373 contribution, prune_tasks, prune_tasks_size));
00374 }
00375 return subsumed ? home.ES_SUBSUMED(*this): ES_NOFIX;
00376 }
00377
00378 }}}
00379
00380