00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <gecode/gist/spacenode.hh>
00039 #include <gecode/gist/visualnode.hh>
00040 #include <gecode/gist/stopbrancher.hh>
00041 #include <gecode/search.hh>
00042 #include <stack>
00043
00044 namespace Gecode { namespace Gist {
00045
00047 class Branch {
00048 public:
00050 int alternative;
00052 SpaceNode* ownBest;
00053 const Choice* choice;
00054
00056 Branch(int a, const Choice* c, SpaceNode* best = NULL)
00057 : alternative(a), ownBest(best) {
00058 choice = c;
00059 }
00060 };
00061
00062 BestNode::BestNode(SpaceNode* s0) : s(s0) {}
00063
00064 int
00065 SpaceNode::recompute(NodeAllocator& na,
00066 BestNode* curBest, int c_d, int a_d) {
00067 int rdist = 0;
00068
00069 if (copy == NULL) {
00070 SpaceNode* curNode = this;
00071 SpaceNode* lastFixpoint = NULL;
00072
00073 lastFixpoint = curNode;
00074
00075 std::stack<Branch> stck;
00076
00077 int idx = getIndex(na);
00078 while (curNode->copy == NULL) {
00079 SpaceNode* parent = curNode->getParent(na);
00080 int parentIdx = curNode->getParent();
00081 int alternative = curNode->getAlternative(na);
00082
00083 SpaceNode* ownBest = na.best(idx);
00084 Branch b(alternative, parent->choice,
00085 curBest == NULL ? NULL : ownBest);
00086 stck.push(b);
00087
00088 curNode = parent;
00089 idx = parentIdx;
00090 rdist++;
00091 }
00092 Space* curSpace = curNode->copy->clone();
00093 curNode->setDistance(0);
00094
00095 SpaceNode* lastBest = NULL;
00096 SpaceNode* middleNode = curNode;
00097 int curDist = 0;
00098
00099 while (!stck.empty()) {
00100 if (a_d >= 0 &&
00101 curDist > a_d &&
00102 curDist == rdist / 2) {
00103 if (curSpace->status() == SS_FAILED) {
00104 copy = static_cast<Space*>(Support::mark(curSpace));
00105 return rdist;
00106 } else {
00107 middleNode->copy = curSpace->clone();
00108 }
00109 }
00110 Branch b = stck.top(); stck.pop();
00111
00112 if(middleNode == lastFixpoint) {
00113 curSpace->status();
00114 }
00115
00116 curSpace->commit(*b.choice, b.alternative);
00117
00118 if (b.ownBest != NULL && b.ownBest != lastBest) {
00119 b.ownBest->acquireSpace(na,curBest, c_d, a_d);
00120 Space* ownBestSpace =
00121 static_cast<Space*>(Support::funmark(b.ownBest->copy));
00122 if (ownBestSpace->status() != SS_SOLVED) {
00123
00124
00125 ownBestSpace = Gecode::dfs(ownBestSpace);
00126 if (Support::marked(b.ownBest->copy)) {
00127 delete static_cast<Space*>(Support::unmark(b.ownBest->copy));
00128 b.ownBest->copy =
00129 static_cast<Space*>(Support::mark(ownBestSpace));
00130 } else {
00131 delete b.ownBest->copy;
00132 b.ownBest->copy = ownBestSpace;
00133 }
00134 }
00135 curSpace->constrain(*ownBestSpace);
00136 lastBest = b.ownBest;
00137 }
00138 curDist++;
00139 middleNode = middleNode->getChild(na,b.alternative);
00140 middleNode->setDistance(curDist);
00141 }
00142 copy = static_cast<Space*>(Support::mark(curSpace));
00143
00144 }
00145 return rdist;
00146 }
00147
00148 void
00149 SpaceNode::acquireSpace(NodeAllocator& na,
00150 BestNode* curBest, int c_d, int a_d) {
00151 SpaceNode* p = getParent(na);
00152 int parentIdx = getParent();
00153 int idx = getIndex(na);
00154
00155 if (getStatus() == UNDETERMINED && curBest != NULL &&
00156 na.best(idx) == NULL &&
00157 p != NULL && curBest->s != na.best(parentIdx)) {
00158 na.setBest(idx, curBest->s->getIndex(na));
00159 }
00160 SpaceNode* ownBest = na.best(idx);
00161
00162 if (copy == NULL && p != NULL && p->copy != NULL &&
00163 Support::marked(p->copy)) {
00164
00165 copy = p->copy;
00166 p->copy = NULL;
00167 if (p->choice != NULL)
00168 static_cast<Space*>(Support::unmark(copy))->
00169 commit(*p->choice, getAlternative(na));
00170
00171 if (ownBest != NULL) {
00172 ownBest->acquireSpace(na,curBest, c_d, a_d);
00173 Space* ownBestSpace =
00174 static_cast<Space*>(Support::funmark(ownBest->copy));
00175 if (ownBestSpace->status() != SS_SOLVED) {
00176
00177
00178
00179 ownBestSpace = Gecode::dfs(ownBestSpace);
00180 if (Support::marked(ownBest->copy)) {
00181 delete static_cast<Space*>(Support::unmark(ownBest->copy));
00182 ownBest->copy =
00183 static_cast<Space*>(Support::mark(ownBestSpace));
00184 } else {
00185 delete ownBest->copy;
00186 ownBest->copy = ownBestSpace;
00187 }
00188 }
00189 static_cast<Space*>(Support::unmark(copy))->constrain(*ownBestSpace);
00190 }
00191 int d = p->getDistance()+1;
00192 if (d > c_d && c_d >= 0 &&
00193 static_cast<Space*>(Support::unmark(copy))->status() == SS_BRANCH) {
00194 copy = static_cast<Space*>(Support::unmark(copy));
00195 d = 0;
00196 }
00197 setDistance(d);
00198 }
00199
00200 if (copy == NULL) {
00201 if (recompute(na, curBest, c_d, a_d) > c_d && c_d >= 0 &&
00202 static_cast<Space*>(Support::unmark(copy))->status() == SS_BRANCH) {
00203 copy = static_cast<Space*>(Support::unmark(copy));
00204 setDistance(0);
00205 }
00206 }
00207
00208
00209 static_cast<Space*>(Support::funmark(copy))->status();
00210 if (Support::marked(copy) && p != NULL && isOpen() &&
00211 p->copy != NULL && p->getNoOfOpenChildren(na) == 1 &&
00212 !p->isRoot()) {
00213
00214
00215
00216 assert(!Support::marked(p->copy));
00217
00218 copy = static_cast<Space*>(Support::unmark(copy));
00219 delete p->copy;
00220 p->copy = NULL;
00221 setDistance(0);
00222 p->setDistance(p->getParent(na)->getDistance()+1);
00223 }
00224 }
00225
00226 void
00227 SpaceNode::closeChild(const NodeAllocator& na,
00228 bool hadFailures, bool hadSolutions) {
00229 setHasFailedChildren(hasFailedChildren() || hadFailures);
00230 setHasSolvedChildren(hasSolvedChildren() || hadSolutions);
00231
00232 bool allClosed = true;
00233 for (int i=getNumberOfChildren(); i--;) {
00234 if (getChild(na,i)->isOpen()) {
00235 allClosed = false;
00236 break;
00237 }
00238 }
00239
00240 if (allClosed) {
00241 setHasOpenChildren(false);
00242 for (unsigned int i=0; i<getNumberOfChildren(); i++)
00243 setHasSolvedChildren(hasSolvedChildren() ||
00244 getChild(na,i)->hasSolvedChildren());
00245 SpaceNode* p = getParent(na);
00246 if (p != NULL) {
00247 delete copy;
00248 copy = NULL;
00249 p->closeChild(na, hasFailedChildren(), hasSolvedChildren());
00250 }
00251 } else {
00252
00253 if (hadSolutions) {
00254 setHasSolvedChildren(true);
00255 SpaceNode* p = getParent(na);
00256 while (p != NULL && !p->hasSolvedChildren()) {
00257 p->setHasSolvedChildren(true);
00258 p = p->getParent(na);
00259 }
00260 }
00261 if (hadFailures) {
00262 SpaceNode* p = getParent(na);
00263 while (p != NULL && !p->hasFailedChildren()) {
00264 p->setHasFailedChildren(true);
00265 p = p->getParent(na);
00266 }
00267 }
00268 }
00269
00270 }
00271
00272 SpaceNode::SpaceNode(Space* root)
00273 : Node(-1, root==NULL),
00274 copy(root), choice(NULL), nstatus(0) {
00275 if (root == NULL) {
00276 setStatus(FAILED);
00277 setHasSolvedChildren(false);
00278 setHasFailedChildren(true);
00279 } else {
00280 setStatus(UNDETERMINED);
00281 setHasSolvedChildren(false);
00282 setHasFailedChildren(false);
00283 }
00284 }
00285
00286 void
00287 SpaceNode::dispose(void) {
00288 delete choice;
00289 delete static_cast<Space*>(Support::funmark(copy));
00290 }
00291
00292
00293 int
00294 SpaceNode::getNumberOfChildNodes(NodeAllocator& na,
00295 BestNode* curBest, Statistics& stats,
00296 int c_d, int a_d) {
00297 int kids = 0;
00298 if (isUndetermined()) {
00299 stats.undetermined--;
00300 acquireSpace(na, curBest, c_d, a_d);
00301 switch (static_cast<Space*>(Support::funmark(copy))->status(stats)) {
00302 case SS_FAILED:
00303 {
00304 purge(na);
00305 kids = 0;
00306 setHasOpenChildren(false);
00307 setHasSolvedChildren(false);
00308 setHasFailedChildren(true);
00309 setStatus(FAILED);
00310 stats.failures++;
00311 SpaceNode* p = getParent(na);
00312 if (p != NULL)
00313 p->closeChild(na, true, false);
00314 }
00315 break;
00316 case SS_SOLVED:
00317 {
00318
00319 (void) static_cast<Space*>(Support::funmark(copy))->choice();
00320 kids = 0;
00321 setStatus(SOLVED);
00322 setHasOpenChildren(false);
00323 setHasSolvedChildren(true);
00324 setHasFailedChildren(false);
00325 stats.solutions++;
00326 if (curBest != NULL) {
00327 curBest->s = this;
00328 }
00329 SpaceNode* p = getParent(na);
00330 if (p != NULL)
00331 p->closeChild(na, false, true);
00332 }
00333 break;
00334 case SS_BRANCH:
00335 {
00336 choice = static_cast<Space*>(Support::funmark(copy))->choice();
00337 kids = choice->alternatives();
00338 setHasOpenChildren(true);
00339 if (dynamic_cast<const StopChoice*>(choice)) {
00340 setStatus(STOP);
00341 } else {
00342 setStatus(BRANCH);
00343 stats.choices++;
00344 }
00345 stats.undetermined += kids;
00346 }
00347 break;
00348 }
00349 static_cast<VisualNode*>(this)->changedStatus(na);
00350 setNumberOfChildren(kids, na);
00351 } else {
00352 kids = getNumberOfChildren();
00353 }
00354 return kids;
00355 }
00356
00357 int
00358 SpaceNode::getNoOfOpenChildren(const NodeAllocator& na) {
00359 if (!hasOpenChildren())
00360 return 0;
00361 int noOfOpenChildren = 0;
00362 for (int i=getNumberOfChildren(); i--;)
00363 noOfOpenChildren += (getChild(na,i)->isOpen());
00364 return noOfOpenChildren;
00365 }
00366
00367 }}
00368
00369