00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 namespace Gecode { namespace Int { namespace Channel {
00043
00048 template<class View, class Offset>
00049 class DomInfo {
00050 public:
00052 View view;
00054 unsigned int size;
00056 int min;
00058 int max;
00060 void init(View x, int n);
00062 void update(Space& home, bool share, DomInfo<View,Offset>& vcb);
00064 bool doval(void) const;
00066 bool dodom(void) const;
00068 void assigned(void);
00070 void removed(int i);
00072 void done(Offset& o);
00073 };
00074
00075 template<class View, class Offset>
00076 forceinline void
00077 DomInfo<View,Offset>::init(View x, int n) {
00078 view = x;
00079 size = static_cast<unsigned int>(n);
00080 min = 0;
00081 max = n-1;
00082 }
00083
00084 template<class View, class Offset>
00085 forceinline void
00086 DomInfo<View,Offset>::update(Space& home, bool share,
00087 DomInfo<View,Offset>& di) {
00088 view.update(home,share,di.view);
00089 size = di.size;
00090 min = di.min;
00091 max = di.max;
00092 }
00093
00094 template<class View, class Offset>
00095 forceinline bool
00096 DomInfo<View,Offset>::doval(void) const {
00097 return (size != 1) && view.assigned();
00098 }
00099
00100 template<class View, class Offset>
00101 forceinline bool
00102 DomInfo<View,Offset>::dodom(void) const {
00103 return size != view.size();
00104 }
00105
00106 template<class View, class Offset>
00107 forceinline void
00108 DomInfo<View,Offset>::assigned(void) {
00109 size = 1;
00110 }
00111
00112 template<class View, class Offset>
00113 forceinline void
00114 DomInfo<View,Offset>::removed(int i) {
00115 size--;
00116 if (i == min)
00117 min++;
00118 else if (i == max)
00119 max--;
00120 }
00121
00122 template<class View, class Offset>
00123 forceinline void
00124 DomInfo<View,Offset>::done(Offset& o) {
00125 size = view.size();
00126 min = o(view).min();
00127 max = o(view).max();
00128 }
00129
00130
00131 template<class View, class Offset>
00132 ExecStatus
00133 prop_dom(Space& home, int n, DomInfo<View,Offset>* x, Offset& ox,
00134 DomInfo<View,Offset>* y, Offset& oy, ProcessStack& ya) {
00135 for (int i = n; i--; )
00136
00137 if (x[i].dodom()) {
00138
00139 ViewRanges<typename Offset::ViewType>
00140 xir(ox(x[i].view));
00141 Iter::Ranges::ComplVal<ViewRanges<typename Offset::ViewType> >
00142 xirc(x[i].min,x[i].max,xir);
00143 Iter::Ranges::ToValues<Iter::Ranges::ComplVal<
00144 ViewRanges<typename Offset::ViewType> > > jv(xirc);
00145 while (jv()) {
00146
00147 int j = jv.val();
00148 ModEvent me = oy(y[j].view).nq(home,i);
00149 if (me_failed(me))
00150 return ES_FAILED;
00151 if (me_modified(me)) {
00152 if (me == ME_INT_VAL) {
00153
00154 ya.push(j);
00155 } else {
00156
00157 y[j].removed(i);
00158 }
00159 }
00160 ++jv;
00161 }
00162
00163 x[i].done(ox);
00164 }
00165 return ES_OK;
00166 }
00167
00168
00169
00170
00171
00172 template<class View, class Offset, bool shared>
00173 forceinline
00174 Dom<View,Offset,shared>::Dom(Home home, int n, DomInfo<View,Offset>* xy,
00175 Offset& ox, Offset& oy)
00176 : Base<DomInfo<View,Offset>,Offset,PC_INT_DOM>(home,n,xy,ox,oy) {}
00177
00178 template<class View, class Offset, bool shared>
00179 forceinline
00180 Dom<View,Offset,shared>::Dom(Space& home, bool share,
00181 Dom<View,Offset,shared>& p)
00182 : Base<DomInfo<View,Offset>,Offset,PC_INT_DOM>(home,share,p) {}
00183
00184 template<class View, class Offset, bool shared>
00185 Actor*
00186 Dom<View,Offset,shared>::copy(Space& home, bool share) {
00187 return new (home) Dom<View,Offset,shared>(home,share,*this);
00188 }
00189
00190 template<class View, class Offset, bool shared>
00191 PropCost
00192 Dom<View,Offset,shared>::cost(const Space&,
00193 const ModEventDelta& med) const {
00194 if (View::me(med) == ME_INT_VAL)
00195 return PropCost::quadratic(PropCost::LO, 2*n);
00196 else
00197 return PropCost::quadratic(PropCost::HI, 2*n);
00198 }
00199
00200 template<class View, class Offset, bool shared>
00201 ExecStatus
00202 Dom<View,Offset,shared>::propagate(Space& home, const ModEventDelta& med) {
00203 Region r(home);
00204 ProcessStack xa(r,n);
00205 ProcessStack ya(r,n);
00206
00207 DomInfo<View,Offset>* x = xy;
00208 DomInfo<View,Offset>* y = xy+n;
00209
00210 if (View::me(med) == ME_INT_VAL) {
00211
00212 for (int i = n; i--; ) {
00213 if (x[i].doval()) xa.push(i);
00214 if (y[i].doval()) ya.push(i);
00215 }
00216
00217 if (shared) {
00218 do {
00219
00220 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
00221 (home,n,x,ox,y,oy,n_na,xa,ya)));
00222
00223 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
00224 (home,n,y,oy,x,ox,n_na,ya,xa)));
00225 assert(ya.empty());
00226 } while (!xa.empty() || !ya.empty());
00227 return home.ES_NOFIX_PARTIAL(*this,View::med(ME_INT_DOM));
00228 } else {
00229 do {
00230
00231 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
00232 (home,n,x,ox,y,oy,n_na,xa,ya)));
00233
00234 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
00235 (home,n,y,oy,x,ox,n_na,ya,xa)));
00236 assert(ya.empty());
00237 } while (!xa.empty());
00238 return home.ES_FIX_PARTIAL(*this,View::med(ME_INT_DOM));
00239 }
00240 }
00241
00242
00243
00244
00245 GECODE_ES_CHECK(prop_dom(home,n,y,oy,x,ox,xa));
00246
00247
00248 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
00249 (home,n,x,ox,y,oy,n_na,xa,ya)));
00250
00251
00252 if (dc.available()) {
00253 GECODE_ES_CHECK(dc.sync(home));
00254 } else {
00255 ViewArray<View> xv(r,n);
00256 for (int i=n; i--; )
00257 xv[i] = x[i].view;
00258 GECODE_ES_CHECK(dc.init(home,xv));
00259 }
00260 bool assigned;
00261 GECODE_ES_CHECK(dc.propagate(home,assigned));
00262 if (assigned) {
00263
00264
00265
00266
00267 for (int i=n; i--; )
00268 if (x[i].doval()) {
00269 int j = ox(x[i].view).val();
00270
00271 ModEvent me = oy(y[j].view).eq(home,i);
00272 if (me_failed(me))
00273 return ES_FAILED;
00274 if (me_modified(me)) {
00275
00276 assert(me == ME_INT_VAL);
00277
00278 ya.push(j);
00279 }
00280 x[i].assigned(); n_na--;
00281 }
00282 }
00283
00284
00285
00286
00287 GECODE_ES_CHECK(prop_dom(home,n,x,ox,y,oy,ya));
00288
00289
00290 while (!xa.empty() || !ya.empty()) {
00291
00292 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
00293 (home,n,x,ox,y,oy,n_na,xa,ya)));
00294
00295 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
00296 (home,n,y,oy,x,ox,n_na,ya,xa)));
00297 };
00298
00299 if (shared) {
00300 for (int i=2*n; i--; )
00301 if (!xy[i].view.assigned())
00302 return ES_NOFIX;
00303 return home.ES_SUBSUMED(*this);
00304 } else {
00305 return (n_na == 0) ? home.ES_SUBSUMED(*this) : ES_FIX;
00306 }
00307 }
00308
00309 template<class View, class Offset, bool shared>
00310 ExecStatus
00311 Dom<View,Offset,shared>::post(Home home, int n, DomInfo<View,Offset>* xy,
00312 Offset& ox, Offset& oy) {
00313 assert(n > 0);
00314 if (n == 1) {
00315 GECODE_ME_CHECK(ox(xy[0].view).eq(home,0));
00316 GECODE_ME_CHECK(oy(xy[1].view).eq(home,0));
00317 return ES_OK;
00318 }
00319 for (int i=n; i--; ) {
00320 GECODE_ME_CHECK(ox(xy[i ].view).gq(home,0));
00321 GECODE_ME_CHECK(ox(xy[i ].view).le(home,n));
00322 GECODE_ME_CHECK(oy(xy[i+n].view).gq(home,0));
00323 GECODE_ME_CHECK(oy(xy[i+n].view).le(home,n));
00324 }
00325 (void) new (home) Dom<View,Offset,shared>(home,n,xy,ox,oy);
00326 return ES_OK;
00327 }
00328
00329 }}}
00330
00331
00332