Ignore:
Timestamp:
Jun 26, 2007 5:59:58 AM (12 years ago)
Author:
forrest
Message:

update branches/devel for threads

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/devel/Cbc/src/CbcModel.cpp

    r616 r642  
    3636#include "CbcBranchDynamic.hpp"
    3737#include "CbcHeuristic.hpp"
     38#include "CbcHeuristicFPump.hpp"
    3839#include "CbcModel.hpp"
    3940#include "CbcTreeLocal.hpp"
     
    4849#include "CbcCutGenerator.hpp"
    4950#include "CbcFeasibilityBase.hpp"
     51#include "CbcFathom.hpp"
    5052// include Probing
    5153#include "CglProbing.hpp"
     
    6062#include "CbcCompareActual.hpp"
    6163#include "CbcTree.hpp"
     64//#define CBC_THREAD
     65#ifdef CBC_THREAD
     66#include <pthread.h>
     67//#define CBC_THREAD_DEBUG 1
     68// To Pass across to doOneNode
     69typedef struct {
     70  CbcModel * baseModel;
     71  CbcModel * thisModel;
     72  CbcNode * node; // filled in every time
     73  CbcNode * createdNode; // filled in every time on return
     74  pthread_t threadIdOfBase;
     75  pthread_mutex_t * mutex; // for locking data
     76  pthread_mutex_t * mutex2; // for waking up threads
     77  pthread_cond_t * condition2; // for waking up thread
     78  int returnCode; // -1 available, 0 busy, 1 finished , 2??
     79  double timeLocked;
     80  double timeWaitingToLock;
     81  double timeWaitingToStart;
     82  double timeInThread;
     83  int numberTimesLocked;
     84  int numberTimesUnlocked;
     85  int numberTimesWaitingToStart;
     86  int saveStuff[2];
     87  struct timespec absTime;
     88  bool locked;
     89#if CBC_THREAD_DEBUG
     90  int threadNumber;
     91#endif
     92} threadStruct;
     93static void * doNodesThread(void * voidInfo);
     94static void * doCutsThread(void * voidInfo);
     95#endif
    6296/* Various functions local to CbcModel.cpp */
    6397
     
    449483  system held by the solver.
    450484*/
    451 
    452485void CbcModel::branchAndBound(int doStatistics)
    453486
     
    461494  strongInfo_[2]=0;
    462495  numberStrongIterations_ = 0;
     496#ifndef NDEBUG
     497  {
     498    int i;
     499    int n = solver_->getNumCols();
     500    const double *lower = solver_->getColLower() ;
     501    const double *upper = solver_->getColUpper() ;
     502    for (i=0;i<n;i++) {
     503      assert (lower[i]<1.0e10);
     504      assert (upper[i]>-1.0e10);
     505    }
     506    n = solver_->getNumRows();
     507    lower = solver_->getRowLower() ;
     508    upper = solver_->getRowUpper() ;
     509    for (i=0;i<n;i++) {
     510      assert (lower[i]<1.0e10);
     511      assert (upper[i]>-1.0e10);
     512    }
     513  }
     514#endif
    463515  // original solver (only set if pre-processing)
    464516  OsiSolverInterface * originalSolver=NULL;
     
    466518  OsiObject ** originalObject = NULL;
    467519  // Set up strategies
     520#if 0
     521  std::string problemName ;
     522  solver_->getStrParam(OsiProbName,problemName) ;
     523  if (!strcmp(problemName.c_str(),"P0282")) solver_->activateRowCutDebugger(problemName.c_str()) ;
     524#endif
    468525  if (strategy_) {
    469526    // May do preprocessing
     
    894951     = dynamic_cast<OsiClpSolverInterface *> (solver_);
    895952   if (clpSolver) {
    896 #define CLP_QUICK_OPTIONS
     953     //#define CLP_QUICK_OPTIONS
    897954#ifdef CLP_QUICK_OPTIONS
    898955     // Try and re-use regions   
     
    9431000  whichGenerator_ = new int[maximumWhich_] ;
    9441001  memset(whichGenerator_,0,maximumWhich_*sizeof(int));
    945   int currentNumberCuts = 0 ;
    9461002  maximumNumberCuts_ = 0 ;
    9471003  currentNumberCuts_ = 0 ;
     
    10051061  maximumDepthActual_=0;
    10061062  numberDJFixed_=0.0;
     1063  // Do heuristics
     1064  {
     1065    double * newSolution = new double [numberColumns] ;
     1066    double heuristicValue = getCutoff() ;
     1067    int found = -1; // no solution found
     1068
     1069    currentPassNumber_ = 1; // so root heuristics will run
     1070    int i;
     1071    for (i = 0;i<numberHeuristics_;i++) {
     1072      // see if heuristic will do anything
     1073      double saveValue = heuristicValue ;
     1074      int ifSol = heuristic_[i]->solution(heuristicValue,
     1075                                          newSolution);
     1076      if (ifSol>0) {
     1077        // better solution found
     1078        found = i ;
     1079        incrementUsed(newSolution);
     1080        // increment number of solutions so other heuristics can test
     1081        numberSolutions_++;
     1082        numberHeuristicSolutions_++;
     1083      } else {
     1084        heuristicValue = saveValue ;
     1085      }
     1086    }
     1087    currentPassNumber_ = 0;
     1088    /*
     1089      Did any of the heuristics turn up a new solution? Record it before we free
     1090      the vector.
     1091    */
     1092    if (found >= 0) {
     1093      lastHeuristic_ = heuristic_[found];
     1094      setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
     1095      CbcTreeLocal * tree
     1096          = dynamic_cast<CbcTreeLocal *> (tree_);
     1097      if (tree)
     1098        tree->passInSolution(bestSolution_,heuristicValue);
     1099    }
     1100    for (i = 0;i<numberHeuristics_;i++) {
     1101      // delete FPump
     1102      CbcHeuristicFPump * pump
     1103        = dynamic_cast<CbcHeuristicFPump *> (heuristic_[i]);
     1104      if (pump) {
     1105        delete pump;
     1106        numberHeuristics_ --;
     1107        for (int j=i;j<numberHeuristics_;j++)
     1108          heuristic_[j] = heuristic_[j+1];
     1109      }
     1110    }
     1111    delete [] newSolution ;
     1112  }
    10071113  statistics_ = NULL;
    10081114  // Do on switch
     
    10371143        feasible = solveWithCuts(cuts, 1,
    10381144                                 NULL);
    1039 #if 0
    1040         currentNumberCuts_ = cuts.sizeRowCuts();
    1041         if (currentNumberCuts_ >= maximumNumberCuts_) {
    1042           maximumNumberCuts_ = currentNumberCuts;
    1043           delete [] addedCuts_;
    1044           addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
    1045         }
    1046 #endif
    10471145      }
    10481146    }
     
    10641162                           *dblParam_[CbcAllowableFractionGap]);
    10651163  if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
    1066     if (bestPossibleObjective_<getCutoff()) {
     1164    if (bestPossibleObjective_<getCutoff())
    10671165      stoppedOnGap_ = true ;
    1068       messageHandler()->message(CBC_GAP,messages())
    1069         << bestObjective_-bestPossibleObjective_
    1070         << dblParam_[CbcAllowableGap]
    1071         << dblParam_[CbcAllowableFractionGap]*100.0
    1072         << CoinMessageEol ;
    1073       secondaryStatus_ = 2;
    1074     }
    10751166    feasible = false;
    10761167  }
     
    11271218      }
    11281219    }
    1129 #if 0
    1130     while (anyAction == -1)
    1131     {
    1132       // Set objective value (not so obvious if NLP etc)
    1133       setObjectiveValue(newNode,NULL);
    1134       if (numberBeforeTrust_==0 ) {
    1135         anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ;
    1136       } else {
    1137         OsiSolverBranch * branches=NULL;
    1138         anyAction = newNode->chooseDynamicBranch(this,NULL,branches,numberPassesLeft) ;
    1139         if (anyAction==-3)
    1140           anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ; // dynamic did nothing
    1141       }
    1142       numberPassesLeft--;
    1143       if (anyAction == -1)
    1144       {
    1145         //if (solverCharacteristics_->solverType()!=4)
    1146           feasible = resolve(NULL,10) != 0 ;
    1147           //else
    1148           //feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,NULL);
    1149       if (problemFeasibility_->feasible(this,0)<0) {
    1150         feasible=false; // pretend infeasible
    1151       }
    1152       reducedCostFix() ;
    1153       resolved = true ;
    1154 #       ifdef CBC_DEBUG
    1155       printf("Resolve (root) as something fixed, Obj value %g %d rows\n",
    1156              solver_->getObjValue(),
    1157              solver_->getNumRows()) ;
    1158 #       endif
    1159       if (!feasible) anyAction = -2 ; }
    1160       if (anyAction == -2||newNode->objectiveValue() >= cutoff)
    1161       { delete newNode ;
    1162         newNode = NULL ;
    1163         feasible = false ; } }
    1164 #else
    1165   OsiSolverBranch * branches = NULL;
    1166   anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts,resolved,
    1167                            NULL,NULL,NULL,branches);
    1168   if (anyAction == -2||newNode->objectiveValue() >= cutoff) {
    1169     if (anyAction != -2) {
    1170       // zap parent nodeInfo
     1220    OsiSolverBranch * branches = NULL;
     1221    anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts,resolved,
     1222                             NULL,NULL,NULL,branches);
     1223    if (anyAction == -2||newNode->objectiveValue() >= cutoff) {
     1224      if (anyAction != -2) {
     1225        // zap parent nodeInfo
    11711226#ifdef COIN_DEVELOP
    1172       printf("zapping CbcNodeInfo %x\n",newNode->nodeInfo()->parent());
     1227        printf("zapping CbcNodeInfo %x\n",newNode->nodeInfo()->parent());
    11731228#endif
    1174       if (newNode->nodeInfo())
    1175         newNode->nodeInfo()->nullParent();
    1176     }
    1177     delete newNode ;
    1178     newNode = NULL ;
    1179     feasible = false ;
    1180   }
    1181 #endif
     1229        if (newNode->nodeInfo())
     1230          newNode->nodeInfo()->nullParent();
     1231      }
     1232      delete newNode ;
     1233      newNode = NULL ;
     1234      feasible = false ;
     1235    }
    11821236  }
    11831237/*
     
    11881242  assert (!newNode || newNode->objectiveValue() <= cutoff) ;
    11891243  // Save address of root node as we don't want to delete it
    1190   CbcNode * rootNode = newNode;
    11911244  // initialize for print out
    11921245  int lastDepth=0;
     
    12041257  a valid solution for use by setBestSolution().
    12051258*/
    1206   CoinWarmStartBasis *lastws = 0 ;
     1259  CoinWarmStartBasis *lastws = NULL ;
    12071260  if (feasible && newNode->branchingObject())
    12081261  { if (resolved)
     
    12911344  */
    12921345  numberLongStrong_=0;
     1346  double totalTime = 0.0;
     1347#ifdef CBC_THREAD
     1348  CbcNode * createdNode=NULL;
     1349  CbcModel ** threadModel = NULL;
     1350  pthread_t * threadId = NULL;
     1351  int * threadCount = NULL;
     1352  pthread_mutex_t mutex;
     1353  pthread_cond_t condition_main;
     1354  pthread_mutex_t condition_mutex;
     1355  pthread_mutex_t * mutex2 = NULL;
     1356  pthread_cond_t * condition2 = NULL;
     1357  threadStruct * threadInfo = NULL;
     1358  bool locked=false;
     1359  int threadStats[6];
     1360  memset(threadStats,0,sizeof(threadStats));
     1361  double timeWaiting=0.0;
     1362  // For now just one model
     1363  if (numberThreads_) {
     1364    threadId = new pthread_t [numberThreads_];
     1365    threadCount = new int [numberThreads_];
     1366    CoinZeroN(threadCount,numberThreads_);
     1367    pthread_mutex_init(&mutex,NULL);
     1368    pthread_cond_init(&condition_main,NULL);
     1369    pthread_mutex_init(&condition_mutex,NULL);
     1370    threadModel = new CbcModel * [numberThreads_+1];
     1371    threadInfo = new threadStruct [numberThreads_+1];
     1372    mutex2 = new pthread_mutex_t [numberThreads_];
     1373    condition2 = new pthread_cond_t [numberThreads_];
     1374    // we don't want a strategy object
     1375    CbcStrategy * saveStrategy = strategy_;
     1376    strategy_ = NULL;
     1377    for (int i=0;i<numberThreads_;i++) {
     1378      pthread_mutex_init(mutex2+i,NULL);
     1379      pthread_cond_init(condition2+i,NULL);
     1380      threadId[i]=0;
     1381      threadInfo[i].baseModel=this;
     1382      threadModel[i]=new CbcModel(*this);
     1383#ifdef COIN_HAS_CLP
     1384      // Solver may need to know about model
     1385      CbcModel * thisModel = threadModel[i];
     1386      CbcOsiSolver * solver =
     1387              dynamic_cast<CbcOsiSolver *>(thisModel->solver()) ;
     1388      if (solver)
     1389        solver->setCbcModel(thisModel);
     1390#endif
     1391      mutex_ = (void *) (threadInfo+i);
     1392      threadModel[i]->moveToModel(this,-1);
     1393      threadInfo[i].thisModel=threadModel[i];
     1394      threadInfo[i].node=NULL;
     1395      threadInfo[i].createdNode=NULL;
     1396      threadInfo[i].threadIdOfBase=pthread_self();
     1397      threadInfo[i].mutex=&mutex;
     1398      threadInfo[i].mutex2=mutex2+i;
     1399      threadInfo[i].condition2=condition2+i;
     1400      threadInfo[i].returnCode=-1;
     1401      threadInfo[i].timeLocked=0.0;
     1402      threadInfo[i].timeWaitingToLock=0.0;
     1403      threadInfo[i].timeWaitingToStart=0.0;
     1404      threadInfo[i].timeInThread=0.0;
     1405      threadInfo[i].numberTimesLocked=0;
     1406      threadInfo[i].numberTimesUnlocked=0;
     1407      threadInfo[i].numberTimesWaitingToStart=0;
     1408      threadInfo[i].locked=false;
     1409#if CBC_THREAD_DEBUG
     1410      threadInfo[i].threadNumber=i+2;
     1411#endif
     1412      pthread_create(threadId+i,NULL,doNodesThread,threadInfo+i);
     1413    }
     1414    strategy_ = saveStrategy;
     1415    // Do a partial one for base model
     1416    threadInfo[numberThreads_].baseModel=this;
     1417    threadModel[numberThreads_]=this;
     1418    mutex_ = (void *) (threadInfo+numberThreads_);
     1419    threadInfo[numberThreads_].node=NULL;
     1420    threadInfo[numberThreads_].mutex=&mutex;
     1421    threadInfo[numberThreads_].condition2=&condition_main;
     1422    threadInfo[numberThreads_].mutex2=&condition_mutex;
     1423    threadInfo[numberThreads_].timeLocked=0.0;
     1424    threadInfo[numberThreads_].timeWaitingToLock=0.0;
     1425    threadInfo[numberThreads_].numberTimesLocked=0;
     1426    threadInfo[numberThreads_].numberTimesUnlocked=0;
     1427    threadInfo[numberThreads_].locked=false;
     1428#if CBC_THREAD_DEBUG
     1429    threadInfo[numberThreads_].threadNumber=1;
     1430#endif
     1431  }
     1432#endif
    12931433/*
    12941434  At last, the actual branch-and-cut search loop, which will iterate until
     
    13011441  than the current objective cutoff.
    13021442*/
    1303   while (!tree_->empty()) {
     1443  while (true) {
     1444#ifdef CBC_THREAD
     1445    if (!locked) {
     1446      lockThread();
     1447      locked=true;
     1448    }
     1449#endif
     1450    if (tree_->empty()) {
     1451#ifdef CBC_THREAD
     1452      if (numberThreads_) {
     1453        // may still be outstanding nodes
     1454        int iThread;
     1455        for (iThread=0;iThread<numberThreads_;iThread++) {
     1456          if (threadId[iThread]) {
     1457            if (threadInfo[iThread].returnCode==0)
     1458              break;
     1459          }
     1460        }
     1461        if (iThread<numberThreads_) {
     1462          unlockThread();
     1463          locked = false;
     1464          pthread_cond_signal(threadInfo[iThread].condition2); // unlock in case
     1465#define CONDITION_WAIT
     1466#ifdef CONDITION_WAIT
     1467          while (true) {
     1468            pthread_mutex_lock(&condition_mutex);
     1469            struct timespec absTime;
     1470            clock_gettime(CLOCK_REALTIME,&absTime);
     1471            double time = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     1472            absTime.tv_nsec += 1000000; // millisecond
     1473            if (absTime.tv_nsec>=1000000000) {
     1474              absTime.tv_nsec -= 1000000000;
     1475              absTime.tv_sec++;
     1476            }
     1477            pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     1478            clock_gettime(CLOCK_REALTIME,&absTime);
     1479            double time2 = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     1480            timeWaiting += time2-time;
     1481            pthread_mutex_unlock(&condition_mutex);
     1482            if (threadInfo[iThread].returnCode!=0)
     1483              break;
     1484          }
     1485#else
     1486          while (threadInfo[iThread].returnCode==0) {
     1487            struct timespec moreTime;
     1488            moreTime.tv_nsec = 10000;
     1489            moreTime.tv_sec = 0;
     1490            nanosleep(&moreTime,NULL);
     1491          }
     1492#endif
     1493          threadModel[iThread]->moveToModel(this,1);
     1494          assert (threadInfo[iThread].returnCode==1);
     1495          // say available
     1496          threadInfo[iThread].returnCode=-1;
     1497          threadStats[4]++;
     1498          continue;
     1499        }
     1500      }
     1501      unlockThread();
     1502      locked=false; // not needed as break
     1503#endif
     1504      break;
     1505    }
     1506#ifdef CBC_THREAD
     1507    unlockThread();
     1508    locked = false;
     1509#endif
     1510/*
     1511  Check for abort on limits: node count, solution count, time, integrality gap.
     1512*/
     1513    totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
     1514    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
     1515          numberSolutions_ < intParam_[CbcMaxNumSol] &&
     1516          totalTime < dblParam_[CbcMaximumSeconds] &&
     1517          !stoppedOnGap_&&!eventHappened_)) {
     1518      // out of loop
     1519      break;
     1520    }
    13041521#ifdef BONMIN
    13051522    assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible());
     
    13081525      double newCutoff = getCutoff();
    13091526      if (analyzeResults_) {
    1310         // see if we could fix any (more)
    1311         int n=0;
    1312         double * newLower = analyzeResults_;
    1313         double * objLower = newLower+numberIntegers_;
    1314         double * newUpper = objLower+numberIntegers_;
    1315         double * objUpper = newUpper+numberIntegers_;
    1316         for (int i=0;i<numberIntegers_;i++) {
    1317           if (objLower[i]>newCutoff) {
    1318             n++;
    1319             if (objUpper[i]>newCutoff) {
    1320               newCutoff = -COIN_DBL_MAX;
    1321               break;
    1322             }
    1323           } else if (objUpper[i]>newCutoff) {
    1324             n++;
    1325           }
    1326         }
    1327         if (newCutoff==-COIN_DBL_MAX) {
    1328           printf("Root analysis says finished\n");
    1329         } else if (n>numberFixedNow_) {
    1330           printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
    1331           numberFixedNow_=n;
    1332         }
     1527        // see if we could fix any (more)
     1528        int n=0;
     1529        double * newLower = analyzeResults_;
     1530        double * objLower = newLower+numberIntegers_;
     1531        double * newUpper = objLower+numberIntegers_;
     1532        double * objUpper = newUpper+numberIntegers_;
     1533        for (int i=0;i<numberIntegers_;i++) {
     1534          if (objLower[i]>newCutoff) {
     1535            n++;
     1536            if (objUpper[i]>newCutoff) {
     1537              newCutoff = -COIN_DBL_MAX;
     1538              break;
     1539            }
     1540          } else if (objUpper[i]>newCutoff) {
     1541            n++;
     1542          }
     1543        }
     1544        if (newCutoff==-COIN_DBL_MAX) {
     1545          printf("Root analysis says finished\n");
     1546        } else if (n>numberFixedNow_) {
     1547          printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
     1548          numberFixedNow_=n;
     1549        }
    13331550      }
    13341551      if (eventHandler) {
    1335         if (!eventHandler->event(CbcEventHandler::solution)) {
    1336           eventHappened_=true; // exit
    1337         }
    1338       }
     1552        if (!eventHandler->event(CbcEventHandler::solution)) {
     1553          eventHappened_=true; // exit
     1554        }
     1555      }
     1556      lockThread();
    13391557      // Do from deepest
    13401558      tree_->cleanTree(this, newCutoff,bestPossibleObjective_) ;
    13411559      nodeCompare_->newSolution(this) ;
    13421560      nodeCompare_->newSolution(this,continuousObjective_,
    1343                                 continuousInfeasibilities_) ;
     1561                                continuousInfeasibilities_) ;
    13441562      tree_->setComparison(*nodeCompare_) ;
    1345       if (tree_->empty())
     1563      if (tree_->empty()) {
     1564        unlockThread();
    13461565        break; // finished
     1566      }
     1567      unlockThread();
    13471568    }
    13481569    cutoff = getCutoff() ;
    13491570/*
    1350   Periodic activities: Opportunities to
     1571    Periodic activities: Opportunities to
    13511572    + tweak the nodeCompare criteria,
    13521573    + check if we've closed the integrality gap enough to quit,
     
    13541575*/
    13551576    if ((numberNodes_%1000) == 0) {
     1577      lockThread();
    13561578      bool redoTree=nodeCompare_->every1000Nodes(this, numberNodes_) ;
    13571579#ifdef CHECK_CUT_SIZE
     
    13611583      if (redoTree)
    13621584        tree_->setComparison(*nodeCompare_) ;
     1585      unlockThread();
    13631586    }
    13641587    if (saveCompare&&!hotstartSolution_) {
     
    13681591      saveCompare=NULL;
    13691592      // redo tree
     1593      lockThread();
    13701594      tree_->setComparison(*nodeCompare_) ;
     1595      unlockThread();
    13711596    }
    13721597    if ((numberNodes_%printFrequency_) == 0) {
     1598      lockThread();
    13731599      int j ;
    13741600      int nNodes = tree_->size() ;
     
    13791605          bestPossibleObjective_ = node->objectiveValue() ;
    13801606      }
     1607      unlockThread();
    13811608      if (!intParam_[CbcPrinting]) {
    13821609        messageHandler()->message(CBC_STATUS,messages())
     
    14051632      stoppedOnGap_ = true ;
    14061633    }
    1407 
     1634   
    14081635#   ifdef CHECK_NODE_FULL
    14091636    verifyTreeNodes(tree_,*this) ;
     
    14121639    verifyCutCounts(tree_,*this) ;
    14131640#   endif
    1414 
    14151641/*
    14161642  Now we come to the meat of the loop. To create the active subproblem, we'll
     
    14231649    if (!node)
    14241650      continue;
     1651#ifndef CBC_THREAD
     1652    int currentNumberCuts = 0 ;
    14251653    currentNode_=node; // so can be accessed elsewhere
    14261654#ifdef CBC_DEBUG
     
    14321660    if(branchingMethod_)
    14331661      branchingMethod_->saveBranchingObject(node->modifiableBranchingObject());
    1434     bool nodeOnTree=false; // Node has been popped
    14351662    // Say not on optimal path
    14361663    bool onOptimalPath=false;
     
    14601687    CbcNodeInfo * nodeInfo = node->nodeInfo() ;
    14611688    newNode = NULL ;
     1689    int branchesLeft=0;
    14621690    if (!addCuts(node,lastws,numberFixedNow_>numberFixedAtRoot_))
    14631691    { int i ;
     
    14711699        solverCharacteristics_->setBeforeUpper(upperBefore);
    14721700      }
    1473       bool deleteNode ;
    14741701      if (messageHandler()->logLevel()>2)
    14751702        node->modifiableBranchingObject()->print();
    1476       int retCode;
    14771703      if (!useOsiBranching)
    1478         retCode = node->branch(NULL); // old way
     1704        branchesLeft = node->branch(NULL); // old way
    14791705      else
    1480         retCode = node->branch(solver_); // new way
    1481       if (retCode)
    1482       {
     1706        branchesLeft = node->branch(solver_); // new way
     1707      if (branchesLeft) {
    14831708        // set nodenumber correctly
    14841709        node->nodeInfo()->setNodeNumber(numberNodes2_);
     
    14971722        }
    14981723        numberNodes2_++;
    1499         nodeOnTree=true; // back on tree
    1500         deleteNode = false ;
     1724        //nodeOnTree=true; // back on tree
     1725        //deleteNode = false ;
    15011726#       ifdef CHECK_NODE
    15021727        printf("Node %x pushed back on tree - %d left, %d count\n",node,
     
    15041729               nodeInfo->numberPointingToThis()) ;
    15051730#       endif
    1506       }
    1507       else
    1508       { deleteNode = true ;
    1509       if (!nodeInfo->numberBranchesLeft())
    1510         nodeInfo->allBranchesGone(); // can clean up
    1511       }
    1512 
     1731      } else {
     1732        //deleteNode = true ;
     1733        if (!nodeInfo->numberBranchesLeft())
     1734          nodeInfo->allBranchesGone(); // can clean up
     1735      }
    15131736      if ((specialOptions_&1)!=0) {
    15141737        /*
     
    15241747        }
    15251748      }
     1749     
    15261750/*
    15271751  Reoptimize, possibly generating cuts and/or using heuristics to find
     
    15971821      }
    15981822/*
    1599   Check for abort on limits: node count, solution count, time, integrality gap.
    1600 */
    1601       double totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
    1602       if (numberNodes_ < intParam_[CbcMaxNumNode] &&
    1603           numberSolutions_ < intParam_[CbcMaxNumSol] &&
    1604           totalTime < dblParam_[CbcMaximumSeconds] &&
    1605           !stoppedOnGap_&&!eventHappened_)
    1606       {
    1607 /*
    16081823  Are we still feasible? If so, create a node and do the work to attach a
    16091824  branching object, reoptimising as needed if chooseBranch() identifies
     
    16451860          int numberPassesLeft=5;
    16461861          checkingNode=true;
    1647 #if 0
    1648           while (anyAction == -1)
    1649           {
    1650             // Set objective value (not so obvious if NLP etc)
    1651             setObjectiveValue(newNode,node);
    1652             if (numberBeforeTrust_==0 ) {
    1653               anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ;
    1654             } else {
    1655               OsiSolverBranch * branches=NULL;
    1656               anyAction = newNode->chooseDynamicBranch(this,node,branches,numberPassesLeft) ;
    1657               if (anyAction==-3)
    1658                 anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ; // dynamic did nothing
    1659             }
    1660             if (solverCharacteristics_ &&
    1661                 solverCharacteristics_->solutionAddsCuts() && // we are in some OA based bab
    1662                 feasible && (newNode->numberUnsatisfied()==0) //solution has become integer feasible during strong branching
    1663                 )
    1664               {
    1665                 //in the present case we need to check here integer infeasibility if the node is not fathomed we will have to do the loop
    1666                 // again
    1667                 std::cout<<solver_<<std::endl;
    1668                 resolve(solver_);
    1669                 double objval = solver_->getObjValue();
    1670                 setBestSolution(CBC_SOLUTION, objval,
    1671                                 solver_->getColSolution()) ;
    1672                 lastHeuristic_ = NULL;
    1673                 int easy=2;
    1674                 if (!solverCharacteristics_->mipFeasible())//did we prove that the node could be pruned?
    1675                   feasible = false;
    1676                 // Reset the bound now
    1677                 solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
    1678                
    1679                
    1680                 //numberPassesLeft++;
    1681                 solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
    1682                 feasible &= resolve(node ? node->nodeInfo() : NULL,11) != 0 ;
    1683                 solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    1684                 resolved = true ;
    1685                 if (problemFeasibility_->feasible(this,0)<0) {
    1686                   feasible=false; // pretend infeasible
    1687                 }
    1688                 if(feasible)
    1689                   anyAction = -1;
    1690                 else
    1691                   anyAction = -2;
    1692               }
    1693 /*
    1694   Yep, false positives for sure. And no easy way to distinguish honest
    1695   infeasibility from `found a solution and tightened objective target.'
    1696 
    1697             if (onOptimalPath)
    1698               assert (anyAction!=-2); // can be useful but gives false positives on strong
    1699 */
    1700             numberPassesLeft--;
    1701             if (numberPassesLeft<=-1) {
    1702               if (!numberLongStrong_)
    1703                 messageHandler()->message(CBC_WARNING_STRONG,
    1704                                           messages()) << CoinMessageEol ;
    1705               numberLongStrong_++;
    1706             }
    1707             if (anyAction == -1)
    1708             {
    1709               // can do quick optimality check
    1710               int easy=2;
    1711               solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
    1712               //if (solverCharacteristics_->solverType()!=4)
    1713                 feasible = resolve(node ? node->nodeInfo() : NULL,11) != 0 ;
    1714                 //else
    1715                 //feasible = solveWithCuts(cuts,maximumCutPasses_,node);
    1716               solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    1717               resolved = true ;
    1718               if (problemFeasibility_->feasible(this,0)<0) {
    1719                 feasible=false; // pretend infeasible
    1720               }
    1721               if (feasible)
    1722               {
    1723                 // Set objective value (not so obvious if NLP etc)
    1724                 setObjectiveValue(newNode,node);
    1725                 reducedCostFix() ;
    1726                 if (newNode->objectiveValue() >= getCutoff())
    1727                   anyAction=-2;
    1728               }
    1729               else
    1730               { anyAction = -2 ; } } }
    1731           if (anyAction >= 0)
    1732           { if (resolved)
    1733             { bool needValidSolution = (newNode->branchingObject() == NULL) ;
    1734               takeOffCuts(cuts,needValidSolution,NULL) ;
    1735 #             ifdef CHECK_CUT_COUNTS
    1736               { printf("Number of rows after chooseBranch fix (node)"
    1737                        "(active only) %d\n",
    1738                         numberRowsAtContinuous_+numberNewCuts_+
    1739                         numberOldActiveCuts_) ;
    1740                 const CoinWarmStartBasis* debugws =
    1741                   dynamic_cast<const CoinWarmStartBasis*>
    1742                     (solver_->getWarmStart()) ;
    1743                 debugws->print() ;
    1744                 delete debugws ; }
    1745 #             endif
    1746             }
    1747             newNode->createInfo(this,node,lastws,lowerBefore,upperBefore,
    1748                                 numberOldActiveCuts_,numberNewCuts_) ;
    1749             if (newNode->numberUnsatisfied()) {
    1750               maximumDepthActual_ = CoinMax(maximumDepthActual_,newNode->depth());
    1751               newNode->initializeInfo() ;
    1752               newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
    1753                                            whichGenerator_) ; } } }
    1754         else {
    1755           anyAction = -2 ;
    1756           // Reset bound anyway (no harm if not odd)
    1757           solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
    1758           node->nodeInfo()->decrement();
    1759         }
    1760         // May have slipped through i.e. anyAction == 0 and objective above cutoff
    1761         // I think this will screw up cut reference counts if executed.
    1762         // We executed addCuts just above. (lh)
    1763         if ( anyAction >=0 ) {
    1764           assert (newNode);
    1765           if (newNode->objectiveValue() >= getCutoff()) {
    1766             anyAction = -2; // say bad after all
    1767 #ifdef COIN_DEVELOP
    1768             printf("zapping2 CbcNodeInfo %x\n",newNode->nodeInfo()->parent());
    1769 #endif
    1770             // zap parent nodeInfo
    1771             if (newNode->nodeInfo())
    1772               newNode->nodeInfo()->nullParent();
    1773           }
    1774         }
    1775 /*
    1776   If we end up infeasible, we can delete the new node immediately. Since this
    1777   node won't be needing the cuts we collected, decrement the reference counts.
    1778   If we are feasible, then we'll be placing this node into the live set, so
    1779   increment the reference count in the current (parent) nodeInfo.
    1780 */
    1781         if (anyAction == -2)
    1782         { delete newNode ;
    1783           newNode = NULL ;
    1784           // say strong doing well
    1785           if (checkingNode)
    1786             setSpecialOptions(specialOptions_|8);
    1787           for (i = 0 ; i < currentNumberCuts_ ; i++)
    1788           { if (addedCuts_[i])
    1789             { if (!addedCuts_[i]->decrement(1))
    1790                 delete addedCuts_[i] ; } } }
    1791         else
    1792         { nodeInfo->increment() ;
    1793         if ((numberNodes_%20)==0) {
    1794           // say strong not doing as well
    1795           setSpecialOptions(specialOptions_&~8);
    1796         }
    1797 #else
    17981862        OsiSolverBranch * branches=NULL;
    17991863        // point to useful information
     
    18231887          }
    18241888        }
    1825 #endif
    18261889        }
    18271890/*
     
    18661929                generate=false; // only special cuts
    18671930              if (generate) {
    1868                 generator_[i]->generateCuts(theseCuts,true,NULL) ;
     1931                generator_[i]->generateCuts(theseCuts,true,solver_,NULL) ;
    18691932                int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    18701933                if (numberRowCutsAfter) {
     
    19131976                heurValue = saveValue ; } }
    19141977            if (found >= 0) {
     1978              lastHeuristic_ = heuristic_[found];
    19151979              setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
    1916               lastHeuristic_ = heuristic_[found];
    19171980            }
    19181981            delete [] newSolution ;
     
    19642027  set.
    19652028*/
    1966         if (deleteNode)
    1967           delete node ; }
    1968 /*
    1969   End of the non-abort actions. The next block of code is executed if we've
    1970   aborted because we hit one of the limits. Clean up by deleting the live set
    1971   and break out of the node processing loop. Note that on an abort, node may
    1972   have been pushed back onto the tree for further processing, in which case
    1973   it'll be deleted in cleanTree. We need to check.
    1974 */
     2029      if (branchesLeft)
     2030      {
     2031      }
    19752032      else
    19762033      {
    1977         if (tree_->size())
    1978           tree_->cleanTree(this,-COIN_DBL_MAX,bestPossibleObjective_) ;
    1979         delete nextRowCut_;
    1980         // We need to get rid of node if is has already been popped from tree
    1981         if (!nodeOnTree&&!stoppedOnGap_&&node!=rootNode)
    1982           delete node;
    1983         if (stoppedOnGap_)
    1984         { messageHandler()->message(CBC_GAP,messages())
    1985             << bestObjective_-bestPossibleObjective_
    1986             << dblParam_[CbcAllowableGap]
    1987             << dblParam_[CbcAllowableFractionGap]*100.0
    1988             << CoinMessageEol ;
    1989         secondaryStatus_ = 2;
    1990           status_ = 0 ; }
    1991         else
    1992         if (isNodeLimitReached())
    1993         { handler_->message(CBC_MAXNODES,messages_) << CoinMessageEol ;
    1994         secondaryStatus_ = 3;
    1995           status_ = 1 ; }
    1996         else
    1997         if (totalTime >= dblParam_[CbcMaximumSeconds])
    1998         { handler_->message(CBC_MAXTIME,messages_) << CoinMessageEol ;
    1999         secondaryStatus_ = 4;
    2000           status_ = 1 ; }
    2001         else
    2002         if (eventHappened_)
    2003         { handler_->message(CBC_EVENT,messages_) << CoinMessageEol ;
    2004         secondaryStatus_ = 5;
    2005           status_ = 5 ; }
    2006         else
    2007         { handler_->message(CBC_MAXSOLS,messages_) << CoinMessageEol ;
    2008         secondaryStatus_ = 6;
    2009           status_ = 1 ; }
    2010         break ; }
     2034        if (!nodeInfo->numberBranchesLeft())
     2035          nodeInfo->allBranchesGone(); // can clean up
     2036        delete node ; }
     2037    } else {
     2038      // add cuts found to be infeasible (on bound)!
     2039      abort();
     2040      delete node;
     2041    }
    20112042/*
    20122043  Delete cuts to get back to the original system.
     
    20222053        { delRows[i] = i+numberRowsAtContinuous_ ; }
    20232054        solver_->deleteRows(numberToDelete,delRows) ;
    2024         delete [] delRows ; } }
    2025 /*
    2026   This node fathomed when addCuts atttempted to revive it. Toss it.
    2027 */
    2028     else
    2029       { delete node ; } }
     2055        delete [] delRows ; }
     2056#else // end of not CBC_THREAD
     2057      if (!numberThreads_) {
     2058        doOneNode(this,node,createdNode);
     2059      } else {
     2060        threadStats[0]++;
     2061        //need to think
     2062        int iThread;
     2063        // Start one off if any available
     2064        for (iThread=0;iThread<numberThreads_;iThread++) {
     2065          if (threadInfo[iThread].returnCode==-1)
     2066            break;
     2067        }
     2068        if (iThread<numberThreads_) {
     2069          threadInfo[iThread].node=node;
     2070          assert (threadInfo[iThread].returnCode==-1);
     2071          // say in use
     2072          threadInfo[iThread].returnCode=0;
     2073          threadModel[iThread]->moveToModel(this,0);
     2074          pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     2075          threadCount[iThread]++;
     2076        }
     2077        lockThread();
     2078        locked=true;
     2079        // see if any finished
     2080        for (iThread=0;iThread<numberThreads_;iThread++) {
     2081          if (threadInfo[iThread].returnCode>0)
     2082            break;
     2083        }
     2084        unlockThread();
     2085        locked=false;
     2086        if (iThread<numberThreads_) {
     2087          threadModel[iThread]->moveToModel(this,1);
     2088          assert (threadInfo[iThread].returnCode==1);
     2089          // say available
     2090          threadInfo[iThread].returnCode=-1;
     2091          // carry on
     2092          threadStats[3]++;
     2093        } else {
     2094          // Start one off if any available
     2095          for (iThread=0;iThread<numberThreads_;iThread++) {
     2096            if (threadInfo[iThread].returnCode==-1)
     2097              break;
     2098          }
     2099          if (iThread<numberThreads_) {
     2100            lockThread();
     2101            locked=true;
     2102            // If any on tree get
     2103            if (!tree_->empty()) {
     2104              //node = tree_->bestNode(cutoff) ;
     2105              //assert (node);
     2106              threadStats[1]++;
     2107              continue; // ** get another node
     2108            }
     2109            unlockThread();
     2110            locked=false;
     2111          }
     2112          // wait (for debug could sleep and use test)
     2113          bool finished=false;
     2114          while (!finished) {
     2115#ifdef CONDITION_WAIT
     2116            pthread_mutex_lock(&condition_mutex);
     2117            struct timespec absTime;
     2118            clock_gettime(CLOCK_REALTIME,&absTime);
     2119            double time = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     2120            absTime.tv_nsec += 1000000; // millisecond
     2121            if (absTime.tv_nsec>=1000000000) {
     2122              absTime.tv_nsec -= 1000000000;
     2123              absTime.tv_sec++;
     2124            }
     2125            pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     2126            clock_gettime(CLOCK_REALTIME,&absTime);
     2127            double time2 = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     2128            timeWaiting += time2-time;
     2129            pthread_mutex_unlock(&condition_mutex);
     2130#else
     2131            struct timespec moreTime;
     2132            moreTime.tv_nsec = 100;
     2133            moreTime.tv_sec = 0;
     2134            nanosleep(&moreTime,NULL);
     2135#endif
     2136            for (iThread=0;iThread<numberThreads_;iThread++) {
     2137              if (threadInfo[iThread].returnCode>0) {
     2138                finished=true;
     2139                break;
     2140              } else if (threadInfo[iThread].returnCode==0) {
     2141                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     2142              }
     2143            }
     2144          }
     2145          assert (iThread<numberThreads_);
     2146          threadModel[iThread]->moveToModel(this,1);
     2147          node = threadInfo[iThread].node;
     2148          threadInfo[iThread].node=NULL;
     2149          assert (threadInfo[iThread].returnCode==1);
     2150          // say available
     2151          threadInfo[iThread].returnCode=-1;
     2152          // carry on
     2153          threadStats[2]++;
     2154        }
     2155      }
     2156      //lastDepth=node->depth();
     2157      //lastUnsatisfied=node->numberUnsatisfied();
     2158#endif // end of CBC_THREAD
     2159  }
     2160#ifdef CBC_THREAD
     2161  if (numberThreads_) {
     2162    //printf("stats ");
     2163    //for (unsigned int j=0;j<sizeof(threadStats)/sizeof(int);j++)
     2164    //printf("%d ",threadStats[j]);
     2165    //printf("\n");
     2166    int i;
     2167    // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
     2168    double time=0.0;
     2169    for (i=0;i<numberThreads_;i++)
     2170      time += threadInfo[i].timeInThread;
     2171    bool goodTimer = time<(CoinCpuTime() - dblParam_[CbcStartSeconds]);
     2172    for (i=0;i<numberThreads_;i++) {
     2173      pthread_cond_signal(threadInfo[i].condition2); // unlock
     2174      while (threadInfo[i].returnCode==0) {
     2175        struct timespec moreTime;
     2176        moreTime.tv_nsec = 10000;
     2177        moreTime.tv_sec = 0;
     2178        nanosleep(&moreTime,NULL);
     2179      }
     2180      threadModel[i]->numberThreads_=0; // say exit
     2181      threadInfo[i].returnCode=0;
     2182      pthread_cond_signal(threadInfo[i].condition2); // unlock
     2183      pthread_join(threadId[i],NULL);
     2184      threadModel[i]->moveToModel(this,2);
     2185      pthread_mutex_destroy (threadInfo[i].mutex2);
     2186      pthread_cond_destroy (threadInfo[i].condition2);
     2187      assert (threadInfo[i].numberTimesLocked==threadInfo[i].numberTimesUnlocked);
     2188      handler_->message(CBC_THREAD_STATS,messages_)
     2189        <<"Thread";
     2190      handler_->printing(true)
     2191        <<i<<threadCount[i]<<threadInfo[i].timeWaitingToStart;
     2192      handler_->printing(goodTimer)<<threadInfo[i].timeInThread;
     2193      handler_->printing(false)<<0.0;
     2194      handler_->printing(true)<<threadInfo[i].numberTimesLocked
     2195        <<threadInfo[i].timeLocked<<threadInfo[i].timeWaitingToLock
     2196        <<CoinMessageEol;
     2197    }
     2198    assert (threadInfo[numberThreads_].numberTimesLocked==threadInfo[numberThreads_].numberTimesUnlocked);
     2199    handler_->message(CBC_THREAD_STATS,messages_)
     2200      <<"Main thread";
     2201    handler_->printing(false)<<0<<0<<0.0;
     2202    handler_->printing(false)<<0.0;
     2203    handler_->printing(true)<<timeWaiting;
     2204    handler_->printing(true)<<threadInfo[numberThreads_].numberTimesLocked
     2205      <<threadInfo[numberThreads_].timeLocked<<threadInfo[numberThreads_].timeWaitingToLock
     2206      <<CoinMessageEol;
     2207    pthread_mutex_destroy (&mutex);
     2208    pthread_cond_destroy (&condition_main);
     2209    pthread_mutex_destroy (&condition_mutex);
     2210    // delete models (here in case some point to others)
     2211    for (i=0;i<numberThreads_;i++) {
     2212      delete threadModel[i];
     2213    }
     2214    delete [] mutex2;
     2215    delete [] condition2;
     2216    delete [] threadId;
     2217    delete [] threadInfo;
     2218    delete [] threadModel;
     2219    delete [] threadCount;
     2220    mutex_=NULL;
     2221  }
     2222#endif
     2223/*
     2224  End of the non-abort actions. The next block of code is executed if we've
     2225  aborted because we hit one of the limits. Clean up by deleting the live set
     2226  and break out of the node processing loop. Note that on an abort, node may
     2227  have been pushed back onto the tree for further processing, in which case
     2228  it'll be deleted in cleanTree. We need to check.
     2229*/
     2230    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
     2231        numberSolutions_ < intParam_[CbcMaxNumSol] &&
     2232        totalTime < dblParam_[CbcMaximumSeconds] &&
     2233        !stoppedOnGap_&&!eventHappened_)) {
     2234      if (tree_->size())
     2235        tree_->cleanTree(this,-COIN_DBL_MAX,bestPossibleObjective_) ;
     2236      delete nextRowCut_;
     2237      if (stoppedOnGap_)
     2238        { messageHandler()->message(CBC_GAP,messages())
     2239          << bestObjective_-bestPossibleObjective_
     2240          << dblParam_[CbcAllowableGap]
     2241          << dblParam_[CbcAllowableFractionGap]*100.0
     2242          << CoinMessageEol ;
     2243        secondaryStatus_ = 2;
     2244        status_ = 0 ; }
     2245        else
     2246          if (isNodeLimitReached())
     2247            { handler_->message(CBC_MAXNODES,messages_) << CoinMessageEol ;
     2248            secondaryStatus_ = 3;
     2249            status_ = 1 ; }
     2250          else
     2251        if (totalTime >= dblParam_[CbcMaximumSeconds])
     2252          { handler_->message(CBC_MAXTIME,messages_) << CoinMessageEol ;
     2253          secondaryStatus_ = 4;
     2254          status_ = 1 ; }
     2255        else
     2256          if (eventHappened_)
     2257            { handler_->message(CBC_EVENT,messages_) << CoinMessageEol ;
     2258            secondaryStatus_ = 5;
     2259            status_ = 5 ; }
     2260          else
     2261            { handler_->message(CBC_MAXSOLS,messages_) << CoinMessageEol ;
     2262            secondaryStatus_ = 6;
     2263            status_ = 1 ; }
     2264    }
    20302265/*
    20312266  That's it, we've exhausted the search tree, or broken out of the loop because
     
    24642699  subTreeModel_(NULL),
    24652700  numberStoppedSubTrees_(0),
     2701  mutex_(NULL),
    24662702  presolve_(0),
    24672703  numberStrong_(5),
     
    25112747  searchStrategy_(-1),
    25122748  numberStrongIterations_(0),
    2513   resolveAfterTakeOffCuts_(true)
     2749  resolveAfterTakeOffCuts_(true),
     2750  numberThreads_(0),
     2751  threadMode_(0)
    25142752{
    25152753  memset(intParam_,0,sizeof(intParam_));
     
    25942832  subTreeModel_(NULL),
    25952833  numberStoppedSubTrees_(0),
     2834  mutex_(NULL),
    25962835  presolve_(0),
    25972836  numberStrong_(5),
     
    26412880  searchStrategy_(-1),
    26422881  numberStrongIterations_(0),
    2643   resolveAfterTakeOffCuts_(true)
     2882  resolveAfterTakeOffCuts_(true),
     2883  numberThreads_(0),
     2884  threadMode_(0)
    26442885{
    26452886  memset(intParam_,0,sizeof(intParam_));
     
    28193060  subTreeModel_(rhs.subTreeModel_),
    28203061  numberStoppedSubTrees_(rhs.numberStoppedSubTrees_),
     3062  mutex_(NULL),
    28213063  presolve_(rhs.presolve_),
    28223064  numberStrong_(rhs.numberStrong_),
     
    28553097  searchStrategy_(rhs.searchStrategy_),
    28563098  numberStrongIterations_(rhs.numberStrongIterations_),
    2857   resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_)
     3099  resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_),
     3100  numberThreads_(rhs.numberThreads_),
     3101  threadMode_(rhs.threadMode_)
    28583102{
    28593103  memcpy(intParam_,rhs.intParam_,sizeof(intParam_));
     
    29073151      object_ = new OsiObject * [numberObjects_];
    29083152      int i;
    2909       for (i=0;i<numberObjects_;i++)
     3153      for (i=0;i<numberObjects_;i++) {
    29103154        object_[i]=(rhs.object_[i])->clone();
     3155        CbcObject * obj = dynamic_cast <CbcObject *>(object_[i]) ;
     3156        assert (obj);
     3157        obj->setModel(this);
     3158      }
    29113159    } else {
    29123160      object_=NULL;
     
    31053353    subTreeModel_ = rhs.subTreeModel_;
    31063354    numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
     3355    mutex_ = NULL;
    31073356    presolve_ = rhs.presolve_;
    31083357    numberStrong_ = rhs.numberStrong_;
     
    31563405    numberNewCuts_ = rhs.numberNewCuts_;
    31573406    resolveAfterTakeOffCuts_=rhs.resolveAfterTakeOffCuts_;
     3407    numberThreads_ = rhs.numberThreads_;
     3408    threadMode_ = rhs.threadMode_;
    31583409    sizeMiniTree_ = rhs.sizeMiniTree_;
    31593410    searchStrategy_ = rhs.searchStrategy_;
     
    36863937*/
    36873938  currentNumberCuts_=currentNumberCuts;
    3688   if (currentNumberCuts >= maximumNumberCuts_) {
     3939  if (currentNumberCuts > maximumNumberCuts_) {
    36893940    maximumNumberCuts_ = currentNumberCuts;
    36903941    delete [] addedCuts_;
     
    37844035  reconstructed basis in the solver.
    37854036*/
    3786   if (node->objectiveValue() < cutoff)
     4037  if (node->objectiveValue() < cutoff||numberThreads_)
    37874038  {
    37884039#   ifdef CBC_CHECK_BASIS
     
    38644115  set. Adjust the cut reference counts to reflect that we no longer need to
    38654116  explore the remaining branch arms, hence they will no longer reference any
    3866   cuts. Cuts whose reference count falls to zero are deleted.
     4117  cuts. Cuts whose reference count falls to zero are deleted. 
    38674118*/
    38684119  else
    38694120  { int i;
    3870     int numberLeft = nodeInfo->numberBranchesLeft();
    3871     for (i = 0 ; i < currentNumberCuts ; i++)
    3872     { if (addedCuts_[i])
    3873       { if (!addedCuts_[i]->decrement(numberLeft))
    3874         { delete addedCuts_[i];
    3875           addedCuts_[i] = NULL; } } }
     4121    if (currentNumberCuts) {
     4122      lockThread();
     4123      int numberLeft = nodeInfo->numberBranchesLeft();
     4124      for (i = 0 ; i < currentNumberCuts ; i++)
     4125        { if (addedCuts_[i])
     4126          { if (!addedCuts_[i]->decrement(numberLeft))
     4127            { delete addedCuts_[i];
     4128            addedCuts_[i] = NULL; } } }
     4129      unlockThread();
     4130    }
    38764131    return 1 ; }
    38774132}
     
    39884243    saveClpOptions = clpSolver->specialOptions();
    39894244# endif
     4245#ifdef CBC_THREAD
     4246  CbcModel ** threadModel = NULL;
     4247  pthread_t * threadId = NULL;
     4248  pthread_cond_t condition_main;
     4249  pthread_mutex_t condition_mutex;
     4250  pthread_mutex_t * mutex2 = NULL;
     4251  pthread_cond_t * condition2 = NULL;
     4252  threadStruct * threadInfo = NULL;
     4253  void * saveMutex = NULL;
     4254  if (numberThreads_&&(threadMode_&2)!=0&&!numberNodes_) {
     4255    threadId = new pthread_t [numberThreads_];
     4256    pthread_cond_init(&condition_main,NULL);
     4257    pthread_mutex_init(&condition_mutex,NULL);
     4258    threadModel = new CbcModel * [numberThreads_];
     4259    threadInfo = new threadStruct [numberThreads_+1];
     4260    mutex2 = new pthread_mutex_t [numberThreads_];
     4261    condition2 = new pthread_cond_t [numberThreads_];
     4262    saveMutex = mutex_;
     4263    for (int i=0;i<numberThreads_;i++) {
     4264      pthread_mutex_init(mutex2+i,NULL);
     4265      pthread_cond_init(condition2+i,NULL);
     4266      threadId[i]=0;
     4267      threadModel[i]=new CbcModel;
     4268      threadModel[i]->generator_ = new CbcCutGenerator * [1];
     4269      delete threadModel[i]->solver_;
     4270      threadModel[i]->solver_=NULL;
     4271      threadModel[i]->numberThreads_=numberThreads_;
     4272      mutex_ = (void *) (threadInfo+i);
     4273      threadInfo[i].thisModel=(CbcModel *) threadModel[i];
     4274      threadInfo[i].baseModel=this;
     4275      threadInfo[i].threadIdOfBase=pthread_self();
     4276      threadInfo[i].mutex2=mutex2+i;
     4277      threadInfo[i].condition2=condition2+i;
     4278      threadInfo[i].returnCode=-1;
     4279      pthread_create(threadId+i,NULL,doCutsThread,threadInfo+i);
     4280    }
     4281    // Do a partial one for base model
     4282    threadInfo[numberThreads_].baseModel=this;
     4283    mutex_ = (void *) (threadInfo+numberThreads_);
     4284    threadInfo[numberThreads_].condition2=&condition_main;
     4285    threadInfo[numberThreads_].mutex2=&condition_mutex;
     4286  }
     4287#endif
    39904288  bool feasible = true ;
    39914289  int lastNumberCuts = 0 ;
     
    40264324  //printf("zero iterations on first solve of branch\n");
    40274325#endif
    4028   if (node&&!node->nodeInfo()->numberBranchesLeft())
     4326  if (node&&node->nodeInfo()&&!node->nodeInfo()->numberBranchesLeft())
    40294327    node->nodeInfo()->allBranchesGone(); // can clean up
    40304328  feasible = returnCode  != 0 ;
     
    42444542      whichGenerator_[numberViolated++]=-2;
    42454543    }
    4246     double * newSolution = new double [numberColumns] ;
    4247     double heuristicValue = getCutoff() ;
    4248     int found = -1; // no solution found
    42494544
    42504545    // reset probing info
    42514546    if (probingInfo_)
    42524547      probingInfo_->initializeFixing();
    4253     for (int i = 0;i<numberCutGenerators_+numberHeuristics_;i++) {
    4254       int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
    4255       int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
    4256       if (i<numberCutGenerators_) {
    4257         bool generate = generator_[i]->normal();
    4258         // skip if not optimal and should be (maybe a cut generator has fixed variables)
    4259         if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
    4260           generate=false;
    4261         if (generator_[i]->switchedOff())
    4262           generate=false;;
     4548    int i;
     4549    if ((threadMode_&2)==0||numberNodes_) {
     4550      for (i = 0;i<numberCutGenerators_;i++) {
     4551        int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
     4552        int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
     4553        bool generate = generator_[i]->normal();
     4554        // skip if not optimal and should be (maybe a cut generator has fixed variables)
     4555        if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     4556          generate=false;
     4557        if (generator_[i]->switchedOff())
     4558          generate=false;;
    42634559        if (generate) {
    42644560          bool mustResolve =
    4265             generator_[i]->generateCuts(theseCuts,fullScan,node) ;
     4561            generator_[i]->generateCuts(theseCuts,fullScan,solver_,node) ;
    42664562          int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    4267           if(numberRowCutsBefore < numberRowCutsAfter &&
    4268              generator_[i]->mustCallAgain())
    4269             keepGoing=true; // say must go round
     4563          if(numberRowCutsBefore < numberRowCutsAfter &&
     4564             generator_[i]->mustCallAgain())
     4565            keepGoing=true; // say must go round
    42704566          // Check last cut to see if infeasible
    4271           if(numberRowCutsBefore < numberRowCutsAfter) {
     4567          if(numberRowCutsBefore < numberRowCutsAfter) {
    42724568            const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter-1) ;
    42734569            if (thisCut->lb()>thisCut->ub()) {
     
    42774573          }
    42784574#ifdef CBC_DEBUG
    4279           {
    4280             int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    4281             int k ;
    4282             for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
    4283               OsiRowCut thisCut = theseCuts.rowCut(k) ;
    4284               /* check size of elements.
    4285                  We can allow smaller but this helps debug generators as it
    4286                  is unsafe to have small elements */
    4287               int n=thisCut.row().getNumElements();
    4288               const int * column = thisCut.row().getIndices();
    4289               const double * element = thisCut.row().getElements();
    4290               //assert (n);
    4291               for (int i=0;i<n;i++) {
    4292                 double value = element[i];
    4293                 assert(fabs(value)>1.0e-12&&fabs(value)<1.0e20);
    4294               }
    4295             }
    4296           }
     4575          {
     4576            int k ;
     4577            for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4578              OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4579              /* check size of elements.
     4580                 We can allow smaller but this helps debug generators as it
     4581                 is unsafe to have small elements */
     4582              int n=thisCut.row().getNumElements();
     4583              const int * column = thisCut.row().getIndices();
     4584              const double * element = thisCut.row().getElements();
     4585              //assert (n);
     4586              for (int i=0;i<n;i++) {
     4587                double value = element[i];
     4588                assert(fabs(value)>1.0e-12&&fabs(value)<1.0e20);
     4589              }
     4590            }
     4591          }
    42974592#endif
    42984593          if (mustResolve) {
    4299             int returncode = resolve(node ? node->nodeInfo() : NULL,2);
    4300             feasible = returnCode  != 0 ;
    4301             if (returncode<0)
    4302               numberTries=0;
    4303             if ((specialOptions_&1)!=0) {
    4304               debugger = solver_->getRowCutDebugger() ;
    4305               if (debugger)
    4306                 onOptimalPath = (debugger->onOptimalPath(*solver_)) ;
    4307               else
    4308                 onOptimalPath=false;
    4309               if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
    4310                 assert(feasible) ;
    4311             }
     4594            int returncode = resolve(node ? node->nodeInfo() : NULL,2);
     4595            feasible = returnCode  != 0 ;
     4596            if (returncode<0)
     4597              numberTries=0;
     4598            if ((specialOptions_&1)!=0) {
     4599              debugger = solver_->getRowCutDebugger() ;
     4600              if (debugger)
     4601                onOptimalPath = (debugger->onOptimalPath(*solver_)) ;
     4602              else
     4603                onOptimalPath=false;
     4604              if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
     4605                assert(feasible) ;
     4606            }
    43124607            if (!feasible)
    43134608              break ;
    43144609          }
    43154610        }
     4611        int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
     4612        int numberColumnCutsAfter = theseCuts.sizeColCuts() ;
     4613       
     4614        if ((specialOptions_&1)!=0) {
     4615          if (onOptimalPath) {
     4616            int k ;
     4617            for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4618              OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4619              if(debugger->invalidCut(thisCut)) {
     4620                solver_->writeMps("badCut");
     4621#ifdef NDEBUG
     4622                printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
     4623                       i,generator_[i]->cutGeneratorName(),k-numberRowCutsBefore);
     4624                abort();
     4625#endif
     4626              }
     4627              assert(!debugger->invalidCut(thisCut)) ;
     4628            }
     4629          }
     4630        }
     4631/*
     4632  The cut generator has done its thing, and maybe it generated some
     4633  cuts.  Do a bit of bookkeeping: load
     4634  whichGenerator[i] with the index of the generator responsible for a cut,
     4635  and place cuts flagged as global in the global cut pool for the model.
     4636
     4637  lastNumberCuts is the sum of cuts added in previous iterations; it's the
     4638  offset to the proper starting position in whichGenerator.
     4639*/
     4640        int numberBefore =
     4641          numberRowCutsBefore+numberColumnCutsBefore+lastNumberCuts ;
     4642        int numberAfter =
     4643          numberRowCutsAfter+numberColumnCutsAfter+lastNumberCuts ;
     4644        // possibly extend whichGenerator
     4645        resizeWhichGenerator(numberBefore, numberAfter);
     4646        int j ;
     4647        if (fullScan) {
     4648          // counts
     4649          countColumnCuts[i] += numberColumnCutsAfter-numberColumnCutsBefore ;
     4650        }
     4651        countRowCuts[i] += numberRowCutsAfter-numberRowCutsBefore ;
     4652       
     4653        for (j = numberRowCutsBefore;j<numberRowCutsAfter;j++) {
     4654          whichGenerator_[numberBefore++] = i ;
     4655          const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
     4656          if (thisCut->lb()>thisCut->ub())
     4657            violated=-2; // sub-problem is infeasible
     4658          if (thisCut->globallyValid()) {
     4659            // add to global list
     4660            OsiRowCut newCut(*thisCut);
     4661            newCut.setGloballyValid(2);
     4662            newCut.mutableRow().setTestForDuplicateIndex(false);
     4663            globalCuts_.insert(newCut) ;
     4664          }
     4665        }
     4666        for (j = numberColumnCutsBefore;j<numberColumnCutsAfter;j++) {
     4667          whichGenerator_[numberBefore++] = i ;
     4668          const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
     4669          if (thisCut->globallyValid()) {
     4670            // add to global list
     4671            OsiColCut newCut(*thisCut);
     4672            newCut.setGloballyValid(2);
     4673            globalCuts_.insert(newCut) ;
     4674          }
     4675        }
     4676      }
     4677      // Add in any violated saved cuts
     4678      if (!theseCuts.sizeRowCuts()&&!theseCuts.sizeColCuts()) {
     4679        int numberOld = theseCuts.sizeRowCuts();
     4680        int numberCuts = slackCuts.sizeRowCuts() ;
     4681        int i;
     4682        // possibly extend whichGenerator
     4683        resizeWhichGenerator(numberOld, numberOld+numberCuts);
     4684        for ( i = 0;i<numberCuts;i++) {
     4685          const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
     4686          if (thisCut->violated(cbcColSolution_)>100.0*primalTolerance) {
     4687            if (messageHandler()->logLevel()>2)
     4688              printf("Old cut added - violation %g\n",
     4689                     thisCut->violated(cbcColSolution_)) ;
     4690            whichGenerator_[numberOld++]=-1;
     4691            theseCuts.insert(*thisCut) ;
     4692          }
     4693        }
     4694      }
     4695    } else {
     4696      // do cuts independently
     4697      OsiCuts * eachCuts = new OsiCuts [numberCutGenerators_];;
     4698#ifdef CBC_THREAD
     4699      if (!threadModel) {
     4700#endif
     4701        // generate cuts
     4702        for (i = 0;i<numberCutGenerators_;i++) {
     4703          bool generate = generator_[i]->normal();
     4704          // skip if not optimal and should be (maybe a cut generator has fixed variables)
     4705          if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     4706            generate=false;
     4707          if (generator_[i]->switchedOff())
     4708            generate=false;;
     4709          if (generate)
     4710            generator_[i]->generateCuts(eachCuts[i],fullScan,solver_,node) ;
     4711        }
     4712#ifdef CBC_THREAD
    43164713      } else {
     4714        for (i=0;i<numberThreads_;i++) {
     4715          // set solver here after cloning
     4716          threadModel[i]->solver_=solver_->clone();
     4717          threadModel[i]->numberNodes_ = (fullScan) ? 1 : 0;
     4718        }
     4719        // generate cuts
     4720        for (i = 0;i<numberCutGenerators_;i++) {
     4721          bool generate = generator_[i]->normal();
     4722          // skip if not optimal and should be (maybe a cut generator has fixed variables)
     4723          if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     4724            generate=false;
     4725          if (generator_[i]->switchedOff())
     4726            generate=false;;
     4727          if (generate) {
     4728            bool finished=false;
     4729            int iThread=-1;
     4730            // see if any available
     4731            for (iThread=0;iThread<numberThreads_;iThread++) {
     4732              if (threadInfo[iThread].returnCode) {
     4733                finished=true;
     4734                break;
     4735              } else if (threadInfo[iThread].returnCode==0) {
     4736#ifdef CONDITION_WAIT
     4737                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4738#endif
     4739              }
     4740            }
     4741            while (!finished) {
     4742#ifdef CONDITION_WAIT
     4743              pthread_mutex_lock(&condition_mutex);
     4744              struct timespec absTime;
     4745              clock_gettime(CLOCK_REALTIME,&absTime);
     4746              absTime.tv_nsec += 1000000; // millisecond
     4747              if (absTime.tv_nsec>=1000000000) {
     4748                absTime.tv_nsec -= 1000000000;
     4749                absTime.tv_sec++;
     4750              }
     4751              pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     4752              pthread_mutex_unlock(&condition_mutex);
     4753#else
     4754              struct timespec moreTime;
     4755              moreTime.tv_nsec = 100;
     4756              moreTime.tv_sec = 0 ;
     4757              nanosleep(&moreTime,NULL);
     4758#endif
     4759              for (iThread=0;iThread<numberThreads_;iThread++) {
     4760                if (threadInfo[iThread].returnCode>0) {
     4761                  finished=true;
     4762                  break;
     4763                } else if (threadInfo[iThread].returnCode==0) {
     4764#ifdef CONDITION_WAIT
     4765                  pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4766#endif
     4767                }
     4768              }
     4769            }
     4770            assert (iThread<numberThreads_);
     4771            assert (threadInfo[iThread].returnCode);
     4772            threadModel[iThread]->generator_[0]=generator_[i];
     4773            threadModel[iThread]->object_ = (OsiObject **) (eachCuts+i);
     4774            // allow to start
     4775            threadInfo[iThread].returnCode=0;
     4776#ifdef CONDITION_WAIT
     4777            pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4778#endif
     4779          }
     4780        }
     4781        // wait
     4782        for (int iThread=0;iThread<numberThreads_;iThread++) {
     4783          if (threadInfo[iThread].returnCode==0) {
     4784            bool finished=false;
     4785#ifdef CONDITION_WAIT
     4786            pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4787#endif
     4788            while (!finished) {
     4789#ifdef CONDITION_WAIT
     4790              pthread_mutex_lock(&condition_mutex);
     4791              struct timespec absTime;
     4792              clock_gettime(CLOCK_REALTIME,&absTime);
     4793              absTime.tv_nsec += 1000000; // millisecond
     4794              if (absTime.tv_nsec>=1000000000) {
     4795                absTime.tv_nsec -= 1000000000;
     4796                absTime.tv_sec++;
     4797              }
     4798              pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     4799              pthread_mutex_unlock(&condition_mutex);
     4800#else
     4801              struct timespec moreTime;
     4802              moreTime.tv_nsec = 100;
     4803              moreTime.tv_sec = 0;
     4804              nanosleep(&moreTime,NULL);
     4805#endif
     4806              if (threadInfo[iThread].returnCode>0) {
     4807                finished=true;
     4808                break;
     4809              } else if (threadInfo[iThread].returnCode==0) {
     4810#ifdef CONDITION_WAIT
     4811                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4812#endif
     4813              }
     4814            }
     4815          }
     4816          assert (threadInfo[iThread].returnCode);
     4817          // say available
     4818          threadInfo[iThread].returnCode=-1;
     4819          delete threadModel[iThread]->solver_;
     4820          threadModel[iThread]->solver_=NULL;
     4821        }
     4822      }
     4823#endif
     4824      // Now put together
     4825      for (i = 0;i<numberCutGenerators_;i++) {
     4826        // add column cuts
     4827        int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
     4828        int numberColumnCuts = eachCuts[i].sizeColCuts();
     4829        int numberColumnCutsAfter = numberColumnCutsBefore
     4830          + numberColumnCuts;
     4831        int j;
     4832        for (j=0;j<numberColumnCuts;j++) {
     4833          theseCuts.insert(eachCuts[i].colCut(j));
     4834        }
     4835        int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
     4836        int numberRowCuts = eachCuts[i].sizeRowCuts();
     4837        int numberRowCutsAfter = numberRowCutsBefore
     4838          + numberRowCuts;
     4839        if (numberRowCuts) {
     4840          for (j=0;j<numberRowCuts;j++) {
     4841            theseCuts.insert(eachCuts[i].rowCut(j));
     4842          }
     4843          if (generator_[i]->mustCallAgain())
     4844            keepGoing=true; // say must go round
     4845          // Check last cut to see if infeasible
     4846          const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter-1) ;
     4847          if (thisCut->lb()>thisCut->ub()) {
     4848            feasible = false; // sub-problem is infeasible
     4849            break;
     4850          }
     4851        }
     4852#ifdef CBC_DEBUG
     4853        {
     4854          int k ;
     4855          for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4856            OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4857            /* check size of elements.
     4858               We can allow smaller but this helps debug generators as it
     4859               is unsafe to have small elements */
     4860            int n=thisCut.row().getNumElements();
     4861            const int * column = thisCut.row().getIndices();
     4862            const double * element = thisCut.row().getElements();
     4863            //assert (n);
     4864            for (int i=0;i<n;i++) {
     4865              double value = element[i];
     4866              assert(fabs(value)>1.0e-12&&fabs(value)<1.0e20);
     4867            }
     4868          }
     4869        }
     4870#endif
     4871        if ((specialOptions_&1)!=0) {
     4872          if (onOptimalPath) {
     4873            int k ;
     4874            for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4875              OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4876              if(debugger->invalidCut(thisCut)) {
     4877                solver_->writeMps("badCut");
     4878#ifdef NDEBUG
     4879                printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
     4880                       i,generator_[i]->cutGeneratorName(),k-numberRowCutsBefore);
     4881                abort();
     4882#endif
     4883              }
     4884              assert(!debugger->invalidCut(thisCut)) ;
     4885            }
     4886          }
     4887        }
     4888/*
     4889  The cut generator has done its thing, and maybe it generated some
     4890  cuts.  Do a bit of bookkeeping: load
     4891  whichGenerator[i] with the index of the generator responsible for a cut,
     4892  and place cuts flagged as global in the global cut pool for the model.
     4893
     4894  lastNumberCuts is the sum of cuts added in previous iterations; it's the
     4895  offset to the proper starting position in whichGenerator.
     4896*/
     4897        int numberBefore =
     4898          numberRowCutsBefore+numberColumnCutsBefore+lastNumberCuts ;
     4899        int numberAfter =
     4900          numberRowCutsAfter+numberColumnCutsAfter+lastNumberCuts ;
     4901        // possibly extend whichGenerator
     4902        resizeWhichGenerator(numberBefore, numberAfter);
     4903        if (fullScan) {
     4904          // counts
     4905          countColumnCuts[i] += numberColumnCutsAfter-numberColumnCutsBefore ;
     4906        }
     4907        countRowCuts[i] += numberRowCutsAfter-numberRowCutsBefore ;
     4908       
     4909        for (j = numberRowCutsBefore;j<numberRowCutsAfter;j++) {
     4910          whichGenerator_[numberBefore++] = i ;
     4911          const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
     4912          if (thisCut->lb()>thisCut->ub())
     4913            violated=-2; // sub-problem is infeasible
     4914          if (thisCut->globallyValid()) {
     4915            // add to global list
     4916            OsiRowCut newCut(*thisCut);
     4917            newCut.setGloballyValid(2);
     4918            newCut.mutableRow().setTestForDuplicateIndex(false);
     4919            globalCuts_.insert(newCut) ;
     4920          }
     4921        }
     4922        for (j = numberColumnCutsBefore;j<numberColumnCutsAfter;j++) {
     4923          whichGenerator_[numberBefore++] = i ;
     4924          const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
     4925          if (thisCut->globallyValid()) {
     4926            // add to global list
     4927            OsiColCut newCut(*thisCut);
     4928            newCut.setGloballyValid(2);
     4929            globalCuts_.insert(newCut) ;
     4930          }
     4931        }
     4932      }
     4933      // Add in any violated saved cuts
     4934      if (!theseCuts.sizeRowCuts()&&!theseCuts.sizeColCuts()) {
     4935        int numberOld = theseCuts.sizeRowCuts();
     4936        int numberCuts = slackCuts.sizeRowCuts() ;
     4937        int i;
     4938        // possibly extend whichGenerator
     4939        resizeWhichGenerator(numberOld, numberOld+numberCuts);
     4940        for ( i = 0;i<numberCuts;i++) {
     4941          const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
     4942          if (thisCut->violated(cbcColSolution_)>100.0*primalTolerance) {
     4943            if (messageHandler()->logLevel()>2)
     4944              printf("Old cut added - violation %g\n",
     4945                     thisCut->violated(cbcColSolution_)) ;
     4946            whichGenerator_[numberOld++]=-1;
     4947            theseCuts.insert(*thisCut) ;
     4948          }
     4949        }
     4950      }
     4951      delete [] eachCuts;
     4952    }
     4953    //if (!feasible)
     4954    //break;
     4955/*
     4956  End of the loop to exercise each generator - try heuristics
     4957  - unless at root node and first pass
     4958*/
     4959    if (numberNodes_||currentPassNumber_!=1) {
     4960      double * newSolution = new double [numberColumns] ;
     4961      double heuristicValue = getCutoff() ;
     4962      int found = -1; // no solution found
     4963      for (i = 0;i<numberHeuristics_;i++) {
    43174964        // see if heuristic will do anything
    43184965        double saveValue = heuristicValue ;
    43194966        int ifSol =
    4320           heuristic_[i-numberCutGenerators_]->solution(heuristicValue,
    4321                                                        newSolution,
    4322                                                        theseCuts) ;
     4967          heuristic_[i]->solution(heuristicValue,
     4968                                  newSolution,
     4969                                  theseCuts) ;
    43234970        if (ifSol>0) {
    43244971          // better solution found
    4325           found = i-numberCutGenerators_ ;
     4972          found = i ;
    43264973          incrementUsed(newSolution);
    43274974        } else if (ifSol<0) {
     
    43294976        }
    43304977      }
    4331       int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    4332       int numberColumnCutsAfter = theseCuts.sizeColCuts() ;
    4333 
    4334       if ((specialOptions_&1)!=0) {
    4335         if (onOptimalPath) {
    4336           int k ;
    4337           for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
    4338             OsiRowCut thisCut = theseCuts.rowCut(k) ;
    4339             if(debugger->invalidCut(thisCut)) {
    4340               solver_->writeMps("badCut");
    4341             }
    4342             assert(!debugger->invalidCut(thisCut)) ;
    4343           }
    4344         }
    4345       }
    4346 /*
    4347   The cut generator/heuristic has done its thing, and maybe it generated some
    4348   cuts and/or a new solution.  Do a bit of bookkeeping: load
    4349   whichGenerator[i] with the index of the generator responsible for a cut,
    4350   and place cuts flagged as global in the global cut pool for the model.
    4351 
    4352   lastNumberCuts is the sum of cuts added in previous iterations; it's the
    4353   offset to the proper starting position in whichGenerator.
    4354 */
    4355       int numberBefore =
    4356             numberRowCutsBefore+numberColumnCutsBefore+lastNumberCuts ;
    4357       int numberAfter =
    4358             numberRowCutsAfter+numberColumnCutsAfter+lastNumberCuts ;
    4359       // possibly extend whichGenerator
    4360       resizeWhichGenerator(numberBefore, numberAfter);
    4361       int j ;
    4362       if (fullScan) {
    4363         // counts
    4364         countColumnCuts[i] += numberColumnCutsAfter-numberColumnCutsBefore ;
    4365       }
    4366       countRowCuts[i] += numberRowCutsAfter-numberRowCutsBefore ;
    4367      
    4368       for (j = numberRowCutsBefore;j<numberRowCutsAfter;j++) {
    4369         whichGenerator_[numberBefore++] = i ;
    4370         const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
    4371         if (thisCut->lb()>thisCut->ub())
    4372           violated=-2; // sub-problem is infeasible
    4373         if (thisCut->globallyValid()) {
    4374           // add to global list
    4375           OsiRowCut newCut(*thisCut);
    4376           newCut.setGloballyValid(2);
    4377           newCut.mutableRow().setTestForDuplicateIndex(false);
    4378           globalCuts_.insert(newCut) ;
    4379         }
    4380       }
    4381       for (j = numberColumnCutsBefore;j<numberColumnCutsAfter;j++) {
    4382         whichGenerator_[numberBefore++] = i ;
    4383         const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
    4384         if (thisCut->globallyValid()) {
    4385           // add to global list
    4386           OsiColCut newCut(*thisCut);
    4387           newCut.setGloballyValid(2);
    4388           globalCuts_.insert(newCut) ;
    4389         }
    4390       }
    4391     }
    4392     // If at root node and first pass do heuristics without cuts
    4393     if (!numberNodes_&&currentPassNumber_==1) {
    4394       // Save number solutions
    4395       int saveNumberSolutions = numberSolutions_;
    4396       int saveNumberHeuristicSolutions = numberHeuristicSolutions_;
    4397       // make sure bounds tight
    4398       {
    4399         for (int i = 0;i < numberObjects_;i++)
    4400           object_[i]->resetBounds(solver_) ;
    4401       }
    4402       for (int i = 0;i<numberHeuristics_;i++) {
    4403         // see if heuristic will do anything
    4404         double saveValue = heuristicValue ;
    4405         int ifSol = heuristic_[i]->solution(heuristicValue,
    4406                                             newSolution);
    4407         if (ifSol>0) {
    4408           // better solution found
    4409           found = i ;
    4410           incrementUsed(newSolution);
    4411           // increment number of solutions so other heuristics can test
    4412           numberSolutions_++;
    4413           numberHeuristicSolutions_++;
    4414         } else {
    4415           heuristicValue = saveValue ;
    4416         }
    4417       }
    4418       // Restore number solutions
    4419       numberSolutions_ = saveNumberSolutions;
    4420       numberHeuristicSolutions_ = saveNumberHeuristicSolutions;
    4421     }
    4422     // Add in any violated saved cuts
    4423     if (!theseCuts.sizeRowCuts()&&!theseCuts.sizeColCuts()) {
    4424       int numberOld = theseCuts.sizeRowCuts();
    4425       int numberCuts = slackCuts.sizeRowCuts() ;
    4426       int i;
    4427       // possibly extend whichGenerator
    4428       resizeWhichGenerator(numberOld, numberOld+numberCuts);
    4429       for ( i = 0;i<numberCuts;i++) {
    4430         const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
    4431         if (thisCut->violated(cbcColSolution_)>100.0*primalTolerance) {
    4432           if (messageHandler()->logLevel()>2)
    4433             printf("Old cut added - violation %g\n",
    4434                    thisCut->violated(cbcColSolution_)) ;
    4435           whichGenerator_[numberOld++]=-1;
    4436           theseCuts.insert(*thisCut) ;
    4437         }
    4438       }
    4439     }
    4440 /*
    4441   End of the loop to exercise each generator/heuristic.
    4442 
     4978/*
    44434979  Did any of the heuristics turn up a new solution? Record it before we free
    44444980  the vector.
    44454981*/
    4446     if (found >= 0) {
    4447       phase_=4;
    4448       incrementUsed(newSolution);
    4449       setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
    4450       lastHeuristic_ = heuristic_[found];
    4451       CbcTreeLocal * tree
     4982      if (found >= 0) {
     4983        phase_=4;
     4984        incrementUsed(newSolution);
     4985        lastHeuristic_ = heuristic_[found];
     4986        setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
     4987        CbcTreeLocal * tree
    44524988          = dynamic_cast<CbcTreeLocal *> (tree_);
    4453       if (tree)
    4454         tree->passInSolution(bestSolution_,heuristicValue);
    4455     }
    4456     delete [] newSolution ;
     4989        if (tree)
     4990          tree->passInSolution(bestSolution_,heuristicValue);
     4991      }
     4992      delete [] newSolution ;
     4993    }
    44574994
    44584995#if 0
     
    46895226    if (!feasible)
    46905227    { int i ;
    4691       for (i = 0;i<currentNumberCuts_;i++) {
    4692         // take off node
    4693         if (addedCuts_[i]) {
    4694           if (!addedCuts_[i]->decrement())
    4695             delete addedCuts_[i] ;
    4696           addedCuts_[i] = NULL ;
     5228      if (currentNumberCuts_) {
     5229        lockThread();
     5230        for (i = 0;i<currentNumberCuts_;i++) {
     5231          // take off node
     5232          if (addedCuts_[i]) {
     5233            if (!addedCuts_[i]->decrement())
     5234              delete addedCuts_[i] ;
     5235            addedCuts_[i] = NULL ;
     5236          }
    46975237        }
    46985238      }
     
    48305370      phase_=4;
    48315371      incrementUsed(newSolution);
     5372      lastHeuristic_ = heuristic_[found];
    48325373      setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
    4833       lastHeuristic_ = heuristic_[found];
    48345374    }
    48355375    delete [] newSolution ;
     
    51655705    clpSolver->setSpecialOptions(saveClpOptions);
    51665706# endif
     5707#ifdef CBC_THREAD
     5708  if (threadModel) {
     5709    // stop threads
     5710    int i;
     5711    for (i=0;i<numberThreads_;i++) {
     5712      pthread_cond_signal(threadInfo[i].condition2); // unlock
     5713      while (threadInfo[i].returnCode==0) {
     5714        struct timespec moreTime;
     5715        moreTime.tv_nsec = 10000;
     5716        moreTime.tv_sec = 0;
     5717        nanosleep(&moreTime,NULL);
     5718      }
     5719      threadModel[i]->numberThreads_=0; // say exit
     5720      threadInfo[i].returnCode=0;
     5721      pthread_cond_signal(threadInfo[i].condition2); // unlock
     5722      pthread_join(threadId[i],NULL);
     5723      pthread_mutex_destroy (threadInfo[i].mutex2);
     5724      pthread_cond_destroy (threadInfo[i].condition2);
     5725      threadModel[i]->generator_[0]=NULL;
     5726      delete [] threadModel[i]->generator_;
     5727      threadModel[i]->generator_=NULL;
     5728      threadModel[i]->object_=NULL;
     5729    }
     5730    pthread_cond_destroy (&condition_main);
     5731    pthread_mutex_destroy (&condition_mutex);
     5732    // delete models and solvers
     5733    for (i=0;i<numberThreads_;i++) {
     5734      delete threadModel[i];
     5735    }
     5736    delete [] mutex2;
     5737    delete [] condition2;
     5738    delete [] threadId;
     5739    delete [] threadInfo;
     5740    delete [] threadModel;
     5741    mutex_ = saveMutex;
     5742  }
     5743#endif
    51675744
    51685745  return feasible ; }
     
    52425819*/
    52435820    int oldCutIndex = 0 ;
    5244     for (i = 0 ; i < numberOldActiveCuts_ ; i++)
    5245     { status = ws->getArtifStatus(i+firstOldCut) ;
    5246       while (!addedCuts_[oldCutIndex]) oldCutIndex++ ;
    5247       assert(oldCutIndex < currentNumberCuts_) ;
    5248       // always leave if from nextRowCut_
    5249       if (status == CoinWarmStartBasis::basic&&
    5250           addedCuts_[oldCutIndex]->effectiveness()!=COIN_DBL_MAX)
    5251       { solverCutIndices[numberOldToDelete++] = i+firstOldCut ;
    5252         if (saveCuts) {
    5253           // send to cut pool
    5254           OsiRowCut * slackCut = addedCuts_[oldCutIndex];
    5255           if (slackCut->effectiveness()!=-1.234) {
    5256             slackCut->setEffectiveness(-1.234);
    5257             saveCuts->insert(*slackCut);
    5258           }
    5259         }
    5260         if (addedCuts_[oldCutIndex]->decrement() == 0)
    5261           delete addedCuts_[oldCutIndex] ;
    5262         addedCuts_[oldCutIndex] = NULL ;
    5263         oldCutIndex++ ; }
    5264       else
    5265       { oldCutIndex++ ; } }
     5821    if (numberOldActiveCuts_) {
     5822      lockThread();
     5823      for (i = 0 ; i < numberOldActiveCuts_ ; i++)
     5824        { status = ws->getArtifStatus(i+firstOldCut) ;
     5825        while (!addedCuts_[oldCutIndex]) oldCutIndex++ ;
     5826        assert(oldCutIndex < currentNumberCuts_) ;
     5827        // always leave if from nextRowCut_
     5828        if (status == CoinWarmStartBasis::basic&&
     5829            addedCuts_[oldCutIndex]->effectiveness()!=COIN_DBL_MAX)
     5830          { solverCutIndices[numberOldToDelete++] = i+firstOldCut ;
     5831          if (saveCuts) {
     5832            // send to cut pool
     5833            OsiRowCut * slackCut = addedCuts_[oldCutIndex];
     5834            if (slackCut->effectiveness()!=-1.234) {
     5835              slackCut->setEffectiveness(-1.234);
     5836              saveCuts->insert(*slackCut);
     5837            }
     5838          }
     5839          if (addedCuts_[oldCutIndex]->decrement() == 0)
     5840            delete addedCuts_[oldCutIndex] ;
     5841          addedCuts_[oldCutIndex] = NULL ;
     5842          oldCutIndex++ ; }
     5843        else
     5844          { oldCutIndex++ ; } }
     5845      unlockThread();
     5846    }
    52665847/*
    52675848  Scan the basis entries of the new cuts generated with this round of cut
     
    66337214            if (generator_[i]->atSolution())
    66347215              {
    6635                 generator_[i]->generateCuts(theseCuts,true,NULL);
     7216                generator_[i]->generateCuts(theseCuts,true,solver_,NULL);
    66367217                int numberCuts = theseCuts.sizeRowCuts();
    66377218                for (int j=lastNumberCuts;j<numberCuts;j++)
     
    67597340      cutoff = bestObjective_-dblParam_[CbcCutoffIncrement];
    67607341      // But allow for rounding errors
    6761       if (dblParam_[CbcCutoffIncrement] == 1e-5)
     7342      if (dblParam_[CbcCutoffIncrement] == 1e-5) {
     7343#ifdef COIN_DEVELOP
     7344        if (saveObjectiveValue+1.0e-7<bestObjective_)
     7345          printf("First try at solution had objective %.16g, rechecked as %.16g\n",
     7346                 saveObjectiveValue,bestObjective_);
     7347#endif
     7348        saveObjectiveValue = CoinMax(saveObjectiveValue,bestObjective_-0.0000001*fabs(bestObjective_));
    67627349        cutoff = CoinMin(bestObjective_,saveObjectiveValue)-1.0e-5;
     7350      }
    67637351      // This is not correct - that way cutoff can go up if maximization
    67647352      //double direction = solver_->getObjSense();
     
    67737361      else
    67747362        stateOfSearch_ = 2;
    6775      
    6776       handler_->message(how,messages_)
    6777         <<bestObjective_<<numberIterations_
    6778         <<numberNodes_<<getCurrentSeconds()
    6779         <<CoinMessageEol;
     7363
     7364      if (how!=CBC_ROUNDING) {
     7365        handler_->message(how,messages_)
     7366          <<bestObjective_<<numberIterations_
     7367          <<numberNodes_<<getCurrentSeconds()
     7368          <<CoinMessageEol;
     7369      } else {
     7370        assert (lastHeuristic_);
     7371        const char * name = lastHeuristic_->heuristicName();
     7372        handler_->message(CBC_ROUNDING,messages_)
     7373          <<bestObjective_
     7374          <<name
     7375          <<numberIterations_
     7376          <<numberNodes_<<getCurrentSeconds()
     7377          <<CoinMessageEol;
     7378      }
    67807379      /*
    67817380        Now step through the cut generators and see if any of them are flagged to
     
    67967395          generate=false;
    67977396        if (generate) {
    6798           generator_[i]->generateCuts(theseCuts,true,NULL);
     7397          generator_[i]->generateCuts(theseCuts,true,solver_,NULL);
    67997398          int numberCuts = theseCuts.sizeRowCuts();
    68007399          for (int j=lastNumberCuts;j<numberCuts;j++) {
     
    76368235          testSolution_=currentSolution_;
    76378236          // better solution save
     8237          lastHeuristic_ = heuristic_[found];
    76388238          setBestSolution(CBC_ROUNDING,heuristicValue,
    76398239                          newSolution);
    7640           lastHeuristic_ = heuristic_[found];
    76418240          // update cutoff
    76428241          cutoff = getCutoff();
     
    86249223      resolve(solver_);
    86259224      double objval = solver_->getObjValue();
     9225      lastHeuristic_ = NULL;
    86269226      setBestSolution(CBC_SOLUTION, objval,
    86279227                      solver_->getColSolution()) ;
    8628       lastHeuristic_ = NULL;
    86299228      int easy=2;
    86309229      if (!solverCharacteristics_->mipFeasible())//did we prove that the node could be pruned?
     
    86559254    numberPassesLeft--;
    86569255    if (numberPassesLeft<=-1) {
    8657       if (!numberLongStrong_)
     9256      if (!numberLongStrong_&&!numberThreads_)
    86589257        messageHandler()->message(CBC_WARNING_STRONG,
    86599258                                  messages()) << CoinMessageEol ;
     
    87109309      maximumDepthActual_ = CoinMax(maximumDepthActual_,newNode->depth());
    87119310      newNode->initializeInfo() ;
    8712       newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
    8713                                    whichGenerator_) ;
     9311      if (cuts.sizeRowCuts()) {
     9312        lockThread();
     9313        newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
     9314                                     whichGenerator_) ;
     9315        unlockThread();
     9316      }
    87149317    }
    87159318  } else {
     
    89679570  delete solver_;
    89689571  solver_ = process->originalModel();
     9572}
     9573void
     9574CbcModel::setBestSolution(const double * solution,int numberColumns,double objectiveValue)
     9575{
     9576  bestObjective_ = objectiveValue;
     9577  int n = CoinMax(numberColumns,solver_->getNumCols());
     9578  delete [] bestSolution_;
     9579  bestSolution_ = new double [n];
     9580  memset(bestSolution_,0,n*sizeof(double));
     9581  memcpy(bestSolution_,solution,numberColumns*sizeof(double));
    89699582}
    89709583// Create C++ lines to get to current state
     
    91509763  cutModifier_ = modifier.clone();
    91519764}
     9765#ifdef CBC_THREAD
     9766/* Do one node - broken out for clarity?
     9767   also for parallel (when baseModel!=this)
     9768   Returns 1 if solution found
     9769   node NULL on return if no branches left
     9770   newNode NULL if no new node created
     9771*/
     9772int
     9773CbcModel::doOneNode(CbcModel * baseModel, CbcNode * & node, CbcNode * & newNode)
     9774{
     9775  int foundSolution=0;
     9776  int currentNumberCuts = 0 ;
     9777  currentNode_=node; // so can be accessed elsewhere
     9778  double bestObjective = bestObjective_;
     9779#ifdef CBC_DEBUG
     9780  printf("%d unsat, way %d, obj %g est %g\n",
     9781         node->numberUnsatisfied(),node->way(),node->objectiveValue(),
     9782         node->guessedObjectiveValue());
     9783#endif
     9784#if 0
     9785  if (node->objectiveValue()>getCutoff()) {
     9786    printf("cutoff\n");
     9787    assert (node->nodeInfo());
     9788    node->nodeInfo()->decrement(node->nodeInfo()->numberBranchesLeft()) ;
     9789    delete node;
     9790    node=NULL;
     9791    newNode=NULL;
     9792    return 0;
     9793  }
     9794#endif
     9795  // Save clone in branching decision
     9796  if(branchingMethod_)
     9797    branchingMethod_->saveBranchingObject(node->modifiableBranchingObject());
     9798  // Say not on optimal path
     9799  bool onOptimalPath=false;
     9800#   ifdef CHECK_NODE
     9801  printf("Node %x popped from tree - %d left, %d count\n",node,
     9802         node->nodeInfo()->numberBranchesLeft(),
     9803         node->nodeInfo()->numberPointingToThis()) ;
     9804  printf("\tdepth = %d, z =  %g, unsat = %d, var = %d.\n",
     9805         node->depth(),node->objectiveValue(),
     9806         node->numberUnsatisfied(),
     9807         node->columnNumber()) ;
     9808#   endif
     9809 
     9810  /*
     9811    Rebuild the subproblem for this node:        Call addCuts() to adjust the model
     9812    to recreate the subproblem for this node (set proper variable bounds, add
     9813    cuts, create a basis).  This may result in the problem being fathomed by
     9814    bound or infeasibility. Returns 1 if node is fathomed.
     9815    Execute the current arm of the branch: If the problem survives, save the
     9816    resulting variable bounds and call branch() to modify variable bounds
     9817    according to the current arm of the branching object. If we're processing
     9818    the final arm of the branching object, flag the node for removal from the
     9819    live set.
     9820  */
     9821  /*
     9822    Used to generate bound edits for CbcPartialNodeInfo.
     9823  */
     9824  int numberColumns = getNumCols() ;
     9825  double * lowerBefore = new double [numberColumns] ;
     9826  double * upperBefore = new double [numberColumns] ;
     9827  newNode = NULL ;
     9828  bool feasible=true;
     9829  CoinWarmStartBasis *lastws = new CoinWarmStartBasis();
     9830  lockThread();
     9831  // point to genuine ones
     9832  //int save1 = maximumNumberCuts_;
     9833  int save2 = maximumDepth_;
     9834  //maximumNumberCuts_ = baseModel->maximumNumberCuts_;
     9835  //addedCuts_ = baseModel->addedCuts_;
     9836  maximumDepth_ = baseModel->maximumDepth_;
     9837  walkback_ = baseModel->walkback_;
     9838  int retCode =addCuts(node,lastws,numberFixedNow_>numberFixedAtRoot_);
     9839  //if (save1<maximumNumberCuts_) {
     9840    // increased
     9841    //baseModel->maximumNumberCuts_ = maximumNumberCuts_;
     9842    //baseModel->addedCuts_ = addedCuts_;
     9843  //}
     9844  if (save2<maximumDepth_) {
     9845    // increased
     9846    baseModel->maximumDepth_ = maximumDepth_;
     9847    baseModel->walkback_ = walkback_;
     9848  }
     9849  unlockThread();
     9850  int branchesLeft=0;
     9851  if (!retCode) {
     9852    int i ;
     9853    const double * lower = getColLower() ;
     9854    const double * upper = getColUpper() ;
     9855    for (i = 0 ; i < numberColumns ; i++) {
     9856      lowerBefore[i]= lower[i] ;
     9857      upperBefore[i]= upper[i] ;
     9858    }
     9859    if ((solverCharacteristics_->extraCharacteristics()&2)!=0) {
     9860      solverCharacteristics_->setBeforeLower(lowerBefore);
     9861      solverCharacteristics_->setBeforeUpper(upperBefore);
     9862    }
     9863    lockThread();
     9864    if (messageHandler()->logLevel()>2)
     9865      node->modifiableBranchingObject()->print();
     9866    if (branchingMethod_&&branchingMethod_->chooseMethod()) {
     9867      branchesLeft = node->branch(solver_); // new way
     9868    } else {
     9869      // old way so need to cheat
     9870      OsiBranchingObject * branch2 = node->modifiableBranchingObject();
     9871      CbcBranchingObject * branch = dynamic_cast <CbcBranchingObject *>(branch2) ;
     9872      assert (branch);
     9873      branch->setModel(this);
     9874      branchesLeft = node->branch(NULL); // old way
     9875      branch->setModel(baseModel);
     9876    }
     9877    if (mutex_) {
     9878      assert (node->nodeInfo());
     9879      node->nodeInfo()->increment() ;
     9880    }
     9881    unlockThread();
     9882    if ((specialOptions_&1)!=0) {
     9883      /*
     9884        This doesn't work as intended --- getRowCutDebugger will return null
     9885        unless the current feasible solution region includes the optimal solution
     9886        that RowCutDebugger knows. There's no way to tell inactive from off the
     9887        optimal path.
     9888      */
     9889      const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
     9890      if (debugger) {
     9891        onOptimalPath=true;
     9892        printf("On optimal path\n") ;
     9893      }
     9894    }
     9895     
     9896    /*
     9897      Reoptimize, possibly generating cuts and/or using heuristics to find
     9898      solutions.  Cut reference counts are unaffected unless we lose feasibility,
     9899      in which case solveWithCuts() will make the adjustment.
     9900    */
     9901    phase_=2;
     9902    OsiCuts cuts ;
     9903    currentNumberCuts = solver_->getNumRows()-numberRowsAtContinuous_ ;
     9904    int saveNumber = numberIterations_;
     9905    if(solverCharacteristics_->solutionAddsCuts()) {
     9906      int returnCode=resolve(node ? node->nodeInfo() : NULL,1);
     9907      feasible = returnCode != 0;
     9908      if (feasible) {
     9909        int iObject ;
     9910        int preferredWay ;
     9911        int numberUnsatisfied = 0 ;
     9912        memcpy(currentSolution_,solver_->getColSolution(),
     9913               numberColumns*sizeof(double)) ;
     9914        // point to useful information
     9915        OsiBranchingInformation usefulInfo=usefulInformation();
     9916       
     9917        for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
     9918          double infeasibility =
     9919            object_[iObject]->infeasibility(&usefulInfo,preferredWay) ;
     9920          if (infeasibility ) numberUnsatisfied++ ;
     9921        }
     9922        if (returnCode>0) {
     9923          if (numberUnsatisfied)   {
     9924            feasible = solveWithCuts(cuts,maximumCutPasses_,node);
     9925          } else {
     9926            // may generate cuts and turn the solution
     9927            //to an infeasible one
     9928            feasible = solveWithCuts(cuts, 1,
     9929                                     node);
     9930          }
     9931        }
     9932        // check extra info on feasibility
     9933        if (!solverCharacteristics_->mipFeasible()) {
     9934          feasible = false;
     9935          solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
     9936        }
     9937      }
     9938    } else {
     9939      // normal
     9940      feasible = solveWithCuts(cuts,maximumCutPasses_,node);
     9941    }
     9942    if ((specialOptions_&1)!=0&&onOptimalPath) {
     9943      if (!solver_->getRowCutDebugger()) {
     9944        // dj fix did something???
     9945        solver_->writeMps("infeas2");
     9946        assert (solver_->getRowCutDebugger()) ;
     9947      }
     9948    }
     9949    if (statistics_) {
     9950      assert (numberNodes2_);
     9951      assert (statistics_[numberNodes2_-1]);
     9952      assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     9953      statistics_[numberNodes2_-1]->endOfBranch(numberIterations_-saveNumber,
     9954                                                feasible ? solver_->getObjValue()
     9955                                                : COIN_DBL_MAX);
     9956    }
     9957    /*
     9958      Are we still feasible? If so, create a node and do the work to attach a
     9959      branching object, reoptimising as needed if chooseBranch() identifies
     9960      monotone objects.
     9961     
     9962      Finally, attach a partial nodeInfo object and store away any cuts that we
     9963      created back in solveWithCuts. addCuts() will initialise the reference
     9964      counts for these new cuts.
     9965     
     9966      This next test can be problematic if we've discovered an
     9967      alternate equivalent answer and subsequently fathom the solution
     9968      known to the row cut debugger due to bounds.
     9969    */
     9970    if (onOptimalPath) {
     9971      bool objLim = solver_->isDualObjectiveLimitReached() ;
     9972      if (!feasible && !objLim) {
     9973        printf("infeas2\n");
     9974        solver_->writeMps("infeas");
     9975        CoinWarmStartBasis *slack =
     9976          dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
     9977        solver_->setWarmStart(slack);
     9978        delete slack ;
     9979        solver_->setHintParam(OsiDoReducePrint,false,OsiHintDo,0) ;
     9980        solver_->initialSolve();
     9981        assert (!solver_->isProvenOptimal());
     9982      }
     9983      assert (feasible || objLim);
     9984    }
     9985    bool checkingNode=false;
     9986    if (feasible) {
     9987      newNode = new CbcNode ;
     9988      // Set objective value (not so obvious if NLP etc)
     9989      setObjectiveValue(newNode,node);
     9990      int anyAction =-1 ;
     9991      bool resolved = false ;
     9992      if (newNode->objectiveValue() >= getCutoff())
     9993        anyAction=-2;
     9994      // only allow at most a few passes
     9995      int numberPassesLeft=5;
     9996      checkingNode=true;
     9997      OsiSolverBranch * branches=NULL;
     9998      // point to useful information
     9999      anyAction = chooseBranch(newNode, numberPassesLeft,node, cuts,resolved,
     10000                               lastws, lowerBefore, upperBefore, branches);
     10001      /*
     10002        If we end up infeasible, we can delete the new node immediately. Since this
     10003        node won't be needing the cuts we collected, decrement the reference counts.
     10004        If we are feasible, then we'll be placing this node into the live set, so
     10005        increment the reference count in the current (parent) nodeInfo.
     10006      */
     10007      lockThread();
     10008      if (anyAction == -2) {
     10009        if (mutex_) {
     10010          assert (node->nodeInfo());
     10011          node->nodeInfo()->decrement() ;
     10012        }
     10013        delete newNode ;
     10014        if (mutex_) {
     10015          assert (node->nodeInfo());
     10016          node->nodeInfo()->increment() ;
     10017        }
     10018        newNode = NULL ;
     10019        // say strong doing well
     10020        if (checkingNode)
     10021          setSpecialOptions(specialOptions_|8);
     10022        for (i = 0 ; i < currentNumberCuts_ ; i++) {
     10023          if (addedCuts_[i]) {
     10024            if (!addedCuts_[i]->decrement(1)) {
     10025              delete addedCuts_[i] ;
     10026            }
     10027              addedCuts_[i]=NULL;
     10028              //}
     10029          }
     10030        }
     10031      } else {
     10032        assert (node->nodeInfo());
     10033        node->nodeInfo()->increment() ;
     10034        if ((numberNodes_%20)==0) {
     10035          // say strong not doing as well
     10036          setSpecialOptions(specialOptions_&~8);
     10037        }
     10038      }
     10039      unlockThread();
     10040    }
     10041    /*
     10042      At this point, there are three possibilities:
     10043      * newNode is live and will require further branching to resolve
     10044      (variable() >= 0). Increment the cut reference counts by
     10045      numberBranches() to allow for use by children of this node, and
     10046      decrement by 1 because we've executed one arm of the branch of our
     10047      parent (consuming one reference). Before we push newNode onto the
     10048      search tree, try for a heuristic solution.
     10049      * We have a solution, in which case newNode is non-null but we have no
     10050      branching variable. Decrement the cut counts and save the solution.
     10051      * The node was found to be infeasible, in which case it's already been
     10052      deleted, and newNode is null.
     10053    */
     10054    if (!getEventHandler()->event(CbcEventHandler::node)) {
     10055      eventHappened_=true; // exit
     10056    }
     10057    assert (!newNode || newNode->objectiveValue() <= getCutoff()) ;
     10058    if (statistics_) {
     10059      assert (numberNodes2_);
     10060      assert (statistics_[numberNodes2_-1]);
     10061      assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     10062      if (newNode)
     10063        statistics_[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied());
     10064      else
     10065        statistics_[numberNodes2_-1]->sayInfeasible();
     10066    }
     10067    lockThread();
     10068    if (newNode) {
     10069      if (newNode->branchingObject() == NULL&&solverCharacteristics_->solverType()==4) {
     10070        // need to check if any cuts would do anything
     10071        OsiCuts theseCuts;
     10072        // reset probing info
     10073        if (probingInfo_)
     10074          probingInfo_->initializeFixing();
     10075        for (int i = 0;i<numberCutGenerators_;i++) {
     10076          bool generate = generator_[i]->normal();
     10077          // skip if not optimal and should be (maybe a cut generator has fixed variables)
     10078          if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     10079            generate=false;
     10080          if (!generator_[i]->mustCallAgain())
     10081            generate=false; // only special cuts
     10082          if (generate) {
     10083            generator_[i]->generateCuts(theseCuts,true,solver_,NULL) ;
     10084            int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
     10085            if (numberRowCutsAfter) {
     10086              // need dummy branch
     10087              newNode->setBranchingObject(new CbcDummyBranchingObject(this));
     10088              newNode->nodeInfo()->initializeInfo(1);
     10089              break;
     10090            }
     10091          }
     10092        }
     10093      }
     10094      if (newNode->branchingObject()) {
     10095        handler_->message(CBC_BRANCH,messages_)
     10096          << numberNodes_<< newNode->objectiveValue()
     10097          << newNode->numberUnsatisfied()<< newNode->depth()
     10098          << CoinMessageEol ;
     10099        // Increment cut counts (taking off current)
     10100        int numberLeft = newNode->numberBranches() ;
     10101        for (i = 0;i < currentNumberCuts_;i++) {
     10102          if (addedCuts_[i]) {
     10103#               ifdef CHECK_CUT_COUNTS
     10104            printf("Count on cut %x increased by %d\n",addedCuts_[i],
     10105                   numberLeft-1) ;
     10106#               endif
     10107            addedCuts_[i]->increment(numberLeft-1) ;
     10108          }
     10109        }
     10110        unlockThread();
     10111
     10112        double estValue = newNode->guessedObjectiveValue() ;
     10113        int found = -1 ;
     10114        double * newSolution = new double [numberColumns] ;
     10115        double heurValue = getCutoff() ;
     10116        int iHeur ;
     10117        for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) {
     10118          double saveValue = heurValue ;
     10119          int ifSol = heuristic_[iHeur]->solution(heurValue,newSolution) ;
     10120          if (ifSol > 0) {
     10121            // new solution found
     10122            found = iHeur ;
     10123            lockThread();
     10124            baseModel->incrementUsed(newSolution);
     10125            unlockThread();
     10126          } else if (ifSol < 0) { // just returning an estimate
     10127            estValue = CoinMin(heurValue,estValue) ;
     10128            heurValue = saveValue ;
     10129          }
     10130        }
     10131        if (found >= 0) {
     10132          lastHeuristic_ = heuristic_[found];
     10133          setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
     10134          foundSolution=1;
     10135        }
     10136        delete [] newSolution ;
     10137        newNode->setGuessedObjectiveValue(estValue) ;
     10138        lockThread();
     10139#define PUSH_LATER
     10140#ifdef PUSH_LATER
     10141        if (!mutex_) // only if serial
     10142#endif
     10143        tree_->push(newNode) ;
     10144        if (statistics_) {
     10145          if (numberNodes2_==maximumStatistics_) {
     10146            maximumStatistics_ = 2*maximumStatistics_;
     10147            CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     10148            memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     10149            memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     10150            delete [] statistics_;
     10151            statistics_=temp;
     10152          }
     10153          assert (!statistics_[numberNodes2_]);
     10154          statistics_[numberNodes2_]=new CbcStatistics(newNode);
     10155        }
     10156        numberNodes2_++;
     10157#           ifdef CHECK_NODE
     10158        printf("Node %x pushed on tree c\n",newNode) ;
     10159#           endif
     10160      } else {
     10161        if(solverCharacteristics_ && //we may be in a non standard bab
     10162           solverCharacteristics_->solutionAddsCuts()// we are in some kind of OA based bab.
     10163           ) {
     10164         
     10165          std::cerr<<"You should never get here"<<std::endl;
     10166          throw CoinError("Nodes should not be fathomed on integer infeasibility in this setting",
     10167                          "branchAndBound","CbcModel") ;
     10168        }
     10169        for (i = 0 ; i < currentNumberCuts_ ; i++) {
     10170          if (addedCuts_[i]) {
     10171            if (!addedCuts_[i]->decrement(1)) {
     10172              delete addedCuts_[i] ;
     10173              addedCuts_[i]=NULL;
     10174            }
     10175          }
     10176        }
     10177        double objectiveValue = newNode->objectiveValue();
     10178        lastHeuristic_ = NULL;
     10179        // Just possible solver did not know about a solution from another thread!
     10180        if (objectiveValue<getCutoff()) {
     10181          incrementUsed(solver_->getColSolution());
     10182          setBestSolution(CBC_SOLUTION,objectiveValue,
     10183                          solver_->getColSolution()) ;
     10184          foundSolution=1;
     10185        }
     10186        //assert(nodeInfo->numberPointingToThis() <= 2) ;
     10187        // avoid accidental pruning, if newNode was final branch arm
     10188        node->nodeInfo()->increment();
     10189        delete newNode ;
     10190        newNode=NULL;
     10191        node->nodeInfo()->decrement() ;
     10192      }
     10193    }
     10194    if (branchesLeft) {
     10195      // set nodenumber correctly
     10196      if (node->nodeInfo())
     10197        node->nodeInfo()->setNodeNumber(numberNodes2_);
     10198#ifdef PUSH_LATER
     10199        if (!mutex_) // only if serial
     10200#endif
     10201      tree_->push(node) ;
     10202      if (statistics_) {
     10203        if (numberNodes2_==maximumStatistics_) {
     10204          maximumStatistics_ = 2*maximumStatistics_;
     10205          CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     10206          memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     10207          memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     10208          delete [] statistics_;
     10209          statistics_=temp;
     10210        }
     10211        assert (!statistics_[numberNodes2_]);
     10212        statistics_[numberNodes2_]=new CbcStatistics(node);
     10213      }
     10214      numberNodes2_++;
     10215      //nodeOnTree=true; // back on tree
     10216      //deleteNode = false ;
     10217#       ifdef CHECK_NODE
     10218      printf("Node %x pushed back on tree - %d left, %d count\n",node,
     10219             node->nodeInfo()->numberBranchesLeft(),
     10220             node->nodeInfo()->numberPointingToThis()) ;
     10221#       endif
     10222      if (mutex_) {
     10223        assert (node->nodeInfo());
     10224        node->nodeInfo()->decrement() ;
     10225      }
     10226    } else {
     10227    /*
     10228      This node has been completely expanded and can be removed from the live
     10229      set.
     10230    */
     10231      if (mutex_) {
     10232        assert (node->nodeInfo());
     10233        node->nodeInfo()->decrement() ;
     10234      }
     10235      assert (node->nodeInfo());
     10236      if (!node->nodeInfo()->numberBranchesLeft())
     10237        node->nodeInfo()->allBranchesGone(); // can clean up
     10238      delete node ;
     10239      node=NULL;
     10240    }
     10241    unlockThread();
     10242  } else {
     10243    // add cuts found to be infeasible (on bound)!
     10244    printf("found to be infeas! - branches left %d\n",node->nodeInfo()->numberBranchesLeft());
     10245    //abort();
     10246    assert (node->nodeInfo());
     10247    if (!node->nodeInfo()->numberBranchesLeft())
     10248      node->nodeInfo()->allBranchesGone(); // can clean up
     10249    delete node;
     10250    node=NULL;
     10251  }
     10252  /*
     10253    Delete cuts to get back to the original system.
     10254   
     10255    I'm thinking this is redundant --- the call to addCuts that conditions entry
     10256    to this code block also performs this action.
     10257  */
     10258  int numberToDelete = getNumRows()-numberRowsAtContinuous_ ;
     10259  if (numberToDelete) {
     10260    int * delRows = new int[numberToDelete] ;
     10261    int i ;
     10262    for (i = 0 ; i < numberToDelete ; i++)
     10263      delRows[i] = i+numberRowsAtContinuous_ ;
     10264    solver_->deleteRows(numberToDelete,delRows) ;
     10265    delete [] delRows ;
     10266  }
     10267  delete lastws ;
     10268  delete [] lowerBefore ;
     10269  delete [] upperBefore ;
     10270  if (bestObjective > bestObjective_)
     10271    foundSolution=2;
     10272  if (foundSolution) {
     10273    lockThread();
     10274    // might as well mark all including continuous
     10275    int numberColumns = solver_->getNumCols();
     10276    for (int i=0;i<numberColumns;i++) {
     10277      baseModel->usedInSolution_[i] += usedInSolution_[i];
     10278      usedInSolution_[i]=0;
     10279    }
     10280    baseModel->numberSolutions_ = numberSolutions_;
     10281    if (bestObjective_ < baseModel->bestObjective_&&bestObjective_<baseModel->getCutoff()) {
     10282      baseModel->bestObjective_ = bestObjective_ ;
     10283      int numberColumns = solver_->getNumCols();
     10284      if (!baseModel->bestSolution_)
     10285        baseModel->bestSolution_ = new double[numberColumns];
     10286      CoinCopyN(bestSolution_,numberColumns,baseModel->bestSolution_);
     10287      baseModel->setCutoff(getCutoff());
     10288    }
     10289    unlockThread();
     10290  }
     10291  return foundSolution;
     10292}
     10293/* Move/copy information from one model to another
     10294   -1 - initial setup
     10295   0 - from base model
     10296   1 - to base model (and reset)
     10297   2 - add in final statistics etc (and reset so can do clean destruction)
     10298*/
     10299void
     10300CbcModel::moveToModel(CbcModel * baseModel,int mode)
     10301{
     10302  if (mode==0) {
     10303    setCutoff(baseModel->getCutoff());
     10304    bestObjective_ = baseModel->bestObjective_;
     10305    assert (!baseModel->globalCuts_.sizeRowCuts());
     10306    numberSolutions_ = baseModel->numberSolutions_;
     10307    stateOfSearch_ = baseModel->stateOfSearch_;
     10308    numberNodes_ = baseModel->numberNodes_;
     10309    numberIterations_ = baseModel->numberIterations_;
     10310    numberFixedAtRoot_ = numberIterations_; // for statistics
     10311    phase_ = baseModel->phase_;
     10312    assert (!nextRowCut_);
     10313    nodeCompare_ = baseModel->nodeCompare_;
     10314    tree_ = baseModel->tree_;
     10315    assert (!subTreeModel_);
     10316    //branchingMethod_ = NULL; // need something but what
     10317    numberOldActiveCuts_ = baseModel->numberOldActiveCuts_;
     10318    cutModifier_ = NULL;
     10319    assert (!analyzeResults_);
     10320    threadStruct * stuff = (threadStruct *) mutex_;
     10321    assert (stuff);
     10322    //if (stuff)
     10323    stuff->createdNode=NULL;
     10324    // ?? searchStrategy_;
     10325    searchStrategy_=baseModel->searchStrategy_;
     10326    stuff->saveStuff[0]=searchStrategy_;
     10327    stateOfSearch_=baseModel->stateOfSearch_;
     10328    stuff->saveStuff[1]=stateOfSearch_;
     10329 } else if (mode==1) {
     10330    lockThread();
     10331    threadStruct * stuff = (threadStruct *) mutex_;
     10332    assert (stuff);
     10333    //stateOfSearch_
     10334#if 1
     10335    if(stuff->saveStuff[0]!=searchStrategy_) {
     10336      printf("changing searchStrategy from %d to %d\n",
     10337             baseModel->searchStrategy_,searchStrategy_);
     10338      baseModel->searchStrategy_=searchStrategy_;
     10339    }
     10340    if(stuff->saveStuff[1]!=stateOfSearch_) {
     10341      printf("changing stateOfSearch from %d to %d\n",
     10342             baseModel->stateOfSearch_,stateOfSearch_);
     10343      baseModel->stateOfSearch_=stateOfSearch_;
     10344    }
     10345#endif
     10346    if (eventHappened_)
     10347      baseModel->eventHappened_=true;
     10348    baseModel->numberNodes_++;
     10349    baseModel->numberIterations_ +=
     10350      numberIterations_ - numberFixedAtRoot_;
     10351#ifdef PUSH_LATER
     10352    if (stuff->node)
     10353      baseModel->tree_->push(stuff->node);
     10354    if (stuff->createdNode)
     10355      baseModel->tree_->push(stuff->createdNode);
     10356#endif
     10357    unlockThread();
     10358  } else if (mode==2) {
     10359    baseModel->sumChangeObjective1_ += sumChangeObjective1_;
     10360    baseModel->sumChangeObjective2_ += sumChangeObjective2_;
     10361    //baseModel->numberIterations_ += numberIterations_;
     10362    for (int iGenerator=0;iGenerator<numberCutGenerators_;iGenerator++) {
     10363      CbcCutGenerator * generator = baseModel->generator_[iGenerator];
     10364      CbcCutGenerator * generator2 = generator_[iGenerator];
     10365      generator->incrementNumberTimesEntered(generator2->numberTimesEntered());
     10366      generator->incrementNumberCutsInTotal(generator2->numberCutsInTotal());
     10367      generator->incrementNumberCutsActive(generator2->numberCutsActive());
     10368      generator->incrementTimeInCutGenerator(generator2->timeInCutGenerator());
     10369    }
     10370    nodeCompare_ = NULL;
     10371    baseModel->maximumDepthActual_ = CoinMax(baseModel->maximumDepthActual_,maximumDepthActual_);
     10372    baseModel->numberDJFixed_ += numberDJFixed_;
     10373    baseModel->numberStrongIterations_ += numberStrongIterations_;
     10374    int i;
     10375    for (i=0;i<3;i++)
     10376      baseModel->strongInfo_[i] += strongInfo_[i];
     10377    walkback_ = NULL;
     10378    //addedCuts_ = NULL;
     10379    tree_ = NULL;
     10380    eventHandler_=NULL;
     10381    delete solverCharacteristics_;
     10382    solverCharacteristics_ = NULL;
     10383    if (baseModel->branchingMethod_&&baseModel->branchingMethod_->chooseMethod()) {
     10384      // new method - we were using base models
     10385      numberObjects_=0;
     10386      object_=NULL;
     10387    }
     10388  } else {
     10389    delete eventHandler_;
     10390    eventHandler_ = baseModel->eventHandler_;
     10391    assert (!statistics_);
     10392    delete [] walkback_;
     10393    //delete [] addedCuts_;
     10394    walkback_ = NULL;
     10395    //addedCuts_ = NULL;
     10396    assert(baseModel->solverCharacteristics_);
     10397    solverCharacteristics_ = new OsiBabSolver (*baseModel->solverCharacteristics_);
     10398    solverCharacteristics_->setSolver(solver_);
     10399    delete tree_;
     10400    tree_ = NULL;
     10401    delete nodeCompare_;
     10402    nodeCompare_ = NULL;
     10403    continuousSolver_ = baseModel->continuousSolver_->clone();
     10404    if (baseModel->branchingMethod_&&baseModel->branchingMethod_->chooseMethod()) {
     10405      // new method uses solver - but point to base model
     10406      numberObjects_=baseModel->numberObjects_;
     10407      object_=baseModel->object_;
     10408    }
     10409    mutex_ = baseModel->mutex_;
     10410    int i;
     10411    for (i=0;i<numberHeuristics_;i++) {
     10412      delete heuristic_[i];
     10413      heuristic_[i] = baseModel->heuristic_[i]->clone();
     10414      heuristic_[i]->setModelOnly(this);
     10415    }
     10416    for (i=0;i<numberCutGenerators_;i++) {
     10417      delete generator_[i];
     10418      generator_[i] = new CbcCutGenerator(*baseModel->generator_[i]);
     10419      // refreshModel was overkill as thought too many rows
     10420      generator_[i]->setModel(this);
     10421    }
     10422  }
     10423}
     10424#ifdef CBC_THREAD
     10425static void * doNodesThread(void * voidInfo)
     10426{
     10427  threadStruct * stuff = (threadStruct *) voidInfo;
     10428  pthread_mutex_t * mutex = stuff->mutex2;
     10429  pthread_cond_t * condition = stuff->condition2;
     10430  CbcModel * thisModel = stuff->thisModel;
     10431  CbcModel * baseModel = stuff->baseModel;
     10432  while (true) {
     10433    pthread_mutex_lock (mutex);
     10434    while (stuff->returnCode) {
     10435      struct timespec absTime2;
     10436      clock_gettime(CLOCK_REALTIME,&absTime2);
     10437      double time2 = absTime2.tv_sec+1.0e-9*absTime2.tv_nsec;
     10438      pthread_cond_wait(condition,mutex);
     10439      clock_gettime(CLOCK_REALTIME,&stuff->absTime);
     10440      double time = stuff->absTime.tv_sec+1.0e-9*stuff->absTime.tv_nsec;
     10441      stuff->timeWaitingToStart+=time-time2;;
     10442      stuff->numberTimesWaitingToStart++;
     10443    }
     10444    //printf("start node %x\n",stuff->node);
     10445    int mode = thisModel->getNumberThreads();
     10446    if (mode) {
     10447      // normal
     10448      double time2 = CoinCpuTime();
     10449      assert (stuff->returnCode==0);
     10450      assert (stuff->node->nodeInfo());
     10451      thisModel->doOneNode(baseModel,stuff->node,stuff->createdNode);
     10452      stuff->returnCode=1;
     10453      //printf("end node %x\n",stuff->node);
     10454#ifdef CONDITION_WAIT
     10455      threadStruct * stuffMain = (threadStruct *) baseModel->mutex();
     10456      //pthread_mutex_t * condition_mutex = stuffMain->mutex2;
     10457      pthread_cond_t * condition_main = stuffMain->condition2;
     10458      pthread_cond_signal(condition_main); // unlock
     10459#endif
     10460      pthread_mutex_unlock(mutex);
     10461      stuff->timeInThread += CoinCpuTime()-time2;
     10462    } else {
     10463      // exit
     10464      break;
     10465    }
     10466  }
     10467  pthread_mutex_unlock(mutex);
     10468  pthread_exit(NULL);
     10469}
     10470static void * doCutsThread(void * voidInfo)
     10471{
     10472  threadStruct * stuff = (threadStruct *) voidInfo;
     10473  pthread_mutex_t * mutex = stuff->mutex2;
     10474  pthread_cond_t * condition = stuff->condition2;
     10475  CbcModel * thisModel =  stuff->thisModel;
     10476  CbcModel * baseModel = stuff->baseModel;
     10477  while (true) {
     10478    pthread_mutex_lock(mutex);
     10479    while (stuff->returnCode) {
     10480      pthread_cond_wait(condition,mutex);
     10481    }
     10482    //printf("start node %x\n",stuff->node);
     10483    int mode = thisModel->getNumberThreads();
     10484    if (mode) {
     10485      // normal
     10486      assert (stuff->returnCode==0);
     10487      bool fullScan = thisModel->getNodeCount()>0;
     10488      CbcCutGenerator * generator = thisModel->cutGenerator(0);
     10489      OsiCuts * cuts = (OsiCuts *) thisModel->objects();
     10490      OsiSolverInterface * thisSolver = thisModel->solver();
     10491      generator->generateCuts(*cuts,fullScan,thisSolver,NULL);
     10492      stuff->returnCode=1;
     10493      //printf("end node %x\n",stuff->node);
     10494#ifdef CONDITION_WAIT
     10495      threadStruct * stuffMain = (threadStruct *) baseModel->mutex();
     10496      //pthread_mutex_t * condition_mutex = stuffMain->mutex2;
     10497      pthread_cond_t * condition_main = stuffMain->condition2;
     10498      pthread_cond_signal(condition_main); // unlock
     10499#endif
     10500      pthread_mutex_unlock(mutex);
     10501    } else {
     10502      // exit
     10503      break;
     10504    }
     10505  }
     10506  pthread_mutex_unlock(mutex);
     10507  pthread_exit(NULL);
     10508}
     10509#endif
     10510#endif
     10511#if CBC_THREAD_DEBUG
     10512static int threadFlag=0;
     10513/*
     10514  -100 all quiet
     10515  k locked
     10516  k+n*100 locked for n'th time
     10517  -k unlocked when already unlocked
     10518*/
     10519static int lastAction=-100;
     10520#if CBC_THREAD_DEBUG>1
     10521#define MAX_DEBUG 10000000
     10522static int numberActions=0;
     10523static int action[MAX_DEBUG];
     10524#endif
     10525#endif
     10526#ifdef CBC_THREAD
     10527/*
     10528  Locks a thread if parallel so that stuff like cut pool
     10529  can be updated and/or used.y
     10530*/
     10531void
     10532CbcModel::lockThread()
     10533{
     10534  threadStruct * stuff = (threadStruct *) mutex_;
     10535  if (stuff) {
     10536    if(!stuff->locked) {
     10537      struct timespec absTime2;
     10538      clock_gettime(CLOCK_REALTIME,&absTime2);
     10539      double time2 = absTime2.tv_sec+1.0e-9*absTime2.tv_nsec;
     10540      pthread_mutex_lock (stuff->mutex);
     10541      stuff->locked=true;
     10542      clock_gettime(CLOCK_REALTIME,&stuff->absTime);
     10543      double time = stuff->absTime.tv_sec+1.0e-9*stuff->absTime.tv_nsec;
     10544      stuff->timeWaitingToLock+=time-time2;;
     10545      stuff->numberTimesLocked++;
     10546#if CBC_THREAD_DEBUG
     10547      if (lastAction==-100) {
     10548        lastAction = stuff->threadNumber;
     10549      } else if (lastAction<=0) {
     10550        printf ("thread %d was over unlocked - now locked by %d\n",
     10551                lastAction,stuff->threadNumber);
     10552        lastAction = stuff->threadNumber;
     10553      } else if ((lastAction%100)==stuff->threadNumber) {
     10554        printf ("thread %d was already locked at level %d\n",
     10555                stuff->threadNumber,lastAction);
     10556        lastAction += 100;
     10557      } else {
     10558        printf ("thread %d was locked - now lock wanted by %d\n",
     10559                lastAction,stuff->threadNumber);
     10560        abort();
     10561      }
     10562#if CBC_THREAD_DEBUG>1
     10563      assert (numberActions<MAX_DEBUG);
     10564      action[numberActions++] = lastAction;
     10565#endif
     10566      assert (threadFlag==0);
     10567      threadFlag=1;
     10568    } else {
     10569      if (lastAction>0&&(lastAction%100)==stuff->threadNumber) {
     10570        //printf ("OKish - thread %d was already locked at level %d\n",
     10571        //stuff->threadNumber,lastAction);
     10572        lastAction += 100;
     10573      } else {
     10574        printf ("lastAction %d - now second lock wanted by %d\n",
     10575                lastAction,stuff->threadNumber);
     10576        abort();
     10577      }
     10578#if CBC_THREAD_DEBUG>1
     10579      assert (numberActions<MAX_DEBUG);
     10580      action[numberActions++] = lastAction;
     10581#endif
     10582      assert (threadFlag==1);
     10583#endif
     10584    }
     10585  }
     10586}
     10587/*
     10588  Unlocks a thread if parallel
     10589*/
     10590void
     10591CbcModel::unlockThread()
     10592{
     10593  threadStruct * stuff = (threadStruct *) mutex_;
     10594  if (stuff) {
     10595    if(stuff->locked) {
     10596#if CBC_THREAD_DEBUG
     10597      if (lastAction>0&&(lastAction%100)==stuff->threadNumber) {
     10598        lastAction = -100;
     10599      } else {
     10600        printf ("lastAction %d - %d trying to unlock\n",
     10601                lastAction,stuff->threadNumber);
     10602        abort();
     10603      }
     10604#if CBC_THREAD_DEBUG>1
     10605      assert (numberActions<MAX_DEBUG);
     10606      action[numberActions++] = lastAction;
     10607#endif
     10608      assert (threadFlag==1);
     10609      threadFlag=0;
     10610#endif
     10611      stuff->locked=false;
     10612      pthread_mutex_unlock (stuff->mutex);
     10613      struct timespec absTime2;
     10614      clock_gettime(CLOCK_REALTIME,&absTime2);
     10615      double time2 = absTime2.tv_sec+1.0e-9*absTime2.tv_nsec;
     10616      double time = stuff->absTime.tv_sec+1.0e-9*stuff->absTime.tv_nsec;
     10617      stuff->timeLocked+=time2-time;
     10618      stuff->numberTimesUnlocked++;
     10619#if CBC_THREAD_DEBUG
     10620    } else {
     10621      printf ("lastAction %d - %d trying to unlock when flag says unlocked!\n",
     10622              lastAction,stuff->threadNumber);
     10623      lastAction = -100;
     10624#if CBC_THREAD_DEBUG>1
     10625      assert (numberActions<MAX_DEBUG);
     10626      action[numberActions++] = lastAction;
     10627#endif
     10628      assert (threadFlag==0);
     10629#endif
     10630    }
     10631  }
     10632}
     10633#endif
     10634// Returns true if locked
     10635bool
     10636CbcModel::isLocked() const
     10637{
     10638#ifdef CBC_THREAD
     10639  threadStruct * stuff = (threadStruct *) mutex_;
     10640  if (stuff) {
     10641    return (stuff->locked);
     10642  } else {
     10643    return true;
     10644  }
     10645#else
     10646  return true;
     10647#endif
     10648}
Note: See TracChangeset for help on using the changeset viewer.