1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 /* 3 * Main authors: 4 * Vincent Barichard <Vincent.Barichard@univ-angers.fr> 5 * 6 * Copyright: 7 * Vincent Barichard, 2014 8 * 9 * Last modified: 10 * $Date$ by $Author$ 11 * $Revision$ 12 * 13 * This file is part of Quacode: 14 * http://quacode.barichard.com 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining 17 * a copy of this software and associated documentation files (the 18 * "Software"), to deal in the Software without restriction, including 19 * without limitation the rights to use, copy, modify, merge, publish, 20 * distribute, sublicense, and/or sell copies of the Software, and to 21 * permit persons to whom the Software is furnished to do so, subject to 22 * the following conditions: 23 * 24 * The above copyright notice and this permission notice shall be 25 * included in all copies or substantial portions of the Software. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 31 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 32 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 33 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 34 * 35 */ 36 37 namespace Gecode { 38 39 forceinline DynamicStrategy* fromStaticStrategy(const Strategy & ds)40 DynamicStrategy::fromStaticStrategy(const Strategy& ds) { 41 assert(ds.bx == NULL); 42 return new DynamicStrategy(ds); 43 } 44 45 forceinline DynamicExpandStrategy* fromStaticStrategy(const Strategy & ds)46 DynamicExpandStrategy::fromStaticStrategy(const Strategy& ds) { 47 assert(ds.bx == NULL); 48 return new DynamicExpandStrategy(ds); 49 } 50 51 forceinline Strategy()52 Strategy::Strategy() 53 : bx(NULL), strategyTotalSize(0), cur(NULL), curDepth(0), lastEvent(NONE) 54 {} 55 56 forceinline Strategy(const Strategy & s)57 Strategy::Strategy(const Strategy& s) 58 : bx(NULL), domSize(s.domSize), idxInCurBranch(s.idxInCurBranch), strategyTotalSize(s.strategyTotalSize), cur(NULL), curBranch(s.curBranch), curDepth(s.curDepth), lastEvent(s.lastEvent) { 59 if (s.bx) { 60 bx = new (std::nothrow) Box[strategyTotalSize]; 61 Box* p = bx; 62 const Box* q = s.bx; 63 for (unsigned int i=s.strategyTotalSize ; i--; ) *p++ = *q++; 64 assert(s.cur); 65 cur = bx + (s.cur - s.bx); 66 } 67 } 68 69 forceinline ~Strategy()70 Strategy::~Strategy() { 71 if (bx) delete [] bx; 72 bx = NULL; 73 cur = NULL; 74 } 75 76 forceinline void makeLeaf(void)77 Strategy::makeLeaf(void) { 78 if (curDepth) (cur - 1)->val.leaf = true; 79 } 80 81 forceinline void backtrackFromFailure(int vId)82 Strategy::backtrackFromFailure(int vId) { 83 assert(curDepth > 0); 84 curDepth = idxInCurBranch[vId]; 85 cur = curBranch[curDepth].ptrCur; 86 } 87 88 forceinline void backtrackFromSuccess(int vId)89 Strategy::backtrackFromSuccess(int vId) { 90 assert(curDepth > 0); 91 curDepth = idxInCurBranch[vId]; 92 // We increase the number of the current alternative 93 curBranch[curDepth].ptrId->var.nbAlt++; 94 cur = curBranch[curDepth].ptrCur + 1 + curBranch[curDepth].curRemainingStrategySize; 95 } 96 97 forceinline void addVariable(int vId)98 Strategy::addVariable(int vId) { 99 if ((curDepth > 0) && (curBranch[curDepth-1].id == vId)) { 100 // We add again on the same variable so we overwrite the last box 101 curDepth--; 102 cur = curBranch[curDepth].ptrCur; 103 } else { 104 // We put the id of the variable only the first time we branch on it 105 unsigned int sizeBelow = curDepth?curBranch[curDepth-1].curRemainingStrategySize:strategyTotalSize; 106 sizeBelow = (sizeBelow - 1) / domSize[vId] - 1; 107 idxInCurBranch[vId] = curDepth; 108 (*cur).var.id = vId; 109 (*cur).var.needNewBlock = false; 110 (*cur++).var.nbAlt = 1; 111 curBranch[curDepth] = BPtr(vId,cur-1,sizeBelow); 112 } 113 } 114 115 forceinline void addValue(int,int vInf,int vSup)116 Strategy::addValue(int, int vInf, int vSup) { 117 BPtr& bPtr = curBranch[curDepth++]; 118 bPtr.vInf = vInf; 119 bPtr.vSup = vSup; 120 bPtr.ptrCur = cur; 121 (*cur).val.leaf = false; 122 (*cur).val.inf = vInf; 123 (*cur++).val.sup = vSup; 124 } 125 126 forceinline void scenarioFailed(void)127 Strategy::scenarioFailed(void) { 128 lastEvent = Strategy::FAILURE; 129 makeLeaf(); 130 } 131 132 forceinline void scenarioSuccess(const QSpaceInfo &)133 Strategy::scenarioSuccess(const QSpaceInfo&) { 134 lastEvent = Strategy::SUCCESS; 135 makeLeaf(); 136 } 137 138 forceinline void scenarioChoice(int vId,int vInf,int vSup)139 Strategy::scenarioChoice(int vId, int vInf, int vSup) { 140 switch (lastEvent) { 141 case Strategy::FAILURE: 142 backtrackFromFailure(vId); 143 goto branching; 144 case Strategy::SUCCESS: 145 backtrackFromSuccess(vId); 146 goto branching; 147 case Strategy::NONE: 148 case Strategy::CHOICE: 149 addVariable(vId); 150 branching: 151 lastEvent = Strategy::CHOICE; 152 addValue(vId,vInf,vSup); 153 } 154 } 155 156 forceinline StaticExpandStrategy()157 StaticExpandStrategy::StaticExpandStrategy() 158 : Strategy() {} 159 160 forceinline StaticExpandStrategy(const StaticExpandStrategy & s)161 StaticExpandStrategy::StaticExpandStrategy(const StaticExpandStrategy& s) 162 : Strategy(s) { } 163 164 forceinline ~StaticExpandStrategy()165 StaticExpandStrategy::~StaticExpandStrategy() { } 166 167 forceinline void addValue(int vId,int vInf,int vSup,unsigned int sizeBelow,bool & bForce)168 StaticExpandStrategy::addValue(int vId, int vInf, int vSup, unsigned int sizeBelow, bool& bForce) { 169 // Compute address of value of variable depending on the number of alternative 170 if (bForce || ((*cur).var.id != vId)) { 171 (*cur).var.id = vId; 172 (*cur).var.needNewBlock = false; 173 (*cur++).var.nbAlt = 1; 174 (*cur).val.leaf = false; 175 (*cur).val.inf = vInf; 176 (*cur++).val.sup = vSup; 177 bForce = true; 178 } else { 179 Box* ptrVal = cur + 1 + ((*cur).var.nbAlt - 1) * (1 + sizeBelow); 180 if (((*ptrVal).val.inf != vInf) || ((*ptrVal).val.sup != vSup)) { 181 if ((*cur).var.nbAlt < domSize[vId]) { 182 ptrVal += 1 + sizeBelow; 183 (*cur).var.nbAlt++; 184 } else { 185 // If we reach the last alternative we rewrite all 186 (*cur).var.nbAlt = 1; 187 } 188 cur = ptrVal; 189 (*cur).val.leaf = false; 190 (*cur).val.inf = vInf; 191 (*cur++).val.sup = vSup; 192 bForce = true; 193 } else { 194 // Its the same variable and value so we go next one 195 cur = ptrVal + 1; 196 } 197 } 198 } 199 200 forceinline void scenarioFailed(void)201 StaticExpandStrategy::scenarioFailed(void) { } 202 203 forceinline void scenarioSuccess(const QSpaceInfo & qsi)204 StaticExpandStrategy::scenarioSuccess(const QSpaceInfo& qsi) { 205 bool bForce = false; 206 unsigned int sizeBelow = strategyTotalSize; 207 cur = bx; 208 unsigned int i = 0; 209 const std::vector<QSpaceInfo::LkBinderVarObj>& _linkIdVars = qsi.sharedInfo.linkIdVars(); 210 for ( ; i<_linkIdVars.size(); i++) { 211 sizeBelow = (sizeBelow - 1) / domSize[i] - 1; 212 if (_linkIdVars[i].type == QSpaceInfo::LkBinderVarObj::BOOL) { 213 const BoolVar& x = qsi._boolVars[_linkIdVars[i].id]; 214 addValue(i,x.min(),x.max(),sizeBelow,bForce); 215 } else { 216 const IntVar& x = qsi._intVars[_linkIdVars[i].id]; 217 addValue(i,x.min(),x.max(),sizeBelow,bForce); 218 } 219 } 220 (cur - 1)->val.leaf = true; // Make last print to be a leaf 221 lastEvent = Strategy::SUCCESS; 222 } 223 224 forceinline void scenarioChoice(int,int,int)225 StaticExpandStrategy::scenarioChoice(int, int, int) { } 226 227 forceinline DynamicStrategy()228 DynamicStrategy::DynamicStrategy() 229 : Strategy(), bxBlockSize(0) {} 230 231 forceinline DynamicStrategy(const DynamicStrategy & s)232 DynamicStrategy::DynamicStrategy(const DynamicStrategy& s) 233 : Strategy(s), bxBlockSize(s.bxBlockSize) { 234 } 235 236 forceinline DynamicStrategy(const Strategy & s)237 DynamicStrategy::DynamicStrategy(const Strategy& s) 238 : Strategy(s), bxBlockSize(0) { 239 assert(bx == NULL); 240 } 241 242 forceinline ~DynamicStrategy()243 DynamicStrategy::~DynamicStrategy() { 244 int i = curDepth; 245 while (i >= 0) { 246 if (!curBranch[i].blocks.empty()) { 247 std::vector<Box*>::iterator it = curBranch[i].blocks.begin(); 248 std::vector<Box*>::iterator itEnd = curBranch[i].blocks.end(); 249 for ( ; it != itEnd; ++it) delete [] *it; 250 curBranch[i].blocks.clear(); 251 } 252 i--; 253 } 254 } 255 256 forceinline void backtrackFromSuccess(int vId)257 DynamicStrategy::backtrackFromSuccess(int vId) { 258 assert(curDepth > 0); 259 // We build the list of blocks to delete if node will be deleted 260 std::vector<Box*> blocks; 261 while (curDepth > idxInCurBranch[vId]) { 262 if (!curBranch[curDepth].blocks.empty()) { 263 blocks.insert(blocks.end(), curBranch[curDepth].blocks.begin(), curBranch[curDepth].blocks.end()); 264 curBranch[curDepth].blocks.clear(); 265 } 266 curDepth--; 267 } 268 // We increase the number of the current alternative 269 curBranch[curDepth].ptrId->var.nbAlt++; 270 curBranch[curDepth].blocks.insert(curBranch[curDepth].blocks.end(),blocks.begin(),blocks.end()); 271 cur = curBranch[curDepth].ptrCur + 1 + curBranch[curDepth].curRemainingBlockSize; 272 } 273 274 forceinline void backtrackFromFailure(int vId)275 DynamicStrategy::backtrackFromFailure(int vId) { 276 assert(curDepth > 0); 277 // We delete all blocks on the path to the variable to backtrack 278 while (curDepth > idxInCurBranch[vId]) { 279 if (!curBranch[curDepth].blocks.empty()) { 280 std::vector<Box*>::iterator it = curBranch[curDepth].blocks.begin(); 281 std::vector<Box*>::iterator itEnd = curBranch[curDepth].blocks.end(); 282 for ( ; it != itEnd; ++it) delete [] *it; 283 curBranch[curDepth].blocks.clear(); 284 } 285 curDepth--; 286 } 287 cur = curBranch[curDepth].ptrCur; 288 } 289 290 forceinline void addVariable(int vId)291 DynamicStrategy::addVariable(int vId) { 292 if ((curDepth > 0) && (curBranch[curDepth-1].id == vId)) { 293 // We add again on the same variable so we overwrite the last box 294 curDepth--; 295 cur = curBranch[curDepth].ptrCur; 296 } else { 297 // We put the id of the variable only the first time we branch on it 298 Box* newAllocatedBlock = NULL; 299 unsigned int sizeBelow = curDepth?curBranch[curDepth-1].curRemainingStrategySize:strategyTotalSize; 300 unsigned int allocatedBlockSize = curDepth?curBranch[curDepth-1].curRemainingBlockSize:bxBlockSize; 301 302 if (sizeBelow == 0) { 303 // We need to allocate a new block 304 sizeBelow = 0; 305 int k = domSize.size()-1; 306 for (int i = k; i >= vId; i-- ) { 307 if (domSize[i] > 0) sizeBelow = 1 + domSize[i] * (1 + sizeBelow); 308 } 309 k--; 310 311 allocatedBlockSize = sizeBelow; 312 while (allocatedBlockSize > sMaxBlockMemory) { 313 if (k <= vId) { 314 //We can at least store first level of strategy 315 std::cerr << "Can't allocate size for one level of strategy, try to disable it." << std::endl; 316 GECODE_NEVER; 317 } 318 k--; 319 sizeBelow = 0; 320 allocatedBlockSize = 2; // We save space for writing the flag to know that we have to allocate a new block plus the ptr to the new block 321 for (int i = k; i >= vId; i-- ) 322 if (domSize[i] > 0) { 323 sizeBelow = 1 + domSize[i] * (1 + sizeBelow); 324 allocatedBlockSize = 1 + domSize[i] * (1 + allocatedBlockSize); 325 } 326 } 327 newAllocatedBlock = new Box[allocatedBlockSize]; 328 (*cur).var.id = -1; 329 (*cur++).var.needNewBlock = true; 330 (*cur).nextBlock.ptr = newAllocatedBlock; 331 (*cur).nextBlock.size = allocatedBlockSize; 332 cur = newAllocatedBlock; 333 } 334 335 sizeBelow = (sizeBelow - 1) / domSize[vId] - 1; 336 allocatedBlockSize = (allocatedBlockSize - 1) / domSize[vId] - 1; 337 idxInCurBranch[vId] = curDepth; 338 (*cur).var.id = vId; 339 (*cur).var.needNewBlock = false; 340 (*cur++).var.nbAlt = 1; 341 curBranch[curDepth] = BPtr(vId,cur-1,sizeBelow,newAllocatedBlock,allocatedBlockSize); 342 } 343 } 344 345 forceinline void scenarioFailed(void)346 DynamicStrategy::scenarioFailed(void) { 347 lastEvent = Strategy::FAILURE; 348 makeLeaf(); 349 } 350 351 forceinline void scenarioSuccess(const QSpaceInfo &)352 DynamicStrategy::scenarioSuccess(const QSpaceInfo&) { 353 lastEvent = Strategy::SUCCESS; 354 makeLeaf(); 355 } 356 357 forceinline void scenarioChoice(int vId,int vInf,int vSup)358 DynamicStrategy::scenarioChoice(int vId, int vInf, int vSup) { 359 switch (lastEvent) { 360 case Strategy::FAILURE: 361 backtrackFromFailure(vId); 362 goto branching; 363 case Strategy::SUCCESS: 364 backtrackFromSuccess(vId); 365 goto branching; 366 case Strategy::NONE: 367 case Strategy::CHOICE: 368 addVariable(vId); 369 branching: 370 lastEvent = Strategy::CHOICE; 371 addValue(vId,vInf,vSup); 372 } 373 } 374 375 forceinline DynamicExpandStrategy()376 DynamicExpandStrategy::DynamicExpandStrategy() 377 : DynamicStrategy() {} 378 379 forceinline DynamicExpandStrategy(const DynamicExpandStrategy & s)380 DynamicExpandStrategy::DynamicExpandStrategy(const DynamicExpandStrategy& s) 381 : DynamicStrategy(s) { } 382 383 forceinline DynamicExpandStrategy(const Strategy & s)384 DynamicExpandStrategy::DynamicExpandStrategy(const Strategy& s) 385 : DynamicStrategy(s) { } 386 387 forceinline ~DynamicExpandStrategy()388 DynamicExpandStrategy::~DynamicExpandStrategy() { 389 // To force destructor of Dynamicstrategy to free all allocated blocks 390 curDepth = curBranch.size() - 1; 391 } 392 393 forceinline void addValue(int vId,int vInf,int vSup,unsigned int & sizeBelow,unsigned int & allocatedBlockSizeBelow,bool & bForce)394 DynamicExpandStrategy::addValue(int vId, int vInf, int vSup, unsigned int& sizeBelow, unsigned int& allocatedBlockSizeBelow, bool& bForce) { 395 if (sizeBelow == 0) { 396 // We need to allocate a new block 397 sizeBelow = 0; 398 int k = domSize.size()-1; 399 for (int i = k; i >= vId; i-- ) { 400 if (domSize[i] > 0) sizeBelow = 1 + domSize[i] * (1 + sizeBelow); 401 } 402 k--; 403 404 allocatedBlockSizeBelow = sizeBelow; 405 while (allocatedBlockSizeBelow > sMaxBlockMemory) { 406 if (k <= vId) { 407 //We can at least store first level of strategy 408 std::cerr << "Can't allocate size for one level of strategy, try to disable it." << std::endl; 409 GECODE_NEVER; 410 } 411 k--; 412 sizeBelow = 0; 413 allocatedBlockSizeBelow = 2; // We save space for writing the flag to know that we have to allocate a new block plus the ptr to the new block 414 for (int i = k; i >= vId; i-- ) 415 if (domSize[i] > 0) { 416 sizeBelow = 1 + domSize[i] * (1 + sizeBelow); 417 allocatedBlockSizeBelow = 1 + domSize[i] * (1 + allocatedBlockSizeBelow); 418 } 419 } 420 Box* newAllocatedBlock = new Box[allocatedBlockSizeBelow]; 421 // We remember the new allocated block in the curBranch data structure to free it when 422 // backtrack 423 curBranch[vId].blocks.push_back(newAllocatedBlock); 424 // Link new block to previous one 425 (*cur).var.id = -1; 426 (*cur).var.nbAlt = sizeBelow; // This block doesn't need the nbAlt field, so we use it to store sizeBelow 427 (*cur++).var.needNewBlock = true; 428 (*cur).nextBlock.ptr = newAllocatedBlock; 429 (*cur).nextBlock.size = allocatedBlockSizeBelow; 430 cur = newAllocatedBlock; 431 bForce = true; 432 } 433 sizeBelow = (sizeBelow - 1) / domSize[vId] - 1; 434 allocatedBlockSizeBelow = (allocatedBlockSizeBelow - 1) / domSize[vId] - 1; 435 436 // Compute address of value of variable depending on the number of alternative 437 if (bForce || ((*cur).var.id != vId)) { 438 // Add the current value and variable 439 (*cur).var.id = vId; 440 (*cur).var.needNewBlock = false; 441 (*cur++).var.nbAlt = 1; 442 (*cur).val.leaf = false; 443 (*cur).val.inf = vInf; 444 (*cur++).val.sup = vSup; 445 bForce = true; 446 } else { 447 Box* ptrVal = cur + 1 + ((*cur).var.nbAlt - 1) * (1 + allocatedBlockSizeBelow); 448 if (((*ptrVal).val.inf != vInf) || ((*ptrVal).val.sup != vSup)) { 449 if ((*cur).var.nbAlt < domSize[vId]) { 450 ptrVal += 1 + allocatedBlockSizeBelow; 451 (*cur).var.nbAlt++; 452 // We build the list of blocks to delete if node will be deleted 453 int curDepth = curBranch.size()-1; 454 std::vector<Box*> blocks; 455 while (curDepth > vId) { 456 if (!curBranch[curDepth].blocks.empty()) { 457 blocks.insert(blocks.end(), curBranch[curDepth].blocks.begin(), curBranch[curDepth].blocks.end()); 458 curBranch[curDepth].blocks.clear(); 459 } 460 curDepth--; 461 } 462 curBranch[curDepth].blocks.insert(curBranch[curDepth].blocks.end(),blocks.begin(),blocks.end()); 463 } else { 464 // If we reach the last alternative we rewrite all 465 (*cur).var.nbAlt = 1; 466 // We free all blocks allowed behond that point as we rewrite all 467 int curDepth = curBranch.size()-1; 468 while (curDepth > vId) { 469 if (!curBranch[curDepth].blocks.empty()) { 470 std::vector<Box*>::iterator it = curBranch[curDepth].blocks.begin(); 471 std::vector<Box*>::iterator itEnd = curBranch[curDepth].blocks.end(); 472 for ( ; it != itEnd; ++it) delete [] *it; 473 curBranch[curDepth].blocks.clear(); 474 } 475 curDepth--; 476 } 477 } 478 cur = ptrVal; 479 (*cur).val.leaf = false; 480 (*cur).val.inf = vInf; 481 (*cur++).val.sup = vSup; 482 bForce = true; 483 } else { 484 // Its the same variable and value so we go next one 485 cur = ptrVal + 1; 486 if (cur->var.needNewBlock) { 487 sizeBelow = cur->var.nbAlt; // This block doesn't need the nbAlt field, so we use it to store sizeBelow 488 cur++; 489 allocatedBlockSizeBelow = cur->nextBlock.size; 490 cur = cur->nextBlock.ptr; 491 } 492 } 493 } 494 } 495 496 forceinline void scenarioFailed(void)497 DynamicExpandStrategy::scenarioFailed(void) { } 498 499 forceinline void scenarioSuccess(const QSpaceInfo & qsi)500 DynamicExpandStrategy::scenarioSuccess(const QSpaceInfo& qsi) { 501 bool bForce = false; 502 unsigned int sizeBelow = strategyTotalSize; 503 unsigned int allocatedBlockSizeBelow = bxBlockSize; 504 cur = bx; 505 unsigned int i = 0; 506 const std::vector<QSpaceInfo::LkBinderVarObj>& _linkIdVars = qsi.sharedInfo.linkIdVars(); 507 for ( ; i<_linkIdVars.size(); i++) { 508 if (_linkIdVars[i].type == QSpaceInfo::LkBinderVarObj::BOOL) { 509 const BoolVar& x = qsi._boolVars[_linkIdVars[i].id]; 510 addValue(i,x.min(),x.max(),sizeBelow,allocatedBlockSizeBelow,bForce); 511 } else { 512 const IntVar& x = qsi._intVars[_linkIdVars[i].id]; 513 addValue(i,x.min(),x.max(),sizeBelow,allocatedBlockSizeBelow,bForce); 514 } 515 } 516 (cur - 1)->val.leaf = true; // Make last print to be a leaf 517 lastEvent = Strategy::SUCCESS; 518 } 519 520 forceinline void scenarioChoice(int,int,int)521 DynamicExpandStrategy::scenarioChoice(int, int, int) { } 522 523 forceinline void strategyReset(void)524 QSpaceInfo::QSpaceSharedInfoO::strategyReset(void) { 525 if (s) s->strategyReset(); 526 } 527 528 forceinline void strategyPrint(std::ostream & os) const529 QSpaceInfo::QSpaceSharedInfoO::strategyPrint(std::ostream& os) const { 530 if (s) s->print(os); 531 } 532 533 forceinline void scenarioSuccess(const QSpaceInfo & qsi)534 QSpaceInfo::QSpaceSharedInfoO::scenarioSuccess(const QSpaceInfo& qsi) { 535 s->scenarioSuccess(qsi); 536 } 537 538 forceinline void scenarioFailed(void)539 QSpaceInfo::QSpaceSharedInfoO::scenarioFailed(void) { 540 s->scenarioFailed(); 541 } 542 543 forceinline void scenarioChoice(unsigned int id,int pos,int vInf,int vSup)544 QSpaceInfo::QSpaceSharedInfoO::scenarioChoice(unsigned int id, int pos, int vInf, int vSup) { 545 int vId = v[id-1].offset + pos; 546 s->scenarioChoice(vId,vInf,vSup); 547 } 548 549 forceinline const std::vector<QSpaceInfo::LkBinderVarObj>& linkIdVars(void) const550 QSpaceInfo::QSpaceSharedInfoO::linkIdVars(void) const { 551 return _linkIdVars; 552 } 553 554 forceinline StrategyMethod strategyInit(StrategyMethod sm)555 QSpaceInfo::QSpaceSharedInfo::strategyInit(StrategyMethod sm) { 556 return static_cast<QSpaceSharedInfoO*>(object())->strategyInit(sm); 557 } 558 559 forceinline void strategyReset(void)560 QSpaceInfo::QSpaceSharedInfo::strategyReset(void) { 561 return static_cast<QSpaceSharedInfoO*>(object())->strategyReset(); 562 } 563 564 forceinline void strategyPrint(std::ostream & os) const565 QSpaceInfo::QSpaceSharedInfo::strategyPrint(std::ostream& os) const { 566 return static_cast<QSpaceSharedInfoO*>(object())->strategyPrint(os); 567 } 568 569 forceinline void scenarioSuccess(const QSpaceInfo & qsi)570 QSpaceInfo::QSpaceSharedInfo::scenarioSuccess(const QSpaceInfo& qsi) { 571 return static_cast<QSpaceSharedInfoO*>(object())->scenarioSuccess(qsi); 572 } 573 574 forceinline void scenarioFailed(void)575 QSpaceInfo::QSpaceSharedInfo::scenarioFailed(void) { 576 return static_cast<QSpaceSharedInfoO*>(object())->scenarioFailed(); 577 } 578 579 forceinline void scenarioChoice(unsigned int id,int pos,int vInf,int vSup)580 QSpaceInfo::QSpaceSharedInfo::scenarioChoice(unsigned int id, int pos, int vInf, int vSup) { 581 return static_cast<QSpaceSharedInfoO*>(object())->scenarioChoice(id,pos,vInf,vSup); 582 } 583 584 forceinline TQuantifier brancherQuantifier(unsigned int id) const585 QSpaceInfo::QSpaceSharedInfo::brancherQuantifier(unsigned int id) const { 586 return static_cast<QSpaceSharedInfoO*>(object())->brancherQuantifier(id); 587 } 588 589 forceinline unsigned int brancherOffset(unsigned int id) const590 QSpaceInfo::QSpaceSharedInfo::brancherOffset(unsigned int id) const { 591 return static_cast<QSpaceSharedInfoO*>(object())->brancherOffset(id); 592 } 593 594 forceinline int getLastBrancherId(void) const595 QSpaceInfo::QSpaceSharedInfo::getLastBrancherId(void) const { 596 return static_cast<QSpaceSharedInfoO*>(object())->getLastBrancherId(); 597 } 598 599 forceinline const std::vector<QSpaceInfo::LkBinderVarObj>& linkIdVars(void) const600 QSpaceInfo::QSpaceSharedInfo::linkIdVars(void) const { 601 return static_cast<QSpaceSharedInfoO*>(object())->linkIdVars(); 602 } 603 604 forceinline void eventNewInstance(void) const605 QSpaceInfo::eventNewInstance(void) const { } 606 607 forceinline TQuantifier brancherQuantifier(unsigned int id) const608 QSpaceInfo::brancherQuantifier(unsigned int id) const { 609 assert(id > 0); 610 return sharedInfo.brancherQuantifier(id); 611 } 612 613 forceinline unsigned int brancherOffset(unsigned int id) const614 QSpaceInfo::brancherOffset(unsigned int id) const { 615 assert(id > 0); 616 return sharedInfo.brancherOffset(id); 617 } 618 619 forceinline StrategyMethod strategyMethod(void) const620 QSpaceInfo::strategyMethod(void) const { 621 return curStrategyMethod; 622 } 623 624 forceinline void strategyMethod(StrategyMethod sm)625 QSpaceInfo::strategyMethod(StrategyMethod sm) { 626 curStrategyMethod = sm; 627 } 628 629 forceinline StrategyMethod strategyInit(void)630 QSpaceInfo::strategyInit(void) { 631 curStrategyMethod = sharedInfo.strategyInit(curStrategyMethod); 632 bRecordStrategy = (curStrategyMethod & StrategyMethodValues::BUILD); 633 return curStrategyMethod; 634 } 635 636 forceinline void strategyReset(void)637 QSpaceInfo::strategyReset(void) { 638 return sharedInfo.strategyReset(); 639 } 640 641 forceinline void strategyPrint(std::ostream & os) const642 QSpaceInfo::strategyPrint(std::ostream& os) const { 643 return sharedInfo.strategyPrint(os); 644 } 645 646 forceinline void strategySuccess(void)647 QSpaceInfo::strategySuccess(void) { 648 } 649 650 forceinline void strategyFailed(void)651 QSpaceInfo::strategyFailed(void) { 652 } 653 654 forceinline void scenarioSuccess(void)655 QSpaceInfo::scenarioSuccess(void) { 656 if (bRecordStrategy) sharedInfo.scenarioSuccess(*this); 657 } 658 659 forceinline void scenarioFailed(void)660 QSpaceInfo::scenarioFailed(void) { 661 if (bRecordStrategy) sharedInfo.scenarioFailed(); 662 } 663 664 template<class VarType> forceinline doubleChoice(const Space & home,const BrancherHandle & bh,unsigned int,VarType x,int pos,const int &,std::ostream &)665 void QSpaceInfo::doubleChoice (const Space &home, const BrancherHandle& bh, 666 unsigned int, 667 VarType x, int pos, const int&, 668 std::ostream& ) { 669 const QSpaceInfo& qsi = dynamic_cast<const QSpaceInfo&>(home); 670 if (qsi.bRecordStrategy) const_cast<QSpaceInfo&>(qsi).sharedInfo.scenarioChoice(bh.id(),pos,x.min(),x.max()); 671 } 672 673 template<> forceinline runCustomChoice(const Space & home,const BrancherHandle & bh,unsigned int alt,BoolVar x,int pos,const int & val,std::ostream & os)674 void QSpaceInfo::runCustomChoice (const Space &home, const BrancherHandle& bh, 675 unsigned int alt, 676 BoolVar x, int pos, const int& val, 677 std::ostream& os) { 678 assert(QSpaceInfo::customBoolVVP); 679 (*QSpaceInfo::customBoolVVP)(home,bh,alt,x,pos,val,os); 680 } 681 682 template<> forceinline runCustomChoice(const Space & home,const BrancherHandle & bh,unsigned int alt,IntVar x,int pos,const int & val,std::ostream & os)683 void QSpaceInfo::runCustomChoice (const Space &home, const BrancherHandle& bh, 684 unsigned int alt, 685 IntVar x, int pos, const int& val, 686 std::ostream& os) { 687 assert(QSpaceInfo::customIntVVP); 688 (*QSpaceInfo::customIntVVP)(home,bh,alt,x,pos,val,os); 689 } 690 691 template<class VarType> forceinline tripleChoice(const Space & home,const BrancherHandle & bh,unsigned int alt,VarType x,int pos,const int & val,std::ostream & os)692 void QSpaceInfo::tripleChoice (const Space &home, const BrancherHandle& bh, 693 unsigned int alt, 694 VarType x, int pos, const int& val, 695 std::ostream& os) { 696 const QSpaceInfo& qsi = dynamic_cast<const QSpaceInfo&>(home); 697 if (qsi.bRecordStrategy) const_cast<QSpaceInfo&>(qsi).sharedInfo.scenarioChoice(bh.id(),pos,x.min(),x.max()); 698 runCustomChoice(home,bh,alt,x,pos,val,os); 699 } 700 701 forceinline unsigned int watchConstraints(void) const702 QSpaceInfo::watchConstraints(void) const { 703 return nbWatchConstraint; 704 } 705 706 forceinline void addWatchConstraint(void)707 QSpaceInfo::addWatchConstraint(void) { 708 ++nbWatchConstraint; 709 } 710 711 forceinline void delWatchConstraint(void)712 QSpaceInfo::delWatchConstraint(void) { 713 --nbWatchConstraint; 714 } 715 716 forceinline void setForAll(Home home,BoolVar x)717 QSpaceInfo::setForAll(Home home, BoolVar x) { 718 // Create the unwatched variable and the watch constraint 719 BoolVar uw_x = BoolVar(home,x.min(),x.max()); 720 _unWatchedBoolVariables << uw_x; 721 _watchedBoolVariables << x; 722 Int::Watch<Int::BoolView>::post(home,x,uw_x,uw_x.size()); 723 } 724 725 forceinline void setForAll(Home home,const BoolVarArgs & x)726 QSpaceInfo::setForAll(Home home, const BoolVarArgs& x) { 727 for (int i=0; i<x.size(); i++) { 728 // Create the unwatched variable and the watch constraint 729 BoolVar uw_x = BoolVar(home,x[i].min(),x[i].max()); 730 _unWatchedBoolVariables << uw_x; 731 _watchedBoolVariables << x[i]; 732 Int::Watch<Int::BoolView>::post(home,x[i],uw_x,uw_x.size()); 733 } 734 } 735 736 forceinline void setForAll(Home home,IntVar x)737 QSpaceInfo::setForAll(Home home, IntVar x) { 738 // Create the unwatched variable and the watch constraint 739 IntVar uw_x = IntVar(home,x.min(),x.max()); 740 _unWatchedIntVariables << uw_x; 741 _watchedIntVariables << x; 742 Int::Watch<Int::IntView>::post(home,x,uw_x,uw_x.size()); 743 } 744 745 forceinline void setForAll(Home home,const IntVarArgs & x)746 QSpaceInfo::setForAll(Home home, const IntVarArgs& x) { 747 for (int i=0; i<x.size(); i++) { 748 // Create the unwatched variable and the watch constraint 749 IntVar uw_x = IntVar(home,x[i].min(),x[i].max()); 750 _unWatchedIntVariables << uw_x; 751 _watchedIntVariables << x[i]; 752 Int::Watch<Int::IntView>::post(home,x[i],uw_x,uw_x.size()); 753 } 754 } 755 756 forceinline BoolVar getUnWatched(BoolVar x)757 QSpaceInfo::getUnWatched(BoolVar x) { 758 for (int i=0; i < _watchedBoolVariables.size(); i++) 759 if (_watchedBoolVariables[i].same(x)) return _unWatchedBoolVariables[i]; 760 GECODE_NEVER; 761 return x; // Only for removing warning when compilation mode is Release 762 } 763 764 forceinline IntVar getUnWatched(IntVar x)765 QSpaceInfo::getUnWatched(IntVar x) { 766 for (int i=0; i < _watchedIntVariables.size(); i++) 767 if (_watchedIntVariables[i].same(x)) return _unWatchedIntVariables[i]; 768 GECODE_NEVER; 769 return x; // Only for removing warning when compilation mode is Release 770 } 771 772 forceinline BoolVar* unWatched(BoolVar x)773 QSpaceInfo::unWatched(BoolVar x) { 774 for (int i=0; i < _watchedBoolVariables.size(); i++) 775 if (_watchedBoolVariables[i].same(x)) return &_unWatchedBoolVariables[i]; 776 return NULL; 777 } 778 779 forceinline IntVar* unWatched(IntVar x)780 QSpaceInfo::unWatched(IntVar x) { 781 for (int i=0; i < _watchedIntVariables.size(); i++) 782 if (_watchedIntVariables[i].same(x)) return &_unWatchedIntVariables[i]; 783 return NULL; 784 } 785 786 } 787