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

incremental.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Mikael Lagerkvist, 2007
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-01-31 18:29:16 +0100 (Thu, 31 Jan 2008) $ by $Author: tack $
00011  *     $Revision: 6017 $
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 namespace Gecode { namespace Int { namespace Extensional {
00039   /*
00040    * Support entries
00041    *
00042    */
00043   
00044   template <class View>
00045   forceinline
00046   Incremental<View>::SupportEntry::SupportEntry(void) 
00047     : t(NULL), next(NULL) {}
00048 
00049   template <class View>
00050   forceinline
00051   Incremental<View>::SupportEntry::SupportEntry(Tuple t0, SupportEntry* n0)
00052     : t(t0), next(n0) {}
00053 
00054   template <class View>
00055   forceinline void
00056   Incremental<View>::SupportEntry::operator delete(void*) {}
00057 
00058   template <class View>
00059   forceinline void
00060   Incremental<View>::SupportEntry::operator delete(void*, Space*) {
00061     GECODE_NEVER;
00062   }
00063 
00064   template <class View>
00065   forceinline void*
00066   Incremental<View>::SupportEntry::operator new(size_t, Space* home) {
00067     return home->fl_alloc<sizeof(SupportEntry)>();
00068   }
00069 
00070   template <class View>
00071   forceinline void
00072   Incremental<View>::SupportEntry::dispose(Space* home, SupportEntry* l) {
00073     home->fl_dispose<sizeof(SupportEntry)>(this,l);
00074   }
00075 
00076   template <class View>
00077   forceinline void
00078   Incremental<View>::SupportEntry::dispose(Space* home) {
00079     next = NULL;
00080     home->fl_dispose<sizeof(SupportEntry)>(this,this);
00081   }
00082 
00083 
00084 
00085   /*
00086    * The propagator proper
00087    *
00088    */
00089 
00090   template <class View>
00091   forceinline
00092   Incremental<View>::Incremental(Space* home, ViewArray<View>& x, const TupleSet& t)
00093     : Base<View,false>(home,x,t), support_data(NULL), 
00094       work(x.size()), unassigned(x.size()), ac(home) {
00095     init_support(home);
00096 
00097     ModEvent me = ME_INT_DOM;
00098 
00099     // Post advisors
00100     for (int i = x.size(); i--; ) {
00101       if (x[i].assigned()) {
00102         --unassigned;
00103         me = ME_INT_VAL;
00104       } else {
00105         (void) new (home) SupportAdvisor(home, this, ac, x[i], i);
00106       }
00107     }
00108 
00109     // Add initial supports
00110     GECODE_AUTOARRAY(BitSet, dom, x.size());
00111     init_dom(home, dom);
00112     for (int i = x.size(); i--; ) {
00113       ViewValues<View> vv(x[i]);
00114       while (vv()) {
00115         find_support(home, dom, i, vv.val());
00116         ++vv;
00117       }
00118     }
00119     if (!work.empty() || unassigned==0) {
00120       // Work to be done or subsumption
00121       View::schedule(home,this,me);
00122     }
00123   }
00124 
00125   template <class View>
00126   ExecStatus
00127   Incremental<View>::post(Space* home, ViewArray<View>& x, const TupleSet& t) {
00128     (void) new (home) Incremental<View>(home,x,t);
00129     return ES_OK;
00130   }
00131 
00132   template <class View>
00133   forceinline
00134   Incremental<View>::Incremental(Space* home, bool share, Incremental<View>& p)
00135     : Base<View,false>(home,share,p), support_data(NULL), 
00136       work(2), unassigned(p.unassigned) {
00137     ac.update(home,share,p.ac);
00138 
00139     init_support(home);
00140     int literals = ts()->domsize*x.size();    
00141     for (int i = literals; i--; ) {
00142       SupportEntry** n = &(support_data[i]);
00143       SupportEntry*  o = p.support_data[i];
00144       while (o) {
00145         // Allocate new support entry
00146         SupportEntry* s = new (home) SupportEntry(o->t);
00147         // Link in support entry
00148         (*n) = s;
00149         n = &(s->next);
00150         // move to next one
00151         o = o->next;
00152       }
00153     }
00154   }
00155 
00156   template <class View>
00157   PropCost
00158   Incremental<View>::cost(ModEventDelta med) const {
00159     return (View::me(med) == ME_INT_VAL)
00160       ? PC_QUADRATIC_HI : PC_CUBIC_HI;
00161   }
00162 
00163   template <class View>
00164   Actor*
00165   Incremental<View>::copy(Space* home, bool share) {
00166     return new (home) Incremental<View>(home,share,*this);
00167   }
00168 
00169   template <class View>
00170   Gecode::Support::Symbol
00171   Incremental<View>::ati(void) {
00172     return Reflection::mangle<View>("Gecode::Int::Extensional::Incremental");
00173   }
00174 
00175   template <class View>
00176   Reflection::ActorSpec
00177   Incremental<View>::spec(const Space* home, Reflection::VarMap& m) const {
00178     Reflection::ActorSpec s(ati());
00179     return s << x.spec(home, m)
00180              << tupleSet.spec(m);
00181   }
00182 
00183   template <class View>
00184   void
00185   Incremental<View>::post(Space* home, Reflection::VarMap& vars,
00186                     const Reflection::ActorSpec& spec) {
00187     spec.checkArity(2);
00188     ViewArray<View> x(home, vars, spec[0]);
00189     TupleSet tupleSet(vars, spec[1]);
00190     (void) new (home) Incremental<View>(home,x,tupleSet);    
00191   }
00192 
00193   template <class View>
00194   ExecStatus
00195   Incremental<View>::propagate(Space* home, ModEventDelta) {
00196     assert(!work.empty() || unassigned==0);
00199     GECODE_AUTOARRAY(BitSet, dom, x.size());
00200     init_dom(home, dom);
00201 
00203     while (!work.empty()) {
00204       Work w = work.pop();
00205       if (dom[w.var].get(w.val-ts()->min)) {
00206         // Work is still relevant
00207         switch (w.work) {
00208         case WT_FIND_SUPPORT:
00209           find_support(home, dom, w.var, w.val);
00210           break;
00211         case WT_REMOVE_VALUE:
00212           {
00213             assert(support(w.var, w.val) == NULL);
00214             ModEvent me = x[w.var].nq(home,w.val);
00215             if (me_failed(me)) {
00216               return ES_FAILED;
00217             }
00218             dom[w.var].set(w.val-ts()->min, false);
00219           }
00220           break;
00221         default:
00222           GECODE_NEVER;
00223           break;
00224         };
00225       }
00226     }
00227     /*
00228     for (int i = 0; i < x.size(); ++i) {
00229       ViewValues<View> vv(x[i]);
00230       while(vv()) {
00231         assert(support(i, vv.val()) != NULL);
00232         ++vv;
00233       }
00234     }
00235     */
00236     if (unassigned != 0) {
00237       return ES_FIX;
00238     }
00239 
00240     return ES_SUBSUMED(this, home);
00241   }
00242 
00243 
00244 
00245   template <class View>
00246   forceinline void
00247   Incremental<View>::add_support(Space* home, Tuple l) {
00248     for (int i = x.size(); i--; ) {
00249       int pos = (i*ts()->domsize) + (l[i] - ts()->min);
00250 
00251       SupportEntry* s = new (home) SupportEntry(l, support_data[pos]);
00252       support_data[pos] = s;
00253     }
00254   }
00255 
00256   template <class View>
00257   forceinline void
00258   Incremental<View>::remove_support(Space* home, Tuple l,
00259                                     int var, int /*val*/) {
00260     for (int i = x.size(); i--; ) {
00261       int v = l[i];
00262       int ov = v - ts()->min;
00263       int pos = (i*(ts()->domsize)) + ov;
00264 
00265       assert(support_data[pos] != NULL);
00266       
00267       SupportEntry** a = &(support_data[pos]);
00268       while ((*a)->t != l) {
00269         assert((*a)->next != NULL);
00270         a = &((*a)->next);
00271       }
00272       SupportEntry* old = *a;
00273       *a = (*a)->next;
00274       
00275       old->dispose(home);
00276       if (i != var && support_data[pos] == NULL) {
00277         work.push(Work(WT_FIND_SUPPORT, i, v));
00278       }
00279     }
00280   }
00281 
00282   template <class View>
00283   forceinline void
00284   Incremental<View>::find_support(Space* home, Domain dom, int var, int val) {
00285     if (support(var, val) == NULL) {
00286       int oval = val - ts()->min;
00287       // Find support for value vv.val() in variable var
00288       Tuple l = Base<View,false>::find_support(dom, var, oval);
00289       if (l == NULL) {
00290         // No possible supports left
00291         work.push(Work(WT_REMOVE_VALUE, var, val));
00292       } else {
00293         // Mark values in support as supported
00294         add_support(home, l);
00295       }
00296     }
00297   }
00298 
00299   template <class View>
00300   forceinline void
00301   Incremental<View>::init_support(Space* home) {
00302     assert(support_data == NULL);
00303     int literals = ts()->domsize*x.size();
00304     support_data = static_cast<SupportEntry**>
00305       (home->alloc(literals*sizeof(SupportEntry*)));
00306     for (int i = literals; i--; ) {
00307       support_data[i] = NULL;
00308     }
00309   }
00310 
00311   template <class View>
00312   forceinline typename Incremental<View>::SupportEntry*
00313   Incremental<View>::support(int var, int val) {
00314     int oval = val - ts()->min;
00315     return support_data[(var*(ts()->domsize)) + oval];
00316   }
00317 
00318 
00319   // 
00320   // Advisor proper
00321   //
00322   template <class View>
00323   ExecStatus
00324   Incremental<View>::advise(Space *home, Advisor* a0, const Delta* d) {
00325     SupportAdvisor* a = static_cast<SupportAdvisor*>(a0);
00326     ModEvent me = View::modevent(d);
00327     bool scheduled = !work.empty();
00328 
00329     if (a->x.any(d)) {
00330       ViewValues<View> vv(a->x);
00331       for (int i = ts()->min; i <= ts()->max; ++i) {
00332         if (vv() && i == vv.val()) {
00333           ++vv;  
00334           continue;
00335         }
00336         while (SupportEntry* s = support(a->pos, i)) {
00337           remove_support(home, s->t, a->pos, i);
00338         }
00339       } 
00340     } else {
00341       int lo = a->x.min(d);
00342       int hi = a->x.max(d);
00343       for (int val = lo; val <= hi; ++val) {
00344         while (SupportEntry* s = support(a->pos, val)) {
00345           remove_support(home, s->t, a->pos, val);
00346         }
00347       }
00348     }
00349 
00350     
00351     if (me == ME_INT_VAL) {
00352       --unassigned;
00353       if ((work.empty() || scheduled) && unassigned!=0) {
00354         // nothing to do or already scheduled
00355         // propagator is not subsumed since unassigned!=0
00356         return ES_SUBSUMED_FIX(a,home,ac);
00357       }
00358       return ES_SUBSUMED_NOFIX(a,home,ac);
00359     }
00360     if (work.empty() || scheduled) {
00361       // nothing to do or already scheduled
00362       return ES_FIX;
00363     }
00364     return ES_NOFIX;
00365   }
00366   
00367 
00368   template <class View>
00369   size_t
00370   Incremental<View>::dispose(Space* home) {
00371     if (!home->failed()) {
00372       int literals = ts()->domsize*x.size();    
00373       for (int i = literals; i--; ) {
00374         if (support_data[i]) {
00375           SupportEntry* lastse = support_data[i];
00376           while (lastse->next) lastse = lastse->next;
00377           support_data[i]->dispose(home, lastse);
00378         }
00379       }
00380       home->reuse(support_data, sizeof(SupportEntry*)*literals);
00381     }
00382     work.~WorkStack();
00383     (void) ac.dispose(home);
00384 
00385     (void) Base<View,false>::dispose(home);
00386 
00387     return sizeof(*this);
00388   }
00389 
00390 }}}
00391 
00392 // STATISTICS: int-prop
00393