Generated on Wed Nov 1 15:04:42 2006 for Gecode by doxygen 1.4.5

core.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Christian Schulte, 2002
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-08-21 11:34:39 +0200 (Mon, 21 Aug 2006) $ by $Author: tack $
00010  *     $Revision: 3550 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
00019  *
00020  */
00021 
00022 #include "gecode/kernel.hh"
00023 
00024 namespace Gecode {
00025 
00026   unsigned long int Space::unused_uli;
00027 
00028   /*
00029    * Spaces
00030    *
00031    */
00032 
00033   VarTypeProcessorBase* Space::vtp[VTI_LAST];
00034 
00035   VarTypeProcessorBase::~VarTypeProcessorBase(void) {}
00036 
00037   Space::Space(void) {
00038     // Initialize variable entry points
00039     for (int i=0; i<VTI_LAST; i++) {
00040       vars[i]=NULL;
00041       vars_dispose[i]=NULL;
00042     }
00043     vars_noidx = NULL;
00044     // Initialize propagator pool
00045     pool_next = 0;
00046     for (int i=0; i<=PC_MAX; i++)
00047       pool[i].init();
00048     // Initialize actor and branching links
00049     a_actors.init();
00050     a_actors.init_delete();
00051     b_status = static_cast<Branching*>(&a_actors);
00052     b_commit = static_cast<Branching*>(&a_actors);
00053     n_sub = 0;
00054     sub = NULL;
00055   }
00056 
00057 
00058 
00059   /*
00060    * Space deletion
00061    *
00062    */
00063 
00064   void
00065   Actor::flush(void) {}
00066 
00067   size_t
00068   Actor::cached(void) const {
00069     return 0;
00070   }
00071 
00072   void
00073   Space::flush(void) {
00074     // Flush actors registered for deletion
00075     ActorDeleteLink* e = &a_actors;
00076     ActorDeleteLink* a = e->next_delete();
00077     while (a != e) {
00078       static_cast<Actor*>(a)->flush(); a = a->next_delete();
00079     }
00080   }
00081 
00082   size_t
00083   Space::cached(void) const {
00084     size_t s = 0;
00085     const ActorDeleteLink* e = &a_actors;
00086     const ActorDeleteLink* a = e->next_delete();
00087     while (a != e) {
00088       s += static_cast<const Actor*>(a)->cached();
00089       a = a->next_delete();
00090     }
00091     return s;
00092   }
00093 
00094   Space::~Space(void) {
00095     // Mark space as failed
00096     fail();
00097     // Delete actors that must be deleted
00098     ActorDeleteLink* e = &a_actors;
00099     ActorDeleteLink* a = e->next_delete();
00100     while (a != e) {
00101       Actor* d = static_cast<Actor*>(a);
00102       a = a->next_delete();
00103       d->dispose(this);
00104     }
00105     // Delete variables that were registered for deletion
00106     for (int vti=VTI_LAST; vti--;)
00107       if (vars_dispose[vti] != NULL)
00108         vtp[vti]->dispose(this, vars_dispose[vti]);
00109     if (sub != NULL)
00110       Memory::free(sub);
00111   }
00112 
00113 
00114   /*
00115    * Performing propagation
00116    *
00117    */
00118 
00119   forceinline void
00120   Space::process(void) {
00121     for (int vti=VTI_LAST; vti--; ) {
00122       VarBase* vs = vars[vti];
00123       if (vs != NULL) {
00124         vars[vti] = NULL; vtp[vti]->process(this,vs);
00125       }
00126     }
00127   }
00128 
00129   forceinline bool
00130   Space::pool_get(Propagator*& p) {
00131     for (int c = pool_next+1; c--; ) {
00132       // Head of the queue
00133       ActorLink* lnk = &pool[c];
00134       // First propagator or link back to queue
00135       ActorLink* fst = lnk->next();
00136       if (lnk != fst) {
00137         pool_next = c;
00138         // Unlink first propagator from queue
00139         ActorLink* snd = fst->next();
00140         lnk->next(snd); snd->prev(lnk);
00141         p = static_cast<Propagator*>(fst);
00142         return true;
00143       }
00144     }
00145     pool_next = 0;
00146     return false;
00147   }
00148 
00149   unsigned long int
00150   Space::propagate(void) {
00151     if (failed())
00152       return 0;
00153     const PropModEvent PME_NONE = 0;
00154     const PropModEvent PME_ASSIGNED  =
00155       ((ME_GEN_ASSIGNED <<  0) | (ME_GEN_ASSIGNED <<  4) |
00156        (ME_GEN_ASSIGNED <<  8) | (ME_GEN_ASSIGNED << 12) |
00157        (ME_GEN_ASSIGNED << 16) | (ME_GEN_ASSIGNED << 20) |
00158        (ME_GEN_ASSIGNED << 24) | (ME_GEN_ASSIGNED << 28));
00159     /*
00160      * Count the number of propagation steps performed
00161      *
00162      */
00163     unsigned long int pn = 0;
00164     /*
00165      * Process modified variables, there might be modified variables
00166      * either from initializing the space or from a commit operation
00167      *
00168      */
00169     process();
00170     Propagator* p;
00171     while (pool_get(p)) {
00172       pn++;
00173       switch (p->propagate(this)) {
00174       case ES_FAILED:
00175         fail();
00176         return pn;
00177       case ES_FIX:
00178         {
00179           // Put propagator in idle queue
00180           propagator(p);
00181           // Prevent that propagator gets rescheduled (turn on all events)
00182           p->pme = PME_ASSIGNED;
00183           process();
00184           p->pme = PME_NONE;
00185         }
00186         break;
00187       case ES_NOFIX:
00188         {
00189           // Propagator is currently in no queue, put in into idle
00190           propagator(p);
00191           p->pme = PME_NONE;
00192           process();
00193         }
00194         break;
00195       case ES_SUBSUMED:
00196         {
00197           // Prevent that propagator gets rescheduled (turn on all events)
00198           p->pme = PME_ASSIGNED;
00199           process();
00200           p->destruct(this);
00201         }
00202         break;
00203       case __ES_FIX_PARTIAL:
00204         {
00205           // Remember the event set to be kept after processing
00206           PropModEvent keep = p->pme;
00207           // Prevent that propagator gets rescheduled (turn on all events)
00208           p->pme = PME_ASSIGNED;
00209           process();
00210           p->pme = keep;
00211           assert(p->pme);
00212           pool_put(p);
00213         }
00214         break;
00215       case __ES_NOFIX_PARTIAL:
00216         {
00217           // Start from the specified propagator events
00218           pool_put(p);
00219           process();
00220         }
00221         break;
00222       default:
00223         GECODE_NEVER;
00224       }
00225     }
00226     return pn;
00227   }
00228 
00229   void
00230   Space::commit(const BranchingDesc* d, unsigned int a) {
00231     if (failed())
00232       return;
00233     /*
00234      * This relies on the fact that branching descriptions must be
00235      * used in the order of creation. If a branching description
00236      * with an id different from the id of the current branching
00237      * is used, it is clear that the current branching can be discarded
00238      * as all of its descriptions must have been used already.
00239      *
00240      */
00241     while ((b_commit != &a_actors) && (d->id != b_commit->id)) {
00242       Branching* b = b_commit;
00243       b_commit = static_cast<Branching*>(b_commit->next());
00244       if (b == b_status)
00245         b_status = b_commit;
00246       b->unlink(); b->destruct(this);
00247     }
00248     if (b_commit == &a_actors)
00249       throw SpaceNoBranching();
00250     if (a >= d->alternatives())
00251       throw SpaceIllegalAlternative();
00252     if (b_commit->commit(this,d,a) == ES_FAILED)
00253       fail();
00254   }
00255 
00256   /*
00257    * Space cloning
00258    *
00259    * Cloning is performed in two steps:
00260    *  - The space itself is copied by the copy constructor. This
00261    *    also copies all propagators, branchings, and variables.
00262    *    The copied variables are recorded by the variable processor.
00263    *  - In the second step the dependency information of the recorded
00264    *    variables is updated and their forwarding information is reset.
00265    *
00266    */
00267 
00268   Space::Space(bool share, Space& s) : mm(s.mm) {
00269     // Initialize variable entry points
00270     for (int i=0; i<VTI_LAST; i++) {
00271       vars[i]=NULL;
00272       vars_dispose[i]=NULL;
00273     }
00274     vars_noidx = NULL;
00275     // Initialize propagator pool
00276     pool_next = 0;
00277     for (int i=0; i<=PC_MAX; i++)
00278       pool[i].init();
00279     // Copy all actors
00280     {
00281       ActorLink* p  = &a_actors;
00282       ActorLink* e  = &s.a_actors;
00283       for (ActorLink* a = e->next(); a != e; a = a->next()) {
00284         ActorLink* c = static_cast<Actor*>(a)->copy(this,share);
00285         // Link copied actor
00286         p->next(c); c->prev(p);
00287         // Forward
00288         a->prev(c);
00289         //
00290         static_cast<ActorDeleteLink*>(c)->init_delete();
00291         p = c;
00292       }
00293       // Link last actor
00294       p->next(&a_actors); a_actors.prev(p);
00295     }
00296     // Setup delete links
00297     {
00298       ActorDeleteLink* p  = &a_actors;
00299       ActorDeleteLink* e  = &s.a_actors;
00300       for (ActorDeleteLink* a = e->next_delete(); a != e;
00301            a = a->next_delete()) {
00302         ActorDeleteLink* c = static_cast<ActorDeleteLink*>(a->prev());
00303         // Link copied actor
00304         p->next_delete(c); c->prev_delete(p);
00305         // Forward
00306         p = c;
00307       }
00308       // Link last actor
00309       p->next_delete(&a_actors); a_actors.prev_delete(p);
00310     }
00311     // Setup branching pointers
00312     if (s.b_status == &s.a_actors) {
00313       b_status = static_cast<Branching*>(&a_actors);
00314     } else {
00315       b_status = static_cast<Branching*>(s.b_status->prev());
00316     }
00317     if (s.b_commit == &s.a_actors) {
00318       b_commit = static_cast<Branching*>(&a_actors);
00319     } else {
00320       b_commit = static_cast<Branching*>(s.b_commit->prev());
00321     }
00322   }
00323 
00324 
00325   /*
00326    * Stage 2: updating variables
00327    *
00328    */
00329 
00331   class __Combine {
00332   public:
00333     ModEvent operator()(ModEvent,ModEvent) {
00334       GECODE_NEVER;
00335       return ME_GEN_ASSIGNED;
00336     }
00337   };
00338 
00339   Space*
00340   Space::clone(bool share, unsigned long int& pn) {
00341     pn += propagate();
00342     if (failed())
00343       throw SpaceFailed("Space::clone");
00344 
00345     /*
00346      * Stage one
00347      *
00348      * Copy all data structures (which in turn will invoke the
00349      * constructor Space::Space.
00350      */
00351     Space* c = copy(share);
00352 
00353     /*
00354      * Stage two
00355      *
00356      * Update subscriptions and reset forwarding pointers
00357      *
00358      */
00359     // Update variables without indexing structure
00360     for (Variable<VTI_NOIDX,0,__Combine>* x
00361            = static_cast<Variable<VTI_NOIDX,0,__Combine>*>(c->vars_noidx);
00362          x != NULL; x = x->next())
00363       x->u.free_me = 0;
00364     c->vars_noidx = NULL;
00365     // Update variables with indexing structure
00366     Propagator** s;
00367     if (n_sub > 0)
00368       s = reinterpret_cast<Propagator**>
00369         (Memory::malloc(n_sub*sizeof(Propagator*)));
00370     else
00371       s = NULL;
00372     c->sub = s;
00373     for (int vti=VTI_LAST; vti--; ) {
00374       VarBase* vs = c->vars[vti];
00375       if (vs != NULL) {
00376         c->vars[vti] = NULL; vtp[vti]->update(vs,s);
00377       }
00378     }
00379     // Update the number of subscriptions (both in copy and original)
00380     // Remember: this is a conservative estimate
00381     unsigned int n = s - c->sub;
00382     assert(n <= n_sub);
00383     c->n_sub = n; n_sub = n;
00384     // Re-establish prev links (reset forwarding information)
00385     ActorLink* p = &a_actors;
00386     ActorLink* a = p->next();
00387     while (a != &a_actors) {
00388       a->prev(p); p = a; a = a->next();
00389     }
00390     assert(a->prev() == p);
00391     return c;
00392   }
00393 
00394   unsigned int
00395   Space::propagators(void) const {
00396     if (failed())
00397       throw SpaceFailed("Space::propagators");
00398     unsigned int n = 0;
00399     for (const ActorLink* a = a_actors.next(); a != b_commit; a = a->next())
00400       n++;
00401     return n;
00402   }
00403 
00404   unsigned int
00405   Space::branchings(void) const {
00406     if (failed())
00407       throw SpaceFailed("Space::branchings");
00408     unsigned int n = 0;
00409     for (const ActorLink* a = b_status; a != &a_actors; a = a->next())
00410       n++;
00411     return n;
00412   }
00413 
00414 }
00415 
00416 // STATISTICS: kernel-core
00417