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