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

val.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Contributing authors:
00006  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00007  *
00008  *  Copyright:
00009  *     Christian Schulte, 2006
00010  *     Mikael Lagerkvist, 2006
00011  *
00012  *  Last modified:
00013  *     $Date: 2006-08-04 16:03:26 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00014  *     $Revision: 3512 $
00015  *
00016  *  This file is part of Gecode, the generic constraint
00017  *  development environment:
00018  *     http://www.gecode.org
00019  *
00020  *  See the file "LICENSE" for information on usage and
00021  *  redistribution of this file, and for a
00022  *     DISCLAIMER OF ALL WARRANTIES.
00023  *
00024  */
00025 
00026 #include "gecode/iter.hh"
00027 
00028 namespace Gecode { namespace Int { namespace Channel {
00029 
00034   template <class View>
00035   class ValInfo {
00036   public:
00038     View view;
00040     bool a;
00042     static ValInfo<View>* allocate(Space* home, int n);
00044     void init(View x, int n);
00046     void update(Space* home, bool share, ValInfo<View>& vi);
00048     bool doval(void) const;
00050     bool dodom(void) const;
00052     void assigned(void);
00054     void removed(int i);
00056     void done(void);
00057   };
00058 
00059   template <class View>
00060   forceinline ValInfo<View>*
00061   ValInfo<View>::allocate(Space* home, int n) {
00062     return reinterpret_cast<ValInfo<View>*>
00063       (home->alloc(n*sizeof(ValInfo<View>)));
00064   }
00065 
00066   template <class View>
00067   forceinline void
00068   ValInfo<View>::init(View x, int) {
00069     view = x; a = false;
00070   }
00071 
00072   template <class View>
00073   forceinline void
00074   ValInfo<View>::update(Space* home, bool share, ValInfo<View>& vi) {
00075     view.update(home,share,vi.view); a = vi.a;
00076   }
00077 
00078   template <class View>
00079   forceinline bool
00080   ValInfo<View>::doval(void) const {
00081     return !a && view.assigned();
00082   }
00083 
00084   template <class View>
00085   forceinline bool
00086   ValInfo<View>::dodom(void) const {
00087     return false;
00088   }
00089 
00090   template <class View>
00091   forceinline void
00092   ValInfo<View>::assigned(void) {
00093     a = true;
00094   }
00095 
00096   template <class View>
00097   forceinline void
00098   ValInfo<View>::removed(int) {}
00099 
00100   template <class View>
00101   forceinline void
00102   ValInfo<View>::done(void) {}
00103 
00104 
00105   // Propagate assigned views for x
00106   template <class View, class Info>
00107   ExecStatus
00108   doprop_val(Space* home, int n, Info* x, Info* y,
00109              int& n_na, ProcessStack& xa, ProcessStack& ya) {
00110     do {
00111       int i = xa.pop();
00112       int j = x[i].view.val();
00113       // Assign the y variable to i (or test if already assigned!)
00114       {
00115         ModEvent me = y[j].view.eq(home,i);
00116         if (me_failed(me))
00117           return ES_FAILED;
00118         // Record that y[j] has been assigned and must be propagated
00119         if (me_modified(me))
00120           ya.push(j);
00121       }
00122       // Prune the value j from all x variables
00123       for (int k=i; k--; ) {
00124         ModEvent me = x[k].view.nq(home,j);
00125         if (me_failed(me))
00126           return ES_FAILED;
00127         if (me_modified(me))
00128           if (me == ME_INT_VAL) {
00129             // Record that x[k] has been assigned and must be propagated
00130             xa.push(k);
00131           } else {
00132             // One value has been removed and this removal does not need
00133             // to be propagated again: after all y[j] = i, so it holds
00134             // that y[j] != k.
00135             x[k].removed(j);
00136           }
00137       }
00138       // The same for the other views
00139       for (int k=i+1; k<n; k++) {
00140         ModEvent me = x[k].view.nq(home,j);
00141         if (me_failed(me))
00142           return ES_FAILED;
00143         if (me_modified(me))
00144           if (me == ME_INT_VAL) {
00145             // Record that x[k] has been assigned and must be propagated
00146             xa.push(k);
00147           } else {
00148             // One value has been removed and this removal does not need
00149             // to be propagated again: after all y[j] = i, so it holds
00150             // that y[j] != k.
00151             x[k].removed(j);
00152           }
00153       }
00154       x[i].assigned(); n_na--;
00155     } while (!xa.empty());
00156     return ES_OK;
00157   }
00158 
00159   // Just do a test whether a call to the routine is necessary
00160   template <class View, class Info>
00161   forceinline ExecStatus
00162   prop_val(Space* home, int n, Info* x, Info* y,
00163            int& n_na, ProcessStack& xa, ProcessStack& ya) {
00164     if (xa.empty())
00165       return ES_OK;
00166     return doprop_val<View,Info>(home,n,x,y,n_na,xa,ya);
00167   }
00168 
00169   /*
00170    * The actual propagator
00171    *
00172    */
00173   template <class View>
00174   forceinline
00175   Val<View>::Val(Space* home, int n, ValInfo<View>* xy)
00176     : Base<ValInfo<View>,PC_INT_VAL>(home,n,xy) {}
00177 
00178   template <class View>
00179   forceinline
00180   Val<View>::Val(Space* home, bool share, Val<View>& p)
00181     : Base<ValInfo<View>,PC_INT_VAL>(home,share,p) {}
00182 
00183   template <class View>
00184   Actor*
00185   Val<View>::copy(Space* home, bool share) {
00186     return new (home) Val<View>(home,share,*this);
00187   }
00188 
00189   template <class View>
00190   ExecStatus
00191   Val<View>::propagate(Space* home) {
00192     GECODE_AUTOARRAY(int, __xa, n+1);
00193     GECODE_AUTOARRAY(int, __ya, n+1);
00194     ProcessStack xa(__xa);
00195     ProcessStack ya(__ya);
00196 
00197     ValInfo<View>* x = xy;
00198     ValInfo<View>* y = xy+n;
00199 
00200     // Scan x and y for assigned but not yet propagated views
00201     for (int i = n; i--; ) {
00202       if (x[i].doval()) xa.push(i);
00203       if (y[i].doval()) ya.push(i);
00204     }
00205 
00206     do {
00207       // Propagate assigned views for x
00208       if (prop_val<View,ValInfo<View> >(home,n,x,y,n_na,xa,ya) == ES_FAILED)
00209         return ES_FAILED;
00210       // Propagate assigned views for y
00211       if (prop_val<View,ValInfo<View> >(home,n,y,x,n_na,ya,xa) == ES_FAILED)
00212         return ES_FAILED;
00213       assert(ya.empty());
00214     } while (!xa.empty());
00215 
00216     return (n_na == 0) ? ES_SUBSUMED : ES_FIX;
00217   }
00218 
00219   template <class View>
00220   ExecStatus
00221   Val<View>::post(Space* home, int n, ValInfo<View>* xy) {
00222     assert(n > 0);
00223     if (n == 1) {
00224       GECODE_ME_CHECK(xy[0].view.eq(home,0));
00225       GECODE_ME_CHECK(xy[1].view.eq(home,0));
00226       return ES_OK;
00227     }
00228     for (int i=2*n; i--; ) {
00229       GECODE_ME_CHECK(xy[i].view.gq(home,0));
00230       GECODE_ME_CHECK(xy[i].view.le(home,n));
00231     }
00232     (void) new (home) Val<View>(home,n,xy);
00233     return ES_OK;
00234   }
00235 
00236 }}}
00237 
00238 // STATISTICS: int-prop
00239