this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Guido Tack <tack@gecode.org> 5 * Christian Schulte <schulte@gecode.org> 6 * 7 * Contributing authors: 8 * Gabor Szokoli <szokoli@gecode.org> 9 * 10 * Copyright: 11 * Guido Tack, 2004 12 * Christian Schulte, 2004 13 * Gabor Szokoli, 2004 14 * 15 * This file is part of Gecode, the generic constraint 16 * development environment: 17 * http://www.gecode.org 18 * 19 * Permission is hereby granted, free of charge, to any person obtaining 20 * a copy of this software and associated documentation files (the 21 * "Software"), to deal in the Software without restriction, including 22 * without limitation the rights to use, copy, modify, merge, publish, 23 * distribute, sublicense, and/or sell copies of the Software, and to 24 * permit persons to whom the Software is furnished to do so, subject to 25 * the following conditions: 26 * 27 * The above copyright notice and this permission notice shall be 28 * included in all copies or substantial portions of the Software. 29 * 30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 34 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 35 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 36 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37 * 38 */ 39 40namespace Gecode { namespace Set { namespace RelOp { 41 42 /* 43 * "Ternary intersection" propagator 44 * 45 */ 46 47 template<class View0, class View1, class View2> ExecStatus 48 Intersection<View0,View1,View2>::post(Home home, 49 View0 x0,View1 x1,View2 x2) { 50 (void) new (home) Intersection<View0,View1,View2>(home,x0,x1,x2); 51 return ES_OK; 52 } 53 54 template<class View0, class View1, class View2> 55 Actor* 56 Intersection<View0,View1,View2>::copy(Space& home) { 57 return new (home) Intersection(home,*this); 58 } 59 60 template<class View0, class View1, class View2> 61 ExecStatus 62 Intersection<View0,View1,View2>::propagate(Space& home, const ModEventDelta& med) { 63 // This propagator implements the constraint 64 // x2 = x0 \cap x1 65 66 bool x0ass = x0.assigned(); 67 bool x1ass = x1.assigned(); 68 bool x2ass = x2.assigned(); 69 70 ModEvent me0 = View0::me(med); 71 ModEvent me1 = View1::me(med); 72 ModEvent me2 = View2::me(med); 73 74 bool x0lbmod = false; 75 bool x1lbmod = false; 76 bool modified = false; 77 78 do { 79 80 modified = false; 81 do { 82 // 4) glb(x2) <= glb(x0) \cap glb(x1) 83 { 84 GlbRanges<View0> x0lb(x0); 85 GlbRanges<View1> x1lb(x1); 86 Iter::Ranges::Inter<GlbRanges<View0>, GlbRanges<View1> > 87 i2(x0lb,x1lb); 88 GECODE_ME_CHECK_MODIFIED(modified, x2.includeI(home,i2) ); 89 } 90 91 if (modified || Rel::testSetEventLB(me2) ) 92 { 93 modified = false; 94 // 5) x2 <= x0 95 GlbRanges<View2> x2lb1(x2); 96 GECODE_ME_CHECK_MODIFIED(modified, x0.includeI(home,x2lb1) ); 97 x0lbmod |= modified; 98 99 // 6) x2 <= x1 100 bool modified2=false; 101 GlbRanges<View2> x2lb2(x2); 102 GECODE_ME_CHECK_MODIFIED(modified2, x1.includeI(home,x2lb2) ); 103 x1lbmod |= modified2; 104 modified |= modified2; 105 } 106 107 } while (modified); 108 109 modified = false; 110 do { 111 bool modifiedOld = modified; 112 modified = false; 113 114 if (Rel::testSetEventUB(me2) || Rel::testSetEventLB(me0) 115 || x0lbmod || modifiedOld) 116 { 117 // 1) lub(x2) \ glb(x0) => lub(x1) 118 GlbRanges<View0> x0lb(x0); 119 LubRanges<View2> x2ub(x2); 120 Iter::Ranges::Diff<GlbRanges<View0>,LubRanges<View2> > 121 diff(x0lb, x2ub); 122 GECODE_ME_CHECK_MODIFIED(modified, x1.excludeI(home,diff) ); 123 } 124 125 if (Rel::testSetEventUB(me2) || Rel::testSetEventLB(me1) 126 || x1lbmod || modifiedOld) 127 { 128 // 2) lub(x2) \ glb(x1) => lub(x0) 129 GlbRanges<View1> x1lb(x1); 130 LubRanges<View2> x2ub(x2); 131 Iter::Ranges::Diff<GlbRanges<View1>, LubRanges<View2> > 132 diff(x1lb, x2ub); 133 GECODE_ME_CHECK_MODIFIED(modified, x0.excludeI(home,diff) ); 134 } 135 136 if (Rel::testSetEventUB(me0,me1) || modified) 137 { 138 // modified = false; 139 // 3) lub(x0) \cap lub(x1) <= lub(x2) 140 LubRanges<View0> x0ub(x0); 141 LubRanges<View1> x1ub(x1); 142 Iter::Ranges::Inter<LubRanges<View0>, LubRanges<View1> > 143 i1(x0ub,x1ub); 144 GECODE_ME_CHECK_MODIFIED(modified, x2.intersectI(home,i1) ); 145 } 146 147 } while(modified); 148 149 modified = false; 150 { 151 // cardinality 152 ExecStatus ret = interCard(home,modified, x0, x1, x2); 153 GECODE_ES_CHECK(ret); 154 } 155 156 if (x2.cardMin() == Set::Limits::card) { 157 GECODE_ME_CHECK( x0.cardMin(home, Set::Limits::card) ); 158 GECODE_ME_CHECK( x1.cardMin(home, Set::Limits::card) ); 159 return home.ES_SUBSUMED(*this); 160 } 161 162 if (x0.cardMin() == Set::Limits::card) 163 GECODE_REWRITE(*this,(Rel::Eq<View1,View2>::post(home(*this),x1,x2))); 164 if (x1.cardMin() == Set::Limits::card) 165 GECODE_REWRITE(*this,(Rel::Eq<View0,View2>::post(home(*this),x0,x2))); 166 167 } while(modified); 168 169 if (shared(x0,x1,x2)) { 170 return (x0ass && x1ass && x2ass) ? home.ES_SUBSUMED(*this) : ES_NOFIX; 171 } else { 172 if (x0ass && x1ass && x2ass) 173 return home.ES_SUBSUMED(*this); 174 if (x0ass != x0.assigned() || 175 x1ass != x1.assigned() || 176 x2ass != x2.assigned()) { 177 return ES_NOFIX; 178 } else { 179 return ES_FIX; 180 } 181 } 182 } 183 184 template<class View0, class View1, class View2> 185 forceinline 186 Intersection<View0,View1,View2>::Intersection(Home home, 187 View0 y0,View1 y1,View2 y2) 188 : MixTernaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY, 189 View2,PC_SET_ANY>(home,y0,y1,y2) {} 190 191 template<class View0, class View1, class View2> 192 forceinline 193 Intersection<View0,View1,View2>::Intersection(Space& home, 194 Intersection<View0,View1,View2>& p) 195 : MixTernaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY, 196 View2,PC_SET_ANY>(home,p) {} 197 198 /* 199 * "Nary intersection" propagator 200 * 201 */ 202 203 template<class View0, class View1> 204 forceinline 205 IntersectionN<View0,View1>::IntersectionN(Home home, ViewArray<View0>& x, 206 View1 y) 207 : MixNaryOnePropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,x,y), 208 intOfDets(home) { 209 shared = Gecode::shared(x) || viewarrayshared(x,y); 210 } 211 212 template<class View0, class View1> 213 forceinline 214 IntersectionN<View0,View1>::IntersectionN(Home home, ViewArray<View0>& x, 215 const IntSet& z, View1 y) 216 : MixNaryOnePropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,x,y), 217 intOfDets(home) { 218 shared = Gecode::shared(x) || viewarrayshared(x,y); 219 IntSetRanges rz(z); 220 intOfDets.intersectI(home, rz); 221 } 222 223 template<class View0, class View1> 224 forceinline 225 IntersectionN<View0,View1>::IntersectionN(Space& home, 226 IntersectionN& p) 227 : MixNaryOnePropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,p), 228 shared(p.shared), 229 intOfDets() { 230 intOfDets.update(home, p.intOfDets); 231 } 232 233 template<class View0, class View1> 234 ExecStatus 235 IntersectionN<View0,View1>::post(Home home, 236 ViewArray<View0>& x, View1 y) { 237 switch (x.size()) { 238 case 0: 239 GECODE_ME_CHECK(y.cardMin(home, Limits::card)); 240 return ES_OK; 241 case 1: 242 return Rel::Eq<View0,View1>::post(home, x[0], y); 243 case 2: 244 return Intersection<View0,View0,View1>::post(home, x[0], x[1], y); 245 default: 246 (void) new (home) IntersectionN<View0,View1>(home,x,y); 247 return ES_OK; 248 } 249 } 250 251 template<class View0, class View1> 252 ExecStatus 253 IntersectionN<View0,View1>::post(Home home, ViewArray<View0>& x, 254 const IntSet& z, View1 y) { 255 (void) new (home) IntersectionN<View0,View1>(home,x,z,y); 256 return ES_OK; 257 } 258 259 template<class View0, class View1> 260 Actor* 261 IntersectionN<View0,View1>::copy(Space& home) { 262 return new (home) IntersectionN<View0,View1>(home,*this); 263 } 264 265 template<class View0, class View1> 266 PropCost 267 IntersectionN<View0,View1>::cost(const Space&, const ModEventDelta&) const { 268 return PropCost::quadratic(PropCost::HI, x.size()+1); 269 } 270 271 template<class View0, class View1> 272 ExecStatus 273 IntersectionN<View0,View1>::propagate(Space& home, const ModEventDelta&) { 274 bool repeat = false; 275 do { 276 repeat = false; 277 int xsize = x.size(); 278 if (xsize == 0) 279 goto size0; 280 for (int i = xsize; i--; ) { 281 GECODE_ME_CHECK( y.cardMax(home,x[i].cardMax()) ); 282 GECODE_ME_CHECK( x[i].cardMin(home,y.cardMin()) ); 283 if (x[i].cardMax()==0) { 284 GECODE_ME_CHECK( y.cardMax(home, 0)); 285 intOfDets.dispose(home); 286 return home.ES_SUBSUMED(*this); 287 } 288 } 289 { 290 Region r; 291 GlbRanges<View0>* xLBs = r.alloc<GlbRanges<View0> >(xsize); 292 LubRanges<View0>* xUBs = r.alloc<LubRanges<View0> >(xsize); 293 for (int i = xsize; i--; ) { 294 GlbRanges<View0> lb(x[i]); 295 LubRanges<View0> ub(x[i]); 296 xLBs[i]=lb; 297 xUBs[i]=ub; 298 } 299 { 300 Iter::Ranges::NaryInter lbi(r,xLBs,xsize); 301 BndSetRanges dets(intOfDets); 302 lbi &= dets; 303 GECODE_ME_CHECK(y.includeI(home,lbi)); 304 } 305 { 306 Iter::Ranges::NaryInter ubi(r,xUBs,xsize); 307 BndSetRanges dets(intOfDets); 308 ubi &= dets; 309 GECODE_ME_CHECK(y.intersectI(home,ubi)); 310 } 311 } 312 313 for (int i = xsize; i--; ) { 314 GlbRanges<View1> ylb(y); 315 GECODE_ME_CHECK( x[i].includeI(home,ylb) ); 316 } 317 318 // xi.exclude (Intersection(xj.lb) - y.ub) 319 { 320 Region r; 321 GLBndSet* rightSet = 322 static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*xsize)); 323 new (&rightSet[xsize-1]) GLBndSet(home); 324 rightSet[xsize-1].update(home,intOfDets); 325 for (int i=xsize-1;i--;) { 326 GlbRanges<View0> xilb(x[i+1]); 327 BndSetRanges prev(rightSet[i+1]); 328 Iter::Ranges::Inter<GlbRanges<View0>, 329 BndSetRanges> inter(xilb,prev); 330 new (&rightSet[i]) GLBndSet(home); 331 rightSet[i].includeI(home,inter); 332 } 333 334 LUBndSet leftAcc(home); 335 336 for (int i=0;i<xsize;i++) { 337 BndSetRanges left(leftAcc); 338 BndSetRanges right(rightSet[i]); 339 Iter::Ranges::Inter<BndSetRanges, 340 BndSetRanges> inter(left, right); 341 LubRanges<View1> yub(y); 342 Iter::Ranges::Diff<Iter::Ranges::Inter<BndSetRanges, 343 BndSetRanges>, LubRanges<View1> > 344 forbidden(inter, yub); 345 GECODE_ME_CHECK( x[i].excludeI(home,forbidden) ); 346 GlbRanges<View0> xlb(x[i]); 347 leftAcc.intersectI(home,xlb); 348 } 349 for (int i=xsize; i--;) 350 rightSet[i].dispose(home); 351 leftAcc.dispose(home); 352 } 353 354 355 for(int i=0;i<x.size();i++) { 356 //Do not reverse! Eats away the end of the array! 357 while (i<x.size() && x[i].assigned()) { 358 GlbRanges<View0> det(x[i]); 359 if (intOfDets.intersectI(home,det)) {repeat = true;} 360 x.move_lst(i); 361 if (intOfDets.size()==0) { 362 GECODE_ME_CHECK( y.cardMax(home,0) ); 363 intOfDets.dispose(home); 364 return home.ES_SUBSUMED(*this); 365 } 366 } 367 } 368 size0: 369 if (x.size()==0) { 370 BndSetRanges all1(intOfDets); 371 GECODE_ME_CHECK( y.intersectI(home,all1) ); 372 BndSetRanges all2(intOfDets); 373 GECODE_ME_CHECK( y.includeI(home,all2) ); 374 intOfDets.dispose(home); 375 return home.ES_SUBSUMED(*this); 376 } 377 378 } while (repeat); 379 380 return shared ? ES_NOFIX : ES_FIX; 381 } 382 383}}} 384 385// STATISTICS: set-prop