Generated on Sun Feb 17 15:24:25 2019 for Gecode by doxygen 1.6.3

core.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Contributing authors:
00007  *     Samuel Gagnon <samuel.gagnon92@gmail.com>
00008  *
00009  *  Copyright:
00010  *     Christian Schulte, 2002
00011  *     Samuel Gagnon, 2018
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/kernel.hh>
00039 
00040 namespace Gecode {
00041 
00042   /*
00043    * Variable type disposer
00044    *
00045    */
00046   void
00047   VarImpDisposerBase::dispose(Space&,VarImpBase*) {}
00048 
00049   VarImpDisposerBase::~VarImpDisposerBase(void) {}
00050 
00051 
00052 
00053   /*
00054    * Actor
00055    *
00056    */
00057   Actor* Actor::sentinel;
00058 
00059   Actor::~Actor(void) {}
00060 
00061 
00062   /*
00063    * Propagator
00064    *
00065    */
00066   ExecStatus
00067   Propagator::advise(Space&, Advisor&, const Delta&) {
00068     GECODE_NEVER;
00069     return ES_FAILED;
00070   }
00071   void
00072   Propagator::advise(Space&, Advisor&) {
00073     GECODE_NEVER;
00074   }
00075 
00076 
00077   /*
00078    * No-goods
00079    *
00080    */
00081   void
00082   NoGoods::post(Space&) const {
00083   }
00084 
00085   NoGoods NoGoods::eng;
00086 
00087   /*
00088    * Brancher
00089    *
00090    */
00091   NGL*
00092   Brancher::ngl(Space&, const Choice&, unsigned int) const {
00093     return NULL;
00094   }
00095 
00096   void
00097   Brancher::print(const Space&, const Choice&, unsigned int,
00098                   std::ostream&) const {
00099   }
00100 
00101 
00102   /*
00103    * Space: Misc
00104    *
00105    */
00106 
00107   StatusStatistics Space::unused_status;
00108   CloneStatistics Space::unused_clone;
00109   CommitStatistics Space::unused_commit;
00110 
00111 #ifdef GECODE_HAS_VAR_DISPOSE
00112   VarImpDisposerBase* Space::vd[AllVarConf::idx_d];
00113 #endif
00114 
00115   Space::Space(void) : mm(ssd.data().sm) {
00116 #ifdef GECODE_HAS_CBS
00117     var_id_counter = 0;
00118 #endif
00119 #ifdef GECODE_HAS_VAR_DISPOSE
00120     for (int i=0; i<AllVarConf::idx_d; i++)
00121       _vars_d[i] = NULL;
00122 #endif
00123     // Initialize propagator and brancher links
00124     pl.init();
00125     bl.init();
00126     b_status = b_commit = Brancher::cast(&bl);
00127     // Initialize array for forced deletion to be empty
00128     d_fst = d_cur = d_lst = NULL;
00129     // Initialize space as stable but not failed
00130     pc.p.active = &pc.p.queue[0]-1;
00131     // Initialize propagator queues
00132     for (int i=0; i<=PropCost::AC_MAX; i++)
00133       pc.p.queue[i].init();
00134     pc.p.bid_sc = (reserved_bid+1) << sc_bits;
00135     pc.p.n_sub  = 0;
00136     pc.p.vti.other();
00137   }
00138 
00139   void
00140   Space::ap_notice_dispose(Actor* a, bool duplicate) {
00141     // Note that a might be a marked pointer!
00142     if (duplicate && (d_fst != NULL)) {
00143       for (Actor** f = d_fst; f < d_cur; f++)
00144         if (a == *f)
00145           return;
00146     }
00147     if (d_cur == d_lst) {
00148       // Resize
00149       if (d_fst == NULL) {
00150         // Create new array
00151         d_fst = alloc<Actor*>(4);
00152         d_cur = d_fst;
00153         d_lst = d_fst+4;
00154       } else {
00155         // Resize existing array
00156         unsigned int n = static_cast<unsigned int>(d_lst - d_fst);
00157         assert(n != 0);
00158         d_fst = realloc<Actor*>(d_fst,n,2*n);
00159         d_cur = d_fst+n;
00160         d_lst = d_fst+2*n;
00161       }
00162     }
00163     *(d_cur++) = a;
00164   }
00165 
00166   void
00167   Space::ap_ignore_dispose(Actor* a, bool duplicate) {
00168     // Note that a might be a marked pointer!
00169     assert(d_fst != NULL);
00170     Actor** f = d_fst;
00171     if (duplicate) {
00172       while (f < d_cur)
00173         if (a == *f)
00174           break;
00175         else
00176           f++;
00177       if (f == d_cur)
00178         return;
00179     } else {
00180       while (a != *f)
00181         f++;
00182     }
00183     *f = *(--d_cur);
00184   }
00185 
00186   Space::~Space(void) {
00187     // Mark space as failed
00188     fail();
00189     // Delete actors that must be deleted
00190     {
00191       Actor** a = d_fst;
00192       Actor** e = d_cur;
00193       // So that d_unforce knows that deletion is in progress
00194       d_fst = NULL;
00195       while (a < e) {
00196         // Ignore entries for tracers
00197         if (!Support::marked(*a))
00198           (void) (*a)->dispose(*this);
00199         a++;
00200       }
00201     }
00202 #ifdef GECODE_HAS_VAR_DISPOSE
00203     // Delete variables that were registered for disposal
00204     for (int i=0; i<AllVarConf::idx_d; i++)
00205       if (_vars_d[i] != NULL)
00206         vd[i]->dispose(*this, _vars_d[i]);
00207 #endif
00208     // Release memory from memory manager
00209     mm.release(ssd.data().sm);
00210   }
00211 
00212 
00213 
00214   /*
00215    * Space: propagation
00216    *
00217    */
00218 
00219   TraceRecorder*
00220   Space::findtracerecorder(void) {
00221     for (Actor** a=d_fst; a<d_cur; a++) {
00222       Propagator* p = Propagator::cast(*a);
00223       if (!p->disabled())
00224         if (TraceRecorder* tr = dynamic_cast<TraceRecorder*>(p)) {
00225           std::swap(*d_fst,*a);
00226           return tr;
00227         }
00228     }
00229     return nullptr;
00230   }
00231 
00232   void
00233   Space::post(const PostInfo& pi) {
00234     assert(pc.p.bid_sc & sc_trace);
00235     TraceRecorder* tr = findtracerecorder();
00236     if ((tr != NULL) && (tr->events() & TE_POST)) {
00237       GECODE_ASSUME(ssd.data().gpi.pid() >= pi.pid);
00238       unsigned int n = ssd.data().gpi.pid() - pi.pid;
00239       PostTraceInfo::Status s;
00240       if (failed())
00241         s = PostTraceInfo::FAILED;
00242       else if (n == 0)
00243         s = PostTraceInfo::SUBSUMED;
00244       else
00245         s = PostTraceInfo::POSTED;
00246       PostTraceInfo pti(pi.pg,s,n);
00247       tr->tracer()._post(*this,pti);
00248     }
00249   }
00250 
00251   SpaceStatus
00252   Space::status(StatusStatistics& stat) {
00253     // Check whether space is failed
00254     if (failed())
00255       return SS_FAILED;
00256     assert(pc.p.active <= &pc.p.queue[PropCost::AC_MAX+1]);
00257     Propagator* p;
00258     // Check whether space is stable but not failed
00259     if (pc.p.active >= &pc.p.queue[0]) {
00260       ModEventDelta med_o;
00261       if ((pc.p.bid_sc & ((1 << sc_bits) - 1)) == 0) {
00262         // No support for disabled propagators and tracing
00263         // Check whether space is stable but not failed
00264         goto f_unstable;
00265       f_execute:
00266         stat.propagate++;
00267         // Keep old modification event delta
00268         med_o = p->u.med;
00269         // Clear med but leave propagator in queue
00270         p->u.med = 0;
00271         switch (p->propagate(*this,med_o)) {
00272         case ES_FAILED:
00273           goto failed;
00274         case ES_NOFIX:
00275           // Find next, if possible
00276           if (p->u.med != 0) {
00277           f_unstable:
00278             // There is at least one propagator in a queue
00279             do {
00280               assert(pc.p.active >= &pc.p.queue[0]);
00281               // First propagator or link back to queue
00282               ActorLink* fst = pc.p.active->next();
00283               if (pc.p.active != fst) {
00284                 p = Propagator::cast(fst);
00285                 goto f_execute;
00286               }
00287               pc.p.active--;
00288             } while (true);
00289             GECODE_NEVER;
00290           }
00291           // Fall through
00292         case ES_FIX:
00293           // Clear med
00294           p->u.med = 0;
00295           // Put into idle queue
00296           p->unlink(); pl.head(p);
00297         f_stable_or_unstable:
00298           // There might be a propagator in the queue
00299           do {
00300             assert(pc.p.active >= &pc.p.queue[0]);
00301             // First propagator or link back to queue
00302             ActorLink* fst = pc.p.active->next();
00303             if (pc.p.active != fst) {
00304               p = Propagator::cast(fst);
00305               goto f_execute;
00306             }
00307           } while (--pc.p.active >= &pc.p.queue[0]);
00308           assert(pc.p.active < &pc.p.queue[0]);
00309           goto f_stable;
00310         case __ES_SUBSUMED:
00311           p->unlink(); rfree(p,p->u.size);
00312           goto f_stable_or_unstable;
00313         case __ES_PARTIAL:
00314           // Schedule propagator with specified propagator events
00315           assert(p->u.med != 0);
00316           enqueue(p);
00317           goto f_unstable;
00318         default:
00319           GECODE_NEVER;
00320         }
00321       f_stable: ;
00322       } else if ((pc.p.bid_sc & ((1 << sc_bits) - 1)) == sc_disabled) {
00323         // Support for disabled propagators
00324         goto d_unstable;
00325       d_execute:
00326         stat.propagate++;
00327         if (p->disabled())
00328           goto d_put_into_idle;
00329         // Keep old modification event delta
00330         med_o = p->u.med;
00331         // Clear med but leave propagator in queue
00332         p->u.med = 0;
00333         switch (p->propagate(*this,med_o)) {
00334         case ES_FAILED:
00335           goto failed;
00336         case ES_NOFIX:
00337           // Find next, if possible
00338           if (p->u.med != 0) {
00339           d_unstable:
00340             // There is at least one propagator in a queue
00341             do {
00342               assert(pc.p.active >= &pc.p.queue[0]);
00343               // First propagator or link back to queue
00344               ActorLink* fst = pc.p.active->next();
00345               if (pc.p.active != fst) {
00346                 p = Propagator::cast(fst);
00347                 goto d_execute;
00348               }
00349               pc.p.active--;
00350             } while (true);
00351             GECODE_NEVER;
00352           }
00353           // Fall through
00354         case ES_FIX:
00355         d_put_into_idle:
00356           // Clear med
00357           p->u.med = 0;
00358           // Put into idle queue
00359           p->unlink(); pl.head(p);
00360         d_stable_or_unstable:
00361           // There might be a propagator in the queue
00362           do {
00363             assert(pc.p.active >= &pc.p.queue[0]);
00364             // First propagator or link back to queue
00365             ActorLink* fst = pc.p.active->next();
00366             if (pc.p.active != fst) {
00367               p = Propagator::cast(fst);
00368               goto d_execute;
00369             }
00370           } while (--pc.p.active >= &pc.p.queue[0]);
00371           assert(pc.p.active < &pc.p.queue[0]);
00372           goto d_stable;
00373         case __ES_SUBSUMED:
00374           p->unlink(); rfree(p,p->u.size);
00375           goto d_stable_or_unstable;
00376         case __ES_PARTIAL:
00377           // Schedule propagator with specified propagator events
00378           assert(p->u.med != 0);
00379           enqueue(p);
00380           goto d_unstable;
00381         default:
00382           GECODE_NEVER;
00383         }
00384       d_stable: ;
00385       } else {
00386         // Support disabled propagators and tracing
00387         // Find a non-disabled tracer recorder (possibly null)
00388         TraceRecorder* tr = findtracerecorder();
00389         ViewTraceInfo vti; vti.other();
00390 #define GECODE_STATUS_TRACE(q,s) \
00391   if ((tr != NULL) && (tr->events() & TE_PROPAGATE) && \
00392       (tr->filter()(p->group()))) {                    \
00393     PropagateTraceInfo pti(p->id(),p->group(),q,       \
00394                            PropagateTraceInfo::s);     \
00395     tr->tracer()._propagate(*this,pti);                \
00396   }
00397 
00398         goto t_unstable;
00399       t_execute:
00400         stat.propagate++;
00401         if (p->disabled())
00402           goto t_put_into_idle;
00403         vti = pc.p.vti;
00404         pc.p.vti.propagator(*p);
00405         // Keep old modification event delta
00406         med_o = p->u.med;
00407         // Clear med but leave propagator in queue
00408         p->u.med = 0;
00409         switch (p->propagate(*this,med_o)) {
00410         case ES_FAILED:
00411           GECODE_STATUS_TRACE(p,FAILED);
00412           goto failed;
00413         case ES_NOFIX:
00414           // Find next, if possible
00415           if (p->u.med != 0) {
00416             GECODE_STATUS_TRACE(p,NOFIX);
00417           t_unstable:
00418             // There is at least one propagator in a queue
00419             do {
00420               assert(pc.p.active >= &pc.p.queue[0]);
00421               // First propagator or link back to queue
00422               ActorLink* fst = pc.p.active->next();
00423               if (pc.p.active != fst) {
00424                 p = Propagator::cast(fst);
00425                 goto t_execute;
00426               }
00427               pc.p.active--;
00428             } while (true);
00429             GECODE_NEVER;
00430           }
00431           // Fall through
00432         case ES_FIX:
00433           GECODE_STATUS_TRACE(p,FIX);
00434         t_put_into_idle:
00435           // Clear med
00436           p->u.med = 0;
00437           // Put into idle queue
00438           p->unlink(); pl.head(p);
00439         t_stable_or_unstable:
00440           // There might be a propagator in the queue
00441           do {
00442             assert(pc.p.active >= &pc.p.queue[0]);
00443             // First propagator or link back to queue
00444             ActorLink* fst = pc.p.active->next();
00445             if (pc.p.active != fst) {
00446               p = Propagator::cast(fst);
00447               goto t_execute;
00448             }
00449           } while (--pc.p.active >= &pc.p.queue[0]);
00450           assert(pc.p.active < &pc.p.queue[0]);
00451           goto t_stable;
00452         case __ES_SUBSUMED:
00453           GECODE_STATUS_TRACE(NULL,SUBSUMED);
00454           p->unlink(); rfree(p,p->u.size);
00455           goto t_stable_or_unstable;
00456         case __ES_PARTIAL:
00457           GECODE_STATUS_TRACE(p,NOFIX);
00458           // Schedule propagator with specified propagator events
00459           assert(p->u.med != 0);
00460           enqueue(p);
00461           goto t_unstable;
00462         default:
00463           GECODE_NEVER;
00464         }
00465       t_stable:
00466         pc.p.vti = vti;
00467 #undef GECODE_STATUS_TRACE
00468       }
00469     }
00470 
00471     /*
00472      * Find the next brancher that has still alternatives left
00473      *
00474      * It is important to note that branchers reporting to have no more
00475      * alternatives left cannot be deleted. They cannot be deleted
00476      * as there might be choices to be used in commit
00477      * that refer to one of these branchers. This e.g. happens when
00478      * we combine branch-and-bound search with adaptive recomputation: during
00479      * recomputation, a copy is constrained to be better than the currently
00480      * best solution, then the first half of the choices are posted,
00481      * and a fixpoint computed (for storing in the middle of the path). Then
00482      * the remaining choices are posted, and because of the additional
00483      * constraints that the space must be better than the previous solution,
00484      * the corresponding Branchers may already have no alternatives left.
00485      *
00486      * The same situation may arise due to weakly monotonic propagators.
00487      *
00488      * A brancher reporting that no more alternatives exist is exhausted.
00489      * All exhausted branchers will be left of the current pointer b_status.
00490      * Only when it is known that no more choices
00491      * can be used for commit an exhausted brancher can actually be deleted.
00492      * This becomes known when choice is called.
00493      */
00494     while (b_status != Brancher::cast(&bl))
00495       if (b_status->status(*this)) {
00496         // Brancher still has choices to generate
00497         return SS_BRANCH;
00498       } else {
00499         // Brancher is exhausted
00500         b_status = Brancher::cast(b_status->next());
00501       }
00502     // No brancher with alternatives left, space is solved
00503     return SS_SOLVED;
00504 
00505     // Process failure
00506   failed:
00507     // Count failure
00508     ssd.data().gpi.fail(p->gpi());
00509     // Mark as failed
00510     fail();
00511     // Propagate top priority propagators
00512     ActorLink* e = &pc.p.queue[PropCost::AC_RECORD];
00513     for (ActorLink* a = e->next(); a != e; a = a->next()) {
00514       Propagator* top = Propagator::cast(a);
00515       // Keep old modification event delta
00516       ModEventDelta top_med_o = top->u.med;
00517       // Clear med but leave propagator in queue
00518       top->u.med = 0;
00519       switch (top->propagate(*this,top_med_o)) {
00520       case ES_FIX:
00521       case __ES_SUBSUMED:
00522         break;
00523       default:
00524         GECODE_NEVER;
00525       }
00526     }
00527     return SS_FAILED;
00528   }
00529 
00530 
00531   const Choice*
00532   Space::choice(void) {
00533     if (!stable())
00534       throw SpaceNotStable("Space::choice");
00535     if (failed() || (b_status == Brancher::cast(&bl))) {
00536       // There are no more choices to be generated
00537       // Delete all branchers
00538       Brancher* b = Brancher::cast(bl.next());
00539       while (b != Brancher::cast(&bl)) {
00540         Brancher* d = b;
00541         b = Brancher::cast(b->next());
00542         rfree(d,d->dispose(*this));
00543       }
00544       bl.init();
00545       b_status = b_commit = Brancher::cast(&bl);
00546       return NULL;
00547     }
00548     /*
00549      * The call to choice() says that no older choices
00550      * can be used. Hence, all branchers that are exhausted can be deleted.
00551      */
00552     Brancher* b = Brancher::cast(bl.next());
00553     while (b != b_status) {
00554       Brancher* d = b;
00555       b = Brancher::cast(b->next());
00556       d->unlink();
00557       rfree(d,d->dispose(*this));
00558     }
00559     // Make sure that b_commit does not point to a deleted brancher!
00560     b_commit = b_status;
00561     return b_status->choice(*this);
00562   }
00563 
00564   const Choice*
00565   Space::choice(Archive& e) const {
00566     unsigned int id; e >> id;
00567     Brancher* b_cur = Brancher::cast(bl.next());
00568     while (b_cur != Brancher::cast(&bl)) {
00569       if (id == b_cur->id())
00570         return b_cur->choice(*this,e);
00571       b_cur = Brancher::cast(b_cur->next());
00572     }
00573     throw SpaceNoBrancher("Space::choice");
00574   }
00575 
00576   void
00577   Space::_commit(const Choice& c, unsigned int a) {
00578     if (a >= c.alternatives())
00579       throw SpaceIllegalAlternative("Space::commit");
00580     if (failed())
00581       return;
00582     if (Brancher* b = brancher(c.bid)) {
00583       // There is a matching brancher
00584       if (pc.p.bid_sc & sc_trace) {
00585         TraceRecorder* tr = findtracerecorder();
00586         if ((tr != NULL) && (tr->events() & TE_COMMIT) &&
00587             tr->filter()(b->group())) {
00588           CommitTraceInfo cti(*b,c,a);
00589           tr->tracer()._commit(*this,cti);
00590         }
00591         ViewTraceInfo vti = pc.p.vti;
00592         pc.p.vti.brancher(*b);
00593         ExecStatus es = b->commit(*this,c,a);
00594         pc.p.vti = vti;
00595         if (es == ES_FAILED)
00596           fail();
00597       } else {
00598         if (b->commit(*this,c,a) == ES_FAILED)
00599           fail();
00600       }
00601     } else {
00602       // There is no matching brancher!
00603       throw SpaceNoBrancher("Space::commit");
00604     }
00605   }
00606 
00607   void
00608   Space::_trycommit(const Choice& c, unsigned int a) {
00609     if (a >= c.alternatives())
00610       throw SpaceIllegalAlternative("Space::commit");
00611     if (failed())
00612       return;
00613     if (Brancher* b = brancher(c.bid)) {
00614       // There is a matching brancher
00615       if (pc.p.bid_sc & sc_trace) {
00616         TraceRecorder* tr = findtracerecorder();
00617         if ((tr != NULL) && (tr->events() & TE_COMMIT) &&
00618             tr->filter()(b->group())) {
00619           CommitTraceInfo cti(*b,c,a);
00620           tr->tracer()._commit(*this,cti);
00621         }
00622         ViewTraceInfo vti = pc.p.vti;
00623         pc.p.vti.brancher(*b);
00624         ExecStatus es = b->commit(*this,c,a);
00625         pc.p.vti = vti;
00626         if (es == ES_FAILED)
00627           fail();
00628       } else {
00629         if (b->commit(*this,c,a) == ES_FAILED)
00630           fail();
00631       }
00632     }
00633   }
00634 
00635   NGL*
00636   Space::ngl(const Choice& c, unsigned int a) {
00637     if (a >= c.alternatives())
00638       throw SpaceIllegalAlternative("Space::ngl");
00639     if (failed())
00640       return NULL;
00641     if (Brancher* b = brancher(c.bid)) {
00642       // There is a matching brancher
00643       return b->ngl(*this,c,a);
00644     } else {
00645       return NULL;
00646     }
00647   }
00648 
00649   void
00650   Space::print(const Choice& c, unsigned int a, std::ostream& o) const {
00651     if (a >= c.alternatives())
00652       throw SpaceIllegalAlternative("Space::print");
00653     if (failed())
00654       return;
00655     if (Brancher* b = const_cast<Space&>(*this).brancher(c.bid)) {
00656       // There is a matching brancher
00657       b->print(*this,c,a,o);
00658     } else {
00659       // There is no matching brancher!
00660       throw SpaceNoBrancher("Space::print");
00661     }
00662   }
00663 
00664   void
00665   Space::kill_brancher(unsigned int id) {
00666     if (failed())
00667       return;
00668     for (Brancher* b = Brancher::cast(bl.next());
00669          b != Brancher::cast(&bl); b = Brancher::cast(b->next()))
00670       if (b->id() == id) {
00671         kill(*b);
00672         return;
00673       }
00674   }
00675 
00676 
00677   /*
00678    * Space cloning
00679    *
00680    * Cloning is performed in two steps:
00681    *  - The space itself is copied by the copy constructor. This
00682    *    also copies all propagators, branchers, and variables.
00683    *    The copied variables are recorded.
00684    *  - In the second step the dependency information of the recorded
00685    *    variables is updated and their forwarding information is reset.
00686    *
00687    */
00688   Space::Space(Space& s)
00689     : ssd(s.ssd),
00690       mm(ssd.data().sm,s.mm,s.pc.p.n_sub*sizeof(Propagator**)),
00691 #ifdef GECODE_HAS_CBS
00692       var_id_counter(s.var_id_counter),
00693 #endif
00694       d_fst(&Actor::sentinel) {
00695 #ifdef GECODE_HAS_VAR_DISPOSE
00696     for (int i=0; i<AllVarConf::idx_d; i++)
00697       _vars_d[i] = NULL;
00698 #endif
00699     for (int i=0; i<AllVarConf::idx_c; i++)
00700       pc.c.vars_u[i] = NULL;
00701     pc.c.vars_noidx = NULL;
00702     pc.c.local = NULL;
00703     // Copy all propagators
00704     {
00705       ActorLink* p = &pl;
00706       ActorLink* e = &s.pl;
00707       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00708         Actor* c = Actor::cast(a)->copy(*this);
00709         // Link copied actor
00710         p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p);
00711         // Note that forwarding is done in the constructors
00712         p = c;
00713       }
00714       // Link last actor
00715       p->next(&pl); pl.prev(p);
00716     }
00717     // Copy all branchers
00718     {
00719       ActorLink* p = &bl;
00720       ActorLink* e = &s.bl;
00721       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00722         Actor* c = Actor::cast(a)->copy(*this);
00723         // Link copied actor
00724         p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p);
00725         // Note that forwarding is done in the constructors
00726         p = c;
00727       }
00728       // Link last actor
00729       p->next(&bl); bl.prev(p);
00730     }
00731     // Setup brancher pointers
00732     if (s.b_status == &s.bl) {
00733       b_status = Brancher::cast(&bl);
00734     } else {
00735       b_status = Brancher::cast(s.b_status->prev());
00736     }
00737     if (s.b_commit == &s.bl) {
00738       b_commit = Brancher::cast(&bl);
00739     } else {
00740       b_commit = Brancher::cast(s.b_commit->prev());
00741     }
00742   }
00743 
00744   Space*
00745   Space::_clone(void) {
00746     if (failed())
00747       throw SpaceFailed("Space::clone");
00748     if (!stable())
00749       throw SpaceNotStable("Space::clone");
00750 
00751     // Copy all data structures (which in turn will invoke the constructor)
00752     Space* c = copy();
00753 
00754     if (c->d_fst != &Actor::sentinel)
00755       throw SpaceNotCloned("Space::clone");
00756 
00757     // Setup array for actor disposal in c
00758     {
00759       unsigned int n = static_cast<unsigned int>(d_cur - d_fst);
00760       if (n == 0) {
00761         // No actors
00762         c->d_fst = c->d_cur = c->d_lst = NULL;
00763       } else {
00764         // Leave one entry free
00765         c->d_fst = c->alloc<Actor*>(n+1);
00766         c->d_cur = c->d_fst;
00767         c->d_lst = c->d_fst+n+1;
00768         for (Actor** d_fst_iter = d_fst; d_fst_iter != d_cur; d_fst_iter++) {
00769           ptrdiff_t m;
00770           Actor* a = static_cast<Actor*>(Support::ptrsplit(*d_fst_iter,m));
00771           if (a->prev())
00772             *(c->d_cur++) = Actor::cast(static_cast<ActorLink*>
00773                                         (Support::ptrjoin(a->prev(),m)));
00774         }
00775       }
00776     }
00777 
00778     // Update variables without indexing structure
00779     VarImp<NoIdxVarImpConf>* x =
00780       static_cast<VarImp<NoIdxVarImpConf>*>(c->pc.c.vars_noidx);
00781     while (x != NULL) {
00782       VarImp<NoIdxVarImpConf>* n = x->next();
00783       x->b.base = NULL; x->u.idx[0] = 0;
00784       if (sizeof(ActorLink**) > sizeof(unsigned int))
00785         *(1+&x->u.idx[0]) = 0;
00786       x = n;
00787     }
00788     // Update variables with indexing structure
00789     c->update(static_cast<ActorLink**>(c->mm.subscriptions()));
00790 
00791     // Re-establish prev links (reset forwarding information)
00792     {
00793       ActorLink* p_a = &pl;
00794       ActorLink* c_a = p_a->next();
00795       // First update propagators and advisors
00796       while (c_a != &pl) {
00797         Propagator* p = Propagator::cast(c_a);
00798         if (p->u.advisors != NULL) {
00799           ActorLink* a = p->u.advisors;
00800           p->u.advisors = NULL;
00801           do {
00802             a->prev(p); a = a->next();
00803           } while (a != NULL);
00804         }
00805         c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00806       }
00807     }
00808     {
00809       ActorLink* p_a = &bl;
00810       ActorLink* c_a = p_a->next();
00811       // Update branchers
00812       while (c_a != &bl) {
00813         c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00814       }
00815     }
00816 
00817     // Reset links for local objects
00818     for (ActorLink* l = c->pc.c.local; l != NULL; l = l->next())
00819       l->prev(NULL);
00820 
00821     // Initialize propagator queue
00822     c->pc.p.active = &c->pc.p.queue[0]-1;
00823     for (int i=0; i<=PropCost::AC_MAX; i++)
00824       c->pc.p.queue[i].init();
00825     // Copy propagation only data
00826     c->pc.p.n_sub  = pc.p.n_sub;
00827     c->pc.p.bid_sc = pc.p.bid_sc;
00828 
00829     // Reset execution information
00830     c->pc.p.vti.other(); pc.p.vti.other();
00831 
00832     return c;
00833   }
00834 
00835   void
00836   Space::constrain(const Space&) {
00837   }
00838 
00839   bool
00840   Space::master(const MetaInfo& mi) {
00841     switch (mi.type()) {
00842     case MetaInfo::RESTART:
00843       if (mi.last() != NULL)
00844         constrain(*mi.last());
00845       mi.nogoods().post(*this);
00846       // Perform a restart even if a solution has been found
00847       return true;
00848     case MetaInfo::PORTFOLIO:
00849       // Kill all branchers
00850       BrancherGroup::all.kill(*this);
00851       return true;
00852     default: GECODE_NEVER;
00853       return true;
00854     }
00855   }
00856 
00857   bool
00858   Space::slave(const MetaInfo&) {
00859     return true;
00860   }
00861 
00862 
00863   void
00864   Space::afc_unshare(void) {
00865     if (ssd.data().gpi.unshare()) {
00866       for (Propagators ps(*this); ps(); ++ps) {
00867         Propagator& p = ps.propagator();
00868         Kernel::GPI::Info* gpi
00869           = ssd.data().gpi.allocate(p.gpi().pid,p.gpi().gid);
00870         if (p.disabled())
00871           p.gpi_disabled = Support::mark(gpi);
00872         else
00873           p.gpi_disabled = gpi;
00874       }
00875     }
00876   }
00877 
00878   void
00879   LocalObject::fwdcopy(Space& home) {
00880     ActorLink::cast(this)->prev(copy(home));
00881     next(home.pc.c.local);
00882     home.pc.c.local = this;
00883   }
00884 
00885   void
00886   Choice::archive(Archive& e) const {
00887     e << id();
00888   }
00889 
00890   bool
00891   NGL::notice(void) const {
00892     return false;
00893   }
00894 
00895   NGL::~NGL(void) {
00896   }
00897 
00898 
00899   /*
00900    * Groups
00901    */
00902 
00903   Group Group::all(GROUPID_ALL);
00904   Group Group::def(GROUPID_DEF);
00905 
00906   PropagatorGroup PropagatorGroup::all(GROUPID_ALL);
00907   PropagatorGroup PropagatorGroup::def(GROUPID_DEF);
00908 
00909   BrancherGroup BrancherGroup::all(GROUPID_ALL);
00910   BrancherGroup BrancherGroup::def(GROUPID_DEF);
00911 
00912   unsigned int Group::next = GROUPID_DEF+1;
00913   Support::Mutex Group::m;
00914 
00915 
00916   Group::Group(void) {
00917     {
00918       Support::Lock l(m);
00919       gid = next++;
00920     }
00921     if (gid == GROUPID_MAX)
00922       throw TooManyGroups("Group::Group");
00923   }
00924 
00925 
00926   PropagatorGroup&
00927   PropagatorGroup::move(Space& home, PropagatorGroup g) {
00928     if ((id() != GROUPID_ALL) && (id() != g.id()))
00929       for (Space::Propagators ps(home); ps(); ++ps)
00930         if (g.in(ps.propagator().group()))
00931           ps.propagator().group(*this);
00932     return *this;
00933   }
00934 
00935   PropagatorGroup&
00936   PropagatorGroup::move(Space& home, unsigned int pid) {
00937     if (id() == GROUPID_ALL)
00938       return *this;
00939     for (Space::Propagators ps(home); ps(); ++ps)
00940       if (ps.propagator().id() == pid) {
00941         ps.propagator().group(*this);
00942         return *this;
00943       }
00944     throw UnknownPropagator("PropagatorGroup::move");
00945     GECODE_NEVER;
00946     return *this;
00947   }
00948 
00949   unsigned int
00950   PropagatorGroup::size(Space& home) const {
00951     if (home.failed())
00952       return 0;
00953     unsigned int n=0;
00954     for (Space::Propagators ps(home); ps(); ++ps)
00955       if (in(ps.propagator().group()))
00956         n++;
00957     return n;
00958   }
00959 
00960   void
00961   PropagatorGroup::kill(Space& home) {
00962     if (home.failed())
00963       return;
00964     Space::Propagators ps(home);
00965     while (ps()) {
00966       Propagator& p = ps.propagator();
00967       ++ps;
00968       if (in(p.group()))
00969         home.kill(p);
00970     }
00971   }
00972 
00973   void
00974   PropagatorGroup::disable(Space& home) {
00975     if (home.failed())
00976       return;
00977     for (Space::Propagators ps(home); ps(); ++ps)
00978       if (in(ps.propagator().group()))
00979         ps.propagator().disable(home);
00980   }
00981 
00982   void
00983   PropagatorGroup::enable(Space& home, bool s) {
00984     if (home.failed())
00985       return;
00986     if (s) {
00987       Space::Propagators ps(home);
00988       while (ps()) {
00989         Propagator& p = ps.propagator();
00990         ++ps;
00991         if (in(p.group())) {
00992           p.enable(home);
00993           p.reschedule(home);
00994         }
00995       }
00996     } else {
00997       for (Space::Propagators ps(home); ps(); ++ps)
00998         if (in(ps.propagator().group()))
00999           ps.propagator().enable(home);
01000     }
01001   }
01002 
01003 
01004   BrancherGroup&
01005   BrancherGroup::move(Space& home, BrancherGroup g) {
01006     if ((id() != GROUPID_ALL) && (id() != g.id()))
01007       for (Space::Branchers bs(home); bs(); ++bs)
01008         if (g.in(bs.brancher().group()))
01009           bs.brancher().group(*this);
01010     return *this;
01011   }
01012 
01013   BrancherGroup&
01014   BrancherGroup::move(Space& home, unsigned int bid) {
01015     if (id() == GROUPID_ALL)
01016       return *this;
01017     for (Space::Branchers bs(home); bs(); ++bs)
01018       if (bs.brancher().id() == bid) {
01019         bs.brancher().group(*this);
01020         return *this;
01021       }
01022     throw UnknownBrancher("BrancherGroup::move");
01023     GECODE_NEVER;
01024     return *this;
01025   }
01026 
01027   unsigned int
01028   BrancherGroup::size(Space& home) const {
01029     if (home.failed())
01030       return 0;
01031     unsigned int n=0;
01032     for (Space::Branchers bs(home); bs(); ++bs)
01033       if (in(bs.brancher().group()))
01034         n++;
01035     return n;
01036   }
01037 
01038   void
01039   BrancherGroup::kill(Space& home) {
01040     if (home.failed())
01041       return;
01042     Space::Branchers bs(home);
01043     while (bs()) {
01044       Brancher& b = bs.brancher();
01045       ++bs;
01046       if (in(b.group()))
01047         home.kill(b);
01048     }
01049   }
01050 
01051 
01052 }
01053 
01054 // STATISTICS: kernel-core