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