Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
29 kB · 1060 lines
C++
at develop
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- *//* * Main authors: * Christian Schulte <schulte@gecode.org> * * Contributing authors: * Samuel Gagnon <samuel.gagnon92@gmail.com> * * Copyright: * Christian Schulte, 2002 * Samuel Gagnon, 2018 * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */
#include <gecode/kernel.hh>
namespace Gecode {
/* * Variable type disposer * */ void VarImpDisposerBase::dispose(Space&,VarImpBase*) {}
VarImpDisposerBase::~VarImpDisposerBase(void) {}
/* * Actor * */ Actor* Actor::sentinel;
Actor::~Actor(void) {}
/* * Propagator * */ ExecStatus Propagator::advise(Space&, Advisor&, const Delta&) { GECODE_NEVER; return ES_FAILED; } void Propagator::advise(Space&, Advisor&) { GECODE_NEVER; }
/* * No-goods * */ void NoGoods::post(Space&) const { }
NoGoods NoGoods::eng;
/* * Brancher * */ NGL* Brancher::ngl(Space&, const Choice&, unsigned int) const { return nullptr; }
void Brancher::print(const Space&, const Choice&, unsigned int, std::ostream&) const { }
/* * Space: Misc * */
StatusStatistics Space::unused_status; CloneStatistics Space::unused_clone; CommitStatistics Space::unused_commit;
#ifdef GECODE_HAS_VAR_DISPOSE VarImpDisposerBase* Space::vd[AllVarConf::idx_d];#endif
Space::Space(void) : mm(ssd.data().sm) {#ifdef GECODE_HAS_CBS var_id_counter = 0;#endif#ifdef GECODE_HAS_VAR_DISPOSE for (int i=0; i<AllVarConf::idx_d; i++) _vars_d[i] = nullptr;#endif // Initialize propagator and brancher links pl.init(); bl.init(); b_status = b_commit = Brancher::cast(&bl); // Initialize array for forced deletion to be empty d_fst = d_cur = d_lst = nullptr; // Initialize space as stable but not failed pc.p.active = &pc.p.queue[0]-1; // Initialize propagator queues for (int i=0; i<=PropCost::AC_MAX; i++) pc.p.queue[i].init(); pc.p.bid_sc = (reserved_bid+1) << sc_bits; pc.p.n_sub = 0; pc.p.vti.other(); }
void Space::ap_notice_dispose(Actor* a, bool duplicate) { // Note that a might be a marked pointer! if (duplicate && (d_fst != nullptr)) { for (Actor** f = d_fst; f < d_cur; f++) if (a == *f) return; } if (d_cur == d_lst) { // Resize if (d_fst == nullptr) { // Create new array d_fst = alloc<Actor*>(4); d_cur = d_fst; d_lst = d_fst+4; } else { // Resize existing array unsigned int n = static_cast<unsigned int>(d_lst - d_fst); assert(n != 0); d_fst = realloc<Actor*>(d_fst,n,2*n); d_cur = d_fst+n; d_lst = d_fst+2*n; } } *(d_cur++) = a; }
void Space::ap_ignore_dispose(Actor* a, bool duplicate) { // Note that a might be a marked pointer! assert(d_fst != nullptr); Actor** f = d_fst; if (duplicate) { while (f < d_cur) if (a == *f) break; else f++; if (f == d_cur) return; } else { while (a != *f) f++; } *f = *(--d_cur); }
Space::~Space(void) { // Mark space as failed fail(); // Delete actors that must be deleted { Actor** a = d_fst; Actor** e = d_cur; // So that d_unforce knows that deletion is in progress d_fst = nullptr; while (a < e) { // Ignore entries for tracers if (!Support::marked(*a)) (void) (*a)->dispose(*this); a++; } }#ifdef GECODE_HAS_VAR_DISPOSE // Delete variables that were registered for disposal for (int i=0; i<AllVarConf::idx_d; i++) if (_vars_d[i] != nullptr) vd[i]->dispose(*this, _vars_d[i]);#endif // Release memory from memory manager mm.release(ssd.data().sm); }
/* * Space: propagation * */
TraceRecorder* Space::findtracerecorder(void) { for (Actor** a=d_fst; a<d_cur; a++) { Propagator* p = Propagator::cast(*a); if (!p->disabled()) if (TraceRecorder* tr = dynamic_cast<TraceRecorder*>(p)) { std::swap(*d_fst,*a); return tr; } } return nullptr; }
void Space::post(const PostInfo& pi) { assert(pc.p.bid_sc & sc_trace); TraceRecorder* tr = findtracerecorder(); if ((tr != nullptr) && (tr->events() & TE_POST)) { GECODE_ASSUME(ssd.data().gpi.pid() >= pi.pid); unsigned int n = ssd.data().gpi.pid() - pi.pid; PostTraceInfo::Status s; if (failed()) s = PostTraceInfo::FAILED; else if (n == 0) s = PostTraceInfo::SUBSUMED; else s = PostTraceInfo::POSTED; PostTraceInfo pti(pi.pg,s,n); tr->tracer()._post(*this,pti); } }
SpaceStatus Space::status(StatusStatistics& stat) { // Check whether space is failed if (failed()) return SS_FAILED; assert(pc.p.active <= &pc.p.queue[PropCost::AC_MAX+1]); Propagator* p; // Check whether space is stable but not failed if (pc.p.active >= &pc.p.queue[0]) { ModEventDelta med_o; if ((pc.p.bid_sc & ((1 << sc_bits) - 1)) == 0) { // No support for disabled propagators and tracing // Check whether space is stable but not failed goto f_unstable; f_execute: stat.propagate++; // Keep old modification event delta med_o = p->u.med; // Clear med but leave propagator in queue p->u.med = 0; switch (p->propagate(*this,med_o)) { case ES_FAILED: goto failed; case ES_NOFIX: // Find next, if possible if (p->u.med != 0) { f_unstable: // There is at least one propagator in a queue do { assert(pc.p.active >= &pc.p.queue[0]); // First propagator or link back to queue ActorLink* fst = pc.p.active->next(); if (pc.p.active != fst) { p = Propagator::cast(fst); goto f_execute; } pc.p.active--; } while (true); GECODE_NEVER; } // Fall through case ES_FIX: // Clear med p->u.med = 0; // Put into idle queue p->unlink(); pl.head(p); f_stable_or_unstable: // There might be a propagator in the queue do { assert(pc.p.active >= &pc.p.queue[0]); // First propagator or link back to queue ActorLink* fst = pc.p.active->next(); if (pc.p.active != fst) { p = Propagator::cast(fst); goto f_execute; } } while (--pc.p.active >= &pc.p.queue[0]); assert(pc.p.active < &pc.p.queue[0]); goto f_stable; case ES_SUBSUMED_: p->unlink(); rfree(p,p->u.size); goto f_stable_or_unstable; case ES_PARTIAL_: // Schedule propagator with specified propagator events assert(p->u.med != 0); enqueue(p); goto f_unstable; default: GECODE_NEVER; } f_stable: ; } else if ((pc.p.bid_sc & ((1 << sc_bits) - 1)) == sc_disabled) { // Support for disabled propagators goto d_unstable; d_execute: stat.propagate++; if (p->disabled()) goto d_put_into_idle; // Keep old modification event delta med_o = p->u.med; // Clear med but leave propagator in queue p->u.med = 0; switch (p->propagate(*this,med_o)) { case ES_FAILED: goto failed; case ES_NOFIX: // Find next, if possible if (p->u.med != 0) { d_unstable: // There is at least one propagator in a queue do { assert(pc.p.active >= &pc.p.queue[0]); // First propagator or link back to queue ActorLink* fst = pc.p.active->next(); if (pc.p.active != fst) { p = Propagator::cast(fst); goto d_execute; } pc.p.active--; } while (true); GECODE_NEVER; } // Fall through case ES_FIX: d_put_into_idle: // Clear med p->u.med = 0; // Put into idle queue p->unlink(); pl.head(p); d_stable_or_unstable: // There might be a propagator in the queue do { assert(pc.p.active >= &pc.p.queue[0]); // First propagator or link back to queue ActorLink* fst = pc.p.active->next(); if (pc.p.active != fst) { p = Propagator::cast(fst); goto d_execute; } } while (--pc.p.active >= &pc.p.queue[0]); assert(pc.p.active < &pc.p.queue[0]); goto d_stable; case ES_SUBSUMED_: p->unlink(); rfree(p,p->u.size); goto d_stable_or_unstable; case ES_PARTIAL_: // Schedule propagator with specified propagator events assert(p->u.med != 0); enqueue(p); goto d_unstable; default: GECODE_NEVER; } d_stable: ; } else { // Support disabled propagators and tracing
#define GECODE_STATUS_TRACE(q,s) \ if ((tr != nullptr) && (tr->events() & TE_PROPAGATE) && \ (tr->filter()(p->group()))) { \ PropagateTraceInfo pti(p->id(),p->group(),q, \ PropagateTraceInfo::s); \ tr->tracer()._propagate(*this,pti); \ }
// Find a non-disabled tracer recorder (possibly null) TraceRecorder* tr = findtracerecorder(); // Remember post information ViewTraceInfo vti(pc.p.vti); goto t_unstable;
t_execute: stat.propagate++; if (p->disabled()) goto t_put_into_idle; pc.p.vti.propagator(*p); // Keep old modification event delta med_o = p->u.med; // Clear med but leave propagator in queue p->u.med = 0; switch (p->propagate(*this,med_o)) { case ES_FAILED: GECODE_STATUS_TRACE(p,FAILED); goto failed; case ES_NOFIX: // Find next, if possible if (p->u.med != 0) { GECODE_STATUS_TRACE(p,NOFIX); t_unstable: // There is at least one propagator in a queue do { assert(pc.p.active >= &pc.p.queue[0]); // First propagator or link back to queue ActorLink* fst = pc.p.active->next(); if (pc.p.active != fst) { p = Propagator::cast(fst); goto t_execute; } pc.p.active--; } while (true); GECODE_NEVER; } // Fall through case ES_FIX: GECODE_STATUS_TRACE(p,FIX); t_put_into_idle: // Clear med p->u.med = 0; // Put into idle queue p->unlink(); pl.head(p); t_stable_or_unstable: // There might be a propagator in the queue do { assert(pc.p.active >= &pc.p.queue[0]); // First propagator or link back to queue ActorLink* fst = pc.p.active->next(); if (pc.p.active != fst) { p = Propagator::cast(fst); goto t_execute; } } while (--pc.p.active >= &pc.p.queue[0]); assert(pc.p.active < &pc.p.queue[0]); goto t_stable; case ES_SUBSUMED_: GECODE_STATUS_TRACE(nullptr,SUBSUMED); p->unlink(); rfree(p,p->u.size); goto t_stable_or_unstable; case ES_PARTIAL_: GECODE_STATUS_TRACE(p,NOFIX); // Schedule propagator with specified propagator events assert(p->u.med != 0); enqueue(p); goto t_unstable; default: GECODE_NEVER; } t_stable: // Restore post information pc.p.vti = vti;
#undef GECODE_STATUS_TRACE
} }
/* * Find the next brancher that has still alternatives left * * It is important to note that branchers reporting to have no more * alternatives left cannot be deleted. They cannot be deleted * as there might be choices to be used in commit * that refer to one of these branchers. This e.g. happens when * we combine branch-and-bound search with adaptive recomputation: during * recomputation, a copy is constrained to be better than the currently * best solution, then the first half of the choices are posted, * and a fixpoint computed (for storing in the middle of the path). Then * the remaining choices are posted, and because of the additional * constraints that the space must be better than the previous solution, * the corresponding Branchers may already have no alternatives left. * * The same situation may arise due to weakly monotonic propagators. * * A brancher reporting that no more alternatives exist is exhausted. * All exhausted branchers will be left of the current pointer b_status. * Only when it is known that no more choices * can be used for commit an exhausted brancher can actually be deleted. * This becomes known when choice is called. */ while (b_status != Brancher::cast(&bl)) if (b_status->status(*this)) { // Brancher still has choices to generate return SS_BRANCH; } else { // Brancher is exhausted b_status = Brancher::cast(b_status->next()); } // No brancher with alternatives left, space is solved return SS_SOLVED;
// Process failure failed: // Count failure ssd.data().gpi.fail(p->gpi()); // Mark as failed fail(); // Propagate top priority propagators ActorLink* e = &pc.p.queue[PropCost::AC_RECORD]; for (ActorLink* a = e->next(); a != e; a = a->next()) { Propagator* top = Propagator::cast(a); // Keep old modification event delta ModEventDelta top_med_o = top->u.med; // Clear med but leave propagator in queue top->u.med = 0; switch (top->propagate(*this,top_med_o)) { case ES_FIX: break; case ES_SUBSUMED_: break; default: GECODE_NEVER; } } return SS_FAILED; }
const Choice* Space::choice(void) { if (!stable()) throw SpaceNotStable("Space::choice"); if (failed() || (b_status == Brancher::cast(&bl))) { // There are no more choices to be generated // Delete all branchers Brancher* b = Brancher::cast(bl.next()); while (b != Brancher::cast(&bl)) { Brancher* d = b; b = Brancher::cast(b->next()); rfree(d,d->dispose(*this)); } bl.init(); b_status = b_commit = Brancher::cast(&bl); return nullptr; } /* * The call to choice() says that no older choices * can be used. Hence, all branchers that are exhausted can be deleted. */ Brancher* b = Brancher::cast(bl.next()); while (b != b_status) { Brancher* d = b; b = Brancher::cast(b->next()); d->unlink(); rfree(d,d->dispose(*this)); } // Make sure that b_commit does not point to a deleted brancher! b_commit = b_status; return b_status->choice(*this); }
const Choice* Space::choice(Archive& e) const { unsigned int id; e >> id; Brancher* b_cur = Brancher::cast(bl.next()); while (b_cur != Brancher::cast(&bl)) { if (id == b_cur->id()) return b_cur->choice(*this,e); b_cur = Brancher::cast(b_cur->next()); } throw SpaceNoBrancher("Space::choice"); }
void Space::_commit(const Choice& c, unsigned int a) { if (a >= c.alternatives()) throw SpaceIllegalAlternative("Space::commit"); if (failed()) return; if (Brancher* b = brancher(c.bid)) { // There is a matching brancher if (pc.p.bid_sc & sc_trace) { TraceRecorder* tr = findtracerecorder(); if ((tr != nullptr) && (tr->events() & TE_COMMIT) && tr->filter()(b->group())) { CommitTraceInfo cti(*b,c,a); tr->tracer()._commit(*this,cti); } ViewTraceInfo vti = pc.p.vti; pc.p.vti.brancher(*b); ExecStatus es = b->commit(*this,c,a); pc.p.vti = vti; if (es == ES_FAILED) fail(); } else { if (b->commit(*this,c,a) == ES_FAILED) fail(); } } else { // There is no matching brancher! throw SpaceNoBrancher("Space::commit"); } }
void Space::_trycommit(const Choice& c, unsigned int a) { if (a >= c.alternatives()) throw SpaceIllegalAlternative("Space::commit"); if (failed()) return; if (Brancher* b = brancher(c.bid)) { // There is a matching brancher if (pc.p.bid_sc & sc_trace) { TraceRecorder* tr = findtracerecorder(); if ((tr != nullptr) && (tr->events() & TE_COMMIT) && tr->filter()(b->group())) { CommitTraceInfo cti(*b,c,a); tr->tracer()._commit(*this,cti); } ViewTraceInfo vti = pc.p.vti; pc.p.vti.brancher(*b); ExecStatus es = b->commit(*this,c,a); pc.p.vti = vti; if (es == ES_FAILED) fail(); } else { if (b->commit(*this,c,a) == ES_FAILED) fail(); } } }
NGL* Space::ngl(const Choice& c, unsigned int a) { if (a >= c.alternatives()) throw SpaceIllegalAlternative("Space::ngl"); if (failed()) return nullptr; if (Brancher* b = brancher(c.bid)) { // There is a matching brancher return b->ngl(*this,c,a); } else { return nullptr; } }
void Space::print(const Choice& c, unsigned int a, std::ostream& o) const { if (a >= c.alternatives()) throw SpaceIllegalAlternative("Space::print"); if (failed()) return; if (Brancher* b = const_cast<Space&>(*this).brancher(c.bid)) { // There is a matching brancher b->print(*this,c,a,o); } else { // There is no matching brancher! throw SpaceNoBrancher("Space::print"); } }
void Space::kill_brancher(unsigned int id) { if (failed()) return; for (Brancher* b = Brancher::cast(bl.next()); b != Brancher::cast(&bl); b = Brancher::cast(b->next())) if (b->id() == id) { kill(*b); return; } }
/* * Space cloning * * Cloning is performed in two steps: * - The space itself is copied by the copy constructor. This * also copies all propagators, branchers, and variables. * The copied variables are recorded. * - In the second step the dependency information of the recorded * variables is updated and their forwarding information is reset. * */ Space::Space(Space& s) : ssd(s.ssd), mm(ssd.data().sm,s.mm,s.pc.p.n_sub*sizeof(Propagator**)),#ifdef GECODE_HAS_CBS var_id_counter(s.var_id_counter),#endif d_fst(&Actor::sentinel) {#ifdef GECODE_HAS_VAR_DISPOSE for (int i=0; i<AllVarConf::idx_d; i++) _vars_d[i] = nullptr;#endif for (int i=0; i<AllVarConf::idx_c; i++) pc.c.vars_u[i] = nullptr; pc.c.vars_noidx = nullptr; pc.c.local = nullptr; // Copy all propagators { ActorLink* p = &pl; ActorLink* e = &s.pl; for (ActorLink* a = e->next(); a != e; a = a->next()) { Actor* c = Actor::cast(a)->copy(*this); // Link copied actor p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p); // Note that forwarding is done in the constructors p = c; } // Link last actor p->next(&pl); pl.prev(p); } // Copy all branchers { ActorLink* p = &bl; ActorLink* e = &s.bl; for (ActorLink* a = e->next(); a != e; a = a->next()) { Actor* c = Actor::cast(a)->copy(*this); // Link copied actor p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p); // Note that forwarding is done in the constructors p = c; } // Link last actor p->next(&bl); bl.prev(p); } // Setup brancher pointers if (s.b_status == &s.bl) { b_status = Brancher::cast(&bl); } else { b_status = Brancher::cast(s.b_status->prev()); } if (s.b_commit == &s.bl) { b_commit = Brancher::cast(&bl); } else { b_commit = Brancher::cast(s.b_commit->prev()); } }
Space* Space::_clone(void) { if (failed()) throw SpaceFailed("Space::clone"); if (!stable()) throw SpaceNotStable("Space::clone");
// Copy all data structures (which in turn will invoke the constructor) Space* c = copy();
if (c->d_fst != &Actor::sentinel) throw SpaceNotCloned("Space::clone");
// Setup array for actor disposal in c { unsigned int n = static_cast<unsigned int>(d_cur - d_fst); if (n == 0) { // No actors c->d_fst = c->d_cur = c->d_lst = nullptr; } else { // Leave one entry free c->d_fst = c->alloc<Actor*>(n+1); c->d_cur = c->d_fst; c->d_lst = c->d_fst+n+1; for (Actor** d_fst_iter = d_fst; d_fst_iter != d_cur; d_fst_iter++) { ptrdiff_t m; Actor* a = static_cast<Actor*>(Support::ptrsplit(*d_fst_iter,m)); if (a->prev()) *(c->d_cur++) = Actor::cast(static_cast<ActorLink*> (Support::ptrjoin(a->prev(),m))); } } }
// Update variables without indexing structure VarImp<NoIdxVarImpConf>* x = static_cast<VarImp<NoIdxVarImpConf>*>(c->pc.c.vars_noidx); while (x != nullptr) { VarImp<NoIdxVarImpConf>* n = x->next(); x->b.base = nullptr; x->u.idx[0] = 0; if (sizeof(ActorLink**) > sizeof(unsigned int)) *(1+&x->u.idx[0]) = 0; x = n; } // Update variables with indexing structure c->update(static_cast<ActorLink**>(c->mm.subscriptions()));
// Re-establish prev links (reset forwarding information) { ActorLink* p_a = &pl; ActorLink* c_a = p_a->next(); // First update propagators and advisors while (c_a != &pl) { Propagator* p = Propagator::cast(c_a); if (p->u.advisors != nullptr) { ActorLink* a = p->u.advisors; p->u.advisors = nullptr; do { a->prev(p); a = a->next(); } while (a != nullptr); } c_a->prev(p_a); p_a = c_a; c_a = c_a->next(); } } { ActorLink* p_a = &bl; ActorLink* c_a = p_a->next(); // Update branchers while (c_a != &bl) { c_a->prev(p_a); p_a = c_a; c_a = c_a->next(); } }
// Reset links for local objects for (ActorLink* l = c->pc.c.local; l != nullptr; l = l->next()) l->prev(nullptr);
// Initialize propagator queue c->pc.p.active = &c->pc.p.queue[0]-1; for (int i=0; i<=PropCost::AC_MAX; i++) c->pc.p.queue[i].init(); // Copy propagation only data c->pc.p.n_sub = pc.p.n_sub; c->pc.p.bid_sc = pc.p.bid_sc;
// Reset execution information c->pc.p.vti.other(); pc.p.vti.other();
return c; }
void Space::constrain(const Space&) { }
bool Space::master(const MetaInfo& mi) { switch (mi.type()) { case MetaInfo::RESTART: if (mi.last() != nullptr) constrain(*mi.last()); mi.nogoods().post(*this); // Perform a restart even if a solution has been found return true; case MetaInfo::PORTFOLIO: // Kill all branchers BrancherGroup::all.kill(*this); return true; default: GECODE_NEVER; return true; } }
bool Space::slave(const MetaInfo&) { return true; }
void Space::afc_unshare(void) { if (ssd.data().gpi.unshare()) { for (Propagators ps(*this); ps(); ++ps) { Propagator& p = ps.propagator(); Kernel::GPI::Info* gpi = ssd.data().gpi.allocate(p.gpi().pid,p.gpi().gid); if (p.disabled()) p.gpi_disabled = Support::mark(gpi); else p.gpi_disabled = gpi; } } }
void LocalObject::fwdcopy(Space& home) { ActorLink::cast(this)->prev(copy(home)); next(home.pc.c.local); home.pc.c.local = this; }
void Choice::archive(Archive& e) const { e << id(); }
bool NGL::notice(void) const { return false; }
NGL::~NGL(void) { }
/* * Groups */
Group Group::all(GROUPID_ALL); Group Group::def(GROUPID_DEF);
PropagatorGroup PropagatorGroup::all(GROUPID_ALL); PropagatorGroup PropagatorGroup::def(GROUPID_DEF);
BrancherGroup BrancherGroup::all(GROUPID_ALL); BrancherGroup BrancherGroup::def(GROUPID_DEF);
unsigned int Group::next = GROUPID_DEF+1; Support::Mutex Group::m;
Group::Group(void) { { Support::Lock l(m); gid = next++; } if (gid == GROUPID_MAX) throw TooManyGroups("Group::Group"); }
PropagatorGroup& PropagatorGroup::move(Space& home, PropagatorGroup g) { if ((id() != GROUPID_ALL) && (id() != g.id())) for (Space::Propagators ps(home); ps(); ++ps) if (g.in(ps.propagator().group())) ps.propagator().group(*this); return *this; }
PropagatorGroup& PropagatorGroup::move(Space& home, unsigned int pid) { if (id() == GROUPID_ALL) return *this; for (Space::Propagators ps(home); ps(); ++ps) if (ps.propagator().id() == pid) { ps.propagator().group(*this); return *this; } throw UnknownPropagator("PropagatorGroup::move"); GECODE_NEVER; return *this; }
unsigned int PropagatorGroup::size(Space& home) const { if (home.failed()) return 0; unsigned int n=0; for (Space::Propagators ps(home); ps(); ++ps) if (in(ps.propagator().group())) n++; return n; }
void PropagatorGroup::kill(Space& home) { if (home.failed()) return; Space::Propagators ps(home); while (ps()) { Propagator& p = ps.propagator(); ++ps; if (in(p.group())) home.kill(p); } }
void PropagatorGroup::disable(Space& home) { if (home.failed()) return; for (Space::Propagators ps(home); ps(); ++ps) if (in(ps.propagator().group())) ps.propagator().disable(home); }
void PropagatorGroup::enable(Space& home, bool s) { if (home.failed()) return; if (s) { Space::Propagators ps(home); while (ps()) { Propagator& p = ps.propagator(); ++ps; if (in(p.group())) { p.enable(home); p.reschedule(home); } } } else { for (Space::Propagators ps(home); ps(); ++ps) if (in(ps.propagator().group())) ps.propagator().enable(home); } }
BrancherGroup& BrancherGroup::move(Space& home, BrancherGroup g) { if ((id() != GROUPID_ALL) && (id() != g.id())) for (Space::Branchers bs(home); bs(); ++bs) if (g.in(bs.brancher().group())) bs.brancher().group(*this); return *this; }
BrancherGroup& BrancherGroup::move(Space& home, unsigned int bid) { if (id() == GROUPID_ALL) return *this; for (Space::Branchers bs(home); bs(); ++bs) if (bs.brancher().id() == bid) { bs.brancher().group(*this); return *this; } throw UnknownBrancher("BrancherGroup::move"); GECODE_NEVER; return *this; }
unsigned int BrancherGroup::size(Space& home) const { if (home.failed()) return 0; unsigned int n=0; for (Space::Branchers bs(home); bs(); ++bs) if (in(bs.brancher().group())) n++; return n; }
void BrancherGroup::kill(Space& home) { if (home.failed()) return; Space::Branchers bs(home); while (bs()) { Brancher& b = bs.brancher(); ++bs; if (in(b.group())) home.kill(b); } }
}
// STATISTICS: kernel-core