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

val.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  *  Contributing authors:
00007  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00008  *
00009  *  Copyright:
00010  *     Christian Schulte, 2006
00011  *     Mikael Lagerkvist, 2006
00012  *
00013  *  Last modified:
00014  *     $Date: 2008-07-11 09:32:27 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00015  *     $Revision: 7289 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */
00041 
00042 namespace Gecode { namespace Int { namespace Channel {
00043 
00048   template <class View>
00049   class ValInfo {
00050   public:
00052     View view;
00054     bool a;
00056     static ValInfo<View>* allocate(Space* home, int n);
00058     void init(View x, int n);
00060     void update(Space* home, bool share, ValInfo<View>& vi);
00062     bool doval(void) const;
00064     bool dodom(void) const;
00066     void assigned(void);
00068     void removed(int i);
00070     void done(void);
00071   };
00072 
00073   template <class View>
00074   forceinline ValInfo<View>*
00075   ValInfo<View>::allocate(Space* home, int n) {
00076     return static_cast<ValInfo<View>*>
00077       (home->alloc(n*sizeof(ValInfo<View>)));
00078   }
00079 
00080   template <class View>
00081   forceinline void
00082   ValInfo<View>::init(View x, int) {
00083     view = x; a = false;
00084   }
00085 
00086   template <class View>
00087   forceinline void
00088   ValInfo<View>::update(Space* home, bool share, ValInfo<View>& vi) {
00089     view.update(home,share,vi.view); a = vi.a;
00090   }
00091 
00092   template <class View>
00093   forceinline bool
00094   ValInfo<View>::doval(void) const {
00095     return !a && view.assigned();
00096   }
00097 
00098   template <class View>
00099   forceinline bool
00100   ValInfo<View>::dodom(void) const {
00101     return false;
00102   }
00103 
00104   template <class View>
00105   forceinline void
00106   ValInfo<View>::assigned(void) {
00107     a = true;
00108   }
00109 
00110   template <class View>
00111   forceinline void
00112   ValInfo<View>::removed(int) {}
00113 
00114   template <class View>
00115   forceinline void
00116   ValInfo<View>::done(void) {}
00117 
00118 
00119   // Propagate assigned views for x
00120   template <class View, class Info>
00121   ExecStatus
00122   doprop_val(Space* home, int n, Info* x, Info* y,
00123              int& n_na, ProcessStack& xa, ProcessStack& ya) {
00124     do {
00125       int i = xa.pop();
00126       int j = x[i].view.val();
00127       // Assign the y variable to i (or test if already assigned!)
00128       {
00129         ModEvent me = y[j].view.eq(home,i);
00130         if (me_failed(me))
00131           return ES_FAILED;
00132         // Record that y[j] has been assigned and must be propagated
00133         if (me_modified(me))
00134           ya.push(j);
00135       }
00136       // Prune the value j from all x variables
00137       for (int k=i; k--; ) {
00138         ModEvent me = x[k].view.nq(home,j);
00139         if (me_failed(me))
00140           return ES_FAILED;
00141         if (me_modified(me)) {
00142           if (me == ME_INT_VAL) {
00143             // Record that x[k] has been assigned and must be propagated
00144             xa.push(k);
00145           } else {
00146             // One value has been removed and this removal does not need
00147             // to be propagated again: after all y[j] = i, so it holds
00148             // that y[j] != k.
00149             x[k].removed(j);
00150           }
00151         }
00152       }
00153       // The same for the other views
00154       for (int k=i+1; k<n; k++) {
00155         ModEvent me = x[k].view.nq(home,j);
00156         if (me_failed(me))
00157           return ES_FAILED;
00158         if (me_modified(me)) {
00159           if (me == ME_INT_VAL) {
00160             // Record that x[k] has been assigned and must be propagated
00161             xa.push(k);
00162           } else {
00163             // One value has been removed and this removal does not need
00164             // to be propagated again: after all y[j] = i, so it holds
00165             // that y[j] != k.
00166             x[k].removed(j);
00167           }
00168         }
00169       }
00170       x[i].assigned(); n_na--;
00171     } while (!xa.empty());
00172     return ES_OK;
00173   }
00174 
00175   // Just do a test whether a call to the routine is necessary
00176   template <class View, class Info>
00177   forceinline ExecStatus
00178   prop_val(Space* home, int n, Info* x, Info* y,
00179            int& n_na, ProcessStack& xa, ProcessStack& ya) {
00180     if (xa.empty())
00181       return ES_OK;
00182     return doprop_val<View,Info>(home,n,x,y,n_na,xa,ya);
00183   }
00184 
00185   /*
00186    * The actual propagator
00187    *
00188    */
00189   template <class View, bool shared>
00190   forceinline
00191   Val<View,shared>::Val(Space* home, int n, ValInfo<View>* xy)
00192     : Base<ValInfo<View>,PC_INT_VAL>(home,n,xy) {}
00193 
00194   template <class View, bool shared>
00195   forceinline
00196   Val<View,shared>::Val(Space* home, bool share, Val<View,shared>& p)
00197     : Base<ValInfo<View>,PC_INT_VAL>(home,share,p) {}
00198 
00199   template <class View, bool shared>
00200   Actor*
00201   Val<View,shared>::copy(Space* home, bool share) {
00202     return new (home) Val<View,shared>(home,share,*this);
00203   }
00204 
00205   template <class View, bool shared>
00206   ExecStatus
00207   Val<View,shared>::propagate(Space* home, ModEventDelta) {
00208     GECODE_AUTOSTACK(int,-1, xa, n);
00209     GECODE_AUTOSTACK(int,-1, ya, n);
00210 
00211     ValInfo<View>* x = xy;
00212     ValInfo<View>* y = xy+n;
00213 
00214     // Scan x and y for assigned but not yet propagated views
00215     for (int i = n; i--; ) {
00216       if (x[i].doval()) xa.push(i);
00217       if (y[i].doval()) ya.push(i);
00218     }
00219 
00220     do {
00221       // Propagate assigned views for x
00222       GECODE_ES_CHECK((prop_val<View,ValInfo<View> >(home,n,x,y,n_na,xa,ya)));
00223       // Propagate assigned views for y
00224       GECODE_ES_CHECK((prop_val<View,ValInfo<View> >(home,n,y,x,n_na,ya,xa)));
00225       assert(ya.empty());
00226     } while (!xa.empty());
00227 
00228     if (n_na == 0) 
00229       return ES_SUBSUMED(this,home);
00230     return shared ? ES_NOFIX : ES_FIX;
00231   }
00232 
00233   template <class View, bool shared>
00234   Support::Symbol
00235   Val<View,shared>::ati(void) {
00236     return Reflection::mangle<View>("Gecode::Int::Channel::Val",shared);
00237   }
00238 
00239   template <class View, bool shared>
00240   Reflection::ActorSpec
00241   Val<View,shared>::spec(const Space* home, Reflection::VarMap& m) const {
00242     return Base<ValInfo<View>,PC_INT_VAL>::spec(home, m, ati());
00243   }
00244 
00245   template <class View, bool shared>
00246   void
00247   Val<View,shared>::post(Space* home, Reflection::VarMap& vars,
00248                          const Reflection::ActorSpec& spec) {
00249     const int n = spec.noOfArgs();
00250     ValInfo<View>* vi
00251       = ValInfo<View>::allocate(home,n);
00252     for (int i=0; i<n; i++) {
00253       vi[i].init(View(home, vars, spec[i]),n/2);
00254     }
00255     (void) new (home) Val<View,shared>(home,n/2,vi);
00256   }
00257 
00258   template <class View, bool shared>
00259   ExecStatus
00260   Val<View,shared>::post(Space* home, int n, ValInfo<View>* xy) {
00261     assert(n > 0);
00262     if (n == 1) {
00263       GECODE_ME_CHECK(xy[0].view.eq(home,0));
00264       GECODE_ME_CHECK(xy[1].view.eq(home,0));
00265       return ES_OK;
00266     }
00267     for (int i=2*n; i--; ) {
00268       GECODE_ME_CHECK(xy[i].view.gq(home,0));
00269       GECODE_ME_CHECK(xy[i].view.le(home,n));
00270     }
00271     (void) new (home) Val<View,shared>(home,n,xy);
00272     return ES_OK;
00273   }
00274 
00275 }}}
00276 
00277 // STATISTICS: int-prop
00278