Generated on Fri Mar 20 15:56:17 2015 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: 2015-01-05 07:32:41 +0100 (Mon, 05 Jan 2015) $ by $Author: tack $
00011  *     $Revision: 14336 $
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 #ifdef __GNUC__
00060 
00061   Actor::~Actor(void) {}
00062 #endif
00063 
00064 
00065 
00066   /*
00067    * Propagator
00068    *
00069    */
00070   ExecStatus
00071   Propagator::advise(Space&, Advisor&, const Delta&) {
00072     assert(false);
00073     return ES_FAILED;
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)
00115     : sm(new SharedMemory), mm(sm), _wmp_afc(0U) {
00116 #ifdef GECODE_HAS_VAR_DISPOSE
00117     for (int i=0; i<AllVarConf::idx_d; i++)
00118       _vars_d[i] = NULL;
00119 #endif
00120     // Initialize propagator and brancher links
00121     pl.init();
00122     bl.init();
00123     b_status = b_commit = Brancher::cast(&bl);
00124     // Initialize array for forced deletion to be empty
00125     d_fst = d_cur = d_lst = NULL;
00126     // Initialize space as stable but not failed
00127     pc.p.active = &pc.p.queue[0]-1;
00128     // Initialize propagator queues
00129     for (int i=0; i<=PropCost::AC_MAX; i++)
00130       pc.p.queue[i].init();
00131     pc.p.branch_id = reserved_branch_id+1;
00132     pc.p.n_sub = 0;
00133   }
00134 
00135   void
00136   Space::notice(Actor& a, ActorProperty p, bool duplicate) {
00137     if (p & AP_DISPOSE) {
00138       if (duplicate && (d_fst != NULL)) {
00139         for (Actor** f = d_fst; f < d_cur; f++)
00140           if (&a == *f)
00141             return;
00142       }
00143       if (d_cur == d_lst) {
00144         // Resize
00145         if (d_fst == NULL) {
00146           // Create new array
00147           d_fst = alloc<Actor*>(4);
00148           d_cur = d_fst;
00149           d_lst = d_fst+4;
00150         } else {
00151           // Resize existing array
00152           unsigned int n = static_cast<unsigned int>(d_lst - d_fst);
00153           assert(n != 0);
00154           d_fst = realloc<Actor*>(d_fst,n,2*n);
00155           d_cur = d_fst+n;
00156           d_lst = d_fst+2*n;
00157         }
00158       }
00159       *(d_cur++) = &a;
00160     } else if (p & AP_WEAKLY) {
00161       if (wmp() == 0)
00162         wmp(2);
00163       else
00164         wmp(wmp()+1);
00165     }
00166   }
00167 
00168   void
00169   Space::ignore(Actor& a, ActorProperty p, bool duplicate) {
00170     if (p & AP_DISPOSE) {
00171       // Check wether array has already been discarded as space
00172       // deletion is already in progress
00173       if (d_fst == NULL)
00174         return;
00175       Actor** f = d_fst;
00176       if (duplicate) {
00177         while (f < d_cur)
00178           if (&a == *f)
00179             break;
00180           else
00181             f++;
00182         if (f == d_cur)
00183           return;
00184       } else {
00185         while (&a != *f)
00186           f++;
00187       }
00188       *f = *(--d_cur);
00189     } else if (p & AP_WEAKLY) {
00190       assert(wmp() > 1U);
00191       wmp(wmp()-1);
00192     }
00193   }
00194 
00195   unsigned int
00196   Space::propagators(void) const {
00197     unsigned int n = 0;
00198     for (Propagators p(*this); p(); ++p)
00199       n++;
00200     return n;
00201   }
00202 
00203   unsigned int
00204   Space::branchers(void) const {
00205     unsigned int n = 0;
00206     for (Branchers b(*this); b(); ++b)
00207       n++;
00208     return n;
00209   }
00210 
00211   void
00212   Space::flush(void) {
00213     // Flush malloc cache
00214     sm->flush();
00215   }
00216 
00217   Space::~Space(void) {
00218     // Mark space as failed
00219     fail();
00220     // Delete actors that must be deleted
00221     {
00222       Actor** a = d_fst;
00223       Actor** e = d_cur;
00224       // So that d_unforce knows that deletion is in progress
00225       d_fst = NULL;
00226       while (a < e) {
00227         (void) (*a)->dispose(*this);
00228         a++;
00229       }
00230     }
00231 #ifdef GECODE_HAS_VAR_DISPOSE
00232     // Delete variables that were registered for disposal
00233     for (int i=AllVarConf::idx_d; i--;)
00234       if (_vars_d[i] != NULL)
00235         vd[i]->dispose(*this, _vars_d[i]);
00236 #endif
00237     // Release memory from memory manager
00238     mm.release(sm);
00239     // Release shared memory
00240     if (sm->release())
00241       delete sm;
00242   }
00243 
00244 
00245 
00246   /*
00247    * Space: propagation
00248    *
00249    */
00250 
00251   SpaceStatus
00252   Space::status(StatusStatistics& stat) {
00253     SpaceStatus s = SS_FAILED;
00254     // Check whether space is failed
00255     if (failed()) {
00256       s = SS_FAILED; goto exit;
00257     }
00258     assert(pc.p.active <= &pc.p.queue[PropCost::AC_MAX+1]);
00259     // Check whether space is stable but not failed
00260     if (pc.p.active >= &pc.p.queue[0]) {
00261       Propagator* p;
00262       ModEventDelta med_o;
00263       goto unstable;
00264     execute:
00265       stat.propagate++;
00266       // Keep old modification event delta
00267       med_o = p->u.med;
00268       // Clear med but leave propagator in queue
00269       p->u.med = 0;
00270       switch (p->propagate(*this,med_o)) {
00271       case ES_FAILED:
00272         // Count failure
00273         if (afc_enabled())
00274           gafc.fail(p->gafc);
00275         // Mark as failed
00276         fail(); s = SS_FAILED; goto exit;
00277       case ES_NOFIX:
00278         // Find next, if possible
00279         if (p->u.med != 0) {
00280         unstable:
00281           // There is at least one propagator in a queue
00282           do {
00283             assert(pc.p.active >= &pc.p.queue[0]);
00284             // First propagator or link back to queue
00285             ActorLink* fst = pc.p.active->next();
00286             if (pc.p.active != fst) {
00287               p = Propagator::cast(fst);
00288               goto execute;
00289             }
00290             pc.p.active--;
00291           } while (true);
00292           GECODE_NEVER;
00293         }
00294         // Fall through
00295       case ES_FIX:
00296         // Clear med and put into idle queue
00297         p->u.med = 0; p->unlink(); pl.head(p);
00298       stable_or_unstable:
00299         // There might be a propagator in the queue
00300         do {
00301           assert(pc.p.active >= &pc.p.queue[0]);
00302           // First propagator or link back to queue
00303           ActorLink* fst = pc.p.active->next();
00304           if (pc.p.active != fst) {
00305             p = Propagator::cast(fst);
00306             goto execute;
00307           }
00308         } while (--pc.p.active >= &pc.p.queue[0]);
00309         assert(pc.p.active < &pc.p.queue[0]);
00310         goto stable;
00311       case __ES_SUBSUMED:
00312         p->unlink(); rfree(p,p->u.size);
00313         goto stable_or_unstable;
00314       case __ES_PARTIAL:
00315         // Schedule propagator with specified propagator events
00316         assert(p->u.med != 0);
00317         enqueue(p);
00318         goto unstable;
00319       default:
00320         GECODE_NEVER;
00321       }
00322     }
00323   stable:
00324     /*
00325      * Find the next brancher that has still alternatives left
00326      *
00327      * It is important to note that branchers reporting to have no more
00328      * alternatives left cannot be deleted. They cannot be deleted
00329      * as there might be choices to be used in commit
00330      * that refer to one of these branchers. This e.g. happens when
00331      * we combine branch-and-bound search with adaptive recomputation: during
00332      * recomputation, a copy is constrained to be better than the currently
00333      * best solution, then the first half of the choices are posted,
00334      * and a fixpoint computed (for storing in the middle of the path). Then
00335      * the remaining choices are posted, and because of the additional
00336      * constraints that the space must be better than the previous solution,
00337      * the corresponding Branchers may already have no alternatives left.
00338      *
00339      * The same situation may arise due to weakly monotonic propagators.
00340      *
00341      * A brancher reporting that no more alternatives exist is exhausted.
00342      * All exhausted branchers will be left of the current pointer b_status.
00343      * Only when it is known that no more choices
00344      * can be used for commit an exhausted brancher can actually be deleted.
00345      * This becomes known when choice is called.
00346      */
00347     while (b_status != Brancher::cast(&bl))
00348       if (b_status->status(*this)) {
00349         // Brancher still has choices to generate
00350         s = SS_BRANCH; goto exit;
00351       } else {
00352         // Brancher is exhausted
00353         b_status = Brancher::cast(b_status->next());
00354       }
00355     // No brancher with alternatives left, space is solved
00356     s = SS_SOLVED;
00357   exit:
00358     stat.wmp = (wmp() > 0U);
00359     if (wmp() == 1U) 
00360       wmp(0U);
00361     return s;
00362   }
00363 
00364 
00365   const Choice*
00366   Space::choice(void) {
00367     if (!stable())
00368       throw SpaceNotStable("Space::choice");
00369     if (failed() || (b_status == Brancher::cast(&bl))) {
00370       // There are no more choices to be generated
00371       // Delete all branchers
00372       Brancher* b = Brancher::cast(bl.next()); 
00373       while (b != Brancher::cast(&bl)) {
00374         Brancher* d = b;
00375         b = Brancher::cast(b->next());
00376         rfree(d,d->dispose(*this));
00377       }
00378       bl.init();
00379       b_status = b_commit = Brancher::cast(&bl);
00380       return NULL;
00381     }
00382     /*
00383      * The call to choice() says that no older choices
00384      * can be used. Hence, all branchers that are exhausted can be deleted.
00385      */
00386     Brancher* b = Brancher::cast(bl.next());
00387     while (b != b_status) {
00388       Brancher* d = b;
00389       b = Brancher::cast(b->next());
00390       d->unlink();
00391       rfree(d,d->dispose(*this));
00392     }
00393     // Make sure that b_commit does not point to a deleted brancher!
00394     b_commit = b_status;
00395     return b_status->choice(*this);
00396   }
00397 
00398   const Choice*
00399   Space::choice(Archive& e) const {
00400     unsigned int id; e >> id;
00401     Brancher* b_cur = Brancher::cast(bl.next());
00402     while (b_cur != Brancher::cast(&bl)) {
00403       if (id == b_cur->id())
00404         return b_cur->choice(*this,e);
00405       b_cur = Brancher::cast(b_cur->next());
00406     }
00407     throw SpaceNoBrancher("Space::choice");
00408   }
00409 
00410   void
00411   Space::_commit(const Choice& c, unsigned int a) {
00412     if (a >= c.alternatives())
00413       throw SpaceIllegalAlternative("Space::commit");
00414     if (failed())
00415       return;
00416     if (Brancher* b = brancher(c._id)) {
00417       // There is a matching brancher
00418       if (b->commit(*this,c,a) == ES_FAILED)
00419         fail();
00420     } else {
00421       // There is no matching brancher!
00422       throw SpaceNoBrancher("Space::commit");
00423     }
00424   }
00425 
00426   void
00427   Space::_trycommit(const Choice& c, unsigned int a) {
00428     if (a >= c.alternatives())
00429       throw SpaceIllegalAlternative("Space::commit");
00430     if (failed())
00431       return;
00432     if (Brancher* b = brancher(c._id)) {
00433       // There is a matching brancher
00434       if (b->commit(*this,c,a) == ES_FAILED)
00435         fail();
00436     }
00437   }
00438 
00439   NGL*
00440   Space::ngl(const Choice& c, unsigned int a) {
00441     if (a >= c.alternatives())
00442       throw SpaceIllegalAlternative("Space::ngl");
00443     if (failed())
00444       return NULL;
00445     if (Brancher* b = brancher(c._id)) {
00446       // There is a matching brancher
00447       return b->ngl(*this,c,a);
00448     } else {
00449       return NULL;
00450     }
00451   }
00452 
00453   void
00454   Space::print(const Choice& c, unsigned int a, std::ostream& o) const {
00455     if (a >= c.alternatives())
00456       throw SpaceIllegalAlternative("Space::print");
00457     if (failed())
00458       return;
00459     if (Brancher* b = const_cast<Space&>(*this).brancher(c._id)) {
00460       // There is a matching brancher
00461       b->print(*this,c,a,o);
00462     } else {
00463       // There is no matching brancher!
00464       throw SpaceNoBrancher("Space::print");
00465     }
00466   }
00467 
00468   void
00469   Space::kill_brancher(unsigned int id) {
00470     if (failed())
00471       return;
00472     for (Brancher* b = Brancher::cast(bl.next()); 
00473          b != Brancher::cast(&bl); b = Brancher::cast(b->next()))
00474       if (b->id() == id) {
00475         // Make sure that neither b_status nor b_commit does not point to b
00476         if (b_commit == b)
00477           b_commit = Brancher::cast(b->next());
00478         if (b_status == b)
00479           b_status = Brancher::cast(b->next());
00480         b->unlink();
00481         rfree(b,b->dispose(*this));
00482         return;
00483       }
00484   }
00485 
00486 
00487 
00488 
00489   /*
00490    * Space cloning
00491    *
00492    * Cloning is performed in two steps:
00493    *  - The space itself is copied by the copy constructor. This
00494    *    also copies all propagators, branchers, and variables.
00495    *    The copied variables are recorded.
00496    *  - In the second step the dependency information of the recorded
00497    *    variables is updated and their forwarding information is reset.
00498    *
00499    */
00500   Space::Space(bool share, Space& s)
00501     : sm(s.sm->copy(share)), 
00502       mm(sm,s.mm,s.pc.p.n_sub*sizeof(Propagator**)),
00503       gafc(s.gafc),
00504       d_fst(&Actor::sentinel),
00505       _wmp_afc(s._wmp_afc) {
00506 #ifdef GECODE_HAS_VAR_DISPOSE
00507     for (int i=0; i<AllVarConf::idx_d; i++)
00508       _vars_d[i] = NULL;
00509 #endif
00510     for (int i=0; i<AllVarConf::idx_c; i++)
00511       pc.c.vars_u[i] = NULL;
00512     pc.c.vars_noidx = NULL;
00513     pc.c.shared = NULL;
00514     pc.c.local = NULL;
00515     // Copy all propagators
00516     {
00517       ActorLink* p = &pl;
00518       ActorLink* e = &s.pl;
00519       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00520         Actor* c = Actor::cast(a)->copy(*this,share);
00521         // Link copied actor
00522         p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p);
00523         // Note that forwarding is done in the constructors
00524         p = c;
00525       }
00526       // Link last actor
00527       p->next(&pl); pl.prev(p);
00528     }
00529     // Copy all branchers
00530     {
00531       ActorLink* p = &bl;
00532       ActorLink* e = &s.bl;
00533       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00534         Actor* c = Actor::cast(a)->copy(*this,share);
00535         // Link copied actor
00536         p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p);
00537         // Note that forwarding is done in the constructors
00538         p = c;
00539       }
00540       // Link last actor
00541       p->next(&bl); bl.prev(p);
00542     }
00543     // Setup brancher pointers
00544     if (s.b_status == &s.bl) {
00545       b_status = Brancher::cast(&bl);
00546     } else {
00547       b_status = Brancher::cast(s.b_status->prev());
00548     }
00549     if (s.b_commit == &s.bl) {
00550       b_commit = Brancher::cast(&bl);
00551     } else {
00552       b_commit = Brancher::cast(s.b_commit->prev());
00553     }
00554   }
00555 
00556   Space*
00557   Space::_clone(bool share) {
00558     if (failed())
00559       throw SpaceFailed("Space::clone");
00560     if (!stable())
00561       throw SpaceNotStable("Space::clone");
00562 
00563     // Copy all data structures (which in turn will invoke the constructor)
00564     Space* c = copy(share);
00565 
00566     if (c->d_fst != &Actor::sentinel)
00567       throw SpaceNotCloned("Space::clone");
00568 
00569     // Setup array for actor disposal in c
00570     {
00571       unsigned int n = static_cast<unsigned int>(d_cur - d_fst);
00572       if (n == 0) {
00573         // No actors
00574         c->d_fst = c->d_cur = c->d_lst = NULL;
00575       } else {
00576         // Leave one entry free
00577         c->d_fst = c->alloc<Actor*>(n+1);
00578         c->d_cur = c->d_fst;
00579         c->d_lst = c->d_fst+n+1;
00580         for (Actor** d_fst_iter = d_fst; d_fst_iter != d_cur; d_fst_iter++) {
00581           if ((*d_fst_iter)->prev())
00582             *(c->d_cur++) = Actor::cast((*d_fst_iter)->prev());
00583         }
00584       }
00585     }
00586 
00587     // Update variables without indexing structure
00588     VarImp<NoIdxVarImpConf>* x =
00589       static_cast<VarImp<NoIdxVarImpConf>*>(c->pc.c.vars_noidx);
00590     while (x != NULL) {
00591       VarImp<NoIdxVarImpConf>* n = x->next();
00592       x->b.base = NULL; x->u.idx[0] = 0;
00593       if (sizeof(ActorLink**) > sizeof(unsigned int))
00594         *(1+&x->u.idx[0]) = 0;
00595       x = n;
00596     }
00597     // Update variables with indexing structure
00598     c->update(static_cast<ActorLink**>(c->mm.subscriptions()));
00599 
00600     // Re-establish prev links (reset forwarding information)
00601     {
00602       ActorLink* p_a = &pl;
00603       ActorLink* c_a = p_a->next();
00604       // First update propagators and advisors
00605       while (c_a != &pl) {
00606         Propagator* p = Propagator::cast(c_a);
00607         if (p->u.advisors != NULL) {
00608           ActorLink* a = p->u.advisors;
00609           p->u.advisors = NULL;
00610           do {
00611             a->prev(p); a = a->next();
00612           } while (a != NULL);
00613         }
00614         c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00615       }
00616     }
00617     {
00618       ActorLink* p_a = &bl;
00619       ActorLink* c_a = p_a->next();
00620       // Update branchers
00621       while (c_a != &bl) {
00622         c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00623       }
00624     }
00625 
00626     // Reset links for shared objects
00627     for (SharedHandle::Object* s = c->pc.c.shared; s != NULL; s = s->next)
00628       s->fwd = NULL;
00629 
00630     // Reset links for local objects
00631     for (ActorLink* l = c->pc.c.local; l != NULL; l = l->next())
00632       l->prev(NULL);
00633 
00634     // Initialize propagator queue
00635     c->pc.p.active = &c->pc.p.queue[0]-1;
00636     for (int i=0; i<=PropCost::AC_MAX; i++)
00637       c->pc.p.queue[i].init();
00638     // Copy propagation only data
00639     c->pc.p.n_sub = pc.p.n_sub;
00640     c->pc.p.branch_id = pc.p.branch_id;
00641     return c;
00642   }
00643 
00644   void
00645   Space::constrain(const Space&) {
00646   }
00647 
00648   bool
00649   Space::master(const CRI& cri) {
00650     if (cri.last() != NULL)
00651       constrain(*cri.last());
00652     cri.nogoods().post(*this);
00653     // Perform a restart even if a solution has been found
00654     return true;
00655   }
00656 
00657   bool
00658   Space::slave(const CRI&) {
00659     return true;
00660   }
00661 
00662   void
00663   LocalObject::fwdcopy(Space& home, bool share) {
00664     ActorLink::cast(this)->prev(copy(home,share));
00665     next(home.pc.c.local);
00666     home.pc.c.local = this;
00667   }
00668 
00669   void
00670   Choice::archive(Archive& e) const {
00671     e << id();
00672   }
00673 
00674   void
00675   Space::afc_decay(double d) {
00676     afc_enable();
00677     // Commit outstanding decay operations
00678     if (gafc.decay() != 1.0)
00679       for (Propagators p(*this); p(); ++p)
00680         (void) gafc.afc(p.propagator().gafc);
00681     gafc.decay(d);
00682   }
00683 
00684   void
00685   Space::afc_set(double a) {
00686     afc_enable();
00687     for (Propagators p(*this); p(); ++p)
00688       gafc.set(p.propagator().gafc,a);
00689   }
00690 
00691 
00692   bool
00693   NGL::notice(void) const {
00694     return false;
00695   }
00696 
00697 }
00698 
00699 // STATISTICS: kernel-core