this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * Gabor Szokoli <szokoli@gecode.org> 6 * 7 * Copyright: 8 * Christian Schulte, 2003 9 * Gabor Szokoli, 2003 10 * 11 * This file is part of Gecode, the generic constraint 12 * development environment: 13 * http://www.gecode.org 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining 16 * a copy of this software and associated documentation files (the 17 * "Software"), to deal in the Software without restriction, including 18 * without limitation the rights to use, copy, modify, merge, publish, 19 * distribute, sublicense, and/or sell copies of the Software, and to 20 * permit persons to whom the Software is furnished to do so, subject to 21 * the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 * 34 */ 35 36namespace Gecode { namespace Int { namespace Rel { 37 38 /* 39 * Less or equal propagator 40 * 41 */ 42 43 template<class V0, class V1> 44 forceinline 45 Lq<V0,V1>::Lq(Home home, V0 x0, V1 x1) 46 : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,x0,x1) {} 47 48 template<class V0, class V1> 49 ExecStatus 50 Lq<V0,V1>::post(Home home, V0 x0, V1 x1) { 51 GECODE_ME_CHECK(x0.lq(home,x1.max())); 52 GECODE_ME_CHECK(x1.gq(home,x0.min())); 53 if ((x0 != x1) && (x0.max() > x1.min())) 54 (void) new (home) Lq<V0,V1>(home,x0,x1); 55 return ES_OK; 56 } 57 58 template<class V0, class V1> 59 forceinline 60 Lq<V0,V1>::Lq(Space& home, Lq<V0,V1>& p) 61 : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,p) {} 62 63 template<class V0, class V1> 64 Actor* 65 Lq<V0,V1>::copy(Space& home) { 66 return new (home) Lq<V0,V1>(home,*this); 67 } 68 69 template<class V0, class V1> 70 ExecStatus 71 Lq<V0,V1>::propagate(Space& home, const ModEventDelta&) { 72 GECODE_ME_CHECK(x0.lq(home,x1.max())); 73 GECODE_ME_CHECK(x1.gq(home,x0.min())); 74 return (x0.max() <= x1.min()) ? home.ES_SUBSUMED(*this) : ES_FIX; 75 } 76 77 78 79 80 /* 81 * Less propagator 82 * 83 */ 84 template<class V0, class V1> 85 forceinline 86 Le<V0,V1>::Le(Home home, V0 x0, V1 x1) 87 : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,x0,x1) {} 88 89 template<class V0, class V1> 90 ExecStatus 91 Le<V0,V1>::post(Home home, V0 x0, V1 x1) { 92 if (x0 == x1) 93 return ES_FAILED; 94 GECODE_ME_CHECK(x0.le(home,x1.max())); 95 GECODE_ME_CHECK(x1.gr(home,x0.min())); 96 if (x0.max() >= x1.min()) 97 (void) new (home) Le<V0,V1>(home,x0,x1); 98 return ES_OK; 99 } 100 101 template<class V0, class V1> 102 forceinline 103 Le<V0,V1>::Le(Space& home, Le<V0,V1>& p) 104 : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,p) {} 105 106 template<class V0, class V1> 107 Actor* 108 Le<V0,V1>::copy(Space& home) { 109 return new (home) Le<V0,V1>(home,*this); 110 } 111 112 template<class V0, class V1> 113 ExecStatus 114 Le<V0,V1>::propagate(Space& home, const ModEventDelta&) { 115 GECODE_ME_CHECK(x0.le(home,x1.max())); 116 GECODE_ME_CHECK(x1.gr(home,x0.min())); 117 return (x0.max() < x1.min()) ? home.ES_SUBSUMED(*this) : ES_FIX; 118 } 119 120 121 122 /* 123 * Nary less and less or equal propagator 124 * 125 */ 126 127 template<class View, int o> 128 forceinline 129 NaryLqLe<View,o>::Index::Index(Space& home, Propagator& p, 130 Council<Index>& c, int i0) 131 : Advisor(home,p,c), i(i0) {} 132 133 template<class View, int o> 134 forceinline 135 NaryLqLe<View,o>::Index::Index(Space& home, Index& a) 136 : Advisor(home,a), i(a.i) {} 137 138 139 140 template<class View, int o> 141 forceinline 142 NaryLqLe<View,o>::Pos::Pos(int p0, Pos* n) 143 : FreeList(n), p(p0) {} 144 145 template<class View, int o> 146 forceinline typename NaryLqLe<View,o>::Pos* 147 NaryLqLe<View,o>::Pos::next(void) const { 148 return static_cast<Pos*>(FreeList::next()); 149 } 150 151 template<class View, int o> 152 forceinline void 153 NaryLqLe<View,o>::Pos::operator delete(void*) {} 154 155 template<class View, int o> 156 forceinline void 157 NaryLqLe<View,o>::Pos::operator delete(void*, Space&) { 158 GECODE_NEVER; 159 } 160 161 template<class View, int o> 162 forceinline void* 163 NaryLqLe<View,o>::Pos::operator new(size_t, Space& home) { 164 return home.fl_alloc<sizeof(Pos)>(); 165 } 166 167 template<class View, int o> 168 forceinline void 169 NaryLqLe<View,o>::Pos::dispose(Space& home) { 170 home.fl_dispose<sizeof(Pos)>(this,this); 171 } 172 173 174 template<class View, int o> 175 forceinline bool 176 NaryLqLe<View,o>::empty(void) const { 177 return pos == nullptr; 178 } 179 template<class View, int o> 180 forceinline void 181 NaryLqLe<View,o>::push(Space& home, int p) { 182 // Try to avoid entering same position twice 183 if ((pos != nullptr) && (pos->p == p)) 184 return; 185 pos = new (home) Pos(p,pos); 186 } 187 template<class View, int o> 188 forceinline int 189 NaryLqLe<View,o>::pop(Space& home) { 190 Pos* t = pos; 191 int p = t->p; 192 pos = pos->next(); 193 t->dispose(home); 194 return p; 195 } 196 197 template<class View, int o> 198 forceinline 199 NaryLqLe<View,o>::NaryLqLe(Home home, ViewArray<View>& x) 200 : NaryPropagator<View,PC_INT_NONE>(home,x), 201 c(home), pos(nullptr), run(false), n_subsumed(0) { 202 for (int i=0; i<x.size(); i++) 203 x[i].subscribe(home, *new (home) Index(home,*this,c,i)); 204 } 205 206 template<class View, int o> 207 ExecStatus 208 NaryLqLe<View,o>::post(Home home, ViewArray<View>& x) { 209 assert((o == 0) || (o == 1)); 210 // Check for sharing 211 if (x.same()) { 212 if (o == 1) 213 return ES_FAILED; 214 /* 215 * Eliminate sharing: if a view occurs twice, all views in between 216 * must be equal. 217 */ 218 int n = x.size(); 219 for (int i=0; i<n; i++) 220 for (int j=n-1; j>i; j--) 221 if (x[i] == x[j]) { 222 if (i+1 != j) { 223 // Create equality propagator for elements i+1 ... j 224 ViewArray<View> y(home,j-i); 225 for (int k=j-i; k--; ) 226 y[k] = x[i+1+k]; 227 GECODE_ES_CHECK(NaryEqBnd<View>::post(home,y)); 228 } 229 for (int k=0; k<n-1-j-1+1; k++) 230 x[i+1+k]=x[j+1+k]; 231 n -= j-i; 232 break; 233 } 234 x.size(n); 235 } 236 237 // Propagate one round 238 for (int i=1; i<x.size(); i++) 239 GECODE_ME_CHECK(x[i].gq(home,x[i-1].min()+o)); 240 for (int i=x.size()-1; i--;) 241 GECODE_ME_CHECK(x[i].lq(home,x[i+1].max()-o)); 242 // Eliminate redundant variables 243 { 244 // Eliminate at beginning 245 { 246 int i=0; 247 while ((i+1 < x.size()) && (x[i].max()+o <= x[i+1].min())) 248 i++; 249 x.drop_fst(i); 250 } 251 // Eliminate at end 252 { 253 int i=x.size()-1; 254 while ((i > 0) && (x[i-1].max()+o <= x[i].min())) 255 i--; 256 x.drop_lst(i); 257 } 258 // Eliminate in the middle 259 if (x.size() > 1) { 260 int j=1; 261 for (int i=1; i+1<x.size(); i++) 262 if ((x[j-1].max()+o > x[i].min()) || 263 (x[i].max()+o > x[i+1].min())) 264 x[j++]=x[i]; 265 x[j++]=x[x.size()-1]; 266 x.size(j); 267 } 268 } 269 if (x.size() == 2) { 270 if (o == 0) 271 return Lq<View,View>::post(home,x[0],x[1]); 272 else 273 return Le<View,View>::post(home,x[0],x[1]); 274 } else if (x.size() >= 2) { 275 (void) new (home) NaryLqLe<View,o>(home,x); 276 } 277 return ES_OK; 278 } 279 280 template<class View, int o> 281 forceinline 282 NaryLqLe<View,o>::NaryLqLe(Space& home, NaryLqLe<View,o>& p) 283 : NaryPropagator<View,PC_INT_NONE>(home,p), 284 pos(nullptr), run(false), n_subsumed(p.n_subsumed) { 285 assert(p.pos == nullptr); 286 c.update(home, p.c); 287 } 288 289 template<class View, int o> 290 Actor* 291 NaryLqLe<View,o>::copy(Space& home) { 292 if (n_subsumed > n_threshold) { 293 Region r; 294 // Record for which views there is an advisor 295 Support::BitSet<Region> a(r,static_cast<unsigned int>(x.size())); 296 for (Advisors<Index> as(c); as(); ++as) 297 a.set(static_cast<unsigned int>(as.advisor().i)); 298 // Compact view array and compute map for advisors 299 int* m = r.alloc<int>(x.size()); 300 int j=0; 301 for (int i=0; i<x.size(); i++) 302 if (a.get(static_cast<unsigned int>(i))) { 303 m[i] = j; x[j++] = x[i]; 304 } 305 x.size(j); 306 // Remap advisors 307 for (Advisors<Index> as(c); as(); ++as) 308 as.advisor().i = m[as.advisor().i]; 309 310 n_subsumed = 0; 311 } 312 return new (home) NaryLqLe<View,o>(home,*this); 313 } 314 315 template<class View, int o> 316 PropCost 317 NaryLqLe<View,o>::cost(const Space&, const ModEventDelta&) const { 318 return PropCost::binary(PropCost::HI); 319 } 320 321 template<class View, int o> 322 forceinline size_t 323 NaryLqLe<View,o>::dispose(Space& home) { 324 for (Advisors<Index> as(c); as(); ++as) 325 x[as.advisor().i].cancel(home,as.advisor()); 326 c.dispose(home); 327 while (!empty()) 328 (void) pop(home); 329 (void) NaryPropagator<View,PC_INT_NONE>::dispose(home); 330 return sizeof(*this); 331 } 332 333 334 template<class View, int o> 335 ExecStatus 336 NaryLqLe<View,o>::advise(Space& home, Advisor& _a, const Delta& d) { 337 Index& a = static_cast<Index&>(_a); 338 const int i = a.i; 339 switch (View::modevent(d)) { 340 case ME_INT_VAL: 341 a.dispose(home,c); 342 n_subsumed++; 343 break; 344 case ME_INT_BND: 345 if (((i == 0) || (x[i-1].max()+o <= x[i].min())) && 346 ((i == x.size()-1) || (x[i].max()+o <= x[i+1].min()))) { 347 x[i].cancel(home,a); 348 a.dispose(home,c); 349 n_subsumed++; 350 return (run || (n_subsumed + 1 < x.size())) ? ES_FIX : ES_NOFIX; 351 } 352 break; 353 default: 354 return ES_FIX; 355 } 356 if (run) 357 return ES_FIX; 358 if (((i < x.size()-1) && (x[i+1].min() < x[i].min()+o)) || 359 ((i > 0) && (x[i-1].max() > x[i].max()-o))) { 360 push(home,i); 361 return ES_NOFIX; 362 } 363 return (n_subsumed+1 >= x.size()) ? ES_NOFIX : ES_FIX; 364 } 365 366 template<class View, int o> 367 void 368 NaryLqLe<View,o>::reschedule(Space& home) { 369 View::schedule(home, *this, ME_INT_BND); 370 } 371 372 template<class View, int o> 373 ExecStatus 374 NaryLqLe<View,o>::propagate(Space& home, const ModEventDelta&) { 375 run = true; 376 int n = x.size(); 377 while (!empty()) { 378 int p = pop(home); 379 for (int i=p; i<n-1; i++) { 380 ModEvent me = x[i+1].gq(home,x[i].min()+o); 381 if (me_failed(me)) 382 return ES_FAILED; 383 if (!me_modified(me)) 384 break; 385 } 386 for (int i=p; i>0; i--) { 387 ModEvent me = x[i-1].lq(home,x[i].max()-o); 388 if (me_failed(me)) 389 return ES_FAILED; 390 if (!me_modified(me)) 391 break; 392 } 393 } 394#ifdef GECODE_AUDIT 395 for (int i=0; i<n-1; i++) 396 assert(!me_modified(x[i+1].gq(home,x[i].min()+o))); 397 for (int i=n-1; i>0; i--) 398 assert(!me_modified(x[i-1].lq(home,x[i].max()-o))); 399#endif 400 if (n_subsumed+1 >= n) 401 return home.ES_SUBSUMED(*this); 402 run = false; 403 return ES_FIX; 404 } 405 406 407 408 /* 409 * Reified less or equal propagator 410 * 411 */ 412 413 template<class View, class CtrlView, ReifyMode rm> 414 forceinline 415 ReLq<View,CtrlView,rm>::ReLq(Home home, View x0, View x1, CtrlView b) 416 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,x0,x1,b) {} 417 418 template<class View, class CtrlView, ReifyMode rm> 419 ExecStatus 420 ReLq<View,CtrlView,rm>::post(Home home, View x0, View x1, CtrlView b) { 421 if (b.one()) { 422 if (rm == RM_PMI) 423 return ES_OK; 424 return Lq<View,View>::post(home,x0,x1); 425 } 426 if (b.zero()) { 427 if (rm == RM_IMP) 428 return ES_OK; 429 return Le<View,View>::post(home,x1,x0); 430 } 431 if (x0 != x1) { 432 switch (rtest_lq(x0,x1)) { 433 case RT_TRUE: 434 if (rm != RM_IMP) 435 GECODE_ME_CHECK(b.one_none(home)); 436 break; 437 case RT_FALSE: 438 if (rm != RM_PMI) 439 GECODE_ME_CHECK(b.zero_none(home)); 440 break; 441 case RT_MAYBE: 442 (void) new (home) ReLq<View,CtrlView,rm>(home,x0,x1,b); 443 break; 444 default: GECODE_NEVER; 445 } 446 } else if (rm != RM_IMP) { 447 GECODE_ME_CHECK(b.one_none(home)); 448 } 449 return ES_OK; 450 } 451 452 template<class View, class CtrlView, ReifyMode rm> 453 forceinline 454 ReLq<View,CtrlView,rm>::ReLq(Space& home, ReLq& p) 455 : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,p) {} 456 457 template<class View, class CtrlView, ReifyMode rm> 458 Actor* 459 ReLq<View,CtrlView,rm>::copy(Space& home) { 460 return new (home) ReLq<View,CtrlView,rm>(home,*this); 461 } 462 463 template<class View, class CtrlView, ReifyMode rm> 464 ExecStatus 465 ReLq<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { 466 if (b.one()) { 467 if (rm != RM_PMI) 468 GECODE_REWRITE(*this,(Lq<View,View>::post(home(*this),x0,x1))); 469 } else if (b.zero()) { 470 if (rm != RM_IMP) 471 GECODE_REWRITE(*this,(Le<View,View>::post(home(*this),x1,x0))); 472 } else { 473 switch (rtest_lq(x0,x1)) { 474 case RT_TRUE: 475 if (rm != RM_IMP) 476 GECODE_ME_CHECK(b.one_none(home)); 477 break; 478 case RT_FALSE: 479 if (rm != RM_PMI) 480 GECODE_ME_CHECK(b.zero_none(home)); 481 break; 482 case RT_MAYBE: 483 return ES_FIX; 484 default: GECODE_NEVER; 485 } 486 } 487 return home.ES_SUBSUMED(*this); 488 } 489 490 /* 491 * Reified less or equal propagator involving one variable 492 * 493 */ 494 495 template<class View, class CtrlView, ReifyMode rm> 496 forceinline 497 ReLqInt<View,CtrlView,rm>::ReLqInt(Home home, View x, int c0, CtrlView b) 498 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,x,b), c(c0) {} 499 500 template<class View, class CtrlView, ReifyMode rm> 501 ExecStatus 502 ReLqInt<View,CtrlView,rm>::post(Home home, View x, int c, CtrlView b) { 503 if (b.one()) { 504 if (rm != RM_PMI) 505 GECODE_ME_CHECK(x.lq(home,c)); 506 } else if (b.zero()) { 507 if (rm != RM_IMP) 508 GECODE_ME_CHECK(x.gr(home,c)); 509 } else { 510 switch (rtest_lq(x,c)) { 511 case RT_TRUE: 512 if (rm != RM_IMP) 513 GECODE_ME_CHECK(b.one_none(home)); 514 break; 515 case RT_FALSE: 516 if (rm != RM_PMI) 517 GECODE_ME_CHECK(b.zero_none(home)); 518 break; 519 case RT_MAYBE: 520 (void) new (home) ReLqInt<View,CtrlView,rm>(home,x,c,b); 521 break; 522 default: GECODE_NEVER; 523 } 524 } 525 return ES_OK; 526 } 527 528 529 template<class View, class CtrlView, ReifyMode rm> 530 forceinline 531 ReLqInt<View,CtrlView,rm>::ReLqInt(Space& home, ReLqInt& p) 532 : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,p), c(p.c) {} 533 534 template<class View, class CtrlView, ReifyMode rm> 535 Actor* 536 ReLqInt<View,CtrlView,rm>::copy(Space& home) { 537 return new (home) ReLqInt<View,CtrlView,rm>(home,*this); 538 } 539 540 template<class View, class CtrlView, ReifyMode rm> 541 ExecStatus 542 ReLqInt<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) { 543 if (b.one()) { 544 if (rm != RM_PMI) 545 GECODE_ME_CHECK(x0.lq(home,c)); 546 } else if (b.zero()) { 547 if (rm != RM_IMP) 548 GECODE_ME_CHECK(x0.gr(home,c)); 549 } else { 550 switch (rtest_lq(x0,c)) { 551 case RT_TRUE: 552 if (rm != RM_IMP) 553 GECODE_ME_CHECK(b.one_none(home)); 554 break; 555 case RT_FALSE: 556 if (rm != RM_PMI) 557 GECODE_ME_CHECK(b.zero_none(home)); 558 break; 559 case RT_MAYBE: 560 return ES_FIX; 561 default: GECODE_NEVER; 562 } 563 } 564 return home.ES_SUBSUMED(*this); 565 } 566 567}}} 568 569// STATISTICS: int-prop 570