this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * 6 * Contributing authors: 7 * Samuel Gagnon <samuel.gagnon92@gmail.com> 8 * 9 * Copyright: 10 * Christian Schulte, 2002 11 * Samuel Gagnon, 2018 12 * 13 * This file is part of Gecode, the generic constraint 14 * development environment: 15 * http://www.gecode.org 16 * 17 * Permission is hereby granted, free of charge, to any person obtaining 18 * a copy of this software and associated documentation files (the 19 * "Software"), to deal in the Software without restriction, including 20 * without limitation the rights to use, copy, modify, merge, publish, 21 * distribute, sublicense, and/or sell copies of the Software, and to 22 * permit persons to whom the Software is furnished to do so, subject to 23 * the following conditions: 24 * 25 * The above copyright notice and this permission notice shall be 26 * included in all copies or substantial portions of the Software. 27 * 28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35 * 36 */ 37 38#include <gecode/kernel.hh> 39 40namespace Gecode { 41 42 /* 43 * Variable type disposer 44 * 45 */ 46 void 47 VarImpDisposerBase::dispose(Space&,VarImpBase*) {} 48 49 VarImpDisposerBase::~VarImpDisposerBase(void) {} 50 51 52 53 /* 54 * Actor 55 * 56 */ 57 Actor* Actor::sentinel; 58 59 Actor::~Actor(void) {} 60 61 62 /* 63 * Propagator 64 * 65 */ 66 ExecStatus 67 Propagator::advise(Space&, Advisor&, const Delta&) { 68 GECODE_NEVER; 69 return ES_FAILED; 70 } 71 void 72 Propagator::advise(Space&, Advisor&) { 73 GECODE_NEVER; 74 } 75 76 77 /* 78 * No-goods 79 * 80 */ 81 void 82 NoGoods::post(Space&) const { 83 } 84 85 NoGoods NoGoods::eng; 86 87 /* 88 * Brancher 89 * 90 */ 91 NGL* 92 Brancher::ngl(Space&, const Choice&, unsigned int) const { 93 return nullptr; 94 } 95 96 void 97 Brancher::print(const Space&, const Choice&, unsigned int, 98 std::ostream&) const { 99 } 100 101 102 /* 103 * Space: Misc 104 * 105 */ 106 107 StatusStatistics Space::unused_status; 108 CloneStatistics Space::unused_clone; 109 CommitStatistics Space::unused_commit; 110 111#ifdef GECODE_HAS_VAR_DISPOSE 112 VarImpDisposerBase* Space::vd[AllVarConf::idx_d]; 113#endif 114 115 Space::Space(void) : mm(ssd.data().sm) { 116#ifdef GECODE_HAS_CBS 117 var_id_counter = 0; 118#endif 119#ifdef GECODE_HAS_VAR_DISPOSE 120 for (int i=0; i<AllVarConf::idx_d; i++) 121 _vars_d[i] = nullptr; 122#endif 123 // Initialize propagator and brancher links 124 pl.init(); 125 bl.init(); 126 b_status = b_commit = Brancher::cast(&bl); 127 // Initialize array for forced deletion to be empty 128 d_fst = d_cur = d_lst = nullptr; 129 // Initialize space as stable but not failed 130 pc.p.active = &pc.p.queue[0]-1; 131 // Initialize propagator queues 132 for (int i=0; i<=PropCost::AC_MAX; i++) 133 pc.p.queue[i].init(); 134 pc.p.bid_sc = (reserved_bid+1) << sc_bits; 135 pc.p.n_sub = 0; 136 pc.p.vti.other(); 137 } 138 139 void 140 Space::ap_notice_dispose(Actor* a, bool duplicate) { 141 // Note that a might be a marked pointer! 142 if (duplicate && (d_fst != nullptr)) { 143 for (Actor** f = d_fst; f < d_cur; f++) 144 if (a == *f) 145 return; 146 } 147 if (d_cur == d_lst) { 148 // Resize 149 if (d_fst == nullptr) { 150 // Create new array 151 d_fst = alloc<Actor*>(4); 152 d_cur = d_fst; 153 d_lst = d_fst+4; 154 } else { 155 // Resize existing array 156 unsigned int n = static_cast<unsigned int>(d_lst - d_fst); 157 assert(n != 0); 158 d_fst = realloc<Actor*>(d_fst,n,2*n); 159 d_cur = d_fst+n; 160 d_lst = d_fst+2*n; 161 } 162 } 163 *(d_cur++) = a; 164 } 165 166 void 167 Space::ap_ignore_dispose(Actor* a, bool duplicate) { 168 // Note that a might be a marked pointer! 169 assert(d_fst != nullptr); 170 Actor** f = d_fst; 171 if (duplicate) { 172 while (f < d_cur) 173 if (a == *f) 174 break; 175 else 176 f++; 177 if (f == d_cur) 178 return; 179 } else { 180 while (a != *f) 181 f++; 182 } 183 *f = *(--d_cur); 184 } 185 186 Space::~Space(void) { 187 // Mark space as failed 188 fail(); 189 // Delete actors that must be deleted 190 { 191 Actor** a = d_fst; 192 Actor** e = d_cur; 193 // So that d_unforce knows that deletion is in progress 194 d_fst = nullptr; 195 while (a < e) { 196 // Ignore entries for tracers 197 if (!Support::marked(*a)) 198 (void) (*a)->dispose(*this); 199 a++; 200 } 201 } 202#ifdef GECODE_HAS_VAR_DISPOSE 203 // Delete variables that were registered for disposal 204 for (int i=0; i<AllVarConf::idx_d; i++) 205 if (_vars_d[i] != nullptr) 206 vd[i]->dispose(*this, _vars_d[i]); 207#endif 208 // Release memory from memory manager 209 mm.release(ssd.data().sm); 210 } 211 212 213 214 /* 215 * Space: propagation 216 * 217 */ 218 219 TraceRecorder* 220 Space::findtracerecorder(void) { 221 for (Actor** a=d_fst; a<d_cur; a++) { 222 Propagator* p = Propagator::cast(*a); 223 if (!p->disabled()) 224 if (TraceRecorder* tr = dynamic_cast<TraceRecorder*>(p)) { 225 std::swap(*d_fst,*a); 226 return tr; 227 } 228 } 229 return nullptr; 230 } 231 232 void 233 Space::post(const PostInfo& pi) { 234 assert(pc.p.bid_sc & sc_trace); 235 TraceRecorder* tr = findtracerecorder(); 236 if ((tr != nullptr) && (tr->events() & TE_POST)) { 237 GECODE_ASSUME(ssd.data().gpi.pid() >= pi.pid); 238 unsigned int n = ssd.data().gpi.pid() - pi.pid; 239 PostTraceInfo::Status s; 240 if (failed()) 241 s = PostTraceInfo::FAILED; 242 else if (n == 0) 243 s = PostTraceInfo::SUBSUMED; 244 else 245 s = PostTraceInfo::POSTED; 246 PostTraceInfo pti(pi.pg,s,n); 247 tr->tracer()._post(*this,pti); 248 } 249 } 250 251 SpaceStatus 252 Space::status(StatusStatistics& stat) { 253 // Check whether space is failed 254 if (failed()) 255 return SS_FAILED; 256 assert(pc.p.active <= &pc.p.queue[PropCost::AC_MAX+1]); 257 Propagator* p; 258 // Check whether space is stable but not failed 259 if (pc.p.active >= &pc.p.queue[0]) { 260 ModEventDelta med_o; 261 if ((pc.p.bid_sc & ((1 << sc_bits) - 1)) == 0) { 262 // No support for disabled propagators and tracing 263 // Check whether space is stable but not failed 264 goto f_unstable; 265 f_execute: 266 stat.propagate++; 267 // Keep old modification event delta 268 med_o = p->u.med; 269 // Clear med but leave propagator in queue 270 p->u.med = 0; 271 switch (p->propagate(*this,med_o)) { 272 case ES_FAILED: 273 goto failed; 274 case ES_NOFIX: 275 // Find next, if possible 276 if (p->u.med != 0) { 277 f_unstable: 278 // There is at least one propagator in a queue 279 do { 280 assert(pc.p.active >= &pc.p.queue[0]); 281 // First propagator or link back to queue 282 ActorLink* fst = pc.p.active->next(); 283 if (pc.p.active != fst) { 284 p = Propagator::cast(fst); 285 goto f_execute; 286 } 287 pc.p.active--; 288 } while (true); 289 GECODE_NEVER; 290 } 291 // Fall through 292 case ES_FIX: 293 // Clear med 294 p->u.med = 0; 295 // Put into idle queue 296 p->unlink(); pl.head(p); 297 f_stable_or_unstable: 298 // There might be a propagator in the queue 299 do { 300 assert(pc.p.active >= &pc.p.queue[0]); 301 // First propagator or link back to queue 302 ActorLink* fst = pc.p.active->next(); 303 if (pc.p.active != fst) { 304 p = Propagator::cast(fst); 305 goto f_execute; 306 } 307 } while (--pc.p.active >= &pc.p.queue[0]); 308 assert(pc.p.active < &pc.p.queue[0]); 309 goto f_stable; 310 case ES_SUBSUMED_: 311 p->unlink(); rfree(p,p->u.size); 312 goto f_stable_or_unstable; 313 case ES_PARTIAL_: 314 // Schedule propagator with specified propagator events 315 assert(p->u.med != 0); 316 enqueue(p); 317 goto f_unstable; 318 default: 319 GECODE_NEVER; 320 } 321 f_stable: ; 322 } else if ((pc.p.bid_sc & ((1 << sc_bits) - 1)) == sc_disabled) { 323 // Support for disabled propagators 324 goto d_unstable; 325 d_execute: 326 stat.propagate++; 327 if (p->disabled()) 328 goto d_put_into_idle; 329 // Keep old modification event delta 330 med_o = p->u.med; 331 // Clear med but leave propagator in queue 332 p->u.med = 0; 333 switch (p->propagate(*this,med_o)) { 334 case ES_FAILED: 335 goto failed; 336 case ES_NOFIX: 337 // Find next, if possible 338 if (p->u.med != 0) { 339 d_unstable: 340 // There is at least one propagator in a queue 341 do { 342 assert(pc.p.active >= &pc.p.queue[0]); 343 // First propagator or link back to queue 344 ActorLink* fst = pc.p.active->next(); 345 if (pc.p.active != fst) { 346 p = Propagator::cast(fst); 347 goto d_execute; 348 } 349 pc.p.active--; 350 } while (true); 351 GECODE_NEVER; 352 } 353 // Fall through 354 case ES_FIX: 355 d_put_into_idle: 356 // Clear med 357 p->u.med = 0; 358 // Put into idle queue 359 p->unlink(); pl.head(p); 360 d_stable_or_unstable: 361 // There might be a propagator in the queue 362 do { 363 assert(pc.p.active >= &pc.p.queue[0]); 364 // First propagator or link back to queue 365 ActorLink* fst = pc.p.active->next(); 366 if (pc.p.active != fst) { 367 p = Propagator::cast(fst); 368 goto d_execute; 369 } 370 } while (--pc.p.active >= &pc.p.queue[0]); 371 assert(pc.p.active < &pc.p.queue[0]); 372 goto d_stable; 373 case ES_SUBSUMED_: 374 p->unlink(); rfree(p,p->u.size); 375 goto d_stable_or_unstable; 376 case ES_PARTIAL_: 377 // Schedule propagator with specified propagator events 378 assert(p->u.med != 0); 379 enqueue(p); 380 goto d_unstable; 381 default: 382 GECODE_NEVER; 383 } 384 d_stable: ; 385 } else { 386 // Support disabled propagators and tracing 387 388#define GECODE_STATUS_TRACE(q,s) \ 389 if ((tr != nullptr) && (tr->events() & TE_PROPAGATE) && \ 390 (tr->filter()(p->group()))) { \ 391 PropagateTraceInfo pti(p->id(),p->group(),q, \ 392 PropagateTraceInfo::s); \ 393 tr->tracer()._propagate(*this,pti); \ 394 } 395 396 // Find a non-disabled tracer recorder (possibly null) 397 TraceRecorder* tr = findtracerecorder(); 398 // Remember post information 399 ViewTraceInfo vti(pc.p.vti); 400 goto t_unstable; 401 402 t_execute: 403 stat.propagate++; 404 if (p->disabled()) 405 goto t_put_into_idle; 406 pc.p.vti.propagator(*p); 407 // Keep old modification event delta 408 med_o = p->u.med; 409 // Clear med but leave propagator in queue 410 p->u.med = 0; 411 switch (p->propagate(*this,med_o)) { 412 case ES_FAILED: 413 GECODE_STATUS_TRACE(p,FAILED); 414 goto failed; 415 case ES_NOFIX: 416 // Find next, if possible 417 if (p->u.med != 0) { 418 GECODE_STATUS_TRACE(p,NOFIX); 419 t_unstable: 420 // There is at least one propagator in a queue 421 do { 422 assert(pc.p.active >= &pc.p.queue[0]); 423 // First propagator or link back to queue 424 ActorLink* fst = pc.p.active->next(); 425 if (pc.p.active != fst) { 426 p = Propagator::cast(fst); 427 goto t_execute; 428 } 429 pc.p.active--; 430 } while (true); 431 GECODE_NEVER; 432 } 433 // Fall through 434 case ES_FIX: 435 GECODE_STATUS_TRACE(p,FIX); 436 t_put_into_idle: 437 // Clear med 438 p->u.med = 0; 439 // Put into idle queue 440 p->unlink(); pl.head(p); 441 t_stable_or_unstable: 442 // There might be a propagator in the queue 443 do { 444 assert(pc.p.active >= &pc.p.queue[0]); 445 // First propagator or link back to queue 446 ActorLink* fst = pc.p.active->next(); 447 if (pc.p.active != fst) { 448 p = Propagator::cast(fst); 449 goto t_execute; 450 } 451 } while (--pc.p.active >= &pc.p.queue[0]); 452 assert(pc.p.active < &pc.p.queue[0]); 453 goto t_stable; 454 case ES_SUBSUMED_: 455 GECODE_STATUS_TRACE(nullptr,SUBSUMED); 456 p->unlink(); rfree(p,p->u.size); 457 goto t_stable_or_unstable; 458 case ES_PARTIAL_: 459 GECODE_STATUS_TRACE(p,NOFIX); 460 // Schedule propagator with specified propagator events 461 assert(p->u.med != 0); 462 enqueue(p); 463 goto t_unstable; 464 default: 465 GECODE_NEVER; 466 } 467 t_stable: 468 // Restore post information 469 pc.p.vti = vti; 470 471#undef GECODE_STATUS_TRACE 472 473 } 474 } 475 476 /* 477 * Find the next brancher that has still alternatives left 478 * 479 * It is important to note that branchers reporting to have no more 480 * alternatives left cannot be deleted. They cannot be deleted 481 * as there might be choices to be used in commit 482 * that refer to one of these branchers. This e.g. happens when 483 * we combine branch-and-bound search with adaptive recomputation: during 484 * recomputation, a copy is constrained to be better than the currently 485 * best solution, then the first half of the choices are posted, 486 * and a fixpoint computed (for storing in the middle of the path). Then 487 * the remaining choices are posted, and because of the additional 488 * constraints that the space must be better than the previous solution, 489 * the corresponding Branchers may already have no alternatives left. 490 * 491 * The same situation may arise due to weakly monotonic propagators. 492 * 493 * A brancher reporting that no more alternatives exist is exhausted. 494 * All exhausted branchers will be left of the current pointer b_status. 495 * Only when it is known that no more choices 496 * can be used for commit an exhausted brancher can actually be deleted. 497 * This becomes known when choice is called. 498 */ 499 while (b_status != Brancher::cast(&bl)) 500 if (b_status->status(*this)) { 501 // Brancher still has choices to generate 502 return SS_BRANCH; 503 } else { 504 // Brancher is exhausted 505 b_status = Brancher::cast(b_status->next()); 506 } 507 // No brancher with alternatives left, space is solved 508 return SS_SOLVED; 509 510 // Process failure 511 failed: 512 // Count failure 513 ssd.data().gpi.fail(p->gpi()); 514 // Mark as failed 515 fail(); 516 // Propagate top priority propagators 517 ActorLink* e = &pc.p.queue[PropCost::AC_RECORD]; 518 for (ActorLink* a = e->next(); a != e; a = a->next()) { 519 Propagator* top = Propagator::cast(a); 520 // Keep old modification event delta 521 ModEventDelta top_med_o = top->u.med; 522 // Clear med but leave propagator in queue 523 top->u.med = 0; 524 switch (top->propagate(*this,top_med_o)) { 525 case ES_FIX: 526 break; 527 case ES_SUBSUMED_: 528 break; 529 default: 530 GECODE_NEVER; 531 } 532 } 533 return SS_FAILED; 534 } 535 536 537 const Choice* 538 Space::choice(void) { 539 if (!stable()) 540 throw SpaceNotStable("Space::choice"); 541 if (failed() || (b_status == Brancher::cast(&bl))) { 542 // There are no more choices to be generated 543 // Delete all branchers 544 Brancher* b = Brancher::cast(bl.next()); 545 while (b != Brancher::cast(&bl)) { 546 Brancher* d = b; 547 b = Brancher::cast(b->next()); 548 rfree(d,d->dispose(*this)); 549 } 550 bl.init(); 551 b_status = b_commit = Brancher::cast(&bl); 552 return nullptr; 553 } 554 /* 555 * The call to choice() says that no older choices 556 * can be used. Hence, all branchers that are exhausted can be deleted. 557 */ 558 Brancher* b = Brancher::cast(bl.next()); 559 while (b != b_status) { 560 Brancher* d = b; 561 b = Brancher::cast(b->next()); 562 d->unlink(); 563 rfree(d,d->dispose(*this)); 564 } 565 // Make sure that b_commit does not point to a deleted brancher! 566 b_commit = b_status; 567 return b_status->choice(*this); 568 } 569 570 const Choice* 571 Space::choice(Archive& e) const { 572 unsigned int id; e >> id; 573 Brancher* b_cur = Brancher::cast(bl.next()); 574 while (b_cur != Brancher::cast(&bl)) { 575 if (id == b_cur->id()) 576 return b_cur->choice(*this,e); 577 b_cur = Brancher::cast(b_cur->next()); 578 } 579 throw SpaceNoBrancher("Space::choice"); 580 } 581 582 void 583 Space::_commit(const Choice& c, unsigned int a) { 584 if (a >= c.alternatives()) 585 throw SpaceIllegalAlternative("Space::commit"); 586 if (failed()) 587 return; 588 if (Brancher* b = brancher(c.bid)) { 589 // There is a matching brancher 590 if (pc.p.bid_sc & sc_trace) { 591 TraceRecorder* tr = findtracerecorder(); 592 if ((tr != nullptr) && (tr->events() & TE_COMMIT) && 593 tr->filter()(b->group())) { 594 CommitTraceInfo cti(*b,c,a); 595 tr->tracer()._commit(*this,cti); 596 } 597 ViewTraceInfo vti = pc.p.vti; 598 pc.p.vti.brancher(*b); 599 ExecStatus es = b->commit(*this,c,a); 600 pc.p.vti = vti; 601 if (es == ES_FAILED) 602 fail(); 603 } else { 604 if (b->commit(*this,c,a) == ES_FAILED) 605 fail(); 606 } 607 } else { 608 // There is no matching brancher! 609 throw SpaceNoBrancher("Space::commit"); 610 } 611 } 612 613 void 614 Space::_trycommit(const Choice& c, unsigned int a) { 615 if (a >= c.alternatives()) 616 throw SpaceIllegalAlternative("Space::commit"); 617 if (failed()) 618 return; 619 if (Brancher* b = brancher(c.bid)) { 620 // There is a matching brancher 621 if (pc.p.bid_sc & sc_trace) { 622 TraceRecorder* tr = findtracerecorder(); 623 if ((tr != nullptr) && (tr->events() & TE_COMMIT) && 624 tr->filter()(b->group())) { 625 CommitTraceInfo cti(*b,c,a); 626 tr->tracer()._commit(*this,cti); 627 } 628 ViewTraceInfo vti = pc.p.vti; 629 pc.p.vti.brancher(*b); 630 ExecStatus es = b->commit(*this,c,a); 631 pc.p.vti = vti; 632 if (es == ES_FAILED) 633 fail(); 634 } else { 635 if (b->commit(*this,c,a) == ES_FAILED) 636 fail(); 637 } 638 } 639 } 640 641 NGL* 642 Space::ngl(const Choice& c, unsigned int a) { 643 if (a >= c.alternatives()) 644 throw SpaceIllegalAlternative("Space::ngl"); 645 if (failed()) 646 return nullptr; 647 if (Brancher* b = brancher(c.bid)) { 648 // There is a matching brancher 649 return b->ngl(*this,c,a); 650 } else { 651 return nullptr; 652 } 653 } 654 655 void 656 Space::print(const Choice& c, unsigned int a, std::ostream& o) const { 657 if (a >= c.alternatives()) 658 throw SpaceIllegalAlternative("Space::print"); 659 if (failed()) 660 return; 661 if (Brancher* b = const_cast<Space&>(*this).brancher(c.bid)) { 662 // There is a matching brancher 663 b->print(*this,c,a,o); 664 } else { 665 // There is no matching brancher! 666 throw SpaceNoBrancher("Space::print"); 667 } 668 } 669 670 void 671 Space::kill_brancher(unsigned int id) { 672 if (failed()) 673 return; 674 for (Brancher* b = Brancher::cast(bl.next()); 675 b != Brancher::cast(&bl); b = Brancher::cast(b->next())) 676 if (b->id() == id) { 677 kill(*b); 678 return; 679 } 680 } 681 682 683 /* 684 * Space cloning 685 * 686 * Cloning is performed in two steps: 687 * - The space itself is copied by the copy constructor. This 688 * also copies all propagators, branchers, and variables. 689 * The copied variables are recorded. 690 * - In the second step the dependency information of the recorded 691 * variables is updated and their forwarding information is reset. 692 * 693 */ 694 Space::Space(Space& s) 695 : ssd(s.ssd), 696 mm(ssd.data().sm,s.mm,s.pc.p.n_sub*sizeof(Propagator**)), 697#ifdef GECODE_HAS_CBS 698 var_id_counter(s.var_id_counter), 699#endif 700 d_fst(&Actor::sentinel) { 701#ifdef GECODE_HAS_VAR_DISPOSE 702 for (int i=0; i<AllVarConf::idx_d; i++) 703 _vars_d[i] = nullptr; 704#endif 705 for (int i=0; i<AllVarConf::idx_c; i++) 706 pc.c.vars_u[i] = nullptr; 707 pc.c.vars_noidx = nullptr; 708 pc.c.local = nullptr; 709 // Copy all propagators 710 { 711 ActorLink* p = &pl; 712 ActorLink* e = &s.pl; 713 for (ActorLink* a = e->next(); a != e; a = a->next()) { 714 Actor* c = Actor::cast(a)->copy(*this); 715 // Link copied actor 716 p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p); 717 // Note that forwarding is done in the constructors 718 p = c; 719 } 720 // Link last actor 721 p->next(&pl); pl.prev(p); 722 } 723 // Copy all branchers 724 { 725 ActorLink* p = &bl; 726 ActorLink* e = &s.bl; 727 for (ActorLink* a = e->next(); a != e; a = a->next()) { 728 Actor* c = Actor::cast(a)->copy(*this); 729 // Link copied actor 730 p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p); 731 // Note that forwarding is done in the constructors 732 p = c; 733 } 734 // Link last actor 735 p->next(&bl); bl.prev(p); 736 } 737 // Setup brancher pointers 738 if (s.b_status == &s.bl) { 739 b_status = Brancher::cast(&bl); 740 } else { 741 b_status = Brancher::cast(s.b_status->prev()); 742 } 743 if (s.b_commit == &s.bl) { 744 b_commit = Brancher::cast(&bl); 745 } else { 746 b_commit = Brancher::cast(s.b_commit->prev()); 747 } 748 } 749 750 Space* 751 Space::_clone(void) { 752 if (failed()) 753 throw SpaceFailed("Space::clone"); 754 if (!stable()) 755 throw SpaceNotStable("Space::clone"); 756 757 // Copy all data structures (which in turn will invoke the constructor) 758 Space* c = copy(); 759 760 if (c->d_fst != &Actor::sentinel) 761 throw SpaceNotCloned("Space::clone"); 762 763 // Setup array for actor disposal in c 764 { 765 unsigned int n = static_cast<unsigned int>(d_cur - d_fst); 766 if (n == 0) { 767 // No actors 768 c->d_fst = c->d_cur = c->d_lst = nullptr; 769 } else { 770 // Leave one entry free 771 c->d_fst = c->alloc<Actor*>(n+1); 772 c->d_cur = c->d_fst; 773 c->d_lst = c->d_fst+n+1; 774 for (Actor** d_fst_iter = d_fst; d_fst_iter != d_cur; d_fst_iter++) { 775 ptrdiff_t m; 776 Actor* a = static_cast<Actor*>(Support::ptrsplit(*d_fst_iter,m)); 777 if (a->prev()) 778 *(c->d_cur++) = Actor::cast(static_cast<ActorLink*> 779 (Support::ptrjoin(a->prev(),m))); 780 } 781 } 782 } 783 784 // Update variables without indexing structure 785 VarImp<NoIdxVarImpConf>* x = 786 static_cast<VarImp<NoIdxVarImpConf>*>(c->pc.c.vars_noidx); 787 while (x != nullptr) { 788 VarImp<NoIdxVarImpConf>* n = x->next(); 789 x->b.base = nullptr; x->u.idx[0] = 0; 790 if (sizeof(ActorLink**) > sizeof(unsigned int)) 791 *(1+&x->u.idx[0]) = 0; 792 x = n; 793 } 794 // Update variables with indexing structure 795 c->update(static_cast<ActorLink**>(c->mm.subscriptions())); 796 797 // Re-establish prev links (reset forwarding information) 798 { 799 ActorLink* p_a = &pl; 800 ActorLink* c_a = p_a->next(); 801 // First update propagators and advisors 802 while (c_a != &pl) { 803 Propagator* p = Propagator::cast(c_a); 804 if (p->u.advisors != nullptr) { 805 ActorLink* a = p->u.advisors; 806 p->u.advisors = nullptr; 807 do { 808 a->prev(p); a = a->next(); 809 } while (a != nullptr); 810 } 811 c_a->prev(p_a); p_a = c_a; c_a = c_a->next(); 812 } 813 } 814 { 815 ActorLink* p_a = &bl; 816 ActorLink* c_a = p_a->next(); 817 // Update branchers 818 while (c_a != &bl) { 819 c_a->prev(p_a); p_a = c_a; c_a = c_a->next(); 820 } 821 } 822 823 // Reset links for local objects 824 for (ActorLink* l = c->pc.c.local; l != nullptr; l = l->next()) 825 l->prev(nullptr); 826 827 // Initialize propagator queue 828 c->pc.p.active = &c->pc.p.queue[0]-1; 829 for (int i=0; i<=PropCost::AC_MAX; i++) 830 c->pc.p.queue[i].init(); 831 // Copy propagation only data 832 c->pc.p.n_sub = pc.p.n_sub; 833 c->pc.p.bid_sc = pc.p.bid_sc; 834 835 // Reset execution information 836 c->pc.p.vti.other(); pc.p.vti.other(); 837 838 return c; 839 } 840 841 void 842 Space::constrain(const Space&) { 843 } 844 845 bool 846 Space::master(const MetaInfo& mi) { 847 switch (mi.type()) { 848 case MetaInfo::RESTART: 849 if (mi.last() != nullptr) 850 constrain(*mi.last()); 851 mi.nogoods().post(*this); 852 // Perform a restart even if a solution has been found 853 return true; 854 case MetaInfo::PORTFOLIO: 855 // Kill all branchers 856 BrancherGroup::all.kill(*this); 857 return true; 858 default: GECODE_NEVER; 859 return true; 860 } 861 } 862 863 bool 864 Space::slave(const MetaInfo&) { 865 return true; 866 } 867 868 869 void 870 Space::afc_unshare(void) { 871 if (ssd.data().gpi.unshare()) { 872 for (Propagators ps(*this); ps(); ++ps) { 873 Propagator& p = ps.propagator(); 874 Kernel::GPI::Info* gpi 875 = ssd.data().gpi.allocate(p.gpi().pid,p.gpi().gid); 876 if (p.disabled()) 877 p.gpi_disabled = Support::mark(gpi); 878 else 879 p.gpi_disabled = gpi; 880 } 881 } 882 } 883 884 void 885 LocalObject::fwdcopy(Space& home) { 886 ActorLink::cast(this)->prev(copy(home)); 887 next(home.pc.c.local); 888 home.pc.c.local = this; 889 } 890 891 void 892 Choice::archive(Archive& e) const { 893 e << id(); 894 } 895 896 bool 897 NGL::notice(void) const { 898 return false; 899 } 900 901 NGL::~NGL(void) { 902 } 903 904 905 /* 906 * Groups 907 */ 908 909 Group Group::all(GROUPID_ALL); 910 Group Group::def(GROUPID_DEF); 911 912 PropagatorGroup PropagatorGroup::all(GROUPID_ALL); 913 PropagatorGroup PropagatorGroup::def(GROUPID_DEF); 914 915 BrancherGroup BrancherGroup::all(GROUPID_ALL); 916 BrancherGroup BrancherGroup::def(GROUPID_DEF); 917 918 unsigned int Group::next = GROUPID_DEF+1; 919 Support::Mutex Group::m; 920 921 922 Group::Group(void) { 923 { 924 Support::Lock l(m); 925 gid = next++; 926 } 927 if (gid == GROUPID_MAX) 928 throw TooManyGroups("Group::Group"); 929 } 930 931 932 PropagatorGroup& 933 PropagatorGroup::move(Space& home, PropagatorGroup g) { 934 if ((id() != GROUPID_ALL) && (id() != g.id())) 935 for (Space::Propagators ps(home); ps(); ++ps) 936 if (g.in(ps.propagator().group())) 937 ps.propagator().group(*this); 938 return *this; 939 } 940 941 PropagatorGroup& 942 PropagatorGroup::move(Space& home, unsigned int pid) { 943 if (id() == GROUPID_ALL) 944 return *this; 945 for (Space::Propagators ps(home); ps(); ++ps) 946 if (ps.propagator().id() == pid) { 947 ps.propagator().group(*this); 948 return *this; 949 } 950 throw UnknownPropagator("PropagatorGroup::move"); 951 GECODE_NEVER; 952 return *this; 953 } 954 955 unsigned int 956 PropagatorGroup::size(Space& home) const { 957 if (home.failed()) 958 return 0; 959 unsigned int n=0; 960 for (Space::Propagators ps(home); ps(); ++ps) 961 if (in(ps.propagator().group())) 962 n++; 963 return n; 964 } 965 966 void 967 PropagatorGroup::kill(Space& home) { 968 if (home.failed()) 969 return; 970 Space::Propagators ps(home); 971 while (ps()) { 972 Propagator& p = ps.propagator(); 973 ++ps; 974 if (in(p.group())) 975 home.kill(p); 976 } 977 } 978 979 void 980 PropagatorGroup::disable(Space& home) { 981 if (home.failed()) 982 return; 983 for (Space::Propagators ps(home); ps(); ++ps) 984 if (in(ps.propagator().group())) 985 ps.propagator().disable(home); 986 } 987 988 void 989 PropagatorGroup::enable(Space& home, bool s) { 990 if (home.failed()) 991 return; 992 if (s) { 993 Space::Propagators ps(home); 994 while (ps()) { 995 Propagator& p = ps.propagator(); 996 ++ps; 997 if (in(p.group())) { 998 p.enable(home); 999 p.reschedule(home); 1000 } 1001 } 1002 } else { 1003 for (Space::Propagators ps(home); ps(); ++ps) 1004 if (in(ps.propagator().group())) 1005 ps.propagator().enable(home); 1006 } 1007 } 1008 1009 1010 BrancherGroup& 1011 BrancherGroup::move(Space& home, BrancherGroup g) { 1012 if ((id() != GROUPID_ALL) && (id() != g.id())) 1013 for (Space::Branchers bs(home); bs(); ++bs) 1014 if (g.in(bs.brancher().group())) 1015 bs.brancher().group(*this); 1016 return *this; 1017 } 1018 1019 BrancherGroup& 1020 BrancherGroup::move(Space& home, unsigned int bid) { 1021 if (id() == GROUPID_ALL) 1022 return *this; 1023 for (Space::Branchers bs(home); bs(); ++bs) 1024 if (bs.brancher().id() == bid) { 1025 bs.brancher().group(*this); 1026 return *this; 1027 } 1028 throw UnknownBrancher("BrancherGroup::move"); 1029 GECODE_NEVER; 1030 return *this; 1031 } 1032 1033 unsigned int 1034 BrancherGroup::size(Space& home) const { 1035 if (home.failed()) 1036 return 0; 1037 unsigned int n=0; 1038 for (Space::Branchers bs(home); bs(); ++bs) 1039 if (in(bs.brancher().group())) 1040 n++; 1041 return n; 1042 } 1043 1044 void 1045 BrancherGroup::kill(Space& home) { 1046 if (home.failed()) 1047 return; 1048 Space::Branchers bs(home); 1049 while (bs()) { 1050 Brancher& b = bs.brancher(); 1051 ++bs; 1052 if (in(b.group())) 1053 home.kill(b); 1054 } 1055 } 1056 1057 1058} 1059 1060// STATISTICS: kernel-core