Exemplo n.º 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

}
Exemplo n.º 2
0
double
CbcBranchToFixLots::infeasibility(const OsiBranchingInformation * /*info*/,
                                  int &preferredWay) const
{
    preferredWay = -1;
    CbcNode * node = model_->currentNode();
    int depth;
    if (node)
        depth = CoinMax(node->depth(), 0);
    else
        return 0.0;
    if (depth_ < 0) {
        return 0.0;
    } else if (depth_ > 0) {
        if ((depth % depth_) != 0)
            return 0.0;
    }
    if (djTolerance_ != -1.234567) {
        if (!shallWe())
            return 0.0;
        else
            return 1.0e20;
    } else {
        // See if 3 in same row and sum <FIX_IF_LESS?
        int numberRows = matrixByRow_.getNumRows();
        const double * solution = model_->testSolution();
        const int * column = matrixByRow_.getIndices();
        const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
        const int * rowLength = matrixByRow_.getVectorLengths();
        double bestSum = 1.0;
        int nBest = -1;
        OsiSolverInterface * solver = model_->solver();
        for (int i = 0; i < numberRows; i++) {
            int numberUnsatisfied = 0;
            double sum = 0.0;
            for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
                int iColumn = column[j];
                if (solver->isInteger(iColumn)) {
                    double solValue = solution[iColumn];
                    if (solValue > 1.0e-5 && solValue < FIX_IF_LESS) {
                        numberUnsatisfied++;
                        sum += solValue;
                    }
                }
            }
            if (numberUnsatisfied >= 3 && sum < FIX_IF_LESS) {
                // possible
                if (numberUnsatisfied > nBest ||
                        (numberUnsatisfied == nBest && sum < bestSum)) {
                    nBest = numberUnsatisfied;
                    bestSum = sum;
                }
            }
        }
        if (nBest > 0)
            return 1.0e20;
        else
            return 0.0;
    }
}
Exemplo n.º 3
0
// Start dive
void
CbcCompareDefault::startDive(CbcModel * model)
{
    // Get best - using ? criterion
    double saveWeight = weight_;
    weight_ = 0.5 * saveWeight_; //0.0;
    // Switch off to get best
    startNodeNumber_ = -1;
    afterNodeNumber_ = -1;
    CbcNode * best = model->tree()->bestAlternate();
    startNodeNumber_ = best->nodeNumber();
    // send signal to setComparison
    setupForDiving_ = true ;
    /*
      TODO (review when fixing cleanDive and setComparison)
      Both afterNodeNumber_ and weight_ must not change
      after setComparison is invoked, as that will change
      the behaviour of test(). I replaced the overload on
      afterNodeNumber_ (magic number -2) with a boolean. Weight_
      is more problematic. Either it's correct before calling
      setComparison, or it needs to be cut from the tie-breaking
      part of test() during a dive, or there needs to be a new
      attribute to save and restore it around the dive. Otherwise
      heap checks fail in debug builds with Visual Studio.
      
      Given that weight_ was restored immediately after the call
      to setComparison, there should be no change in behaviour
      in terms of calls to test().
      -- lh, 100921 --
    */
    afterNodeNumber_ = model->tree()->maximumNodeNumber();
    weight_ = saveWeight ;
    // redo tree
    model->tree()->setComparison(*this);
    setupForDiving_ = false ;
}
Exemplo n.º 4
0
void
CbcTreeArray::cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective)
{
    int j;
    int nNodes = size();
    int lastNode = nNodes + 1;
    CbcNode ** nodeArray = new CbcNode * [lastNode];
    int * depth = new int [lastNode];
    int k = 0;
    int kDelete = lastNode;
    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 = nodes_.front();
        nodes_.front()->setOnTree(false);
        std::pop_heap(nodes_.begin(), nodes_.end(), comparison_);
        nodes_.pop_back();
        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;
        }
    }
    if (lastNode_) {
        double value = lastNode_->objectiveValue();
        bestPossibleObjective = CoinMin(bestPossibleObjective, value);
        if (value >= cutoff || !lastNode_->active()) {
            nodeArray[--kDelete] = lastNode_;
            depth[kDelete] = lastNode_->depth();
            lastNode_ = NULL;
        }
    }
    CbcCompareDefault * compareDefault
    = dynamic_cast<CbcCompareDefault *> (comparison_.test_);
    assert (compareDefault);
    compareDefault->setBestPossible(bestPossibleObjective);
    compareDefault->setCutoff(cutoff);
    /*
      Rebuild the heap using the retained nodes.
    */
    for (j = 0; j < k; j++) {
        CbcNode * node = nodeArray[j];
        node->setOnTree(true);
        nodes_.push_back(node);
        std::push_heap(nodes_.begin(), nodes_.end(), comparison_);
    }
    /*
      Sort the list of nodes to be deleted, nondecreasing.
    */
    CoinSort_2(depth + kDelete, depth + lastNode, 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 = lastNode - 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;
}
Exemplo n.º 5
0
// Gets best node and takes off heap
CbcNode *
CbcTreeArray::bestNode(double cutoff)
{
    CbcNode * best = NULL;
    // See if we want last node or best on heap
    if (lastNode_) {
#ifdef CBCTREE_PRINT
        printf("Best lastNode_ %x (%x at depth %d) - nodeNumber %d obj %g\n",
               lastNode_, lastNode_->nodeInfo(), lastNode_->depth(),
               lastNode_->nodeNumber(), lastNode_->objectiveValue());
#endif
        assert (lastNode_->onTree());
        int nodeNumber = lastNode_->nodeNumber();
        bool useLastNode = false;
        if (nodeNumber + 1 == maximumNodeNumber_) {
            // diving - look further
            CbcCompareDefault * compareDefault
            = dynamic_cast<CbcCompareDefault *> (comparison_.test_);
            assert (compareDefault);
            double bestPossible = compareDefault->getBestPossible();
            double cutoff = compareDefault->getCutoff();
            double objValue = lastNode_->objectiveValue();
            if (cutoff < 1.0e20) {
                if (objValue - bestPossible < 0.999*(cutoff - bestPossible))
                    useLastNode = true;
            } else {
                useLastNode = true;
            }
        }
        if (useLastNode) {
            lastNode_->setOnTree(false);
            best = lastNode_;
            lastNode_ = NULL;
            assert(best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo());
            if (best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo())
                assert (best->nodeInfo()->numberBranchesLeft());
            if (best->objectiveValue() >= cutoff) {
                // double check in case node can change its mind!
                best->checkIsCutoff(cutoff);
            }
            lastNodePopped_ = best;
            return best;
        } else {
            // put on tree
            nodes_.push_back(lastNode_);
            lastNode_->setNodeNumber(maximumNodeNumber_);
            maximumNodeNumber_++;
            lastNode_ = NULL;
            std::push_heap(nodes_.begin(), nodes_.end(), comparison_);
        }
    }
    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) {
            // let code get rid of it
            assert (best);
        }
    }
    lastNodePopped_ = best;
#ifdef CBCTREE_PRINT
    if (best)
        printf("Heap returning node %x (%x at depth %d) - nodeNumber %d - obj %g\n",
               best, best->nodeInfo(), best->depth(),
               best->nodeNumber(), best->objectiveValue());
    else
        printf("Heap returning Null\n");
#endif
    if (best) {
        // take off
        std::pop_heap(nodes_.begin(), nodes_.end(), comparison_);
        nodes_.pop_back();
    }
#ifdef DEBUG_CBC_HEAP
    if (best) {
        int n = nodes_.size();
        bool good = true;
        for (int i = 0; i < n; i++) {
            // temp
            assert (nodes_[i]);
            if (!comparison_.compareNodes(nodes_[i], best)) {
                good = false;
                CbcNode * x = nodes_[i];
                printf("i=%d x is better nun %d depth %d obj %g, best nun %d depth %d obj %g\n", i,
                       x->numberUnsatisfied(), x->depth(), x->objectiveValue(),
                       best->numberUnsatisfied(), best->depth(), best->objectiveValue());
            }
        }
        if (!good) {
            // compare best to all
            int i;
            for (i = 0; i < n; i++) {
                CbcNode * x = nodes_[i];
                printf("i=%d x is nun %d depth %d obj %g", i,
                       x->numberUnsatisfied(), x->depth(), x->objectiveValue());
                if (!comparison_.compareNodes(x, best)) {
                    printf(" - best is worse!\n");
                } else {
                    printf("\n");
                }
            }
            // Now compare amongst rest
            for (i = 0; i < n; i++) {
                CbcNode * x = nodes_[i];
                printf("For i=%d ", i);
                for (int j = i + 1; j < n; j++) {
                    CbcNode * y = nodes_[j];
                    if (!comparison_.compareNodes(x, y)) {
                        printf(" b %d", j);
                    } else {
                        printf(" w %d", j);
                    }
                }
                printf("\n");
            }
            assert(good);
        }
    }
#endif
    if (best)
        best->setOnTree(false);
    return best;
}
Exemplo n.º 6
0
void CbcTree::validateHeap ()
{
  if (comparison_.test_ == 0) {
    std::cout
      << " Invalid heap (no predicate)!" << std::endl ;
    return ;
  }
  std::vector<CbcNode *>::const_iterator curNode,lastNode ;
  curNode = nodes_.begin() ;
  lastNode = nodes_.end() ;
  int curNdx = 0 ;
  int parNdx = 0 ;
  if (curNode == lastNode) return ;
  if (*curNode == 0) {
    std::cout
      << " Invalid heap[" << curNdx << "] (null entry)!" << std::endl ;
  }
  std::vector<CbcNode *>::const_iterator parent ;
  std::vector<CbcNode*>::const_iterator &child = curNode ;
  for (parent = curNode ; ++curNode != lastNode ; ++parent, ++parNdx) {
    curNdx++ ;
    if (*parent == 0) {
      std::cout
        << " Invalid heap[" << parNdx << "] (parent null entry)!" << std::endl ;
      curNode++ ;
      curNdx++ ;
      continue ;
    }
    if (*curNode == 0) {
      std::cout
        << " Invalid heap[" << curNdx << "] (left child null entry)!"
	<< std::endl ;
    } else {
      if (!check_pred(*comparison_.test_,*parent,*child)) {
        std::cout
          << " Invalid heap (left child better)!" << std::endl ;
        CbcNode *node = *parent ; 
        std::cout
          << "   Parent [" << parNdx << "] (" << std::hex << node << std::dec
          << ") unsat " << node->numberUnsatisfied() << ", depth "
	  << node->depth() << ", obj " << node->objectiveValue() << "."
	  << std::endl ;
        node = *child ;
        std::cout
          << "   Child [" << curNdx << "] (" << std::hex << node << std::dec
          << ") unsat " << node->numberUnsatisfied() << ", depth "
	  << node->depth() << ", obj " << node->objectiveValue() << "."
	  << std::endl ;
      }
    }
    curNode++ ;
    curNdx++ ;
    if (curNode == lastNode) break ;
    if (*curNode == 0) {
      std::cout
        << " Invalid heap[" << curNdx << "] (right child null entry)!"
	<< std::endl ;
    } else {
      if (!check_pred(*comparison_.test_,*parent,*child)) {
        std::cout
          << " Invalid heap (right child better)!" << std::endl ;
        CbcNode *node = *parent ;
        std::cout
          << "   Parent [" << parNdx << "] (" << std::hex << node << std::dec
          << ") unsat " << node->numberUnsatisfied() << ", depth "
	  << node->depth() << ", obj " << node->objectiveValue() << "."
	  << std::endl ;
        node = *child ;
        std::cout
          << "   Child [" << curNdx << "] (" << std::hex << node << std::dec
          << ") unsat " << node->numberUnsatisfied() << ", depth "
	  << node->depth() << ", obj " << node->objectiveValue() << "."
	  << std::endl ;
      }
    }
  }
  return ;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
// Gets best node and takes off heap
CbcNode *
CbcTree::bestNode(double cutoff)
{
    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
        }
    }
    // switched off for now
    if (best && comparison_.test_->fullScan() && false) {
        CbcNode * saveBest = best;
        int n = nodes_.size();
        int iBest = -1;
        for (int 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) {
        // take off
#ifdef JJF_ZERO
        std::pop_heap(nodes_.begin(), nodes_.end(), comparison_);
        nodes_.pop_back();
#else
realpop();
#endif
    }
#ifdef DEBUG_CBC_HEAP
    if (best) {
        int n = nodes_.size();
        bool good = true;
        for (int i = 0; i < n; i++) {
            // temp
            assert (nodes_[i]);
            if (!comparison_.compareNodes(nodes_[i], best)) {
                good = false;
                CbcNode * x = nodes_[i];
                printf("i=%d x is better nun %d depth %d obj %g, best nun %d depth %d obj %g\n", i,
                       x->numberUnsatisfied(), x->depth(), x->objectiveValue(),
                       best->numberUnsatisfied(), best->depth(), best->objectiveValue());
            }
        }
        if (!good) {
            // compare best to all
            int i;
            for (i = 0; i < n; i++) {
                CbcNode * x = nodes_[i];
                printf("i=%d x is nun %d depth %d obj %g", i,
                       x->numberUnsatisfied(), x->depth(), x->objectiveValue());
                if (!comparison_.compareNodes(x, best)) {
                    printf(" - best is worse!\n");
                } else {
                    printf("\n");
                }
            }
            // Now compare amongst rest
            for (i = 0; i < n; i++) {
                CbcNode * x = nodes_[i];
                printf("For i=%d ", i);
                for (int j = i + 1; j < n; j++) {
                    CbcNode * y = nodes_[j];
                    if (!comparison_.compareNodes(x, y)) {
                        printf(" b %d", j);
                    } else {
                        printf(" w %d", j);
                    }
                }
                printf("\n");
            }
            assert(good);
        }
    }
#endif
    if (best)
        best->setOnTree(false);
    return best;
}