path.hh
Go to the documentation of this file.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 #ifndef __GECODE_SEARCH_PARALLEL_PATH_HH__
00039 #define __GECODE_SEARCH_PARALLEL_PATH_HH__
00040
00041 #include <gecode/search.hh>
00042
00043 namespace Gecode { namespace Search { namespace Parallel {
00044
00058 class Path {
00059 public:
00061 class Node {
00062 protected:
00064 Space* _space;
00066 unsigned int _alt;
00068 unsigned int _alt_max;
00070 const BranchingDesc* _desc;
00071 public:
00073 Node(void);
00075 Node(Space* s, Space* c);
00076
00078 Space* space(void) const;
00080 void space(Space* s);
00081
00083 const BranchingDesc* desc(void) const;
00084
00086 unsigned int alt(void) const;
00088 bool rightmost(void) const;
00090 bool work(void) const;
00092 void next(void);
00094 unsigned int steal(void);
00095
00097 void dispose(void);
00098 };
00100 Support::DynamicStack<Node,Heap> ds;
00102 unsigned int n_work;
00103 public:
00105 Path(void);
00107 const BranchingDesc* push(Worker& stat, Space* s, Space* c);
00109 bool next(Worker& s);
00111 int lc(void) const;
00113 void unwind(int l);
00115 void commit(Space* s, int i) const;
00117 Space* recompute(unsigned int& d, unsigned int a_d, Worker& s);
00119 Space* recompute(unsigned int& d, unsigned int a_d, Worker& s,
00120 const Space* best, int& mark);
00122 int entries(void) const;
00124 size_t size(void) const;
00126 void reset(void);
00128 bool steal(void) const;
00130 Space* steal(Worker& stat, unsigned long int& d);
00131 };
00132
00133
00134
00135
00136
00137
00138 forceinline
00139 Path::Node::Node(void) {}
00140
00141 forceinline
00142 Path::Node::Node(Space* s, Space* c)
00143 : _space(c), _alt(0), _desc(s->description()) {
00144 _alt_max = _desc->alternatives()-1;
00145 }
00146
00147 forceinline Space*
00148 Path::Node::space(void) const {
00149 return _space;
00150 }
00151 forceinline void
00152 Path::Node::space(Space* s) {
00153 _space = s;
00154 }
00155
00156 forceinline unsigned int
00157 Path::Node::alt(void) const {
00158 return _alt;
00159 }
00160 forceinline bool
00161 Path::Node::rightmost(void) const {
00162 return _alt == _alt_max;
00163 }
00164 forceinline bool
00165 Path::Node::work(void) const {
00166 return _alt != _alt_max;
00167 }
00168 forceinline void
00169 Path::Node::next(void) {
00170 _alt++;
00171 }
00172 forceinline unsigned int
00173 Path::Node::steal(void) {
00174 assert(work());
00175 return _alt_max--;
00176 }
00177
00178 forceinline const BranchingDesc*
00179 Path::Node::desc(void) const {
00180 return _desc;
00181 }
00182
00183 forceinline void
00184 Path::Node::dispose(void) {
00185 delete _space;
00186 delete _desc;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196 forceinline
00197 Path::Path(void) : ds(heap), n_work(0) {}
00198
00199 forceinline const BranchingDesc*
00200 Path::push(Worker& stat, Space* s, Space* c) {
00201 Node sn(s,c);
00202 if (sn.work())
00203 n_work++;
00204 ds.push(sn);
00205 stat.stack_depth(static_cast<unsigned long int>(ds.entries()));
00206 return sn.desc();
00207 }
00208
00209 forceinline bool
00210 Path::next(Worker& stat) {
00211
00212 while (!ds.empty())
00213 if (ds.top().rightmost()) {
00214 stat.pop(ds.top().space(),ds.top().desc());
00215 ds.pop().dispose();
00216 } else {
00217 assert(ds.top().work());
00218 ds.top().next();
00219 if (!ds.top().work())
00220 n_work--;
00221 return true;
00222 }
00223 return false;
00224 }
00225
00226 forceinline void
00227 Path::commit(Space* s, int i) const {
00228 const Node& n = ds[i];
00229 s->commit(*n.desc(),n.alt());
00230 }
00231
00232 forceinline int
00233 Path::lc(void) const {
00234 int l = ds.entries()-1;
00235 while (ds[l].space() == NULL)
00236 l--;
00237 return l;
00238 }
00239
00240 forceinline int
00241 Path::entries(void) const {
00242 return ds.entries();
00243 }
00244
00245 forceinline size_t
00246 Path::size(void) const {
00247 return ds.size();
00248 }
00249
00250 forceinline void
00251 Path::unwind(int l) {
00252 assert((ds[l].space() == NULL) || ds[l].space()->failed());
00253 int n = ds.entries();
00254 for (int i=l; i<n; i++) {
00255 if (ds.top().work())
00256 n_work--;
00257 ds.pop().dispose();
00258 }
00259 assert(ds.entries() == l);
00260 }
00261
00262 forceinline void
00263 Path::reset(void) {
00264 n_work = 0;
00265 while (!ds.empty())
00266 ds.pop().dispose();
00267 }
00268
00269 forceinline bool
00270 Path::steal(void) const {
00271 return n_work > Config::steal_limit;
00272 }
00273
00274 forceinline Space*
00275 Path::steal(Worker& stat, unsigned long int& d) {
00276
00277 int n = ds.entries()-1;
00278 unsigned int w = 0;
00279 while (n >= 0) {
00280 if (ds[n].work())
00281 w++;
00282 if (w > Config::steal_limit) {
00283
00284 int l=n;
00285
00286 while (ds[l].space() == NULL)
00287 l--;
00288 Space* c = ds[l].space()->clone(false);
00289
00290 for (int i=l; i<n; i++)
00291 commit(c,i);
00292 c->commit(*ds[n].desc(),ds[n].steal());
00293 if (!ds[n].work())
00294 n_work--;
00295 d = stat.steal_depth(static_cast<unsigned long int>(n+1));
00296 return c;
00297 }
00298 n--;
00299 }
00300 return NULL;
00301 }
00302
00303 forceinline Space*
00304 Path::recompute(unsigned int& d, unsigned int a_d, Worker& stat) {
00305 assert(!ds.empty());
00306
00307
00308
00309
00310 if ((ds.top().space() != NULL) && ds.top().rightmost()) {
00311 Space* s = ds.top().space();
00312 s->commit(*ds.top().desc(),ds.top().alt());
00313 assert(ds.entries()-1 == lc());
00314 ds.top().space(NULL);
00315 stat.lao(s);
00316 d = 0;
00317 return s;
00318 }
00319
00320 int l = lc();
00321 int n = ds.entries();
00322
00323 d = static_cast<unsigned int>(n - l);
00324
00325 Space* s = ds[l].space()->clone();
00326
00327 if (d < a_d) {
00328
00329 for (int i=l; i<n; i++)
00330 commit(s,i);
00331 } else {
00332 int m = l + static_cast<int>(d >> 1);
00333 int i = l;
00334
00335 for (; i<m; i++ )
00336 commit(s,i);
00337
00338 for (; (i<n) && ds[i].rightmost(); i++)
00339 commit(s,i);
00340
00341 if (i<n-1) {
00342
00343 SpaceStatus ss = s->status(stat);
00344
00345
00346
00347
00348 if (ss == SS_FAILED) {
00349
00350 delete s;
00351 stat.fail++;
00352 unwind(i);
00353 return NULL;
00354 }
00355 ds[i].space(s->clone());
00356 stat.adapt(ds[i].space());
00357 d = static_cast<unsigned int>(n-i);
00358 }
00359
00360 for (; i<n; i++)
00361 commit(s,i);
00362 }
00363 return s;
00364 }
00365
00366 forceinline Space*
00367 Path::recompute(unsigned int& d, unsigned int a_d, Worker& stat,
00368 const Space* best, int& mark) {
00369 assert(!ds.empty());
00370
00371
00372
00373
00374 if ((ds.top().space() != NULL) && ds.top().rightmost()) {
00375 Space* s = ds.top().space();
00376 s->commit(*ds.top().desc(),ds.top().alt());
00377 assert(ds.entries()-1 == lc());
00378 if (mark > ds.entries()-1) {
00379 mark = ds.entries()-1;
00380 s->constrain(*best);
00381 }
00382 ds.top().space(NULL);
00383 stat.lao(s);
00384 d = 0;
00385 return s;
00386 }
00387
00388 int l = lc();
00389 int n = ds.entries();
00390
00391 d = static_cast<unsigned int>(n - l);
00392
00393 Space* s = ds[l].space();
00394
00395 if (l < mark) {
00396 mark = l;
00397 s->constrain(*best);
00398
00399
00400 if (s->status(stat) == SS_FAILED) {
00401
00402 stat.fail++;
00403 unwind(l);
00404 return NULL;
00405 }
00406
00407
00408
00409 Space* c = s->clone();
00410 ds[l].space(c);
00411 stat.constrained(s,c);
00412 } else {
00413 s = s->clone();
00414 }
00415
00416 if (d < a_d) {
00417
00418 for (int i=l; i<n; i++)
00419 commit(s,i);
00420 } else {
00421 int m = l + static_cast<int>(d >> 1);
00422 int i = l;
00423
00424 for (; i<m; i++ )
00425 commit(s,i);
00426
00427 for (; (i<n) && ds[i].rightmost(); i++)
00428 commit(s,i);
00429
00430 if (i<n-1) {
00431
00432 SpaceStatus ss = s->status(stat);
00433
00434
00435
00436
00437
00438
00439
00440 if (ss == SS_FAILED) {
00441
00442 delete s;
00443 stat.fail++;
00444 unwind(i);
00445 return NULL;
00446 }
00447 ds[i].space(s->clone());
00448 stat.adapt(ds[i].space());
00449 d = static_cast<unsigned int>(n-i);
00450 }
00451
00452 for (; i<n; i++)
00453 commit(s,i);
00454 }
00455 return s;
00456 }
00457
00458 }}}
00459
00460 #endif
00461
00462