Generated on Wed Mar 13 11:48:31 2013 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: 2013-03-05 15:37:20 +0100 (Tue, 05 Mar 2013) $ by $Author: schulte $
00011  *     $Revision: 13437 $
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   size_t
00058   Actor::allocated(void) const {
00059     return 0;
00060   }
00061 
00062   Actor* Actor::sentinel;
00063 
00064 #ifdef __GNUC__
00065 
00066   Actor::~Actor(void) {}
00067 #endif
00068 
00069 
00070 
00071   /*
00072    * Propagator
00073    *
00074    */
00075   ExecStatus
00076   Propagator::advise(Space&, Advisor&, const Delta&) {
00077     assert(false);
00078     return ES_FAILED;
00079   }
00080 
00081 
00082 
00083   /*
00084    * Space: Misc
00085    *
00086    */
00087   StatusStatistics Space::unused_status;
00088   CloneStatistics Space::unused_clone;
00089   CommitStatistics Space::unused_commit;
00090 
00091 #ifdef GECODE_HAS_VAR_DISPOSE
00092   VarImpDisposerBase* Space::vd[AllVarConf::idx_d];
00093 #endif
00094 
00095   Space::Space(void)
00096     : sm(new SharedMemory), mm(sm), _wmp_afc(0U) {
00097 #ifdef GECODE_HAS_VAR_DISPOSE
00098     for (int i=0; i<AllVarConf::idx_d; i++)
00099       _vars_d[i] = NULL;
00100 #endif
00101     // Initialize propagator and brancher links
00102     pl.init();
00103     bl.init();
00104     b_status = b_commit = Brancher::cast(&bl);
00105     // Initialize array for forced deletion to be empty
00106     d_fst = d_cur = d_lst = NULL;
00107     // Initialize space as stable but not failed
00108     pc.p.active = &pc.p.queue[0]-1;
00109     // Initialize propagator queues
00110     for (int i=0; i<=PropCost::AC_MAX; i++)
00111       pc.p.queue[i].init();
00112     pc.p.branch_id = reserved_branch_id+1;
00113     pc.p.n_sub = 0;
00114   }
00115 
00116   void
00117   Space::d_resize(void) {
00118     if (d_fst == NULL) {
00119       // Create new array
00120       d_fst = alloc<Actor*>(4);
00121       d_cur = d_fst;
00122       d_lst = d_fst+4;
00123     } else {
00124       // Resize existing array
00125       unsigned int n = static_cast<unsigned int>(d_lst - d_fst);
00126       assert(n != 0);
00127       d_fst = realloc<Actor*>(d_fst,n,2*n);
00128       d_cur = d_fst+n;
00129       d_lst = d_fst+2*n;
00130     }
00131   }
00132 
00133   unsigned int
00134   Space::propagators(void) const {
00135     unsigned int n = 0;
00136     for (Propagators p(*this); p(); ++p)
00137       n++;
00138     return n;
00139   }
00140 
00141   unsigned int
00142   Space::branchers(void) const {
00143     unsigned int n = 0;
00144     for (Branchers b(*this); b(); ++b)
00145       n++;
00146     return n;
00147   }
00148 
00149   void
00150   Space::flush(void) {
00151     // Flush malloc cache
00152     sm->flush();
00153   }
00154 
00155   Space::~Space(void) {
00156     // Mark space as failed
00157     fail();
00158     // Delete actors that must be deleted
00159     {
00160       Actor** a = d_fst;
00161       Actor** e = d_cur;
00162       // So that d_unforce knows that deletion is in progress
00163       d_fst = NULL;
00164       while (a < e) {
00165         (void) (*a)->dispose(*this);
00166         a++;
00167       }
00168     }
00169 #ifdef GECODE_HAS_VAR_DISPOSE
00170     // Delete variables that were registered for disposal
00171     for (int i=AllVarConf::idx_d; i--;)
00172       if (_vars_d[i] != NULL)
00173         vd[i]->dispose(*this, _vars_d[i]);
00174 #endif
00175     // Release memory from memory manager
00176     mm.release(sm);
00177     // Release shared memory
00178     if (sm->release())
00179       delete sm;
00180   }
00181 
00182 
00183 
00184   /*
00185    * Space: propagation
00186    *
00187    */
00188 
00189   SpaceStatus
00190   Space::status(StatusStatistics& stat) {
00191     SpaceStatus s = SS_FAILED;
00192     // Check whether space is failed
00193     if (failed()) {
00194       s = SS_FAILED; goto exit;
00195     }
00196     assert(pc.p.active <= &pc.p.queue[PropCost::AC_MAX+1]);
00197     // Check whether space is stable but not failed
00198     if (pc.p.active >= &pc.p.queue[0]) {
00199       Propagator* p;
00200       ModEventDelta med_o;
00201       goto unstable;
00202     execute:
00203       stat.propagate++;
00204       // Keep old modification event delta
00205       med_o = p->u.med;
00206       // Clear med but leave propagator in queue
00207       p->u.med = 0;
00208       switch (p->propagate(*this,med_o)) {
00209       case ES_FAILED:
00210         // Count failure
00211         if (afc_enabled())
00212           gafc.fail(p->gafc);
00213         // Mark as failed
00214         fail(); s = SS_FAILED; goto exit;
00215       case ES_NOFIX:
00216         // Find next, if possible
00217         if (p->u.med != 0) {
00218         unstable:
00219           // There is at least one propagator in a queue
00220           do {
00221             assert(pc.p.active >= &pc.p.queue[0]);
00222             // First propagator or link back to queue
00223             ActorLink* fst = pc.p.active->next();
00224             if (pc.p.active != fst) {
00225               p = Propagator::cast(fst);
00226               goto execute;
00227             }
00228             pc.p.active--;
00229           } while (true);
00230           GECODE_NEVER;
00231         }
00232         // Fall through
00233       case ES_FIX:
00234         // Clear med and put into idle queue
00235         p->u.med = 0; p->unlink(); pl.head(p);
00236       stable_or_unstable:
00237         // There might be a propagator in the queue
00238         do {
00239           assert(pc.p.active >= &pc.p.queue[0]);
00240           // First propagator or link back to queue
00241           ActorLink* fst = pc.p.active->next();
00242           if (pc.p.active != fst) {
00243             p = Propagator::cast(fst);
00244             goto execute;
00245           }
00246         } while (--pc.p.active >= &pc.p.queue[0]);
00247         assert(pc.p.active < &pc.p.queue[0]);
00248         goto stable;
00249       case __ES_SUBSUMED:
00250         p->unlink(); rfree(p,p->u.size);
00251         goto stable_or_unstable;
00252       case __ES_PARTIAL:
00253         // Schedule propagator with specified propagator events
00254         assert(p->u.med != 0);
00255         enqueue(p);
00256         goto unstable;
00257       default:
00258         GECODE_NEVER;
00259       }
00260     }
00261   stable:
00262     /*
00263      * Find the next brancher that has still alternatives left
00264      *
00265      * It is important to note that branchers reporting to have no more
00266      * alternatives left cannot be deleted. They cannot be deleted
00267      * as there might be choices to be used in commit
00268      * that refer to one of these branchers. This e.g. happens when
00269      * we combine branch-and-bound search with adaptive recomputation: during
00270      * recomputation, a copy is constrained to be better than the currently
00271      * best solution, then the first half of the choices are posted,
00272      * and a fixpoint computed (for storing in the middle of the path). Then
00273      * the remaining choices are posted, and because of the additional
00274      * constraints that the space must be better than the previous solution,
00275      * the corresponding Branchers may already have no alternatives left.
00276      *
00277      * The same situation may arise due to weakly monotonic propagators.
00278      *
00279      * A brancher reporting that no more alternatives exist is exhausted.
00280      * All exhausted branchers will be left of the current pointer b_status.
00281      * Only when it is known that no more choices
00282      * can be used for commit an exhausted brancher can actually be deleted.
00283      * This becomes known when choice is called.
00284      */
00285     while (b_status != Brancher::cast(&bl))
00286       if (b_status->status(*this)) {
00287         // Brancher still has choices to generate
00288         s = SS_BRANCH; goto exit;
00289       } else {
00290         // Brancher is exhausted
00291         b_status = Brancher::cast(b_status->next());
00292       }
00293     // No brancher with alternatives left, space is solved
00294     s = SS_SOLVED;
00295   exit:
00296     stat.wmp = (wmp() > 0U);
00297     if (wmp() == 1U) 
00298       wmp(0U);
00299     return s;
00300   }
00301 
00302 
00303   const Choice*
00304   Space::choice(void) {
00305     if (!stable())
00306       throw SpaceNotStable("Space::choice");
00307     if (failed() || (b_status == Brancher::cast(&bl))) {
00308       // There are no more choices to be generated
00309       // Delete all branchers
00310       Brancher* b = Brancher::cast(bl.next()); 
00311       while (b != Brancher::cast(&bl)) {
00312         Brancher* d = b;
00313         b = Brancher::cast(b->next());
00314         rfree(d,d->dispose(*this));
00315       }
00316       bl.init();
00317       b_status = b_commit = Brancher::cast(&bl);
00318       return NULL;
00319     }
00320     /*
00321      * The call to choice() says that no older choices
00322      * can be used. Hence, all branchers that are exhausted can be deleted.
00323      */
00324     Brancher* b = Brancher::cast(bl.next());
00325     while (b != b_status) {
00326       Brancher* d = b;
00327       b = Brancher::cast(b->next());
00328       d->unlink();
00329       rfree(d,d->dispose(*this));
00330     }
00331     // Make sure that b_commit does not point to a deleted brancher!
00332     b_commit = b_status;
00333     return b_status->choice(*this);
00334   }
00335 
00336   const Choice*
00337   Space::choice(Archive& e) const {
00338     unsigned int id; e >> id;
00339     Brancher* b_cur = Brancher::cast(bl.next());
00340     while (b_cur != Brancher::cast(&bl)) {
00341       if (id == b_cur->id())
00342         return b_cur->choice(*this,e);
00343       b_cur = Brancher::cast(b_cur->next());
00344     }
00345     throw SpaceNoBrancher("Space::choice");
00346   }
00347 
00348   void
00349   Space::_commit(const Choice& c, unsigned int a) {
00350     if (a >= c.alternatives())
00351       throw SpaceIllegalAlternative();
00352     if (failed())
00353       return;
00354     if (Brancher* b = brancher(c._id)) {
00355       // There is a matching brancher
00356       if (b->commit(*this,c,a) == ES_FAILED)
00357         fail();
00358     } else {
00359       // There is no matching brancher!
00360       throw SpaceNoBrancher("Space::commit");
00361     }
00362   }
00363 
00364   void
00365   Space::kill_brancher(unsigned int id) {
00366     if (failed())
00367       return;
00368     for (Brancher* b = Brancher::cast(bl.next()); 
00369          b != Brancher::cast(&bl); b = Brancher::cast(b->next()))
00370       if (b->id() == id) {
00371         // Make sure that neither b_status nor b_commit does not point to b
00372         if (b_commit == b)
00373           b_commit = Brancher::cast(b->next());
00374         if (b_status == b)
00375           b_status = Brancher::cast(b->next());
00376         b->unlink();
00377         rfree(b,b->dispose(*this));
00378         return;
00379       }
00380   }
00381 
00382 
00383 
00384 
00385   /*
00386    * Space cloning
00387    *
00388    * Cloning is performed in two steps:
00389    *  - The space itself is copied by the copy constructor. This
00390    *    also copies all propagators, branchers, and variables.
00391    *    The copied variables are recorded.
00392    *  - In the second step the dependency information of the recorded
00393    *    variables is updated and their forwarding information is reset.
00394    *
00395    */
00396   Space::Space(bool share, Space& s)
00397     : sm(s.sm->copy(share)), 
00398       mm(sm,s.mm,s.pc.p.n_sub*sizeof(Propagator**)),
00399       gafc(s.gafc),
00400       d_fst(&Actor::sentinel),
00401       _wmp_afc(s._wmp_afc) {
00402 #ifdef GECODE_HAS_VAR_DISPOSE
00403     for (int i=0; i<AllVarConf::idx_d; i++)
00404       _vars_d[i] = NULL;
00405 #endif
00406     for (int i=0; i<AllVarConf::idx_c; i++)
00407       pc.c.vars_u[i] = NULL;
00408     pc.c.vars_noidx = NULL;
00409     pc.c.shared = NULL;
00410     pc.c.local = NULL;
00411     // Copy all propagators
00412     {
00413       ActorLink* p = &pl;
00414       ActorLink* e = &s.pl;
00415       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00416         Actor* c = Actor::cast(a)->copy(*this,share);
00417         // Link copied actor
00418         p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p);
00419         // Note that forwarding is done in the constructors
00420         p = c;
00421       }
00422       // Link last actor
00423       p->next(&pl); pl.prev(p);
00424     }
00425     // Copy all branchers
00426     {
00427       ActorLink* p = &bl;
00428       ActorLink* e = &s.bl;
00429       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00430         Actor* c = Actor::cast(a)->copy(*this,share);
00431         // Link copied actor
00432         p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p);
00433         // Note that forwarding is done in the constructors
00434         p = c;
00435       }
00436       // Link last actor
00437       p->next(&bl); bl.prev(p);
00438     }
00439     // Setup brancher pointers
00440     if (s.b_status == &s.bl) {
00441       b_status = Brancher::cast(&bl);
00442     } else {
00443       b_status = Brancher::cast(s.b_status->prev());
00444     }
00445     if (s.b_commit == &s.bl) {
00446       b_commit = Brancher::cast(&bl);
00447     } else {
00448       b_commit = Brancher::cast(s.b_commit->prev());
00449     }
00450   }
00451 
00452   Space*
00453   Space::_clone(bool share) {
00454     if (failed())
00455       throw SpaceFailed("Space::clone");
00456     if (!stable())
00457       throw SpaceNotStable("Space::clone");
00458 
00459     // Copy all data structures (which in turn will invoke the constructor)
00460     Space* c = copy(share);
00461 
00462     if (c->d_fst != &Actor::sentinel)
00463       throw SpaceNotCloned("Space::clone");
00464 
00465     // Setup array for actor disposal in c
00466     {
00467       unsigned int n = static_cast<unsigned int>(d_cur - d_fst);
00468       if (n == 0) {
00469         // No actors
00470         c->d_fst = c->d_cur = c->d_lst = NULL;
00471       } else {
00472         // Leave one entry free
00473         c->d_fst = c->alloc<Actor*>(n+1);
00474         c->d_cur = c->d_fst;
00475         c->d_lst = c->d_fst+n+1;
00476         for (Actor** d_fst_iter = d_fst; d_fst_iter != d_cur; d_fst_iter++) {
00477           if ((*d_fst_iter)->prev())
00478             *(c->d_cur++) = Actor::cast((*d_fst_iter)->prev());
00479         }
00480       }
00481     }
00482 
00483     // Update variables without indexing structure
00484     VarImp<NoIdxVarImpConf>* x =
00485       static_cast<VarImp<NoIdxVarImpConf>*>(c->pc.c.vars_noidx);
00486     while (x != NULL) {
00487       VarImp<NoIdxVarImpConf>* n = x->next();
00488       x->b.base = NULL; x->u.idx[0] = 0;
00489       if (sizeof(ActorLink**) > sizeof(unsigned int))
00490         *(1+&x->u.idx[0]) = 0;
00491       x = n;
00492     }
00493     // Update variables with indexing structure
00494     c->update(static_cast<ActorLink**>(c->mm.subscriptions()));
00495 
00496     // Re-establish prev links (reset forwarding information)
00497     {
00498       ActorLink* p_a = &pl;
00499       ActorLink* c_a = p_a->next();
00500       // First update propagators and advisors
00501       while (c_a != &pl) {
00502         Propagator* p = Propagator::cast(c_a);
00503         if (p->u.advisors != NULL) {
00504           ActorLink* a = p->u.advisors;
00505           p->u.advisors = NULL;
00506           do {
00507             a->prev(p); a = a->next();
00508           } while (a != NULL);
00509         }
00510         c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00511       }
00512     }
00513     {
00514       ActorLink* p_a = &bl;
00515       ActorLink* c_a = p_a->next();
00516       // Update branchers
00517       while (c_a != &bl) {
00518         c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00519       }
00520     }
00521 
00522     // Reset links for shared objects
00523     for (SharedHandle::Object* s = c->pc.c.shared; s != NULL; s = s->next)
00524       s->fwd = NULL;
00525 
00526     // Reset links for local objects
00527     for (ActorLink* l = c->pc.c.local; l != NULL; l = l->next())
00528       l->prev(NULL);
00529 
00530     // Initialize propagator queue
00531     c->pc.p.active = &c->pc.p.queue[0]-1;
00532     for (int i=0; i<=PropCost::AC_MAX; i++)
00533       c->pc.p.queue[i].init();
00534     // Copy propagation only data
00535     c->pc.p.n_sub = pc.p.n_sub;
00536     c->pc.p.branch_id = pc.p.branch_id;
00537     return c;
00538   }
00539 
00540   void
00541   Space::constrain(const Space&) {
00542   }
00543 
00544   void
00545   Space::master(unsigned long int, const Space*) {
00546   }
00547 
00548   void
00549   Space::slave(unsigned long int, const Space*) {
00550   }
00551 
00552   void
00553   LocalObject::fwdcopy(Space& home, bool share) {
00554     ActorLink::cast(this)->prev(copy(home,share));
00555     next(home.pc.c.local);
00556     home.pc.c.local = this;
00557   }
00558 
00559   void
00560   Choice::archive(Archive& e) const {
00561     e << id();
00562   }
00563 
00564   void
00565   Space::afc_decay(double d) {
00566     afc_enable();
00567     // Commit outstanding decay operations
00568     if (gafc.decay() != 1.0)
00569       for (Propagators p(*this); p(); ++p)
00570         (void) gafc.afc(p.propagator().gafc);
00571     gafc.decay(d);
00572   }
00573 
00574 
00575 }
00576 
00577 // STATISTICS: kernel-core