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