Beispiel #1
0
// 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

}
Beispiel #2
0
// 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
}
void
CbcNodeInfo::incrementParentCuts(CbcModel * model, int change)
{
    if (parent_) {
        int i;
        // Get over-estimate of space needed for basis
        CoinWarmStartBasis & dummy = model->workingBasis();
        dummy.setSize(0, numberRows_ + numberCuts_);
        /* everything is zero (i.e. free) so we can use to see
           if latest basis */
        buildRowBasis(dummy);
        CbcNodeInfo * thisInfo = parent_;
        while (thisInfo)
            thisInfo = thisInfo->buildRowBasis(dummy);
        // increment cut counts
        thisInfo = parent_;
        int numberRows = numberRows_;
        while (thisInfo) {
            for (i = thisInfo->numberCuts_ - 1; i >= 0; i--) {
                CoinWarmStartBasis::Status status = dummy.getArtifStatus(--numberRows);
#ifdef ALLCUTS
                status = CoinWarmStartBasis::isFree;
#endif
                if (thisInfo->cuts_[i] && status != CoinWarmStartBasis::basic) {
                    thisInfo->cuts_[i]->increment(change);
                }
            }
            thisInfo = thisInfo->parent_;
        }
    }
}
void
CbcNodeInfo::decrementParentCuts(CbcModel * model, int change)
{
    if (parent_) {
        // get rid of all remaining if negative
        int changeThis;
        if (change < 0)
            changeThis = numberBranchesLeft_;
        else
            changeThis = change;
        int i;
        // Get over-estimate of space needed for basis
        CoinWarmStartBasis & dummy = model->workingBasis();
        dummy.setSize(0, numberRows_ + numberCuts_);
        buildRowBasis(dummy);
        /* everything is zero (i.e. free) so we can use to see
           if latest basis */
        CbcNodeInfo * thisInfo = parent_;
        while (thisInfo)
            thisInfo = thisInfo->buildRowBasis(dummy);
        // decrement cut counts
        thisInfo = parent_;
        int numberRows = numberRows_;
        while (thisInfo) {
            for (i = thisInfo->numberCuts_ - 1; i >= 0; i--) {
                CoinWarmStartBasis::Status status = dummy.getArtifStatus(--numberRows);
#ifdef ALLCUTS
                status = CoinWarmStartBasis::isFree;
#endif
                if (thisInfo->cuts_[i]) {
                    int number = 1;
                    if (status != CoinWarmStartBasis::basic) {
                        // tight - drop 1 or 2
                        if (change < 0)
                            number = thisInfo->cuts_[i]->decrement(changeThis);
                        else
                            number = thisInfo->cuts_[i]->decrement(change);
                    }
                    if (!number) {
#ifndef GLOBAL_CUTS_JUST_POINTERS
                        delete thisInfo->cuts_[i];
#else
                        if (thisInfo->cuts_[i]->globallyValidAsInteger() != 2)
                            delete thisInfo->cuts_[i];
#endif
                        thisInfo->cuts_[i] = NULL;
                    }
                }
            }
            thisInfo = thisInfo->parent_;
        }
    }
}
Beispiel #5
0
// First or second branch
CbcStatistics::CbcStatistics(CbcNode * node, CbcModel * model)
        :  endingObjective_(COIN_DBL_MAX),
        endingInfeasibility_(0),
        numberIterations_(0)
{
    CbcNodeInfo * nodeInfo = node->nodeInfo();
    CbcNodeInfo * parent = nodeInfo->parent();
    int numberBranches = nodeInfo->numberBranchesLeft();
    const CbcBranchingObject * branch = dynamic_cast <const CbcBranchingObject *>(node->branchingObject());
    const OsiTwoWayBranchingObject * branch2 = dynamic_cast <const OsiTwoWayBranchingObject *>(node->branchingObject());
    startingObjective_ = node->objectiveValue();
    way_ = node->way();
    depth_ = node->depth();
    startingInfeasibility_ = node->numberUnsatisfied();
    if (branch) {
        sequence_ = branch->variable();
        value_ = branch->value();
    } else {
        const OsiSimpleInteger * obj = dynamic_cast<const OsiSimpleInteger *>(branch2->originalObject());
        assert (obj);
        sequence_ = obj->columnNumber();
        value_ = branch2->value();
    }
    if (parent)
        parentId_ = parent->nodeNumber();
    else
        parentId_ = -1;
    if (numberBranches == 2) {
        id_ = nodeInfo->nodeNumber();
    } else {
        way_ *= 10;
        id_ = model->getNodeCount2();
    }
}
Beispiel #6
0
/*
  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;
}