// Remove the top node from the heap void CbcTree::pop() { # if CBC_DEBUG_HEAP > 2 CbcNode *node = nodes_.front() ; CbcNodeInfo *info = node->nodeInfo() ; assert(info) ; std::cout << " HEAP: Popping node " << node->nodeNumber() << "(" << std::hex << node << std::dec << ") obj " << node->objectiveValue() << ", ref " << info->decrement(0) << ", todo " << info->numberBranchesLeft() << ", refd by " << info->numberPointingToThis() << "." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif nodes_.front()->setOnTree(false); std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif }
// Add a node to the heap void CbcTree::push(CbcNode * x) { x->setNodeNumber(maximumNodeNumber_); maximumNodeNumber_++; # if CBC_DEBUG_HEAP > 2 CbcNodeInfo *info = x->nodeInfo() ; assert(info) ; std::cout << " HEAP: Pushing node " << x->nodeNumber() << "(" << std::hex << x << std::dec << ") obj " << x->objectiveValue() << ", ref " << info->decrement(0) << ", todo " << info->numberBranchesLeft() << ", refd by " << info->numberPointingToThis() << "." << std::endl ; assert(x->objectiveValue() != COIN_DBL_MAX); # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif x->setOnTree(true); nodes_.push_back(x); std::push_heap(nodes_.begin(), nodes_.end(), comparison_); # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif }
/** * * Ellenőrző függvény * */ void validate(bool items = false) { if (items) { for (unsigned int i=0; i<v.size(); ++i) std::cout << v[i] << " "; } std::cout << std::endl << "A vektor" << (validateHeap(v.begin(), v.end())?" ":" NEM ") << "teljesiti a kupac-tulajdonsagot!" << std::endl; }
/* Rebuild the heap. */ void CbcTree::rebuild () { std::make_heap(nodes_.begin(), nodes_.end(), comparison_); # if CBC_DEBUG_HEAP > 1 std::cout << " HEAP: rebuild complete." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif }
bool check() { return validateHeap(v.begin(), v.end()); }
void CbcTree::cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective) { # if CBC_DEBUG_HEAP > 1 std::cout << " cleanTree: beginning clean." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif int j; int nNodes = size(); CbcNode ** nodeArray = new CbcNode * [nNodes]; int * depth = new int [nNodes]; int k = 0; int kDelete = nNodes; bestPossibleObjective = 1.0e100 ; /* Destructively scan the heap. Nodes to be retained go into the front of nodeArray, nodes to be deleted into the back. Store the depth in a correlated array for nodes to be deleted. */ for (j = 0; j < nNodes; j++) { CbcNode * node = top(); pop(); double value = node ? node->objectiveValue() : COIN_DBL_MAX; if (node && value >= cutoff) { // double check in case node can change its mind! value = node->checkIsCutoff(cutoff); } if (value >= cutoff || !node->active()) { if (node) { nodeArray[--kDelete] = node; depth[kDelete] = node->depth(); } } else { bestPossibleObjective = CoinMin(bestPossibleObjective, value); nodeArray[k++] = node; } } /* Rebuild the heap using the retained nodes. */ for (j = 0; j < k; j++) { push(nodeArray[j]); } # if CBC_DEBUG_HEAP > 1 std::cout << " cleanTree: finished rebuild." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif /* Sort the list of nodes to be deleted, nondecreasing. */ CoinSort_2(depth + kDelete, depth + nNodes, nodeArray + kDelete); /* Work back from deepest to shallowest. In spite of the name, addCuts1 is just a preparatory step. When it returns, the following will be true: * all cuts are removed from the solver's copy of the constraint system; * lastws will be a basis appropriate for the specified node; * variable bounds will be adjusted to be appropriate for the specified node; * addedCuts_ (returned via addedCuts()) will contain a list of cuts that should be added to the constraint system at this node (but they have not actually been added). Then we scan the cut list for the node. Decrement the reference count for the cut, and if it's gone to 0, really delete it. I don't yet see why the checks for status != basic and addedCuts_[i] != 0 are necessary. When reconstructing a node, these checks are used to skip over loose cuts, excluding them from the reconstituted basis. But here we're just interested in correcting the reference count. Tight/loose should make no difference. Arguably a separate routine should be used in place of addCuts1. It's doing more work than needed, modifying the model to match a subproblem at a node that will be discarded. Then again, we seem to need the basis. */ for (j = nNodes - 1; j >= kDelete; j--) { CbcNode * node = nodeArray[j]; CoinWarmStartBasis *lastws = model->getEmptyBasis() ; model->addCuts1(node, lastws); // Decrement cut counts assert (node); //assert (node->nodeInfo()); int numberLeft = (node->nodeInfo()) ? node->nodeInfo()->numberBranchesLeft() : 0; int i; for (i = 0; i < model->currentNumberCuts(); i++) { // take off node CoinWarmStartBasis::Status status = lastws->getArtifStatus(i + model->numberRowsAtContinuous()); if (status != CoinWarmStartBasis::basic && model->addedCuts()[i]) { if (!model->addedCuts()[i]->decrement(numberLeft)) delete model->addedCuts()[i]; } } // node should not have anything pointing to it if (node->nodeInfo()) node->nodeInfo()->throwAway(); delete node ; delete lastws ; } delete [] nodeArray; delete [] depth; }
/* Return the best node from the heap. Note that best is offered a chance (checkIsCutoff) to reevaluate itself and make arbitrary changes. A caller should be prepared to check that the returned node is acceptable. There's quite a bit of suspect code here, much of it disabled in some way. The net effect at present is to return the top node on the heap after offering the node an opportunity to reevaluate itself. Documentation for checkIsCutoff() puts no restrictions on allowable changes. -- lh, 100921 -- */ CbcNode * CbcTree::bestNode(double cutoff) { # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif /* This code is problematic. As of 100921, there's really no loop. If front() == null, an assert will trigger. checkIsCutoff seems to be work in progress; comments assert that it can make pretty much arbitrary changes to best. If best can change its objective, there's a good possibility the heap is invalid. */ CbcNode * best = NULL; while (!best && nodes_.size()) { best = nodes_.front(); if (best) assert(best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()); if (best && best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()) assert (best->nodeInfo()->numberBranchesLeft()); if (best && best->objectiveValue() >= cutoff) { // double check in case node can change its mind! best->checkIsCutoff(cutoff); } if (!best || best->objectiveValue() >= cutoff) { #ifdef JJF_ZERO // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); delete best; best = NULL; #else // let code get rid of it assert (best); #endif } } /* See if the comparison object wants us to do a full scan with the alternative criteria. The net effect is to confirm best by the alternative criteria, or identify a competitor and erase it. This code is problematic. Nulling an arbitrary node will in general break the heap property. Disabled some time ago, as noted in several places. */ if (false && best && comparison_.test_->fullScan()) { CbcNode * saveBest = best; size_t n = nodes_.size(); size_t iBest = -1; for (size_t i = 0; i < n; i++) { // temp assert (nodes_[i]); assert (nodes_[i]->nodeInfo()); if (nodes_[i] && nodes_[i]->objectiveValue() != COIN_DBL_MAX && nodes_[i]->nodeInfo()) assert (nodes_[i]->nodeInfo()->numberBranchesLeft()); if (nodes_[i] && nodes_[i]->objectiveValue() < cutoff && comparison_.alternateTest(best, nodes_[i])) { best = nodes_[i]; iBest = i; } } if (best == saveBest) { // can pop // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } else { // make impossible nodes_[iBest] = NULL; } } else if (best) { # if CBC_DEBUG_HEAP > 2 CbcNode *node = nodes_.front() ; CbcNodeInfo *info = node->nodeInfo() ; assert(info) ; std::cout << " bestNode: Popping node " << node->nodeNumber() << "(" << std::hex << node << std::dec << ") obj " << node->objectiveValue() << ", ref " << info->decrement(0) << ", todo " << info->numberBranchesLeft() << ", refd by " << info->numberPointingToThis() << "." << std::endl ; # endif // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } #if CBC_DEBUG_HEAP > 0 validateHeap() ; #endif if (best) best->setOnTree(false); return best; }