Generated on Thu Mar 22 10:39:35 2012 for Gecode by doxygen 1.6.3

val.hpp

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: 2011-04-01 15:26:13 +0200 (Fri, 01 Apr 2011) $ by $Author: tack $
00015  *     $Revision: 11858 $
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     void init(View x, int n);
00058     void update(Space& home, bool share, ValInfo<View>& vi);
00060     bool doval(void) const;
00062     bool dodom(void) const;
00064     void assigned(void);
00066     void removed(int i);
00068     void done(void);
00069   };
00070 
00071   template<class View>
00072   forceinline void
00073   ValInfo<View>::init(View x, int) {
00074     view = x; a = false;
00075   }
00076 
00077   template<class View>
00078   forceinline void
00079   ValInfo<View>::update(Space& home, bool share, ValInfo<View>& vi) {
00080     view.update(home,share,vi.view); a = vi.a;
00081   }
00082 
00083   template<class View>
00084   forceinline bool
00085   ValInfo<View>::doval(void) const {
00086     return !a && view.assigned();
00087   }
00088 
00089   template<class View>
00090   forceinline bool
00091   ValInfo<View>::dodom(void) const {
00092     return false;
00093   }
00094 
00095   template<class View>
00096   forceinline void
00097   ValInfo<View>::assigned(void) {
00098     a = true;
00099   }
00100 
00101   template<class View>
00102   forceinline void
00103   ValInfo<View>::removed(int) {}
00104 
00105   template<class View>
00106   forceinline void
00107   ValInfo<View>::done(void) {}
00108 
00109 
00110   // Propagate assigned views for x
00111   template<class View, class Offset, class Info>
00112   ExecStatus
00113   doprop_val(Space& home, int n, Info* x, Offset& ox,
00114              Info* y, Offset& oy,
00115              int& n_na, ProcessStack& xa, ProcessStack& ya) {
00116     do {
00117       int i = xa.pop();
00118       int j = ox(x[i].view).val();
00119       // Assign the y variable to i (or test if already assigned!)
00120       {
00121         ModEvent me = oy(y[j].view).eq(home,i);
00122         if (me_failed(me)) {
00123           return ES_FAILED;
00124         }
00125         // Record that y[j] has been assigned and must be propagated
00126         if (me_modified(me))
00127           ya.push(j);
00128       }
00129       // Prune the value j from all x variables
00130       for (int k=i; k--; ) {
00131         ModEvent me = ox(x[k].view).nq(home,j);
00132         if (me_failed(me)) {
00133           return ES_FAILED;
00134         }
00135         if (me_modified(me)) {
00136           if (me == ME_INT_VAL) {
00137             // Record that x[k] has been assigned and must be propagated
00138             xa.push(k);
00139           } else {
00140             // One value has been removed and this removal does not need
00141             // to be propagated again: after all y[j] = i, so it holds
00142             // that y[j] != k.
00143             x[k].removed(j);
00144           }
00145         }
00146       }
00147       // The same for the other views
00148       for (int k=i+1; k<n; k++) {
00149         ModEvent me = ox(x[k].view).nq(home,j);
00150         if (me_failed(me)) {
00151           return ES_FAILED;
00152         }
00153         if (me_modified(me)) {
00154           if (me == ME_INT_VAL) {
00155             // Record that x[k] has been assigned and must be propagated
00156             xa.push(k);
00157           } else {
00158             // One value has been removed and this removal does not need
00159             // to be propagated again: after all y[j] = i, so it holds
00160             // that y[j] != k.
00161             x[k].removed(j);
00162           }
00163         }
00164       }
00165       x[i].assigned(); n_na--;
00166     } while (!xa.empty());
00167     return ES_OK;
00168   }
00169 
00170   // Just do a test whether a call to the routine is necessary
00171   template<class View, class Offset, class Info>
00172   forceinline ExecStatus
00173   prop_val(Space& home, int n, Info* x, Offset& ox, Info* y, Offset& oy,
00174            int& n_na, ProcessStack& xa, ProcessStack& ya) {
00175     if (xa.empty())
00176       return ES_OK;
00177     return doprop_val<View,Offset,Info>(home,n,x,ox,y,oy,n_na,xa,ya);
00178   }
00179 
00180   /*
00181    * The actual propagator
00182    *
00183    */
00184   template<class View, class Offset, bool shared>
00185   forceinline
00186   Val<View,Offset,shared>::Val(Home home, int n, ValInfo<View>* xy,
00187                                Offset& ox, Offset& oy)
00188     : Base<ValInfo<View>,Offset,PC_INT_VAL>(home,n,xy,ox,oy) {}
00189 
00190   template<class View, class Offset, bool shared>
00191   forceinline
00192   Val<View,Offset,shared>::Val(Space& home, bool share, 
00193                                Val<View,Offset,shared>& p)
00194     : Base<ValInfo<View>,Offset,PC_INT_VAL>(home,share,p) {}
00195 
00196   template<class View, class Offset, bool shared>
00197   Actor*
00198   Val<View,Offset,shared>::copy(Space& home, bool share) {
00199     return new (home) Val<View,Offset,shared>(home,share,*this);
00200   }
00201 
00202   template<class View, class Offset, bool shared>
00203   ExecStatus
00204   Val<View,Offset,shared>::propagate(Space& home, const ModEventDelta&) {
00205     Region r(home);
00206     ProcessStack xa(r,n);
00207     ProcessStack ya(r,n);
00208 
00209     ValInfo<View>* x = xy;
00210     ValInfo<View>* y = xy+n;
00211 
00212     // Scan x and y for assigned but not yet propagated views
00213     for (int i = n; i--; ) {
00214       if (x[i].doval()) xa.push(i);
00215       if (y[i].doval()) ya.push(i);
00216     }
00217 
00218     do {
00219       // Propagate assigned views for x
00220       GECODE_ES_CHECK((prop_val<View,Offset,ValInfo<View> >
00221                        (home,n,x,ox,y,oy,n_na,xa,ya)));
00222       // Propagate assigned views for y
00223       GECODE_ES_CHECK((prop_val<View,Offset,ValInfo<View> >
00224                        (home,n,y,oy,x,ox,n_na,ya,xa)));
00225       assert(ya.empty());
00226     } while (!xa.empty());
00227 
00228     if (n_na == 0)
00229       return home.ES_SUBSUMED(*this);
00230     return shared ? ES_NOFIX : ES_FIX;
00231   }
00232 
00233   template<class View, class Offset, bool shared>
00234   ExecStatus
00235   Val<View,Offset,shared>::post(Home home, int n, ValInfo<View>* xy,
00236                                 Offset& ox, Offset& oy) {
00237     assert(n > 0);
00238     if (n == 1) {
00239       GECODE_ME_CHECK(ox(xy[0].view).eq(home,0));
00240       GECODE_ME_CHECK(oy(xy[1].view).eq(home,0));
00241       return ES_OK;
00242     }
00243     for (int i=n; i--; ) {
00244       GECODE_ME_CHECK(ox(xy[i  ].view).gq(home,0));
00245       GECODE_ME_CHECK(ox(xy[i  ].view).le(home,n));
00246       GECODE_ME_CHECK(oy(xy[i+n].view).gq(home,0));
00247       GECODE_ME_CHECK(oy(xy[i+n].view).le(home,n));
00248     }
00249     (void) new (home) Val<View,Offset,shared>(home,n,xy,ox,oy);
00250     return ES_OK;
00251   }
00252 
00253 }}}
00254 
00255 // STATISTICS: int-prop
00256