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