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

reco-stack.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Christian Schulte, 2003
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-08-04 16:03:17 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00010  *     $Revision: 3511 $
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 namespace Gecode { namespace Search {
00023 
00024   /*
00025    * Node for recomputation
00026    *
00027    */
00028 
00029   forceinline
00030   ReCoNode::ReCoNode(Space* s, Space* c)
00031     : _space(c), _alt(0), _desc(s->description()) {}
00032 
00033   forceinline Space*
00034   ReCoNode::space(void) const {
00035     return _space;
00036   }
00037   forceinline void
00038   ReCoNode::space(Space* s) {
00039     _space = s;
00040   }
00041 
00042   forceinline unsigned int
00043   ReCoNode::alt(void) const {
00044     return _alt;
00045   }
00046   forceinline bool
00047   ReCoNode::rightmost(void) const {
00048     return _alt+1 == _desc->alternatives();
00049   }
00050   forceinline void
00051   ReCoNode::next(void) {
00052     _alt++;
00053   }
00054 
00055   forceinline const BranchingDesc*
00056   ReCoNode::desc(void) const {
00057     return _desc;
00058   }
00059 
00060   forceinline void
00061   ReCoNode::dispose(void) {
00062     delete _space;
00063     delete _desc;
00064   }
00065 
00066 
00067 
00068   /*
00069    * Depth-first stack with recomputation
00070    *
00071    */
00072 
00073   forceinline
00074   ReCoStack::ReCoStack(unsigned int a_d0) : a_d(a_d0) {}
00075 
00076   forceinline const BranchingDesc*
00077   ReCoStack::push(Space* s, Space* c) {
00078     ReCoNode sn(s,c);
00079     ds.push(sn);
00080     return sn.desc();
00081   }
00082 
00083   forceinline bool
00084   ReCoStack::next(EngineCtrl& stat) {
00085     // Generate path for next node and return whether node exists.
00086     while (!ds.empty())
00087       if (ds.top().rightmost()) {
00088         stat.pop(ds.top().space(),ds.top().desc());
00089         ds.pop().dispose();
00090       } else {
00091         ds.top().next();
00092         return true;
00093       }
00094     return false;
00095   }
00096 
00097   forceinline void
00098   ReCoStack::commit(Space* s, int i) const {
00099     const ReCoNode& n = ds[i];
00100     s->commit(n.desc(),n.alt());
00101   }
00102 
00103   forceinline int
00104   ReCoStack::lc(Space*& s) const {
00105     int l = ds.entries()-1;
00106     while (ds[l].space() == NULL)
00107       l--;
00108     s = ds[l].space();
00109     return l;
00110   }
00111 
00112   forceinline int
00113   ReCoStack::entries(void) const {
00114     return ds.entries();
00115   }
00116 
00117   forceinline size_t
00118   ReCoStack::stacksize(void) const {
00119     return ds.size();
00120   }
00121 
00122   forceinline void
00123   ReCoStack::unwind(int l) {
00124     assert((ds[l].space() == NULL) || ds[l].space()->failed());
00125     int n = ds.entries();
00126     for (int i=l; i<n; i++)
00127       ds.pop().dispose();
00128     assert(ds.entries() == l);
00129   }
00130 
00131   inline void
00132   ReCoStack::reset(void) {
00133     while (!ds.empty())
00134       ds.pop().dispose();
00135   }
00136 
00137   template <bool constrained>
00138   forceinline Space*
00139   ReCoStack::recompute(unsigned int& d, EngineCtrl& stat) {
00140     assert(!ds.empty());
00141     // Recompute space according to path
00142     // Also say distance to copy (d == 0) requires immediate copying
00143 
00144     // Check for LAO
00145     if ((ds.top().space() != NULL) && ds.top().rightmost()) {
00146       Space* s = ds.top().space();
00147       s->commit(ds.top().desc(),ds.top().alt());
00148       ds.top().space(NULL);
00149       stat.lao(s);
00150       d = 0;
00151       stat.commit++;
00152       return s;
00153     }
00154     // General case for recomputation
00155     Space* s;             // Last clone
00156     int l = lc(s);        // Position of last clone
00157     int n = ds.entries(); // Number of stack entries
00158     d = n - l;            // New distance, if no adaptive recomputation
00159 
00160     if (constrained) {
00161       // The space on the stack could be failed now as an additional
00162       // constraint might have been added.
00163       if (s->status(stat.propagate) == SS_FAILED) {
00164         // s does not need deletion as it is on the stack (unwind does this)
00165         stat.fail++;
00166         unwind(l);
00167         return NULL;
00168       }
00169       // It is important to replace the space on the stack with the
00170       // copy: a copy might be much smaller due to flushed caches
00171       // of propagators
00172       Space* c = s->clone(true,stat.propagate);
00173       ds[l].space(c);
00174       stat.constrained(s,c);
00175     } else {
00176       s = s->clone(true,stat.propagate);
00177     }
00178     stat.clone++;
00179 
00180     if (d < a_d) {
00181       // No adaptive recomputation
00182       for (int i=l; i<n; i++)
00183         commit(s,i);
00184     } else {
00185       int m = l + (d >> 1); // Middle between copy and top
00186       int i = l;            // To iterate over all entries
00187       // Recompute up to middle
00188       for (; i<m; i++ )
00189         commit(s,i);
00190       // Skip over all rightmost branches
00191       for (; (i<n) && ds[i].rightmost(); i++)
00192         commit(s,i);
00193       // Is there any point to make a copy?
00194       if (i<n-1) {
00195         // Again, the space might already propagate to failure
00196         if (constrained && s->status(stat.propagate) == SS_FAILED) {
00197           // s must be deleted as it is not on the stack
00198           delete s;
00199           stat.commit += (i-l);
00200           stat.fail++;
00201           unwind(i);
00202           return NULL;
00203         }
00204         stat.clone++;
00205         ds[i].space(s->clone(true,stat.propagate));
00206         stat.adapt(ds[i].space());
00207         d = n-i;
00208       }
00209       // Finally do the remaining commits
00210       for (; i<n; i++)
00211         commit(s,i);
00212     }
00213     stat.commit += d;
00214     return s;
00215   }
00216 
00217 }}
00218 
00219 // STATISTICS: search-any