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 namespace Gecode { namespace Int { namespace Extensional {
00039
00040
00041
00042
00043
00044 template <class View>
00045 forceinline
00046 Incremental<View>::SupportEntry::SupportEntry(void)
00047 : t(NULL), next(NULL) {}
00048
00049 template <class View>
00050 forceinline
00051 Incremental<View>::SupportEntry::SupportEntry(Tuple t0, SupportEntry* n0)
00052 : t(t0), next(n0) {}
00053
00054 template <class View>
00055 forceinline void
00056 Incremental<View>::SupportEntry::operator delete(void*) {}
00057
00058 template <class View>
00059 forceinline void
00060 Incremental<View>::SupportEntry::operator delete(void*, Space*) {
00061 GECODE_NEVER;
00062 }
00063
00064 template <class View>
00065 forceinline void*
00066 Incremental<View>::SupportEntry::operator new(size_t, Space* home) {
00067 return home->fl_alloc<sizeof(SupportEntry)>();
00068 }
00069
00070 template <class View>
00071 forceinline void
00072 Incremental<View>::SupportEntry::dispose(Space* home, SupportEntry* l) {
00073 home->fl_dispose<sizeof(SupportEntry)>(this,l);
00074 }
00075
00076 template <class View>
00077 forceinline void
00078 Incremental<View>::SupportEntry::dispose(Space* home) {
00079 next = NULL;
00080 home->fl_dispose<sizeof(SupportEntry)>(this,this);
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090 template <class View>
00091 forceinline
00092 Incremental<View>::Incremental(Space* home, ViewArray<View>& x, const TupleSet& t)
00093 : Base<View,false>(home,x,t), support_data(NULL),
00094 work(x.size()), unassigned(x.size()), ac(home) {
00095 init_support(home);
00096
00097 ModEvent me = ME_INT_DOM;
00098
00099
00100 for (int i = x.size(); i--; ) {
00101 if (x[i].assigned()) {
00102 --unassigned;
00103 me = ME_INT_VAL;
00104 } else {
00105 (void) new (home) SupportAdvisor(home, this, ac, x[i], i);
00106 }
00107 }
00108
00109
00110 GECODE_AUTOARRAY(BitSet, dom, x.size());
00111 init_dom(home, dom);
00112 for (int i = x.size(); i--; ) {
00113 ViewValues<View> vv(x[i]);
00114 while (vv()) {
00115 find_support(home, dom, i, vv.val());
00116 ++vv;
00117 }
00118 }
00119 if (!work.empty() || unassigned==0) {
00120
00121 View::schedule(home,this,me);
00122 }
00123 }
00124
00125 template <class View>
00126 ExecStatus
00127 Incremental<View>::post(Space* home, ViewArray<View>& x, const TupleSet& t) {
00128 (void) new (home) Incremental<View>(home,x,t);
00129 return ES_OK;
00130 }
00131
00132 template <class View>
00133 forceinline
00134 Incremental<View>::Incremental(Space* home, bool share, Incremental<View>& p)
00135 : Base<View,false>(home,share,p), support_data(NULL),
00136 work(2), unassigned(p.unassigned) {
00137 ac.update(home,share,p.ac);
00138
00139 init_support(home);
00140 int literals = ts()->domsize*x.size();
00141 for (int i = literals; i--; ) {
00142 SupportEntry** n = &(support_data[i]);
00143 SupportEntry* o = p.support_data[i];
00144 while (o) {
00145
00146 SupportEntry* s = new (home) SupportEntry(o->t);
00147
00148 (*n) = s;
00149 n = &(s->next);
00150
00151 o = o->next;
00152 }
00153 }
00154 }
00155
00156 template <class View>
00157 PropCost
00158 Incremental<View>::cost(ModEventDelta med) const {
00159 return (View::me(med) == ME_INT_VAL)
00160 ? PC_QUADRATIC_HI : PC_CUBIC_HI;
00161 }
00162
00163 template <class View>
00164 Actor*
00165 Incremental<View>::copy(Space* home, bool share) {
00166 return new (home) Incremental<View>(home,share,*this);
00167 }
00168
00169 template <class View>
00170 Gecode::Support::Symbol
00171 Incremental<View>::ati(void) {
00172 return Reflection::mangle<View>("Gecode::Int::Extensional::Incremental");
00173 }
00174
00175 template <class View>
00176 Reflection::ActorSpec
00177 Incremental<View>::spec(const Space* home, Reflection::VarMap& m) const {
00178 Reflection::ActorSpec s(ati());
00179 return s << x.spec(home, m)
00180 << tupleSet.spec(m);
00181 }
00182
00183 template <class View>
00184 void
00185 Incremental<View>::post(Space* home, Reflection::VarMap& vars,
00186 const Reflection::ActorSpec& spec) {
00187 spec.checkArity(2);
00188 ViewArray<View> x(home, vars, spec[0]);
00189 TupleSet tupleSet(vars, spec[1]);
00190 (void) new (home) Incremental<View>(home,x,tupleSet);
00191 }
00192
00193 template <class View>
00194 ExecStatus
00195 Incremental<View>::propagate(Space* home, ModEventDelta) {
00196 assert(!work.empty() || unassigned==0);
00199 GECODE_AUTOARRAY(BitSet, dom, x.size());
00200 init_dom(home, dom);
00201
00203 while (!work.empty()) {
00204 Work w = work.pop();
00205 if (dom[w.var].get(w.val-ts()->min)) {
00206
00207 switch (w.work) {
00208 case WT_FIND_SUPPORT:
00209 find_support(home, dom, w.var, w.val);
00210 break;
00211 case WT_REMOVE_VALUE:
00212 {
00213 assert(support(w.var, w.val) == NULL);
00214 ModEvent me = x[w.var].nq(home,w.val);
00215 if (me_failed(me)) {
00216 return ES_FAILED;
00217 }
00218 dom[w.var].set(w.val-ts()->min, false);
00219 }
00220 break;
00221 default:
00222 GECODE_NEVER;
00223 break;
00224 };
00225 }
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 if (unassigned != 0) {
00237 return ES_FIX;
00238 }
00239
00240 return ES_SUBSUMED(this, home);
00241 }
00242
00243
00244
00245 template <class View>
00246 forceinline void
00247 Incremental<View>::add_support(Space* home, Tuple l) {
00248 for (int i = x.size(); i--; ) {
00249 int pos = (i*ts()->domsize) + (l[i] - ts()->min);
00250
00251 SupportEntry* s = new (home) SupportEntry(l, support_data[pos]);
00252 support_data[pos] = s;
00253 }
00254 }
00255
00256 template <class View>
00257 forceinline void
00258 Incremental<View>::remove_support(Space* home, Tuple l,
00259 int var, int ) {
00260 for (int i = x.size(); i--; ) {
00261 int v = l[i];
00262 int ov = v - ts()->min;
00263 int pos = (i*(ts()->domsize)) + ov;
00264
00265 assert(support_data[pos] != NULL);
00266
00267 SupportEntry** a = &(support_data[pos]);
00268 while ((*a)->t != l) {
00269 assert((*a)->next != NULL);
00270 a = &((*a)->next);
00271 }
00272 SupportEntry* old = *a;
00273 *a = (*a)->next;
00274
00275 old->dispose(home);
00276 if (i != var && support_data[pos] == NULL) {
00277 work.push(Work(WT_FIND_SUPPORT, i, v));
00278 }
00279 }
00280 }
00281
00282 template <class View>
00283 forceinline void
00284 Incremental<View>::find_support(Space* home, Domain dom, int var, int val) {
00285 if (support(var, val) == NULL) {
00286 int oval = val - ts()->min;
00287
00288 Tuple l = Base<View,false>::find_support(dom, var, oval);
00289 if (l == NULL) {
00290
00291 work.push(Work(WT_REMOVE_VALUE, var, val));
00292 } else {
00293
00294 add_support(home, l);
00295 }
00296 }
00297 }
00298
00299 template <class View>
00300 forceinline void
00301 Incremental<View>::init_support(Space* home) {
00302 assert(support_data == NULL);
00303 int literals = ts()->domsize*x.size();
00304 support_data = static_cast<SupportEntry**>
00305 (home->alloc(literals*sizeof(SupportEntry*)));
00306 for (int i = literals; i--; ) {
00307 support_data[i] = NULL;
00308 }
00309 }
00310
00311 template <class View>
00312 forceinline typename Incremental<View>::SupportEntry*
00313 Incremental<View>::support(int var, int val) {
00314 int oval = val - ts()->min;
00315 return support_data[(var*(ts()->domsize)) + oval];
00316 }
00317
00318
00319
00320
00321
00322 template <class View>
00323 ExecStatus
00324 Incremental<View>::advise(Space *home, Advisor* a0, const Delta* d) {
00325 SupportAdvisor* a = static_cast<SupportAdvisor*>(a0);
00326 ModEvent me = View::modevent(d);
00327 bool scheduled = !work.empty();
00328
00329 if (a->x.any(d)) {
00330 ViewValues<View> vv(a->x);
00331 for (int i = ts()->min; i <= ts()->max; ++i) {
00332 if (vv() && i == vv.val()) {
00333 ++vv;
00334 continue;
00335 }
00336 while (SupportEntry* s = support(a->pos, i)) {
00337 remove_support(home, s->t, a->pos, i);
00338 }
00339 }
00340 } else {
00341 int lo = a->x.min(d);
00342 int hi = a->x.max(d);
00343 for (int val = lo; val <= hi; ++val) {
00344 while (SupportEntry* s = support(a->pos, val)) {
00345 remove_support(home, s->t, a->pos, val);
00346 }
00347 }
00348 }
00349
00350
00351 if (me == ME_INT_VAL) {
00352 --unassigned;
00353 if ((work.empty() || scheduled) && unassigned!=0) {
00354
00355
00356 return ES_SUBSUMED_FIX(a,home,ac);
00357 }
00358 return ES_SUBSUMED_NOFIX(a,home,ac);
00359 }
00360 if (work.empty() || scheduled) {
00361
00362 return ES_FIX;
00363 }
00364 return ES_NOFIX;
00365 }
00366
00367
00368 template <class View>
00369 size_t
00370 Incremental<View>::dispose(Space* home) {
00371 if (!home->failed()) {
00372 int literals = ts()->domsize*x.size();
00373 for (int i = literals; i--; ) {
00374 if (support_data[i]) {
00375 SupportEntry* lastse = support_data[i];
00376 while (lastse->next) lastse = lastse->next;
00377 support_data[i]->dispose(home, lastse);
00378 }
00379 }
00380 home->reuse(support_data, sizeof(SupportEntry*)*literals);
00381 }
00382 work.~WorkStack();
00383 (void) ac.dispose(home);
00384
00385 (void) Base<View,false>::dispose(home);
00386
00387 return sizeof(*this);
00388 }
00389
00390 }}}
00391
00392
00393