Changeset 222


Ignore:
Timestamp:
Dec 9, 2005 6:07:01 PM (14 years ago)
Author:
forrest
Message:

towards next version

Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/CbcBranchActual.cpp

    r216 r222  
    1111
    1212#include "OsiSolverInterface.hpp"
     13#include "OsiSolverBranch.hpp"
    1314#include "CbcModel.hpp"
    1415#include "CbcMessage.hpp"
     
    423424      // Possibly due to scaling a fixed variable might slip through
    424425      if (value>upper[iColumn]) {
     426        value=upper[iColumn];
    425427        // Could change to #ifdef CBC_DEBUG
    426428#ifndef NDEBUG
    427         if (model_->messageHandler()->logLevel()>1)
     429        if (model_->messageHandler()->logLevel()>2)
    428430          printf("** Variable %d (%d) has value %g and upper bound of %g\n",
    429431                 iColumn,j,value,upper[iColumn]);
     
    719721}
    720722
     723/* Create an OsiSolverBranch object
     724   
     725This returns NULL if branch not represented by bound changes
     726*/
     727OsiSolverBranch *
     728CbcSimpleInteger::solverBranch() const
     729{
     730  OsiSolverInterface * solver = model_->solver();
     731  const double * solution = model_->testSolution();
     732  const double * lower = solver->getColLower();
     733  const double * upper = solver->getColUpper();
     734  double value = solution[columnNumber_];
     735  value = CoinMax(value, lower[columnNumber_]);
     736  value = CoinMin(value, upper[columnNumber_]);
     737  assert (upper[columnNumber_]>lower[columnNumber_]);
     738#ifndef NDEBUG
     739  double nearest = floor(value+0.5);
     740  double integerTolerance =
     741    model_->getDblParam(CbcModel::CbcIntegerTolerance);
     742  assert (fabs(value-nearest)>integerTolerance);
     743#endif
     744  OsiSolverBranch * branch = new OsiSolverBranch();
     745  branch->addBranch(columnNumber_,value);
     746  return branch;
     747}
     748 
    721749
    722750/* Given valid solution (i.e. satisfied) and reduced costs etc
     
    18651893  }
    18661894  return betterWay;
     1895}
     1896/* Sets or gets best criterion so far */
     1897void
     1898CbcBranchDefaultDecision::setBestCriterion(double value)
     1899{
     1900  bestCriterion_ = value;
     1901}
     1902double
     1903CbcBranchDefaultDecision::getBestCriterion() const
     1904{
     1905  return bestCriterion_;
    18671906}
    18681907
  • trunk/CbcBranchBase.cpp

    r216 r222  
    1010
    1111#include "OsiSolverInterface.hpp"
     12#include "OsiSolverBranch.hpp"
    1213#include "CbcModel.hpp"
    1314#include "CbcMessage.hpp"
     
    9091  return -1;
    9192}
     93/* Create an OsiSolverBranch object
     94   
     95This returns NULL if branch not represented by bound changes
     96*/
     97OsiSolverBranch *
     98CbcObject::solverBranch() const
     99{
     100  return NULL;
     101}
     102 
    92103// Default Constructor
    93104CbcBranchingObject::CbcBranchingObject()
  • trunk/CbcBranchDynamic.cpp

    r208 r222  
    1111
    1212#include "OsiSolverInterface.hpp"
     13#include "OsiSolverBranch.hpp"
    1314#include "CbcModel.hpp"
    1415#include "CbcMessage.hpp"
     
    211212  return newObject;
    212213}
     214/* Create an OsiSolverBranch object
     215   
     216This returns NULL if branch not represented by bound changes
     217*/
     218OsiSolverBranch *
     219CbcSimpleIntegerDynamicPseudoCost::solverBranch() const
     220{
     221  OsiSolverInterface * solver = model_->solver();
     222  const double * solution = model_->testSolution();
     223  const double * lower = solver->getColLower();
     224  const double * upper = solver->getColUpper();
     225  double value = solution[columnNumber_];
     226  value = CoinMax(value, lower[columnNumber_]);
     227  value = CoinMin(value, upper[columnNumber_]);
     228  assert (upper[columnNumber_]>lower[columnNumber_]);
     229#ifndef NDEBUG
     230  double nearest = floor(value+0.5);
     231  double integerTolerance =
     232    model_->getDblParam(CbcModel::CbcIntegerTolerance);
     233  assert (fabs(value-nearest)>integerTolerance);
     234#endif
     235  OsiSolverBranch * branch = new OsiSolverBranch();
     236  branch->addBranch(columnNumber_,value);
     237  return branch;
     238}
     239 
    213240// Infeasibility - large is 0.5
    214241double
     
    768795  return betterWay;
    769796}
     797/* Sets or gets best criterion so far */
     798void
     799CbcBranchDynamicDecision::setBestCriterion(double value)
     800{
     801  bestCriterion_ = value;
     802}
     803double
     804CbcBranchDynamicDecision::getBestCriterion() const
     805{
     806  return bestCriterion_;
     807}
  • trunk/CbcModel.cpp

    r220 r222  
    2121
    2222#include "OsiSolverInterface.hpp"
     23#include "OsiSolverBranch.hpp"
    2324#include "CoinWarmStartBasis.hpp"
    2425#include "CoinPackedMatrix.hpp"
     
    4142// include Probing
    4243#include "CglProbing.hpp"
    43 
     44// include preprocessing
     45#include "CglPreProcess.hpp"
    4446
    4547#include "CoinTime.hpp"
     
    121123  for (j = 0 ; j < nNodes ; j++)
    122124  { CbcNode *node = branchingTree->nodePointer(j) ;
     125  if (!node)
     126    continue;
    123127    CbcNodeInfo *nodeInfo = node->nodeInfo() ;
    124128    int change = node->nodeInfo()->numberBranchesLeft() ;
     
    349353  return ;
    350354}
    351 
     355#ifndef CBC_NEXT_VERSION
    352356
    353357
     
    382386
    383387{
     388/*
     389  Capture a time stamp before we start.
     390*/
     391  dblParam_[CbcStartSeconds] = CoinCpuTime();
     392  // original solver (only set if pre-processing)
     393  OsiSolverInterface * originalSolver=NULL;
    384394  // Set up strategies
    385395  if (strategy_) {
     396    // May do preprocessing
     397    originalSolver = solver_;
     398    strategy_->setupOther(*this);
     399    if (strategy_->preProcessState()) {
     400      // pre-processing done
     401      if (strategy_->preProcessState()<0) {
     402        // infeasible
     403        handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;
     404        status_ = 0 ;
     405        secondaryStatus_ = 1;
     406        originalContinuousObjective_ = COIN_DBL_MAX;
     407        return ;
     408      }
     409    } else {
     410      //no preprocessing
     411      originalSolver=NULL;
     412    }
    386413    strategy_->setupCutGenerators(*this);
    387414    strategy_->setupHeuristics(*this);
    388415    // Set strategy print level to models
    389416    strategy_->setupPrinting(*this,handler_->logLevel());
    390     strategy_->setupOther(*this);
    391   }
    392   bool eventHappened=false;
     417  }
     418  eventHappened_=false;
    393419  ClpEventHandler * eventHandler=NULL;
    394420#ifdef COIN_USE_CLP
     
    444470*/
    445471  synchronizeModel() ;
    446 /*
    447   Capture a time stamp before we start.
    448 */
    449   dblParam_[CbcStartSeconds] = CoinCpuTime();
    450472  // Set so we can tell we are in initial phase in resolve
    451473  continuousObjective_ = -COIN_DBL_MAX ;
     
    553575  that produced a given cut.
    554576*/
    555   int maximumWhich = 1000 ;
    556   int * whichGenerator = new int[maximumWhich] ;
     577  maximumWhich_ = 1000 ;
     578  delete [] whichGenerator_;
     579  whichGenerator_ = new int[maximumWhich_] ;
     580  memset(whichGenerator_,0,maximumWhich_*sizeof(int));
    557581  int currentNumberCuts = 0 ;
    558582  maximumNumberCuts_ = 0 ;
     
    586610  At the end of all this, any cuts will be recorded in cuts and also
    587611  installed in the solver's constraint system. We'll have reoptimised, and
    588   removed any slack cuts (numberOldActiveCuts and numberNewCuts have been
     612  removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
    589613  adjusted accordingly).
    590614
     
    602626  OsiCuts cuts ;
    603627  int anyAction = -1 ;
    604   int numberOldActiveCuts = 0 ;
    605   int numberNewCuts = 0 ;
     628  numberOldActiveCuts_ = 0 ;
     629  numberNewCuts_ = 0 ;
    606630  // Array to mark solution
    607631  delete [] usedInSolution_;
     
    614638  numberNodes_ = 0 ;
    615639  numberNodes2_ = 0 ;
    616   int maximumStatistics=0;
    617   CbcStatistics ** statistics = NULL;
     640  maximumStatistics_=0;
     641  statistics_ = NULL;
    618642  // Do on switch
    619643  if (doStatistics) {
    620     maximumStatistics=10000;
    621     statistics = new CbcStatistics * [maximumStatistics];
    622     memset(statistics,0,maximumStatistics*sizeof(CbcStatistics *));
     644    maximumStatistics_=10000;
     645    statistics_ = new CbcStatistics * [maximumStatistics_];
     646    memset(statistics_,0,maximumStatistics_*sizeof(CbcStatistics *));
    623647  }
    624648
     
    634658      if (infeasibility ) numberUnsatisfied++ ; }
    635659    if (numberUnsatisfied) {
    636       feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,
    637                                NULL,numberOldActiveCuts,numberNewCuts,
    638                                maximumWhich, whichGenerator) ;
     660      feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,NULL);
    639661    }
    640662  }
     
    644666    generator->setAggressiveness(generator->getAggressiveness()-100);
    645667  }
    646   currentNumberCuts_ = numberNewCuts ;
     668  currentNumberCuts_ = numberNewCuts_ ;
    647669/*
    648670  We've taken the continuous relaxation as far as we can. Time to branch.
     
    662684  bool resolved = false ;
    663685  CbcNode *newNode = NULL ;
    664   int numberFixedAtRoot=0;
    665   int numberFixedNow=0;
     686  numberFixedAtRoot_=0;
     687  numberFixedNow_=0;
    666688  if (feasible)
    667689  { newNode = new CbcNode ;
     
    681703      delete [] analyzeResults_;
    682704      analyzeResults_ = new double [4*numberIntegers_];
    683       numberFixedAtRoot=newNode->analyze(this,analyzeResults_);
    684       if (numberFixedAtRoot>0) {
    685         printf("%d fixed by analysis\n",numberFixedAtRoot);
     705      numberFixedAtRoot_=newNode->analyze(this,analyzeResults_);
     706      if (numberFixedAtRoot_>0) {
     707        printf("%d fixed by analysis\n",numberFixedAtRoot_);
    686708        setPointers(solver_);
    687         numberFixedNow = numberFixedAtRoot;
    688       } else if (numberFixedAtRoot<0) {
     709        numberFixedNow_ = numberFixedAtRoot_;
     710      } else if (numberFixedAtRoot_<0) {
    689711        printf("analysis found to be infeasible\n");
    690712        anyAction=-2;
     
    696718    while (anyAction == -1)
    697719    {
     720      newNode->setObjectiveValue(direction*solver_->getObjValue()) ;
    698721      if (numberBeforeTrust_==0 ) {
    699722        anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ;
    700723      } else {
    701         anyAction = newNode->chooseDynamicBranch(this,NULL,numberPassesLeft) ;
     724        OsiSolverBranch * branches=NULL;
     725        anyAction = newNode->chooseDynamicBranch(this,NULL,branches,numberPassesLeft) ;
    702726        if (anyAction==-3)
    703727          anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ; // dynamic did nothing
     
    746770  { if (resolved)
    747771    { bool needValidSolution = (newNode->variable() < 0) ;
    748       takeOffCuts(cuts,whichGenerator,numberOldActiveCuts,numberNewCuts,
    749                   needValidSolution,NULL) ;
     772      takeOffCuts(cuts,needValidSolution,NULL) ;
    750773#     ifdef CHECK_CUT_COUNTS
    751774      { printf("Number of rows after chooseBranch fix (root)"
    752775               "(active only) %d\n",
    753                 numberRowsAtContinuous_+numberNewCuts+numberOldActiveCuts) ;
     776                numberRowsAtContinuous_+numberNewCuts_+numberOldActiveCuts_) ;
    754777        const CoinWarmStartBasis* debugws =
    755778          dynamic_cast <const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
     
    760783    newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
    761784    newNode->nodeInfo()->addCuts(cuts,
    762                                  newNode->numberBranches(),whichGenerator) ;
    763 /*
    764   Courtesy of createInfo, there's now a full basis stashed in
    765   newNode->nodeInfo_->basis_. We're about to make two more copies, lastws and
    766   model.basis_.
    767 
    768   (jf) With some thought I should be able to get rid of lastws and use
    769   basis_.
    770   (lh) I agree, but haven't pursued it to the end.
    771 */
    772     if (basis_) delete basis_ ;
    773     basis_ = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
     785                                 newNode->numberBranches(),whichGenerator_) ;
    774786    if (lastws) delete lastws ;
    775     lastws = dynamic_cast<CoinWarmStartBasis*>(basis_->clone()) ; }
     787    lastws = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
     788  }
    776789/*
    777790  Continuous data to be used later
     
    791804    for (i = 0;i < numberObjects_;i++)
    792805      object_[i]->resetBounds() ; }
    793   bool stoppedOnGap = false ;
     806  stoppedOnGap_ = false ;
    794807/*
    795808  Feasible? Then we should have either a live node prepped for future
     
    806819      newNode->initializeInfo() ;
    807820      tree_->push(newNode) ;
    808       if (statistics) {
    809         if (numberNodes2_==maximumStatistics) {
    810           maximumStatistics = 2*maximumStatistics;
    811           CbcStatistics ** temp = new CbcStatistics * [maximumStatistics];
    812           memset(temp,0,maximumStatistics*sizeof(CbcStatistics *));
    813           memcpy(temp,statistics,numberNodes2_*sizeof(CbcStatistics *));
    814           delete [] statistics;
    815           statistics=temp;
     821      if (statistics_) {
     822        if (numberNodes2_==maximumStatistics_) {
     823          maximumStatistics_ = 2*maximumStatistics_;
     824          CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     825          memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     826          memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     827          delete [] statistics_;
     828          statistics_=temp;
    816829        }
    817         assert (!statistics[numberNodes2_]);
    818         statistics[numberNodes2_]=new CbcStatistics(newNode);
     830        assert (!statistics_[numberNodes2_]);
     831        statistics_[numberNodes2_]=new CbcStatistics(newNode);
    819832      }
    820833      numberNodes2_++;
     
    841854    again and again.  This can take too long.  So we need to warn user - just once.
    842855  */
    843   int numberLongStrong=0;
     856  numberLongStrong_=0;
    844857/*
    845858  At last, the actual branch-and-cut search loop, which will iterate until
     
    875888        if (newCutoff==-COIN_DBL_MAX) {
    876889          printf("Root analysis says finished\n");
    877         } else if (n>numberFixedNow) {
    878           printf("%d more fixed by analysis - now %d\n",n-numberFixedNow,n);
    879           numberFixedNow=n;
     890        } else if (n>numberFixedNow_) {
     891          printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
     892          numberFixedNow_=n;
    880893        }
    881894      }
    882895      if (eventHandler) {
    883896        if (!eventHandler->event(ClpEventHandler::solution)) {
    884           eventHappened=true; // exit
     897          eventHappened_=true; // exit
    885898        }
    886899      }
     
    921934      if (eventHandler) {
    922935        if (!eventHandler->event(ClpEventHandler::treeStatus)) {
    923           eventHappened=true; // exit
     936          eventHappened_=true; // exit
    924937        }
    925938      }
     
    933946                             *dblParam_[CbcAllowableFractionGap]);
    934947    if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
    935       stoppedOnGap = true ;
     948      stoppedOnGap_ = true ;
    936949    }
    937950
     
    9931006    CbcNodeInfo * nodeInfo = node->nodeInfo() ;
    9941007    newNode = NULL ;
    995     if (!addCuts(node,lastws,numberFixedNow>numberFixedAtRoot))
     1008    if (!addCuts(node,lastws,numberFixedNow_>numberFixedAtRoot_))
    9961009    { int i ;
    9971010      const double * lower = getColLower() ;
     
    10061019        node->nodeInfo()->setNodeNumber(numberNodes2_);
    10071020        tree_->push(node) ;
    1008         if (statistics) {
    1009           if (numberNodes2_==maximumStatistics) {
    1010             maximumStatistics = 2*maximumStatistics;
    1011             CbcStatistics ** temp = new CbcStatistics * [maximumStatistics];
    1012             memset(temp,0,maximumStatistics*sizeof(CbcStatistics *));
    1013             memcpy(temp,statistics,numberNodes2_*sizeof(CbcStatistics *));
    1014             delete [] statistics;
    1015             statistics=temp;
     1021        if (statistics_) {
     1022          if (numberNodes2_==maximumStatistics_) {
     1023            maximumStatistics_ = 2*maximumStatistics_;
     1024            CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     1025            memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     1026            memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     1027            delete [] statistics_;
     1028            statistics_=temp;
    10161029          }
    1017           assert (!statistics[numberNodes2_]);
    1018           statistics[numberNodes2_]=new CbcStatistics(node);
     1030          assert (!statistics_[numberNodes2_]);
     1031          statistics_[numberNodes2_]=new CbcStatistics(node);
    10191032        }
    10201033        numberNodes2_++;
     
    10521065      currentNumberCuts = solver_->getNumRows()-numberRowsAtContinuous_ ;
    10531066      int saveNumber = numberIterations_;
    1054       feasible = solveWithCuts(cuts,maximumCutPasses_,node,
    1055                                numberOldActiveCuts,numberNewCuts,
    1056                                maximumWhich,whichGenerator) ;
    1057       if (statistics) {
     1067      feasible = solveWithCuts(cuts,maximumCutPasses_,node);
     1068      if (statistics_) {
    10581069        assert (numberNodes2_);
    1059         assert (statistics[numberNodes2_-1]);
    1060         assert (statistics[numberNodes2_-1]->node()==numberNodes2_-1);
    1061         statistics[numberNodes2_-1]->endOfBranch(numberIterations_-saveNumber,
     1070        assert (statistics_[numberNodes2_-1]);
     1071        assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     1072        statistics_[numberNodes2_-1]->endOfBranch(numberIterations_-saveNumber,
    10621073                                               feasible ? solver_->getObjValue()
    10631074                                               : COIN_DBL_MAX);
     
    10701081          numberSolutions_ < intParam_[CbcMaxNumSol] &&
    10711082          totalTime < dblParam_[CbcMaximumSeconds] &&
    1072           !stoppedOnGap&&!eventHappened)
     1083          !stoppedOnGap_&&!eventHappened_)
    10731084      {
    10741085/*
     
    11011112          while (anyAction == -1)
    11021113          {
     1114            newNode->setObjectiveValue(direction*solver_->getObjValue()) ;
    11031115            if (numberBeforeTrust_==0 ) {
    11041116              anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ;
    11051117            } else {
    1106               anyAction = newNode->chooseDynamicBranch(this,node,numberPassesLeft) ;
     1118              OsiSolverBranch * branches=NULL;
     1119              anyAction = newNode->chooseDynamicBranch(this,node,branches,numberPassesLeft) ;
    11071120              if (anyAction==-3)
    11081121                anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ; // dynamic did nothing
     
    11121125            numberPassesLeft--;
    11131126            if (numberPassesLeft<=-1) {
    1114               if (!numberLongStrong)
     1127              if (!numberLongStrong_)
    11151128                messageHandler()->message(CBC_WARNING_STRONG,
    11161129                                          messages()) << CoinMessageEol ;
    1117               numberLongStrong++;
     1130              numberLongStrong_++;
    11181131            }
    11191132            if (anyAction == -1)
     
    11431156          { if (resolved)
    11441157            { bool needValidSolution = (newNode->variable() < 0) ;
    1145               takeOffCuts(cuts,whichGenerator,numberOldActiveCuts,
    1146                           numberNewCuts,needValidSolution,NULL) ;
     1158              takeOffCuts(cuts,needValidSolution,NULL) ;
    11471159#             ifdef CHECK_CUT_COUNTS
    11481160              { printf("Number of rows after chooseBranch fix (node)"
    11491161                       "(active only) %d\n",
    1150                         numberRowsAtContinuous_+numberNewCuts+
    1151                         numberOldActiveCuts) ;
     1162                        numberRowsAtContinuous_+numberNewCuts_+
     1163                        numberOldActiveCuts_) ;
    11521164                const CoinWarmStartBasis* debugws =
    11531165                  dynamic_cast<const CoinWarmStartBasis*>
     
    11581170            }
    11591171            newNode->createInfo(this,node,lastws,lowerBefore,upperBefore,
    1160                                 numberOldActiveCuts,numberNewCuts) ;
     1172                                numberOldActiveCuts_,numberNewCuts_) ;
    11611173            if (newNode->numberUnsatisfied()) {
    11621174              newNode->initializeInfo() ;
    11631175              newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
    1164                                            whichGenerator) ; } } }
     1176                                           whichGenerator_) ; } } }
    11651177        else
    11661178        { anyAction = -2 ; }
     
    12121224        if (eventHandler) {
    12131225          if (!eventHandler->event(ClpEventHandler::node)) {
    1214             eventHappened=true; // exit
     1226            eventHappened_=true; // exit
    12151227          }
    12161228        }
    12171229        assert (!newNode || newNode->objectiveValue() <= getCutoff()) ;
    1218         if (statistics) {
     1230        if (statistics_) {
    12191231          assert (numberNodes2_);
    1220           assert (statistics[numberNodes2_-1]);
    1221           assert (statistics[numberNodes2_-1]->node()==numberNodes2_-1);
     1232          assert (statistics_[numberNodes2_-1]);
     1233          assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
    12221234          if (newNode)
    1223             statistics[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied());
     1235            statistics_[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied());
    12241236          else
    1225             statistics[numberNodes2_-1]->sayInfeasible();
     1237            statistics_[numberNodes2_-1]->sayInfeasible();
    12261238        }
    12271239        if (newNode)
     
    12681280            newNode->setGuessedObjectiveValue(estValue) ;
    12691281            tree_->push(newNode) ;
    1270             if (statistics) {
    1271               if (numberNodes2_==maximumStatistics) {
    1272                 maximumStatistics = 2*maximumStatistics;
    1273                 CbcStatistics ** temp = new CbcStatistics * [maximumStatistics];
    1274                 memset(temp,0,maximumStatistics*sizeof(CbcStatistics *));
    1275                 memcpy(temp,statistics,numberNodes2_*sizeof(CbcStatistics *));
    1276                 delete [] statistics;
    1277                 statistics=temp;
     1282            if (statistics_) {
     1283              if (numberNodes2_==maximumStatistics_) {
     1284                maximumStatistics_ = 2*maximumStatistics_;
     1285                CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     1286                memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     1287                memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     1288                delete [] statistics_;
     1289                statistics_=temp;
    12781290              }
    1279               assert (!statistics[numberNodes2_]);
    1280               statistics[numberNodes2_]=new CbcStatistics(newNode);
     1291              assert (!statistics_[numberNodes2_]);
     1292              statistics_[numberNodes2_]=new CbcStatistics(newNode);
    12811293            }
    12821294            numberNodes2_++;
     
    13161328        delete nextRowCut_;
    13171329        // We need to get rid of node if is has already been popped from tree
    1318         if (!nodeOnTree&&!stoppedOnGap&&node!=rootNode)
     1330        if (!nodeOnTree&&!stoppedOnGap_&&node!=rootNode)
    13191331          delete node;
    1320         if (stoppedOnGap)
     1332        if (stoppedOnGap_)
    13211333        { messageHandler()->message(CBC_GAP,messages())
    13221334            << bestObjective_-bestPossibleObjective_
     
    13371349          status_ = 1 ; }
    13381350        else
    1339         if (eventHappened)
     1351        if (eventHappened_)
    13401352        { handler_->message(CBC_EVENT,messages_) << CoinMessageEol ;
    13411353        secondaryStatus_ = 5;
     
    13881400      << CoinMessageEol ;
    13891401  }
    1390   if (statistics) {
     1402  if (statistics_) {
    13911403    // report in some way
    13921404    int * lookup = new int[numberObjects_];
     
    14191431      printf("  node parent depth column   value                    obj      inf\n");
    14201432      for ( i=0;i<numberNodes2_;i++) {
    1421         statistics[i]->print(lookup);
     1433        statistics_[i]->print(lookup);
    14221434      }
    14231435    }
     
    14261438      int k;
    14271439      for (k=numberNodes2_-1;k>=0;k--) {
    1428         if (statistics[k]->endingObjective()!=COIN_DBL_MAX&&
    1429             !statistics[k]->endingInfeasibility())
     1440        if (statistics_[k]->endingObjective()!=COIN_DBL_MAX&&
     1441            !statistics_[k]->endingInfeasibility())
    14301442          break;
    14311443      }
    14321444      if (k>=0) {
    1433         int depth=statistics[k]->depth();
     1445        int depth=statistics_[k]->depth();
    14341446        int * which = new int[depth+1];
    14351447        for (i=depth;i>=0;i--) {
    14361448          which[i]=k;
    1437           k=statistics[k]->parentNode();
     1449          k=statistics_[k]->parentNode();
    14381450        }
    14391451        printf("  node parent depth column   value                    obj      inf\n");
    14401452        for (i=0;i<=depth;i++) {
    1441           statistics[which[i]]->print(lookup);
     1453          statistics_[which[i]]->print(lookup);
    14421454        }
    14431455        delete [] which;
     
    14641476    double averageValue=0.0;
    14651477    for ( i=0;i<numberNodes2_;i++) {
    1466       int depth =  statistics[i]->depth();
    1467       int way =  statistics[i]->way();
    1468       double value = statistics[i]->value();
    1469       double startingObjective =  statistics[i]->startingObjective();
    1470       int startingInfeasibility = statistics[i]->startingInfeasibility();
    1471       double endingObjective = statistics[i]->endingObjective();
    1472       int endingInfeasibility = statistics[i]->endingInfeasibility();
     1478      int depth =  statistics_[i]->depth();
     1479      int way =  statistics_[i]->way();
     1480      double value = statistics_[i]->value();
     1481      double startingObjective =  statistics_[i]->startingObjective();
     1482      int startingInfeasibility = statistics_[i]->startingInfeasibility();
     1483      double endingObjective = statistics_[i]->endingObjective();
     1484      int endingInfeasibility = statistics_[i]->endingInfeasibility();
    14731485      maxDepth = CoinMax(depth,maxDepth);
    14741486      // Only for completed
    1475       averageNumberIterations1 += statistics[i]->numberIterations();
     1487      averageNumberIterations1 += statistics_[i]->numberIterations();
    14761488      averageValue += value;
    14771489      if (endingObjective!=COIN_DBL_MAX&&!endingInfeasibility) {
     
    15481560           averageInfUp,averageObjUp);
    15491561    for ( i=0;i<numberNodes2_;i++)
    1550       delete statistics[i];
    1551     delete [] statistics;
     1562      delete statistics_[i];
     1563    delete [] statistics_;
     1564    statistics_=NULL;
    15521565    delete [] lookup;
    15531566  }
     
    15831596*/
    15841597  delete lastws ;
    1585   delete [] whichGenerator ;
     1598  delete [] whichGenerator_ ;
     1599  whichGenerator_=NULL;
    15861600  delete [] lowerBefore ;
    15871601  delete [] upperBefore ;
     
    15971611*/
    15981612  globalCuts_= OsiCuts() ;
     1613  if (strategy_&&strategy_->preProcessState()>0) {
     1614    // undo preprocessing
     1615    CglPreProcess * process = strategy_->process();
     1616    assert (process);
     1617    int n = originalSolver->getNumCols();
     1618    if (bestSolution_) {
     1619      delete [] bestSolution_;
     1620      bestSolution_ = new double [n];
     1621      process->postProcess(*solver_);
     1622    }
     1623    strategy_->deletePreProcess();
     1624    // Solution now back in originalSolver
     1625    delete solver_;
     1626    solver_=originalSolver;
     1627    if (bestSolution_)
     1628      memcpy(bestSolution_,solver_->getColSolution(),n*sizeof(double));
     1629  }
    15991630  return ; }
    1600 
     1631#else
     1632void CbcModel::branchAndBound(int doStatistics)
     1633
     1634{
     1635/*
     1636  Capture a time stamp before we start.
     1637*/
     1638  dblParam_[CbcStartSeconds] = CoinCpuTime();
     1639  // original solver (only set if pre-processing)
     1640  OsiSolverInterface * originalSolver=NULL;
     1641  // Set up strategies
     1642  if (strategy_) {
     1643    // May do preprocessing
     1644    originalSolver = solver_;
     1645    strategy_->setupOther(*this);
     1646    if (strategy_->preProcessState()) {
     1647      // pre-processing done
     1648      if (strategy_->preProcessState()<0) {
     1649        // infeasible
     1650        handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;
     1651        status_ = 0 ;
     1652        secondaryStatus_ = 1;
     1653        originalContinuousObjective_ = COIN_DBL_MAX;
     1654        return ;
     1655      }
     1656    } else {
     1657      //no preprocessing
     1658      originalSolver=NULL;
     1659    }
     1660    strategy_->setupCutGenerators(*this);
     1661    strategy_->setupHeuristics(*this);
     1662    // Set strategy print level to models
     1663    strategy_->setupPrinting(*this,handler_->logLevel());
     1664  }
     1665  eventHappened_=false;
     1666  ClpEventHandler * eventHandler=NULL;
     1667#ifdef COIN_USE_CLP
     1668 {
     1669   OsiClpSolverInterface * clpSolver
     1670     = dynamic_cast<OsiClpSolverInterface *> (solver_);
     1671   if (clpSolver) {
     1672     ClpSimplex * clpSimplex = clpSolver->getModelPtr();
     1673     eventHandler = clpSimplex->eventHandler();
     1674   }
     1675 }
     1676#endif
     1677  if (!nodeCompare_)
     1678    nodeCompare_=new CbcCompareDefault();;
     1679  if (!problemFeasibility_)
     1680    problemFeasibility_=new CbcFeasibilityBase();
     1681# ifdef CBC_DEBUG
     1682  std::string problemName ;
     1683  solver_->getStrParam(OsiProbName,problemName) ;
     1684  printf("Problem name - %s\n",problemName.c_str()) ;
     1685  solver_->setHintParam(OsiDoReducePrint,false,OsiHintDo,0) ;
     1686# endif
     1687/*
     1688  Assume we're done, and see if we're proven wrong.
     1689*/
     1690  status_ = 0 ;
     1691  secondaryStatus_ = 0;
     1692  phase_=0;
     1693/*
     1694  Scan the variables, noting the integer variables. Create an
     1695  CbcSimpleInteger object for each integer variable.
     1696*/
     1697  findIntegers(false) ;
     1698  // If dynamic pseudo costs then do
     1699  if (numberBeforeTrust_)
     1700    convertToDynamic();
     1701  // Set up char array to say if integer
     1702  delete [] integerInfo_;
     1703  {
     1704    int n = solver_->getNumCols();
     1705    integerInfo_ = new char [n];
     1706    for (int i=0;i<n;i++) {
     1707      if (solver_->isInteger(i))
     1708        integerInfo_[i]=1;
     1709      else
     1710        integerInfo_[i]=0;
     1711    }
     1712  }
     1713   
     1714/*
     1715  Ensure that objects on the lists of CbcObjects, heuristics, and cut
     1716  generators attached to this model all refer to this model.
     1717*/
     1718  synchronizeModel() ;
     1719  // Set so we can tell we are in initial phase in resolve
     1720  continuousObjective_ = -COIN_DBL_MAX ;
     1721/*
     1722  Solve the relaxation.
     1723
     1724  Apparently there are circumstances where this will be non-trivial --- i.e.,
     1725  we've done something since initialSolve that's trashed the solution to the
     1726  continuous relaxation.
     1727*/
     1728  bool feasible = resolve() ;
     1729  if (problemFeasibility_->feasible(this,0)<0) {
     1730    feasible=false; // pretend infeasible
     1731  }
     1732/*
     1733  If the linear relaxation of the root is infeasible, bail out now. Otherwise,
     1734  continue with processing the root node.
     1735*/
     1736  if (!feasible)
     1737  { handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;
     1738    status_ = 0 ;
     1739    secondaryStatus_ = 1;
     1740    originalContinuousObjective_ = COIN_DBL_MAX;
     1741    return ; }
     1742  // Save objective (just so user can access it)
     1743  originalContinuousObjective_ = solver_->getObjValue();
     1744  bestPossibleObjective_=originalContinuousObjective_;
     1745  sumChangeObjective1_=0.0;
     1746  sumChangeObjective2_=0.0;
     1747/*
     1748  OsiRowCutDebugger knows an optimal answer for a subset of MIP problems.
     1749  Assuming it recognises the problem, when called upon it will check a cut to
     1750  see if it cuts off the optimal answer.
     1751*/
     1752  // If debugger exists set specialOptions_ bit
     1753  if (solver_->getRowCutDebuggerAlways())
     1754    specialOptions_ |= 1;
     1755
     1756# ifdef CBC_DEBUG
     1757  if ((specialOptions_&1)==0)
     1758    solver_->activateRowCutDebugger(problemName.c_str()) ;
     1759  if (solver_->getRowCutDebuggerAlways())
     1760    specialOptions_ |= 1;
     1761# endif
     1762
     1763/*
     1764  Begin setup to process a feasible root node.
     1765*/
     1766  bestObjective_ = CoinMin(bestObjective_,1.0e50) ;
     1767  numberSolutions_ = 0 ;
     1768  stateOfSearch_=0;
     1769  numberHeuristicSolutions_ = 0 ;
     1770  // Everything is minimization
     1771  {
     1772    // needed to sync cutoffs
     1773    double value ;
     1774    solver_->getDblParam(OsiDualObjectiveLimit,value) ;
     1775    dblParam_[CbcCurrentCutoff]= value * solver_->getObjSense();
     1776  }
     1777  double cutoff=getCutoff() ;
     1778  double direction = solver_->getObjSense() ;
     1779  dblParam_[CbcOptimizationDirection]=direction;
     1780  if (cutoff < 1.0e20&&direction<0.0)
     1781    messageHandler()->message(CBC_CUTOFF_WARNING1,
     1782                                    messages())
     1783                                      << cutoff << -cutoff << CoinMessageEol ;
     1784  if (cutoff > bestObjective_)
     1785    cutoff = bestObjective_ ;
     1786  setCutoff(cutoff) ;
     1787/*
     1788  We probably already have a current solution, but just in case ...
     1789*/
     1790  int numberColumns = getNumCols() ;
     1791  if (!currentSolution_)
     1792    currentSolution_ = new double[numberColumns] ;
     1793  testSolution_ = currentSolution_;
     1794  /* Tell solver we are in Branch and Cut
     1795     Could use last parameter for subtle differences */
     1796  solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
     1797/*
     1798  Create a copy of the solver, thus capturing the original (root node)
     1799  constraint system (aka the continuous system).
     1800*/
     1801  continuousSolver_ = solver_->clone() ;
     1802#ifdef COIN_USE_CLP
     1803  OsiClpSolverInterface * clpSolver
     1804    = dynamic_cast<OsiClpSolverInterface *> (solver_);
     1805  if (clpSolver) {
     1806    ClpSimplex * clpSimplex = clpSolver->getModelPtr();
     1807    // take off names
     1808    clpSimplex->dropNames();
     1809  }
     1810#endif
     1811
     1812  numberRowsAtContinuous_ = getNumRows() ;
     1813/*
     1814  Check the objective to see if we can deduce a nontrivial increment. If
     1815  it's better than the current value for CbcCutoffIncrement, it'll be
     1816  installed.
     1817*/
     1818  analyzeObjective() ;
     1819/*
     1820  Set up for cut generation. addedCuts_ holds the cuts which are relevant for
     1821  the active subproblem. whichGenerator will be used to record the generator
     1822  that produced a given cut.
     1823*/
     1824  maximumWhich_ = 1000 ;
     1825  delete [] whichGenerator_;
     1826  whichGenerator_ = new int[maximumWhich_] ;
     1827  memset(whichGenerator_,0,maximumWhich_*sizeof(int));
     1828  maximumNumberCuts_ = 0 ;
     1829  currentNumberCuts_ = 0 ;
     1830  delete [] addedCuts_ ;
     1831  addedCuts_ = NULL ;
     1832/*
     1833  Set up an empty heap and associated data structures to hold the live set
     1834  (problems which require further exploration).
     1835*/
     1836  tree_->setComparison(*nodeCompare_) ;
     1837/*
     1838  Used to record the path from a node to the root of the search tree, so that
     1839  we can then traverse from the root to the node when restoring a subproblem.
     1840*/
     1841  maximumDepth_ = 10 ;
     1842  delete [] walkback_ ;
     1843  walkback_ = new CbcNodeInfo * [maximumDepth_] ;
     1844/*
     1845  Used to generate bound edits for CbcPartialNodeInfo.
     1846*/
     1847  double * lowerBefore = new double [numberColumns] ;
     1848  double * upperBefore = new double [numberColumns] ;
     1849/*
     1850 
     1851  Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
     1852  lifting. It will iterate a generate/reoptimise loop (including reduced cost
     1853  fixing) until no cuts are generated, the change in objective falls off,  or
     1854  the limit on the number of rounds of cut generation is exceeded.
     1855
     1856  At the end of all this, any cuts will be recorded in cuts and also
     1857  installed in the solver's constraint system. We'll have reoptimised, and
     1858  removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
     1859  adjusted accordingly).
     1860
     1861  Tell cut generators they can be a bit more aggressive at root node
     1862
     1863  TODO: Why don't we make a copy of the solution after solveWithCuts?
     1864  TODO: If numberUnsatisfied == 0, don't we have a solution?
     1865*/
     1866  phase_=1;
     1867  int iCutGenerator;
     1868  for (iCutGenerator = 0;iCutGenerator<numberCutGenerators_;iCutGenerator++) {
     1869    CglCutGenerator * generator = generator_[iCutGenerator]->generator();
     1870    generator->setAggressiveness(generator->getAggressiveness()+100);
     1871  }
     1872  OsiCuts cuts ;
     1873  int anyAction = -1 ;
     1874  numberOldActiveCuts_ = 0 ;
     1875  numberNewCuts_ = 0 ;
     1876  // Array to mark solution
     1877  delete [] usedInSolution_;
     1878  usedInSolution_ = new int[numberColumns];
     1879  CoinZeroN(usedInSolution_,numberColumns);
     1880/*
     1881  For printing totals and for CbcNode (numberNodes_)
     1882*/
     1883  numberIterations_ = 0 ;
     1884  numberNodes_ = 0 ;
     1885  numberNodes2_ = 0 ;
     1886  maximumStatistics_=0;
     1887  statistics_ = NULL;
     1888  // Do on switch
     1889  if (doStatistics) {
     1890    maximumStatistics_=10000;
     1891    statistics_ = new CbcStatistics * [maximumStatistics_];
     1892    memset(statistics_,0,maximumStatistics_*sizeof(CbcStatistics *));
     1893  }
     1894
     1895  { int iObject ;
     1896    int preferredWay ;
     1897    int numberUnsatisfied = 0 ;
     1898    memcpy(currentSolution_,solver_->getColSolution(),
     1899           numberColumns*sizeof(double)) ;
     1900
     1901    for (iObject = 0 ; iObject < numberObjects_ ; iObject++)
     1902    { double infeasibility =
     1903          object_[iObject]->infeasibility(preferredWay) ;
     1904      if (infeasibility ) numberUnsatisfied++ ; }
     1905    if (numberUnsatisfied) {
     1906      feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,NULL);
     1907    }
     1908  }
     1909  // make cut generators less aggressive
     1910  for (iCutGenerator = 0;iCutGenerator<numberCutGenerators_;iCutGenerator++) {
     1911    CglCutGenerator * generator = generator_[iCutGenerator]->generator();
     1912    generator->setAggressiveness(generator->getAggressiveness()-100);
     1913  }
     1914  currentNumberCuts_ = numberNewCuts_ ;
     1915/*
     1916  We've taken the continuous relaxation as far as we can. Time to branch.
     1917  The first order of business is to actually create a node. chooseBranch
     1918  currently uses strong branching to evaluate branch object candidates,
     1919  unless forced back to simple branching. If chooseBranch concludes that a
     1920  branching candidate is monotone (anyAction == -1) or infeasible (anyAction
     1921  == -2) when forced to integer values, it returns here immediately.
     1922
     1923  Monotone variables trigger a call to resolve(). If the problem remains
     1924  feasible, try again to choose a branching variable. At the end of the loop,
     1925  resolved == true indicates that some variables were fixed.
     1926
     1927  Loss of feasibility will result in the deletion of newNode.
     1928*/
     1929
     1930  bool resolved = false ;
     1931  CbcNode *newNode = NULL ;
     1932  numberFixedAtRoot_=0;
     1933  numberFixedNow_=0;
     1934  if (feasible)
     1935  { newNode = new CbcNode ;
     1936    newNode->setObjectiveValue(direction*solver_->getObjValue()) ;
     1937    anyAction = -1 ;
     1938    // To make depth available we may need a fake node
     1939    CbcNode fakeNode;
     1940    if (!currentNode_) {
     1941      // Not true if sub trees assert (!numberNodes_);
     1942      currentNode_=&fakeNode;
     1943    }
     1944    phase_=3;
     1945    // only allow 1000 passes
     1946    int numberPassesLeft=1000;
     1947    // This is first crude step
     1948    if (numberAnalyzeIterations_) {
     1949      delete [] analyzeResults_;
     1950      analyzeResults_ = new double [4*numberIntegers_];
     1951      numberFixedAtRoot_=newNode->analyze(this,analyzeResults_);
     1952      if (numberFixedAtRoot_>0) {
     1953        printf("%d fixed by analysis\n",numberFixedAtRoot_);
     1954        setPointers(solver_);
     1955        numberFixedNow_ = numberFixedAtRoot_;
     1956      } else if (numberFixedAtRoot_<0) {
     1957        printf("analysis found to be infeasible\n");
     1958        anyAction=-2;
     1959        delete newNode ;
     1960        newNode = NULL ;
     1961        feasible = false ;
     1962      }
     1963    }
     1964    while (anyAction == -1)
     1965    {
     1966      newNode->setObjectiveValue(direction*solver_->getObjValue()) ;
     1967      if (numberBeforeTrust_==0 ) {
     1968        anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ;
     1969      } else {
     1970        OsiSolverBranch * branches=NULL;
     1971        anyAction = newNode->chooseDynamicBranch(this,NULL,branches,numberPassesLeft) ;
     1972        if (anyAction==-3)
     1973          anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ; // dynamic did nothing
     1974      }
     1975      numberPassesLeft--;
     1976      if (anyAction == -1)
     1977      { feasible = resolve() ;
     1978      if (problemFeasibility_->feasible(this,0)<0) {
     1979        feasible=false; // pretend infeasible
     1980      }
     1981      //int nfix=
     1982      reducedCostFix() ;
     1983      //if (nfix)
     1984      //printf("%d fixed after resolve root\n",nfix);
     1985        resolved = true ;
     1986#       ifdef CBC_DEBUG
     1987        printf("Resolve (root) as something fixed, Obj value %g %d rows\n",
     1988                  solver_->getObjValue(),
     1989                  solver_->getNumRows()) ;
     1990#       endif
     1991        if (!feasible) anyAction = -2 ; }
     1992      if (anyAction == -2||newNode->objectiveValue() >= cutoff)
     1993      { delete newNode ;
     1994        newNode = NULL ;
     1995        feasible = false ; } } }
     1996/*
     1997  At this point, the root subproblem is infeasible or fathomed by bound
     1998  (newNode == NULL), or we're live with an objective value that satisfies the
     1999  current objective cutoff.
     2000*/
     2001  assert (!newNode || newNode->objectiveValue() <= cutoff) ;
     2002  // Save address of root node as we don't want to delete it
     2003  //CbcNode * rootNode = newNode;
     2004/*
     2005  The common case is that the lp relaxation is feasible but doesn't satisfy
     2006  integrality (i.e., newNode->variable() >= 0, indicating we've been able to
     2007  select a branching variable). Remove any cuts that have gone slack due to
     2008  forcing monotone variables. Then tack on an CbcFullNodeInfo object and full
     2009  basis (via createInfo()) and stash the new cuts in the nodeInfo (via
     2010  addCuts()). If, by some miracle, we have an integral solution at the root
     2011  (newNode->variable() < 0), takeOffCuts() will ensure that the solver holds
     2012  a valid solution for use by setBestSolution().
     2013*/
     2014  if (feasible && newNode->variable() >= 0)
     2015  { if (resolved)
     2016    { bool needValidSolution = (newNode->variable() < 0) ;
     2017      takeOffCuts(cuts,needValidSolution,NULL) ;
     2018#     ifdef CHECK_CUT_COUNTS
     2019      { printf("Number of rows after chooseBranch fix (root)"
     2020               "(active only) %d\n",
     2021                numberRowsAtContinuous_+numberNewCuts_+numberOldActiveCuts_) ;
     2022        const CoinWarmStartBasis* debugws =
     2023          dynamic_cast <const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
     2024        debugws->print() ;
     2025        delete debugws ; }
     2026#     endif
     2027    }
     2028    newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
     2029    newNode->nodeInfo()->addCuts(cuts,
     2030                                 newNode->numberBranches(),whichGenerator_) ;
     2031  }
     2032/*
     2033  Continuous data to be used later
     2034*/
     2035  continuousObjective_ = solver_->getObjValue()*solver_->getObjSense();
     2036  continuousInfeasibilities_ = 0 ;
     2037  if (newNode)
     2038  { continuousObjective_ = newNode->objectiveValue() ;
     2039    delete [] continuousSolution_;
     2040    continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
     2041                                             numberColumns);
     2042    continuousInfeasibilities_ = newNode->numberUnsatisfied() ; }
     2043/*
     2044  Bound may have changed so reset in objects
     2045*/
     2046  { int i ;
     2047    for (i = 0;i < numberObjects_;i++)
     2048      object_[i]->resetBounds() ; }
     2049  stoppedOnGap_ = false ;
     2050/*
     2051  Feasible? Then we should have either a live node prepped for future
     2052  expansion (indicated by variable() >= 0), or (miracle of miracles) an
     2053  integral solution at the root node.
     2054
     2055  initializeInfo sets the reference counts in the nodeInfo object.  Since
     2056  this node is still live, push it onto the heap that holds the live set.
     2057*/
     2058  double bestValue = 0.0 ;
     2059  if (newNode) {
     2060    bestValue = newNode->objectiveValue();
     2061    if (newNode->variable() >= 0) {
     2062      newNode->initializeInfo() ;
     2063      tree_->push(newNode) ;
     2064      if (statistics_) {
     2065        if (numberNodes2_==maximumStatistics_) {
     2066          maximumStatistics_ = 2*maximumStatistics_;
     2067          CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     2068          memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     2069          memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     2070          delete [] statistics_;
     2071          statistics_=temp;
     2072        }
     2073        assert (!statistics_[numberNodes2_]);
     2074        statistics_[numberNodes2_]=new CbcStatistics(newNode);
     2075      }
     2076      numberNodes2_++;
     2077#     ifdef CHECK_NODE
     2078      printf("Node %x on tree\n",newNode) ;
     2079#     endif
     2080    } else {
     2081      // continuous is integer
     2082      double objectiveValue = newNode->objectiveValue();
     2083      setBestSolution(CBC_SOLUTION,objectiveValue,
     2084                      solver_->getColSolution()) ;
     2085      delete newNode ;
     2086      newNode = NULL ;
     2087    }
     2088  }
     2089
     2090  if (printFrequency_ <= 0) {
     2091    printFrequency_ = 1000 ;
     2092    if (getNumCols() > 2000)
     2093      printFrequency_ = 100 ;
     2094  }
     2095  /*
     2096    It is possible that strong branching fixes one variable and then the code goes round
     2097    again and again.  This can take too long.  So we need to warn user - just once.
     2098  */
     2099  numberLongStrong_=0;
     2100/*
     2101  At last, the actual branch-and-cut search loop, which will iterate until
     2102  the live set is empty or we hit some limit (integrality gap, time, node
     2103  count, etc.). The overall flow is to rebuild a subproblem, reoptimise using
     2104  solveWithCuts(), choose a branching pattern with chooseBranch(), and finally
     2105  add the node to the live set.
     2106
     2107  The first action is to winnow the live set to remove nodes which are worse
     2108  than the current objective cutoff.
     2109*/
     2110  while (!tree_->empty()) {
     2111    if (cutoff > getCutoff()) {
     2112      double newCutoff = getCutoff();
     2113      if (analyzeResults_) {
     2114        // see if we could fix any (more)
     2115        int n=0;
     2116        double * newLower = analyzeResults_;
     2117        double * objLower = newLower+numberIntegers_;
     2118        double * newUpper = objLower+numberIntegers_;
     2119        double * objUpper = newUpper+numberIntegers_;
     2120        for (int i=0;i<numberIntegers_;i++) {
     2121          if (objLower[i]>newCutoff) {
     2122            n++;
     2123            if (objUpper[i]>newCutoff) {
     2124              newCutoff = -COIN_DBL_MAX;
     2125              break;
     2126            }
     2127          } else if (objUpper[i]>newCutoff) {
     2128            n++;
     2129          }
     2130        }
     2131        if (newCutoff==-COIN_DBL_MAX) {
     2132          printf("Root analysis says finished\n");
     2133        } else if (n>numberFixedNow_) {
     2134          printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
     2135          numberFixedNow_=n;
     2136        }
     2137      }
     2138      if (eventHandler) {
     2139        if (!eventHandler->event(ClpEventHandler::solution)) {
     2140          eventHappened_=true; // exit
     2141        }
     2142      }
     2143      // Do from deepest
     2144      tree_->cleanTree(this, newCutoff,bestPossibleObjective_) ;
     2145      nodeCompare_->newSolution(this) ;
     2146      nodeCompare_->newSolution(this,continuousObjective_,
     2147                                continuousInfeasibilities_) ;
     2148      tree_->setComparison(*nodeCompare_) ;
     2149      if (tree_->empty())
     2150        break; // finished
     2151    }
     2152    cutoff = getCutoff() ;
     2153    /*
     2154      Periodic activities: Opportunities to
     2155      + tweak the nodeCompare criteria,
     2156      + check if we've closed the integrality gap enough to quit,
     2157      + print a summary line to let the user know we're working
     2158    */
     2159    if ((numberNodes_%1000) == 0) {
     2160      bool redoTree=nodeCompare_->every1000Nodes(this, numberNodes_) ;
     2161      // redo tree if wanted
     2162      if (redoTree)
     2163        tree_->setComparison(*nodeCompare_) ;
     2164    }
     2165    if ((numberNodes_%printFrequency_) == 0) {
     2166      int j ;
     2167      int nNodes = tree_->size() ;
     2168      bestPossibleObjective_ = 1.0e100 ;
     2169      for (j = 0;j < nNodes;j++) {
     2170        CbcNode * node = tree_->nodePointer(j) ;
     2171        if (node&&node->objectiveValue() < bestPossibleObjective_)
     2172          bestPossibleObjective_ = node->objectiveValue() ;
     2173      }
     2174      messageHandler()->message(CBC_STATUS,messages())
     2175        << numberNodes_<< nNodes<< bestObjective_<< bestPossibleObjective_
     2176        << CoinMessageEol ;
     2177      if (eventHandler) {
     2178        if (!eventHandler->event(ClpEventHandler::treeStatus)) {
     2179          eventHappened_=true; // exit
     2180        }
     2181      }
     2182    }
     2183    // If no solution but many nodes - signal change in strategy
     2184    if (numberNodes_>2*numberObjects_+1000&&stateOfSearch_!=2)
     2185      stateOfSearch_=3;
     2186    // See if can stop on gap
     2187    double testGap = CoinMax(dblParam_[CbcAllowableGap],
     2188                             CoinMax(fabs(bestObjective_),fabs(bestPossibleObjective_))
     2189                             *dblParam_[CbcAllowableFractionGap]);
     2190    if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
     2191      stoppedOnGap_ = true ;
     2192    }
     2193
     2194#   ifdef CHECK_NODE_FULL
     2195    verifyTreeNodes(tree_,*this) ;
     2196#   endif
     2197#   ifdef CHECK_CUT_COUNTS
     2198    verifyCutCounts(tree_,*this) ;
     2199#   endif
     2200   
     2201    /*
     2202      Now we come to the meat of the loop. To create the active subproblem, we'll
     2203      pop the most promising node in the live set, rebuild the subproblem it
     2204      represents, and then execute the current arm of the branch to create the
     2205      active subproblem.
     2206    */
     2207    CbcNode *node = tree_->bestNode(cutoff) ;
     2208    // Possible one on tree worse than cutoff
     2209    if (!node)
     2210      continue;
     2211    // Solve node
     2212    int status;
     2213    int numberNewNodes;
     2214    CbcNode ** newNodes = solveOneNode(-1,node,numberNewNodes,status);
     2215    // put nodes back on tree
     2216    for (int iPush = 0; iPush<numberNewNodes;iPush++) {
     2217      tree_->push(newNodes[iPush]) ;
     2218    }     
     2219    delete [] newNodes;
     2220    if (status==2) {
     2221      /*
     2222        The next block of code is executed if we've
     2223        aborted because we hit one of the limits. Clean up by deleting the live set
     2224        and break out of the node processing loop.
     2225      */
     2226      tree_->cleanTree(this,-COIN_DBL_MAX,bestPossibleObjective_) ;
     2227      delete nextRowCut_;
     2228      // We need to get rid of node if is has already been popped from tree
     2229      //if (!nodeOnTree&&!stoppedOnGap_&&node!=rootNode)
     2230      //delete node;
     2231      double totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
     2232      if (stoppedOnGap_) {
     2233        messageHandler()->message(CBC_GAP,messages())
     2234          << bestObjective_-bestPossibleObjective_
     2235          << dblParam_[CbcAllowableGap]
     2236          << dblParam_[CbcAllowableFractionGap]*100.0
     2237          << CoinMessageEol ;
     2238        secondaryStatus_ = 2;
     2239        status_ = 0 ;
     2240      } else if (isNodeLimitReached()) {
     2241        handler_->message(CBC_MAXNODES,messages_) << CoinMessageEol ;
     2242        secondaryStatus_ = 3;
     2243        status_ = 1 ;
     2244      } else if (totalTime >= dblParam_[CbcMaximumSeconds]) {
     2245        handler_->message(CBC_MAXTIME,messages_) << CoinMessageEol ;
     2246        secondaryStatus_ = 4;
     2247        status_ = 1 ;
     2248      } else if (eventHappened_) {
     2249        handler_->message(CBC_EVENT,messages_) << CoinMessageEol ;
     2250        secondaryStatus_ = 5;
     2251        status_ = 5 ;
     2252      } else {
     2253        handler_->message(CBC_MAXSOLS,messages_) << CoinMessageEol ;
     2254        secondaryStatus_ = 6;
     2255        status_ = 1 ;
     2256      }
     2257      break ;
     2258    } else {
     2259      /*
     2260        Delete cuts to get back to the original system.
     2261       
     2262        I'm thinking this is redundant --- the call to addCuts that conditions entry
     2263        to this code block also performs this action.
     2264      */
     2265      int numberToDelete = getNumRows()-numberRowsAtContinuous_ ;
     2266      if (numberToDelete) {
     2267        int * delRows = new int[numberToDelete] ;
     2268        int i ;
     2269        for (i = 0 ; i < numberToDelete ; i++)
     2270          delRows[i] = i+numberRowsAtContinuous_ ;
     2271        solver_->deleteRows(numberToDelete,delRows) ;
     2272        delete [] delRows ;
     2273      }
     2274    }
     2275  }
     2276  /*
     2277    That's it, we've exhausted the search tree, or broken out of the loop because
     2278    we hit some limit on evaluation.
     2279   
     2280    We may have got an intelligent tree so give it one more chance
     2281  */
     2282  // Tell solver we are not in Branch and Cut
     2283  solver_->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo,NULL) ;
     2284  tree_->endSearch();
     2285  //  If we did any sub trees - did we give up on any?
     2286  if ( numberStoppedSubTrees_)
     2287    status_=1;
     2288  if (!status_) {
     2289    bestPossibleObjective_=bestObjective_;
     2290    handler_->message(CBC_END_GOOD,messages_)
     2291      << bestObjective_ << numberIterations_ << numberNodes_
     2292      << CoinMessageEol ;
     2293  } else {
     2294    handler_->message(CBC_END,messages_)
     2295      << bestObjective_ <<bestPossibleObjective_
     2296      << numberIterations_ << numberNodes_
     2297      << CoinMessageEol ;
     2298  }
     2299  if (statistics_) {
     2300    // report in some way
     2301    int * lookup = new int[numberObjects_];
     2302    int i;
     2303    for (i=0;i<numberObjects_;i++)
     2304      lookup[i]=-1;
     2305    bool goodIds=true;
     2306    for (i=0;i<numberObjects_;i++) {
     2307      int id = object_[i]->id();
     2308      int iColumn = object_[i]->columnNumber();
     2309      if (iColumn<0)
     2310        iColumn = id+numberColumns;
     2311      if(id>=0&&id<numberObjects_) {
     2312        if (lookup[id]==-1) {
     2313          lookup[id]=iColumn;
     2314        } else {
     2315          goodIds=false;
     2316          break;
     2317        }
     2318      } else {
     2319        goodIds=false;
     2320        break;
     2321      }
     2322    }
     2323    if (!goodIds) {
     2324      delete [] lookup;
     2325      lookup=NULL;
     2326    }
     2327    if (doStatistics==3) {
     2328      printf("  node parent depth column   value                    obj      inf\n");
     2329      for ( i=0;i<numberNodes2_;i++) {
     2330        statistics_[i]->print(lookup);
     2331      }
     2332    }
     2333    if (doStatistics>1) {
     2334      // Find last solution
     2335      int k;
     2336      for (k=numberNodes2_-1;k>=0;k--) {
     2337        if (statistics_[k]->endingObjective()!=COIN_DBL_MAX&&
     2338            !statistics_[k]->endingInfeasibility())
     2339          break;
     2340      }
     2341      if (k>=0) {
     2342        int depth=statistics_[k]->depth();
     2343        int * which = new int[depth+1];
     2344        for (i=depth;i>=0;i--) {
     2345          which[i]=k;
     2346          k=statistics_[k]->parentNode();
     2347        }
     2348        printf("  node parent depth column   value                    obj      inf\n");
     2349        for (i=0;i<=depth;i++) {
     2350          statistics_[which[i]]->print(lookup);
     2351        }
     2352        delete [] which;
     2353      }
     2354    }
     2355    // now summary
     2356    int maxDepth=0;
     2357    double averageSolutionDepth=0.0;
     2358    int numberSolutions=0;
     2359    double averageCutoffDepth=0.0;
     2360    double averageSolvedDepth=0.0;
     2361    int numberCutoff=0;
     2362    int numberDown=0;
     2363    int numberFirstDown=0;
     2364    double averageInfDown=0.0;
     2365    double averageObjDown=0.0;
     2366    int numberCutoffDown=0;
     2367    int numberUp=0;
     2368    int numberFirstUp=0;
     2369    double averageInfUp=0.0;
     2370    double averageObjUp=0.0;
     2371    int numberCutoffUp=0;
     2372    double averageNumberIterations1=0.0;
     2373    double averageValue=0.0;
     2374    for ( i=0;i<numberNodes2_;i++) {
     2375      int depth =  statistics_[i]->depth();
     2376      int way =  statistics_[i]->way();
     2377      double value = statistics_[i]->value();
     2378      double startingObjective =  statistics_[i]->startingObjective();
     2379      int startingInfeasibility = statistics_[i]->startingInfeasibility();
     2380      double endingObjective = statistics_[i]->endingObjective();
     2381      int endingInfeasibility = statistics_[i]->endingInfeasibility();
     2382      maxDepth = CoinMax(depth,maxDepth);
     2383      // Only for completed
     2384      averageNumberIterations1 += statistics_[i]->numberIterations();
     2385      averageValue += value;
     2386      if (endingObjective!=COIN_DBL_MAX&&!endingInfeasibility) {
     2387        numberSolutions++;
     2388        averageSolutionDepth += depth;
     2389      }
     2390      if (endingObjective==COIN_DBL_MAX) {
     2391        numberCutoff++;
     2392        averageCutoffDepth += depth;
     2393        if (way<0) {
     2394          numberDown++;
     2395          numberCutoffDown++;
     2396          if (way==-1)
     2397            numberFirstDown++;
     2398        } else {
     2399          numberUp++;
     2400          numberCutoffUp++;
     2401          if (way==1)
     2402            numberFirstUp++;
     2403        }
     2404      } else {
     2405        averageSolvedDepth += depth;
     2406        if (way<0) {
     2407          numberDown++;
     2408          averageInfDown += startingInfeasibility-endingInfeasibility;
     2409          averageObjDown += endingObjective-startingObjective;
     2410          if (way==-1)
     2411            numberFirstDown++;
     2412        } else {
     2413          numberUp++;
     2414          averageInfUp += startingInfeasibility-endingInfeasibility;
     2415          averageObjUp += endingObjective-startingObjective;
     2416          if (way==1)
     2417            numberFirstUp++;
     2418        }
     2419      }
     2420    }
     2421    // Now print
     2422    if (numberSolutions)
     2423      averageSolutionDepth /= (double) numberSolutions;
     2424    int numberSolved = numberNodes2_-numberCutoff;
     2425    double averageNumberIterations2=numberIterations_-averageNumberIterations1;
     2426    if(numberCutoff) {
     2427      averageCutoffDepth /= (double) numberCutoff;
     2428      averageNumberIterations2 /= (double) numberCutoff;
     2429    }
     2430    if (numberNodes2_)
     2431      averageValue /= (double) numberNodes2_;
     2432    if (numberSolved) {
     2433      averageNumberIterations1 /= (double) numberSolved;
     2434      averageSolvedDepth /= (double) numberSolved;
     2435    }
     2436    printf("%d solution(s) were found (by branching) at an average depth of %g\n",
     2437           numberSolutions,averageSolutionDepth);
     2438    printf("average value of variable being branched on was %g\n",
     2439           averageValue);
     2440    printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n",
     2441           numberCutoff,averageCutoffDepth,averageNumberIterations2);
     2442    printf("%d nodes were solved at an average depth of %g with iteration count of %g\n",
     2443           numberSolved,averageSolvedDepth,averageNumberIterations1);
     2444    if (numberDown) {
     2445      averageInfDown /= (double) numberDown;
     2446      averageObjDown /= (double) numberDown;
     2447    }
     2448    printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
     2449           numberDown,numberFirstDown,numberDown-numberFirstDown,numberCutoffDown,
     2450           averageInfDown,averageObjDown);
     2451    if (numberUp) {
     2452      averageInfUp /= (double) numberUp;
     2453      averageObjUp /= (double) numberUp;
     2454    }
     2455    printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
     2456           numberUp,numberFirstUp,numberUp-numberFirstUp,numberCutoffUp,
     2457           averageInfUp,averageObjUp);
     2458    for ( i=0;i<numberNodes2_;i++)
     2459      delete statistics_[i];
     2460    delete [] statistics_;
     2461    statistics_=NULL;
     2462    delete [] lookup;
     2463  }
     2464/*
     2465  If we think we have a solution, restore and confirm it with a call to
     2466  setBestSolution().  We need to reset the cutoff value so as not to fathom
     2467  the solution on bounds.  Note that calling setBestSolution( ..., true)
     2468  leaves the continuousSolver_ bounds vectors fixed at the solution value.
     2469
     2470  Running resolve() here is a failsafe --- setBestSolution has already
     2471  reoptimised using the continuousSolver_. If for some reason we fail to
     2472  prove optimality, run the problem again after instructing the solver to
     2473  tell us more.
     2474
     2475  If all looks good, replace solver_ with continuousSolver_, so that the
     2476  outside world will be able to obtain information about the solution using
     2477  public methods.
     2478*/
     2479  if (bestSolution_) {
     2480    setCutoff(1.0e50) ; // As best solution should be worse than cutoff
     2481    phase_=5;
     2482    setBestSolution(CBC_SOLUTION,bestObjective_,bestSolution_,true) ;
     2483    continuousSolver_->resolve() ;
     2484    if (!continuousSolver_->isProvenOptimal()) {
     2485      continuousSolver_->messageHandler()->setLogLevel(2) ;
     2486      continuousSolver_->initialSolve() ;
     2487    }
     2488    delete solver_ ;
     2489    solver_ = continuousSolver_ ;
     2490    setPointers(solver_);
     2491    continuousSolver_ = NULL ;
     2492  }
     2493  /*
     2494    Clean up dangling objects. continuousSolver_ may already be toast.
     2495  */
     2496  delete [] whichGenerator_ ;
     2497  whichGenerator_=NULL;
     2498  delete [] lowerBefore ;
     2499  delete [] upperBefore ;
     2500  delete [] walkback_ ;
     2501  walkback_ = NULL ;
     2502  delete [] addedCuts_ ;
     2503  addedCuts_ = NULL ;
     2504  if (continuousSolver_) {
     2505    delete continuousSolver_ ;
     2506    continuousSolver_ = NULL ;
     2507  }
     2508  /*
     2509    Destroy global cuts by replacing with an empty OsiCuts object.
     2510  */
     2511  globalCuts_= OsiCuts() ;
     2512  if (strategy_&&strategy_->preProcessState()>0) {
     2513    // undo preprocessing
     2514    CglPreProcess * process = strategy_->process();
     2515    assert (process);
     2516    int n = originalSolver->getNumCols();
     2517    if (bestSolution_) {
     2518      delete [] bestSolution_;
     2519      bestSolution_ = new double [n];
     2520      process->postProcess(*solver_);
     2521    }
     2522    strategy_->deletePreProcess();
     2523    // Solution now back in originalSolver
     2524    delete solver_;
     2525    solver_=originalSolver;
     2526    if (bestSolution_)
     2527      memcpy(bestSolution_,solver_->getColSolution(),n*sizeof(double));
     2528  }
     2529  return ;
     2530}
     2531/* Input one node output N nodes to put on tree and optional solution update
     2532   This should be able to operate in parallel so is given a solver and is const(ish)
     2533   However we will need to keep an array of solver_ and bases and more
     2534   status is 0 for normal, 1 if solution, 2 if should stop
     2535   Calling code should always push nodes back on tree
     2536 */
     2537CbcNode **
     2538CbcModel::solveOneNode(int whichSolver,CbcNode * node,
     2539                    int & numberNodesOutput, int & status)
     2540{
     2541  numberNodesOutput=0;
     2542  status=0;
     2543  // Maximum number of new nodes will be known
     2544  // For normal case can be 2 (old + new)
     2545  int maximumNewNodes=2+(1<<sizeMiniTree_);
     2546  CbcNode ** newNodes = new CbcNode * [maximumNewNodes];
     2547 
     2548  currentNode_=node; // so can be accessed elsewhere
     2549#ifdef CBC_DEBUG
     2550  printf("%d unsat, way %d, obj %g est %g\n",
     2551         node->numberUnsatisfied(),node->way(),node->objectiveValue(),
     2552         node->guessedObjectiveValue());
     2553#endif
     2554  // Save clone in branching decision
     2555  if(branchingMethod_)
     2556    branchingMethod_->saveBranchingObject(node->modifiableBranchingObject());
     2557  // Say not on optimal path
     2558  bool onOptimalPath=false;
     2559#   ifdef CHECK_NODE
     2560  /*
     2561    WARNING: The use of integerVariable_[*] here will break as soon as the
     2562    branching object is something other than an integer variable.
     2563    This needs some thought.
     2564  */
     2565  printf("Node %x popped from tree - %d left, %d count\n",node,
     2566         node->nodeInfo()->numberBranchesLeft(),
     2567         node->nodeInfo()->numberPointingToThis()) ;
     2568  printf("\tdepth = %d, z =  %g, unsat = %d, var = %d.\n",
     2569         node->depth(),node->objectiveValue(),
     2570         node->numberUnsatisfied(),
     2571         integerVariable_[node->variable()]) ;
     2572#   endif
     2573 
     2574  /*
     2575    Rebuild the subproblem for this node:        Call addCuts() to adjust the model
     2576    to recreate the subproblem for this node (set proper variable bounds, add
     2577    cuts, create a basis).  This may result in the problem being fathomed by
     2578    bound or infeasibility. Returns 1 if node is fathomed.
     2579    Execute the current arm of the branch: If the problem survives, save the
     2580    resulting variable bounds and call branch() to modify variable bounds
     2581    according to the current arm of the branching object. If we're processing
     2582    the final arm of the branching object, flag the node for removal from the
     2583    live set.
     2584  */
     2585  CbcNodeInfo * nodeInfo = node->nodeInfo() ;
     2586  // empty basis
     2587  CoinWarmStartBasis * lastws = new CoinWarmStartBasis();
     2588  int numberColumns = getNumCols() ;
     2589  double * lowerBefore = new double[numberColumns];
     2590  double * upperBefore = new double[numberColumns];
     2591  if (!addCuts(node,lastws,numberFixedNow_>numberFixedAtRoot_)) {
     2592    int i ;
     2593    const double * lower = getColLower() ;
     2594    const double * upper = getColUpper() ;
     2595    for (i = 0 ; i < numberColumns ; i++) {
     2596      lowerBefore[i]= lower[i] ;
     2597      upperBefore[i]= upper[i] ;
     2598    }
     2599    bool deleteNode ;
     2600    if (node->branch()) {
     2601      // set nodenumber correctly
     2602      node->nodeInfo()->setNodeNumber(numberNodes2_);
     2603      if (statistics_) {
     2604        if (numberNodes2_==maximumStatistics_) {
     2605          maximumStatistics_ = 2*maximumStatistics_;
     2606          CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     2607          memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     2608          memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     2609          delete [] statistics_;
     2610          statistics_=temp;
     2611        }
     2612        assert (!statistics_[numberNodes2_]);
     2613        statistics_[numberNodes2_]=new CbcStatistics(node);
     2614      }
     2615      numberNodes2_++;
     2616      newNodes[numberNodesOutput++]=node;
     2617      deleteNode = false ;
     2618#       ifdef CHECK_NODE
     2619      printf("Node %x pushed back on tree - %d left, %d count\n",node,
     2620             nodeInfo->numberBranchesLeft(),
     2621             nodeInfo->numberPointingToThis()) ;
     2622#       endif
     2623    } else {
     2624      deleteNode = true ;
     2625    }
     2626   
     2627    if ((specialOptions_&1)!=0) {
     2628      /*
     2629        This doesn't work as intended --- getRowCutDebugger will return null
     2630        unless the current feasible solution region includes the optimal solution
     2631        that RowCutDebugger knows. There's no way to tell inactive from off the
     2632        optimal path.
     2633      */
     2634      const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
     2635      if (debugger) {
     2636        onOptimalPath=true;
     2637        printf("On optimal path\n") ;
     2638      }
     2639    }
     2640    /*
     2641      Reoptimize, possibly generating cuts and/or using heuristics to find
     2642      solutions.  Cut reference counts are unaffected unless we lose feasibility,
     2643      in which case solveWithCuts() will make the adjustment.
     2644    */
     2645    phase_=2;
     2646    OsiCuts cuts = OsiCuts() ;
     2647    int saveNumber = numberIterations_;
     2648    bool feasible = solveWithCuts(cuts,maximumCutPasses_,node);
     2649    if (statistics_) {
     2650      assert (numberNodes2_);
     2651      assert (statistics_[numberNodes2_-1]);
     2652      assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     2653      statistics_[numberNodes2_-1]->endOfBranch(numberIterations_-saveNumber,
     2654                                               feasible ? solver_->getObjValue()
     2655                                               : COIN_DBL_MAX);
     2656    }
     2657    /*
     2658      Check for abort on limits: node count, solution count, time, integrality gap.
     2659    */
     2660    double totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
     2661    if (numberNodes_ < intParam_[CbcMaxNumNode] &&
     2662        numberSolutions_ < intParam_[CbcMaxNumSol] &&
     2663        totalTime < dblParam_[CbcMaximumSeconds] &&
     2664        !stoppedOnGap_&&!eventHappened_) {
     2665      /*
     2666        Are we still feasible? If so, create a node and do the work to attach a
     2667        branching object, reoptimising as needed if chooseBranch() identifies
     2668        monotone objects.
     2669       
     2670        Finally, attach a partial nodeInfo object and store away any cuts that we
     2671        created back in solveWithCuts. addCuts() will also deal with the cut
     2672        reference counts.
     2673      */
     2674      if (onOptimalPath)
     2675        assert (feasible);
     2676      bool checkingNode=false;
     2677      int anyAction;
     2678      double direction =  dblParam_[CbcOptimizationDirection];
     2679      bool resolved = false;
     2680      CbcNode * newNode=NULL;
     2681      if (feasible) {
     2682        newNode = new CbcNode ;
     2683        newNode->setObjectiveValue(direction*solver_->getObjValue()) ;
     2684        anyAction =-1 ;
     2685        resolved = false ;
     2686        if (newNode->objectiveValue() >= getCutoff())
     2687          anyAction=-2;
     2688        // only allow twenty passes
     2689        int numberPassesLeft=20;
     2690        checkingNode=true;
     2691        OsiSolverBranch * branches=NULL;
     2692        while (anyAction == -1) {
     2693          newNode->setObjectiveValue(direction*solver_->getObjValue()) ;
     2694          if (numberBeforeTrust_==0 ) {
     2695            anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ;
     2696          } else {
     2697            anyAction = newNode->chooseDynamicBranch(this,node,branches,numberPassesLeft) ;
     2698            if (anyAction==-3)
     2699              anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ; // dynamic did nothing
     2700          }
     2701          if (onOptimalPath)
     2702            assert (anyAction!=-2); // can be useful but gives false positives on strong
     2703          numberPassesLeft--;
     2704          if (numberPassesLeft<=-1) {
     2705            if (!numberLongStrong_)
     2706              messageHandler()->message(CBC_WARNING_STRONG,
     2707                                        messages()) << CoinMessageEol ;
     2708            numberLongStrong_++;
     2709          }
     2710          if (anyAction == -1) {
     2711            // can do quick optimality check
     2712            int easy=2;
     2713            solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
     2714            feasible = resolve() ;
     2715            solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
     2716            resolved = true ;
     2717            if (problemFeasibility_->feasible(this,0)<0) {
     2718              feasible=false; // pretend infeasible
     2719            }
     2720            if (feasible) {
     2721              newNode->setObjectiveValue(direction*solver_->getObjValue()) ;
     2722              //int nfix=
     2723              reducedCostFix() ;
     2724              //if (nfix)
     2725              //printf("%d fixed after resolve\n",nfix);
     2726              if (newNode->objectiveValue() >= getCutoff())
     2727                anyAction=-2;
     2728            } else {
     2729              anyAction = -2 ;
     2730            }
     2731          }
     2732        }
     2733        if (anyAction >= 0) {
     2734          if (resolved) {
     2735            bool needValidSolution = (newNode->variable() < 0) ;
     2736            takeOffCuts(cuts,needValidSolution,NULL) ;
     2737#             ifdef CHECK_CUT_COUNTS
     2738            { printf("Number of rows after chooseBranch fix (node)"
     2739                     "(active only) %d\n",
     2740                     numberRowsAtContinuous_+numberNewCuts_+
     2741                     numberOldActiveCuts_) ;
     2742            const CoinWarmStartBasis* debugws =
     2743              dynamic_cast<const CoinWarmStartBasis*>
     2744              (solver_->getWarmStart()) ;
     2745            debugws->print() ;
     2746            delete debugws ; }
     2747#             endif
     2748          }
     2749          if (anyAction==0||!newNode->numberUnsatisfied()) {
     2750            delete [] branches;
     2751            newNode->createInfo(this,node,lastws,lowerBefore,upperBefore,
     2752                                numberOldActiveCuts_,numberNewCuts_) ;
     2753            if (newNode->numberUnsatisfied()) {
     2754              newNode->initializeInfo() ;
     2755              newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
     2756                                           whichGenerator_) ;
     2757            }
     2758          } else {
     2759            // mini tree
     2760            int numberBranches=anyAction;
     2761            int numberResults=1<<numberBranches;
     2762            OsiSolverResult * result = new OsiSolverResult[numberResults];
     2763            double * lowerBefore2 = new double[numberColumns];
     2764            double * upperBefore2 = new double[numberColumns];
     2765            int i ;
     2766            const double * lower = solver_->getColLower() ;
     2767            const double * upper = solver_->getColUpper() ;
     2768            for (i = 0 ; i < numberColumns ; i++) {
     2769              lowerBefore2[i]= lower[i] ;
     2770              upperBefore2[i]= upper[i] ;
     2771            }
     2772            int numberIterations;
     2773            int numberSolves;
     2774            int numberGood = solver_->solveBranches(numberBranches,branches,result,
     2775                                                    numberSolves,numberIterations);
     2776            numberIterations_ += numberIterations;
     2777            // Add in solves needed to get to leaves
     2778            numberNodes_ += (numberSolves-numberGood);
     2779            int numberCutsAdd=-1; // We will be taking off one anyway
     2780            int saveMini = sizeMiniTree_;
     2781            sizeMiniTree_=0;
     2782            int saveNumber = numberNodesOutput;
     2783            for (int iResult=0;iResult<numberGood;iResult++) {
     2784              if (result[iResult].objectiveValue()<1.0e50) {
     2785                // put in correct bounds etc
     2786                solver_->setColLower(lowerBefore2);
     2787                solver_->setColUpper(upperBefore2);
     2788                result[iResult].restoreResult(*solver_);
     2789                numberNodes_++;
     2790#if 0
     2791                // need to tell solver that current factorization is no good
     2792                // should be better way
     2793#ifdef COIN_USE_CLP
     2794                OsiClpSolverInterface * clpSolver
     2795                  = dynamic_cast<OsiClpSolverInterface *> (solver_);
     2796                if (clpSolver)
     2797                  clpSolver->getModelPtr()->setWhatsChanged(clpSolver->getModelPtr()->whatsChanged()&(~512));
     2798#endif
     2799                solver_->resolve();
     2800                assert (!solver_->getIterationCount());
     2801                printf("res obj %g was %g\n",solver_->getObjValue(),
     2802                       result[iResult].objectiveValue());
     2803#endif
     2804                bool checkingNode=false;
     2805                bool feasible = true;
     2806                int anyAction;
     2807                CbcNode * newNode2= new CbcNode ;
     2808                newNode2->setObjectiveValue(result[iResult].objectiveValue()) ;
     2809                anyAction =-1 ;
     2810                // only allow twenty passes
     2811                int numberPassesLeft=20;
     2812                checkingNode=true;
     2813                OsiSolverBranch * branches=NULL;
     2814                while (anyAction == -1) {
     2815                  if (numberBeforeTrust_==0 ) {
     2816                    anyAction = newNode2->chooseBranch(this,node,numberPassesLeft) ;
     2817                  } else {
     2818                    anyAction = newNode2->chooseDynamicBranch(this,node,branches,numberPassesLeft) ;
     2819                    if (anyAction==-3)
     2820                      anyAction = newNode2->chooseBranch(this,node,numberPassesLeft) ; // dynamic did nothing
     2821                  }
     2822                  numberPassesLeft--;
     2823                  if (anyAction == -1) {
     2824                    // can do quick optimality check
     2825                    int easy=2;
     2826                    solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
     2827                    feasible = resolve() ;
     2828                    solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
     2829                    if (problemFeasibility_->feasible(this,0)<0) {
     2830                      feasible=false; // pretend infeasible
     2831                    }
     2832                    if (feasible) {
     2833                      newNode2->setObjectiveValue(direction*solver_->getObjValue()) ;
     2834                      reducedCostFix() ;
     2835                      if (newNode2->objectiveValue() >= getCutoff())
     2836                        anyAction=-2;
     2837                    } else {
     2838                      anyAction = -2 ;
     2839                    }
     2840                  }
     2841                }
     2842                // May have slipped through i.e. anyAction == 0 and objective above cutoff
     2843                if ( anyAction ==0 ) {
     2844                  assert (newNode2);
     2845                  if (newNode2->objectiveValue() >= getCutoff())
     2846                    anyAction = -2; // say bad after all
     2847                }
     2848                if (anyAction >= 0) {
     2849                  if (anyAction==0||!newNode2->numberUnsatisfied()) {
     2850                    newNode2->createInfo(this,node,lastws,lowerBefore,upperBefore,
     2851                                        numberOldActiveCuts_,numberNewCuts_) ;
     2852                    if (newNode2->numberUnsatisfied()) {
     2853                      newNode2->initializeInfo() ;
     2854                      newNode2->nodeInfo()->addCuts(cuts,newNode2->numberBranches(),
     2855                                                   whichGenerator_) ;
     2856                    }
     2857                  }
     2858                }
     2859                /*
     2860                  If we end up infeasible, we can delete the new node immediately. Since this
     2861                  node won't be needing the cuts we collected, decrement the reference counts.
     2862                  If we are feasible, then we'll be placing this node into the live set, so
     2863                  increment the reference count in the current (parent) nodeInfo.
     2864                */
     2865                if (anyAction == -2) {
     2866                  delete newNode2 ;
     2867                  newNode2 = NULL ;
     2868#if 0
     2869                  // say strong doing well
     2870                  if (checkingNode)
     2871                    setSpecialOptions(specialOptions_|8);
     2872#endif
     2873#if 0
     2874                  for (i = 0 ; i < currentNumberCuts_ ; i++) {
     2875                    if (addedCuts_[i]) {
     2876                      if (!addedCuts_[i]->decrement(1)) {
     2877                        delete addedCuts_[i] ;
     2878                        addedCuts_[i]=NULL;
     2879                      }
     2880                    }
     2881                  }
     2882#endif
     2883                } else {
     2884                  nodeInfo->increment() ;
     2885#if 0
     2886                  if ((numberNodes_%20)==0) {
     2887                    // say strong not doing as well
     2888                    setSpecialOptions(specialOptions_&~8);
     2889                  }
     2890#endif
     2891                }
     2892                /*
     2893                  At this point, there are three possibilities:
     2894                  * We have a live node (variable() >= 0) which will require further
     2895                  branching to resolve. Before we push it onto the search tree, try for
     2896                  a heuristic solution.
     2897                  * We have a solution, in which case newNode is non-null but we have no
     2898                  branching variable. Decrement the cut counts and save the solution.
     2899                  * The node was found to be infeasible, in which case it's already been
     2900                  deleted, and newNode is null.
     2901                 
     2902                */
     2903                if (eventHandler()) {
     2904                  if (!eventHandler()->event(ClpEventHandler::node)) {
     2905                    eventHappened_=true; // exit
     2906                  }
     2907                }
     2908                assert (!newNode2 || newNode2->objectiveValue() <= getCutoff()) ;
     2909                if (statistics_) {
     2910                  assert (numberNodes2_);
     2911                  assert (statistics_[numberNodes2_-1]);
     2912                  assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     2913                  if (newNode2)
     2914                    statistics_[numberNodes2_-1]->updateInfeasibility(newNode2->numberUnsatisfied());
     2915                  else
     2916                    statistics_[numberNodes2_-1]->sayInfeasible();
     2917                }
     2918                if (newNode2) {
     2919                  if (newNode2->variable() >= 0) {
     2920                    handler_->message(CBC_BRANCH,messages_)
     2921                      << numberNodes_<< newNode2->objectiveValue()
     2922                      << newNode2->numberUnsatisfied()<< newNode2->depth()
     2923                      << CoinMessageEol ;
     2924                    // Increment cut counts
     2925                    numberCutsAdd += newNode2->numberBranches();
     2926                    double estValue = newNode2->guessedObjectiveValue() ;
     2927                    int found = -1 ;
     2928                    double * newSolution = new double [numberColumns] ;
     2929                    double heurValue = getCutoff() ;
     2930                    int iHeur ;
     2931                    for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) {
     2932                      double saveValue = heurValue ;
     2933                      int ifSol = heuristic_[iHeur]->solution(heurValue,newSolution) ;
     2934                      if (ifSol > 0) {
     2935                        // new solution found
     2936                        found = iHeur ;
     2937                        incrementUsed(newSolution);
     2938                      } else if (ifSol < 0) {   // just returning an estimate
     2939                        estValue = CoinMin(heurValue,estValue) ;
     2940                        heurValue = saveValue ;
     2941                      }
     2942                    }
     2943                    if (found >= 0) {
     2944                      setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
     2945                      lastHeuristic_ = heuristic_[found];
     2946                      status=1;
     2947                    }
     2948                    delete [] newSolution ;
     2949                    newNode2->setGuessedObjectiveValue(estValue) ;
     2950                    newNodes[numberNodesOutput++] = newNode2 ;
     2951                    nodeInfo->increment();
     2952                    if (statistics_) {
     2953                      if (numberNodes2_==maximumStatistics_) {
     2954                        maximumStatistics_ = 2*maximumStatistics_;
     2955                        CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     2956                        memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     2957                        memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     2958                        delete [] statistics_;
     2959                        statistics_=temp;
     2960                      }
     2961                      assert (!statistics_[numberNodes2_]);
     2962                      statistics_[numberNodes2_]=new CbcStatistics(newNode2);
     2963                    }
     2964                    numberNodes2_++;
     2965#           ifdef CHECK_NODE
     2966                    printf("Node %x pushed on tree c\n",newNode2) ;
     2967#           endif
     2968                  } else {
     2969#if 0
     2970                    for (i = 0 ; i < currentNumberCuts_ ; i++) {
     2971                      if (addedCuts_[i]) {
     2972                        if (!addedCuts_[i]->decrement(1)) {
     2973                          delete addedCuts_[i] ;
     2974                          addedCuts_[i]=NULL;
     2975                        }
     2976                      }
     2977                    }
     2978#endif
     2979                    double objectiveValue = newNode2->objectiveValue();
     2980                    setBestSolution(CBC_SOLUTION,objectiveValue,
     2981                                    solver_->getColSolution()) ;
     2982                    lastHeuristic_ = NULL;
     2983                    incrementUsed(solver_->getColSolution());
     2984                    //assert(nodeInfo->numberPointingToThis() <= 2) ;
     2985                    // avoid accidental pruning, if newNode was final branch arm
     2986                    nodeInfo->increment();
     2987                    delete newNode2 ;
     2988                    nodeInfo->decrement() ;
     2989                    status=1;
     2990                  }
     2991                }
     2992              }
     2993            }
     2994            if (numberCutsAdd>0) {
     2995              for (i = 0;i < currentNumberCuts_;i++) {
     2996                if (addedCuts_[i]) {
     2997#               ifdef CHECK_CUT_COUNTS
     2998                  printf("Count on cut %x increased by %d\n",addedCuts_[i],
     2999                         numberCutsAdd) ;
     3000#               endif
     3001                  addedCuts_[i]->increment(numberCutsAdd) ;
     3002                }
     3003              }
     3004            }     
     3005            sizeMiniTree_=saveMini;
     3006            delete [] result;
     3007            delete [] branches;
     3008            delete newNode ;
     3009            newNode = NULL ;
     3010            delete [] lowerBefore2;
     3011            delete [] upperBefore2;
     3012            if (saveNumber < numberNodesOutput)
     3013              anyAction = -4;
     3014            else
     3015              anyAction=-2;
     3016          }
     3017        }
     3018      } else {
     3019        anyAction = -2 ;
     3020      }
     3021#if 0
     3022      if (numberNodesOutput) {
     3023        if (!sizeMiniTree_)
     3024          assert(newNode== newNodes[numberNodesOutput-1]);
     3025        newNode= newNodes[numberNodesOutput-1];
     3026      } else {
     3027        assert (!newNode);
     3028      }
     3029#endif
     3030      // May have slipped through i.e. anyAction == 0 and objective above cutoff
     3031      if ( anyAction >=0 ) {
     3032        assert (newNode);
     3033        if (newNode->objectiveValue() >= getCutoff())
     3034          anyAction = -2; // say bad after all
     3035      }
     3036      /*
     3037        If we end up infeasible, we can delete the new node immediately. Since this
     3038        node won't be needing the cuts we collected, decrement the reference counts.
     3039        If we are feasible, then we'll be placing this node into the live set, so
     3040        increment the reference count in the current (parent) nodeInfo.
     3041      */
     3042      if (anyAction == -2) {
     3043        delete newNode ;
     3044        newNode = NULL ;
     3045        // say strong doing well
     3046        if (checkingNode)
     3047          setSpecialOptions(specialOptions_|8);
     3048        // switch off any hot start
     3049        hotstartStrategy_=0;
     3050        for (i = 0 ; i < currentNumberCuts_ ; i++) {
     3051          if (addedCuts_[i]) {
     3052            if (!addedCuts_[i]->decrement(1)) {
     3053              delete addedCuts_[i] ;
     3054              addedCuts_[i]=NULL;
     3055            }
     3056          }
     3057        }
     3058      } else if (anyAction>=0) {
     3059        nodeInfo->increment() ;
     3060        if ((numberNodes_%20)==0) {
     3061          // say strong not doing as well
     3062          setSpecialOptions(specialOptions_&~8);
     3063        }
     3064      }
     3065      /*
     3066        At this point, there are three possibilities:
     3067        * We have a live node (variable() >= 0) which will require further
     3068        branching to resolve. Before we push it onto the search tree, try for
     3069        a heuristic solution.
     3070        * We have a solution, in which case newNode is non-null but we have no
     3071        branching variable. Decrement the cut counts and save the solution.
     3072        * The node was found to be infeasible, in which case it's already been
     3073        deleted, and newNode is null.
     3074       
     3075      */
     3076      if (eventHandler()) {
     3077        if (!eventHandler()->event(ClpEventHandler::node)) {
     3078          eventHappened_=true; // exit
     3079        }
     3080      }
     3081      assert (!newNode || newNode->objectiveValue() <= getCutoff()) ;
     3082      if (statistics_) {
     3083        assert (numberNodes2_);
     3084        assert (statistics_[numberNodes2_-1]);
     3085        assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     3086        if (newNode)
     3087          statistics_[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied());
     3088        else
     3089          statistics_[numberNodes2_-1]->sayInfeasible();
     3090      }
     3091      if (newNode) {
     3092        if (newNode->variable() >= 0) {
     3093          handler_->message(CBC_BRANCH,messages_)
     3094            << numberNodes_<< newNode->objectiveValue()
     3095            << newNode->numberUnsatisfied()<< newNode->depth()
     3096            << CoinMessageEol ;
     3097          // Increment cut counts (taking off current)
     3098          int numberLeft = newNode->numberBranches() ;
     3099          for (i = 0;i < currentNumberCuts_;i++) {
     3100            if (addedCuts_[i]) {
     3101#               ifdef CHECK_CUT_COUNTS
     3102              printf("Count on cut %x increased by %d\n",addedCuts_[i],
     3103                     numberLeft-1) ;
     3104#               endif
     3105              addedCuts_[i]->increment(numberLeft-1) ;
     3106            }
     3107          }
     3108         
     3109          double estValue = newNode->guessedObjectiveValue() ;
     3110          int found = -1 ;
     3111          double * newSolution = new double [numberColumns] ;
     3112          double heurValue = getCutoff() ;
     3113          int iHeur ;
     3114          for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) {
     3115            double saveValue = heurValue ;
     3116            int ifSol = heuristic_[iHeur]->solution(heurValue,newSolution) ;
     3117            if (ifSol > 0) {
     3118              // new solution found
     3119              found = iHeur ;
     3120              incrementUsed(newSolution);
     3121            } else if (ifSol < 0) {     // just returning an estimate
     3122              estValue = CoinMin(heurValue,estValue) ;
     3123              heurValue = saveValue ;
     3124            }
     3125          }
     3126          if (found >= 0) {
     3127            setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
     3128            lastHeuristic_ = heuristic_[found];
     3129            status=1;
     3130          }
     3131          delete [] newSolution ;
     3132          newNode->setGuessedObjectiveValue(estValue) ;
     3133          newNodes[numberNodesOutput++] = newNode ;
     3134          if (statistics_) {
     3135            if (numberNodes2_==maximumStatistics_) {
     3136              maximumStatistics_ = 2*maximumStatistics_;
     3137              CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     3138              memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     3139              memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     3140              delete [] statistics_;
     3141              statistics_=temp;
     3142            }
     3143            assert (!statistics_[numberNodes2_]);
     3144            statistics_[numberNodes2_]=new CbcStatistics(newNode);
     3145          }
     3146          numberNodes2_++;
     3147#           ifdef CHECK_NODE
     3148          printf("Node %x pushed on tree c\n",newNode) ;
     3149#           endif
     3150        } else {
     3151          for (i = 0 ; i < currentNumberCuts_ ; i++) {
     3152            if (addedCuts_[i]) {
     3153              if (!addedCuts_[i]->decrement(1)) {
     3154                delete addedCuts_[i] ;
     3155                addedCuts_[i]=NULL;
     3156              }
     3157            }
     3158          }
     3159          double objectiveValue = newNode->objectiveValue();
     3160          setBestSolution(CBC_SOLUTION,objectiveValue,
     3161                          solver_->getColSolution()) ;
     3162          lastHeuristic_ = NULL;
     3163          incrementUsed(solver_->getColSolution());
     3164          //assert(nodeInfo->numberPointingToThis() <= 2) ;
     3165          // avoid accidental pruning, if newNode was final branch arm
     3166          nodeInfo->increment();
     3167          delete newNode ;
     3168          nodeInfo->decrement() ;
     3169          status=1;
     3170        }
     3171      }
     3172      /*
     3173        This node has been completely expanded and can be removed from the live
     3174        set.
     3175      */
     3176      if (deleteNode) 
     3177        delete node ;
     3178    } else {
     3179      // max time etc
     3180      status=2;
     3181      if (deleteNode) 
     3182        delete node ;
     3183    }
     3184  } else {
     3185    // node before branching is infeasible (so no nodes output)
     3186    delete node;
     3187  }
     3188  delete lastws;
     3189  delete [] lowerBefore;
     3190  delete [] upperBefore;
     3191  return newNodes;
     3192}
     3193#endif
    16013194
    16023195
     
    16673260  ourSolver_(true),
    16683261  continuousSolver_(NULL),
     3262  referenceSolver_(NULL),
    16693263  defaultHandler_(true),
    16703264  emptyWarmStart_(NULL),
    1671   basis_(NULL),
    16723265  bestObjective_(COIN_DBL_MAX),
    16733266  bestPossibleObjective_(COIN_DBL_MAX),
     
    17303323  maximumCutPassesAtRoot_(20),
    17313324  maximumCutPasses_(10),
     3325  maximumWhich_(1000),
     3326  whichGenerator_(NULL),
     3327  maximumStatistics_(0),
     3328  statistics_(NULL),
     3329  numberFixedAtRoot_(0),
     3330  numberFixedNow_(0),
     3331  stoppedOnGap_(false),
     3332  eventHappened_(false),
     3333  numberLongStrong_(0),
     3334  numberOldActiveCuts_(0),
     3335  numberNewCuts_(0),
     3336  sizeMiniTree_(0),
    17323337  resolveAfterTakeOffCuts_(true)
    17333338{
     
    17753380:
    17763381  continuousSolver_(NULL),
     3382  referenceSolver_(NULL),
    17773383  defaultHandler_(true),
    17783384  emptyWarmStart_(NULL),
    1779   basis_(NULL) ,
    17803385  bestObjective_(COIN_DBL_MAX),
    17813386  bestPossibleObjective_(COIN_DBL_MAX),
     
    18313436  maximumCutPassesAtRoot_(20),
    18323437  maximumCutPasses_(10),
     3438  maximumWhich_(1000),
     3439  whichGenerator_(NULL),
     3440  maximumStatistics_(0),
     3441  statistics_(NULL),
     3442  numberFixedAtRoot_(0),
     3443  numberFixedNow_(0),
     3444  stoppedOnGap_(false),
     3445  eventHappened_(false),
     3446  numberLongStrong_(0),
     3447  numberOldActiveCuts_(0),
     3448  numberNewCuts_(0),
     3449  sizeMiniTree_(0),
    18333450  resolveAfterTakeOffCuts_(true)
    18343451{
     
    18603477  messages_ = CbcMessage();
    18613478  solver_ = rhs.clone();
     3479  referenceSolver_ = rhs.clone();
    18623480  ourSolver_ = true ;
    18633481  cbcColLower_ = NULL;
     
    19073525
    19083526  The integer variable vector is initialized if it's not already present.
     3527  If deleteSolver then current solver deleted (if model owned)
    19093528
    19103529  Assuming ownership matches usage in OsiSolverInterface
     
    19223541*/
    19233542void
    1924 CbcModel::assignSolver(OsiSolverInterface *&solver)
     3543CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver)
    19253544
    19263545{
     
    19293548    solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel()) ;
    19303549
    1931   if (ourSolver_) delete solver_ ;
     3550  if (ourSolver_&&deleteSolver) delete solver_ ;
    19323551  solver_ = solver;
    19333552  solver = NULL ;
     
    19363555  Basis information is solver-specific.
    19373556*/
    1938   if (basis_)
    1939   { delete basis_ ;
    1940     basis_ = 0 ; }
    19413557  if (emptyWarmStart_)
    19423558  { delete emptyWarmStart_  ;
     
    19723588:
    19733589  continuousSolver_(NULL),
     3590  referenceSolver_(NULL),
    19743591  defaultHandler_(rhs.defaultHandler_),
    19753592  emptyWarmStart_(NULL),
    1976   basis_(NULL),
    19773593  bestObjective_(rhs.bestObjective_),
    19783594  bestPossibleObjective_(rhs.bestPossibleObjective_),
     
    20093625  maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_),
    20103626  maximumCutPasses_( rhs.maximumCutPasses_),
     3627  maximumWhich_(rhs.maximumWhich_),
     3628  whichGenerator_(NULL),
     3629  maximumStatistics_(0),
     3630  statistics_(NULL),
     3631  numberFixedAtRoot_(rhs.numberFixedAtRoot_),
     3632  numberFixedNow_(rhs.numberFixedNow_),
     3633  stoppedOnGap_(rhs.stoppedOnGap_),
     3634  eventHappened_(rhs.eventHappened_),
     3635  numberLongStrong_(rhs.numberLongStrong_),
     3636  numberOldActiveCuts_(rhs.numberOldActiveCuts_),
     3637  numberNewCuts_(rhs.numberNewCuts_),
     3638  sizeMiniTree_(rhs.sizeMiniTree_),
    20113639  resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_)
    20123640{
     
    20263654  dblParam_[CbcStartSeconds] = dblParam_[CbcStartSeconds]; // will be overwritten hopefully
    20273655  if (rhs.emptyWarmStart_) emptyWarmStart_ = rhs.emptyWarmStart_->clone() ;
    2028   if (rhs.basis_) basis_ =
    2029     dynamic_cast<CoinWarmStartBasis *>(rhs.basis_->clone()) ;
    20303656  if (defaultHandler_) {
    20313657    handler_ = new CoinMessageHandler();
     
    20703696    object_=NULL;
    20713697  }
     3698  if (rhs.referenceSolver_)
     3699    referenceSolver_ = rhs.referenceSolver_->clone();
     3700  else
     3701    referenceSolver_=NULL;
    20723702  if (!noTree||!rhs.continuousSolver_)
    20733703    solver_ = rhs.solver_->clone();
     
    20813711    originalColumns_=NULL;
    20823712  }
     3713  if (maximumWhich_&&rhs.whichGenerator_)
     3714    whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_,maximumWhich_);
    20833715  nodeCompare_=rhs.nodeCompare_->clone();
    20843716  problemFeasibility_=rhs.problemFeasibility_->clone();
     
    21723804{
    21733805  if (this!=&rhs) {
    2174 
     3806    gutsOfDestructor();
    21753807    if (defaultHandler_)
    21763808    { delete handler_;
     
    21973829    { continuousSolver_ = 0 ; }
    21983830
     3831    if (rhs.referenceSolver_)
     3832    { solver_ = rhs.referenceSolver_->clone() ; }
     3833    else
     3834    { referenceSolver_ = NULL ; }
     3835
    21993836    delete emptyWarmStart_ ;
    22003837    if (rhs.emptyWarmStart_)
     
    22023839    else
    22033840    { emptyWarmStart_ = 0 ; }
    2204     delete basis_ ;
    2205     if (rhs.basis_)
    2206     { basis_ = dynamic_cast<CoinWarmStartBasis *>(rhs.basis_->clone()) ; }
    2207     else
    2208     { basis_ = 0 ; }
    22093841
    22103842    bestObjective_ = rhs.bestObjective_;
     
    22563888    maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_;
    22573889    maximumCutPasses_ = rhs.maximumCutPasses_;
    2258     resolveAfterTakeOffCuts_=rhs.resolveAfterTakeOffCuts_;
    22593890    intParam_[CbcMaxNumNode] = rhs.intParam_[CbcMaxNumNode];
    22603891    intParam_[CbcMaxNumSol] = rhs.intParam_[CbcMaxNumSol];
     
    22803911    delete [] virginGenerator_;
    22813912    delete [] heuristic_;
     3913    maximumWhich_ = rhs.maximumWhich_;
     3914    delete [] whichGenerator_;
     3915    whichGenerator_ = NULL;
     3916    if (maximumWhich_&&rhs.whichGenerator_)
     3917      whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_,maximumWhich_);
     3918    for (i=0;i<maximumStatistics_;i++)
     3919      delete statistics_[i];
     3920    delete [] statistics_;
     3921    maximumStatistics_ = 0;
     3922    statistics_ = NULL;
     3923    numberFixedAtRoot_ = rhs.numberFixedAtRoot_;
     3924    numberFixedNow_ = rhs.numberFixedNow_;
     3925    stoppedOnGap_ = rhs.stoppedOnGap_;
     3926    eventHappened_ = rhs.eventHappened_;
     3927    numberLongStrong_ = rhs.numberLongStrong_;
     3928    numberOldActiveCuts_ = rhs.numberOldActiveCuts_;
     3929    numberNewCuts_ = rhs.numberNewCuts_;
     3930    resolveAfterTakeOffCuts_=rhs.resolveAfterTakeOffCuts_;
     3931    sizeMiniTree_ = rhs.sizeMiniTree_;
    22823932    lastHeuristic_ = NULL;
    22833933    numberCutGenerators_ = rhs.numberCutGenerators_;
     
    23874037  }
    23884038  delete tree_;
     4039  tree_=NULL;
    23894040  if (ourSolver_) delete solver_;
    23904041  gutsOfDestructor();
     
    23944045CbcModel::gutsOfDestructor()
    23954046{
    2396   delete emptyWarmStart_ ;
    2397   emptyWarmStart_ =NULL;
    2398   delete basis_ ;
    2399   basis_ =NULL;
    2400   delete continuousSolver_;
    2401   continuousSolver_=NULL;
    2402   delete [] bestSolution_;
    2403   bestSolution_=NULL;
    2404   delete [] currentSolution_;
    2405   currentSolution_=NULL;
    2406   delete [] integerInfo_;
    2407   integerInfo_=NULL;
    2408   delete [] continuousSolution_;
    2409   continuousSolution_=NULL;
    2410   delete [] usedInSolution_;
    2411   usedInSolution_ = NULL;
    2412   testSolution_=NULL;
    2413   delete [] integerVariable_;
    2414   integerVariable_=NULL;
     4047  delete referenceSolver_;
     4048  referenceSolver_=NULL;
    24154049  int i;
    24164050  for (i=0;i<numberCutGenerators_;i++) {
     
    24264060  delete [] heuristic_;
    24274061  heuristic_=NULL;
    2428   lastHeuristic_ = NULL;
    24294062  delete nodeCompare_;
    24304063  nodeCompare_=NULL;
    24314064  delete problemFeasibility_;
    24324065  problemFeasibility_=NULL;
     4066  delete [] originalColumns_;
     4067  originalColumns_=NULL;
     4068  delete strategy_;
     4069  gutsOfDestructor2();
     4070}
     4071// Clears out enough to reset CbcModel
     4072void
     4073CbcModel::gutsOfDestructor2()
     4074{
     4075  delete [] integerInfo_;
     4076  integerInfo_=NULL;
     4077  delete [] integerVariable_;
     4078  integerVariable_=NULL;
     4079  int i;
     4080  for (i=0;i<numberObjects_;i++)
     4081    delete object_[i];
     4082  delete [] object_;
     4083  object_=NULL;
     4084  numberIntegers_=0;
     4085  numberObjects_=0;
     4086  delete emptyWarmStart_ ;
     4087  emptyWarmStart_ =NULL;
     4088  delete continuousSolver_;
     4089  continuousSolver_=NULL;
     4090  delete [] bestSolution_;
     4091  bestSolution_=NULL;
     4092  delete [] currentSolution_;
     4093  currentSolution_=NULL;
     4094  delete [] continuousSolution_;
     4095  continuousSolution_=NULL;
     4096  delete [] usedInSolution_;
     4097  usedInSolution_ = NULL;
     4098  testSolution_=NULL;
     4099  lastHeuristic_ = NULL;
    24334100  delete [] addedCuts_;
    24344101  addedCuts_=NULL;
     
    24374104  delete [] walkback_;
    24384105  walkback_=NULL;
    2439   for (i=0;i<numberObjects_;i++)
    2440     delete object_[i];
    2441   delete [] object_;
    2442   object_=NULL;
    2443   delete [] originalColumns_;
    2444   originalColumns_=NULL;
    2445   delete strategy_;
     4106  delete [] whichGenerator_;
     4107  whichGenerator_ = NULL;
     4108  for (i=0;i<maximumStatistics_;i++)
     4109    delete statistics_[i];
     4110  delete [] statistics_;
     4111  statistics_=NULL;
     4112  delete [] analyzeResults_;
     4113  analyzeResults_=NULL;
     4114  // Below here is whatever consensus is
     4115  ourSolver_=true;
     4116  bestObjective_=COIN_DBL_MAX;
     4117  bestPossibleObjective_=COIN_DBL_MAX;
     4118  sumChangeObjective1_=0.0;
     4119  sumChangeObjective2_=0.0;
     4120  numberSolutions_=0;
     4121  stateOfSearch_=0;
     4122  hotstartStrategy_=0;
     4123  numberHeuristicSolutions_=0;
     4124  numberNodes_=0;
     4125  numberNodes2_=0;
     4126  numberIterations_=0;
     4127  status_=-1;
     4128  secondaryStatus_=-1;
     4129  maximumNumberCuts_=0;
     4130  phase_=0;
     4131  currentNumberCuts_=0;
     4132  maximumDepth_=0;
     4133  nextRowCut_=NULL;
     4134  currentNode_=NULL;
     4135  // clear out tree
     4136  if (tree_&&tree_->size())
     4137    tree_->cleanTree(this, -1.0e100,bestPossibleObjective_) ;
     4138  subTreeModel_=NULL;
     4139  numberStoppedSubTrees_=0;
     4140  numberInfeasibleNodes_=0;
     4141  numberGlobalViolations_=0;
     4142  continuousObjective_=0.0;
     4143  originalContinuousObjective_=0.0;
     4144  continuousInfeasibilities_=0;
     4145  numberFixedAtRoot_=0;
     4146  numberFixedNow_=0;
     4147  stoppedOnGap_=false;
     4148  eventHappened_=false;
     4149  numberLongStrong_=0;
     4150  numberOldActiveCuts_=0;
     4151  numberNewCuts_=0;
     4152  // Parameters which need to be reset
     4153  dblParam_[CbcCutoffIncrement] = 1e-5;
     4154  dblParam_[CbcCurrentCutoff] = 1.0e100;
     4155  dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
     4156  dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
    24464157}
     4158// Save a copy of the current solver so can be reset to
     4159void
     4160CbcModel::saveReferenceSolver()
     4161{
     4162  delete referenceSolver_;
     4163  referenceSolver_= solver_->clone();
     4164}
     4165
     4166// Uses a copy of reference solver to be current solver
     4167void
     4168CbcModel::resetToReferenceSolver()
     4169{
     4170  delete solver_;
     4171  solver_ = referenceSolver_->clone();
     4172  // clear many things
     4173  gutsOfDestructor2();
     4174  // Reset cutoff
     4175  // Solvers know about direction
     4176  double direction = solver_->getObjSense();
     4177  double value;
     4178  solver_->getDblParam(OsiDualObjectiveLimit,value);
     4179  setCutoff(value*direction);
     4180}
     4181
    24474182// Are there a numerical difficulties?
    24484183bool
     
    27754510    3) Install the tight cuts into the constraint system (applyRowCuts).
    27764511
    2777   TODO: After working through the code in createInfo, I'm more comfortable if
    2778         inactive cuts are retained in lastws. So, instead of cloning
    2779         lastws into basis_ after the compression loop, do it ahead of time
    2780         and then recover lastws from basis_ after the setWarmStart().
    2781         (Minimal code change :-). See CbcNode::createInfo for more.
    2782 */
    2783     if (basis_) delete basis_ ;
    2784     basis_= dynamic_cast<CoinWarmStartBasis *>(lastws->clone()) ;
     4512    Update lastws
     4513*/
    27854514    for (i=0;i<currentNumberCuts;i++) {
    27864515      CoinWarmStartBasis::Status status =
     
    28124541    solver_->applyRowCuts(numberToAdd,addCuts);
    28134542    solver_->setWarmStart(lastws);
    2814 /*
    2815   TODO: Undo the debugging change. Delete lastws and assign basis_.
    2816 */
    2817   delete lastws ;
    2818   lastws = basis_ ;
    2819   basis_ = 0 ;
    28204543
    28214544#if 0
     
    29084631
    29094632// Collect coding to replace whichGenerator
    2910 static int * newWhichGenerator(int numberNow, int numberAfter,
    2911                                int & maximumWhich, int * whichGenerator)
     4633void
     4634CbcModel::resizeWhichGenerator(int numberNow, int numberAfter)
    29124635{
    2913   if (numberAfter > maximumWhich) {
    2914     maximumWhich = CoinMax(maximumWhich*2+100,numberAfter) ;
    2915     int * temp = new int[2*maximumWhich] ;
    2916     memcpy(temp,whichGenerator,numberNow*sizeof(int)) ;
    2917     delete [] whichGenerator ;
    2918     whichGenerator = temp ;
    2919   }
    2920   return whichGenerator;
     4636  if (numberAfter > maximumWhich_) {
     4637    maximumWhich_ = CoinMax(maximumWhich_*2+100,numberAfter) ;
     4638    int * temp = new int[2*maximumWhich_] ;
     4639    memcpy(temp,whichGenerator_,numberNow*sizeof(int)) ;
     4640    delete [] whichGenerator_ ;
     4641    whichGenerator_ = temp ;
     4642    memset(whichGenerator_+numberNow,0,(maximumWhich_-numberNow)*sizeof(int));
     4643  }
    29214644}
    29224645
     
    29344657
    29354658bool
    2936 CbcModel::solveWithCuts (OsiCuts &cuts, int numberTries, CbcNode *node,
    2937                          int &numberOldActiveCuts, int &numberNewCuts,
    2938                          int &maximumWhich, int *&whichGenerator)
     4659CbcModel::solveWithCuts (OsiCuts &cuts, int numberTries, CbcNode *node)
    29394660/*
    29404661  Parameters:
     
    29434664   
    29444665    cuts:       (o) all cuts generated in this round of cut generation
    2945     whichGenerator: (i/o) whichGenerator[i] is loaded with the index of the
    2946                         generator that produced cuts[i]; reallocated as
    2947                         required
    2948     numberOldActiveCuts: (o) the number of active cuts at this node from
    2949                         previous rounds of cut generation
    2950     numberNewCuts: (o) the number of cuts produced in this round of cut
    2951                        generation
    2952     maximumWhich: (i/o) capacity of whichGenerator; may be updated if
    2953                         whichGenerator grows.
    29544666
    29554667    node: (i)     So we can update dynamic pseudo costs
     
    29664678  CoinBigIndex numberElementsAtStart = solver_->getNumElements();
    29674679
    2968   numberOldActiveCuts = numberRowsAtStart-numberRowsAtContinuous_ ;
    2969   numberNewCuts = 0 ;
     4680  numberOldActiveCuts_ = numberRowsAtStart-numberRowsAtContinuous_ ;
     4681  numberNewCuts_ = 0 ;
    29704682
    29714683  bool onOptimalPath = false ;
     
    30414753  if (!numberTries) {
    30424754    cuts=OsiCuts();
    3043     numberNewCuts=0;
     4755    numberNewCuts_=0;
    30444756    return true;
    30454757  }
     
    31114823      int i;
    31124824      // possibly extend whichGenerator
    3113       whichGenerator = newWhichGenerator(numberViolated, numberViolated+numberCuts,
    3114                                          maximumWhich,  whichGenerator);
     4825      resizeWhichGenerator(numberViolated, numberViolated+numberCuts);
    31154826      for ( i = 0 ; i < numberCuts ; i++)
    31164827      { const OsiColCut *thisCut = globalCuts_.colCutPtr(i) ;
     
    31184829          printf("Global cut added - violation %g\n",
    31194830                 thisCut->violated(solution)) ;
    3120           whichGenerator[numberViolated++]=-1;
     4831          whichGenerator_[numberViolated++]=-1;
    31214832          theseCuts.insert(*thisCut) ;
    31224833        }
     
    31244835      numberCuts = globalCuts_.sizeRowCuts() ;
    31254836      // possibly extend whichGenerator
    3126       whichGenerator = newWhichGenerator(numberViolated, numberViolated+numberCuts,
    3127                                          maximumWhich,  whichGenerator);
     4837      resizeWhichGenerator(numberViolated, numberViolated+numberCuts);
    31284838      for ( i = 0;i<numberCuts;i++) {
    31294839        const OsiRowCut * thisCut = globalCuts_.rowCutPtr(i) ;
     
    31314841          //printf("Global cut added - violation %g\n",
    31324842          // thisCut->violated(solution)) ;
    3133           whichGenerator[numberViolated++]=-1;
     4843          whichGenerator_[numberViolated++]=-1;
    31344844          theseCuts.insert(*thisCut) ;
    31354845        }
     
    31724882        printf("applying branch cut, sum is %g, bounds %g %g\n",sum,lb,ub);
    31734883      // possibly extend whichGenerator
    3174       whichGenerator = newWhichGenerator(numberViolated, numberViolated+1,
    3175                                          maximumWhich,  whichGenerator);
     4884      resizeWhichGenerator(numberViolated, numberViolated+1);
    31764885      // set whichgenerator (also serves as marker to say don't delete0
    3177       whichGenerator[numberViolated++]=-2;
     4886      whichGenerator_[numberViolated++]=-2;
    31784887    }
    31794888    double * newSolution = new double [numberColumns] ;
     
    32024911              //assert (n);
    32034912              for (int i=0;i<n;i++) {
    3204                 int iColumn = column[i];
    32054913                double value = element[i];
    32064914                assert(fabs(value)>1.0e-12&&fabs(value)<1.0e20);
     
    32694977            numberRowCutsAfter+numberColumnCutsAfter+lastNumberCuts ;
    32704978      // possibly extend whichGenerator
    3271       whichGenerator = newWhichGenerator(numberBefore, numberAfter,
    3272                                          maximumWhich,  whichGenerator);
     4979      resizeWhichGenerator(numberBefore, numberAfter);
    32734980      int j ;
    32744981      if (fullScan) {
     
    32794986     
    32804987      for (j = numberRowCutsBefore;j<numberRowCutsAfter;j++) {
    3281         whichGenerator[numberBefore++] = i ;
     4988        whichGenerator_[numberBefore++] = i ;
    32824989        const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
    32834990        if (thisCut->lb()>thisCut->ub())
     
    32894996      }
    32904997      for (j = numberColumnCutsBefore;j<numberColumnCutsAfter;j++) {
    3291         whichGenerator[numberBefore++] = i ;
     4998        whichGenerator_[numberBefore++] = i ;
    32924999        const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
    32935000        if (thisCut->globallyValid()) {
     
    33285035      int i;
    33295036      // possibly extend whichGenerator
    3330       whichGenerator = newWhichGenerator(numberOld, numberOld+numberCuts,
    3331                                          maximumWhich,  whichGenerator);
     5037      resizeWhichGenerator(numberOld, numberOld+numberCuts);
    33325038      for ( i = 0;i<numberCuts;i++) {
    33335039        const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
     
    33365042            printf("Old cut added - violation %g\n",
    33375043                   thisCut->violated(solution)) ;
    3338           whichGenerator[numberOld++]=-1;
     5044          whichGenerator_[numberOld++]=-1;
    33395045          theseCuts.insert(*thisCut) ;
    33405046        }
     
    34685174    assert(numberRowsNow == numberRowsAtStart+lastNumberCuts) ;
    34695175    int numberToAdd = theseCuts.sizeRowCuts() ;
    3470     numberNewCuts = lastNumberCuts+numberToAdd ;
    3471 /*
    3472   Get a basis by asking the solver for warm start information. Resize it
    3473   (retaining the basis) so it can accommodate the cuts.
    3474 */
    3475     delete basis_ ;
    3476     basis_ = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
    3477     assert(basis_ != NULL); // make sure not volume
    3478     basis_->resize(numberRowsAtStart+numberNewCuts,numberColumns) ;
     5176    numberNewCuts_ = lastNumberCuts+numberToAdd ;
    34795177/*
    34805178  Now actually add the row cuts and reoptimise.
     
    35155213        for (i = 0 ; i < numberToAdd ; i++)
    35165214        { cuts.insert(theseCuts.rowCut(i)) ; }
    3517         for (i = 0 ; i < numberToAdd ; i++)
    3518         { basis_->setArtifStatus(numberRowsNow+i,
     5215        CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
     5216        assert(basis != NULL); // make sure not volume
     5217        //basis->resize(numberRowsAtStart+numberNewCuts_,numberColumns) ;
     5218        for (i = 0 ; i < numberToAdd ; i++)
     5219        { basis->setArtifStatus(numberRowsNow+i,
    35195220                                 CoinWarmStartBasis::basic) ; }
    3520         if (solver_->setWarmStart(basis_) == false)
     5221        if (solver_->setWarmStart(basis) == false)
    35215222        { throw CoinError("Fail setWarmStart() after cut installation.",
    3522                           "solveWithCuts","CbcModel") ; } }
     5223                          "solveWithCuts","CbcModel") ; }
     5224        delete basis;
     5225      }
    35235226      feasible = resolve() ;
    35245227      if ( CoinCpuTime()-dblParam_[CbcStartSeconds] > dblParam_[CbcMaximumSeconds] )
     
    35625265    if (feasible)
    35635266    { int cutIterations = solver_->getIterationCount() ;
    3564       if (numberOldActiveCuts+numberNewCuts) {
     5267      if (numberOldActiveCuts_+numberNewCuts_) {
    35655268        OsiCuts * saveCuts = node ? NULL : &slackCuts;
    3566         takeOffCuts(cuts,whichGenerator,numberOldActiveCuts,
    3567                     numberNewCuts,resolveAfterTakeOffCuts_,saveCuts) ;
     5269        takeOffCuts(cuts,resolveAfterTakeOffCuts_,saveCuts) ;
    35685270        if (solver_->isDualObjectiveLimitReached()&&resolveAfterTakeOffCuts_)
    35695271          { feasible = false ;
     
    35775279      }
    35785280      if (feasible)
    3579         { numberRowsAtStart = numberOldActiveCuts+numberRowsAtContinuous_ ;
    3580         lastNumberCuts = numberNewCuts ;
     5281        { numberRowsAtStart = numberOldActiveCuts_+numberRowsAtContinuous_ ;
     5282        lastNumberCuts = numberNewCuts_ ;
    35815283        if (direction*solver_->getObjValue() < lastObjective+minimumDrop &&
    35825284            currentPassNumber_ >= 3)
     
    36315333      if (nDelete) {
    36325334        solver_->deleteRows(nDelete,added);
    3633         delete basis_ ;
    3634         basis_ = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
    36355335      }
    36365336      delete [] added;
     
    37335433    if (!numberNodes_)
    37345434      handler_->message(CBC_ROOT,messages_)
    3735         <<numberNewCuts
     5435        <<numberNewCuts_
    37365436        <<startObjective<<thisObjective
    37375437        <<currentPassNumber_
     
    37405440    memset(count,0,numberCutGenerators_*sizeof(int)) ;
    37415441    int numberActiveGenerators=0;
    3742     for (i = 0;i<numberNewCuts;i++) {
    3743       int iGenerator = whichGenerator[i];
     5442    for (i = 0;i<numberNewCuts_;i++) {
     5443      int iGenerator = whichGenerator_[i];
    37445444      if (iGenerator>=0&&iGenerator<numberCutGenerators_)
    37455445        count[iGenerator]++ ;
     
    38395539        // Take off cuts
    38405540        cuts = OsiCuts();
    3841         numberNewCuts=0;
     5541        numberNewCuts_=0;
    38425542        if (!willBeCutsInTree) {
    38435543          // update size of problem
     
    38845584    // What if not feasible as cuts may have helped
    38855585    if (feasible) {
    3886       for (i = 0;i<numberNewCuts;i++) {
    3887         int iGenerator = whichGenerator[i];
     5586      for (i = 0;i<numberNewCuts_;i++) {
     5587        int iGenerator = whichGenerator_[i];
    38885588        if (iGenerator>=0)
    38895589          generator_[iGenerator]->incrementNumberCutsActive();
     
    38985598#ifdef CHECK_CUT_COUNTS
    38995599  if (feasible)
    3900   { delete basis_ ;
    3901     basis_ = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
     5600  {
     5601    CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
    39025602    printf("solveWithCuts: Number of rows at end (only active cuts) %d\n",
    3903            numberRowsAtContinuous_+numberNewCuts+numberOldActiveCuts) ;
    3904     basis_->print() ; }
     5603           numberRowsAtContinuous_+numberNewCuts_+numberOldActiveCuts_) ;
     5604    basis->print() ; delete basis;}
    39055605#endif
    39065606#ifdef CBC_DEBUG
     
    39565656
    39575657void
    3958 CbcModel::takeOffCuts (OsiCuts &newCuts, int *whichGenerator,
    3959                        int &numberOldActiveCuts, int &numberNewCuts,
     5658CbcModel::takeOffCuts (OsiCuts &newCuts,
    39605659                       bool allowResolve, OsiCuts * saveCuts)
    39615660
    39625661{ // int resolveIterations = 0 ;
    39635662  int firstOldCut = numberRowsAtContinuous_ ;
    3964   int totalNumberCuts = numberNewCuts+numberOldActiveCuts ;
     5663  int totalNumberCuts = numberNewCuts_+numberOldActiveCuts_ ;
    39655664  int *solverCutIndices = new int[totalNumberCuts] ;
    3966   int *newCutIndices = new int[numberNewCuts] ;
     5665  int *newCutIndices = new int[numberNewCuts_] ;
    39675666  const CoinWarmStartBasis* ws ;
    39685667  CoinWarmStartBasis::Status status ;
     
    39865685*/
    39875686    int oldCutIndex = 0 ;
    3988     for (i = 0 ; i < numberOldActiveCuts ; i++)
     5687    for (i = 0 ; i < numberOldActiveCuts_ ; i++)
    39895688    { status = ws->getArtifStatus(i+firstOldCut) ;
    39905689      while (!addedCuts_[oldCutIndex]) oldCutIndex++ ;
     
    40155714  front.
    40165715*/
    4017     int firstNewCut = firstOldCut+numberOldActiveCuts ;
     5716    int firstNewCut = firstOldCut+numberOldActiveCuts_ ;
    40185717    int k = 0 ;
    4019     for (i = 0 ; i < numberNewCuts ; i++)
     5718    for (i = 0 ; i < numberNewCuts_ ; i++)
    40205719    { status = ws->getArtifStatus(i+firstNewCut) ;
    4021       if (status == CoinWarmStartBasis::basic&&whichGenerator[i]!=-2)
     5720      if (status == CoinWarmStartBasis::basic&&whichGenerator_[i]!=-2)
    40225721      { solverCutIndices[numberNewToDelete+numberOldToDelete] = i+firstNewCut ;
    40235722        newCutIndices[numberNewToDelete++] = i ; }
    40245723      else
    40255724      { // save which generator did it
    4026         whichGenerator[k++] = whichGenerator[i] ; } }
     5725        whichGenerator_[k++] = whichGenerator_[i] ; } }
    40275726    delete ws ;
    40285727    for (i = numberNewToDelete-1 ; i >= 0 ; i--)
     
    40465745    { solver_->deleteRows(numberNewToDelete+numberOldToDelete,
    40475746                          solverCutIndices) ;
    4048       numberNewCuts -= numberNewToDelete ;
    4049       numberOldActiveCuts -= numberOldToDelete ;
     5747      numberNewCuts_ -= numberNewToDelete ;
     5748      numberOldActiveCuts_ -= numberOldToDelete ;
    40505749#     ifdef CBC_DEBUG
    40515750      printf("takeOffCuts: purged %d+%d cuts\n", numberOldToDelete,
     
    40665765        else
    40675766          { printf( "Repeating purging loop. %d iters.\n",
    4068                     solver_->getIterationCount());
     5767                    solver_->getIterationCount()); }
    40695768#       endif
    40705769      }
     
    56997398        delete [] newSolution;
    57007399        // Space for type of cuts
    5701         int maximumWhich=1000;
    5702         int * whichGenerator = new int[maximumWhich];
     7400        maximumWhich_=1000;
     7401        delete [] whichGenerator_ ;
     7402        whichGenerator_ = new int[maximumWhich_];
    57037403        // save number of rows
    57047404        numberRowsAtContinuous_ = getNumRows();
     
    57147414       
    57157415        OsiCuts cuts;
    5716         int numberOldActiveCuts=0;
    5717         int numberNewCuts = 0;
    5718         feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,
    5719                                  NULL,numberOldActiveCuts,numberNewCuts,
    5720                                  maximumWhich, whichGenerator);
    5721         currentNumberCuts_=numberNewCuts;
    5722         delete [] whichGenerator;
     7416        numberOldActiveCuts_=0;
     7417        numberNewCuts_ = 0;
     7418        feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,NULL);
     7419        currentNumberCuts_=numberNewCuts_;
     7420        delete [] whichGenerator_;
     7421        whichGenerator_=NULL;
    57237422        delete [] walkback_;
    57247423        walkback_ = NULL;
     
    62467945  that produced a given cut.
    62477946*/
    6248   int maximumWhich = 1000 ;
    6249   int * whichGenerator = new int[maximumWhich] ;
     7947  maximumWhich_ = 1000 ;
     7948  delete [] whichGenerator_ ;
     7949  whichGenerator_ = new int[maximumWhich_] ;
    62507950  maximumNumberCuts_ = 0 ;
    62517951  currentNumberCuts_ = 0 ;
     
    62607960  At the end of all this, any cuts will be recorded in cuts and also
    62617961  installed in the solver's constraint system. We'll have reoptimised, and
    6262   removed any slack cuts (numberOldActiveCuts and numberNewCuts have been
     7962  removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
    62637963  adjusted accordingly).
    62647964
     
    62727972  }
    62737973  OsiCuts cuts ;
    6274   int numberOldActiveCuts = 0 ;
    6275   int numberNewCuts = 0 ;
     7974  numberOldActiveCuts_ = 0 ;
     7975  numberNewCuts_ = 0 ;
    62767976  { int iObject ;
    62777977    int preferredWay ;
     
    62867986    if (numberUnsatisfied)
    62877987    { feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,
    6288                                NULL,numberOldActiveCuts,numberNewCuts,
    6289                                maximumWhich, whichGenerator) ; } }
     7988                               NULL) ; } }
    62907989/*
    62917990  We've taken the continuous relaxation as far as we can.
     
    63007999  Clean up dangling objects. continuousSolver_ may already be toast.
    63018000*/
    6302   delete [] whichGenerator ;
     8001  delete [] whichGenerator_ ;
     8002  whichGenerator_ = NULL;
    63038003  delete [] walkback_ ;
    63048004  walkback_ = NULL ;
  • trunk/CbcNode.cpp

    r219 r222  
    1313#define CUTS
    1414#include "OsiSolverInterface.hpp"
     15#include "OsiSolverBranch.hpp"
    1516#include "CoinWarmStartBasis.hpp"
    1617#include "CoinTime.hpp"
     
    613614  for (i=0;i<numberCuts_;i++) {
    614615    addCuts[currentNumberCuts+i]= cuts_[i];
    615     if (model->messageHandler()->logLevel()>1) {
     616    if (cuts_[i]&&model->messageHandler()->logLevel()>2) {
    616617      cuts_[i]->print();
    617618    }
     
    865866  double saveObjectiveValue = solver->getObjValue();
    866867  double objectiveValue = solver->getObjSense()*saveObjectiveValue;
     868  assert (objectiveValue_==objectiveValue);
    867869  const double * lower = solver->getColLower();
    868870  const double * upper = solver->getColUpper();
     
    13551357            choice[i].numItersDown = 0;
    13561358          }
    1357           objectiveChange = newObjectiveValue-objectiveValue ;
     1359          objectiveChange = newObjectiveValue-objectiveValue_ ;
    13581360        } else {
    13591361          iStatus = outputStuff[2*i];
     
    13621364          solver->setColSolution(outputSolution[2*i]);
    13631365        }
    1364         objectiveChange = newObjectiveValue  - objectiveValue;
     1366        objectiveChange = newObjectiveValue  - objectiveValue_;
    13651367        if (!iStatus) {
    13661368          choice[i].finishedDown = true ;
     
    14471449            choice[i].numItersDown = 0;
    14481450          }
    1449           objectiveChange = newObjectiveValue-objectiveValue ;
     1451          objectiveChange = newObjectiveValue-objectiveValue_ ;
    14501452        } else {
    14511453          iStatus = outputStuff[2*i+1];
     
    14541456          solver->setColSolution(outputSolution[2*i+1]);
    14551457        }
    1456         objectiveChange = newObjectiveValue  - objectiveValue;
     1458        objectiveChange = newObjectiveValue  - objectiveValue_;
    14571459        if (!iStatus) {
    14581460          choice[i].finishedUp = true ;
     
    16981700                                               changeUp,numberInfeasibilitiesUp,
    16991701                                               changeDown,numberInfeasibilitiesDown,
    1700                                                objectiveValue);
     1702                                               objectiveValue_);
    17011703        // move branching object and make sure it will not be deleted
    17021704        if (whichObject>=0) {
     
    17291731  }
    17301732  // Set guessed solution value
    1731   objectiveValue_ = solver->getObjSense()*saveObjectiveValue;
    17321733  guessedObjectiveValue_ = objectiveValue_+estimatedDegradation;
    17331734/*
     
    17821783*/
    17831784
    1784 int CbcNode::chooseDynamicBranch (CbcModel *model, CbcNode *lastNode,int numberPassesLeft)
     1785int CbcNode::chooseDynamicBranch (CbcModel *model, CbcNode *lastNode,
     1786                                  OsiSolverBranch * & branches,int numberPassesLeft)
    17851787
    17861788{ if (lastNode)
     
    17911793  branch_=NULL;
    17921794  OsiSolverInterface * solver = model->solver();
    1793   objectiveValue_ = solver->getObjSense()*solver->getObjValue();
     1795  //assert(objectiveValue_ == solver->getObjSense()*solver->getObjValue());
    17941796  double cutoff =model->getCutoff();
    17951797  const double * lower = solver->getColLower();
     
    18371839  if (!decision)
    18381840    decision = new CbcBranchDynamicDecision();
     1841  int numberMini=0;
    18391842  int xStrong=0;
    18401843  int xIters=0;
     
    18921895    int * which = objectMark+numberObjects+1;
    18931896    int neededPenalties;
    1894     // We may go round this loop twice (only if we think we have solution)
    1895     for (int iPass=0;iPass<2;iPass++) {
     1897    // We may go round this loop three times (only if we think we have solution)
     1898    for (int iPass=0;iPass<3;iPass++) {
    18961899     
    18971900      // compute current state
     
    20072010        break;
    20082011      } else if (!iPass) {
     2012        // may just need resolve
     2013        solver->resolve();
     2014        memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
     2015        model->reserveCurrentSolution(saveSolution);
     2016        if (!solver->isProvenOptimal()) {
     2017          // infeasible
     2018          anyAction=-2;
     2019          break;
     2020        }
     2021      } else if (iPass==1) {
    20092022        // looks like a solution - get paranoid
    20102023        bool roundAgain=false;
     
    22632276        numberTest = CoinMax(numberTest,5);
    22642277      }
     2278      // See if we want mini tree
     2279      bool wantMiniTree=false;
     2280      if (model->sizeMiniTree()&&depth_>7&&saveStateOfSearch>0)
     2281        wantMiniTree=true;
     2282      numberMini=0;
    22652283      for ( iDo=0;iDo<numberToDo;iDo++) {
    22662284        CbcStrongInfo choice;
     
    24732491            //if (!stateOfSearch)
    24742492            //choice.numIntInfeasDown=99999; // temp fudge
     2493            if (wantMiniTree)
     2494              decision->setBestCriterion(-1.0);
     2495            double bestCriterion = -1.0;
    24752496            int betterWay = decision->betterBranch(choice.possibleBranch,
    24762497                                                   branch_,
     
    24792500                                                   choice.downMovement*changeFactor,
    24802501                                                   choice.numIntInfeasDown );
     2502            if (wantMiniTree) {
     2503              double criterion = decision->getBestCriterion();
     2504              sort[numberMini]=-criterion;
     2505              whichObject[numberMini++]=whichObject[iDo];
     2506              assert (betterWay);
     2507              if (criterion>bestCriterion)
     2508                bestCriterion=criterion;
     2509              else
     2510                betterWay=0;
     2511            }
    24812512            if (iDo>=changeStrategy) {
    24822513              // make less likely
     
    26432674            if (feasible) {
    26442675              anyAction=0;
     2676              numberMini=0;
    26452677              memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
    26462678              model->reserveCurrentSolution(saveSolution);
     
    26822714    }
    26832715  }
    2684   if (model->messageHandler()->logLevel()>1)
     2716  if (model->messageHandler()->logLevel()>2)
    26852717    printf("%d strong, %d iters, %d pen, %d mark, %d fixed, action %d\n",
    26862718         xStrong,xIters,xPen,xMark,numberToFix,anyAction);
     
    26892721  // Set guessed solution value
    26902722  guessedObjectiveValue_ = objectiveValue_+estimatedDegradation;
     2723 
     2724  // Get collection of branches if mini tree wanted
     2725  if (anyAction==0&&numberMini&&numberMini>1) {
     2726    // Sort
     2727    CoinSort_2(sort,sort+numberMini,whichObject);
     2728    delete branch_;
     2729    branch_=NULL;
     2730    numberMini = CoinMin(numberMini,model->sizeMiniTree());
     2731    anyAction=numberMini;
     2732    branches = new OsiSolverBranch[numberMini];
     2733    for (int iDo=0;iDo<numberMini;iDo++) {
     2734      int iObject = whichObject[iDo];
     2735      CbcObject * object = model->modifiableObject(iObject);
     2736      OsiSolverBranch * oneBranch = object->solverBranch();
     2737      branches[iDo]=*oneBranch;
     2738      delete oneBranch;
     2739    }
     2740  }
    26912741/*
    26922742  Cleanup, then we're finished
     
    30443094        // neither side feasible
    30453095        anyAction=-2;
    3046         delete choice.possibleBranch;
    30473096        printf("Both infeasible for choice %d sequence %d\n",i,
    30483097               model->object(choice.objectNumber)->columnNumber());
     
    30543103      }
    30553104    }
     3105    delete choice.possibleBranch;
    30563106    if (numberIterationsAllowed<=0)
    30573107      break;
  • trunk/CbcStrategy.cpp

    r197 r222  
    1010
    1111#include "OsiSolverInterface.hpp"
     12#define COIN_USE_CLP
     13#ifdef COIN_USE_CLP
     14#include "OsiClpSolverInterface.hpp"
     15#endif
    1216#include "CbcModel.hpp"
    1317#include "CbcMessage.hpp"
    1418#include "CbcStrategy.hpp"
    1519#include "CbcCutGenerator.hpp"
     20#include "CbcBranchActual.hpp"
     21#include "CglPreProcess.hpp"
    1622// Cuts
    1723
     
    3036// Default Constructor
    3137CbcStrategy::CbcStrategy()
    32   :depth_(0)
     38  :depth_(0),
     39   preProcessState_(0),
     40   process_(NULL)
    3341{
    3442}
     
    3745CbcStrategy::~CbcStrategy ()
    3846{
     47  delete process_;
     48}
     49// Delete pre-processing object to save memory
     50void
     51CbcStrategy::deletePreProcess()
     52{
     53  delete process_;
     54  process_=NULL;
    3955}
    4056
     
    4864   numberStrong_(numberStrong),
    4965   numberBeforeTrust_(numberBeforeTrust),
    50    printLevel_(printLevel)
     66   printLevel_(printLevel),
     67   desiredPreProcess_(0),
     68   preProcessPasses_(0)
    5169{
    5270}
     
    7290  numberStrong_(rhs.numberStrong_),
    7391  numberBeforeTrust_(rhs.numberBeforeTrust_),
    74   printLevel_(rhs.printLevel_)
     92  printLevel_(rhs.printLevel_),
     93  desiredPreProcess_(rhs.desiredPreProcess_),
     94  preProcessPasses_(rhs.preProcessPasses_)
    7595{
    7696  setNested(rhs.getNested());
     
    243263CbcStrategyDefault::setupOther(CbcModel & model)
    244264{
     265  // See if preprocessing wanted
     266  if (desiredPreProcess_) {
     267    delete process_;
     268    // solver_ should have been cloned outside
     269    CglPreProcess * process = new CglPreProcess();
     270    OsiSolverInterface * solver = model.solver();
     271    int logLevel = model.messageHandler()->logLevel();
     272#ifdef COIN_USE_CLP
     273    OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
     274    ClpSimplex * lpSolver=NULL;
     275    if (clpSolver) {
     276      if (clpSolver->messageHandler()->logLevel())
     277        clpSolver->messageHandler()->setLogLevel(1);
     278      if (logLevel>-1)
     279        clpSolver->messageHandler()->setLogLevel(CoinMin(logLevel,clpSolver->messageHandler()->logLevel()));
     280      lpSolver = clpSolver->getModelPtr();
     281      /// If user left factorization frequency then compute
     282      lpSolver->defaultFactorizationFrequency();
     283    }
     284#endif
     285    // Tell solver we are in Branch and Cut
     286    solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;
     287    // Default set of cut generators
     288    CglProbing generator1;
     289    generator1.setUsingObjective(true);
     290    generator1.setMaxPass(3);
     291    generator1.setMaxProbeRoot(solver->getNumCols());
     292    generator1.setMaxElements(100);
     293    generator1.setMaxLookRoot(50);
     294    generator1.setRowCuts(3);
     295    //generator1.messageHandler()->setLogLevel(logLevel);
     296    process->messageHandler()->setLogLevel(logLevel);
     297    // Add in generators
     298    process->addCutGenerator(&generator1);
     299    int translate[]={9999,0,2};
     300    OsiSolverInterface * solver2 =
     301      process->preProcessNonDefault(*solver,
     302                                    translate[desiredPreProcess_],preProcessPasses_);
     303    // Tell solver we are not in Branch and Cut
     304    solver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
     305    if (solver2)
     306      solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
     307    bool feasible=true;
     308    if (!solver2) {
     309      feasible = false;
     310    } else {
     311      // now tighten bounds
     312#ifdef COIN_USE_CLP
     313      if (clpSolver) {
     314        // model has changed
     315        solver = model.solver();
     316        OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
     317        ClpSimplex * lpSolver = clpSolver->getModelPtr();
     318        if (lpSolver->tightenPrimalBounds()==0) {
     319          lpSolver->dual();
     320        } else {
     321          feasible = false;
     322        }
     323      }
     324#endif
     325      if (feasible) {
     326        preProcessState_=1;
     327        process_=process;
     328        /* Note that original solver will be kept (with false)
     329           and that final solver will also be kept.
     330           This is for post-processing
     331        */
     332        OsiSolverInterface * solver3 = solver2->clone();
     333        model.assignSolver(solver3,false);
     334        if (process_->numberSOS()) {
     335          int numberSOS = process_->numberSOS();
     336          int numberIntegers = model.numberIntegers();
     337          /* model may not have created objects
     338             If none then create
     339          */
     340          if (!numberIntegers||!model.numberObjects()) {
     341            model.findIntegers(true);
     342            numberIntegers = model.numberIntegers();
     343          }
     344          CbcObject ** oldObjects = model.objects();
     345          // Do sets and priorities
     346          CbcObject ** objects = new CbcObject * [numberSOS];
     347          // set old objects to have low priority
     348          int numberOldObjects = model.numberObjects();
     349          int numberColumns = model.getNumCols();
     350          for (int iObj = 0;iObj<numberOldObjects;iObj++) {
     351            int oldPriority = oldObjects[iObj]->priority();
     352            oldObjects[iObj]->setPriority(numberColumns+oldPriority);
     353          }
     354          const int * starts = process_->startSOS();
     355          const int * which = process_->whichSOS();
     356          const int * type = process_->typeSOS();
     357          const double * weight = process_->weightSOS();
     358          int iSOS;
     359          for (iSOS =0;iSOS<numberSOS;iSOS++) {
     360            int iStart = starts[iSOS];
     361            int n=starts[iSOS+1]-iStart;
     362            objects[iSOS] = new CbcSOS(&model,n,which+iStart,weight+iStart,
     363                                       iSOS,type[iSOS]);
     364            // branch on long sets first
     365            objects[iSOS]->setPriority(numberColumns-n);
     366          }
     367          model.addObjects(numberSOS,objects);
     368          for (iSOS=0;iSOS<numberSOS;iSOS++)
     369            delete objects[iSOS];
     370          delete [] objects;
     371        }
     372      } else {
     373        //printf("Pre-processing says infeasible\n");
     374        delete process;
     375        preProcessState_=-1;
     376        process_=NULL;
     377      }
     378    }
     379  }
    245380  model.setNumberStrong(numberStrong_);
    246381  model.setNumberBeforeTrust(numberBeforeTrust_);
  • trunk/Test/CoinSolve.cpp

    r221 r222  
    1515#include "CoinHelperFunctions.hpp"
    1616// Same version as CBC
    17 #define CBCVERSION "1.00.01"
     17#define CBCVERSION "1.00.02"
    1818
    1919#include "CoinMpsIO.hpp"
     
    381381    delete solver;
    382382    numberChanged=0;
     383    delete [] changed;
    383384    return NULL;
    384385  }
     
    25882589  and CglStored which just has a list of cuts which can be activated.
    25892590  Modified preprocess option to SOS
     2591  Version 1.00.02 December 9 2005
     2592  Added use of CbcStrategy to do clean preprocessing
     2593  Added use of referenceSolver for cleaner repetition of Cbc
    25902594*/
  • trunk/include/CbcBranchActual.hpp

    r216 r222  
    198198  virtual CbcBranchingObject * createBranch(int way) ;
    199199
     200  /** Create an OsiSolverBranch object
     201
     202      This returns NULL if branch not represented by bound changes
     203  */
     204  virtual OsiSolverBranch * solverBranch() const;
     205 
    200206  /** \brief Given a valid solution (with reduced costs, etc.),
    201207      return a branching object which would give a new feasible
     
    780786                            double changeUp, int numInfUp,
    781787                            double changeDn, int numInfDn);
     788  /** Sets or gets best criterion so far */
     789  virtual void setBestCriterion(double value);
     790  virtual double getBestCriterion() const;
    782791
    783792  /** \brief Compare N branching objects. Return index of best
  • trunk/include/CbcBranchBase.hpp

    r216 r222  
    88
    99class OsiSolverInterface;
     10class OsiSolverBranch;
    1011
    1112class CbcModel;
     
    107108  virtual CbcBranchingObject * createBranch(int way) = 0;
    108109 
     110  /** Create an OsiSolverBranch object
     111
     112      This returns NULL if branch not represented by bound changes
     113  */
     114  virtual OsiSolverBranch * solverBranch() const;
     115 
    109116  /** \brief Given a valid solution (with reduced costs, etc.),
    110117      return a branching object which would give a new feasible
     
    362369    This routine is used only after strong branching.
    363370    Either this or bestBranch is used depending which user wants.
     371
    364372 */
    365373
     
    393401  virtual void updateInformation(OsiSolverInterface * solver,
    394402                                 const CbcNode * node) {};
     403  /** Sets or gets best criterion so far */
     404  virtual void setBestCriterion(double value) {};
     405  virtual double getBestCriterion() const {return 0.0;};
    395406
    396407protected:
  • trunk/include/CbcBranchDynamic.hpp

    r135 r222  
    4949  virtual CbcBranchingObject * createBranch(int way) ;
    5050
     51  /** Create an OsiSolverBranch object
     52
     53      This returns NULL if branch not represented by bound changes
     54  */
     55  virtual OsiSolverBranch * solverBranch() const;
     56 
    5157  /// Down pseudo cost
    5258  inline double downDynamicPseudoCost() const
     
    335341                            double changeUp, int numInfUp,
    336342                            double changeDn, int numInfDn);
     343  /** Sets or gets best criterion so far */
     344  virtual void setBestCriterion(double value);
     345  virtual double getBestCriterion() const;
    337346  /** Says whether this method can handle both methods -
    338347      1 better, 2 best, 3 both */
  • trunk/include/CbcModel.hpp

    r220 r222  
    2929class CbcStrategy;
    3030class CbcFeasibilityBase;
     31class CbcStatistics;
    3132
    3233//#############################################################################
     
    221222    */
    222223     OsiSolverInterface *  strengthenedModel();
     224private:
    223225    /** \brief Evaluate a subproblem using cutting planes and heuristics
    224226
     
    228230      evaluation.
    229231    */
    230     bool solveWithCuts(OsiCuts & cuts, int numberTries,CbcNode * node,
    231                        int & numberOldActiveCuts, int & numberNewCuts,
    232                        int & maximumWhich, int * & whichGenerator);
    233 
     232  bool solveWithCuts(OsiCuts & cuts, int numberTries,CbcNode * node);
     233  /** Input one node output N nodes to put on tree and optional solution update
     234      This should be able to operate in parallel so is given a solver and is const(ish)
     235      However we will need to keep an array of solver_ and bases and more
     236      status is 0 for normal, 1 if solution
     237      Calling code should always push nodes back on tree
     238  */
     239  CbcNode ** solveOneNode(int whichSolver,CbcNode * node,
     240                          int & numberNodesOutput, int & status) ;
     241  /// Update size of whichGenerator
     242  void resizeWhichGenerator(int numberNow, int numberAfter);
     243public:
    234244    /** \brief Reoptimise an LP relaxation
    235245   
     
    237247    */
    238248    bool resolve();
    239   /// Make given rows (L or G) into global cuts and remove from lp
    240   void makeGlobalCuts(int numberRows,const int * which);
     249    /// Make given rows (L or G) into global cuts and remove from lp
     250    void makeGlobalCuts(int numberRows,const int * which);
    241251  //@}
    242252
     
    572582  inline int numberStrong() const
    573583  { return numberStrong_;};
     584  /** Set size of mini - tree.  If > 1 then does total enumeration of
     585      tree given by this best variables to branch on
     586  */
     587  inline void setSizeMiniTree(int value)
     588  { sizeMiniTree_=value;};
     589  inline int sizeMiniTree() const
     590  { return sizeMiniTree_;};
    574591
    575592  /** Set the number of branches before pseudo costs believed
     
    11151132    If saveCuts then slack cuts will be saved
    11161133  */
    1117   void takeOffCuts(OsiCuts &cuts, int *whichGenerator,
    1118                      int &numberOldActiveCuts, int &numberNewCuts,
     1134  void takeOffCuts(OsiCuts &cuts,
    11191135                     bool allowResolve,OsiCuts * saveCuts) ;
    11201136
     
    13381354
    13391355      On return, \p solver will be NULL.
     1356      If deleteSolver then current solver deleted (if model owned)
    13401357
    13411358      \note Parameter settings in the outgoing solver are not inherited by
    13421359            the incoming solver.
    13431360    */
    1344     void assignSolver(OsiSolverInterface *&solver);
     1361    void assignSolver(OsiSolverInterface *&solver,bool deleteSolver=true);
    13451362 
    13461363    /** Copy constructor .
     
    13561373
    13571374    /// Returns solver - has current state
    1358     OsiSolverInterface * solver() const
     1375    inline OsiSolverInterface * solver() const
    13591376    { return solver_;};
    13601377
    13611378    /// Returns solver with continuous state
    1362     OsiSolverInterface * continuousSolver() const
     1379    inline OsiSolverInterface * continuousSolver() const
    13631380    { return continuousSolver_;};
     1381
     1382  /// A copy of the solver, taken at constructor or by saveReferenceSolver
     1383  inline OsiSolverInterface * referenceSolver() const
     1384  { return referenceSolver_;};
     1385
     1386  /// Save a copy of the current solver so can be reset to
     1387  void saveReferenceSolver();
     1388
     1389  /** Uses a copy of reference solver to be current solver.
     1390      Because of possible mismatches all exotic integer information is loat
     1391      (apart from normal information in OsiSolverInterface)
     1392      so SOS etc and priorities will have to be redone
     1393  */
     1394  void resetToReferenceSolver();
     1395
    13641396  /// Clears out as much as possible (except solver)
    13651397  void gutsOfDestructor();
     1398  /** Clears out enough to reset CbcModel as if no branch and bound done
     1399   */
     1400  void gutsOfDestructor2();
    13661401  //@}
    13671402
     
    13951430  OsiSolverInterface * continuousSolver_;
    13961431
     1432  /// A copy of the solver, taken at constructor or by saveReferenceSolver
     1433  OsiSolverInterface * referenceSolver_;
     1434
    13971435   /// Message handler
    13981436  CoinMessageHandler * handler_;
     
    14231461  */
    14241462  mutable CoinWarmStart *emptyWarmStart_ ;
    1425 
    1426   /** Pointer to a warm start basis.  */
    1427   CoinWarmStartBasis *basis_;
    14281463
    14291464  /// Best objective
     
    16701705  /// Current cut pass number
    16711706  int currentPassNumber_;
     1707  /// Maximum number of cuts (for whichGenerator_)
     1708  int maximumWhich_;
     1709  /// Which cut generator generated this cut
     1710  int * whichGenerator_;
     1711  /// Maximum number of statistics
     1712  int maximumStatistics_;
     1713  /// statistics
     1714  CbcStatistics ** statistics_;
     1715  /// Number of fixed by analyze at root
     1716  int numberFixedAtRoot_;
     1717  /// Number fixed by analyze so far
     1718  int numberFixedNow_;
     1719  /// Whether stopping on gap
     1720  bool stoppedOnGap_;
     1721  /// Whether event happened
     1722  bool eventHappened_;
     1723  /// Number of long strong goes
     1724  int numberLongStrong_;
     1725  /// Number of old active cuts
     1726  int numberOldActiveCuts_;
     1727  /// Number of new cuts
     1728  int numberNewCuts_;
     1729  /// Size of mini - tree
     1730  int sizeMiniTree_;
    16721731  /// Whether to force a resolve after takeOffCuts
    16731732  bool resolveAfterTakeOffCuts_;
  • trunk/include/CbcNode.hpp

    r208 r222  
    1111
    1212class OsiSolverInterface;
     13class OsiSolverBranch;
    1314
    1415class OsiCuts;
     
    468469      <li> -1: A monotone object was discovered
    469470      <li> -2: An infeasible object was discovered
     471      <li> >0: Number of quich branching objects (and branches will be non NULL)
    470472    </ul>
    471473  */
    472474  int chooseDynamicBranch (CbcModel * model,
    473                     CbcNode * lastNode,
    474                     int numberPassesLeft);
     475                           CbcNode * lastNode,
     476                           OsiSolverBranch * & branches,
     477                           int numberPassesLeft);
    475478  int analyze(CbcModel * model,double * results);
    476479  /// Decrement active cut counts
  • trunk/include/CbcStrategy.hpp

    r182 r222  
    55
    66#include "CbcModel.hpp"
    7 
     7class CglPreProcess;
    88
    99//#############################################################################
     
    2626  /// Do printing stuff
    2727  virtual void setupPrinting(CbcModel & model,int modelLogLevel)=0;
    28   /// Other stuff e.g. strong branching
     28  /// Other stuff e.g. strong branching and preprocessing
    2929  virtual void setupOther(CbcModel & model)=0;
    3030  /// Set model depth (i.e. how nested)
     
    3434  inline int getNested() const
    3535  { return depth_;};
     36  /// Say preProcessing done
     37  inline void setPreProcessState(int state)
     38  { preProcessState_=state;};
     39  /// See what sort of preprocessing was done
     40  inline int preProcessState() const
     41  { return preProcessState_;};
     42  /// Pre-processing object
     43  inline CglPreProcess * process() const
     44  { return process_;};
     45  /// Delete pre-processing object to save memory
     46  void deletePreProcess();
    3647private:
    3748 
     
    4253  /// Model depth
    4354  int depth_;
     55  /** PreProcessing state -
     56      -1 infeasible
     57      0 off
     58      1 was done (so need post-processing)
     59  */
     60  int preProcessState_;
     61  /// If preprocessing then this is object
     62  CglPreProcess * process_;
    4463};
    4564
     
    107126  /// Other stuff e.g. strong branching
    108127  virtual void setupOther(CbcModel & model);
     128  /// Set up preProcessing - see below
     129  inline void setupPreProcessing(int desired=1, int passes=10)
     130  { desiredPreProcess_=1;preProcessPasses_=passes;};
     131  /// See what sort of preprocessing wanted
     132  inline int desiredPreProcess() const
     133  { return desiredPreProcess_;};
     134  /// See how many passes wanted
     135  inline int preProcessPasses() const
     136  { return preProcessPasses_;};
    109137
    110138protected:
     
    122150  // Print level 0 little, 1 medium
    123151  int printLevel_;
     152
     153  /** Desired pre-processing
     154      0 - none
     155      1 - ordinary
     156      2 - find sos
     157  */
     158  int desiredPreProcess_;
     159  /// Number of pre-processing passes
     160  int preProcessPasses_;
    124161
    125162private:
Note: See TracChangeset for help on using the changeset viewer.