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

core.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2002
00008  *     Guido Tack, 2003
00009  *
00010  *  Bugfixes provided by:
00011  *     Alexander Samoilov <alexander_samoilov@yahoo.com>
00012  *
00013  *  Last modified:
00014  *     $Date: 2006-10-25 13:51:24 +0200 (Wed, 25 Oct 2006) $ by $Author: schulte $
00015  *     $Revision: 3787 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  See the file "LICENSE" for information on usage and
00022  *  redistribution of this file, and for a
00023  *     DISCLAIMER OF ALL WARRANTIES.
00024  *
00025  */
00026 
00027 namespace Gecode {
00028 
00037 
00038   typedef int ModEvent;
00039 
00041   const ModEvent ME_GEN_FAILED   = -1;
00043   const ModEvent ME_GEN_NONE     =  0;
00045   const ModEvent ME_GEN_ASSIGNED =  1;
00047   const ModEvent ME_GEN_MAX      = 15;
00048 
00050   typedef int PropCond;
00052   const PropCond PC_GEN_ASSIGNED = 0;
00054   const PropCond PC_GEN_MAX      = 15;
00056 
00057 
00070   enum VarTypeId {
00071 #include "gecode/vti.icc"
00072     VTI_LAST,     
00073     VTI_NOIDX = 0 
00074   };
00075 
00076 
00077   /*
00078    * These are the classes of interest
00079    *
00080    */
00081   class Actor;
00082   class Propagator;
00083   class Space;
00084   template <VarTypeId VTI, PropCond PC, class MED> class Variable;
00085 
00086 
00087   /*
00088    * Variables
00089    *
00090    */
00091 
00099   class VarBase {};
00100 
00108   class VarTypeProcessorBase {
00109   public:
00111     virtual void process(Space* home, VarBase* x) = 0;
00118     virtual void update(VarBase* x, Propagator**& sub) = 0;
00125     virtual void dispose(Space* home, VarBase* x) = 0;
00127     GECODE_KERNEL_EXPORT virtual ~VarTypeProcessorBase(void);
00128   };
00129 
00137   template <VarTypeId VTI, PropCond PC, class MED>
00138   class VarTypeProcessor : public VarTypeProcessorBase {
00139   public:
00141     VarTypeProcessor(void);
00148     virtual void update(VarBase* x, Propagator**& sub);
00155     virtual void dispose(Space* home, VarBase* x);
00156   };
00157 
00168   typedef int PropModEvent;
00169 
00170 
00178   template <VarTypeId VTI, PropCond PC, class MED>
00179   class Variable : public VarBase {
00180     friend class Space;
00181     friend class Propagator;
00182     friend class VarTypeProcessor<VTI,PC,MED>;
00183   private:
00184     Variable* _next; 
00185     union {
00193       unsigned int free_me;
00195       Variable* fwd;
00196     } u;
00197     Propagator** idx[PC+2]; 
00198 
00200     unsigned int free(void) const;
00202     void free(unsigned int n);
00204     void free_inc(void);
00206     void free_dec(void);
00207 
00214     void update(Variable* x, Propagator**& sub);
00215 
00217     void resize(Space* home);
00218 
00219   public:
00221     Variable(Space* home);
00222 
00224 
00225 
00237     void subscribe(Space* home, Propagator* p, PropCond pc,
00238                    bool assigned, ModEvent me, bool process);
00240     void cancel(Space* home, Propagator* p, PropCond pc);
00242     unsigned int degree(void) const;
00244     void notify(Space* home, ModEvent me);
00246     void notify(Space* home);
00248 
00250 
00251 
00252     bool modified(void) const;
00254 
00256 
00257 
00258     Variable(Space* home, bool share, Variable& x);
00260     bool copied(void) const;
00262     Variable* forward(void) const;
00264 
00266 
00267 
00268     static ModEvent     pme(const Propagator* p);
00270     static PropModEvent pme(ModEvent me);
00272     static ModEvent     combine(ModEvent me1, ModEvent me2);
00274 
00276 
00277 
00278     Variable* next(void);
00280     ModEvent modevent(void) const;
00282     void modevent(ModEvent me);
00284     void process(Space* home, PropCond pc1, PropCond pc2, ModEvent me);
00286     void process(Space* home);
00288 
00290 
00291 
00292     static void* operator new(size_t,Space*);
00294     static void  operator delete(void*,Space*);
00296     static void  operator delete(void*);
00298   };
00299 
00300 
00301 
00302 
00307   enum ExecStatus {
00308     ES_FAILED          = -1, 
00309     ES_NOFIX           =  0, 
00310     ES_OK              =  0, 
00311     ES_FIX             =  1, 
00312     ES_SUBSUMED        =  2, 
00313     __ES_FIX_PARTIAL   =  3, 
00314     __ES_NOFIX_PARTIAL =  4  
00315   };
00316 
00321   enum PropCost {
00322     PC_CRAZY_LO     = 0, 
00323     PC_CRAZY_HI     = 0, 
00324     PC_CUBIC_LO     = 1, 
00325     PC_CUBIC_HI     = 1, 
00326     PC_QUADRATIC_LO = 2, 
00327     PC_QUADRATIC_HI = 2, 
00328     PC_LINEAR_HI    = 3, 
00329     PC_LINEAR_LO    = 4, 
00330     PC_TERNARY_HI   = 5, 
00331     PC_BINARY_HI    = 6, 
00332     PC_TERNARY_LO   = 6, 
00333     PC_BINARY_LO    = 7, 
00334     PC_UNARY_LO     = 7, 
00335     PC_UNARY_HI     = 7, 
00336     PC_MAX          = 7  
00337   };
00338 
00346   class ActorLink {
00347     friend class Actor;
00348     friend class Space;
00349     template <VarTypeId VTI, PropCond PC, class MED> friend class Variable;
00350   private:
00351     ActorLink* _next; ActorLink* _prev;
00352   public:
00354 
00355     ActorLink* prev(void) const; void prev(ActorLink*);
00356     ActorLink* next(void) const; void next(ActorLink*);
00358 
00359 
00361     void init(void);
00363     void unlink(void);
00365     void head(ActorLink* al);
00367     void tail(ActorLink* al);
00368   };
00369 
00370 
00381   class ActorDeleteLink : public ActorLink {
00382     friend class Actor;
00383     friend class Space;
00384     template <VarTypeId VTI, PropCond PC, class MED> friend class Variable;
00385   private:
00386     ActorDeleteLink* _next_d; ActorDeleteLink* _prev_d;
00387   public:
00388     ActorDeleteLink* next_delete(void) const;
00389     void next_delete(ActorDeleteLink*);
00390     ActorDeleteLink* prev_delete(void) const;
00391     void prev_delete(ActorDeleteLink*);
00392 
00394     void init_delete(void);
00395     void unlink_delete(void);
00396     void insert_delete(ActorDeleteLink*,bool);
00397   };
00398 
00399 
00400 
00405   class Actor : private ActorDeleteLink {
00406     friend class Space;
00407     template <VarTypeId VTI, PropCond PC, class MED> friend class Variable;
00408   public:
00410     virtual Actor* copy(Space*,bool) = 0;
00412     GECODE_KERNEL_EXPORT
00413     virtual size_t dispose(Space* home);
00414 
00416 
00417 
00418     GECODE_KERNEL_EXPORT virtual void flush(void);
00420     GECODE_KERNEL_EXPORT virtual size_t cached(void) const;
00422     static void* operator new(size_t s, Space* home);
00424     static void  operator delete(void* p, Space* home);
00425   private:
00426 #ifndef __GNUC__
00427 
00428     static void  operator delete(void* p, size_t s);
00429 #endif
00430 
00431     static void* operator new(size_t s);
00433     void destruct(Space* home);
00435 #ifdef __GNUC__
00436   public:
00438     virtual ~Actor(void) {}
00440     static void  operator delete(void* p, size_t s);
00441 #endif
00442   };
00443 
00444 
00445 
00450   class Propagator : public Actor {
00451     friend class Space;
00452     template <VarTypeId VTI, PropCond PC, class MED> friend class Variable;
00453   private:
00454     PropModEvent pme;
00455   protected:
00461     Propagator(Space* home, bool fd=false);
00463     Propagator(Space* home, bool share, Propagator& p);
00464 
00466 
00467 
00477     ExecStatus ES_FIX_PARTIAL(PropModEvent pme);
00488     ExecStatus ES_NOFIX_PARTIAL(PropModEvent pme);
00490   public:
00492 
00493 
00494     virtual ExecStatus propagate(Space*) = 0;
00496     virtual PropCost cost(void) const  = 0;
00498   };
00499 
00500 
00501 
00502   /*
00503    * Branchings
00504    *
00505    */
00506 
00507   class Branching;
00508 
00518   class BranchingDesc {
00519     friend class Space;
00520   private:
00521     const unsigned int id;  
00522     const unsigned int alt; 
00523   protected:
00525     BranchingDesc(const Branching* b, const unsigned int a);
00526   public:
00528     GECODE_KERNEL_EXPORT virtual ~BranchingDesc(void);
00529 
00531     unsigned int alternatives(void) const;
00532 
00534     virtual size_t size(void) const = 0;
00536     static void* operator new(size_t);
00538     static void  operator delete(void*);
00539   };
00540 
00550   class Branching : public Actor {
00551     friend class Space;
00552     friend class BranchingDesc;
00553   private:
00554     unsigned int id; 
00555   protected:
00557     Branching(Space* home, bool fd=false);
00559     Branching(Space* home, bool share, Branching& b);
00560 
00561   public:
00563 
00564 
00572     virtual bool status(const Space* home) const = 0;
00582     virtual const BranchingDesc* description(const Space* home) const = 0;
00590     virtual ExecStatus commit(Space* home, const BranchingDesc* d,
00591                               unsigned int a) = 0;
00593   };
00594 
00595 
00596 
00601   enum SpaceStatus {
00602     SS_FAILED, 
00603     SS_SOLVED, 
00604     SS_BRANCH  
00605   };
00606 
00610   class Space {
00611     friend class Propagator;
00612     friend class Branching;
00613     template <VarTypeId VTI, PropCond PC, class MED> friend class Variable;
00614     template <VarTypeId VTI, PropCond PC, class MED> friend class VarTypeProcessor;
00615   private:
00616     MemoryManager   mm; 
00617 
00622 
00623     GECODE_KERNEL_EXPORT
00624     static VarTypeProcessorBase* vtp[VTI_LAST];
00626     VarBase* vars[VTI_LAST];
00628     VarBase* vars_dispose[VTI_LAST];
00630     VarBase* vars_noidx;
00632     void process(void);
00634 
00639 
00640     ActorLink pool[PC_MAX+1];
00642     int pool_next;
00644     void pool_put(Propagator* p);
00646     bool pool_get(Propagator*& p);
00648 
00655     ActorDeleteLink a_actors;
00664     Branching*      b_status;
00677     Branching*      b_commit;
00679     unsigned int    branch_id;
00680 
00690     unsigned int n_sub;
00698     Propagator** sub;
00700     GECODE_KERNEL_EXPORT static unsigned long int unused_uli;
00701 
00703     GECODE_KERNEL_EXPORT unsigned long int propagate(void);
00704 
00706     void propagator(Propagator* p, bool fd);
00708     void propagator(Propagator*);
00710     void branching(Branching* b, bool fd);
00711 
00716 
00717     template <VarTypeId VTI, class MED>
00718     void process(Propagator* p, ModEvent me);
00720     template <VarTypeId VTI, class MED>
00721     void process(Propagator* p);
00723 
00724 
00725   public:
00730     GECODE_KERNEL_EXPORT Space(void);
00735     GECODE_KERNEL_EXPORT virtual ~Space(void);
00746     GECODE_KERNEL_EXPORT Space(bool share, Space& s);
00753     virtual Space* copy(bool share) = 0;
00758     static void* operator new(size_t);
00763     static void  operator delete(void*);
00764 
00765 
00766 
00767 
00768     /*
00769      * Member functions for search engines
00770      *
00771      */
00772 
00784     SpaceStatus status(unsigned long int& pn=unused_uli);
00785 
00801     const BranchingDesc* description(void) const;
00802 
00819     GECODE_KERNEL_EXPORT
00820     Space* clone(bool share=true, unsigned long int& pn=unused_uli);
00821 
00851     GECODE_KERNEL_EXPORT
00852     void commit(const BranchingDesc* d, unsigned int a);
00853 
00864     GECODE_KERNEL_EXPORT
00865     void flush(void);
00866 
00867 
00868     /*
00869      * Status checking and failing outside actors
00870      *
00871      */
00872 
00880     void fail(void);
00889     bool failed(void) const;
00899     GECODE_KERNEL_EXPORT
00900     unsigned int propagators(void) const;
00908     GECODE_KERNEL_EXPORT
00909     unsigned int branchings(void) const;
00910 
00916 
00917     void* alloc(size_t);
00919     void  reuse(void*,size_t);
00921     template <size_t> void* fl_alloc(void);
00927     template <size_t> void  fl_dispose(FreeList* f, FreeList* l);
00933     size_t allocated(void) const;
00935     GECODE_KERNEL_EXPORT size_t cached(void) const;
00937     template <VarTypeId VTI> VarBase* varsDisposeList(void);
00939     template <VarTypeId VTI> void varsDisposeList(VarBase* v);
00941   };
00942 
00943 
00944 
00945 
00946   /***
00947    *** MEMORY MANAGEMENT
00948    ***
00949    ***/
00950 
00951   /*
00952    * Heap allocated: Space, BranchDesc
00953    *
00954    */
00955 
00956   forceinline void*
00957   Space::operator new(size_t s) {
00958     return Memory::malloc(s);
00959   }
00960   forceinline void
00961   Space::operator delete(void* p) {
00962     Memory::free(p);
00963   }
00964 
00965   forceinline void
00966   BranchingDesc::operator delete(void* p) {
00967     Memory::free(p);
00968   }
00969   forceinline void*
00970   BranchingDesc::operator new(size_t s) {
00971     return Memory::malloc(s);
00972   }
00973 
00974   /*
00975    * Space allocation: general space heaps and free lists
00976    *
00977    */
00978 
00979   forceinline void*
00980   Space::alloc(size_t s) {
00981     return mm.alloc(s);
00982   }
00983   forceinline void
00984   Space::reuse(void* p, size_t s) {
00985     return mm.reuse(p,s);
00986   }
00987 
00988   template <size_t s>
00989   forceinline void*
00990   Space::fl_alloc(void) {
00991     return mm.template fl_alloc<s>();
00992   }
00993   template <size_t s>
00994   forceinline void
00995   Space::fl_dispose(FreeList* f, FreeList* l) {
00996     mm.template fl_dispose<s>(f,l);
00997   }
00998 
00999   forceinline size_t
01000   Space::allocated(void) const {
01001     return mm.allocated()+n_sub*sizeof(Propagator**);
01002   }
01003 
01004   template <VarTypeId VTI>
01005   forceinline VarBase*
01006   Space::varsDisposeList(void) {
01007     return vars_dispose[VTI];
01008   }
01009 
01010   template <VarTypeId VTI>
01011   forceinline void
01012   Space::varsDisposeList(VarBase* v) {
01013     vars_dispose[VTI]=v;
01014   }
01015 
01016   /*
01017    * Space allocated entities: Actors and Variables
01018    *
01019    */
01020 
01021   forceinline void
01022   Actor::operator delete(void*, size_t) {}
01023   forceinline void
01024   Actor::operator delete(void*,Space*) {}
01025   forceinline void*
01026   Actor::operator new(size_t s, Space* home) {
01027     return home->alloc(s);
01028   }
01029 
01030   template <VarTypeId VTI, PropCond PC, class MED>
01031   forceinline void
01032   Variable<VTI,PC,MED>::operator delete(void*) {}
01033   template <VarTypeId VTI, PropCond PC, class MED>
01034   forceinline void
01035   Variable<VTI,PC,MED>::operator delete(void*, Space*) {}
01036   template <VarTypeId VTI, PropCond PC, class MED>
01037   forceinline void*
01038   Variable<VTI,PC,MED>::operator new(size_t s, Space* home) {
01039     return home->alloc(s);
01040   }
01041 
01042 
01043 
01044   /*
01045    * ActorLinks as common subclass for propagators and branchings
01046    *
01047    */
01048 
01049   forceinline ActorLink*
01050   ActorLink::prev(void) const { return _prev; }
01051   forceinline ActorLink*
01052   ActorLink::next(void) const { return _next; }
01053   forceinline void
01054   ActorLink::prev(ActorLink* al) { _prev = al; }
01055   forceinline void
01056   ActorLink::next(ActorLink* al) { _next = al; }
01057 
01058   forceinline void
01059   ActorLink::unlink(void) {
01060     ActorLink* p = _prev; ActorLink* n = _next;
01061     p->_next = n; n->_prev = p;
01062   }
01063   forceinline void
01064   ActorLink::init(void) {
01065     _next = this; _prev =this;
01066   }
01067   forceinline void
01068   ActorLink::head(ActorLink* a) {
01069     // Inserts al at head of link-chain (that is, after this)
01070     ActorLink* n = _next;
01071     this->_next = a; a->_prev = this;
01072     a->_next = n; n->_prev = a;
01073   }
01074   forceinline void
01075   ActorLink::tail(ActorLink* a) {
01076     // Inserts al at tail of link-chain (that is, before this)
01077     ActorLink* p = _prev;
01078     a->_next = this; this->_prev = a;
01079     p->_next = a; a->_prev = p;
01080   }
01081 
01082 
01083 
01084   forceinline ActorDeleteLink*
01085   ActorDeleteLink::next_delete(void) const { return _next_d; }
01086   forceinline ActorDeleteLink*
01087   ActorDeleteLink::prev_delete(void) const { return _prev_d; }
01088   forceinline void
01089   ActorDeleteLink::next_delete(ActorDeleteLink* adl) { _next_d = adl; }
01090   forceinline void
01091   ActorDeleteLink::prev_delete(ActorDeleteLink* adl) { _prev_d = adl; }
01092 
01093   forceinline void
01094   ActorDeleteLink::unlink_delete(void) {
01095     ActorDeleteLink* p = _prev_d;
01096     ActorDeleteLink* n = _next_d;
01097     p->_next_d = n; n->_prev_d = p;
01098   }
01099 
01100   forceinline void
01101   ActorDeleteLink::insert_delete(ActorDeleteLink* a, bool fd) {
01102     if (fd) {
01103       // Link a after this
01104       ActorDeleteLink* n = _next_d;
01105       this->_next_d = a; a->_prev_d = this;
01106       a->_next_d = n; n->_prev_d = a;
01107     } else {
01108       // Just link to itself
01109       a->_prev_d = a; a->_next_d = a;
01110     }
01111   }
01112 
01113   forceinline void
01114   ActorDeleteLink::init_delete(void) {
01115     _next_d = this; _prev_d = this;
01116   }
01117 
01118 
01119 
01120 
01121   forceinline size_t
01122   Actor::dispose(Space*) {
01123     return sizeof(*this);
01124   }
01125 
01126   forceinline void
01127   Actor::destruct(Space* home) {
01128     unlink_delete();
01129     size_t s = dispose(home);
01130     home->reuse(this,s);
01131   }
01132 
01133 
01134   /*
01135    * Spaces
01136    *
01137    */
01138 
01139   forceinline const BranchingDesc*
01140   Space::description(void) const {
01141     return b_status->description(this);
01142   }
01143 
01144   forceinline bool
01145   Space::failed(void) const {
01146     return b_status == NULL;
01147   }
01148 
01149   /*
01150    * Main control for propagation and branching
01151    *  - a space only propagates and branches if requested by
01152    *    either a status, commit, or clone operation
01153    *  - for all of the operations the number of propagation
01154    *    steps performed is returned in the last (optional)
01155    *    reference argument
01156    *
01157    */
01158   forceinline SpaceStatus
01159   Space::status(unsigned long int& pn) {
01160     // Perform propagation and do not continue when failed
01161     pn += propagate();
01162     if (failed())
01163       return SS_FAILED;
01164     /*
01165      * Find the next branching that has still alternatives left
01166      *
01167      * It is important to note that branchings reporting to have no more
01168      * alternatives left can not be deleted. They can not be deleted
01169      * as there might be branching descriptions to be used in commit
01170      * that refer to one of these branchings.
01171      *
01172      * A branching reporting that no more alternatives exist will eventually
01173      * be deleted in commit. It will be deleted if the first branching
01174      * description is used in commit that does not refer to this branching.
01175      * As we insist that branching descriptions are used in order of
01176      * creation, all further branching descriptions cannot refer to this
01177      * branching.
01178      *
01179      */
01180     while (b_status != &a_actors) {
01181       if (b_status->status(this))
01182         return SS_BRANCH;
01183       b_status = static_cast<Branching*>(b_status->next());
01184     }
01185     // No branching with alternatives left, space is solved
01186     return SS_SOLVED;
01187   }
01188 
01189 
01190   /*
01191    * Variables
01192    *
01193    */
01194 
01195   template <VarTypeId VTI, PropCond PC, class MED>
01196   forceinline
01197   Variable<VTI,PC,MED>::Variable(Space*) :
01198     _next(reinterpret_cast<Variable<VTI,PC,MED>*>(1)) {
01199     u.free_me = 0;
01200     for (int i=PC+2; i--; )
01201       idx[i] = NULL;
01202   }
01203 
01204 
01205   template <VarTypeId VTI, PropCond PC, class MED>
01206   forceinline unsigned int
01207   Variable<VTI,PC,MED>::degree(void) const {
01208     return static_cast<unsigned int>(idx[PC+1] - idx[0]);
01209   }
01210 
01211 
01212 
01213   template <VarTypeId VTI, PropCond PC, class MED>
01214   forceinline ModEvent
01215   Variable<VTI,PC,MED>::modevent(void) const {
01216     return u.free_me & 15;
01217   }
01218 
01219   template <VarTypeId VTI, PropCond PC, class MED>
01220   forceinline void
01221   Variable<VTI,PC,MED>::modevent(ModEvent me) {
01222     u.free_me = (u.free_me & ~15) | me;
01223   }
01224   template <VarTypeId VTI, PropCond PC, class MED>
01225   forceinline unsigned int
01226   Variable<VTI,PC,MED>::free(void) const {
01227     return u.free_me >> 4;
01228   }
01229 
01230   template <VarTypeId VTI, PropCond PC, class MED>
01231   forceinline void
01232   Variable<VTI,PC,MED>::free(unsigned int n) {
01233     u.free_me = (u.free_me & 15) | (n << 4);
01234   }
01235 
01236   template <VarTypeId VTI, PropCond PC, class MED>
01237   forceinline void
01238   Variable<VTI,PC,MED>::free_inc(void) {
01239     u.free_me += (1 << 4);
01240   }
01241 
01242   template <VarTypeId VTI, PropCond PC, class MED>
01243   forceinline void
01244   Variable<VTI,PC,MED>::free_dec(void) {
01245     u.free_me -= (1 << 4);
01246   }
01247 
01248   template <VarTypeId VTI, PropCond PC, class MED>
01249   forceinline bool
01250   Variable<VTI,PC,MED>::modified(void) const {
01251     return _next != reinterpret_cast<Variable<VTI,PC,MED>*>(1);
01252   }
01253 
01254 
01255 
01256   template <VarTypeId VTI, PropCond PC, class MED>
01257   forceinline Variable<VTI,PC,MED>*
01258   Variable<VTI,PC,MED>::next(void) {
01259     Variable<VTI,PC,MED>* n = _next;
01260     _next = reinterpret_cast<Variable<VTI,PC,MED>*>(1);
01261     return n;
01262   }
01263 
01264   template <VarTypeId VTI, PropCond PC, class MED>
01265   forceinline bool
01266   Variable<VTI,PC,MED>::copied(void) const {
01267     return _next != reinterpret_cast<Variable<VTI,PC,MED>*>(1);
01268   }
01269 
01270   template <VarTypeId VTI, PropCond PC, class MED>
01271   forceinline
01272   Variable<VTI,PC,MED>::Variable(Space* home, bool, Variable<VTI,PC,MED>& x)
01273     : _next(reinterpret_cast<Variable<VTI,PC,MED>*>(1)) {
01274     VarBase** reg;
01275     if (x.idx[0] == NULL) {
01276       // Variable needs no index structure
01277       u.free_me = 0;
01278       for (int i=PC+2; i--; )
01279         idx[i] = NULL;
01280       reg = &home->vars_noidx;
01281     } else {
01282       // Recover original value in copy
01283       u.free_me = x.u.free_me;
01284       reg = &home->vars[VTI];
01285     }
01286     // Set forwarding pointer
01287     x.u.fwd = this;
01288     // Register original
01289     x._next = static_cast<Variable<VTI,PC,MED>*>(*reg); *reg = &x;
01290   }
01291 
01292   template <VarTypeId VTI, PropCond PC, class MED>
01293   forceinline Variable<VTI,PC,MED>*
01294   Variable<VTI,PC,MED>::forward(void) const {
01295     return u.fwd;
01296   }
01297 
01298   /*
01299    * Propagator modification events
01300    *
01301    */
01302 
01303   template <VarTypeId VTI, PropCond PC, class MED>
01304   forceinline ModEvent
01305   Variable<VTI,PC,MED>::pme(const Propagator* p) {
01306     return static_cast<ModEvent>((p->pme >> (VTI << 2)) & 15);
01307   }
01308 
01309   template <VarTypeId VTI, PropCond PC, class MED>
01310   forceinline PropModEvent
01311   Variable<VTI,PC,MED>::pme(ModEvent me) {
01312     return static_cast<PropModEvent>(me << (VTI << 2));
01313   }
01314 
01315   template <VarTypeId VTI, PropCond PC, class MED>
01316   forceinline ModEvent
01317   Variable<VTI,PC,MED>::combine(ModEvent me1, ModEvent me2) {
01318     MED med;
01319     return me2^med(me1,me2);
01320   }
01321 
01322   /*
01323    * Propagators
01324    *
01325    */
01326 
01327   forceinline void
01328   Space::propagator(Propagator* p, bool fd) {
01329     // Propagators are put at the front of the link of actors
01330     a_actors.head(p);
01331     a_actors.insert_delete(p,fd);
01332   }
01333 
01334   forceinline void
01335   Space::propagator(Propagator* p) {
01336     a_actors.head(p);
01337   }
01338 
01339   forceinline void
01340   Space::branching(Branching* b, bool fd) {
01341     // Propagators are put at the tail of the link of actors
01342     b->id = branch_id++;
01343     // If no branching available, make it the first one
01344     if (b_status == &a_actors) {
01345       b_status = b;
01346       if (b_commit == &a_actors)
01347         b_commit = b;
01348     }
01349     a_actors.tail(b);
01350     a_actors.insert_delete(b,fd);
01351   }
01352 
01353 
01354 
01355   forceinline
01356   Propagator::Propagator(Space* home, bool fd)
01357     : pme(0) {
01358     home->propagator(this,fd);
01359   }
01360 
01361   forceinline
01362   Propagator::Propagator(Space*, bool, Propagator&)
01363     : pme(0) {}
01364 
01365 
01366   /*
01367    * Branchings
01368    *
01369    */
01370 
01371   forceinline
01372   Branching::Branching(Space* home, bool fd) {
01373     home->branching(this,fd);
01374   }
01375 
01376   forceinline
01377   Branching::Branching(Space*, bool, Branching& b)
01378     : id(b.id)  {}
01379 
01380 
01381 
01382   /*
01383    * Branching descriptions
01384    *
01385    */
01386 
01387   forceinline
01388   BranchingDesc::BranchingDesc(const Branching* b, const unsigned int a)
01389     : id(b->id), alt(a) {}
01390 
01391   forceinline unsigned int
01392   BranchingDesc::alternatives(void) const {
01393     return alt;
01394   }
01395 
01396   forceinline
01397   BranchingDesc::~BranchingDesc(void) {}
01398 
01399 
01400 
01401 
01402 
01403   /*
01404    * Propagator pools
01405    *
01406    */
01407 
01408   forceinline void
01409   Space::pool_put(Propagator* p) {
01410     int c = p->cost();
01411     pool[c].tail(p);
01412     if (c > pool_next)
01413       pool_next = c;
01414   }
01415 
01416   forceinline void
01417   Space::fail(void) {
01418     b_status = NULL;
01419   }
01420 
01421   template <VarTypeId VTI, class MED>
01422   forceinline void
01423   Space::process(Propagator* p) {
01424     // The new event is ME_GEN_ASSIGNED
01425     PropModEvent old_pme = p->pme;
01426     // Compute old modification event
01427     ModEvent old_me = old_pme & (ME_GEN_MAX << (VTI << 2));
01428     // Check whether old event is already ME_GEN_ASSIGNED
01429     if (old_me == (ME_GEN_ASSIGNED << (VTI << 2)))
01430       return;
01431     // Update event
01432     p->pme ^= old_me ^ (ME_GEN_ASSIGNED << (VTI << 2));
01433     // Put propagator into right queue
01434     p->unlink();
01435     pool_put(p);
01436   }
01437 
01438   template <VarTypeId VTI, class MED>
01439   forceinline void
01440   Space::process(Propagator* p, ModEvent new_me) {
01441     MED med;
01442     PropModEvent old_pme = p->pme;
01443     // Compute the old modification event
01444     ModEvent old_me = ((old_pme >> (VTI << 2)) & ME_GEN_MAX);
01445     // Get the new modification event (xor-ed with the old one)
01446     ModEvent com_me = med(new_me,old_me);
01447     // Event has not changed, do not nothing
01448     if (com_me == 0)
01449       return;
01450     // Update modification event for propagator (use xor)
01451     p->pme ^= (com_me << (VTI << 2));
01452     // Put propagator into right queue
01453     p->unlink();
01454     pool_put(p);
01455   }
01456 
01457   forceinline ExecStatus
01458   Propagator::ES_FIX_PARTIAL(PropModEvent pme) {
01459     this->pme = pme; return __ES_FIX_PARTIAL;
01460   }
01461 
01462   forceinline ExecStatus
01463   Propagator::ES_NOFIX_PARTIAL(PropModEvent pme) {
01464     this->pme = pme; return __ES_NOFIX_PARTIAL;
01465   }
01466 
01467 
01468   /*
01469    * Subscribing to a variable
01470    *
01471    */
01472 
01473   template <VarTypeId VTI, PropCond PC, class MED>
01474   forceinline void
01475   Variable<VTI,PC,MED>::subscribe(Space* home, Propagator* p, PropCond pc,
01476                                   bool assigned, ModEvent me, bool process) {
01477     if (assigned) {
01478       // Do not subscribe, just process the propagator
01479       if (process)
01480         home->process<VTI,MED>(p);
01481     } else {
01482       // Count one new subscription
01483       home->n_sub += 1;
01484       if (free() == 0)
01485         resize(home);
01486       free_dec();
01487       // Enter propagator
01488       --idx[0];
01489       for (PropCond i = 0; i < pc; i++)
01490         *(idx[i]) = *(--idx[i+1]);
01491       *idx[pc]=p;
01492       // Process propagator
01493       if (process && (pc != PC_GEN_ASSIGNED))
01494         home->process<VTI,MED>(p,me);
01495     }
01496   }
01497 
01498   template <VarTypeId VTI, PropCond PC, class MED>
01499   void
01500   Variable<VTI,PC,MED>::resize(Space* home) {
01501     assert(free() == 0);
01502     if (idx[0] == NULL) {
01503       // Count the one new free entry
01504       home->n_sub += 1;
01505       // Create fresh dependency array
01506       free(4);
01507       Propagator** prop = reinterpret_cast<Propagator**>
01508         (home->alloc(4*sizeof(Propagator*))) + 4;
01509       for (PropCond i = PC+2; i--; )
01510         idx[i] = prop;
01511     } else {
01512       // Resize dependency array
01513       int n = static_cast<int>(idx[PC+1] - idx[0]);
01514       Propagator** prop = reinterpret_cast<Propagator**>
01515         (home->alloc(2*n*sizeof(Propagator*))) + n;
01516       free(n);
01517       // Copy entries
01518       memcpy(prop, idx[0], n*sizeof(Propagator*));
01519       home->reuse(idx[0], n*sizeof(Propagator*));
01520       // Update index pointers
01521       ptrdiff_t o = prop - idx[0];
01522       idx[0] = prop;
01523       for (PropCond i = PC+1; i > 0; i--)
01524         idx[i] += o;
01525     }
01526   }
01527 
01528 
01529   /*
01530    * Cancelling a subscription
01531    *
01532    */
01533 
01534   template <VarTypeId VTI, PropCond PC, class MED>
01535   forceinline void
01536   Variable<VTI,PC,MED>::cancel(Space* home, Propagator* p, PropCond pc) {
01537     if (idx[0] != NULL) {
01538       Propagator** f = idx[pc];
01539 #ifdef GECODE_AUDIT
01540       while (f < idx[pc+1])
01541         if (*f == p)
01542           goto found;
01543         else
01544           f++;
01545       GECODE_NEVER;
01546     found: ;
01547 #else
01548       while (*f != p) f++;
01549 #endif
01550       *f=*idx[pc];
01551       for (PropCond i=pc; i>0; i--)
01552         *(idx[i]++)=*(idx[i-1]);
01553       idx[0]++;
01554       free_inc();
01555       home->n_sub -= 1;
01556     }
01557   }
01558 
01559   template <VarTypeId VTI, PropCond PC, class MED>
01560   forceinline void
01561   Variable<VTI,PC,MED>::notify(Space* home, ModEvent new_me) {
01562     if (modified()) {
01563       MED med;
01564       u.free_me ^= med(new_me,modevent());
01565     } else {
01566       _next = static_cast<Variable<VTI,PC,MED>*>(home->vars[VTI]);
01567       home->vars[VTI] = this;
01568       modevent(new_me);
01569     }
01570   }
01571 
01572   template <VarTypeId VTI, PropCond PC, class MED>
01573   forceinline void
01574   Variable<VTI,PC,MED>::notify(Space* home) {
01575     assert(!modified());
01576     _next = static_cast<Variable<VTI,PC,MED>*>(home->vars[VTI]);
01577     home->vars[VTI] = this;
01578     modevent(ME_GEN_ASSIGNED);
01579   }
01580 
01581 
01582   /*
01583    * PROCESSING
01584    *
01585    */
01586 
01587   template <VarTypeId VTI, PropCond PC, class MED>
01588   forceinline void
01589   Variable<VTI,PC,MED>::update(Variable<VTI,PC,MED>* x, Propagator**& sub) {
01590     // this refers to the variable to be updated (clone)
01591     // x refers to the original
01592     // Recover from copy (also overwrites forwarding pointer)
01593     x->u.free_me = u.free_me;
01594     Propagator** f = x->idx[0];
01595     int n = static_cast<int>(x->idx[PC+1] - f);
01596     u.free_me = 1 << 4;
01597     Propagator** t = sub + 1;
01598     sub += n+1;
01599     idx[0] = t;
01600     ptrdiff_t o = t - f;
01601     for (PropCond i = PC+1; i>0; i--)
01602       idx[i] = x->idx[i]+o;
01603     while ((n-4) >= 0) {
01604       n -= 4;
01605       t[0] = static_cast<Propagator*>(f[0]->prev());;
01606       t[1] = static_cast<Propagator*>(f[1]->prev());;
01607       t[2] = static_cast<Propagator*>(f[2]->prev());;
01608       t[3] = static_cast<Propagator*>(f[3]->prev());;
01609       t += 4; f += 4;
01610     }
01611     if ((n-2) >= 0) {
01612       n -= 2;
01613       t[0] = static_cast<Propagator*>(f[0]->prev());;
01614       t[1] = static_cast<Propagator*>(f[1]->prev());;
01615       t += 2; f += 2;
01616     }
01617     if (n > 0) {
01618       t[0] = static_cast<Propagator*>(f[0]->prev());;
01619     }
01620   }
01621 
01622   template <VarTypeId VTI, PropCond PC, class MED>
01623   VarTypeProcessor<VTI,PC,MED>::VarTypeProcessor(void) {
01624     Space::vtp[VTI] = this;
01625   }
01626 
01627   template <VarTypeId VTI, PropCond PC, class MED>
01628   void
01629   VarTypeProcessor<VTI,PC,MED>::update(VarBase* vb, Propagator**& sub) {
01630     Variable<VTI,PC,MED>* x = static_cast<Variable<VTI,PC,MED>*>(vb);
01631     do {
01632       x->forward()->update(x,sub); x = x->next();
01633     } while (x != NULL);
01634   }
01635 
01636   template <VarTypeId VTI, PropCond PC, class MED>
01637   void
01638   VarTypeProcessor<VTI,PC,MED>::dispose(Space* home, VarBase* x) {}
01639 
01640   /*
01641    * Processing a single modified variable
01642    *
01643    */
01644   template <VarTypeId VTI, PropCond PC, class MED>
01645   forceinline void
01646   Variable<VTI,PC,MED>::process(Space* home,
01647                                 PropCond pc1, PropCond pc2, ModEvent me) {
01648     Propagator** b = idx[pc1];
01649     Propagator** p = idx[pc2+1];
01650     while (p-- > b)
01651       home->process<VTI,MED>(*p,me);
01652   }
01653 
01654   template <VarTypeId VTI, PropCond PC, class MED>
01655   forceinline void
01656   Variable<VTI,PC,MED>::process(Space* home) {
01657     // Entries in index structure are disabled. However they
01658     // must still work for cloning (idx[0]) and degree (idx[PC+1])
01659     Propagator** b = idx[0];    idx[0] = NULL;
01660     Propagator** p = idx[PC+1]; idx[PC+1] = NULL;
01661     /*
01662      * Decrement for p-b subscriptions
01663      *
01664      * Note that one would like to also decrement for the additional
01665      * single free slot that was counted initially. However, this
01666      * is not possible as there might be no free slot. So the number
01667      * of subscriptions is a conservative estimate and will be corrected
01668      * upon cloning.
01669      */
01670     home->n_sub -= p-b;
01671     // Information needed to release the dependency array
01672     unsigned int n = free() + (p-b);
01673     Propagator** s = p-n;
01674     while (p-- > b)
01675       home->process<VTI,MED>(*p);
01676     home->reuse(s,n*sizeof(Propagator*));
01677   }
01678 
01679 }
01680 
01681 // STATISTICS: kernel-core