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 * 6 * Copyright: 7 * Guido Tack, 2011 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34namespace Gecode { namespace Set { namespace Rel { 35 36 /** 37 * \brief Representation of the characteristic functions of two sets 38 */ 39 class CharacteristicSets { 40 protected: 41 /// Size of the combined upper bounds 42 unsigned int xsize; 43 /// Storage for the characteristic functions 44 Support::BitSetBase b; 45 /// Elements in the combined upper bounds 46 int* ub; 47 /// Whether lower bound of x was updated 48 bool xlm; 49 /// Whether upper bound of x was updated 50 bool xum; 51 /// Whether lower bound of y was updated 52 bool ylm; 53 /// Whether upper bound of y was updated 54 bool yum; 55 /// Get bit \a i 56 bool get(unsigned int i) const; 57 /// Set bit \a i to value \a j 58 void set(unsigned int i, bool j); 59 60 /// \brief Value iterator for characteristic function 61 class CSIter { 62 public: 63 /// Pointer to the underlying set 64 CharacteristicSets* cs; 65 /// Current position 66 unsigned int i; 67 /// Offset from start of bitset 68 unsigned int xoff; 69 /// Offset for each element (0=lower bound, 1=upper bound) 70 unsigned int yoff; 71 /// Move iterator to next element 72 void operator++ (void); 73 /// Default constructor 74 CSIter(void); 75 /// Constructor 76 CSIter(CharacteristicSets& cs0, unsigned int xoff0, unsigned int yoff0); 77 /// Test if iterator is finished 78 bool operator() (void) const; 79 /// Value of current iterator position 80 int val(void) const; 81 }; 82 83 public: 84 /// Constructor 85 template<class View0, class View1> 86 CharacteristicSets(Region& re, View0 x, View1 y); 87 88 /// Return minimum of element \a i for variable x 89 bool xmin(unsigned int i) const; 90 /// Return maximum of element \a i for variable x 91 bool xmax(unsigned int i) const; 92 /// Return minimum of element \a i for variable y 93 bool ymin(unsigned int i) const; 94 /// Return maximum of element \a i for variable y 95 bool ymax(unsigned int i) const; 96 97 /// Set minimum of element \a i for variable x to \a j 98 void xmin(unsigned int i, bool j); 99 /// Set maximum of element \a i for variable x to \a j 100 void xmax(unsigned int i, bool j); 101 /// Set minimum of element \a i for variable y to \a j 102 void ymin(unsigned int i, bool j); 103 /// Set maximum of element \a i for variable y to \a j 104 void ymax(unsigned int i, bool j); 105 106 /// Update upper bound of \f$x_i\f$ to \a j 107 ModEvent xlq(unsigned int i, bool j); 108 /// Update lower bound of \f$x_i\f$ to \a j 109 ModEvent xgq(unsigned int i, bool j); 110 /// Update upper bound of \f$y_i\f$ to \a j 111 ModEvent ylq(unsigned int i, bool j); 112 /// Update lower bound of \f$y_i\f$ to \a j 113 ModEvent ygq(unsigned int i, bool j); 114 115 /// Return size of combined upper bounds 116 unsigned int size(void) const; 117 118 /// Prune \a x and \a y using computed bounds 119 template<class View0, class View1> 120 ExecStatus prune(Space& home, View0 x, View1 y); 121 122 }; 123 124 125 forceinline bool 126 CharacteristicSets::get(unsigned int i) const { 127 return b.get(i); 128 } 129 forceinline void 130 CharacteristicSets::set(unsigned int i, bool j) { 131 if (j) 132 b.set(i); 133 else 134 b.clear(i); 135 } 136 forceinline unsigned int 137 CharacteristicSets::size(void) const { 138 return xsize; 139 } 140 141 forceinline 142 CharacteristicSets::CSIter::CSIter(void) {} 143 forceinline 144 CharacteristicSets::CSIter::CSIter(CharacteristicSets& cs0, 145 unsigned int xoff0, unsigned int yoff0) 146 : cs(&cs0), i(0), xoff(xoff0), yoff(yoff0) { 147 while ((i < cs->xsize) && !cs->get(xoff+2*i+yoff)) 148 i++; 149 } 150 forceinline void 151 CharacteristicSets::CSIter::operator++ (void) { 152 i++; 153 while ((i < cs->xsize) && !cs->get(xoff+2*i+yoff)) 154 i++; 155 } 156 forceinline bool 157 CharacteristicSets::CSIter::operator() (void) const { 158 return i<cs->xsize; 159 } 160 forceinline int 161 CharacteristicSets::CSIter::val(void) const { 162 return cs->ub[i]; 163 } 164 165 166 forceinline bool 167 CharacteristicSets::xmin(unsigned int i) const { 168 return get(2*i); 169 } 170 forceinline bool 171 CharacteristicSets::xmax(unsigned int i) const { 172 return get(2*i+1); 173 } 174 forceinline bool 175 CharacteristicSets::ymin(unsigned int i) const { 176 return get(2*xsize+2*i); 177 } 178 forceinline bool 179 CharacteristicSets::ymax(unsigned int i) const { 180 return get(2*xsize+2*i+1); 181 } 182 183 forceinline void 184 CharacteristicSets::xmin(unsigned int i, bool j) { 185 set(2*i,j); 186 } 187 forceinline void 188 CharacteristicSets::xmax(unsigned int i, bool j) { 189 set(2*i+1,j); 190 } 191 forceinline void 192 CharacteristicSets::ymin(unsigned int i, bool j) { 193 set(2*xsize+2*i,j); 194 } 195 forceinline void 196 CharacteristicSets::ymax(unsigned int i, bool j) { 197 set(2*xsize+2*i+1,j); 198 } 199 200 forceinline ModEvent 201 CharacteristicSets::xlq(unsigned int i, bool j) { 202 if (!j) { 203 if (xmin(i)) return ME_SET_FAILED; 204 if (xmax(i)) { 205 xmax(i,false); 206 xum=true; 207 } 208 } 209 return ME_SET_NONE; 210 } 211 forceinline ModEvent 212 CharacteristicSets::xgq(unsigned int i, bool j) { 213 if (j) { 214 if (!xmax(i)) return ME_SET_FAILED; 215 if (!xmin(i)) { 216 xmin(i,true); 217 xlm=true; 218 } 219 } 220 return ME_SET_NONE; 221 } 222 forceinline ModEvent 223 CharacteristicSets::ylq(unsigned int i, bool j) { 224 if (!j) { 225 if (ymin(i)) return ME_SET_FAILED; 226 if (ymax(i)) { 227 ymax(i,false); 228 yum=true; 229 } 230 } 231 return ME_SET_NONE; 232 } 233 forceinline ModEvent 234 CharacteristicSets::ygq(unsigned int i, bool j) { 235 if (j) { 236 if (!ymax(i)) return ME_SET_FAILED; 237 if (!ymin(i)) { 238 ymin(i,true); 239 ylm=true; 240 } 241 } 242 return ME_SET_NONE; 243 } 244 245 template<class View0, class View1> 246 forceinline ExecStatus 247 CharacteristicSets::prune(Space& home, View0 x, View1 y) { 248 if (xlm) { 249 CSIter i(*this,0,0); 250 Iter::Values::ToRanges<CSIter> ir(i); 251 GECODE_ME_CHECK(x.includeI(home,ir)); 252 } 253 if (xum) { 254 CSIter i(*this,0,1); 255 Iter::Values::ToRanges<CSIter> ir(i); 256 GECODE_ME_CHECK(x.intersectI(home,ir)); 257 } 258 if (ylm) { 259 CSIter i(*this,2*xsize,0); 260 Iter::Values::ToRanges<CSIter> ir(i); 261 GECODE_ME_CHECK(y.includeI(home,ir)); 262 } 263 if (yum) { 264 CSIter i(*this,2*xsize,1); 265 Iter::Values::ToRanges<CSIter> ir(i); 266 GECODE_ME_CHECK(y.intersectI(home,ir)); 267 } 268 return ES_OK; 269 } 270 271 template<class View0, class View1> 272 forceinline 273 CharacteristicSets::CharacteristicSets(Region& re,View0 x, View1 y) 274 : xlm(false), xum(false), ylm(false), yum(false) { 275 LubRanges<View0> xlub(x); 276 LubRanges<View1> ylub(y); 277 Iter::Ranges::Union<LubRanges<View0>,LubRanges<View1> > xylub(xlub,ylub); 278 Iter::Ranges::Cache xylubc(re,xylub); 279 xsize = Iter::Ranges::size(xylubc); 280 b.init(re,4*xsize); 281 ub = re.alloc<int>(xsize); 282 xylubc.reset(); 283 Iter::Ranges::ToValues<Iter::Ranges::Cache> xylubv(xylubc); 284 LubRanges<View0> xur(x); 285 GlbRanges<View0> xlr(x); 286 LubRanges<View1> yur(y); 287 GlbRanges<View1> ylr(y); 288 Iter::Ranges::ToValues<LubRanges<View0> > xuv(xur); 289 Iter::Ranges::ToValues<GlbRanges<View0> > xlv(xlr); 290 Iter::Ranges::ToValues<LubRanges<View1> > yuv(yur); 291 Iter::Ranges::ToValues<GlbRanges<View1> > ylv(ylr); 292 for (unsigned int i=0; xylubv(); ++xylubv, ++i) { 293 ub[i] = xylubv.val(); 294 if (xlv() && xylubv.val()==xlv.val()) { 295 b.set(2*i); 296 ++xlv; 297 } 298 if (xuv() && xylubv.val()==xuv.val()) { 299 b.set(2*i+1); 300 ++xuv; 301 } 302 if (ylv() && xylubv.val()==ylv.val()) { 303 b.set(2*xsize+2*i); 304 ++ylv; 305 } 306 if (yuv() && xylubv.val()==yuv.val()) { 307 b.set(2*xsize+2*i+1); 308 ++yuv; 309 } 310 } 311 } 312 313 template<class View0, class View1, bool strict> 314 forceinline 315 Lq<View0,View1,strict>::Lq(Home home, View0 x, View1 y) 316 : MixBinaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,x,y) {} 317 318 template<class View0, class View1, bool strict> 319 forceinline 320 Lq<View0,View1,strict>::Lq(Space& home, Lq& p) 321 : MixBinaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,p) {} 322 323 template<class View0, class View1, bool strict> 324 ExecStatus 325 Lq<View0,View1,strict>::post(Home home, View0 x, View1 y) { 326 if (strict) 327 GECODE_ME_CHECK(y.cardMin(home,1)); 328 if (same(x,y)) 329 return strict ? ES_FAILED : ES_OK; 330 (void) new (home) Lq(home,x,y); 331 return ES_OK; 332 } 333 334 template<class View0, class View1, bool strict> 335 Actor* 336 Lq<View0,View1,strict>::copy(Space& home) { 337 return new (home) Lq(home,*this); 338 } 339 340 template<class View0, class View1, bool strict> 341 ExecStatus 342 Lq<View0,View1,strict>::propagate(Space& home, const ModEventDelta&) { 343 if ( (!strict) && x1.cardMax()==0) { 344 GECODE_ME_CHECK(x0.cardMax(home,0)); 345 } 346 347 if (x0.cardMax()==0) { 348 return home.ES_SUBSUMED(*this); 349 } 350 351 if (x0.glbMin() < x1.lubMin()) 352 return ES_FAILED; 353 if (x1.glbMin() < x0.lubMin()) 354 return home.ES_SUBSUMED(*this); 355 356 bool assigned = x0.assigned() && x1.assigned(); 357 358 Region re; 359 CharacteristicSets cs(re,x0,x1); 360 361 /* 362 * State 1 363 * 364 */ 365 unsigned int i=0; 366 unsigned int firsti=0; 367 unsigned int n=cs.size(); 368 while ((i<n) && (cs.xmin(i) == cs.ymax(i))) { 369 // case: =, >= 370 GECODE_ME_CHECK(cs.xlq(i,cs.ymax(i))); 371 GECODE_ME_CHECK(cs.ygq(i,cs.xmin(i))); 372 i++; 373 } 374 375 if (i == n) {// case: $ 376 if (strict) { 377 return ES_FAILED; 378 } else { 379 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 380 return home.ES_SUBSUMED(*this); 381 } 382 } 383 384 // Possible cases left: <, <=, > (yields failure), ? 385 GECODE_ME_CHECK(cs.xlq(i,cs.ymax(i))); 386 GECODE_ME_CHECK(cs.ygq(i,cs.xmin(i))); 387 388 if (cs.xmax(i) < cs.ymin(i)) { // case: < (after tell) 389 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 390 return home.ES_SUBSUMED(*this); 391 } 392 393 firsti=i; 394 395 /* 396 * State 2 397 * prefix: (?|<=) 398 * 399 */ 400 i++; 401 402 while ((i < n) && 403 (cs.xmin(i) == cs.ymax(i)) && 404 (cs.xmax(i) == cs.ymin(i))) { // case: = 405 i++; 406 } 407 408 if (i == n) { // case: $ 409 if (strict) 410 goto rewrite_le; 411 else 412 goto rewrite_lq; 413 } 414 415 if (cs.xmax(i) < cs.ymin(i)) // case: < 416 goto rewrite_lq; 417 418 if (cs.xmin(i) > cs.ymax(i)) // case: > 419 goto rewrite_le; 420 421 if (cs.xmax(i) <= cs.ymin(i)) { 422 // case: <= (invariant: not =, <) 423 /* 424 * State 3 425 * prefix: (?|<=),<= 426 * 427 */ 428 i++; 429 430 while ((i < n) && (cs.xmax(i) == cs.ymin(i))) {// case: <=, = 431 i++; 432 } 433 434 if (i == n) { // case: $ 435 if (strict) { 436 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 437 return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX; 438 } else { 439 goto rewrite_lq; 440 } 441 } 442 443 if (cs.xmax(i) < cs.ymin(i)) // case: < 444 goto rewrite_lq; 445 446 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 447 return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX; 448 } 449 450 if (cs.xmin(i) >= cs.ymax(i)) { 451 // case: >= (invariant: not =, >) 452 /* 453 * State 4 454 * prefix: (?|<=) >= 455 * 456 */ 457 i++; 458 459 while ((i < n) && (cs.xmin(i) == cs.ymax(i))) { 460 // case: >=, = 461 i++; 462 } 463 464 if (i == n) { // case: $ 465 if (strict) { 466 goto rewrite_le; 467 } else { 468 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 469 return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX; 470 } 471 } 472 473 if (cs.xmin(i) > cs.ymax(i)) // case: > 474 goto rewrite_le; 475 476 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 477 return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX; 478 } 479 480 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 481 return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX; 482 483 rewrite_le: 484 GECODE_ME_CHECK(cs.xlq(firsti,false)); 485 GECODE_ME_CHECK(cs.ygq(firsti,true)); 486 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 487 return home.ES_SUBSUMED(*this); 488 rewrite_lq: 489 GECODE_ES_CHECK(cs.prune(home,x0,x1)); 490 return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX; 491 } 492 493}}} 494 495// STATISTICS: set-prop