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