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

int-dom.icc

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, 2006
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-07-11 09:28:48 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00011  *     $Revision: 7285 $
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 Linear {
00039 
00047   class SupportSet {
00048   private:
00050     static const unsigned int bpui = sizeof(unsigned int) * 8;
00052     unsigned int* bits;
00053   public:
00055     void init(unsigned int n);
00057     void support(unsigned int i);
00059     bool supported(unsigned int i) const;
00060 
00061   private:
00063     class ResultIter : public ViewValues<IntView> {
00064     protected:
00066       const SupportSet* s;
00068       unsigned int p;
00069     public:
00071       ResultIter(const SupportSet* s0, const IntView& x);
00073       void operator++(void);
00074     };
00075 
00076   public:
00078     ModEvent tell(Space* home, IntView& x) const;
00080     void dispose(void);
00081   };
00082 
00087   template <class Val>
00088   class SupportIter {
00089   protected:
00091     int           a;
00093     IntView       x;
00095     SupportSet    s;
00097     int           c;
00099     unsigned int  p;
00101     Val           l;
00103     Val           u;
00104   public:
00106     void init(int a, const IntView& x, Val l, Val u);
00108     void support(void);
00110     ModEvent tell(Space* home);
00112     void dispose(void);
00113   };
00114 
00115 
00120   template <class Val>
00121   class PosSupportIter : public SupportIter<Val> {
00122   private:
00124     IntVarImpFwd i;
00125     // Using-declarations for dependant names
00126     using SupportIter<Val>::a;
00127     using SupportIter<Val>::x;
00128     using SupportIter<Val>::s;
00129     using SupportIter<Val>::c;
00130     using SupportIter<Val>::p;
00131     using SupportIter<Val>::l;
00132     using SupportIter<Val>::u;
00133   public:
00135     bool reset(Val& d);
00137     bool adjust(Val& d);
00138   };
00139 
00140 
00145   template <class Val>
00146   class NegSupportIter : public SupportIter<Val> {
00147   private:
00149     IntVarImpBwd i;
00150     // Using-declarations for dependant names
00151     using SupportIter<Val>::a;
00152     using SupportIter<Val>::x;
00153     using SupportIter<Val>::s;
00154     using SupportIter<Val>::c;
00155     using SupportIter<Val>::p;
00156     using SupportIter<Val>::l;
00157     using SupportIter<Val>::u;
00158   public:
00160     bool reset(Val& d);
00162     bool adjust(Val& d);
00163   };
00164 
00165 
00166   /*
00167    * Support set
00168    *
00169    */
00170   forceinline void
00171   SupportSet::init(unsigned int n) {
00172     bits = Memory::bmalloc<unsigned int>((n / bpui) + 1);
00173     for (unsigned int i = (n / bpui) + 1; i--; )
00174       bits[i] = 0;
00175   }
00176   forceinline void
00177   SupportSet::support(unsigned int i) {
00178     unsigned int p = i / bpui;
00179     bits[p] |= 1 << (i-p*bpui);
00180   }
00181   forceinline bool
00182   SupportSet::supported(unsigned int i) const {
00183     unsigned int p = i / bpui;
00184     return (bits[p] & (1 << (i-p*bpui))) != 0;
00185   }
00186 
00187   forceinline
00188   SupportSet::ResultIter::ResultIter(const SupportSet* s0, const IntView& x)
00189     : ViewValues<IntView>(x), s(s0), p(0) {
00190     while (ViewValues<IntView>::operator()() && s->supported(p)) {
00191       ViewValues<IntView>::operator++(); ++p;
00192     }
00193   }
00194   forceinline void
00195   SupportSet::ResultIter::operator++(void) {
00196     do {
00197       ViewValues<IntView>::operator++(); ++p;
00198     } while (ViewValues<IntView>::operator()() && s->supported(p));
00199   }
00200 
00201 
00202   inline ModEvent
00203   SupportSet::tell(Space* home, IntView& x) const {
00204     unsigned int n = x.size() / bpui;
00205     // Check whether all bits are zero: failure
00206     for (unsigned int i=n+1; i--; )
00207       if (bits[i] != 0)
00208         goto all;
00209     return ME_INT_FAILED;
00210   all:
00211     // Check whether all bits are one: nothing changed
00212     for (unsigned int i=n; i--; )
00213       if (bits[i] != ~0U)
00214         goto tell;
00215     // Now check the bits in the last word
00216     for (unsigned int i=n*bpui; i<x.size(); i++)
00217       if (!supported(i))
00218         goto tell;
00219     return ME_INT_NONE;
00220   tell:
00221     {
00222       ResultIter i(this,x);
00223       return x.minus_v(home,i);
00224     }
00225   }
00226 
00227   forceinline void
00228   SupportSet::dispose(void) {
00229     Memory::free(bits);
00230   }
00231 
00232 
00233   /*
00234    * Base-class for support-based iterator
00235    *
00236    */
00237   template <class Val>
00238   forceinline void
00239   SupportIter<Val>::init(int a0, const IntView& x0, Val l0, Val u0) {
00240     a=a0; x=x0; l=l0; u=u0;
00241     s.init(x.size());
00242   }
00243   template <class Val>
00244   forceinline void
00245   SupportIter<Val>::support(void) {
00246     s.support(p);
00247   }
00248   template <class Val>
00249   forceinline ModEvent
00250   SupportIter<Val>::tell(Space* home) {
00251     return s.tell(home,x);
00252   }
00253   template <class Val>
00254   forceinline void
00255   SupportIter<Val>::dispose(void) {
00256     s.dispose();
00257   }
00258 
00259 
00260   /*
00261    * Support-based iterator for positive view
00262    *
00263    */
00264   template <class Val>
00265   forceinline bool
00266   PosSupportIter<Val>::reset(Val& d) {
00267     // Way too small, no value can make it big enough
00268     if (d + static_cast<Val>(a)*x.max() < u)
00269       return false;
00270     // Restart iterator and position of values
00271     i.init(x.var()); p = 0;
00272     // Skip all ranges which are too small
00273     while (d + static_cast<Val>(a)*i.max() < u) {
00274       p += i.width(); ++i;
00275     }
00276     // There is at least one range left (check of max)
00277     assert(i());
00278     // Initialize current range and adjust value
00279     c = i.min();
00280     // Skip all values which are too small
00281     while (d + static_cast<Val>(a)*c < u) {
00282       p++; c++;
00283     }
00284     // Adjust to new value
00285     d += static_cast<Val>(a) * c;
00286     return true;
00287   }
00288   template <class Val>
00289   forceinline bool
00290   PosSupportIter<Val>::adjust(Val& d) {
00291     // Current value
00292     Val v = static_cast<Val>(a) * c;
00293     // Subtract current value from d
00294     d -= v;
00295     // Move to next position (number of value)
00296     p++;
00297     // Still in the same range
00298     if (c < i.max()) {
00299       // Decrement current values
00300       c += 1; v += a;
00301     } else {
00302       // Go to next range
00303       ++i;
00304       if (!i())
00305         return false;
00306       c = i.min(); v = static_cast<Val>(a) * c;
00307     }
00308     // Is d with the current value too large?
00309     if (d + v > l)
00310       return false;
00311     // Update d
00312     d += v;
00313     return true;
00314   }
00315 
00316 
00317   /*
00318    * Support-based iterator for negative view
00319    *
00320    */
00321   template <class Val>
00322   forceinline bool
00323   NegSupportIter<Val>::reset(Val& d) {
00324     // Way too small, no value can make it big enough
00325     if (d + static_cast<Val>(a)*x.min() < u)
00326       return false;
00327     // Restart iterator and position of values
00328     i.init(x.var()); p = x.size()-1;
00329     // Skip all ranges which are too small
00330     while (d + static_cast<Val>(a)*i.min() < u) {
00331       p -= i.width(); ++i;
00332     }
00333     // There is at least one range left (check of max)
00334     assert(i());
00335     // Initialize current range
00336     c = i.max();
00337     // Skip all values which are too small
00338     while (d + static_cast<Val>(a)*c < u) {
00339       p--; c--;
00340     }
00341     // Adjust to new value
00342     d += static_cast<Val>(a) * c;
00343     return true;
00344   }
00345   template <class Val>
00346   forceinline bool
00347   NegSupportIter<Val>::adjust(Val& d) {
00348     // Current value
00349     Val v = static_cast<Val>(a) * c;
00350     // Subtract current value from d
00351     d -= v;
00352     // Move to next position (number of value)
00353     p--;
00354     // Still in the same range
00355     if (c > i.min()) {
00356       // Decrement current values
00357       c -= 1; v -= a;
00358     } else {
00359       // Go to next range
00360       ++i;
00361       if (!i())
00362         return false;
00363       c = i.max(); v = static_cast<Val>(a) * c;
00364     }
00365     // Is d with the current value too large?
00366     if (d + v > l)
00367       return false;
00368     // Update d
00369     d += v;
00370     return true;
00371   }
00372 
00373 
00374 
00375   /*
00376    * The domain consisten equality propagator
00377    *
00378    */
00379   template <class Val, class View>
00380   forceinline
00381   DomEq<Val,View>::DomEq(Space* home,
00382                          ViewArray<View >& x, ViewArray<View >& y,
00383                          Val c)
00384     : Lin<Val,View,View,PC_INT_DOM>(home,x,y,c) {}
00385 
00386   template <class Val, class View>
00387   ExecStatus
00388   DomEq<Val,View>::post(Space* home,
00389                         ViewArray<View>& x, ViewArray<View>& y,
00390                         Val c) {
00391     (void) new (home) DomEq<Val,View>(home,x,y,c);
00392     return ES_OK;
00393   }
00394 
00395   template <class Val, class View>
00396   forceinline
00397   DomEq<Val,View>::DomEq(Space* home, bool share, DomEq<Val,View>& p)
00398     : Lin<Val,View,View,PC_INT_DOM>(home,share,p) {}
00399 
00400   template <class Val, class View>
00401   Actor*
00402   DomEq<Val,View>::copy(Space* home, bool share) {
00403     return new (home) DomEq<Val,View>(home,share,*this);
00404   }
00405 
00406   template <class Val, class View>
00407   PropCost
00408   DomEq<Val,View>::cost(ModEventDelta med) const {
00409     return (View::me(med) != ME_INT_DOM)
00410       ? cost_hi(x.size()+y.size(),PC_LINEAR_LO)
00411       : cost_hi(x.size()+y.size(),PC_CRAZY_HI);
00412   }
00413 
00414   template <class Val, class View>
00415   inline Support::Symbol
00416   DomEq<Val,View>::ati(void) {
00417     return Reflection::mangle<Val,View>("Gecode::Int::Linear::DomEq");
00418   }
00419 
00420   template <class Val, class View>
00421   Reflection::ActorSpec
00422   DomEq<Val,View>::spec(const Space* home, Reflection::VarMap& m) const {
00423     return Lin<Val,View,View,PC_INT_DOM>::spec(home, m, ati());
00424   }
00425   
00426   template <class Val, class View>
00427   void
00428   DomEq<Val,View>::post(Space* home, Reflection::VarMap& vars,
00429                         const Reflection::ActorSpec& spec) {
00430     spec.checkArity(3);
00431     ViewArray<View> x(home, vars, spec[0]);
00432     ViewArray<View> y(home, vars, spec[1]);
00433     Val c = spec[2]->toInt();
00434     (void) new (home) DomEq<Val,View>(home, x, y, c);
00435   }  
00436 
00437   template <class Val, class View>
00438   ExecStatus
00439   DomEq<Val,View>::propagate(Space* home, ModEventDelta med) {
00440     if (View::me(med) != ME_INT_DOM) {
00441       ExecStatus es = prop_bnd<Val,View,View>(home,med,this,x,y,c);
00442       GECODE_ES_CHECK(es);
00443       return ES_FIX_PARTIAL(this,View::med(ME_INT_DOM));
00444     }
00445 
00446     // Value of equation for partial assignment
00447     Val d = -c;
00448 
00449     int n = x.size();
00450     int m = y.size();
00451 
00452     // Create support-base iterators
00453     GECODE_AUTOARRAY(PosSupportIter<Val>, xp, n);
00454     GECODE_AUTOARRAY(NegSupportIter<Val>, yp, m);
00455 
00456     // Initialize views for assignments
00457     {
00458       Val l = 0;
00459       Val u = 0;
00460       for (int j=m; j--; ) {
00461         yp[j].init(-y[j].scale(),y[j].base(),l,u);
00462         l += y[j].max(); u += y[j].min();
00463       }
00464       for (int i=n; i--; ) {
00465         xp[i].init(x[i].scale(),x[i].base(),l,u);
00466         l -= x[i].min(); u -= x[i].max();
00467       }
00468     }
00469 
00470     // Collect support information by iterating assignments
00471     {
00472       // Force reset of all iterators in first round
00473       int i = 0;
00474       int j = 0;
00475 
00476     next_i:
00477       // Reset all iterators for positive views and update d
00478       while (i<n) {
00479         if (!xp[i].reset(d)) goto prev_i;
00480         i++;
00481       }
00482     next_j:
00483       // Reset all iterators for negative views and update d
00484       while (j<m) {
00485         if (!yp[j].reset(d)) goto prev_j;
00486         j++;
00487       }
00488       // Check whether current assignment is solution
00489       if (d == 0) {
00490         // Record support
00491         for (int is=n; is--; ) xp[is].support();
00492         for (int js=m; js--; ) yp[js].support();
00493       }
00494     prev_j:
00495       // Try iterating to next assignment: negative views
00496       while (j>0) {
00497         if (yp[j-1].adjust(d)) goto next_j;
00498         j--;
00499       }
00500     prev_i:
00501       // Try iterating to next assignment: positive views
00502       while (i>0) {
00503         if (xp[i-1].adjust(d)) goto next_i;
00504         i--;
00505       }
00506     }
00507 
00508     // Tell back new variable domains
00509     ExecStatus es = ES_NOFIX;
00510     for (int i=n; i--; ) {
00511       ModEvent me = xp[i].tell(home);
00512       if (me_failed(me)) {
00513         es = ES_FAILED; goto dispose;
00514       }
00515       if (!x[i].assigned())
00516         es = ES_FIX;
00517     }
00518     for (int j=m; j--; ) {
00519       ModEvent me = yp[j].tell(home);
00520       if (me_failed(me)) {
00521         es = ES_FAILED; goto dispose;
00522       }
00523       if (!y[j].assigned())
00524         es = ES_FIX;
00525     }
00526 
00527     // Release memory
00528   dispose:
00529     for (int i=n; i--; ) xp[i].dispose();
00530     for (int j=m; j--; ) yp[j].dispose();
00531 
00532     if (es == ES_NOFIX)
00533       return ES_SUBSUMED(this,sizeof(*this));
00534     return es;
00535   }
00536 
00537 }}}
00538 
00539 // STATISTICS: int-prop