Generated on Mon Aug 25 11:35:39 2008 for Gecode by doxygen 1.5.6

core.cc

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: 2008-07-11 10:27:28 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00011  *     $Revision: 7332 $
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   VarDisposerBase::dispose(Space*,VarImpBase*) {}
00048 
00049   VarDisposerBase::~VarDisposerBase(void) {}
00050 
00051 
00052 
00053   /*
00054    * Actor
00055    *
00056    */
00057   Reflection::ActorSpec
00058   Actor::spec(const Space*, Reflection::VarMap&) const {
00059     throw Reflection::NoReflectionDefinedException();
00060   }
00061 
00062   size_t
00063   Actor::allocated(void) const {
00064     return 0;
00065   }
00066 
00067 #ifdef __GNUC__
00069   Actor::~Actor(void) {}
00070 #endif
00071 
00072 
00073 
00074   /*
00075    * Propagator
00076    *
00077    */
00078   ExecStatus 
00079   Propagator::advise(Space*, Advisor*, const Delta*) {
00080     assert(false);
00081     return ES_FAILED;
00082   }
00083 
00084 
00085 
00086   /*
00087    * Branching
00088    *
00089    */
00090   Reflection::BranchingSpec
00091   Branching::branchingSpec(const Space*,
00092                            Reflection::VarMap&, const BranchingDesc*) const {
00093     throw Reflection::NoReflectionDefinedException();
00094   }
00095 
00096 
00097 
00098   /*
00099    * Space: Misc
00100    *
00101    */
00102   unsigned long int Space::unused_uli;
00103 
00104 #ifdef GECODE_HAS_VAR_DISPOSE
00105   VarDisposerBase* Space::vd[AllVarConf::idx_d];
00106 #endif
00107 
00108   Space::Space(void) {
00109 #ifdef GECODE_HAS_VAR_DISPOSE
00110     for (int i=0; i<AllVarConf::idx_d; i++)
00111       _vars_d[i] = NULL;
00112 #endif
00113     // Initialize actor and branching links
00114     a_actors.init();
00115     b_status = b_commit = Branching::cast(&a_actors);
00116     // Initialize array for forced deletion to be empty
00117     d_fst = d_cur = d_lst = NULL;
00118     // Initialize propagator queues
00119     pc.p.active = &pc.p.queue[0]-1;
00120     for (int i=0; i<=PC_MAX; i++)
00121       pc.p.queue[i].init();
00122     pc.p.branch_id = 0;
00123     pc.p.n_sub = 0;
00124   }
00125 
00126   size_t
00127   Space::allocated(void) const {
00128     size_t s = mm.allocated();
00129     Actor** a = d_fst;
00130     Actor** e = d_cur;
00131     while (a < e) {
00132       s += (*a)->allocated(); a++;
00133     }
00134     return s;
00135   }
00136 
00137   void
00138   Space::d_resize(void) {
00139     if (d_fst == NULL) {
00140       // Create new array
00141       d_fst = static_cast<Actor**>(alloc(4*sizeof(Actor*)));
00142       d_cur = d_fst;
00143       d_lst = d_fst+4;
00144     } else {
00145       // Resize existing array
00146       ptrdiff_t n = d_lst - d_fst;
00147       assert(n != 0);
00148       Actor** a = static_cast<Actor**>(alloc(2*n*sizeof(Actor*)));
00149       memcpy(a, d_fst, n*sizeof(Actor*));
00150       reuse(d_fst,n*sizeof(Actor*));
00151       d_fst = a;
00152       d_cur = a+n;
00153       d_lst = a+2*n;
00154     }
00155   }
00156   
00157   unsigned int
00158   Space::propagators(void) const {
00159     unsigned int n = 0;
00160     for (ActorLink* q = pc.p.active; q >= &pc.p.queue[0]; q--)
00161       for (ActorLink* a = q->next(); a != q; a = a->next())
00162         n++;
00163     for (ActorLink* a = a_actors.next(); 
00164          Branching::cast(a) != b_commit; a = a->next())
00165       n++;
00166     return n;
00167   }
00168 
00169   unsigned int
00170   Space::branchings(void) const {
00171     unsigned int n = 0;
00172     for (ActorLink* a = Branching::cast(b_status); 
00173          a != &a_actors; a = a->next())
00174       n++;
00175     return n;
00176   }
00177 
00178   void
00179   Space::getVars(Reflection::VarMap&, bool) {}
00180 
00181   Reflection::BranchingSpec
00182   Space::branchingSpec(Reflection::VarMap& m, const BranchingDesc* d) const {
00183     const Branching* b = b_commit;
00184     while ((b != Branching::cast(&a_actors)) && (d->_id != b->id))
00185       b = Branching::cast(b->next());
00186     if (b == Branching::cast(&a_actors))
00187       throw SpaceNoBranching();
00188     return b->branchingSpec(this, m, d);
00189   }
00190 
00191   Space::~Space(void) {
00192     // Mark space as failed
00193     fail();
00194     // Delete actors that must be deleted
00195     {
00196       Actor** a = d_fst;
00197       Actor** e = d_cur;
00198       // So that d_unforce knows that deletion is in progress
00199       d_fst = NULL;
00200       while (a < e) {
00201         (void) (*a)->dispose(this);
00202         a++;
00203       }
00204     }
00205 #ifdef GECODE_HAS_VAR_DISPOSE
00206     // Delete variables that were registered for disposal
00207     for (int i=AllVarConf::idx_d; i--;)
00208       if (_vars_d[i] != NULL)
00209         vd[i]->dispose(this, _vars_d[i]);
00210 #endif
00211   }
00212 
00213 
00214 
00215   /*
00216    * Space: propagation
00217    *
00218    */
00219   SpaceStatus
00220   Space::status(unsigned long int& pn) {
00221     if (failed())
00222       return SS_FAILED;
00223     if (!stable()) {
00224       assert(pc.p.active >= &pc.p.queue[0]);
00225       Propagator* p;
00226       ModEventDelta med_o;
00227       goto unstable;
00228     execute:
00229       pn++;
00230       // Keep old modification event delta
00231       med_o = p->u.med;
00232       // Clear med but leave propagator in queue
00233       p->u.med = 0;
00234       switch (p->propagate(this,med_o)) {
00235       case ES_FAILED:
00236         fail(); 
00237         return SS_FAILED;
00238       case ES_NOFIX:
00239         // Find next, if possible
00240         if (p->u.med != 0) {
00241         unstable:
00242           // There is at least one propagator in a queue
00243           do {
00244             assert(pc.p.active >= &pc.p.queue[0]);
00245             // First propagator or link back to queue
00246             ActorLink* fst = pc.p.active->next();
00247             if (pc.p.active != fst) {
00248               p = Propagator::cast(fst);
00249               goto execute;
00250             }
00251             pc.p.active--;
00252           } while (true);
00253           GECODE_NEVER;
00254         }
00255         // Fall through
00256       case ES_FIX:
00257         // Clear med and put into idle queue
00258         p->u.med = 0; p->unlink(); a_actors.head(p);
00259       stable_or_unstable:
00260         // There might be a propagator in the queue
00261         do {
00262           assert(pc.p.active >= &pc.p.queue[0]);
00263           // First propagator or link back to queue
00264           ActorLink* fst = pc.p.active->next();
00265           if (pc.p.active != fst) {
00266             p = Propagator::cast(fst);
00267             goto execute;
00268           }
00269         } while (--pc.p.active >= &pc.p.queue[0]);
00270         assert(pc.p.active < &pc.p.queue[0]);
00271         goto stable;
00272       case __ES_SUBSUMED:
00273         p->unlink(); reuse(p,p->u.size);
00274         goto stable_or_unstable;
00275       case __ES_PARTIAL:
00276         // Schedule propagator with specified propagator events
00277         assert(p->u.med != 0);
00278         enqueue(p);
00279         goto unstable;
00280       default:
00281         GECODE_NEVER;
00282       }
00283     }
00284   stable:
00285     /*
00286      * Find the next branching that has still alternatives left
00287      *
00288      * It is important to note that branchings reporting to have no more
00289      * alternatives left can not be deleted. They can not be deleted
00290      * as there might be branching descriptions to be used in commit
00291      * that refer to one of these branchings. This e.g. happens when
00292      * we combine branch-and-bound search with adaptive recomputation: during 
00293      * recomputation, a copy is constrained to be better than the currently 
00294      * best solution, then the first half of the BranchingDescs is posted,
00295      * and a fixpoint computed (for storing in the middle of the path). Then
00296      * the remaining BranchingDescs are posted, and because of the additional
00297      * constraints that the space must be better than the previous solution,
00298      * the corresponding Branchings may already have no alternatives left.
00299      *
00300      * A branching reporting that no more alternatives exist will eventually
00301      * be deleted in commit. It will be deleted if the first branching
00302      * description is used in commit that does not refer to this branching.
00303      * As we insist that branching descriptions are used in order of
00304      * creation, all further branching descriptions cannot refer to this
00305      * branching.
00306      *
00307      */
00308     while (b_status != Branching::cast(&a_actors)) {
00309       if (b_status->status(this))
00310         return SS_BRANCH;
00311       b_status = Branching::cast(b_status->next());
00312     }
00313     // No branching with alternatives left, space is solved
00314     return SS_SOLVED;
00315   }
00316 
00317 
00318   void
00319   Space::commit(const BranchingDesc* d, unsigned int a) {
00320     if (failed())
00321       return;
00322     /*
00323      * This relies on the fact that branching descriptions must be
00324      * used in the order of creation. If a branching description
00325      * with an id different from the id of the current branching
00326      * is used, it is clear that the current branching can be discarded
00327      * as all of its descriptions must have been used already.
00328      *
00329      */
00330     while ((b_commit != Branching::cast(&a_actors)) && 
00331            (d->_id != b_commit->id)) {
00332       Branching* b = b_commit;
00333       b_commit = Branching::cast(b_commit->next());
00334       if (b == b_status)
00335         b_status = b_commit;
00336       b->unlink(); 
00337       reuse(b,b->dispose(this));
00338     }
00339     if (b_commit == Branching::cast(&a_actors))
00340       throw SpaceNoBranching();
00341     if (a >= d->alternatives())
00342       throw SpaceIllegalAlternative();
00343     if (b_commit->commit(this,d,a) == ES_FAILED)
00344       fail();
00345   }
00346 
00347 
00348 
00349   /*
00350    * Space cloning
00351    *
00352    * Cloning is performed in two steps:
00353    *  - The space itself is copied by the copy constructor. This
00354    *    also copies all propagators, branchings, and variables.
00355    *    The copied variables are recorded.
00356    *  - In the second step the dependency information of the recorded
00357    *    variables is updated and their forwarding information is reset.
00358    *
00359    */
00360   Space::Space(bool share, Space& s) 
00361     : mm(s.mm,s.pc.p.n_sub*sizeof(Propagator**)) {
00362 #ifdef GECODE_HAS_VAR_DISPOSE
00363     for (int i=0; i<AllVarConf::idx_d; i++)
00364       _vars_d[i] = NULL;
00365 #endif
00366     for (int i=0; i<AllVarConf::idx_c; i++)
00367       pc.c.vars_u[i] = NULL;
00368     pc.c.vars_noidx = NULL;
00369     pc.c.shared = NULL;
00370     // Copy all actors
00371     {
00372       ActorLink* p = &a_actors;
00373       ActorLink* e = &s.a_actors;
00374       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00375         Actor* c = Actor::cast(a)->copy(this,share);
00376         // Link copied actor
00377         p->next(ActorLink::cast(c)); ActorLink::cast(c)->prev(p);
00378         // Note that forwarding is done in the constructors
00379         p = c;
00380       }
00381       // Link last actor
00382       p->next(&a_actors); a_actors.prev(p);
00383     }
00384     // Setup array for actor disposal
00385     {
00386       ptrdiff_t n = s.d_cur - s.d_fst;
00387       if (n == 0) {
00388         // No actors
00389         d_fst = d_cur = d_lst = NULL;
00390       } else {
00391         // Leave one entry free
00392         Actor** a = static_cast<Actor**>(alloc((n+1)*sizeof(Actor*)));
00393         d_fst = a;
00394         d_cur = a+n;
00395         d_lst = a+n+1;
00396         Actor** f = s.d_fst;
00397         do {
00398           n--;
00399           a[n] = Actor::cast(f[n]->prev());
00400         } while (n != 0);
00401       }
00402     }
00403     // Setup branching pointers
00404     if (s.b_status == &s.a_actors) {
00405       b_status = Branching::cast(&a_actors);
00406     } else {
00407       b_status = Branching::cast(s.b_status->prev());
00408     }
00409     if (s.b_commit == &s.a_actors) {
00410       b_commit = Branching::cast(&a_actors);
00411     } else {
00412       b_commit = Branching::cast(s.b_commit->prev());
00413     }
00414   }
00415 
00416   Space*
00417   Space::clone(bool share) {
00418     if (failed())
00419       throw SpaceFailed("Space::clone");
00420     if (!stable())
00421       throw SpaceNotStable("Space::clone");
00422 
00423     // Copy all data structures (which in turn will invoke the constructor)
00424     Space* c = copy(share);
00425 
00426     // Update variables without indexing structure
00427     VarImp<NoIdxVarImpConf>* x = 
00428       static_cast<VarImp<NoIdxVarImpConf>*>(c->pc.c.vars_noidx);
00429     while (x != NULL) {
00430       VarImp<NoIdxVarImpConf>* n = x->next();
00431       x->idx[0] = x->idx[1] = NULL;
00432       x = n;
00433     }
00434     // Update variables with indexing structure
00435     c->update(static_cast<ActorLink**>(c->mm.subscriptions()));
00436 
00437     // Re-establish prev links (reset forwarding information)
00438     ActorLink* p_a = &a_actors;
00439     ActorLink* c_a = p_a->next();
00440     // First update propagators and check for advisors that also must be reset
00441     while (c_a != b_commit) {
00442       Propagator* p = Propagator::cast(c_a);
00443       if (p->u.advisors != NULL) {
00444         ActorLink* a = p->u.advisors;
00445         p->u.advisors = NULL;
00446         do {
00447           a->prev(p); a = a->next();
00448         } while (a != NULL);
00449       }
00450       c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00451     }
00452     // Update branchings
00453     while (c_a != &a_actors) {
00454       c_a->prev(p_a); p_a = c_a; c_a = c_a->next();
00455     }
00456     assert(c_a->prev() == p_a);
00457 
00458     // Reset links for shared objects
00459     for (SharedHandle::Object* s = c->pc.c.shared; s != NULL; s = s->next)
00460       s->fwd = NULL;
00461 
00462     // Initialize propagator queue
00463     c->pc.p.active = &c->pc.p.queue[0]-1;
00464     for (int i=0; i<=PC_MAX; i++)
00465       c->pc.p.queue[i].init();
00466     // Copy propagation only data
00467     c->pc.p.n_sub = pc.p.n_sub;
00468     c->pc.p.branch_id = pc.p.branch_id;
00469     return c;
00470   }
00471 
00472 }
00473 
00474 // STATISTICS: kernel-core