source: trunk/Cbc/src/CbcModel.cpp @ 1130

Last change on this file since 1130 was 1130, checked in by forrest, 10 years ago

minor changes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 481.3 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3#if defined(_MSC_VER)
4// Turn off compiler warning about long names
5#  pragma warning(disable:4786)
6#endif
7#define MODEL1 0
8#define MODEL2 0
9#define MODEL3 1
10#define MODEL4 0
11#define MODEL5 1
12#define MODEL6 0
13#define MODEL7 0
14#define MODEL8 0
15#define MODEL10 1
16#define MODEL11 0
17#define MODEL12 1
18#define MODEL13 1
19
20#include "CbcConfig.h"
21//static int nXXXXXX=0;
22
23#include <string>
24//#define CBC_DEBUG 1
25//#define CHECK_CUT_COUNTS
26//#define CHECK_NODE_FULL
27//#define NODE_LOG
28//#define GLOBAL_CUTS_JUST_POINTERS
29#ifndef CLP_FAST_CODE
30#ifdef NDEBUG
31#undef NDEBUG
32#endif
33#endif
34#include <cassert>
35#include <cmath>
36#include <cfloat>
37
38#ifdef COIN_HAS_CLP
39// include Presolve from Clp
40#include "ClpPresolve.hpp"
41#include "OsiClpSolverInterface.hpp"
42#include "ClpNode.hpp"
43#include "ClpDualRowDantzig.hpp"
44#include "ClpSimplexPrimal.hpp"
45#endif
46
47#include "CbcEventHandler.hpp"
48
49#include "OsiSolverInterface.hpp"
50#include "OsiAuxInfo.hpp"
51#include "OsiSolverBranch.hpp"
52#include "OsiChooseVariable.hpp"
53#include "CoinWarmStartBasis.hpp"
54#include "CoinPackedMatrix.hpp"
55#include "CoinHelperFunctions.hpp"
56#include "CbcBranchActual.hpp"
57#include "CbcBranchDynamic.hpp"
58#include "CbcHeuristic.hpp"
59#include "CbcHeuristicFPump.hpp"
60#include "CbcModel.hpp"
61#include "CbcTreeLocal.hpp"
62#include "CbcStatistics.hpp"
63#include "CbcStrategy.hpp"
64#include "CbcMessage.hpp"
65#include "OsiRowCut.hpp"
66#include "OsiColCut.hpp"
67#include "OsiRowCutDebugger.hpp"
68#include "OsiCuts.hpp"
69#include "CbcCountRowCut.hpp"
70#include "CbcCutGenerator.hpp"
71#include "CbcFeasibilityBase.hpp"
72#include "CbcFathom.hpp"
73// include Probing
74#include "CglProbing.hpp"
75// include preprocessing
76#include "CglPreProcess.hpp"
77#include "CglDuplicateRow.hpp"
78#include "CglStored.hpp"
79#include "CglClique.hpp"
80
81#include "CoinTime.hpp"
82#include "CoinMpsIO.hpp"
83
84#include "CbcCompareActual.hpp"
85#include "CbcTree.hpp"
86#ifdef CBC_THREAD
87#include <pthread.h>
88#ifdef HAVE_CLOCK_GETTIME
89inline int my_gettime(struct timespec* tp) {
90        return clock_gettime(CLOCK_REALTIME, tp);
91}
92#else
93//struct timespec {
94//      time_t tv_sec;
95//      long tv_nsec;
96//};
97inline int my_gettime(struct timespec* tp) {
98        struct timeval tv;
99        int ret = gettimeofday(&tv, NULL);
100        tp->tv_sec = tv.tv_sec;
101        tp->tv_nsec = tv.tv_usec*1000;
102        return ret;
103}
104#endif
105//#include "clocktime.hpp"
106//#undef small
107
108struct Coin_pthread_t {
109        pthread_t       thr;
110        long            status;
111};
112
113#ifndef CLP_FAST_CODE
114#define CBC_THREAD_DEBUG 1
115#endif
116#ifdef CBC_THREAD_DEBUG
117#ifdef NDEBUG
118#undef NDEBUG
119#undef assert
120#         define assert(expression) {                              \
121             if (!(expression)) {                                          \
122                throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \
123                                "", __FILE__, __LINE__);                   \
124             }                                                             \
125          }
126#endif
127#endif
128// To Pass across to doOneNode
129typedef struct {
130  CbcModel * baseModel;
131  CbcModel * thisModel;
132  CbcNode * node; // filled in every time
133  CbcNode * createdNode; // filled in every time on return
134  Coin_pthread_t threadIdOfBase;
135  pthread_mutex_t * mutex; // for locking data
136  pthread_mutex_t * mutex2; // for waking up threads
137  pthread_cond_t * condition2; // for waking up thread
138  int returnCode; // -1 available, 0 busy, 1 finished , 2??
139  double timeLocked;
140  double timeWaitingToLock;
141  double timeWaitingToStart;
142  double timeInThread;
143  int numberTimesLocked;
144  int numberTimesUnlocked;
145  int numberTimesWaitingToStart;
146  int saveStuff[2];
147  int dantzigState; // 0 unset, -1 waiting to be set, 1 set
148  struct timespec absTime;
149  bool locked;
150#if CBC_THREAD_DEBUG
151  int threadNumber;
152#endif
153  int nDeleteNode;
154  CbcNode ** delNode;
155  int maxDeleteNode;
156  int nodesThisTime;
157  int iterationsThisTime;
158} threadStruct;
159static void * doNodesThread(void * voidInfo);
160static void * doCutsThread(void * voidInfo);
161#endif
162/* Various functions local to CbcModel.cpp */
163
164namespace {
165
166//-------------------------------------------------------------------
167// Returns the greatest common denominator of two
168// positive integers, a and b, found using Euclid's algorithm
169//-------------------------------------------------------------------
170static int gcd(int a, int b) 
171{
172  int remainder = -1;
173  // make sure a<=b (will always remain so)
174  if(a > b) {
175    // Swap a and b
176    int temp = a;
177    a = b;
178    b = temp;
179  }
180  // if zero then gcd is nonzero (zero may occur in rhs of packed)
181  if (!a) {
182    if (b) {
183      return b;
184    } else {
185      printf("**** gcd given two zeros!!\n");
186      abort();
187    }
188  }
189  while (remainder) {
190    remainder = b % a;
191    b = a;
192    a = remainder;
193  }
194  return b;
195}
196
197
198
199#ifdef CHECK_NODE_FULL
200
201/*
202  Routine to verify that tree linkage is correct. The invariant that is tested
203  is
204
205  reference count = (number of actual references) + (number of branches left)
206
207  The routine builds a set of paired arrays, info and count, by traversing the
208  tree. Each CbcNodeInfo is recorded in info, and the number of times it is
209  referenced (via the parent field) is recorded in count. Then a final check is
210  made to see if the numberPointingToThis_ field agrees.
211*/
212
213void verifyTreeNodes (const CbcTree * branchingTree, const CbcModel &model)
214
215{if (model.getNodeCount()==661) return;  printf("*** CHECKING tree after %d nodes\n",model.getNodeCount()) ;
216 
217  int j ;
218  int nNodes = branchingTree->size() ;
219# define MAXINFO 1000
220  int *count = new int [MAXINFO] ;
221  CbcNodeInfo **info = new CbcNodeInfo*[MAXINFO] ;
222  int nInfo = 0 ;
223/*
224  Collect all CbcNodeInfo objects in info, by starting from each live node and
225  traversing back to the root. Nodes in the live set should have unexplored
226  branches remaining.
227
228  TODO: The `while (nodeInfo)' loop could be made to break on reaching a
229        common ancester (nodeInfo is found in info[k]). Alternatively, the
230        check could change to signal an error if nodeInfo is not found above a
231        common ancestor.
232*/
233  for (j = 0 ; j < nNodes ; j++)
234  { CbcNode *node = branchingTree->nodePointer(j) ;
235  if (!node)
236    continue;
237    CbcNodeInfo *nodeInfo = node->nodeInfo() ; 
238    int change = node->nodeInfo()->numberBranchesLeft() ;
239    assert(change) ;
240    while (nodeInfo)
241    { int k ;
242      for (k = 0 ; k < nInfo ; k++)
243      { if (nodeInfo == info[k]) break ; }
244      if (k == nInfo)
245      { assert(nInfo < MAXINFO) ;
246        nInfo++ ;
247        info[k] = nodeInfo ;
248        count[k] = 0 ; }
249      nodeInfo = nodeInfo->parent() ; } }
250/*
251  Walk the info array. For each nodeInfo, look up its parent in info and
252  increment the corresponding count.
253*/
254  for (j = 0 ; j < nInfo ; j++)
255  { CbcNodeInfo *nodeInfo = info[j] ;
256    nodeInfo = nodeInfo->parent() ;
257    if (nodeInfo)
258    { int k ;
259      for (k = 0 ; k < nInfo ; k++)
260      { if (nodeInfo == info[k]) break ; }
261      assert (k < nInfo) ;
262      count[k]++ ; } }
263/*
264  Walk the info array one more time and check that the invariant holds. The
265  number of references (numberPointingToThis()) should equal the sum of the
266  number of actual references (held in count[]) plus the number of potential
267  references (unexplored branches, numberBranchesLeft()).
268*/
269  for (j = 0;j < nInfo;j++) {
270    CbcNodeInfo * nodeInfo = info[j] ;
271    if (nodeInfo) {
272      int k ;
273      for (k = 0;k < nInfo;k++)
274        if (nodeInfo == info[k])
275          break ;
276      printf("Nodeinfo %x - %d left, %d count\n",
277             nodeInfo,
278             nodeInfo->numberBranchesLeft(),
279             nodeInfo->numberPointingToThis()) ;
280      assert(nodeInfo->numberPointingToThis() ==
281             count[k]+nodeInfo->numberBranchesLeft()) ; } }
282
283  delete [] count ;
284  delete [] info ;
285 
286  return ; }
287
288#endif  /* CHECK_NODE_FULL */
289
290
291
292#ifdef CHECK_CUT_COUNTS
293
294/*
295  Routine to verify that cut reference counts are correct.
296*/
297void verifyCutCounts (const CbcTree * branchingTree, CbcModel &model)
298
299{ printf("*** CHECKING cuts after %d nodes\n",model.getNodeCount()) ;
300
301  int j ;
302  int nNodes = branchingTree->size() ;
303
304/*
305  cut.tempNumber_ exists for the purpose of doing this verification. Clear it
306  in all cuts. We traverse the tree by starting from each live node and working
307  back to the root. At each CbcNodeInfo, check for cuts.
308*/
309  for (j = 0 ; j < nNodes ; j++)
310  { CbcNode *node = branchingTree->nodePointer(j) ;
311    CbcNodeInfo * nodeInfo = node->nodeInfo() ;
312    assert (node->nodeInfo()->numberBranchesLeft()) ;
313    while (nodeInfo)
314    { int k ;
315      for (k = 0 ; k < nodeInfo->numberCuts() ; k++)
316      { CbcCountRowCut *cut = nodeInfo->cuts()[k] ;
317        if (cut) cut->tempNumber_ = 0; }
318      nodeInfo = nodeInfo->parent() ; } }
319/*
320  Walk the live set again, this time collecting the list of cuts in use at each
321  node. addCuts1 will collect the cuts in model.addedCuts_. Take into account
322  that when we recreate the basis for a node, we compress out the slack cuts.
323*/
324  for (j = 0 ; j < nNodes ; j++)
325  { CoinWarmStartBasis *debugws = model.getEmptyBasis() ;
326    CbcNode *node = branchingTree->nodePointer(j) ;
327    CbcNodeInfo *nodeInfo = node->nodeInfo(); 
328    int change = node->nodeInfo()->numberBranchesLeft() ;
329    printf("Node %d %x (info %x) var %d way %d obj %g",j,node,
330           node->nodeInfo(),node->columnNumber(),node->way(),
331           node->objectiveValue()) ;
332
333    model.addCuts1(node,debugws) ;
334
335    int i ;
336    int numberRowsAtContinuous = model.numberRowsAtContinuous() ;
337    CbcCountRowCut **addedCuts = model.addedCuts() ;
338    for (i = 0 ; i < model.currentNumberCuts() ; i++)
339    { CoinWarmStartBasis::Status status = 
340        debugws->getArtifStatus(i+numberRowsAtContinuous) ;
341      if (status != CoinWarmStartBasis::basic && addedCuts[i])
342      { addedCuts[i]->tempNumber_ += change ; } }
343
344    while (nodeInfo)
345    { nodeInfo = nodeInfo->parent() ;
346      if (nodeInfo) printf(" -> %x",nodeInfo); }
347    printf("\n") ;
348    delete debugws ; }
349/*
350  The moment of truth: We've tallied up the references by direct scan of the  search tree. Check for agreement with the count in the cut.
351
352  TODO: Rewrite to check and print mismatch only when tempNumber_ == 0?
353*/
354  for (j = 0 ; j < nNodes ; j++)
355  { CbcNode *node = branchingTree->nodePointer(j) ;
356    CbcNodeInfo *nodeInfo = node->nodeInfo(); 
357    while (nodeInfo)
358    { int k ;
359      for (k = 0 ; k < nodeInfo->numberCuts() ; k++)
360      { CbcCountRowCut *cut = nodeInfo->cuts()[k] ;
361        if (cut && cut->tempNumber_ >= 0)
362        { if (cut->tempNumber_ != cut->numberPointingToThis()) 
363            printf("mismatch %x %d %x %d %d\n",nodeInfo,k,
364                    cut,cut->tempNumber_,cut->numberPointingToThis()) ;
365          else
366            printf("   match %x %d %x %d %d\n", nodeInfo,k,
367                   cut,cut->tempNumber_,cut->numberPointingToThis()) ;
368          cut->tempNumber_ = -1 ; } }
369      nodeInfo = nodeInfo->parent() ; } }
370
371  return ; }
372
373#endif /* CHECK_CUT_COUNTS */
374
375
376//#define CHECK_CUT_SIZE
377#ifdef CHECK_CUT_SIZE
378
379/*
380  Routine to verify that cut reference counts are correct.
381*/
382void verifyCutSize (const CbcTree * branchingTree, CbcModel &model)
383{ 
384
385  int j ;
386  int nNodes = branchingTree->size() ;
387  int totalCuts=0;
388
389/*
390  cut.tempNumber_ exists for the purpose of doing this verification. Clear it
391  in all cuts. We traverse the tree by starting from each live node and working
392  back to the root. At each CbcNodeInfo, check for cuts.
393*/
394  for (j = 0 ; j < nNodes ; j++) {
395    CbcNode *node = branchingTree->nodePointer(j) ;
396    CbcNodeInfo * nodeInfo = node->nodeInfo() ;
397    assert (node->nodeInfo()->numberBranchesLeft()) ;
398    while (nodeInfo) {
399      totalCuts += nodeInfo->numberCuts();
400      nodeInfo = nodeInfo->parent() ;
401    }
402  }
403  printf("*** CHECKING cuts (size) after %d nodes - %d cuts\n",model.getNodeCount(),totalCuts) ;
404  return ;
405}
406
407#endif /* CHECK_CUT_SIZE */
408
409}
410
411 /* End unnamed namespace for CbcModel.cpp */
412
413
414static double trueIncrement=0.0;
415void 
416CbcModel::analyzeObjective ()
417/*
418  Try to find a minimum change in the objective function. The first scan
419  checks that there are no continuous variables with non-zero coefficients,
420  and grabs the largest objective coefficient associated with an unfixed
421  integer variable. The second scan attempts to scale up the objective
422  coefficients to a point where they are sufficiently close to integer that
423  we can pretend they are integer, and calculate a gcd over the coefficients
424  of interest. This will be the minimum increment for the scaled coefficients.
425  The final action is to scale the increment back for the original coefficients
426  and install it, if it's better than the existing value.
427
428  John's note: We could do better than this.
429
430  John's second note - apologies for changing s to z
431*/
432{ const double *objective = getObjCoefficients() ;
433  const double *lower = getColLower() ;
434  const double *upper = getColUpper() ;
435  /*
436    Scan continuous and integer variables to see if continuous
437    are cover or network with integral rhs.
438  */
439  double continuousMultiplier = 1.0;
440  double * coeffMultiplier=NULL;
441  {
442    const double *rowLower = getRowLower() ;
443    const double *rowUpper = getRowUpper() ;
444    int numberRows = solver_->getNumRows() ;
445    double * rhs = new double [numberRows];
446    memset(rhs,0,numberRows*sizeof(double));
447    int iColumn;
448    int numberColumns = solver_->getNumCols() ;
449    // Column copy of matrix
450    bool allPlusOnes=true;
451    bool allOnes=true;
452    int problemType=-1;
453    const double * element = solver_->getMatrixByCol()->getElements();
454    const int * row = solver_->getMatrixByCol()->getIndices();
455    const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
456    const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
457    int numberInteger=0;
458    int numberIntegerObj=0;
459    int numberGeneralIntegerObj=0;
460    int numberIntegerWeight=0;
461    int numberContinuousObj=0;
462    double cost=COIN_DBL_MAX;
463    for (iColumn=0;iColumn<numberColumns;iColumn++) {
464      if (upper[iColumn]==lower[iColumn]) {
465        CoinBigIndex start = columnStart[iColumn];
466        CoinBigIndex end = start + columnLength[iColumn];
467        for (CoinBigIndex j=start;j<end;j++) {
468          int iRow = row[j];
469          rhs[iRow] += lower[iColumn]*element[j];
470        }
471      } else {
472        double objValue = objective[iColumn];
473        if(solver_->isInteger(iColumn)) 
474          numberInteger++;
475        if (objValue) {
476          if(!solver_->isInteger(iColumn)) {
477            numberContinuousObj++;
478          } else {
479            numberIntegerObj++;
480            if (cost==COIN_DBL_MAX)
481              cost = objValue;
482            else if (cost!=objValue)
483              cost=-COIN_DBL_MAX;
484            int gap = static_cast<int> (upper[iColumn]-lower[iColumn]);
485            if (gap>1) {
486              numberGeneralIntegerObj++;
487              numberIntegerWeight+=gap;
488            }
489          }
490        }
491      }
492    }
493    int iType=0;
494    if (!numberContinuousObj&&numberIntegerObj<=5&&numberIntegerWeight<=100&&
495        numberIntegerObj*3<numberObjects_&&!parentModel_&&solver_->getNumRows()>100) 
496      iType=3;
497    else if (!numberContinuousObj&&numberIntegerObj<=100&&
498        numberIntegerObj*5<numberObjects_&&numberIntegerWeight<=100&&
499             !parentModel_&&
500             solver_->getNumRows()>100&&cost!=-COIN_DBL_MAX) 
501      iType=2;
502    else if (!numberContinuousObj&&numberIntegerObj<=100&&
503        numberIntegerObj*5<numberObjects_&&
504             !parentModel_&&
505             solver_->getNumRows()>100&&cost!=-COIN_DBL_MAX) 
506      iType=8;
507    //else if (!numberContinuousObj&&
508    //numberIntegerObj*20<numberObjects_&&!parentModel_&&
509    //     solver_->getNumRows()>100)
510    //iType=8;
511    int iTest =getMaximumNodes();
512#if 0
513    // Give priority to costed in probing if few
514    if (!numberContinuousObj&&numberIntegerObj<=100&&
515        numberIntegerObj*5<numberObjects_)
516        specialOptions_ |= xxxx;
517#endif
518    if (iTest>=987654320&&iTest<987654330&&numberObjects_&&!parentModel_) {
519      iType = iTest-987654320;
520      printf("Testing %d integer variables out of %d objects (%d integer) have cost of %g - %d continuous\n",
521             numberIntegerObj,numberObjects_,numberInteger,cost,numberContinuousObj);
522      if (iType==9)
523        exit(77);
524      if (numberContinuousObj) 
525        iType=0;
526    }
527       
528    //if (!numberContinuousObj&&(numberIntegerObj<=5||cost!=-COIN_DBL_MAX)&&
529    //numberIntegerObj*3<numberObjects_&&!parentModel_&&solver_->getNumRows()>100) {
530    if (iType) {
531      /*
532        A) put high priority on (if none)
533        B) create artificial objective (if clp)
534      */
535      int iPriority=-1;
536      for (int i=0;i<numberObjects_;i++) {
537        int k = object_[i]->priority();
538        if (iPriority==-1)
539          iPriority=k;
540        else if (iPriority!=k)
541          iPriority=-2;
542      }
543      bool branchOnSatisfied=((iType&1)!=0);
544      bool createFake=((iType&2)!=0);
545      bool randomCost=((iType&4)!=0);
546      if (iPriority>=0) {
547        char general[200];
548        if (cost==-COIN_DBL_MAX)
549          sprintf(general,"%d integer variables out of %d objects (%d integer) have costs - high priority",
550                  numberIntegerObj,numberObjects_,numberInteger);
551        else
552          sprintf(general,"%d integer variables out of %d objects (%d integer) have cost of %g - high priority",
553                  numberIntegerObj,numberObjects_,numberInteger,cost);
554        messageHandler()->message(CBC_GENERAL,
555                                  messages())
556          << general << CoinMessageEol ;
557        sprintf(general,"branch on satisfied %c create fake objective %c random cost %c",
558               branchOnSatisfied ? 'Y' :'N',
559               createFake ? 'Y' :'N',
560               randomCost ? 'Y' :'N');
561        messageHandler()->message(CBC_GENERAL,
562                                  messages())
563          << general << CoinMessageEol ;
564        // switch off clp type branching
565        fastNodeDepth_ = -1;
566        int highPriority = (branchOnSatisfied) ? -999 : 100;
567        for (int i=0;i<numberObjects_;i++) {
568          CbcSimpleInteger * thisOne = dynamic_cast <CbcSimpleInteger *> (object_[i]);
569          object_[i]->setPriority(1000);
570          if (thisOne) {
571            int iColumn = thisOne->columnNumber();
572            if (objective[iColumn])
573              thisOne->setPriority(highPriority);
574          }
575        }
576      }
577#ifdef COIN_HAS_CLP
578      OsiClpSolverInterface * clpSolver
579        = dynamic_cast<OsiClpSolverInterface *> (solver_);
580      if (clpSolver&&createFake) {
581        // Create artificial objective to be used when all else fixed
582        int numberColumns = clpSolver->getNumCols();
583        double * fakeObj = new double [numberColumns];
584        // Column copy
585        const CoinPackedMatrix  * matrixByCol = clpSolver->getMatrixByCol();
586        //const double * element = matrixByCol.getElements();
587        //const int * row = matrixByCol.getIndices();
588        //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
589        const int * columnLength = matrixByCol->getVectorLengths();
590        for (int i=0;i<numberColumns;i++) {
591          double lowerValue=lower[i];
592          double upperValue=upper[i];
593          double value = (randomCost) ? ceil((CoinDrand48()+0.5)*1000)
594            : i+1;
595          value *= 0.001;
596          value += columnLength[i];
597          if (lowerValue>-1.0e5||upperValue<1.0e5) {
598            if (fabs(lowerValue)>fabs(upperValue))
599              value = - value;
600          } else {
601            value=0.0;
602          }
603          if (clpSolver->isInteger(i))
604            value *= 100;
605          fakeObj[i]=value;
606        }
607        // pass to solver
608        clpSolver->setFakeObjective(fakeObj);
609        delete [] fakeObj;
610      }
611#endif
612    }
613    int iRow;
614    for (iRow=0;iRow<numberRows;iRow++) {
615      if (rowLower[iRow]>-1.0e20&&
616          fabs(rowLower[iRow]-rhs[iRow]-floor(rowLower[iRow]-rhs[iRow]+0.5))>1.0e-10) {
617        continuousMultiplier=0.0;
618        break;
619      }
620      if (rowUpper[iRow]<1.0e20&&
621          fabs(rowUpper[iRow]-rhs[iRow]-floor(rowUpper[iRow]-rhs[iRow]+0.5))>1.0e-10) {
622        continuousMultiplier=0.0;
623        break;
624      }
625      // set rhs to limiting value
626      if (rowLower[iRow]!=rowUpper[iRow]) {
627        if(rowLower[iRow]>-1.0e20) {
628          if (rowUpper[iRow]<1.0e20) {
629            // no good
630            continuousMultiplier=0.0;
631            break;
632          } else {
633            rhs[iRow] = rowLower[iRow]-rhs[iRow];
634            if (problemType<0)
635              problemType=3; // set cover
636            else if (problemType!=3)
637              problemType=4;
638          }
639        } else {
640          rhs[iRow] = rowUpper[iRow]-rhs[iRow];
641            if (problemType<0)
642              problemType=1; // set partitioning <=
643            else if (problemType!=1)
644              problemType=4;
645        }
646      } else {
647        rhs[iRow] = rowUpper[iRow]-rhs[iRow];
648        if (problemType<0)
649          problemType=3; // set partitioning ==
650        else if (problemType!=2)
651          problemType=2;
652      }
653      if (fabs(rhs[iRow]-1.0)>1.0e-12)
654        problemType=4;
655    }
656    if (continuousMultiplier) {
657      // 1 network, 2 cover, 4 negative cover
658      int possible=7;
659      bool unitRhs=true;
660      // See which rows could be set cover
661      for (iColumn=0;iColumn<numberColumns;iColumn++) {
662        if (upper[iColumn] > lower[iColumn]+1.0e-8) {
663          CoinBigIndex start = columnStart[iColumn];
664          CoinBigIndex end = start + columnLength[iColumn];
665          for (CoinBigIndex j=start;j<end;j++) {
666            double value = element[j];
667            if (value==1.0) {
668            } else if (value==-1.0) {
669              rhs[row[j]]=-0.5;
670              allPlusOnes=false;
671            } else {
672              rhs[row[j]]=-COIN_DBL_MAX;
673              allOnes=false;
674            }
675          }
676        }
677      }
678      for (iColumn=0;iColumn<numberColumns;iColumn++) {
679        if (upper[iColumn] > lower[iColumn]+1.0e-8) {
680          if (!isInteger(iColumn)) {
681            CoinBigIndex start = columnStart[iColumn];
682            CoinBigIndex end = start + columnLength[iColumn];
683            double rhsValue=0.0;
684            // 1 all ones, -1 all -1s, 2 all +- 1, 3 no good
685            int type=0;
686            for (CoinBigIndex j=start;j<end;j++) {
687              double value = element[j];
688              if (fabs(value)!=1.0) {
689                type=3;
690                break;
691              } else if (value==1.0) {
692                if (!type) 
693                  type=1;
694                else if (type!=1)
695                  type=2;
696              } else {
697                if (!type) 
698                  type=-1;
699                else if (type!=-1)
700                  type=2;
701              }
702              int iRow = row[j];
703              if (rhs[iRow]==-COIN_DBL_MAX) {
704                type=3;
705                break;
706              } else if (rhs[iRow]==-0.5) {
707                // different values
708                unitRhs=false;
709              } else if (rhsValue) {
710                if (rhsValue!=rhs[iRow])
711                  unitRhs=false;
712              } else {
713                rhsValue=rhs[iRow];
714              }
715            }
716            // if no elements OK
717            if (type==3) {
718              // no good
719              possible=0;
720              break;
721            } else if (type==2) {
722              if (end-start>2) {
723                // no good
724                possible=0;
725                break;
726              } else {
727                // only network
728                possible &= 1;
729                if (!possible)
730                  break;
731              }
732            } else if (type==1) {
733              // only cover
734              possible &= 2;
735              if (!possible)
736                break;
737            } else if (type==-1) {
738              // only negative cover
739              possible &= 4;
740              if (!possible)
741                break;
742            }
743          }
744        }
745      }
746      if ((possible==2||possible==4)&&!unitRhs) {
747#if COIN_DEVELOP>1
748        printf("XXXXXX Continuous all +1 but different rhs\n");
749#endif
750        possible=0;
751      }
752      // may be all integer
753      if (possible!=7) {
754        if (!possible)
755          continuousMultiplier=0.0;
756        else if (possible==1)
757          continuousMultiplier=1.0;
758        else 
759          continuousMultiplier=0.0; // 0.5 was incorrect;
760#if COIN_DEVELOP>1
761        if (continuousMultiplier)
762          printf("XXXXXX multiplier of %g\n",continuousMultiplier);
763#endif
764        if (continuousMultiplier==0.5) {
765          coeffMultiplier=new double [numberColumns];
766          bool allOne=true;
767          for (iColumn=0;iColumn<numberColumns;iColumn++) {
768            coeffMultiplier[iColumn]=1.0;
769            if (upper[iColumn] > lower[iColumn]+1.0e-8) {
770              if (!isInteger(iColumn)) {
771                CoinBigIndex start = columnStart[iColumn];
772                int iRow = row[start];
773                double value = rhs[iRow];
774                assert (value>=0.0);
775                if (value!=0.0&&value!=1.0)
776                  allOne=false;
777                coeffMultiplier[iColumn]=0.5*value;
778              }
779            }
780          }
781          if (allOne) {
782            // back to old way
783            delete [] coeffMultiplier;
784            coeffMultiplier=NULL;
785          }
786        }
787      } else {
788        // all integer
789        problemType_= problemType;
790#if COIN_DEVELOP>1
791        printf("Problem type is %d\n",problemType_);
792#endif
793      }
794    }
795    // But try again
796    if (continuousMultiplier<1.0) {
797      memset(rhs,0,numberRows*sizeof(double));
798      int * count = new int [numberRows];
799      memset(count,0,numberRows*sizeof(int));
800      for (iColumn=0;iColumn<numberColumns;iColumn++) {
801        CoinBigIndex start = columnStart[iColumn];
802        CoinBigIndex end = start + columnLength[iColumn];
803        if (upper[iColumn]==lower[iColumn]) {
804          for (CoinBigIndex j=start;j<end;j++) {
805            int iRow = row[j];
806            rhs[iRow] += lower[iColumn]*element[j];
807          }
808        } else if (solver_->isInteger(iColumn)) {
809          for (CoinBigIndex j=start;j<end;j++) {
810            int iRow = row[j];
811            if (fabs(element[j]-floor(element[j]+0.5))>1.0e-10) 
812              rhs[iRow]  = COIN_DBL_MAX;
813          }
814        } else {
815          for (CoinBigIndex j=start;j<end;j++) {
816            int iRow = row[j];
817            count[iRow]++;
818            if (fabs(element[j])!=1.0)
819              rhs[iRow]  = COIN_DBL_MAX;
820          }
821        }
822      }
823      // now look at continuous
824      bool allGood=true;
825      double direction = solver_->getObjSense() ;
826      int numberObj=0;
827      for (iColumn=0;iColumn<numberColumns;iColumn++) {
828        if (upper[iColumn]>lower[iColumn]) {
829          double objValue = objective[iColumn]*direction;
830          if (objValue&&!solver_->isInteger(iColumn)) {
831            numberObj++;
832            CoinBigIndex start = columnStart[iColumn];
833            CoinBigIndex end = start + columnLength[iColumn];
834            if (objValue>0.0) {
835              // wants to be as low as possible
836              if (lower[iColumn]<-1.0e10||fabs(lower[iColumn]-floor(lower[iColumn]+0.5))>1.0e-10) {
837                allGood=false;
838                break;
839              } else if (upper[iColumn]<1.0e10&&fabs(upper[iColumn]-floor(upper[iColumn]+0.5))>1.0e-10) {
840                allGood=false;
841                break;
842              }
843              bool singletonRow=true;
844              bool equality=false;
845              for (CoinBigIndex j=start;j<end;j++) {
846                int iRow = row[j];
847                if (count[iRow]>1)
848                  singletonRow=false;
849                else if (rowLower[iRow]==rowUpper[iRow])
850                  equality=true;
851                if (fabs(rhs[iRow])>1.0e20||fabs(rhs[iRow]-floor(rhs[iRow]+0.5))>1.0e-10
852                    ||fabs(element[j])!=1.0) {
853                  // no good
854                  allGood=false;
855                  break;
856                }
857                if (element[j]>0.0) {
858                  if (rowLower[iRow]>-1.0e20&&fabs(rowLower[iRow]-floor(rowLower[iRow]+0.5))>1.0e-10) {
859                    // no good
860                    allGood=false;
861                    break;
862                  }
863                } else {
864                  if (rowUpper[iRow]<1.0e20&&fabs(rowUpper[iRow]-floor(rowUpper[iRow]+0.5))>1.0e-10) {
865                    // no good
866                    allGood=false;
867                    break;
868                  }
869                }
870              }
871              if (!singletonRow&&end>start+1&&!equality)
872                allGood=false;
873              if (!allGood)
874                break;
875            } else {
876              // wants to be as high as possible
877              if (upper[iColumn]>1.0e10||fabs(upper[iColumn]-floor(upper[iColumn]+0.5))>1.0e-10) {
878                allGood=false;
879                break;
880              } else if (lower[iColumn]>-1.0e10&&fabs(lower[iColumn]-floor(lower[iColumn]+0.5))>1.0e-10) {
881                allGood=false;
882                break;
883              }
884              bool singletonRow=true;
885              bool equality=false;
886              for (CoinBigIndex j=start;j<end;j++) {
887                int iRow = row[j];
888                if (count[iRow]>1)
889                  singletonRow=false;
890                else if (rowLower[iRow]==rowUpper[iRow])
891                  equality=true;
892                if (fabs(rhs[iRow])>1.0e20||fabs(rhs[iRow]-floor(rhs[iRow]+0.5))>1.0e-10
893                    ||fabs(element[j])!=1.0) {
894                  // no good
895                  allGood=false;
896                  break;
897                }
898                if (element[j]<0.0) {
899                  if (rowLower[iRow]>-1.0e20&&fabs(rowLower[iRow]-floor(rowLower[iRow]+0.5))>1.0e-10) {
900                    // no good
901                    allGood=false;
902                    break;
903                  }
904                } else {
905                  if (rowUpper[iRow]<1.0e20&&fabs(rowUpper[iRow]-floor(rowUpper[iRow]+0.5))>1.0e-10) {
906                    // no good
907                    allGood=false;
908                    break;
909                  }
910                }
911              }
912              if (!singletonRow&&end>start+1&&!equality)
913                allGood=false;
914              if (!allGood)
915                break;
916            }
917          }
918        }
919      }
920      delete [] count;
921      if (allGood) {
922#if COIN_DEVELOP>1
923        if (numberObj)
924          printf("YYYY analysis says all continuous with costs will be integer\n");
925#endif
926        continuousMultiplier=1.0;
927      }
928    }
929    delete [] rhs;
930  }
931/*
932  Take a first scan to see if there are unfixed continuous variables in the
933  objective.  If so, the minimum objective change could be arbitrarily small.
934  Also pick off the maximum coefficient of an unfixed integer variable.
935
936  If the objective is found to contain only integer variables, set the
937  fathoming discipline to strict.
938*/
939  double maximumCost = 0.0 ;
940  trueIncrement=0.0;
941  bool possibleMultiple = continuousMultiplier!=0.0 ;
942  int iColumn ;
943  int numberColumns = getNumCols() ;
944  if (possibleMultiple) {
945    for (iColumn = 0 ; iColumn < numberColumns ; iColumn++)
946      { if (upper[iColumn] > lower[iColumn]+1.0e-8)
947          { maximumCost = CoinMax(maximumCost,fabs(objective[iColumn])) ; } }
948  }
949  setIntParam(CbcModel::CbcFathomDiscipline,possibleMultiple) ;
950/*
951  If a nontrivial increment is possible, try and figure it out. We're looking
952  for gcd(c<j>) for all c<j> that are coefficients of unfixed integer
953  variables. Since the c<j> might not be integers, try and inflate them
954  sufficiently that they look like integers (and we'll deflate the gcd
955  later).
956
957  2520.0 is used as it is a nice multiple of 2,3,5,7
958*/
959    if (possibleMultiple&&maximumCost)
960    { int increment = 0 ;
961      double multiplier = 2520.0 ;
962      while (10.0*multiplier*maximumCost < 1.0e8)
963        multiplier *= 10.0 ;
964    int bigIntegers = 0; // Count of large costs which are integer
965    for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
966      if (upper[iColumn] > lower[iColumn]+1.0e-8) {
967        double objValue = fabs(objective[iColumn]);
968        if (!isInteger(iColumn)) {
969          if (!coeffMultiplier)
970            objValue *= continuousMultiplier;
971          else
972            objValue *= coeffMultiplier[iColumn];
973        }
974        if (objValue) {
975          double value = objValue*multiplier ;
976          if (value <2.1e9) {
977            int nearest = static_cast<int> (floor(value+0.5)) ;
978            if (fabs(value-floor(value+0.5)) > 1.0e-8)
979              { increment = 0 ;
980              break ; }
981            else if (!increment)
982              { increment = nearest ; }
983            else
984              { increment = gcd(increment,nearest) ; }
985          } else {
986            // large value - may still be multiple of 1.0
987            if (fabs(objValue-floor(objValue+0.5)) > 1.0e-8) {
988              increment=0;
989              break;
990            } else {
991              bigIntegers++;
992            }
993          }
994        }
995      }
996    }
997    delete [] coeffMultiplier;
998/*
999  If the increment beats the current value for objective change, install it.
1000*/
1001      if (increment)
1002      { double value = increment ;
1003        double cutoff = getDblParam(CbcModel::CbcCutoffIncrement) ;
1004        if (bigIntegers) {
1005          // allow for 1.0
1006          increment = gcd(increment,static_cast<int> (multiplier));
1007          value = increment;
1008        }
1009        value /= multiplier ;
1010        trueIncrement=CoinMax(cutoff,value);;
1011        if (value*0.999 > cutoff)
1012        { messageHandler()->message(CBC_INTEGERINCREMENT,
1013                                          messages())
1014            << value << CoinMessageEol ;
1015          setDblParam(CbcModel::CbcCutoffIncrement,value*0.999) ; } } }
1016
1017  return ; 
1018}
1019
1020
1021/**
1022  \todo
1023  Normally, it looks like we enter here from command dispatch in the main
1024  routine, after calling the solver for an initial solution
1025  (CbcModel::initialSolve, which simply calls the solver's initialSolve
1026  routine.) The first thing we do is call resolve. Presumably there are
1027  circumstances where this is nontrivial? There's also a call from
1028  CbcModel::originalModel (tied up with integer presolve), which should be
1029  checked.
1030
1031*/
1032
1033/*
1034  The overall flow can be divided into three stages:
1035    * Prep: Check that the lp relaxation remains feasible at the root. If so,
1036      do all the setup for B&C.
1037    * Process the root node: Generate cuts, apply heuristics, and in general do
1038      the best we can to resolve the problem without B&C.
1039    * Do B&C search until we hit a limit or exhaust the search tree.
1040 
1041  Keep in mind that in general there is no node in the search tree that
1042  corresponds to the active subproblem. The active subproblem is represented
1043  by the current state of the model,  of the solver, and of the constraint
1044  system held by the solver.
1045*/
1046//#define CHECK_PATH
1047#ifdef CHECK_PATH
1048extern const double * debuggerSolution_Z;
1049extern int numberColumns_Z;
1050#endif
1051void CbcModel::branchAndBound(int doStatistics) 
1052
1053{
1054/*
1055  Capture a time stamp before we start.
1056*/
1057  dblParam_[CbcStartSeconds] = CoinCpuTime();
1058  strongInfo_[0]=0;
1059  strongInfo_[1]=0;
1060  strongInfo_[2]=0;
1061  strongInfo_[3]=0;
1062  strongInfo_[4]=0;
1063  strongInfo_[5]=0;
1064  strongInfo_[6]=0;
1065  numberStrongIterations_ = 0;
1066  currentNode_ = NULL;
1067  CoinThreadRandom randomGenerator(1234567);
1068  // See if should do cuts old way
1069  if (parallelMode()<0) {
1070    specialOptions_ |= 4096+8192;
1071  } else if (parallelMode()>0) {
1072    specialOptions_ |= 4096;
1073  }
1074  if (dynamic_cast<CbcTreeLocal *> (tree_))
1075    specialOptions_ |= 4096+8192;
1076#ifdef COIN_HAS_CLP
1077 {
1078   OsiClpSolverInterface * clpSolver
1079     = dynamic_cast<OsiClpSolverInterface *> (solver_);
1080   if (clpSolver) {
1081     // pass in disaster handler
1082     CbcDisasterHandler handler(this);
1083     clpSolver->passInDisasterHandler(&handler);
1084     // Initialise solvers seed
1085     clpSolver->getModelPtr()->setRandomSeed(1234567);
1086#if MODEL1
1087     // reduce factorization frequency
1088     int frequency = clpSolver->getModelPtr()->factorizationFrequency();
1089     clpSolver->getModelPtr()->setFactorizationFrequency(CoinMin(frequency,120));
1090#endif
1091   }
1092 }
1093#endif
1094#ifndef NDEBUG
1095  {
1096#if COIN_DEVELOP>1
1097    double big = 1.0e12;
1098#else
1099    double big = 1.0e20;
1100#endif
1101    int i;
1102    int n = solver_->getNumCols();
1103    const double *lower = solver_->getColLower() ;
1104    const double *upper = solver_->getColUpper() ;
1105    for (i=0;i<n;i++) {
1106      assert (lower[i]<big);
1107      assert (upper[i]>-big);
1108    }
1109    n = solver_->getNumRows();
1110    lower = solver_->getRowLower() ;
1111    upper = solver_->getRowUpper() ;
1112    for (i=0;i<n;i++) {
1113      assert (lower[i]<big);
1114      assert (upper[i]>-big);
1115    }
1116  }
1117#endif
1118  // original solver (only set if pre-processing)
1119  OsiSolverInterface * originalSolver=NULL;
1120  int numberOriginalObjects=numberObjects_;
1121  OsiObject ** originalObject = NULL;
1122  // Set up strategies
1123#if 0
1124  std::string problemName ;
1125  solver_->getStrParam(OsiProbName,problemName) ;
1126  if (!strcmp(problemName.c_str(),"EGOUT")) solver_->activateRowCutDebugger(problemName.c_str()) ;
1127#endif
1128  if (strategy_) {
1129    // May do preprocessing
1130    originalSolver = solver_;
1131    strategy_->setupOther(*this);
1132    if (strategy_->preProcessState()) {
1133      // pre-processing done
1134      if (strategy_->preProcessState()<0) {
1135        // infeasible
1136        handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;
1137        status_ = 0 ;
1138        secondaryStatus_ = 1;
1139        originalContinuousObjective_ = COIN_DBL_MAX;
1140        return ; 
1141      } else if (numberObjects_&&object_) {
1142        numberOriginalObjects=numberObjects_;
1143        // redo sequence
1144        numberIntegers_=0;
1145        int numberColumns = getNumCols();
1146        int nOrig = originalSolver->getNumCols();
1147        CglPreProcess * process = strategy_->process();
1148        assert (process);
1149        const int * originalColumns = process->originalColumns();
1150        // allow for cliques etc
1151        nOrig = CoinMax(nOrig,originalColumns[numberColumns-1]+1);
1152        // try and redo debugger
1153        OsiRowCutDebugger * debugger = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
1154        if (debugger) 
1155          debugger->redoSolution(numberColumns,originalColumns);
1156        originalObject = object_;
1157        // object number or -1
1158        int * temp = new int[nOrig];
1159        int iColumn;
1160        for (iColumn=0;iColumn<nOrig;iColumn++) 
1161          temp[iColumn]=-1;
1162        int iObject;
1163        int nNonInt=0;
1164        for (iObject=0;iObject<numberOriginalObjects;iObject++) {
1165          iColumn = originalObject[iObject]->columnNumber();
1166          if (iColumn<0) {
1167            nNonInt++;
1168          } else {
1169            temp[iColumn]=iObject;
1170          }
1171        }
1172        int numberNewIntegers=0;
1173        int numberOldIntegers=0;
1174        int numberOldOther=0;
1175        for (iColumn=0;iColumn<numberColumns;iColumn++) {
1176          int jColumn = originalColumns[iColumn];
1177          if (temp[jColumn]>=0) {
1178            int iObject= temp[jColumn];
1179            CbcSimpleInteger * obj =
1180              dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
1181            if (obj) 
1182              numberOldIntegers++;
1183            else
1184              numberOldOther++;
1185          } else if (isInteger(iColumn)) {
1186            numberNewIntegers++;
1187          }
1188        }
1189        /*
1190          Allocate an array to hold the indices of the integer variables.
1191          Make a large enough array for all objects
1192        */
1193        numberObjects_= numberNewIntegers+numberOldIntegers+numberOldOther+nNonInt;
1194        object_ = new OsiObject * [numberObjects_];
1195        delete [] integerVariable_;
1196        integerVariable_ = new int [numberNewIntegers+numberOldIntegers];
1197        /*
1198          Walk the variables again, filling in the indices and creating objects for
1199          the integer variables. Initially, the objects hold the index and upper &
1200          lower bounds.
1201        */
1202        numberIntegers_=0;
1203        int n=originalColumns[numberColumns-1]+1;
1204        int * backward = new int[n];
1205        int i;
1206        for ( i=0;i<n;i++)
1207          backward[i]=-1;
1208        for (i=0;i<numberColumns;i++)
1209          backward[originalColumns[i]]=i;
1210        for (iColumn=0;iColumn<numberColumns;iColumn++) {
1211          int jColumn = originalColumns[iColumn];
1212          if (temp[jColumn]>=0) {
1213            int iObject= temp[jColumn];
1214            CbcSimpleInteger * obj =
1215              dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
1216            if (obj) {
1217              object_[numberIntegers_] = originalObject[iObject]->clone();
1218              // redo ids etc
1219              //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns);
1220              object_[numberIntegers_]->resetSequenceEtc(numberColumns,backward);
1221              integerVariable_[numberIntegers_++]=iColumn;
1222            }
1223          } else if (isInteger(iColumn)) {
1224            object_[numberIntegers_] =
1225              new CbcSimpleInteger(this,iColumn);
1226            integerVariable_[numberIntegers_++]=iColumn;
1227          }
1228        }
1229        delete [] backward;
1230        numberObjects_=numberIntegers_;
1231        // Now append other column stuff
1232        for (iColumn=0;iColumn<numberColumns;iColumn++) {
1233          int jColumn = originalColumns[iColumn];
1234          if (temp[jColumn]>=0) {
1235            int iObject= temp[jColumn];
1236            CbcSimpleInteger * obj =
1237              dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
1238            if (!obj) {
1239              object_[numberObjects_] = originalObject[iObject]->clone();
1240              // redo ids etc
1241              CbcObject * obj =
1242              dynamic_cast <CbcObject *>(object_[numberObjects_]) ;
1243              assert (obj);
1244              obj->redoSequenceEtc(this,numberColumns,originalColumns);
1245              numberObjects_++;
1246            }
1247          }
1248        }
1249        // now append non column stuff
1250        for (iObject=0;iObject<numberOriginalObjects;iObject++) {
1251          iColumn = originalObject[iObject]->columnNumber();
1252          if (iColumn<0) {
1253            object_[numberObjects_] = originalObject[iObject]->clone();
1254            // redo ids etc
1255            CbcObject * obj =
1256              dynamic_cast <CbcObject *>(object_[numberObjects_]) ;
1257            assert (obj);
1258            obj->redoSequenceEtc(this,numberColumns,originalColumns);
1259            numberObjects_++;
1260          }
1261        }
1262        delete [] temp;
1263        if (!numberObjects_)
1264          handler_->message(CBC_NOINT,messages_) << CoinMessageEol ;
1265      } else {
1266        int numberColumns = getNumCols();
1267        CglPreProcess * process = strategy_->process();
1268        assert (process);
1269        const int * originalColumns = process->originalColumns();
1270        // try and redo debugger
1271        OsiRowCutDebugger * debugger = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
1272        if (debugger)
1273          debugger->redoSolution(numberColumns,originalColumns);
1274      }
1275    } else {
1276      //no preprocessing
1277      originalSolver=NULL;
1278    }
1279    strategy_->setupCutGenerators(*this);
1280    strategy_->setupHeuristics(*this);
1281    // Set strategy print level to models
1282    strategy_->setupPrinting(*this,handler_->logLevel());
1283  }
1284  eventHappened_=false;
1285  CbcEventHandler *eventHandler = getEventHandler() ;
1286  if (eventHandler)
1287    eventHandler->setModel(this);
1288#if MODEL12
1289#define CLIQUE_ANALYSIS
1290#endif
1291#ifdef CLIQUE_ANALYSIS
1292  // set up for probing
1293  if (!parentModel_)
1294    probingInfo_ = new CglTreeProbingInfo(solver_);
1295  else
1296    probingInfo_=NULL;
1297#else
1298  probingInfo_=NULL;
1299#endif
1300
1301  // Try for dominated columns
1302  if ((specialOptions_&64)!=0) {
1303    CglDuplicateRow dupcuts(solver_);
1304    dupcuts.setMode(2);
1305    CglStored * storedCuts = dupcuts.outDuplicates(solver_);
1306    addCutGenerator(storedCuts,1,"StoredCuts from dominated");
1307  }
1308  if (!nodeCompare_)
1309    nodeCompare_=new CbcCompareDefault();;
1310  // See if hot start wanted
1311  CbcCompareBase * saveCompare = NULL;
1312  if (hotstartSolution_) {
1313    if (strategy_&&strategy_->preProcessState()>0) {
1314      CglPreProcess * process = strategy_->process();
1315      assert (process);
1316      int n = solver_->getNumCols();
1317      const int * originalColumns = process->originalColumns();
1318      // columns should be in order ... but
1319      double * tempS = new double[n];
1320      for (int i=0;i<n;i++) {
1321        int iColumn = originalColumns[i];
1322        tempS[i]=hotstartSolution_[iColumn];
1323      }
1324      delete [] hotstartSolution_;
1325      hotstartSolution_=tempS;
1326      if (hotstartPriorities_) {
1327        int * tempP = new int [n];
1328        for (int i=0;i<n;i++) {
1329          int iColumn = originalColumns[i];
1330          tempP[i]=hotstartPriorities_[iColumn];
1331        }
1332        delete [] hotstartPriorities_;
1333        hotstartPriorities_=tempP;
1334      }
1335    }
1336    saveCompare = nodeCompare_;
1337    // depth first
1338    nodeCompare_ = new CbcCompareDepth();
1339  }
1340  if (!problemFeasibility_)
1341    problemFeasibility_=new CbcFeasibilityBase();
1342# ifdef CBC_DEBUG
1343  std::string problemName ;
1344  solver_->getStrParam(OsiProbName,problemName) ;
1345  printf("Problem name - %s\n",problemName.c_str()) ;
1346  solver_->setHintParam(OsiDoReducePrint,false,OsiHintDo,0) ;
1347# endif
1348/*
1349  Assume we're done, and see if we're proven wrong.
1350*/
1351  status_ = 0 ;
1352  secondaryStatus_ = 0;
1353  phase_=0;
1354/*
1355  Scan the variables, noting the integer variables. Create an
1356  CbcSimpleInteger object for each integer variable.
1357*/
1358  findIntegers(false) ;
1359  // Say not dynamic pseudo costs
1360  ownership_ &= ~0x40000000;
1361  // If dynamic pseudo costs then do
1362  if (numberBeforeTrust_)
1363    convertToDynamic();
1364  // Set up char array to say if integer
1365  delete [] integerInfo_;
1366  {
1367    int n = solver_->getNumCols();
1368    integerInfo_ = new char [n];
1369    for (int i=0;i<n;i++) {
1370      if (solver_->isInteger(i))
1371        integerInfo_[i]=1;
1372      else
1373        integerInfo_[i]=0;
1374    }
1375  }
1376  if (preferredWay_) {
1377    // set all unset ones
1378    for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
1379      CbcObject * obj =
1380        dynamic_cast <CbcObject *>(object_[iObject]) ;
1381      if (obj&&!obj->preferredWay())
1382        obj->setPreferredWay(preferredWay_);
1383    }
1384  } 
1385/*
1386  Ensure that objects on the lists of OsiObjects, heuristics, and cut
1387  generators attached to this model all refer to this model.
1388*/
1389  synchronizeModel() ;
1390  if (!solverCharacteristics_) {
1391    OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
1392    if (solverCharacteristics) {
1393      solverCharacteristics_ = solverCharacteristics;
1394    } else {
1395      // replace in solver
1396      OsiBabSolver defaultC;
1397      solver_->setAuxiliaryInfo(&defaultC);
1398      solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
1399    }
1400  }
1401
1402  solverCharacteristics_->setSolver(solver_);
1403  // Set so we can tell we are in initial phase in resolve
1404  continuousObjective_ = -COIN_DBL_MAX ;
1405/*
1406  Solve the relaxation.
1407
1408  Apparently there are circumstances where this will be non-trivial --- i.e.,
1409  we've done something since initialSolve that's trashed the solution to the
1410  continuous relaxation.
1411*/
1412  /* Tell solver we are in Branch and Cut
1413     Could use last parameter for subtle differences */
1414  solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
1415#ifdef COIN_HAS_CLP
1416  {
1417    OsiClpSolverInterface * clpSolver
1418      = dynamic_cast<OsiClpSolverInterface *> (solver_);
1419    if (clpSolver) {
1420      //#define CLP_QUICK_OPTIONS
1421#ifdef CLP_QUICK_OPTIONS
1422      // Try and re-use regions   
1423      ClpSimplex * simplex = clpSolver->getModelPtr();
1424      simplex->setPersistenceFlag(1);
1425#if 0
1426      clpSolver->deleteScaleFactors();
1427      int value=131072;
1428      clpSolver->setSpecialOptions(clpSolver->specialOptions()|value);
1429      if ((clpSolver->specialOptions()&value)!=0)
1430        simplex->setSpecialOptions(simplex->specialOptions()|value);
1431#else
1432#undef CLP_QUICK_OPTIONS
1433      //if (simplex->numberRows()<50)
1434      //simplex->setAlphaAccuracy(1.0);
1435      //clpSolver->setSpecialOptions((clpSolver->specialOptions()&~128)|65536);
1436      //simplex->setMoreSpecialOptions(simplex->moreSpecialOptions()|4);
1437      //simplex->setSpecialOptions(simplex->specialOptions()|65536);
1438      //simplex->startPermanentArrays();
1439#endif
1440#endif
1441      ClpSimplex * clpSimplex = clpSolver->getModelPtr();
1442      if ((specialOptions_&32)==0) {
1443        // take off names
1444        clpSimplex->dropNames();
1445      }
1446      // no crunch if mostly continuous
1447      //int numberColumns = solver_->getNumCols()+1000000; // fake for testing
1448      int numberColumns = solver_->getNumCols();
1449      if (numberColumns>1000&&numberIntegers_*4<numberColumns)
1450        clpSolver->setSpecialOptions(clpSolver->specialOptions()&(~1));
1451      //#define NO_CRUNCH
1452#ifdef NO_CRUNCH
1453      printf("TEMP switching off crunch\n");
1454      int iOpt = clpSolver->specialOptions();
1455      iOpt &= ~1;
1456      iOpt |= 65536;
1457      clpSolver->setSpecialOptions(iOpt);
1458#endif
1459    }
1460  }
1461#endif
1462  bool feasible;
1463  // If NLP then we assume already solved outside branchAndbound
1464  if (!solverCharacteristics_->solverType()||solverCharacteristics_->solverType()==4) {
1465    feasible=resolve(NULL,0) != 0 ;
1466  } else {
1467    // pick up given status
1468    feasible = (solver_->isProvenOptimal() &&
1469                !solver_->isDualObjectiveLimitReached()) ;
1470  }
1471  if (problemFeasibility_->feasible(this,0)<0) {
1472    feasible=false; // pretend infeasible
1473  }
1474  int saveNumberStrong = numberStrong_;
1475  int saveNumberBeforeTrust = numberBeforeTrust_;
1476/*
1477  If the linear relaxation of the root is infeasible, bail out now. Otherwise,
1478  continue with processing the root node.
1479*/
1480  if (!feasible) {
1481    status_ = 0 ;
1482    if (!solver_->isProvenDualInfeasible()) {
1483      handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;
1484      secondaryStatus_ = 1;
1485    } else {
1486      handler_->message(CBC_UNBOUNDED,messages_)<< CoinMessageEol ;
1487      secondaryStatus_ = 7;
1488    }
1489    originalContinuousObjective_ = COIN_DBL_MAX;
1490    solverCharacteristics_ = NULL;
1491    return ;
1492  } else if (!numberObjects_) {
1493    // nothing to do
1494    solverCharacteristics_ = NULL;
1495    bestObjective_ = solver_->getObjValue()*solver_->getObjSense();
1496    int numberColumns = solver_->getNumCols();
1497    delete [] bestSolution_;
1498    bestSolution_ = new double[numberColumns];
1499    CoinCopyN(solver_->getColSolution(),numberColumns,bestSolution_);
1500    return ;
1501  }
1502  // Convert to Osi if wanted
1503  bool useOsiBranching=false;
1504  //OsiBranchingInformation * persistentInfo = NULL;
1505  if (branchingMethod_&&branchingMethod_->chooseMethod()) {
1506    useOsiBranching=true;
1507    //persistentInfo = new OsiBranchingInformation(solver_);
1508    if (numberOriginalObjects) {
1509      for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
1510        CbcObject * obj =
1511          dynamic_cast <CbcObject *>(object_[iObject]) ;
1512        if (obj) {
1513          CbcSimpleInteger * obj2 =
1514            dynamic_cast <CbcSimpleInteger *>(obj) ;
1515          if (obj2) {
1516            // back to Osi land
1517            object_[iObject]=obj2->osiObject();
1518            delete obj;
1519          } else {
1520            OsiSimpleInteger * obj3 =
1521              dynamic_cast <OsiSimpleInteger *>(obj) ;
1522            if (!obj3) {
1523              OsiSOS * obj4 =
1524                dynamic_cast <OsiSOS *>(obj) ;
1525              if (!obj4) {
1526                CbcSOS * obj5 =
1527                  dynamic_cast <CbcSOS *>(obj) ;
1528                if (obj5) {
1529                  // back to Osi land
1530                  object_[iObject]=obj5->osiObject(solver_);
1531                } else {
1532                  printf("Code up CbcObject type in Osi land\n");
1533                  abort();
1534                }
1535              }
1536            }
1537          }
1538        }
1539      }
1540      // and add to solver
1541      //if (!solver_->numberObjects()) {
1542        solver_->addObjects(numberObjects_,object_);
1543        //} else {
1544        //if (solver_->numberObjects()!=numberOriginalObjects) {
1545        //printf("should have trapped that solver has objects before\n");
1546        //abort();
1547        //}
1548        //}
1549    } else {
1550      // do from solver
1551      deleteObjects(false);
1552      solver_->findIntegersAndSOS(false);
1553      numberObjects_=solver_->numberObjects();
1554      object_ = solver_->objects();
1555      ownObjects_ = false;
1556    }
1557    branchingMethod_->chooseMethod()->setSolver(solver_);
1558  }
1559  // take off heuristics if have to
1560  {
1561    int numberOdd=0;
1562    int numberSOS=0;
1563    for (int i=0;i<numberObjects_;i++) {
1564      if (!object_[i]->canDoHeuristics()) 
1565        numberOdd++;
1566      CbcSOS * obj =
1567        dynamic_cast <CbcSOS *>(object_[i]) ;
1568      if (obj)
1569        numberSOS++;
1570    }
1571    if (numberOdd) {
1572      if (numberHeuristics_) {
1573        int k=0;
1574        for (int i=0;i<numberHeuristics_;i++) {
1575          if (!heuristic_[i]->canDealWithOdd())
1576            delete heuristic_[i];
1577          else
1578            heuristic_[k++]=heuristic_[i];
1579        }
1580        if (!k) {
1581          delete [] heuristic_;
1582          heuristic_=NULL;
1583        }
1584        numberHeuristics_=k;
1585        handler_->message(CBC_HEURISTICS_OFF,messages_)<< numberOdd<<CoinMessageEol ;
1586      }
1587    } else if (numberSOS) {
1588      specialOptions_ |= 128; // say can do SOS in dynamic mode
1589      // switch off fast nodes for now
1590      fastNodeDepth_ = -1;
1591    }
1592    if (numberThreads_>0) {
1593      // switch off fast nodes for now
1594      fastNodeDepth_ = -1;
1595    }
1596  }
1597  // Save objective (just so user can access it)
1598  originalContinuousObjective_ = solver_->getObjValue();
1599  bestPossibleObjective_=originalContinuousObjective_;
1600  sumChangeObjective1_=0.0;
1601  sumChangeObjective2_=0.0;
1602/*
1603  OsiRowCutDebugger knows an optimal answer for a subset of MIP problems.
1604  Assuming it recognises the problem, when called upon it will check a cut to
1605  see if it cuts off the optimal answer.
1606*/
1607  // If debugger exists set specialOptions_ bit
1608  if (solver_->getRowCutDebuggerAlways()) {
1609#ifdef CHECK_PATH
1610    if (numberColumns_Z==-1) {
1611      // If not -1 then in nested B&B
1612      OsiRowCutDebugger * debugger = 
1613        const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
1614      debuggerSolution_Z = debugger->optimalSolution();
1615      numberColumns_Z = getNumCols();
1616    }
1617  } else {
1618    debuggerSolution_Z = NULL;
1619    numberColumns_Z = -1;
1620#else
1621    specialOptions_ |= 1;
1622#endif
1623  }
1624
1625# ifdef CBC_DEBUG
1626  if ((specialOptions_&1)==0)
1627    solver_->activateRowCutDebugger(problemName.c_str()) ;
1628  if (solver_->getRowCutDebuggerAlways())
1629    specialOptions_ |= 1;
1630# endif
1631
1632/*
1633  Begin setup to process a feasible root node.
1634*/
1635  bestObjective_ = CoinMin(bestObjective_,1.0e50) ;
1636  if (!bestSolution_) {
1637    numberSolutions_ = 0 ;
1638    numberHeuristicSolutions_ = 0 ;
1639  } 
1640  stateOfSearch_ = 0; 
1641  // Everything is minimization
1642  { 
1643    // needed to sync cutoffs
1644    double value ;
1645    solver_->getDblParam(OsiDualObjectiveLimit,value) ;
1646    dblParam_[CbcCurrentCutoff]= value * solver_->getObjSense();
1647  }
1648  double cutoff=getCutoff() ;
1649  double direction = solver_->getObjSense() ;
1650  dblParam_[CbcOptimizationDirection]=direction;
1651  if (cutoff < 1.0e20&&direction<0.0)
1652    messageHandler()->message(CBC_CUTOFF_WARNING1,
1653                                    messages())
1654                                      << cutoff << -cutoff << CoinMessageEol ;
1655  if (cutoff > bestObjective_)
1656    cutoff = bestObjective_ ;
1657  setCutoff(cutoff) ;
1658/*
1659  We probably already have a current solution, but just in case ...
1660*/
1661  int numberColumns = getNumCols() ;
1662  if (!currentSolution_)
1663    currentSolution_ = new double[numberColumns] ;
1664  testSolution_ = currentSolution_;
1665/*
1666  Create a copy of the solver, thus capturing the original (root node)
1667  constraint system (aka the continuous system).
1668*/
1669  continuousSolver_ = solver_->clone() ;
1670
1671  numberRowsAtContinuous_ = getNumRows() ;
1672  solver_->saveBaseModel();
1673/*
1674  Check the objective to see if we can deduce a nontrivial increment. If
1675  it's better than the current value for CbcCutoffIncrement, it'll be
1676  installed.
1677*/
1678  if(solverCharacteristics_->reducedCostsAccurate())
1679    analyzeObjective() ;
1680#ifdef COIN_HAS_CLP
1681  // Possible save of pivot method
1682  ClpDualRowPivot * savePivotMethod=NULL;
1683  {
1684    // pass tolerance and increment to solver
1685    OsiClpSolverInterface * clpSolver
1686      = dynamic_cast<OsiClpSolverInterface *> (solver_);
1687    if (clpSolver) 
1688      clpSolver->setStuff(getIntegerTolerance(),getCutoffIncrement());
1689  }
1690#endif
1691/*
1692  Set up for cut generation. addedCuts_ holds the cuts which are relevant for
1693  the active subproblem. whichGenerator will be used to record the generator
1694  that produced a given cut.
1695*/
1696  maximumWhich_ = 1000 ;
1697  delete [] whichGenerator_;
1698  whichGenerator_ = new int[maximumWhich_] ;
1699  memset(whichGenerator_,0,maximumWhich_*sizeof(int));
1700  maximumNumberCuts_ = 0 ;
1701  currentNumberCuts_ = 0 ;
1702  delete [] addedCuts_ ;
1703  addedCuts_ = NULL ;
1704  OsiObject ** saveObjects=NULL;
1705  maximumRows_ = numberRowsAtContinuous_;
1706  currentDepth_=0;
1707  workingBasis_.resize(maximumRows_,numberColumns);
1708/*
1709  Set up an empty heap and associated data structures to hold the live set
1710  (problems which require further exploration).
1711*/
1712  tree_->setComparison(*nodeCompare_) ;
1713/*
1714  Used to record the path from a node to the root of the search tree, so that
1715  we can then traverse from the root to the node when restoring a subproblem.
1716*/
1717  maximumDepth_ = 10 ;
1718  delete [] walkback_ ;
1719  walkback_ = new CbcNodeInfo * [maximumDepth_] ;
1720#ifdef NODE_LAST
1721  lastDepth_=0;
1722  delete [] lastNodeInfo_ ;
1723  lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
1724  delete [] lastNumberCuts_ ;
1725  lastNumberCuts_ = new int [maximumDepth_] ;
1726  maximumCuts_ = 100;
1727  lastNumberCuts2_=0;
1728  delete [] lastCut_;
1729  lastCut_ = new const OsiRowCut * [maximumCuts_];
1730#endif
1731/*
1732  Used to generate bound edits for CbcPartialNodeInfo.
1733*/
1734  double * lowerBefore = new double [numberColumns] ;
1735  double * upperBefore = new double [numberColumns] ;
1736/*
1737 
1738  Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
1739  lifting. It will iterate a generate/reoptimise loop (including reduced cost
1740  fixing) until no cuts are generated, the change in objective falls off,  or
1741  the limit on the number of rounds of cut generation is exceeded.
1742
1743  At the end of all this, any cuts will be recorded in cuts and also
1744  installed in the solver's constraint system. We'll have reoptimised, and
1745  removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
1746  adjusted accordingly).
1747
1748  Tell cut generators they can be a bit more aggressive at root node
1749
1750  TODO: Why don't we make a copy of the solution after solveWithCuts?
1751  TODO: If numberUnsatisfied == 0, don't we have a solution?
1752*/
1753  phase_=1;
1754  int iCutGenerator;
1755  for (iCutGenerator = 0;iCutGenerator<numberCutGenerators_;iCutGenerator++) {
1756    CglCutGenerator * generator = generator_[iCutGenerator]->generator();
1757    generator->setAggressiveness(generator->getAggressiveness()+100);
1758  }
1759  OsiCuts cuts ;
1760  int anyAction = -1 ;
1761  numberOldActiveCuts_ = 0 ;
1762  numberNewCuts_ = 0 ;
1763  // Array to mark solution
1764  delete [] usedInSolution_;
1765  usedInSolution_ = new int[numberColumns];
1766  CoinZeroN(usedInSolution_,numberColumns);
1767/*
1768  For printing totals and for CbcNode (numberNodes_)
1769*/
1770  numberIterations_ = 0 ;
1771  numberNodes_ = 0 ;
1772  numberNodes2_ = 0 ;
1773  maximumStatistics_=0;
1774  maximumDepthActual_=0;
1775  numberDJFixed_=0.0;
1776  // Do heuristics
1777  doHeuristicsAtRoot();
1778  if ( intParam_[CbcMaxNumNode] < 0)
1779    eventHappened_=true; // stop as fast as possible
1780  stoppedOnGap_ = false ;
1781  // See if can stop on gap
1782  bestPossibleObjective_ = solver_->getObjValue()*solver_->getObjSense();
1783  double testGap = CoinMax(dblParam_[CbcAllowableGap],
1784                           CoinMax(fabs(bestObjective_),fabs(bestPossibleObjective_))
1785                           *dblParam_[CbcAllowableFractionGap]);
1786  if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
1787    if (bestPossibleObjective_<getCutoff())
1788      stoppedOnGap_ = true ;
1789    feasible = false;
1790    //eventHappened_=true; // stop as fast as possible
1791  }
1792  statistics_ = NULL;
1793  // Do on switch
1794  if (doStatistics>0&&doStatistics<=100) {
1795    maximumStatistics_=10000;
1796    statistics_ = new CbcStatistics * [maximumStatistics_];
1797    memset(statistics_,0,maximumStatistics_*sizeof(CbcStatistics *));
1798  }
1799
1800  { int iObject ;
1801    int preferredWay ;
1802    int numberUnsatisfied = 0 ;
1803    delete [] currentSolution_;
1804    currentSolution_ = new double [numberColumns];
1805    testSolution_ = currentSolution_;
1806    memcpy(currentSolution_,solver_->getColSolution(),
1807           numberColumns*sizeof(double)) ;
1808    // point to useful information
1809    OsiBranchingInformation usefulInfo=usefulInformation();
1810
1811    for (iObject = 0 ; iObject < numberObjects_ ; iObject++)
1812    { double infeasibility =
1813          object_[iObject]->infeasibility(&usefulInfo,preferredWay) ;
1814      if (infeasibility ) numberUnsatisfied++ ; }
1815    // replace solverType
1816    if(solverCharacteristics_->tryCuts())  {
1817
1818      if (numberUnsatisfied)   {
1819        // User event
1820        if (!eventHappened_)
1821          feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,
1822                                   NULL);
1823        else
1824          feasible=false;
1825      } else if (solverCharacteristics_->solutionAddsCuts()||
1826                 solverCharacteristics_->alwaysTryCutsAtRootNode()) {
1827        // may generate cuts and turn the solution
1828        //to an infeasible one
1829        feasible = solveWithCuts(cuts, 1,
1830                                 NULL);
1831      }
1832    }
1833    // check extra info on feasibility
1834    if (!solverCharacteristics_->mipFeasible())
1835      feasible = false;
1836  }
1837  // make cut generators less aggressive
1838  for (iCutGenerator = 0;iCutGenerator<numberCutGenerators_;iCutGenerator++) {
1839    CglCutGenerator * generator = generator_[iCutGenerator]->generator();
1840    generator->setAggressiveness(generator->getAggressiveness()-100);
1841  }
1842  currentNumberCuts_ = numberNewCuts_ ;
1843  // See if can stop on gap
1844  bestPossibleObjective_ = solver_->getObjValue()*solver_->getObjSense();
1845  testGap = CoinMax(dblParam_[CbcAllowableGap],
1846                           CoinMax(fabs(bestObjective_),fabs(bestPossibleObjective_))
1847                           *dblParam_[CbcAllowableFractionGap]);
1848  if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
1849    if (bestPossibleObjective_<getCutoff())
1850      stoppedOnGap_ = true ;
1851    feasible = false;
1852  }
1853  // User event
1854  if (eventHappened_)
1855    feasible=false;
1856  if(fastNodeDepth_>=0&&/*!parentModel_*/(specialOptions_&2048)==0) {
1857    // add in a general depth object doClp
1858    int type = (fastNodeDepth_ <=100) ? fastNodeDepth_ : -(fastNodeDepth_-100);
1859    CbcObject * obj = 
1860      new CbcGeneralDepth(this,type);
1861    addObjects(1,&obj);
1862    // mark as done
1863    fastNodeDepth_ += 1000000;
1864    delete obj;
1865    // fake number of objects
1866    numberObjects_--;
1867    if (parallelMode()<-1) {
1868      // But make sure position is correct
1869      OsiObject * obj2 = object_[numberObjects_];
1870      obj = dynamic_cast<CbcObject *> (obj2);
1871      assert (obj);
1872      obj->setPosition(numberObjects_);
1873    }
1874  }
1875#ifdef COIN_HAS_CLP
1876#ifdef NO_CRUNCH
1877  if (true) {
1878   OsiClpSolverInterface * clpSolver
1879     = dynamic_cast<OsiClpSolverInterface *> (solver_);
1880   if (clpSolver&&!parentModel_) {
1881     ClpSimplex * clpSimplex = clpSolver->getModelPtr();
1882     clpSimplex->setSpecialOptions(clpSimplex->specialOptions()|131072);
1883     //clpSimplex->startPermanentArrays();
1884     clpSimplex->setPersistenceFlag(2);
1885   }
1886 }
1887#endif
1888#endif
1889 // Save copy of solver
1890 OsiSolverInterface * saveSolver = NULL;
1891 if (!parentModel_&&(specialOptions_&(512+2048))!=0)
1892   saveSolver = solver_->clone();
1893 if (saveSolver&&(specialOptions_&2048)!=0) {
1894   // See if worth trying reduction
1895   bool tryNewSearch=solverCharacteristics_->reducedCostsAccurate();
1896   int numberColumns = getNumCols();
1897   if (tryNewSearch) {
1898     double cutoff = getCutoff() ;
1899     saveSolver->resolve();
1900     double direction = saveSolver->getObjSense() ;
1901     double gap = cutoff - saveSolver->getObjValue()*direction ;
1902     double tolerance;
1903     saveSolver->getDblParam(OsiDualTolerance,tolerance) ;
1904     if (gap<=0.0)
1905       gap = tolerance; 
1906     gap += 100.0*tolerance;
1907     double integerTolerance = getDblParam(CbcIntegerTolerance) ;
1908     
1909     const double *lower = saveSolver->getColLower() ;
1910     const double *upper = saveSolver->getColUpper() ;
1911     const double *solution = saveSolver->getColSolution() ;
1912     const double *reducedCost = saveSolver->getReducedCost() ;
1913     
1914     int numberFixed = 0 ;
1915     int numberFixed2=0;
1916     for (int i = 0 ; i < numberIntegers_ ; i++) {
1917       int iColumn = integerVariable_[i] ;
1918       double djValue = direction*reducedCost[iColumn] ;
1919       if (upper[iColumn]-lower[iColumn] > integerTolerance) {
1920         if (solution[iColumn] < lower[iColumn]+integerTolerance && djValue > gap) {
1921           saveSolver->setColUpper(iColumn,lower[iColumn]) ;
1922           numberFixed++ ;
1923         } else if (solution[iColumn] > upper[iColumn]-integerTolerance && -djValue > gap) {
1924           saveSolver->setColLower(iColumn,upper[iColumn]) ;
1925           numberFixed++ ;
1926         }
1927       } else {
1928         numberFixed2++;
1929       }
1930     }
1931#ifdef COIN_DEVELOP
1932     if ((specialOptions_&1)!=0) {
1933       const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ;
1934       if (debugger) { 
1935         printf("Contains optimal\n") ;
1936         saveSolver->writeMps("reduced");
1937       } else {
1938         abort();
1939       }
1940     }
1941     printf("Restart could fix %d integers (%d already fixed)\n",
1942            numberFixed+numberFixed2,numberFixed2);
1943#endif
1944     numberFixed += numberFixed2;
1945     if (numberFixed*20<numberColumns)
1946       tryNewSearch=false;
1947   }
1948   if (tryNewSearch) {
1949     // back to solver without cuts?
1950#if 0
1951     OsiSolverInterface * solver2 = continuousSolver_->clone();
1952#else
1953     OsiSolverInterface * solver2 = saveSolver->clone();
1954#endif
1955     const double *lower = saveSolver->getColLower() ;
1956     const double *upper = saveSolver->getColUpper() ;
1957     for (int i = 0 ; i < numberIntegers_ ; i++) {
1958       int iColumn = integerVariable_[i] ;
1959       solver2->setColLower(iColumn,lower[iColumn]);
1960       solver2->setColUpper(iColumn,upper[iColumn]);
1961     }
1962     // swap
1963     delete saveSolver;
1964     saveSolver=solver2;
1965     double * newSolution = new double[numberColumns];
1966     double objectiveValue=cutoff;
1967     CbcSerendipity heuristic(*this);
1968     if (bestSolution_)
1969       heuristic.setInputSolution(bestSolution_,bestObjective_);
1970     heuristic.setFractionSmall(0.9);
1971     heuristic.setFeasibilityPumpOptions(1008013);
1972     // Use numberNodes to say how many are original rows
1973     heuristic.setNumberNodes(continuousSolver_->getNumRows());
1974#ifdef COIN_DEVELOP
1975     if (continuousSolver_->getNumRows()<
1976         solver_->getNumRows())
1977       printf("%d rows added ZZZZZ\n",
1978              solver_->getNumRows()-continuousSolver_->getNumRows());
1979#endif
1980     int returnCode= heuristic.smallBranchAndBound(saveSolver,
1981                                                   -1,newSolution,
1982                                                   objectiveValue,
1983                                                   cutoff,"Reduce");
1984     if (returnCode<0) {
1985#ifdef COIN_DEVELOP
1986       printf("Restart - not small enough to do search after fixing\n");
1987#endif
1988       delete [] newSolution;
1989     } else {
1990       if ((returnCode&1)!=0) {
1991         // increment number of solutions so other heuristics can test
1992         numberSolutions_++;
1993         numberHeuristicSolutions_++;
1994         lastHeuristic_ = NULL;
1995         setBestSolution(CBC_ROUNDING,objectiveValue,newSolution) ;
1996       }
1997       delete [] newSolution;
1998       feasible=false; // stop search
1999     }
2000   } 
2001 }
2002/*
2003  We've taken the continuous relaxation as far as we can. Time to branch.
2004  The first order of business is to actually create a node. chooseBranch
2005  currently uses strong branching to evaluate branch object candidates,
2006  unless forced back to simple branching. If chooseBranch concludes that a
2007  branching candidate is monotone (anyAction == -1) or infeasible (anyAction
2008  == -2) when forced to integer values, it returns here immediately.
2009
2010  Monotone variables trigger a call to resolve(). If the problem remains
2011  feasible, try again to choose a branching variable. At the end of the loop,
2012  resolved == true indicates that some variables were fixed.
2013
2014  Loss of feasibility will result in the deletion of newNode.
2015*/
2016
2017  bool resolved = false ;
2018  CbcNode *newNode = NULL ;
2019  numberFixedAtRoot_=0;
2020  numberFixedNow_=0;
2021  int numberIterationsAtContinuous = numberIterations_;
2022  //solverCharacteristics_->setSolver(solver_);
2023  if (feasible) {
2024    //#define HOTSTART 1
2025#if HOTSTART
2026    if (hotstartSolution_&&!hotstartPriorities_) {
2027      // Set up hot start
2028      OsiSolverInterface * solver = solver_->clone();
2029      double direction = solver_->getObjSense() ;
2030      int numberColumns = solver->getNumCols();
2031      double * saveLower = CoinCopyOfArray(solver->getColLower(),numberColumns);
2032      double * saveUpper = CoinCopyOfArray(solver->getColUpper(),numberColumns);
2033      // move solution
2034      solver->setColSolution(hotstartSolution_);
2035      // point to useful information
2036      const double * saveSolution = testSolution_;
2037      testSolution_ = solver->getColSolution();
2038      OsiBranchingInformation usefulInfo=usefulInformation();
2039      testSolution_ = saveSolution;
2040      /*
2041        Run through the objects and use feasibleRegion() to set variable bounds
2042        so as to fix the variables specified in the objects at their value in this
2043        solution. Since the object list contains (at least) one object for every
2044        integer variable, this has the effect of fixing all integer variables.
2045      */
2046      for (int i=0;i<numberObjects_;i++) 
2047        object_[i]->feasibleRegion(solver,&usefulInfo);
2048      solver->resolve();
2049      assert (solver->isProvenOptimal());
2050      double gap = CoinMax((solver->getObjValue()-solver_->getObjValue())*direction,0.0) ;
2051      const double * dj = solver->getReducedCost();
2052      const double * colLower = solver->getColLower();
2053      const double * colUpper = solver->getColUpper();
2054      const double * solution = solver->getColSolution();
2055      int nAtLbNatural=0;
2056      int nAtUbNatural=0;
2057      int nAtLbNaturalZero=0;
2058      int nAtUbNaturalZero=0;
2059      int nAtLbFixed=0;
2060      int nAtUbFixed=0;
2061      int nAtOther=0;
2062      int nAtOtherNatural=0;
2063      int nNotNeeded=0;
2064      delete [] hotstartSolution_;
2065      hotstartSolution_ = new double [numberColumns];
2066      delete [] hotstartPriorities_;
2067      hotstartPriorities_ = new int [numberColumns];
2068      int * order = (int *) saveUpper;
2069      int nFix=0;
2070      double bestRatio=COIN_DBL_MAX;
2071      for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2072        double value = solution[iColumn] ;
2073        value = CoinMax(value, saveLower[iColumn]) ;
2074        value = CoinMin(value, saveUpper[iColumn]) ;
2075        double sortValue=COIN_DBL_MAX;
2076        if (solver->isInteger(iColumn)) {
2077          assert(fabs(value-solution[iColumn]) <= 1.0e-5) ;
2078          double value2 = floor(value+0.5);
2079          if (dj[iColumn]<-1.0e-6) {
2080            // negative dj
2081            //assert (value2==colUpper[iColumn]);
2082            if (saveUpper[iColumn]==colUpper[iColumn]) {
2083              nAtUbNatural++;
2084              sortValue = 0.0;
2085              double value=-dj[iColumn];
2086              if (value>gap)
2087                nFix++;
2088              else if (gap<value*bestRatio)
2089                bestRatio=gap/value;
2090              if (saveLower[iColumn]!=colLower[iColumn]) {
2091                nNotNeeded++;
2092                sortValue = 1.0e20;
2093              }
2094            } else if (saveLower[iColumn]==colUpper[iColumn]) {
2095              nAtLbFixed++;
2096              sortValue = dj[iColumn];
2097            } else {
2098              nAtOther++;
2099              sortValue = 0.0;
2100              if (saveLower[iColumn]!=colLower[iColumn]&&
2101                  saveUpper[iColumn]!=colUpper[iColumn]) {
2102                nNotNeeded++;
2103                sortValue = 1.0e20;
2104              }
2105            }
2106          } else if (dj[iColumn]>1.0e-6) {
2107            // positive dj
2108            //assert (value2==colLower[iColumn]);
2109            if (saveLower[iColumn]==colLower[iColumn]) {
2110              nAtLbNatural++;
2111              sortValue = 0.0;
2112              double value=dj[iColumn];
2113              if (value>gap)
2114                nFix++;
2115              else if (gap<value*bestRatio)
2116                bestRatio=gap/value;
2117              if (saveUpper[iColumn]!=colUpper[iColumn]) {
2118                nNotNeeded++;
2119                sortValue = 1.0e20;
2120              }
2121            } else if (saveUpper[iColumn]==colLower[iColumn]) {
2122              nAtUbFixed++;
2123              sortValue = -dj[iColumn];
2124            } else {
2125              nAtOther++;
2126              sortValue = 0.0;
2127              if (saveLower[iColumn]!=colLower[iColumn]&&
2128                  saveUpper[iColumn]!=colUpper[iColumn]) {
2129                nNotNeeded++;
2130                sortValue = 1.0e20;
2131              }
2132            }
2133          } else {
2134            // zero dj
2135            if (value2==saveUpper[iColumn]) {
2136              nAtUbNaturalZero++;
2137              sortValue = 0.0;
2138              if (saveLower[iColumn]!=colLower[iColumn]) {
2139                nNotNeeded++;
2140                sortValue = 1.0e20;
2141              }
2142            } else if (value2==saveLower[iColumn]) {
2143              nAtLbNaturalZero++;
2144              sortValue = 0.0;
2145            } else {
2146              nAtOtherNatural++;
2147              sortValue = 0.0;
2148              if (saveLower[iColumn]!=colLower[iColumn]&& 
2149                  saveUpper[iColumn]!=colUpper[iColumn]) {
2150                nNotNeeded++;
2151                sortValue = 1.0e20;
2152              }
2153            }
2154          }
2155#if HOTSTART==3
2156          sortValue=-fabs(dj[iColumn]);
2157#endif
2158        }
2159        hotstartSolution_[iColumn] = value ; 
2160        saveLower[iColumn]=sortValue;
2161        order[iColumn]=iColumn;
2162      }
2163      printf("** can fix %d columns - best ratio for others is %g on gap of %g\n",
2164             nFix,bestRatio,gap);
2165      int nNeg=0;
2166      CoinSort_2(saveLower,saveLower+numberColumns,order);
2167      for (int i=0;i<numberColumns;i++) {
2168        if (saveLower[i]<0.0) {
2169          nNeg++;
2170#if HOTSTART==2||HOTSTART==3
2171          // swap sign ?
2172          saveLower[i]=-saveLower[i];
2173#endif
2174        }
2175      }
2176      CoinSort_2(saveLower,saveLower+nNeg,order);
2177      for (int i=0;i<numberColumns;i++) {
2178#if HOTSTART==1
2179        hotstartPriorities_[order[i]]=100;
2180#else
2181        hotstartPriorities_[order[i]]=-(i+1);
2182#endif
2183      }
2184      printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n",
2185             nAtLbNatural,
2186             nAtUbNatural,
2187             nAtLbNaturalZero,
2188             nAtUbNaturalZero,
2189             nAtLbFixed,
2190             nAtUbFixed,
2191             nAtOther,
2192             nAtOtherNatural,nNotNeeded,nNeg);
2193      delete [] saveLower;
2194      delete [] saveUpper;
2195      if (!saveCompare) {
2196        // create depth first comparison
2197        saveCompare = nodeCompare_;
2198        // depth first
2199        nodeCompare_ = new CbcCompareDepth();
2200        tree_->setComparison(*nodeCompare_) ;
2201      }
2202    }
2203#endif
2204    if (probingInfo_) {
2205      int number01 = probingInfo_->numberIntegers();
2206      //const fixEntry * entry = probingInfo_->fixEntries();
2207      const int * toZero = probingInfo_->toZero();
2208      //const int * toOne = probingInfo_->toOne();
2209      //const int * integerVariable = probingInfo_->integerVariable();
2210      if (toZero[number01]) {
2211        if (probingInfo_->packDown()) {
2212#ifdef CLP_INVESTIGATE
2213          printf("%d implications on %d 0-1\n",toZero[number01],number01);
2214#endif
2215          CglImplication implication(probingInfo_);
2216          addCutGenerator(&implication,1,"ImplicationCuts",true,false,false,-200);
2217        } else {
2218          delete probingInfo_;
2219          probingInfo_=NULL;
2220        }
2221      } else {
2222        delete probingInfo_;
2223
2224        probingInfo_=NULL;
2225      }
2226    }
2227    newNode = new CbcNode ;
2228    // Set objective value (not so obvious if NLP etc)
2229    setObjectiveValue(newNode,NULL);
2230    anyAction = -1 ;
2231    // To make depth available we may need a fake node
2232    CbcNode fakeNode;
2233    if (!currentNode_) {
2234      // Not true if sub trees assert (!numberNodes_);
2235      currentNode_=&fakeNode;
2236    }
2237    phase_=3;
2238    // only allow 1000 passes
2239    int numberPassesLeft=1000;
2240    // This is first crude step
2241    if (numberAnalyzeIterations_) {
2242      delete [] analyzeResults_;
2243      analyzeResults_ = new double [4*numberIntegers_];
2244      numberFixedAtRoot_=newNode->analyze(this,analyzeResults_);
2245      if (numberFixedAtRoot_>0) {
2246        printf("%d fixed by analysis\n",numberFixedAtRoot_);
2247        setPointers(solver_);
2248        numberFixedNow_ = numberFixedAtRoot_;
2249      } else if (numberFixedAtRoot_<0) {
2250        printf("analysis found to be infeasible\n");
2251        anyAction=-2;
2252        delete newNode ;
2253        newNode = NULL ;
2254        feasible = false ;
2255      }
2256    }
2257    OsiSolverBranch * branches = NULL;
2258    anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts,resolved,
2259                             NULL,NULL,NULL,branches);
2260    if (anyAction == -2||newNode->objectiveValue() >= cutoff) {
2261      if (anyAction != -2) {
2262        // zap parent nodeInfo
2263#ifdef COIN_DEVELOP
2264        printf("zapping CbcNodeInfo %x\n",reinterpret_cast<int>(newNode->nodeInfo()->parent()));
2265#endif
2266        if (newNode->nodeInfo())
2267          newNode->nodeInfo()->nullParent();
2268      }
2269      delete newNode ;
2270      newNode = NULL ;
2271      feasible = false ;
2272    }
2273  }
2274/*
2275  At this point, the root subproblem is infeasible or fathomed by bound
2276  (newNode == NULL), or we're live with an objective value that satisfies the
2277  current objective cutoff.
2278*/
2279  assert (!newNode || newNode->objectiveValue() <= cutoff) ;
2280  // Save address of root node as we don't want to delete it
2281  // initialize for print out
2282  int lastDepth=0;
2283  int lastUnsatisfied=0;
2284  if (newNode)
2285    lastUnsatisfied=newNode->numberUnsatisfied();
2286/*
2287  The common case is that the lp relaxation is feasible but doesn't satisfy
2288  integrality (i.e., newNode->branchingObject(), indicating we've been able to
2289  select a branching variable). Remove any cuts that have gone slack due to
2290  forcing monotone variables. Then tack on an CbcFullNodeInfo object and full
2291  basis (via createInfo()) and stash the new cuts in the nodeInfo (via
2292  addCuts()). If, by some miracle, we have an integral solution at the root
2293  (newNode->branchingObject() is NULL), takeOffCuts() will ensure that the solver holds
2294  a valid solution for use by setBestSolution().
2295*/
2296  CoinWarmStartBasis *lastws = NULL ;
2297  if (feasible && newNode->branchingObject())
2298  { if (resolved)
2299    { takeOffCuts(cuts,false,NULL) ;
2300#     ifdef CHECK_CUT_COUNTS
2301      { printf("Number of rows after chooseBranch fix (root)"
2302               "(active only) %d\n",
2303                numberRowsAtContinuous_+numberNewCuts_+numberOldActiveCuts_) ;
2304        const CoinWarmStartBasis* debugws =
2305          dynamic_cast <const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
2306        debugws->print() ;
2307        delete debugws ; }
2308#     endif
2309    }
2310  //newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
2311    //newNode->nodeInfo()->addCuts(cuts,
2312    //                   newNode->numberBranches(),whichGenerator_) ;
2313    if (lastws) delete lastws ;
2314    lastws = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
2315  }
2316/*
2317  Continuous data to be used later
2318*/
2319  continuousObjective_ = solver_->getObjValue()*solver_->getObjSense();
2320  continuousInfeasibilities_ = 0 ;
2321  if (newNode)
2322  { continuousObjective_ = newNode->objectiveValue() ;
2323    delete [] continuousSolution_;
2324    continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
2325                                             numberColumns);
2326    continuousInfeasibilities_ = newNode->numberUnsatisfied() ; }
2327/*
2328  Bound may have changed so reset in objects
2329*/
2330  { int i ;
2331    for (i = 0;i < numberObjects_;i++)
2332      object_[i]->resetBounds(solver_) ; }
2333/*
2334  Feasible? Then we should have either a live node prepped for future
2335  expansion (indicated by variable() >= 0), or (miracle of miracles) an
2336  integral solution at the root node.
2337
2338  initializeInfo sets the reference counts in the nodeInfo object.  Since
2339  this node is still live, push it onto the heap that holds the live set.
2340*/
2341  double bestValue = 0.0 ;
2342  if (newNode) {
2343    bestValue = newNode->objectiveValue();
2344    if (newNode->branchingObject()) {
2345      newNode->initializeInfo() ;
2346      tree_->push(newNode) ;
2347      if (statistics_) {
2348        if (numberNodes2_==maximumStatistics_) {
2349          maximumStatistics_ = 2*maximumStatistics_;
2350          CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
2351          memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
2352          memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
2353          delete [] statistics_;
2354          statistics_=temp;
2355        }
2356        assert (!statistics_[numberNodes2_]);
2357        statistics_[numberNodes2_]=new CbcStatistics(newNode,this);
2358      }
2359      numberNodes2_++;
2360#     ifdef CHECK_NODE
2361      printf("Node %x on tree\n",newNode) ;
2362#     endif
2363    } else {
2364      // continuous is integer
2365      double objectiveValue = newNode->objectiveValue();
2366      setBestSolution(CBC_SOLUTION,objectiveValue,
2367                      solver_->getColSolution()) ;
2368      delete newNode ;
2369      newNode = NULL ;
2370    }
2371  }
2372
2373  if (printFrequency_ <= 0) {
2374    printFrequency_ = 1000 ;
2375    if (getNumCols() > 2000)
2376      printFrequency_ = 100 ;
2377  }
2378  /*
2379    It is possible that strong branching fixes one variable and then the code goes round
2380    again and again.  This can take too long.  So we need to warn user - just once.
2381  */
2382  numberLongStrong_=0;
2383  double totalTime = 0.0;
2384  CbcNode * createdNode=NULL;
2385#ifdef CBC_THREAD
2386  CbcModel ** threadModel = NULL;
2387  Coin_pthread_t * threadId = NULL;
2388  int * threadCount = NULL;
2389  pthread_mutex_t mutex;
2390  pthread_cond_t condition_main;
2391  pthread_mutex_t condition_mutex;
2392  pthread_mutex_t * mutex2 = NULL;
2393  pthread_cond_t * condition2 = NULL;
2394  threadStruct * threadInfo = NULL;
2395  bool locked=false;
2396  int threadStats[6];
2397  int defaultParallelIterations=500;
2398  int defaultParallelNodes=10;
2399  memset(threadStats,0,sizeof(threadStats));
2400  double timeWaiting=0.0;
2401  // For now just one model
2402  if (numberThreads_) {
2403    nodeCompare_->sayThreaded(); // need to use addresses
2404    threadId = new Coin_pthread_t [numberThreads_];
2405    threadCount = new int [numberThreads_];
2406    CoinZeroN(threadCount,numberThreads_);
2407    pthread_mutex_init(&mutex,NULL);
2408    pthread_cond_init(&condition_main,NULL);
2409    pthread_mutex_init(&condition_mutex,NULL);
2410    threadModel = new CbcModel * [numberThreads_+1];
2411    threadInfo = new threadStruct [numberThreads_+1];
2412    mutex2 = new pthread_mutex_t [numberThreads_];
2413    condition2 = new pthread_cond_t [numberThreads_];
2414    if (parallelMode()<-1) {
2415      // May need for deterministic
2416      saveObjects=new OsiObject * [numberObjects_];
2417      for (int i=0;i<numberObjects_;i++) {
2418        saveObjects[i] = object_[i]->clone();
2419      }
2420    }
2421    // we don't want a strategy object
2422    CbcStrategy * saveStrategy = strategy_;
2423    strategy_ = NULL;
2424    for (int i=0;i<numberThreads_;i++) {
2425      pthread_mutex_init(mutex2+i,NULL);
2426      pthread_cond_init(condition2+i,NULL);
2427      threadId[i].status=0;
2428      threadInfo[i].baseModel=this;
2429      threadModel[i]=new CbcModel(*this,true);
2430      threadModel[i]->synchronizeHandlers(1);
2431#ifdef COIN_HAS_CLP
2432      // Solver may need to know about model
2433      CbcModel * thisModel = threadModel[i];
2434      CbcOsiSolver * solver =
2435              dynamic_cast<CbcOsiSolver *>(thisModel->solver()) ;
2436      if (solver)
2437        solver->setCbcModel(thisModel);
2438#endif
2439      mutex_ = reinterpret_cast<void *> (threadInfo+i);
2440      threadModel[i]->moveToModel(this,-1);
2441      threadInfo[i].thisModel=threadModel[i];
2442      threadInfo[i].node=NULL;
2443      threadInfo[i].createdNode=NULL;
2444      threadInfo[i].threadIdOfBase.thr=pthread_self();
2445      threadInfo[i].mutex=&mutex;
2446      threadInfo[i].mutex2=mutex2+i;
2447      threadInfo[i].condition2=condition2+i;
2448      threadInfo[i].returnCode=-1;
2449      threadInfo[i].timeLocked=0.0;
2450      threadInfo[i].timeWaitingToLock=0.0;
2451      threadInfo[i].timeWaitingToStart=0.0;
2452      threadInfo[i].timeInThread=0.0;
2453      threadInfo[i].numberTimesLocked=0;
2454      threadInfo[i].numberTimesUnlocked=0;
2455      threadInfo[i].numberTimesWaitingToStart=0;
2456      threadInfo[i].dantzigState=0; // 0 unset, -1 waiting to be set, 1 set
2457      threadInfo[i].locked=false;
2458#if CBC_THREAD_DEBUG
2459      threadInfo[i].threadNumber=i+2;
2460#endif
2461      threadInfo[i].delNode = NULL;
2462      threadInfo[i].maxDeleteNode=0;
2463      threadInfo[i].nDeleteNode=0;
2464      threadInfo[i].nodesThisTime=0;
2465      threadInfo[i].iterationsThisTime=0;
2466      pthread_create(&(threadId[i].thr),NULL,doNodesThread,threadInfo+i);
2467      threadId[i].status = 1;
2468    }
2469    strategy_ = saveStrategy;
2470    // Do a partial one for base model
2471    threadInfo[numberThreads_].baseModel=this;
2472    threadModel[numberThreads_]=this;
2473    mutex_ = reinterpret_cast<void *> (threadInfo+numberThreads_);
2474    threadInfo[numberThreads_].node=NULL;
2475    threadInfo[numberThreads_].mutex=&mutex;
2476    threadInfo[numberThreads_].condition2=&condition_main;
2477    threadInfo[numberThreads_].mutex2=&condition_mutex;
2478    threadInfo[numberThreads_].timeLocked=0.0;
2479    threadInfo[numberThreads_].timeWaitingToLock=0.0;
2480    threadInfo[numberThreads_].numberTimesLocked=0;
2481    threadInfo[numberThreads_].numberTimesUnlocked=0;
2482    threadInfo[numberThreads_].locked=false;
2483#if CBC_THREAD_DEBUG
2484    threadInfo[numberThreads_].threadNumber=1;
2485#endif
2486  }
2487#endif
2488#ifdef COIN_HAS_CLP
2489  {
2490    OsiClpSolverInterface * clpSolver
2491      = dynamic_cast<OsiClpSolverInterface *> (solver_);
2492    if (clpSolver&&!parentModel_) {
2493      clpSolver->computeLargestAway();
2494    }
2495  }
2496#endif
2497/*
2498  At last, the actual branch-and-cut search loop, which will iterate until
2499  the live set is empty or we hit some limit (integrality gap, time, node
2500  count, etc.). The overall flow is to rebuild a subproblem, reoptimise using
2501  solveWithCuts(), choose a branching pattern with chooseBranch(), and finally
2502  add the node to the live set.
2503
2504  The first action is to winnow the live set to remove nodes which are worse
2505  than the current objective cutoff.
2506*/
2507  if (solver_->getRowCutDebuggerAlways()) {
2508    OsiRowCutDebugger * debuggerX = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
2509    const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
2510    if (!debugger) {
2511      // infeasible!!
2512      printf("before search\n");
2513      const double * lower = solver_->getColLower();
2514      const double * upper = solver_->getColUpper();
2515      const double * solution = debuggerX->optimalSolution();
2516      int numberColumns = solver_->getNumCols();
2517      for (int i=0;i<numberColumns;i++) {
2518        if (solver_->isInteger(i)) {
2519          if (solution[i]<lower[i]-1.0e-6||solution[i]>upper[i]+1.0e-6)
2520            printf("**** ");
2521          printf("%d %g <= %g <= %g\n",
2522                 i,lower[i],solution[i],upper[i]);
2523        }
2524      }
2525      //abort();
2526    }
2527  }
2528#ifdef CBC_THREAD
2529  bool goneParallel=false;
2530#endif
2531#define MAX_DEL_NODE 1
2532  CbcNode * delNode[MAX_DEL_NODE+1];
2533  int nDeleteNode=0;
2534  // For Printing etc when parallel
2535  int lastEvery1000=0;
2536  int lastPrintEvery=0;
2537  while (true) {
2538#ifdef CBC_THREAD
2539    if (parallelMode()>0&&!locked) {
2540      lockThread();
2541      locked=true;
2542    }
2543#endif
2544#ifdef COIN_HAS_CLP
2545    // Possible change of pivot method
2546    if(!savePivotMethod&&!parentModel_) {
2547      OsiClpSolverInterface * clpSolver
2548        = dynamic_cast<OsiClpSolverInterface *> (solver_);
2549      if (clpSolver&&numberNodes_>=100&&numberNodes_<200) {
2550        if (numberIterations_<numberNodes_*20) {
2551          ClpSimplex * simplex = clpSolver->getModelPtr();
2552          ClpDualRowPivot * pivotMethod=simplex->dualRowPivot();
2553          ClpDualRowDantzig * pivot =
2554            dynamic_cast< ClpDualRowDantzig*>(pivotMethod);
2555          if (!pivot) {
2556            savePivotMethod = pivotMethod->clone(true);
2557            ClpDualRowDantzig dantzig;
2558            simplex->setDualRowPivotAlgorithm(dantzig);
2559#ifdef COIN_DEVELOP
2560            printf("%d node, %d iterations ->Dantzig\n",numberNodes_,
2561                   numberIterations_);
2562#endif
2563#ifdef CBC_THREAD
2564            for (int i=0;i<numberThreads_;i++) {
2565              threadInfo[i].dantzigState=-1;
2566            }
2567#endif
2568          }
2569        }
2570      }
2571    }
2572#endif
2573    if (tree_->empty()) {
2574#ifdef CBC_THREAD
2575      if (parallelMode()>0) {
2576#ifdef COIN_DEVELOP
2577        printf("empty\n");
2578#endif
2579        // may still be outstanding nodes
2580        int iThread;
2581        for (iThread=0;iThread<numberThreads_;iThread++) {
2582          if (threadId[iThread].status) {
2583            if (threadInfo[iThread].returnCode==0) 
2584              break;
2585          }
2586        }
2587        if (iThread<numberThreads_) {
2588#ifdef COIN_DEVELOP
2589          printf("waiting for thread %d code 0\n",iThread);
2590#endif
2591          if (parallelMode()>0) {
2592            unlockThread();
2593            locked = false;
2594          }
2595          pthread_cond_signal(threadInfo[iThread].condition2); // unlock in case
2596          while (true) {
2597            pthread_mutex_lock(&condition_mutex);
2598            struct timespec absTime;
2599            my_gettime(&absTime);
2600            double time = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
2601            absTime.tv_nsec += 1000000; // millisecond
2602            if (absTime.tv_nsec>=1000000000) {
2603              absTime.tv_nsec -= 1000000000;
2604              absTime.tv_sec++;
2605            }
2606            pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
2607            my_gettime(&absTime);
2608            double time2 = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
2609            timeWaiting += time2-time;
2610            pthread_mutex_unlock(&condition_mutex);
2611            if (threadInfo[iThread].returnCode!=0) 
2612              break;
2613            pthread_cond_signal(threadInfo[iThread].condition2); // unlock
2614          }
2615          threadModel[iThread]->moveToModel(this,1);
2616          assert (threadInfo[iThread].returnCode==1);
2617          if (threadInfo[iThread].dantzigState==-1) {
2618            // 0 unset, -1 waiting to be set, 1 set
2619            threadInfo[iThread].dantzigState=1;
2620            CbcModel * model = threadInfo[iThread].thisModel;
2621            OsiClpSolverInterface * clpSolver2
2622              = dynamic_cast<OsiClpSolverInterface *> (model->solver());
2623            assert (clpSolver2);
2624            ClpSimplex * simplex2 = clpSolver2->getModelPtr();
2625            ClpDualRowDantzig dantzig;
2626            simplex2->setDualRowPivotAlgorithm(dantzig);
2627          }
2628          // say available
2629          threadInfo[iThread].returnCode=-1;
2630          threadStats[4]++;
2631#ifdef COIN_DEVELOP
2632          printf("thread %d code now -1\n",iThread);
2633#endif
2634          continue;
2635        } else {
2636#ifdef COIN_DEVELOP
2637          printf("no threads at code 0 \n");
2638#endif
2639          // now check if any have just finished
2640          for (iThread=0;iThread<numberThreads_;iThread++) {
2641            if (threadId[iThread].status) {
2642              if (threadInfo[iThread].returnCode==1) 
2643                break;
2644            }
2645          }
2646          if (iThread<numberThreads_) {
2647            if (parallelMode()>0) {
2648              unlockThread();
2649              locked = false;
2650            }
2651            threadModel[iThread]->moveToModel(this,1);
2652            assert (threadInfo[iThread].returnCode==1);
2653            // say available
2654            threadInfo[iThread].returnCode=-1;
2655            threadStats[4]++;
2656#ifdef COIN_DEVELOP
2657            printf("thread %d code now -1\n",iThread);
2658#endif
2659            continue;
2660          }
2661        }
2662        if (!tree_->empty()) {
2663#ifdef COIN_DEVELOP
2664          printf("tree not empty!!!!!!\n");
2665#endif
2666          continue;
2667        }
2668        for (iThread=0;iThread<numberThreads_;iThread++) {
2669          if (threadId[iThread].status) {
2670            if (threadInfo[iThread].returnCode!=-1) { 
2671              printf("bad end of tree\n");
2672              abort();
2673            }
2674          }
2675        }
2676#ifdef COIN_DEVELOP
2677        printf("finished ************\n");
2678#endif
2679        unlockThread();
2680        locked=false; // not needed as break
2681      }
2682#endif
2683      break;
2684    }
2685#ifdef CBC_THREAD
2686    if (parallelMode()>0) {
2687      unlockThread();
2688      locked = false;
2689    }
2690#endif
2691    // If done 100 nodes see if worth trying reduction
2692    if (numberNodes_==100&&saveSolver) {
2693      bool tryNewSearch=solverCharacteristics_->reducedCostsAccurate();
2694      int numberColumns = getNumCols();
2695      if (tryNewSearch) {
2696        double cutoff = getCutoff() ;
2697        saveSolver->resolve();
2698        double direction = saveSolver->getObjSense() ;
2699        double gap = cutoff - saveSolver->getObjValue()*direction ;
2700        double tolerance;
2701        saveSolver->getDblParam(OsiDualTolerance,tolerance) ;
2702        if (gap<=0.0)
2703          gap = tolerance; 
2704        gap += 100.0*tolerance;
2705        double integerTolerance = getDblParam(CbcIntegerTolerance) ;
2706       
2707        const double *lower = saveSolver->getColLower() ;
2708        const double *upper = saveSolver->getColUpper() ;
2709        const double *solution = saveSolver->getColSolution() ;
2710        const double *reducedCost = saveSolver->getReducedCost() ;
2711       
2712        int numberFixed = 0 ;
2713        int numberFixed2=0;
2714#ifdef COIN_DEVELOP
2715        printf("gap %g\n",gap);
2716#endif
2717        for (int i = 0 ; i < numberIntegers_ ; i++) {
2718          int iColumn = integerVariable_[i] ;
2719          double djValue = direction*reducedCost[iColumn] ;
2720          if (upper[iColumn]-lower[iColumn] > integerTolerance) {
2721            if (solution[iColumn] < lower[iColumn]+integerTolerance && djValue > gap) {
2722              //printf("%d to lb on dj of %g - bounds %g %g\n",
2723              //     iColumn,djValue,lower[iColumn],upper[iColumn]);
2724              saveSolver->setColUpper(iColumn,lower[iColumn]) ;
2725              numberFixed++ ;
2726            } else if (solution[iColumn] > upper[iColumn]-integerTolerance && -djValue > gap) {
2727              //printf("%d to ub on dj of %g - bounds %g %g\n",
2728              //     iColumn,djValue,lower[iColumn],upper[iColumn]);
2729              saveSolver->setColLower(iColumn,upper[iColumn]) ;
2730              numberFixed++ ;
2731            }
2732          } else {
2733            //printf("%d has dj of %g - already fixed to %g\n",
2734            //     iColumn,djValue,lower[iColumn]);
2735            numberFixed2++;
2736          }
2737        }
2738#ifdef COIN_DEVELOP
2739        if ((specialOptions_&1)!=0) {
2740          const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ;
2741          if (debugger) { 
2742            printf("Contains optimal\n") ;
2743            saveSolver->writeMps("reduced");
2744          } else {
2745            abort();
2746          }
2747        }
2748        printf("Restart could fix %d integers (%d already fixed)\n",
2749               numberFixed+numberFixed2,numberFixed2);
2750#endif
2751        numberFixed += numberFixed2;
2752        if (numberFixed*10<numberColumns)
2753          tryNewSearch=false;
2754      }
2755      if (tryNewSearch) {
2756        // back to solver without cuts?
2757#if 0
2758        int numberCuts = solver_->getNumRows()-continuousSolver_->getNumRows();
2759        OsiSolverInterface * solver2;
2760        if (numberCuts>50&&numberCuts*10>solver_->getNumRows())
2761          solver2 = continuousSolver_->clone();
2762        else
2763          solver2 = saveSolver->clone();
2764#else
2765        OsiSolverInterface * solver2 = saveSolver->clone();
2766#endif
2767        const double *lower = saveSolver->getColLower() ;
2768        const double *upper = saveSolver->getColUpper() ;
2769        for (int i = 0 ; i < numberIntegers_ ; i++) {
2770          int iColumn = integerVariable_[i] ;
2771          solver2->setColLower(iColumn,lower[iColumn]);
2772          solver2->setColUpper(iColumn,upper[iColumn]);
2773        }
2774        // swap
2775        delete saveSolver;
2776        saveSolver=solver2;
2777        double * newSolution = new double[numberColumns];
2778        double objectiveValue=cutoff;
2779        CbcSerendipity heuristic(*this);
2780        if (bestSolution_)
2781          heuristic.setInputSolution(bestSolution_,bestObjective_);
2782        heuristic.setFractionSmall(0.6);
2783        heuristic.setFeasibilityPumpOptions(1008013);
2784        // Use numberNodes to say how many are original rows
2785        heuristic.setNumberNodes(continuousSolver_->getNumRows());
2786#ifdef COIN_DEVELOP
2787        if (continuousSolver_->getNumRows()<
2788            solver_->getNumRows())
2789          printf("%d rows added ZZZZZ\n",
2790                 solver_->getNumRows()-continuousSolver_->getNumRows());
2791#endif
2792        int returnCode= heuristic.smallBranchAndBound(saveSolver,
2793                                                      -1,newSolution,
2794                                                      objectiveValue,
2795                                                      cutoff,"Reduce");
2796        if (returnCode<0) {
2797#ifdef COIN_DEVELOP
2798          printf("Restart - not small enough to do search after fixing\n");
2799#endif
2800          delete [] newSolution;
2801        } else {
2802          if ((returnCode&1)!=0) {
2803            // increment number of solutions so other heuristics can test
2804            numberSolutions_++;
2805            numberHeuristicSolutions_++;
2806            lastHeuristic_ = NULL;
2807            setBestSolution(CBC_ROUNDING,objectiveValue,newSolution) ;
2808          }
2809          delete [] newSolution;
2810          if (tree_->size()) {
2811            double dummyBest;
2812            tree_->cleanTree(this,-COIN_DBL_MAX,dummyBest) ;
2813          }
2814          break;
2815        }
2816      } 
2817      delete saveSolver;
2818      saveSolver=NULL;
2819    }
2820/*
2821  Check for abort on limits: node count, solution count, time, integrality gap.
2822*/
2823    totalTime = getCurrentSeconds() ;
2824    double maxSeconds = getMaximumSeconds();
2825    if (parentModel_)
2826      maxSeconds=CoinMin(maxSeconds,parentModel_->getMaximumSeconds());
2827    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
2828          numberSolutions_ < intParam_[CbcMaxNumSol] &&
2829          totalTime < maxSeconds &&
2830          !stoppedOnGap_&&!eventHappened_&&(maximumNumberIterations_<0||
2831                                            numberIterations_<maximumNumberIterations_))) {
2832      // out of loop
2833      break;
2834    }
2835#ifdef BONMIN
2836    assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible());
2837#endif
2838    if (cutoff > getCutoff()) {
2839      double newCutoff = getCutoff();
2840      if (analyzeResults_) {
2841        // see if we could fix any (more)
2842        int n=0;
2843        double * newLower = analyzeResults_;
2844        double * objLower = newLower+numberIntegers_;
2845        double * newUpper = objLower+numberIntegers_;
2846        double * objUpper = newUpper+numberIntegers_;
2847        for (int i=0;i<numberIntegers_;i++) {
2848          if (objLower[i]>newCutoff) {
2849            n++;
2850            if (objUpper[i]>newCutoff) {
2851              newCutoff = -COIN_DBL_MAX;
2852              break;
2853            }
2854          } else if (objUpper[i]>newCutoff) {
2855            n++;
2856          }
2857        }
2858        if (newCutoff==-COIN_DBL_MAX) {
2859          printf("Root analysis says finished\n");
2860        } else if (n>numberFixedNow_) {
2861          printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
2862          numberFixedNow_=n;
2863        }
2864      }
2865      if (eventHandler) {
2866        if (!eventHandler->event(CbcEventHandler::solution)) {
2867          eventHappened_=true; // exit
2868        }
2869      }
2870      if (parallelMode()>0)
2871        lockThread();
2872      // Do from deepest
2873      tree_->cleanTree(this, newCutoff,bestPossibleObjective_) ;
2874      nodeCompare_->newSolution(this) ;
2875      nodeCompare_->newSolution(this,continuousObjective_,
2876                                continuousInfeasibilities_) ;
2877      tree_->setComparison(*nodeCompare_) ;
2878      if (tree_->empty()) {
2879        if (parallelMode()>0)
2880          unlockThread();
2881        // For threads we need to check further
2882        //break; // finished
2883        continue;
2884      }
2885      if (parallelMode()>0)
2886        unlockThread();
2887    }
2888    cutoff = getCutoff() ;
2889/*
2890    Periodic activities: Opportunities to
2891    + tweak the nodeCompare criteria,
2892    + check if we've closed the integrality gap enough to quit,
2893    + print a summary line to let the user know we're working
2894*/
2895    if (numberNodes_>=lastEvery1000) {
2896      if (parallelMode()>0)
2897        lockThread();
2898#ifdef COIN_HAS_CLP
2899      // Possible change of pivot method
2900      if(!savePivotMethod&&!parentModel_) {
2901        OsiClpSolverInterface * clpSolver
2902          = dynamic_cast<OsiClpSolverInterface *> (solver_);
2903        if (clpSolver&&numberNodes_>=1000&&numberNodes_<2000) {
2904          if (numberIterations_<numberNodes_*20) {
2905            ClpSimplex * simplex = clpSolver->getModelPtr();
2906            ClpDualRowPivot * pivotMethod=simplex->dualRowPivot();
2907            ClpDualRowDantzig * pivot =
2908              dynamic_cast< ClpDualRowDantzig*>(pivotMethod);
2909            if (!pivot) {
2910              savePivotMethod = pivotMethod->clone(true);
2911              ClpDualRowDantzig dantzig;
2912              simplex->setDualRowPivotAlgorithm(dantzig);
2913#ifdef COIN_DEVELOP
2914              printf("%d node, %d iterations ->Dantzig\n",numberNodes_,
2915                     numberIterations_);
2916#endif
2917#ifdef CBC_THREAD
2918              for (int i=0;i<numberThreads_;i++) {
2919                threadInfo[i].dantzigState=-1;
2920              }
2921#endif
2922            }
2923          }
2924        }
2925      }
2926#endif
2927      lastEvery1000 = numberNodes_ + 1000;
2928      bool redoTree=nodeCompare_->every1000Nodes(this, numberNodes_) ;
2929#ifdef CHECK_CUT_SIZE
2930      verifyCutSize (tree_, *this);
2931#endif
2932      // redo tree if wanted
2933      if (redoTree)
2934        tree_->setComparison(*nodeCompare_) ;
2935#if MODEL2
2936      if (searchStrategy_==2) {
2937        // may be time to tweak numberBeforeTrust
2938        if (numberStrongIterations_*5<numberIterations_&&numberNodes_<-10000) {
2939          int numberDone = strongInfo_[0]-strongInfo_[3];
2940          int numberFixed = strongInfo_[1]-strongInfo_[4];
2941          int numberInfeasible = strongInfo_[2]-strongInfo_[5];
2942          int numberNodes=numberNodes_-strongInfo_[6];
2943          for (int i=0;i<7;i++)
2944            printf("%d ",strongInfo_[i]);
2945          printf("its %d strong %d\n",
2946                 numberIterations_,numberStrongIterations_);
2947          printf("done %d fixed %d inf %d in %d nodes\n",
2948                 numberDone,numberFixed,numberInfeasible,numberNodes);
2949          if (numberInfeasible*500+numberFixed*10>numberDone) {
2950            synchronizeNumberBeforeTrust(1);
2951            strongInfo_[3]=strongInfo_[0];
2952            strongInfo_[4]=strongInfo_[1];
2953            strongInfo_[5]=strongInfo_[2];
2954            strongInfo_[6]=numberNodes_;
2955          }
2956        }
2957      }
2958#endif
2959      if (parallelMode()>0)
2960        unlockThread();
2961    }
2962    if (saveCompare&&!hotstartSolution_) {
2963      // hotstart switched off
2964      delete nodeCompare_; // off depth first
2965      nodeCompare_=saveCompare;
2966      saveCompare=NULL;
2967      // redo tree
2968      if (parallelMode()>0)
2969        lockThread();
2970      tree_->setComparison(*nodeCompare_) ;
2971      if (parallelMode()>0)
2972        unlockThread();
2973    }
2974    if (numberNodes_>=lastPrintEvery) {
2975      lastPrintEvery = numberNodes_ + printFrequency_;
2976#ifdef CBC_INSTRUMENT
2977      if (0) {
2978        printf("==Start instrument\n");
2979        for (int iObject=0;iObject<numberObjects_;iObject++) {
2980          CbcSimpleIntegerDynamicPseudoCost * obj =
2981            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[iObject]) ;
2982          if (obj)
2983            obj->print();
2984        }
2985        printf("==End instrument\n");
2986      }
2987#endif
2988      if (parallelMode()>0)
2989        lockThread();
2990      int nNodes = tree_->size() ;
2991
2992      //MODIF PIERRE
2993      bestPossibleObjective_ = tree_->getBestPossibleObjective();
2994      if (parallelMode()>0)
2995        unlockThread();
2996      if (!intParam_[CbcPrinting]) {
2997        messageHandler()->message(CBC_STATUS,messages())
2998          << numberNodes_<< nNodes<< bestObjective_<< bestPossibleObjective_
2999          <<getCurrentSeconds()
3000          << CoinMessageEol ;
3001      } else if (intParam_[CbcPrinting]==1) {
3002        messageHandler()->message(CBC_STATUS2,messages())
3003          << numberNodes_<< nNodes<< bestObjective_<< bestPossibleObjective_
3004          <<lastDepth<<lastUnsatisfied<<numberIterations_
3005          <<getCurrentSeconds()
3006          << CoinMessageEol ;
3007      } else if (!numberExtraIterations_) {
3008        messageHandler()->message(CBC_STATUS2,messages())
3009          << numberNodes_<< nNodes<< bestObjective_<< bestPossibleObjective_
3010          <<lastDepth<<lastUnsatisfied<<numberIterations_
3011          <<getCurrentSeconds()
3012          << CoinMessageEol ;
3013      } else {
3014        messageHandler()->message(CBC_STATUS3,messages())
3015          << numberNodes_<<numberExtraNodes_<< nNodes<< bestObjective_<< bestPossibleObjective_
3016          <<lastDepth<<lastUnsatisfied<<numberIterations_<<numberExtraIterations_
3017          <<getCurrentSeconds()
3018          << CoinMessageEol ;
3019      }
3020      if (!eventHandler->event(CbcEventHandler::treeStatus)) {
3021        eventHappened_=true; // exit
3022      }
3023    }
3024    // See if can stop on gap
3025    double testGap = CoinMax(dblParam_[CbcAllowableGap],
3026                             CoinMax(fabs(bestObjective_),fabs(bestPossibleObjective_))
3027                             *dblParam_[CbcAllowableFractionGap]);
3028    if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
3029      stoppedOnGap_ = true ;
3030    }
3031   
3032#ifdef CHECK_NODE_FULL
3033    verifyTreeNodes(tree_,*this) ;
3034#   endif
3035#   ifdef CHECK_CUT_COUNTS
3036    verifyCutCounts(tree_,*this) ;
3037#   endif
3038/*
3039  Now we come to the meat of the loop. To create the active subproblem, we'll
3040  pop the most promising node in the live set, rebuild the subproblem it
3041  represents, and then execute the current arm of the branch to create the
3042  active subproblem.
3043*/
3044    CbcNode * node=NULL;
3045#ifdef CBC_THREAD
3046    if (!parallelMode()||parallelMode()==-1) {
3047#endif
3048      node = tree_->bestNode(cutoff) ;
3049      // Possible one on tree worse than cutoff
3050      if (!node||node->objectiveValue()>cutoff) 
3051        continue;
3052      // Do main work of solving node here
3053      doOneNode(this,node,createdNode);
3054#ifdef CBC_THREAD
3055    } else if (parallelMode()>0) {
3056      node = tree_->bestNode(cutoff) ;
3057      // Possible one on tree worse than cutoff
3058      if (!node||node->objectiveValue()>cutoff) 
3059        continue;
3060      threadStats[0]++;
3061      //need to think
3062      int iThread;
3063      // Start one off if any available
3064      for (iThread=0;iThread<numberThreads_;iThread++) {
3065        if (threadInfo[iThread].returnCode==-1) 
3066          break;
3067      }
3068      if (iThread<numberThreads_) {
3069        threadInfo[iThread].node=node;
3070        assert (threadInfo[iThread].returnCode==-1);
3071        // say in use
3072        threadInfo[iThread].returnCode=0;
3073        threadModel[iThread]->moveToModel(this,0);
3074        pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3075        threadCount[iThread]++;
3076      }
3077      lockThread();
3078      locked=true;
3079      // see if any finished
3080      for (iThread=0;iThread<numberThreads_;iThread++) {
3081        if (threadInfo[iThread].returnCode>0) 
3082          break;
3083      }
3084      unlockThread();
3085      locked=false;
3086      if (iThread<numberThreads_) {
3087        threadModel[iThread]->moveToModel(this,1);
3088        assert (threadInfo[iThread].returnCode==1);
3089        // say available
3090        threadInfo[iThread].returnCode=-1;
3091        // carry on
3092        threadStats[3]++;
3093      } else {
3094        // Start one off if any available
3095        for (iThread=0;iThread<numberThreads_;iThread++) {
3096          if (threadInfo[iThread].returnCode==-1) 
3097            break;
3098        }
3099        if (iThread<numberThreads_) {
3100          lockThread();
3101          locked=true;
3102          // If any on tree get
3103          if (!tree_->empty()) {
3104            //node = tree_->bestNode(cutoff) ;
3105            //assert (node);
3106            threadStats[1]++;
3107            continue; // ** get another node
3108          }
3109          unlockThread();
3110          locked=false;
3111        }
3112        // wait (for debug could sleep and use test)
3113        bool finished=false;
3114        while (!finished) {
3115          pthread_mutex_lock(&condition_mutex);
3116          struct timespec absTime;
3117          my_gettime(&absTime);
3118          double time = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
3119          absTime.tv_nsec += 1000000; // millisecond
3120          if (absTime.tv_nsec>=1000000000) {
3121            absTime.tv_nsec -= 1000000000;
3122            absTime.tv_sec++;
3123          }
3124          pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
3125          my_gettime(&absTime);
3126          double time2 = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
3127          timeWaiting += time2-time;
3128          pthread_mutex_unlock(&condition_mutex);
3129          for (iThread=0;iThread<numberThreads_;iThread++) {
3130            if (threadInfo[iThread].returnCode>0) {
3131              finished=true;
3132              break;
3133            } else if (threadInfo[iThread].returnCode==0) {
3134              pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3135            }
3136          }
3137        }
3138        assert (iThread<numberThreads_);
3139        // move information to model
3140        threadModel[iThread]->moveToModel(this,1);
3141        node = threadInfo[iThread].node;
3142        threadInfo[iThread].node=NULL;
3143        assert (threadInfo[iThread].returnCode==1);
3144        // say available
3145        threadInfo[iThread].returnCode=-1;
3146        // carry on
3147        threadStats[2]++;
3148      }
3149    } else {
3150      // Deterministic parallel
3151      if (tree_->size()<5*numberThreads_&&!goneParallel) {
3152        node = tree_->bestNode(cutoff) ;
3153        // Possible one on tree worse than cutoff
3154        if (!node||node->objectiveValue()>cutoff)
3155          continue;
3156        // Do main work of solving node here
3157        doOneNode(this,node,createdNode);
3158        assert (createdNode);
3159        if (!createdNode->active()) {
3160          delete createdNode;
3161          createdNode=NULL;
3162        } else {
3163          // Say one more pointing to this
3164          node->nodeInfo()->increment() ;
3165          tree_->push(createdNode) ;
3166        }
3167        if (node->active()) {
3168          assert (node->nodeInfo());
3169          if (node->nodeInfo()->numberBranchesLeft()) {
3170            tree_->push(node) ;
3171          } else {
3172            node->setActive(false);
3173          }
3174        } else {
3175          if (node->nodeInfo()) {
3176            if (!node->nodeInfo()->numberBranchesLeft())
3177              node->nodeInfo()->allBranchesGone(); // can clean up
3178            // So will delete underlying stuff
3179            node->setActive(true);
3180          }
3181          delNode[nDeleteNode++]=node;
3182          node=NULL;
3183        } 
3184        if (nDeleteNode>=MAX_DEL_NODE) {
3185          for (int i=0;i<nDeleteNode;i++) {
3186            //printf("trying to del %d %x\n",i,delNode[i]);
3187            delete delNode[i];
3188            //printf("done to del %d %x\n",i,delNode[i]);
3189          }
3190          nDeleteNode=0;
3191        }
3192      } else {
3193        // Split
3194        int saveTreeSize = tree_->size();
3195        goneParallel=true;
3196        int nAffected=splitModel(numberThreads_,threadModel,defaultParallelNodes);
3197#ifndef NDEBUG
3198        int saveTreeSize2 = tree_->size();
3199#endif
3200        int iThread;
3201        // do all until finished
3202        for (iThread=0;iThread<numberThreads_;iThread++) {
3203          // obviously tune
3204          threadInfo[iThread].nDeleteNode=defaultParallelIterations;
3205        }
3206        // Save current state
3207        int iObject;
3208        for (iObject=0;iObject<numberObjects_;iObject++) {
3209          saveObjects[iObject]->updateBefore(object_[iObject]);
3210        }
3211        for (iThread=0;iThread<numberThreads_;iThread++) {
3212          threadInfo[iThread].returnCode=0;
3213          pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3214        }
3215        // wait
3216        bool finished=false;
3217        while (!finished) {
3218          pthread_mutex_lock(&condition_mutex);
3219          struct timespec absTime;
3220          my_gettime(&absTime);
3221          double time = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
3222          absTime.tv_nsec += 1000000; // millisecond
3223          if (absTime.tv_nsec>=1000000000) {
3224            absTime.tv_nsec -= 1000000000;
3225            absTime.tv_sec++;
3226          }
3227          pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
3228          my_gettime(&absTime);
3229          double time2 = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
3230          timeWaiting += time2-time;
3231          pthread_mutex_unlock(&condition_mutex);
3232          finished=true;
3233          for (iThread=0;iThread<numberThreads_;iThread++) {
3234            if (threadInfo[iThread].returnCode<=0) {
3235              finished=false;
3236            }
3237          }
3238        }
3239        // Unmark marked
3240        for (int i=0;i<nAffected;i++) {
3241          walkback_[i]->unmark();
3242        }
3243        assert (saveTreeSize2 == tree_->size());
3244        if (0) { 
3245          // put back cut counts
3246          for (int i=0;i<nAffected;i++) {
3247            walkback_[i]->decrementCuts(1000000);
3248          }
3249        }
3250#if 0 //ndef NDEBUG
3251        for (iObject=0;iObject<numberObjects_;iObject++) {
3252          CbcSimpleIntegerDynamicPseudoCost * obj =
3253            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[iObject]) ;
3254          CbcSimpleIntegerDynamicPseudoCost * obj2 =
3255            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(saveObjects[iObject]) ;
3256          if (obj)
3257            assert (obj->same(obj2));
3258        }
3259#endif
3260        int iModel;
3261        double scaleFactor=1.0;
3262        for (iModel=0;iModel<numberThreads_;iModel++) {
3263          //printf("model %d tree size %d\n",iModel,threadModel[iModel]->tree_->size());
3264          if (saveTreeSize>4*numberThreads_*defaultParallelNodes) {
3265            if (!threadModel[iModel]->tree_->size()) {
3266              scaleFactor *= 1.05;
3267            }
3268          }
3269          threadModel[iModel]->moveToModel(this,11);
3270          // Update base model
3271          OsiObject ** threadObject = threadModel[iModel]->object_;
3272          for (iObject=0;iObject<numberObjects_;iObject++) {
3273            object_[iObject]->updateAfter(threadObject[iObject],saveObjects[iObject]);
3274          }
3275        }
3276        if (scaleFactor!=1.0) {
3277          int newNumber = static_cast<int> (defaultParallelNodes * scaleFactor+0.5001);
3278          if (newNumber*2<defaultParallelIterations) {
3279            char general[200];
3280            sprintf(general,"Changing tree size from %d to %d",
3281                    defaultParallelNodes,newNumber);
3282            messageHandler()->message(CBC_GENERAL,
3283                                      messages())
3284              << general << CoinMessageEol ;
3285            defaultParallelNodes = newNumber;
3286          }
3287        }
3288          //printf("Tree sizes %d %d %d - affected %d\n",saveTreeSize,saveTreeSize2,tree_->size(),nAffected);
3289      }
3290    }
3291#endif
3292  }
3293  if (nDeleteNode) {
3294    for (int i=0;i<nDeleteNode;i++) {
3295      delete delNode[i];
3296    }
3297    nDeleteNode=0;
3298  }
3299#ifdef CBC_THREAD
3300  if (numberThreads_) {
3301    //printf("stats ");
3302    //for (unsigned int j=0;j<sizeof(threadStats)/sizeof(int);j++)
3303    //printf("%d ",threadStats[j]);
3304    //printf("\n");
3305    int i;
3306    // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
3307    double time=0.0;
3308    for (i=0;i<numberThreads_;i++) 
3309      time += threadInfo[i].timeInThread;
3310    bool goodTimer = time<(getCurrentSeconds());
3311    //bool stopped = (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
3312    //        numberSolutions_ < intParam_[CbcMaxNumSol] &&
3313    //        totalTime < dblParam_[CbcMaximumSeconds] &&
3314    //        !stoppedOnGap_&&!eventHappened_));
3315    for (i=0;i<numberThreads_;i++) {
3316      while (threadInfo[i].returnCode==0) {
3317        pthread_cond_signal(threadInfo[i].condition2); // unlock
3318        pthread_mutex_lock(&condition_mutex);
3319        struct timespec absTime;
3320        my_gettime(&absTime);
3321        absTime.tv_nsec += 1000000; // millisecond
3322        if (absTime.tv_nsec>=1000000000) {
3323          absTime.tv_nsec -= 1000000000;
3324          absTime.tv_sec++;
3325        }
3326        pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
3327        my_gettime(&absTime);
3328        pthread_mutex_unlock(&condition_mutex);
3329      }
3330      pthread_cond_signal(threadInfo[i].condition2); // unlock
3331      pthread_mutex_lock(&condition_mutex); // not sure necessary but have had one hang on interrupt
3332      threadModel[i]->numberThreads_=0; // say exit
3333      if (parallelMode()<0)
3334        delete [] threadInfo[i].delNode;
3335      threadInfo[i].returnCode=0;
3336      pthread_mutex_unlock(&condition_mutex);
3337      pthread_cond_signal(threadInfo[i].condition2); // unlock
3338      //if (!stopped)
3339      //pthread_join(threadId[i],NULL);
3340      int returnCode;
3341      returnCode=pthread_join(threadId[i].thr,NULL);
3342      threadId[i].status = 0;
3343      assert (!returnCode);
3344        //else
3345        //pthread_kill(threadId[i]); // kill rather than try and synchronize
3346      threadModel[i]->moveToModel(this,2);
3347      pthread_mutex_destroy (threadInfo[i].mutex2);
3348      pthread_cond_destroy (threadInfo[i].condition2);
3349      assert (threadInfo[i].numberTimesLocked==threadInfo[i].numberTimesUnlocked);
3350      handler_->message(CBC_THREAD_STATS,messages_)
3351        <<"Thread";
3352      handler_->printing(true)
3353        <<i<<threadCount[i]<<threadInfo[i].timeWaitingToStart;
3354      handler_->printing(goodTimer)<<threadInfo[i].timeInThread;
3355      handler_->printing(false)<<0.0;
3356      handler_->printing(true)<<threadInfo[i].numberTimesLocked
3357        <<threadInfo[i].timeLocked<<threadInfo[i].timeWaitingToLock
3358        <<CoinMessageEol;
3359    }
3360    assert (threadInfo[numberThreads_].numberTimesLocked==threadInfo[numberThreads_].numberTimesUnlocked);
3361    handler_->message(CBC_THREAD_STATS,messages_)
3362      <<"Main thread";
3363    handler_->printing(false)<<0<<0<<0.0;
3364    handler_->printing(false)<<0.0;
3365    handler_->printing(true)<<timeWaiting;
3366    handler_->printing(true)<<threadInfo[numberThreads_].numberTimesLocked
3367      <<threadInfo[numberThreads_].timeLocked<<threadInfo[numberThreads_].timeWaitingToLock
3368      <<CoinMessageEol;
3369    pthread_mutex_destroy (&mutex);
3370    pthread_cond_destroy (&condition_main);
3371    pthread_mutex_destroy (&condition_mutex);
3372    // delete models (here in case some point to others)
3373    for (i=0;i<numberThreads_;i++) {
3374      // make sure handler will be deleted
3375      threadModel[i]->defaultHandler_=true;
3376      delete threadModel[i];
3377    }
3378    delete [] mutex2;
3379    delete [] condition2;
3380    delete [] threadId;
3381    delete [] threadInfo;
3382    delete [] threadModel;
3383    delete [] threadCount;
3384    mutex_=NULL;
3385    // adjust time to allow for children on some systems
3386    dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren();
3387  }
3388#endif
3389/*
3390  End of the non-abort actions. The next block of code is executed if we've
3391  aborted because we hit one of the limits. Clean up by deleting the live set
3392  and break out of the node processing loop. Note that on an abort, node may
3393  have been pushed back onto the tree for further processing, in which case
3394  it'll be deleted in cleanTree. We need to check.
3395*/
3396    double maxSeconds = getMaximumSeconds();
3397    if (parentModel_)
3398      maxSeconds=CoinMin(maxSeconds,parentModel_->getMaximumSeconds());
3399    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
3400          numberSolutions_ < intParam_[CbcMaxNumSol] &&
3401          totalTime < maxSeconds &&
3402          !stoppedOnGap_&&!eventHappened_&&(maximumNumberIterations_<0||
3403                                            numberIterations_<maximumNumberIterations_))) {
3404      if (tree_->size()) {
3405        double dummyBest;
3406        tree_->cleanTree(this,-COIN_DBL_MAX,dummyBest) ;
3407      }
3408      delete nextRowCut_;
3409      if (stoppedOnGap_)
3410        { messageHandler()->message(CBC_GAP,messages())
3411          << bestObjective_-bestPossibleObjective_
3412          << dblParam_[CbcAllowableGap]
3413          << dblParam_[CbcAllowableFractionGap]*100.0
3414          << CoinMessageEol ;
3415        secondaryStatus_ = 2;
3416        status_ = 0 ; }
3417        else
3418          if (isNodeLimitReached())
3419            { handler_->message(CBC_MAXNODES,messages_) << CoinMessageEol ;
3420            secondaryStatus_ = 3;
3421            status_ = 1 ; }
3422          else
3423        if (totalTime >= dblParam_[CbcMaximumSeconds])
3424          { handler_->message(CBC_MAXTIME,messages_) << CoinMessageEol ; 
3425          secondaryStatus_ = 4;
3426          status_ = 1 ; }
3427        else
3428          if (eventHappened_)
3429            { handler_->message(CBC_EVENT,messages_) << CoinMessageEol ; 
3430            secondaryStatus_ = 5;
3431            status_ = 5 ; }
3432          else
3433            { handler_->message(CBC_MAXSOLS,messages_) << CoinMessageEol ;
3434            secondaryStatus_ = 6;
3435            status_ = 1 ; }
3436    }
3437/*
3438  That's it, we've exhausted the search tree, or broken out of the loop because
3439  we hit some limit on evaluation.
3440
3441  We may have got an intelligent tree so give it one more chance
3442*/
3443  // Tell solver we are not in Branch and Cut
3444  solver_->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo,NULL) ;
3445  tree_->endSearch();
3446  //  If we did any sub trees - did we give up on any?
3447  if ( numberStoppedSubTrees_)
3448    status_=1;
3449  if (!status_) {
3450    // Set best possible unless stopped on gap
3451    if(secondaryStatus_ != 2)
3452      bestPossibleObjective_=bestObjective_;
3453    handler_->message(CBC_END_GOOD,messages_)
3454      << bestObjective_ << numberIterations_ << numberNodes_<<getCurrentSeconds()
3455      << CoinMessageEol ;
3456  } else {
3457    handler_->message(CBC_END,messages_)
3458      << bestObjective_ <<bestPossibleObjective_
3459      << numberIterations_ << numberNodes_<<getCurrentSeconds()
3460      << CoinMessageEol ;
3461  }
3462  if (numberStrongIterations_)
3463    handler_->message(CBC_STRONG_STATS,messages_)
3464      << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2]
3465      << strongInfo_[1] << CoinMessageEol ;
3466  if (!numberExtraNodes_) 
3467    handler_->message(CBC_OTHER_STATS,messages_)
3468      << maximumDepthActual_
3469      << numberDJFixed_ << CoinMessageEol ;
3470  else
3471    handler_->message(CBC_OTHER_STATS2,messages_)
3472      << maximumDepthActual_
3473      << numberDJFixed_ << numberExtraNodes_<<numberExtraIterations_
3474      <<CoinMessageEol ;
3475  if (doStatistics==100) {
3476    for (int i=0;i<numberObjects_;i++) {
3477      CbcSimpleIntegerDynamicPseudoCost * obj =
3478        dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
3479      if (obj)
3480        obj->print();
3481    }
3482  }
3483  if (statistics_) {
3484    // report in some way
3485    int * lookup = new int[numberObjects_];
3486    int i;
3487    for (i=0;i<numberObjects_;i++) 
3488      lookup[i]=-1;
3489    bool goodIds=false; //true;
3490    for (i=0;i<numberObjects_;i++) {
3491      int iColumn = object_[i]->columnNumber();
3492      if(iColumn>=0&&iColumn<numberColumns) {
3493        if (lookup[i]==-1) {
3494          lookup[i]=iColumn;
3495        } else {
3496          goodIds=false;
3497          break;
3498        }
3499      } else {
3500        goodIds=false;
3501        break;
3502      }
3503    }
3504    if (!goodIds) {
3505      delete [] lookup;
3506      lookup=NULL;
3507    }
3508    if (doStatistics>=3) {
3509      printf("  node parent depth column   value                    obj      inf\n");
3510      for ( i=0;i<numberNodes2_;i++) {
3511        statistics_[i]->print(lookup);
3512      }
3513    }
3514    if (doStatistics>1) {
3515      // Find last solution
3516      int k;
3517      for (k=numberNodes2_-1;k>=0;k--) {
3518        if (statistics_[k]->endingObjective()!=COIN_DBL_MAX&&
3519            !statistics_[k]->endingInfeasibility())
3520          break;
3521      }
3522      if (k>=0) {
3523        int depth=statistics_[k]->depth();
3524        int * which = new int[depth+1];
3525        for (i=depth;i>=0;i--) {
3526          which[i]=k;
3527          k=statistics_[k]->parentNode();
3528        }
3529        printf("  node parent depth column   value                    obj      inf\n");
3530        for (i=0;i<=depth;i++) {
3531          statistics_[which[i]]->print(lookup);
3532        }
3533        delete [] which;
3534      }
3535    }
3536    // now summary
3537    int maxDepth=0;
3538    double averageSolutionDepth=0.0;
3539    int numberSolutions=0;
3540    double averageCutoffDepth=0.0;
3541    double averageSolvedDepth=0.0;
3542    int numberCutoff=0;
3543    int numberDown=0;
3544    int numberFirstDown=0;
3545    double averageInfDown=0.0;
3546    double averageObjDown=0.0;
3547    int numberCutoffDown=0;
3548    int numberUp=0;
3549    int numberFirstUp=0;
3550    double averageInfUp=0.0;
3551    double averageObjUp=0.0;
3552    int numberCutoffUp=0;
3553    double averageNumberIterations1=0.0;
3554    double averageValue=0.0;
3555    for ( i=0;i<numberNodes2_;i++) {
3556      int depth =  statistics_[i]->depth(); 
3557      int way =  statistics_[i]->way(); 
3558      double value = statistics_[i]->value(); 
3559      double startingObjective =  statistics_[i]->startingObjective(); 
3560      int startingInfeasibility = statistics_[i]->startingInfeasibility(); 
3561      double endingObjective = statistics_[i]->endingObjective(); 
3562      int endingInfeasibility = statistics_[i]->endingInfeasibility(); 
3563      maxDepth = CoinMax(depth,maxDepth);
3564      // Only for completed
3565      averageNumberIterations1 += statistics_[i]->numberIterations();
3566      averageValue += value;
3567      if (endingObjective!=COIN_DBL_MAX&&!endingInfeasibility) {
3568        numberSolutions++;
3569        averageSolutionDepth += depth;
3570      }
3571      if (endingObjective==COIN_DBL_MAX) {
3572        numberCutoff++;
3573        averageCutoffDepth += depth;
3574        if (way<0) {
3575          numberDown++;
3576          numberCutoffDown++;
3577          if (way==-1)
3578            numberFirstDown++;
3579        } else {
3580          numberUp++;
3581          numberCutoffUp++;
3582          if (way==1)
3583            numberFirstUp++;
3584        }
3585      } else {
3586        averageSolvedDepth += depth;
3587        if (way<0) {
3588          numberDown++;
3589          averageInfDown += startingInfeasibility-endingInfeasibility;
3590          averageObjDown += endingObjective-startingObjective;
3591          if (way==-1)
3592            numberFirstDown++;
3593        } else {
3594          numberUp++;
3595          averageInfUp += startingInfeasibility-endingInfeasibility;
3596          averageObjUp += endingObjective-startingObjective;
3597          if (way==1)
3598            numberFirstUp++;
3599        }
3600      }
3601    }
3602    // Now print
3603    if (numberSolutions)
3604      averageSolutionDepth /= static_cast<double> (numberSolutions);
3605    int numberSolved = numberNodes2_-numberCutoff;
3606    double averageNumberIterations2=numberIterations_-averageNumberIterations1
3607      -numberIterationsAtContinuous;
3608    if(numberCutoff) {
3609      averageCutoffDepth /= static_cast<double> (numberCutoff);
3610      averageNumberIterations2 /= static_cast<double> (numberCutoff);
3611    }
3612    if (numberNodes2_) 
3613      averageValue /= static_cast<double> (numberNodes2_);
3614    if (numberSolved) {
3615      averageNumberIterations1 /= static_cast<double> (numberSolved);
3616      averageSolvedDepth /= static_cast<double> (numberSolved);
3617    }
3618    printf("%d solution(s) were found (by branching) at an average depth of %g\n",
3619           numberSolutions,averageSolutionDepth);
3620    printf("average value of variable being branched on was %g\n",
3621           averageValue);
3622    printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n",
3623           numberCutoff,averageCutoffDepth,averageNumberIterations2);
3624    printf("%d nodes were solved at an average depth of %g with iteration count of %g\n",
3625           numberSolved,averageSolvedDepth,averageNumberIterations1);
3626    if (numberDown) {
3627      averageInfDown /= static_cast<double> (numberDown);
3628      averageObjDown /= static_cast<double> (numberDown);
3629    }
3630    printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
3631           numberDown,numberFirstDown,numberDown-numberFirstDown,numberCutoffDown,
3632           averageInfDown,averageObjDown);
3633    if (numberUp) {
3634      averageInfUp /= static_cast<double> (numberUp);
3635      averageObjUp /= static_cast<double> (numberUp);
3636    }
3637    printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
3638           numberUp,numberFirstUp,numberUp-numberFirstUp,numberCutoffUp,
3639           averageInfUp,averageObjUp);
3640    for ( i=0;i<numberNodes2_;i++) 
3641      delete statistics_[i];
3642    delete [] statistics_;
3643    statistics_=NULL;
3644    maximumStatistics_=0;
3645    delete [] lookup;
3646  }
3647/*
3648  If we think we have a solution, restore and confirm it with a call to
3649  setBestSolution().  We need to reset the cutoff value so as not to fathom
3650  the solution on bounds.  Note that calling setBestSolution( ..., true)
3651  leaves the continuousSolver_ bounds vectors fixed at the solution value.
3652
3653  Running resolve() here is a failsafe --- setBestSolution has already
3654  reoptimised using the continuousSolver_. If for some reason we fail to
3655  prove optimality, run the problem again after instructing the solver to
3656  tell us more.
3657
3658  If all looks good, replace solver_ with continuousSolver_, so that the
3659  outside world will be able to obtain information about the solution using
3660  public methods.
3661*/
3662  if (bestSolution_&&(solverCharacteristics_->solverType()<2||solverCharacteristics_->solverType()==4)) 
3663  { setCutoff(1.0e50) ; // As best solution should be worse than cutoff
3664    phase_=5;
3665    double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
3666    if ((specialOptions_&4)==0)
3667      bestObjective_ += 100.0*increment+1.0e-3; // only set if we are going to solve
3668    setBestSolution(CBC_END_SOLUTION,bestObjective_,bestSolution_,1) ;
3669    continuousSolver_->resolve() ;
3670    if (!continuousSolver_->isProvenOptimal())
3671    { continuousSolver_->messageHandler()->setLogLevel(2) ;
3672      continuousSolver_->initialSolve() ; }
3673    delete solver_ ;
3674    // above deletes solverCharacteristics_
3675    solverCharacteristics_ = NULL;
3676    solver_ = continuousSolver_ ;
3677    setPointers(solver_);
3678    continuousSolver_ = NULL ; }
3679/*
3680  Clean up dangling objects. continuousSolver_ may already be toast.
3681*/
3682  delete lastws ;
3683  if (saveObjects) {
3684    for (int i=0;i<numberObjects_;i++)
3685      delete saveObjects[i];
3686    delete [] saveObjects;
3687  }
3688  numberStrong_ = saveNumberStrong;
3689  numberBeforeTrust_ = saveNumberBeforeTrust;
3690  delete [] whichGenerator_ ;
3691  whichGenerator_=NULL;
3692  delete [] lowerBefore ;
3693  delete [] upperBefore ;
3694  delete [] walkback_ ;
3695  walkback_ = NULL ;
3696#ifdef NODE_LAST
3697  delete [] lastNodeInfo_ ;
3698  lastNodeInfo_ = NULL;
3699  delete [] lastNumberCuts_ ;
3700  lastNumberCuts_ = NULL;
3701  delete [] lastCut_;
3702  lastCut_ = NULL;
3703#endif
3704  delete [] addedCuts_ ;
3705  addedCuts_ = NULL ;
3706  //delete persistentInfo;
3707  // Get rid of characteristics
3708  solverCharacteristics_=NULL;
3709  if (continuousSolver_)
3710  { delete continuousSolver_ ;
3711    continuousSolver_ = NULL ; }
3712/*
3713  Destroy global cuts by replacing with an empty OsiCuts object.
3714*/
3715  globalCuts_= OsiCuts() ;
3716  if (!bestSolution_) {
3717    // make sure lp solver is infeasible
3718    int numberColumns = solver_->getNumCols();
3719    const double * columnLower = solver_->getColLower();
3720    int iColumn;
3721    for (iColumn=0;iColumn<numberColumns;iColumn++) {
3722      if (solver_->isInteger(iColumn)) 
3723        solver_->setColUpper(iColumn,columnLower[iColumn]);
3724    }
3725    solver_->initialSolve();
3726  }
3727#ifdef COIN_HAS_CLP
3728  {
3729    OsiClpSolverInterface * clpSolver
3730      = dynamic_cast<OsiClpSolverInterface *> (solver_);
3731    if (clpSolver) {
3732      // Possible restore of pivot method
3733      if(savePivotMethod) {
3734        // model may have changed
3735        savePivotMethod->setModel(NULL);
3736        clpSolver->getModelPtr()->setDualRowPivotAlgorithm(*savePivotMethod);
3737        delete savePivotMethod;
3738      }
3739      clpSolver->setLargestAway(-1.0);
3740    }
3741  }
3742#endif
3743  if(fastNodeDepth_>=1000000&&!parentModel_) {
3744    // delete object off end
3745    delete object_[numberObjects_];
3746    fastNodeDepth_ -= 1000000;
3747  }
3748  delete saveSolver;
3749#if COIN_DEVELOP>1
3750  void print_fac_stats();
3751  //if (!parentModel_)
3752  //  print_fac_stats();
3753#endif
3754  if (strategy_&&strategy_->preProcessState()>0) {
3755    // undo preprocessing
3756    CglPreProcess * process = strategy_->process();
3757    assert (process);
3758    int n = originalSolver->getNumCols();
3759    if (bestSolution_) {
3760      delete [] bestSolution_;
3761      bestSolution_ = new double [n];
3762      process->postProcess(*solver_);
3763    }
3764    strategy_->deletePreProcess();
3765    // Solution now back in originalSolver
3766    delete solver_;
3767    solver_=originalSolver;
3768    if (bestSolution_)
3769      memcpy(bestSolution_,solver_->getColSolution(),n*sizeof(double));
3770    // put back original objects if there were any
3771    if (originalObject) {
3772      int iColumn;
3773      assert (ownObjects_);
3774      for (iColumn=0;iColumn<numberObjects_;iColumn++) 
3775        delete object_[iColumn];
3776      delete [] object_;
3777      numberObjects_ = numberOriginalObjects;
3778      object_=originalObject;
3779      delete [] integerVariable_;
3780      numberIntegers_=0;
3781      for (iColumn=0;iColumn<n;iColumn++) {
3782        if (solver_->isInteger(iColumn))
3783          numberIntegers_++;
3784      }
3785      integerVariable_ = new int[numberIntegers_];
3786      numberIntegers_=0;
3787      for (iColumn=0;iColumn<n;iColumn++) {
3788        if (solver_->isInteger(iColumn))
3789            integerVariable_[numberIntegers_++]=iColumn;
3790      }
3791    }
3792  }
3793#ifdef COIN_HAS_CLP
3794  {
3795    OsiClpSolverInterface * clpSolver
3796      = dynamic_cast<OsiClpSolverInterface *> (solver_);
3797    if (clpSolver) 
3798      clpSolver->setFakeObjective(reinterpret_cast<double *> (NULL));
3799  }
3800#endif
3801#ifdef CLP_QUICK_OPTIONS
3802  {
3803    OsiClpSolverInterface * clpSolver
3804      = dynamic_cast<OsiClpSolverInterface *> (solver_);
3805    if (clpSolver) {
3806      // Try and re-use regions   
3807      ClpSimplex * simplex = clpSolver->getModelPtr();
3808      simplex->setPersistenceFlag(0);
3809      clpSolver->deleteScaleFactors();
3810      clpSolver->setSpecialOptions(clpSolver->specialOptions()&(~131072));
3811      simplex->setSpecialOptions(simplex->specialOptions()&(~131072));
3812      simplex->setAlphaAccuracy(-1.0);
3813      //clpSolver->setSpecialOptions((clpSolver->specialOptions()&~128)|65536);
3814    }
3815  }
3816#endif
3817  return ;
3818 }
3819
3820
3821// Solve the initial LP relaxation
3822void 
3823CbcModel::initialSolve() 
3824{
3825  assert (solver_);
3826  assert (!solverCharacteristics_);
3827  OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
3828  if (solverCharacteristics) {
3829    solverCharacteristics_ = solverCharacteristics;
3830  } else {
3831    // replace in solver
3832    OsiBabSolver defaultC;
3833    solver_->setAuxiliaryInfo(&defaultC);
3834    solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
3835  }
3836  solverCharacteristics_->setSolver(solver_);
3837  solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
3838  solver_->initialSolve();
3839  solver_->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo,NULL) ;
3840  // But set up so Jon Lee will be happy
3841  status_=-1;
3842  secondaryStatus_ = -1;
3843  originalContinuousObjective_ = solver_->getObjValue()*solver_->getObjSense();
3844  delete [] continuousSolution_;
3845  continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
3846                                             solver_->getNumCols());
3847  setPointers(solver_);
3848  solverCharacteristics_ = NULL;
3849}
3850
3851/*! \brief Get an empty basis object
3852
3853  Return an empty CoinWarmStartBasis object with the requested capacity,
3854  appropriate for the current solver. The object is cloned from the object
3855  cached as emptyWarmStart_. If there is no cached object, the routine
3856  queries the solver for a warm start object, empties it, and caches the
3857  result.
3858*/
3859
3860CoinWarmStartBasis *CbcModel::getEmptyBasis (int ns, int na) const
3861
3862{ CoinWarmStartBasis *emptyBasis ;
3863/*
3864  Acquire an empty basis object, if we don't yet have one.
3865*/
3866  if (emptyWarmStart_ == 0)
3867  { if (solver_ == 0)
3868    { throw CoinError("Cannot construct basis without solver!",
3869                      "getEmptyBasis","CbcModel") ; }
3870    emptyBasis =
3871        dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
3872    if (emptyBasis == 0)
3873    { throw CoinError(
3874        "Solver does not appear to use a basis-oriented warm start.",
3875        "getEmptyBasis","CbcModel") ; }
3876    emptyBasis->setSize(0,0) ;
3877    emptyWarmStart_ = dynamic_cast<CoinWarmStart *>(emptyBasis) ; }
3878/*
3879  Clone the empty basis object, resize it as requested, and return.
3880*/
3881  emptyBasis = dynamic_cast<CoinWarmStartBasis *>(emptyWarmStart_->clone()) ;
3882  assert(emptyBasis) ;
3883  if (ns != 0 || na != 0) emptyBasis->setSize(ns,na) ;
3884
3885  return (emptyBasis) ; }
3886   
3887
3888/** Default Constructor
3889
3890  Creates an empty model without an associated solver.
3891*/
3892CbcModel::CbcModel() 
3893
3894:
3895  solver_(NULL),
3896  ownership_(0x80000000),
3897  continuousSolver_(NULL),
3898  referenceSolver_(NULL),
3899  defaultHandler_(true),
3900  emptyWarmStart_(NULL),
3901  bestObjective_(COIN_DBL_MAX),
3902  bestPossibleObjective_(COIN_DBL_MAX),
3903  sumChangeObjective1_(0.0),
3904  sumChangeObjective2_(0.0),
3905  bestSolution_(NULL),
3906  currentSolution_(NULL),
3907  testSolution_(NULL),
3908  minimumDrop_(1.0e-4),
3909  numberSolutions_(0),
3910  stateOfSearch_(0),
3911  whenCuts_(-1),
3912  hotstartSolution_(NULL),
3913  hotstartPriorities_(NULL),
3914  numberHeuristicSolutions_(0),
3915  numberNodes_(0),
3916  numberNodes2_(0),
3917  numberIterations_(0),
3918  status_(-1),
3919  secondaryStatus_(-1),
3920  numberIntegers_(0),
3921  numberRowsAtContinuous_(0),
3922  maximumNumberCuts_(0),
3923  phase_(0),
3924  currentNumberCuts_(0),
3925  maximumDepth_(0),
3926  walkback_(NULL),
3927#ifdef NODE_LAST
3928  lastNodeInfo_(NULL),
3929  lastCut_(NULL),
3930  lastDepth_(0),
3931  lastNumberCuts2_(0),
3932  maximumCuts_(0),
3933  lastNumberCuts_(NULL),
3934#endif
3935  addedCuts_(NULL),
3936  nextRowCut_(NULL),
3937  currentNode_(NULL),
3938  integerVariable_(NULL),
3939  integerInfo_(NULL),
3940  continuousSolution_(NULL),
3941  usedInSolution_(NULL),
3942  specialOptions_(0),
3943  subTreeModel_(NULL),
3944  numberStoppedSubTrees_(0),
3945  mutex_(NULL),
3946  presolve_(0),
3947  numberStrong_(5),
3948  numberBeforeTrust_(10),
3949  numberPenalties_(20),
3950  stopNumberIterations_(-1),
3951  penaltyScaleFactor_(3.0),
3952  numberAnalyzeIterations_(0),
3953  analyzeResults_(NULL),
3954  numberInfeasibleNodes_(0),
3955  problemType_(0),
3956  printFrequency_(0),
3957  numberCutGenerators_(0),
3958  generator_(NULL),
3959  virginGenerator_(NULL),
3960  numberHeuristics_(0),
3961  heuristic_(NULL),
3962  lastHeuristic_(NULL),
3963# ifdef COIN_HAS_CLP
3964  fastNodeDepth_(-1),
3965#endif
3966  eventHandler_(NULL),
3967  numberObjects_(0),
3968  object_(NULL),
3969  ownObjects_(true),
3970  originalColumns_(NULL),
3971  howOftenGlobalScan_(1),
3972  numberGlobalViolations_(0),
3973  numberExtraIterations_(0),
3974  numberExtraNodes_(0),
3975  continuousObjective_(COIN_DBL_MAX),
3976  originalContinuousObjective_(COIN_DBL_MAX),
3977  continuousInfeasibilities_(COIN_INT_MAX),
3978  maximumCutPassesAtRoot_(20),
3979  maximumCutPasses_(10),
3980  preferredWay_(0),
3981  currentPassNumber_(0),
3982  maximumWhich_(1000),
3983  maximumRows_(0),
3984  currentDepth_(0),
3985  whichGenerator_(NULL),
3986  maximumStatistics_(0),
3987  statistics_(NULL),
3988  maximumDepthActual_(0),
3989  numberDJFixed_(0.0),
3990  probingInfo_(NULL),
3991  numberFixedAtRoot_(0),
3992  numberFixedNow_(0),
3993  stoppedOnGap_(false),
3994  eventHappened_(false),
3995  numberLongStrong_(0),
3996  numberOldActiveCuts_(0),
3997  numberNewCuts_(0),
3998  sizeMiniTree_(0),
3999  searchStrategy_(-1),
4000  numberStrongIterations_(0),
4001  resolveAfterTakeOffCuts_(true),
4002  maximumNumberIterations_(-1),
4003#if NEW_UPDATE_OBJECT>1
4004  numberUpdateItems_(0),
4005  maximumNumberUpdateItems_(0),
4006  updateItems_(NULL),
4007#endif
4008  numberThreads_(0),
4009  threadMode_(0)
4010{
4011  memset(intParam_,0,sizeof(intParam_));
4012  intParam_[CbcMaxNumNode] = 2147483647;
4013  intParam_[CbcMaxNumSol] = 9999999;
4014  intParam_[CbcFathomDiscipline] = 0;
4015
4016  dblParam_[CbcIntegerTolerance] = 1e-6;
4017  dblParam_[CbcInfeasibilityWeight] = 0.0;
4018  dblParam_[CbcCutoffIncrement] = 1e-5;
4019  dblParam_[CbcAllowableGap] = 1.0e-10;
4020  dblParam_[CbcAllowableFractionGap] = 0.0;
4021  dblParam_[CbcMaximumSeconds] = 1.0e100;
4022  dblParam_[CbcCurrentCutoff] = 1.0e100;
4023  dblParam_[CbcOptimizationDirection] = 1.0;
4024  dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
4025  dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
4026  dblParam_[CbcStartSeconds] = 0.0;
4027  strongInfo_[0]=0;
4028  strongInfo_[1]=0;
4029  strongInfo_[2]=0;
4030  strongInfo_[3]=0;
4031  strongInfo_[4]=0;
4032  strongInfo_[5]=0;
4033  strongInfo_[6]=0;
4034  solverCharacteristics_ = NULL;
4035  nodeCompare_=new CbcCompareDefault();;
4036  problemFeasibility_=new CbcFeasibilityBase();
4037  tree_= new CbcTree();
4038  branchingMethod_=NULL;
4039  cutModifier_=NULL;
4040  strategy_=NULL;
4041  parentModel_=NULL;
4042  cbcColLower_ = NULL;
4043  cbcColUpper_ = NULL;
4044  cbcRowLower_ = NULL;
4045  cbcRowUpper_ = NULL;
4046  cbcColSolution_ = NULL;
4047  cbcRowPrice_ = NULL;
4048  cbcReducedCost_ = NULL;
4049  cbcRowActivity_ = NULL;
4050  appData_=NULL;
4051  handler_ = new CoinMessageHandler();
4052  handler_->setLogLevel(2);
4053  messages_ = CbcMessage();
4054  eventHandler_ = new CbcEventHandler() ;
4055}
4056
4057/** Constructor from solver.
4058
4059  Creates a model complete with a clone of the solver passed as a parameter.
4060*/
4061
4062CbcModel::CbcModel(const OsiSolverInterface &rhs)
4063:
4064  continuousSolver_(NULL),
4065  referenceSolver_(NULL),
4066  defaultHandler_(true),
4067  emptyWarmStart_(NULL),
4068  bestObjective_(COIN_DBL_MAX),
4069  bestPossibleObjective_(COIN_DBL_MAX),
4070  sumChangeObjective1_(0.0),
4071  sumChangeObjective2_(0.0),
4072  minimumDrop_(1.0e-4),
4073  numberSolutions_(0),
4074  stateOfSearch_(0),
4075  whenCuts_(-1),
4076  hotstartSolution_(NULL),
4077  hotstartPriorities_(NULL),
4078  numberHeuristicSolutions_(0),
4079  numberNodes_(0),
4080  numberNodes2_(0),
4081  numberIterations_(0),
4082  status_(-1),
4083  secondaryStatus_(-1),
4084  numberRowsAtContinuous_(0),
4085  maximumNumberCuts_(0),
4086  phase_(0),
4087  currentNumberCuts_(0),
4088  maximumDepth_(0),
4089  walkback_(NULL),
4090#ifdef NODE_LAST
4091  lastNodeInfo_(NULL),
4092  lastCut_(NULL),
4093  lastDepth_(0),
4094  lastNumberCuts2_(0),
4095  maximumCuts_(0),
4096  lastNumberCuts_(NULL),
4097#endif
4098  addedCuts_(NULL),
4099  nextRowCut_(NULL),
4100  currentNode_(NULL),
4101  integerInfo_(NULL),
4102  specialOptions_(0),
4103  subTreeModel_(NULL),
4104  numberStoppedSubTrees_(0),
4105  mutex_(NULL),
4106  presolve_(0),
4107  numberStrong_(5),
4108  numberBeforeTrust_(10),
4109  numberPenalties_(20),
4110  stopNumberIterations_(-1),
4111  penaltyScaleFactor_(3.0),
4112  numberAnalyzeIterations_(0),
4113  analyzeResults_(NULL),
4114  numberInfeasibleNodes_(0),
4115  problemType_(0),
4116  printFrequency_(0),
4117  numberCutGenerators_(0),
4118  generator_(NULL),
4119  virginGenerator_(NULL),
4120  numberHeuristics_(0),
4121  heuristic_(NULL),
4122  lastHeuristic_(NULL),
4123# ifdef COIN_HAS_CLP
4124  fastNodeDepth_(-1),
4125#endif
4126  eventHandler_(NULL),
4127  numberObjects_(0),
4128  object_(NULL),
4129  ownObjects_(true),
4130  originalColumns_(NULL),
4131  howOftenGlobalScan_(1),
4132  numberGlobalViolations_(0),
4133  numberExtraIterations_(0),
4134  numberExtraNodes_(0),
4135  continuousObjective_(COIN_DBL_MAX),
4136  originalContinuousObjective_(COIN_DBL_MAX),
4137  continuousInfeasibilities_(COIN_INT_MAX),
4138  maximumCutPassesAtRoot_(20),
4139  maximumCutPasses_(10),
4140  preferredWay_(0),
4141  currentPassNumber_(0),
4142  maximumWhich_(1000),
4143  maximumRows_(0),
4144  currentDepth_(0),
4145  whichGenerator_(NULL),
4146  maximumStatistics_(0),
4147  statistics_(NULL),
4148  maximumDepthActual_(0),
4149  numberDJFixed_(0.0),
4150  probingInfo_(NULL),
4151  numberFixedAtRoot_(0),
4152  numberFixedNow_(0),
4153  stoppedOnGap_(false),
4154  eventHappened_(false),
4155  numberLongStrong_(0),
4156  numberOldActiveCuts_(0),
4157  numberNewCuts_(0),
4158  sizeMiniTree_(0),
4159  searchStrategy_(-1),
4160  numberStrongIterations_(0),
4161  resolveAfterTakeOffCuts_(true),
4162  maximumNumberIterations_(-1),
4163#if NEW_UPDATE_OBJECT>1
4164  numberUpdateItems_(0),
4165  maximumNumberUpdateItems_(0),
4166  updateItems_(NULL),
4167#endif
4168  numberThreads_(0),
4169  threadMode_(0)
4170{
4171  memset(intParam_,0,sizeof(intParam_));
4172  intParam_[CbcMaxNumNode] = 2147483647;
4173  intParam_[CbcMaxNumSol] = 9999999;
4174  intParam_[CbcFathomDiscipline] = 0;
4175
4176  dblParam_[CbcIntegerTolerance] = 1e-6;
4177  dblParam_[CbcInfeasibilityWeight] = 0.0;
4178  dblParam_[CbcCutoffIncrement] = 1e-5;
4179  dblParam_[CbcAllowableGap] = 1.0e-10;
4180  dblParam_[CbcAllowableFractionGap] = 0.0;
4181  dblParam_[CbcMaximumSeconds] = 1.0e100;
4182  dblParam_[CbcCurrentCutoff] = 1.0e100;
4183  dblParam_[CbcOptimizationDirection] = 1.0;
4184  dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
4185  dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
4186  dblParam_[CbcStartSeconds] = 0.0;
4187  strongInfo_[0]=0;
4188  strongInfo_[1]=0;
4189  strongInfo_[2]=0;
4190  strongInfo_[3]=0;
4191  strongInfo_[4]=0;
4192  strongInfo_[5]=0;
4193  strongInfo_[6]=0;
4194  solverCharacteristics_ = NULL;
4195
4196  nodeCompare_=new CbcCompareDefault();;
4197  problemFeasibility_=new CbcFeasibilityBase();
4198  tree_= new CbcTree();
4199  branchingMethod_=NULL;
4200  cutModifier_=NULL;
4201  strategy_=NULL;
4202  parentModel_=NULL;
4203  appData_=NULL;
4204  handler_ = new CoinMessageHandler();
4205  handler_->setLogLevel(2);
4206  messages_ = CbcMessage();
4207  eventHandler_ = new CbcEventHandler() ;
4208  solver_ = rhs.clone();
4209  referenceSolver_ = solver_->clone();
4210  ownership_ = 0x80000000;
4211  cbcColLower_ = NULL;
4212  cbcColUpper_ = NULL;
4213  cbcRowLower_ = NULL;
4214  cbcRowUpper_ = NULL;
4215  cbcColSolution_ = NULL;
4216  cbcRowPrice_ = NULL;
4217  cbcReducedCost_ = NULL;
4218  cbcRowActivity_ = NULL;
4219
4220  // Initialize solution and integer variable vectors
4221  bestSolution_ = NULL; // to say no solution found
4222  numberIntegers_=0;
4223  int numberColumns = solver_->getNumCols();
4224  int iColumn;
4225  if (numberColumns) {
4226    // Space for current solution
4227    currentSolution_ = new double[numberColumns];
4228    continuousSolution_ = new double[numberColumns];
4229    usedInSolution_ = new int[numberColumns];
4230    CoinZeroN(usedInSolution_,numberColumns);
4231    for (iColumn=0;iColumn<numberColumns;iColumn++) {
4232      if( solver_->isInteger(iColumn)) 
4233        numberIntegers_++;
4234    }
4235  } else {
4236    // empty model
4237    currentSolution_=NULL;
4238    continuousSolution_=NULL;
4239    usedInSolution_=NULL;
4240  }
4241  testSolution_=currentSolution_;
4242  if (numberIntegers_) {
4243    integerVariable_ = new int [numberIntegers_];
4244    numberIntegers_=0;
4245    for (iColumn=0;iColumn<numberColumns;iColumn++) {
4246      if( solver_->isInteger(iColumn)) 
4247        integerVariable_[numberIntegers_++]=iColumn;
4248    }
4249  } else {
4250    integerVariable_ = NULL;
4251  }
4252}
4253
4254/*
4255  Assign a solver to the model (model assumes ownership)
4256
4257  The integer variable vector is initialized if it's not already present.
4258  If deleteSolver then current solver deleted (if model owned)
4259
4260  Assuming ownership matches usage in OsiSolverInterface
4261  (cf. assignProblem, loadProblem).
4262
4263  TODO: What to do about solver parameters? A simple copy likely won't do it,
4264        because the SI must push the settings into the underlying solver. In
4265        the context of switching solvers in cbc, this means that command line
4266        settings will get lost. Stash the command line somewhere and reread it
4267        here, maybe?
4268 
4269  TODO: More generally, how much state should be transferred from the old
4270        solver to the new solver? Best perhaps to see how usage develops.
4271        What's done here mimics the CbcModel(OsiSolverInterface) constructor.
4272*/
4273void
4274CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver)
4275
4276{
4277  // resize best solution if exists
4278  if (bestSolution_&&solver&&solver_) {
4279    int nOld = solver_->getNumCols();
4280    int nNew = solver->getNumCols();
4281    if (nNew>nOld) {
4282      double * temp = new double[nNew];
4283      memcpy(temp,bestSolution_,nOld*sizeof(double));
4284      memset(temp+nOld,0,(nNew-nOld)*sizeof(double));
4285      delete [] bestSolution_;
4286      bestSolution_=temp;
4287    }
4288  }
4289  // Keep the current message level for solver (if solver exists)
4290  if (solver_)
4291    solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel()) ;
4292
4293  if (modelOwnsSolver()&&deleteSolver) delete solver_ ;
4294  solver_ = solver;
4295  solver = NULL ;
4296  setModelOwnsSolver(true) ;
4297/*
4298  Basis information is solver-specific.
4299*/
4300  if (emptyWarmStart_)
4301  { delete emptyWarmStart_  ;
4302    emptyWarmStart_ = 0 ; }
4303  bestSolutionBasis_ = CoinWarmStartBasis();
4304/*
4305  Initialize integer variable vector.
4306*/
4307  numberIntegers_=0;
4308  int numberColumns = solver_->getNumCols();
4309  int iColumn;
4310  for (iColumn=0;iColumn<numberColumns;iColumn++) {
4311    if( solver_->isInteger(iColumn)) 
4312      numberIntegers_++;
4313  }
4314  delete [] integerVariable_;
4315  if (numberIntegers_) {
4316    integerVariable_ = new int [numberIntegers_];
4317    numberIntegers_=0;
4318    for (iColumn=0;iColumn<numberColumns;iColumn++) {
4319      if( solver_->isInteger(iColumn)) 
4320        integerVariable_[numberIntegers_++]=iColumn;
4321    }
4322  } else {
4323    integerVariable_ = NULL;
4324  }
4325
4326  return ;
4327}
4328
4329// Copy constructor.
4330
4331CbcModel::CbcModel(const CbcModel & rhs, bool cloneHandler)
4332:
4333  continuousSolver_(NULL),
4334  referenceSolver_(NULL),
4335  defaultHandler_(rhs.defaultHandler_),
4336  emptyWarmStart_(NULL),
4337  bestObjective_(rhs.bestObjective_),
4338  bestPossibleObjective_(rhs.bestPossibleObjective_),
4339  sumChangeObjective1_(rhs.sumChangeObjective1_),
4340  sumChangeObjective2_(rhs.sumChangeObjective2_),
4341  minimumDrop_(rhs.minimumDrop_),
4342  numberSolutions_(rhs.numberSolutions_),
4343  stateOfSearch_(rhs.stateOfSearch_),
4344  whenCuts_(rhs.whenCuts_),
4345  numberHeuristicSolutions_(rhs.numberHeuristicSolutions_),
4346  numberNodes_(rhs.numberNodes_),
4347  numberNodes2_(rhs.numberNodes2_),
4348  numberIterations_(rhs.numberIterations_),
4349  status_(rhs.status_),
4350  secondaryStatus_(rhs.secondaryStatus_),
4351  specialOptions_(rhs.specialOptions_),
4352  subTreeModel_(rhs.subTreeModel_),
4353  numberStoppedSubTrees_(rhs.numberStoppedSubTrees_),
4354  mutex_(NULL),
4355  presolve_(rhs.presolve_),
4356  numberStrong_(rhs.numberStrong_),
4357  numberBeforeTrust_(rhs.numberBeforeTrust_),
4358  numberPenalties_(rhs.numberPenalties_),
4359  stopNumberIterations_(rhs.stopNumberIterations_),
4360  penaltyScaleFactor_(rhs.penaltyScaleFactor_),
4361  numberAnalyzeIterations_(rhs.numberAnalyzeIterations_),
4362  analyzeResults_(NULL),
4363  numberInfeasibleNodes_(rhs.numberInfeasibleNodes_),
4364  problemType_(rhs.problemType_),
4365  printFrequency_(rhs.printFrequency_),
4366# ifdef COIN_HAS_CLP
4367  fastNodeDepth_(rhs.fastNodeDepth_),
4368#endif
4369  howOftenGlobalScan_(rhs.howOftenGlobalScan_),
4370  numberGlobalViolations_(rhs.numberGlobalViolations_),
4371  numberExtraIterations_(rhs.numberExtraIterations_),
4372  numberExtraNodes_(rhs.numberExtraNodes_),
4373  continuousObjective_(rhs.continuousObjective_),
4374  originalContinuousObjective_(rhs.originalContinuousObjective_),
4375  continuousInfeasibilities_(rhs.continuousInfeasibilities_),
4376  maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_),
4377  maximumCutPasses_( rhs.maximumCutPasses_),
4378  preferredWay_(rhs.preferredWay_),
4379  currentPassNumber_(rhs.currentPassNumber_),
4380  maximumWhich_(rhs.maximumWhich_),
4381  maximumRows_(0),
4382  currentDepth_(0),
4383  whichGenerator_(NULL),
4384  maximumStatistics_(0),
4385  statistics_(NULL),
4386  maximumDepthActual_(0),
4387  numberDJFixed_(0.0),
4388  probingInfo_(NULL),
4389  numberFixedAtRoot_(rhs.numberFixedAtRoot_),
4390  numberFixedNow_(rhs.numberFixedNow_),
4391  stoppedOnGap_(rhs.stoppedOnGap_),
4392  eventHappened_(rhs.eventHappened_),
4393  numberLongStrong_(rhs.numberLongStrong_),
4394  numberOldActiveCuts_(rhs.numberOldActiveCuts_),
4395  numberNewCuts_(rhs.numberNewCuts_),
4396  sizeMiniTree_(rhs.sizeMiniTree_),
4397  searchStrategy_(rhs.searchStrategy_),
4398  numberStrongIterations_(rhs.numberStrongIterations_),
4399  resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_),
4400  maximumNumberIterations_(rhs.maximumNumberIterations_),
4401#if NEW_UPDATE_OBJECT>1
4402  numberUpdateItems_(rhs.numberUpdateItems_),
4403  maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_),
4404  updateItems_(NULL),
4405#endif
4406  numberThreads_(rhs.numberThreads_),
4407  threadMode_(rhs.threadMode_)
4408{
4409  memcpy(intParam_,rhs.intParam_,sizeof(intParam_));
4410  memcpy(dblParam_,rhs.dblParam_,sizeof(dblParam_));
4411  strongInfo_[0]=rhs.strongInfo_[0];
4412  strongInfo_[1]=rhs.strongInfo_[1];
4413  strongInfo_[2]=rhs.strongInfo_[2];
4414  strongInfo_[3]=rhs.strongInfo_[3];
4415  strongInfo_[4]=rhs.strongInfo_[4];
4416  strongInfo_[5]=rhs.strongInfo_[5];
4417  strongInfo_[6]=rhs.strongInfo_[6];
4418  solverCharacteristics_ = NULL;
4419  if (rhs.emptyWarmStart_) emptyWarmStart_ = rhs.emptyWarmStart_->clone() ;
4420  if (defaultHandler_||cloneHandler) {
4421    handler_ = new CoinMessageHandler();
4422    handler_->setLogLevel(2);
4423  } else {
4424    handler_ = rhs.handler_;
4425  }
4426  messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
4427  numberCutGenerators_ = rhs.numberCutGenerators_;
4428  if (numberCutGenerators_) {
4429    generator_ = new CbcCutGenerator * [numberCutGenerators_];
4430    virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
4431    int i;
4432    for (i=0;i<numberCutGenerators_;i++) {
4433      generator_[i]=new CbcCutGenerator(*rhs.generator_[i]);
4434      virginGenerator_[i]=new CbcCutGenerator(*rhs.virginGenerator_[i]);
4435    }
4436  } else {
4437    generator_=NULL;
4438    virginGenerator_=NULL;
4439  }
4440  globalCuts_ = rhs.globalCuts_;
4441  numberHeuristics_ = rhs.numberHeuristics_;
4442  if (numberHeuristics_) {
4443    heuristic_ = new CbcHeuristic * [numberHeuristics_];
4444    int i;
4445    for (i=0;i<numberHeuristics_;i++) {
4446      heuristic_[i]=rhs.heuristic_[i]->clone();
4447    }
4448  } else {
4449    heuristic_=NULL;
4450  }
4451  lastHeuristic_ = NULL;
4452  if (rhs.eventHandler_)
4453    { eventHandler_ = rhs.eventHandler_->clone() ; }
4454  else
4455  { eventHandler_ = NULL ; }
4456  ownObjects_ = rhs.ownObjects_;
4457  if (ownObjects_) {
4458    numberObjects_=rhs.numberObjects_;
4459    if (numberObjects_) {
4460      object_ = new OsiObject * [numberObjects_];
4461      int i;
4462      for (i=0;i<numberObjects_;i++) {
4463        object_[i]=(rhs.object_[i])->clone();
4464        CbcObject * obj = dynamic_cast <CbcObject *>(object_[i]) ;
4465        // Could be OsiObjects
4466        if (obj)
4467          obj->setModel(this);
4468      }
4469    } else {
4470      object_=NULL;
4471    }
4472  } else {
4473    // assume will be redone
4474    numberObjects_=0;
4475    object_=NULL;
4476  }
4477  if (rhs.referenceSolver_)
4478    referenceSolver_ = rhs.referenceSolver_->clone();
4479  else
4480    referenceSolver_=NULL;
4481  solver_ = rhs.solver_->clone();
4482  if (rhs.originalColumns_) {
4483    int numberColumns = solver_->getNumCols();
4484    originalColumns_= new int [numberColumns];
4485    memcpy(originalColumns_,rhs.originalColumns_,numberColumns*sizeof(int));
4486  } else {
4487    originalColumns_=NULL;
4488  }
4489#if NEW_UPDATE_OBJECT>1
4490  if (maximumNumberUpdateItems_) {
4491    updateItems_ = new CbcObjectUpdateData [maximumNumberUpdateItems_];
4492    for (int i=0;i<maximumNumberUpdateItems_;i++)
4493      updateItems_[i] = rhs.updateItems_[i];
4494  }
4495#endif
4496  if (maximumWhich_&&rhs.whichGenerator_)
4497    whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_,maximumWhich_);
4498  nodeCompare_=rhs.nodeCompare_->clone();
4499  problemFeasibility_=rhs.problemFeasibility_->clone();
4500  tree_= rhs.tree_->clone();
4501  if (rhs.branchingMethod_)
4502    branchingMethod_=rhs.branchingMethod_->clone();
4503  else
4504    branchingMethod_=NULL;
4505  if (rhs.cutModifier_)
4506    cutModifier_=rhs.cutModifier_->clone();
4507  else
4508    cutModifier_=NULL;
4509  cbcColLower_ = NULL;
4510  cbcColUpper_ = NULL;
4511  cbcRowLower_ = NULL;
4512  cbcRowUpper_ = NULL;
4513  cbcColSolution_ = NULL;
4514  cbcRowPrice_ = NULL;
4515  cbcReducedCost_ = NULL;
4516  cbcRowActivity_ = NULL;
4517  if (rhs.strategy_)
4518    strategy_=rhs.strategy_->clone();
4519  else
4520    strategy_=NULL;
4521  parentModel_=rhs.parentModel_;
4522  appData_=rhs.appData_;
4523  messages_ = rhs.messages_;
4524  ownership_ = 0x80000000;
4525  messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
4526  numberIntegers_=rhs.numberIntegers_;
4527  randomNumberGenerator_ = rhs.randomNumberGenerator_;
4528  if (numberIntegers_) {
4529    integerVariable_ = new int [numberIntegers_];
4530    memcpy(integerVariable_,rhs.integerVariable_,numberIntegers_*sizeof(int));
4531    integerInfo_ = CoinCopyOfArray(rhs.integerInfo_,solver_->getNumCols());
4532  } else {
4533    integerVariable_ = NULL;
4534    integerInfo_=NULL;
4535  }
4536  if (rhs.hotstartSolution_) {
4537    int numberColumns = solver_->getNumCols();
4538    hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_,numberColumns);
4539    hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_,numberColumns);
4540  } else {
4541    hotstartSolution_ = NULL;
4542    hotstartPriorities_ =NULL;
4543  }
4544  if (rhs.bestSolution_) {
4545    int numberColumns = solver_->getNumCols();
4546    bestSolution_ = new double[numberColumns];
4547    memcpy(bestSolution_,rhs.bestSolution_,numberColumns*sizeof(double));
4548  } else {
4549    bestSolution_=NULL;
4550  }
4551  int numberColumns = solver_->getNumCols();
4552  // Space for current solution
4553  currentSolution_ = new double[numberColumns];
4554  continuousSolution_ = new double[numberColumns];
4555  usedInSolution_ = new int[numberColumns];
4556  CoinZeroN(usedInSolution_,numberColumns);
4557  testSolution_=currentSolution_;
4558  numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
4559  maximumNumberCuts_=rhs.maximumNumberCuts_;
4560  phase_ = rhs.phase_;
4561  currentNumberCuts_=rhs.currentNumberCuts_;
4562  maximumDepth_= rhs.maximumDepth_;
4563  // These are only used as temporary arrays so need not be filled
4564  if (maximumNumberCuts_) {
4565    addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
4566  } else {
4567    addedCuts_ = NULL;
4568  }
4569  bestSolutionBasis_ = rhs.bestSolutionBasis_;
4570  nextRowCut_ = NULL;
4571  currentNode_ = NULL;
4572  if (maximumDepth_) {
4573    walkback_ = new CbcNodeInfo * [maximumDepth_];
4574#ifdef NODE_LAST
4575    lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
4576    lastNumberCuts_ = new int [maximumDepth_] ;
4577#endif
4578  } else {
4579    walkback_ = NULL;
4580#ifdef NODE_LAST
4581    lastNodeInfo_ = NULL;
4582    lastNumberCuts_ = NULL;
4583#endif
4584  }
4585#ifdef NODE_LAST
4586  maximumCuts_ = rhs.maximumCuts_;
4587  if (maximumCuts_) {
4588    lastCut_ = new const OsiRowCut * [maximumCuts_] ;
4589  } else {
4590    lastCut_ = NULL;
4591  }
4592#endif
4593  synchronizeModel();
4594  if (cloneHandler&&!defaultHandler_) {
4595    delete handler_;
4596    CoinMessageHandler * handler = rhs.handler_->clone();
4597    passInMessageHandler(handler);
4598  }
4599}
4600 
4601// Assignment operator
4602CbcModel & 
4603CbcModel::operator=(const CbcModel& rhs)
4604{
4605  if (this!=&rhs) {
4606    if (modelOwnsSolver()) {
4607      delete solver_;
4608      solver_=NULL;
4609    }
4610    gutsOfDestructor();
4611    if (defaultHandler_)
4612    { delete handler_;
4613      handler_ = NULL; }
4614    defaultHandler_ = rhs.defaultHandler_;
4615    if (defaultHandler_)
4616    { handler_ = new CoinMessageHandler();
4617      handler_->setLogLevel(2); }
4618    else
4619    { handler_ = rhs.handler_; }
4620    messages_ = rhs.messages_;
4621    messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
4622    if (rhs.solver_)
4623    { solver_ = rhs.solver_->clone() ; }
4624    else
4625    { solver_ = 0 ; }
4626    ownership_ = 0x80000000;
4627    delete continuousSolver_ ;
4628    if (rhs.continuousSolver_)
4629    { continuousSolver_ = rhs.continuousSolver_->clone() ; }
4630    else
4631    { continuousSolver_ = 0 ; }
4632    delete referenceSolver_;
4633    if (rhs.referenceSolver_)
4634    { referenceSolver_ = rhs.referenceSolver_->clone() ; }
4635    else
4636    { referenceSolver_ = NULL ; }
4637
4638    delete emptyWarmStart_ ;
4639    if (rhs.emptyWarmStart_)
4640    { emptyWarmStart_ = rhs.emptyWarmStart_->clone() ; }
4641    else
4642    { emptyWarmStart_ = 0 ; }
4643
4644    bestObjective_ = rhs.bestObjective_;
4645    bestPossibleObjective_=rhs.bestPossibleObjective_;
4646    sumChangeObjective1_=rhs.sumChangeObjective1_;
4647    sumChangeObjective2_=rhs.sumChangeObjective2_;
4648    delete [] bestSolution_;
4649    if (rhs.bestSolution_) {
4650      int numberColumns = rhs.getNumCols();
4651      bestSolution_ = new double[numberColumns];
4652      memcpy(bestSolution_,rhs.bestSolution_,numberColumns*sizeof(double));
4653    } else {
4654      bestSolution_=NULL;
4655    }
4656    int numberColumns = rhs.getNumCols();
4657    if (numberColumns) {
4658      // Space for current solution
4659      currentSolution_ = new double[numberColumns];
4660      continuousSolution_ = new double[numberColumns];
4661      usedInSolution_ = new int[numberColumns];
4662      CoinZeroN(usedInSolution_,numberColumns);
4663    } else {
4664      currentSolution_=NULL;
4665      continuousSolution_=NULL;
4666      usedInSolution_=NULL;
4667    }
4668    testSolution_=currentSolution_;
4669    minimumDrop_ = rhs.minimumDrop_;
4670    numberSolutions_=rhs.numberSolutions_;
4671    stateOfSearch_= rhs.stateOfSearch_;
4672    whenCuts_ = rhs.whenCuts_;
4673    numberHeuristicSolutions_=rhs.numberHeuristicSolutions_;
4674    numberNodes_ = rhs.numberNodes_;
4675    numberNodes2_ = rhs.numberNodes2_;
4676    numberIterations_ = rhs.numberIterations_;
4677    status_ = rhs.status_;
4678    secondaryStatus_ = rhs.secondaryStatus_;
4679    specialOptions_ = rhs.specialOptions_;
4680    subTreeModel_ = rhs.subTreeModel_;
4681    numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
4682    mutex_ = NULL;
4683    presolve_ = rhs.presolve_;
4684    numberStrong_ = rhs.numberStrong_;
4685    numberBeforeTrust_ = rhs.numberBeforeTrust_;
4686    numberPenalties_ = rhs.numberPenalties_;
4687    stopNumberIterations_ = rhs.stopNumberIterations_;
4688    penaltyScaleFactor_ = rhs.penaltyScaleFactor_;
4689    numberAnalyzeIterations_ = rhs.numberAnalyzeIterations_;
4690    delete [] analyzeResults_;
4691    analyzeResults_ = NULL;
4692    numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_;
4693    problemType_ = rhs.problemType_;
4694    printFrequency_ = rhs.printFrequency_;
4695    howOftenGlobalScan_=rhs.howOftenGlobalScan_;
4696    numberGlobalViolations_=rhs.numberGlobalViolations_;
4697    numberExtraIterations_ = rhs.numberExtraIterations_;
4698    numberExtraNodes_ = rhs.numberExtraNodes_;
4699    continuousObjective_=rhs.continuousObjective_;
4700    originalContinuousObjective_ = rhs.originalContinuousObjective_;
4701    continuousInfeasibilities_ = rhs.continuousInfeasibilities_;
4702    maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_;
4703    maximumCutPasses_ = rhs.maximumCutPasses_;
4704    preferredWay_ = rhs.preferredWay_;
4705    currentPassNumber_ = rhs.currentPassNumber_;
4706    memcpy(intParam_,rhs.intParam_,sizeof(intParam_));
4707    memcpy(dblParam_,rhs.dblParam_,sizeof(dblParam_));
4708    globalCuts_ = rhs.globalCuts_;
4709    int i;
4710    for (i=0;i<numberCutGenerators_;i++) {
4711      delete generator_[i];
4712      delete virginGenerator_[i];
4713    }
4714    delete [] generator_;
4715    delete [] virginGenerator_;
4716    delete [] heuristic_;
4717    maximumWhich_ = rhs.maximumWhich_;
4718    delete [] whichGenerator_;
4719    whichGenerator_ = NULL;
4720    if (maximumWhich_&&rhs.whichGenerator_)
4721      whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_,maximumWhich_);
4722    maximumRows_=0;
4723    currentDepth_ = 0;
4724    randomNumberGenerator_ = rhs.randomNumberGenerator_;
4725    workingBasis_ = CoinWarmStartBasis();
4726    for (i=0;i<maximumStatistics_;i++)
4727      delete statistics_[i];
4728    delete [] statistics_;
4729    maximumStatistics_ = 0;
4730    statistics_ = NULL;
4731    delete probingInfo_;
4732    probingInfo_=NULL;
4733    numberFixedAtRoot_ = rhs.numberFixedAtRoot_;
4734    numberFixedNow_ = rhs.numberFixedNow_;
4735    stoppedOnGap_ = rhs.stoppedOnGap_;
4736    eventHappened_ = rhs.eventHappened_;
4737    numberLongStrong_ = rhs.numberLongStrong_;
4738    numberOldActiveCuts_ = rhs.numberOldActiveCuts_;
4739    numberNewCuts_ = rhs.numberNewCuts_;
4740    resolveAfterTakeOffCuts_=rhs.resolveAfterTakeOffCuts_;
4741    maximumNumberIterations_ = rhs.maximumNumberIterations_;
4742#if NEW_UPDATE_OBJECT>1
4743    numberUpdateItems_ = rhs.numberUpdateItems_;
4744    maximumNumberUpdateItems_ = rhs.maximumNumberUpdateItems_;
4745    delete [] updateItems_;
4746    if (maximumNumberUpdateItems_) {
4747      updateItems_ = new CbcObjectUpdateData [maximumNumberUpdateItems_];
4748      for (i=0;i<maximumNumberUpdateItems_;i++)
4749        updateItems_[i] = rhs.updateItems_[i];
4750    } else {
4751      updateItems_ = NULL;
4752    }
4753#endif
4754    numberThreads_ = rhs.numberThreads_;
4755    threadMode_ = rhs.threadMode_;
4756    sizeMiniTree_ = rhs.sizeMiniTree_;
4757    searchStrategy_ = rhs.searchStrategy_;
4758    numberStrongIterations_ = rhs.numberStrongIterations_;
4759    strongInfo_[0]=rhs.strongInfo_[0];
4760    strongInfo_[1]=rhs.strongInfo_[1];
4761    strongInfo_[2]=rhs.strongInfo_[2];
4762    strongInfo_[3]=rhs.strongInfo_[3];
4763    strongInfo_[4]=rhs.strongInfo_[4];
4764    strongInfo_[5]=rhs.strongInfo_[5];
4765    strongInfo_[6]=rhs.strongInfo_[6];
4766    solverCharacteristics_ = NULL;
4767    lastHeuristic_ = NULL;
4768    numberCutGenerators_ = rhs.numberCutGenerators_;
4769    if (numberCutGenerators_) {
4770      generator_ = new CbcCutGenerator * [numberCutGenerators_];
4771      virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
4772      int i;
4773      for (i=0;i<numberCutGenerators_;i++) {
4774        generator_[i]=new CbcCutGenerator(*rhs.generator_[i]);
4775        virginGenerator_[i]=new CbcCutGenerator(*rhs.virginGenerator_[i]);
4776      }
4777    } else {
4778      generator_=NULL;
4779      virginGenerator_=NULL;
4780    }
4781    numberHeuristics_ = rhs.numberHeuristics_;
4782    if (numberHeuristics_) {
4783      heuristic_ = new CbcHeuristic * [numberHeuristics_];
4784      memcpy(heuristic_,rhs.heuristic_,
4785             numberHeuristics_*sizeof(CbcHeuristic *));
4786    } else {
4787      heuristic_=NULL;
4788    }
4789    lastHeuristic_ = NULL;
4790    if (eventHandler_)
4791      delete eventHandler_ ;
4792    if (rhs.eventHandler_)
4793      { eventHandler_ = rhs.eventHandler_->clone() ; }
4794    else
4795    { eventHandler_ = NULL ; }
4796# ifdef COIN_HAS_CLP
4797    fastNodeDepth_ = rhs.fastNodeDepth_;
4798#endif
4799    if (ownObjects_) {
4800      for (i=0;i<numberObjects_;i++)
4801        delete object_[i];
4802      delete [] object_;
4803      numberObjects_=rhs.numberObjects_;
4804      if (numberObjects_) {
4805        object_ = new OsiObject * [numberObjects_];
4806        int i;
4807        for (i=0;i<numberObjects_;i++) 
4808          object_[i]=(rhs.object_[i])->clone();
4809      } else {
4810        object_=NULL;
4811    }
4812    } else {
4813      // assume will be redone
4814      numberObjects_=0;
4815      object_=NULL;
4816    }
4817    delete [] originalColumns_;
4818    if (rhs.originalColumns_) {
4819      int numberColumns = rhs.getNumCols();
4820      originalColumns_= new int [numberColumns];
4821      memcpy(originalColumns_,rhs.originalColumns_,numberColumns*sizeof(int));
4822    } else {
4823      originalColumns_=NULL;
4824    }
4825    nodeCompare_=rhs.nodeCompare_->clone();
4826    problemFeasibility_=rhs.problemFeasibility_->clone();
4827    delete tree_;
4828    tree_= rhs.tree_->clone();
4829    if (rhs.branchingMethod_)
4830      branchingMethod_=rhs.branchingMethod_->clone();
4831    else
4832      branchingMethod_=NULL;
4833    if (rhs.cutModifier_)
4834      cutModifier_=rhs.cutModifier_->clone();
4835    else
4836      cutModifier_=NULL;
4837    delete strategy_;
4838    if (rhs.strategy_)
4839      strategy_=rhs.strategy_->clone();
4840    else
4841      strategy_=NULL;
4842    parentModel_=rhs.parentModel_;
4843    appData_=rhs.appData_;
4844
4845    delete [] integerVariable_;
4846    numberIntegers_=rhs.numberIntegers_;
4847    if (numberIntegers_) {
4848      integerVariable_ = new int [numberIntegers_];
4849      memcpy(integerVariable_,rhs.integerVariable_,
4850             numberIntegers_*sizeof(int));
4851      integerInfo_ = CoinCopyOfArray(rhs.integerInfo_,rhs.getNumCols());
4852    } else {
4853      integerVariable_ = NULL;
4854      integerInfo_=NULL;
4855    }
4856    if (rhs.hotstartSolution_) {
4857      int numberColumns = solver_->getNumCols();
4858      hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_,numberColumns);
4859      hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_,numberColumns);
4860    } else {
4861      hotstartSolution_ = NULL;
4862      hotstartPriorities_ =NULL;
4863    }
4864    numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
4865    maximumNumberCuts_=rhs.maximumNumberCuts_;
4866    phase_ = rhs.phase_;
4867    currentNumberCuts_=rhs.currentNumberCuts_;
4868    maximumDepth_= rhs.maximumDepth_;
4869    delete [] addedCuts_;
4870    delete [] walkback_;
4871    // These are only used as temporary arrays so need not be filled
4872    if (maximumNumberCuts_) {
4873      addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
4874    } else {
4875      addedCuts_ = NULL;
4876    }
4877#ifdef NODE_LAST
4878    delete [] lastNodeInfo_ ;
4879    delete [] lastNumberCuts_ ;
4880    delete [] lastCut_;
4881#endif
4882    bestSolutionBasis_ = rhs.bestSolutionBasis_;
4883    nextRowCut_ = NULL;
4884    currentNode_ = NULL;
4885    if (maximumDepth_) {
4886      walkback_ = new CbcNodeInfo * [maximumDepth_];
4887#ifdef NODE_LAST
4888      lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
4889      lastNumberCuts_ = new int [maximumDepth_] ;
4890#endif
4891    } else {
4892      walkback_ = NULL;
4893#ifdef NODE_LAST
4894      lastNodeInfo_ = NULL;
4895      lastNumberCuts_ = NULL;
4896#endif
4897    }
4898#ifdef NODE_LAST
4899    maximumCuts_ = rhs.maximumCuts_;
4900    if (maximumCuts_) {
4901      lastCut_ = new const OsiRowCut * [maximumCuts_] ;
4902    } else {
4903      lastCut_ = NULL;
4904    }
4905#endif
4906    synchronizeModel();
4907    cbcColLower_ = NULL;
4908    cbcColUpper_ = NULL;
4909    cbcRowLower_ = NULL;
4910    cbcRowUpper_ = NULL;
4911    cbcColSolution_ = NULL;
4912    cbcRowPrice_ = NULL;
4913    cbcReducedCost_ = NULL;
4914    cbcRowActivity_ = NULL;
4915  }
4916  return *this;
4917}
4918// Destructor
4919CbcModel::~CbcModel ()
4920{
4921  if (defaultHandler_) {
4922    delete handler_;
4923    handler_ = NULL;
4924  }
4925  delete tree_;
4926  tree_=NULL;
4927  if (modelOwnsSolver()) {
4928    delete solver_;
4929    solver_ = NULL;
4930  }
4931  gutsOfDestructor();
4932  delete eventHandler_ ;
4933  eventHandler_ = NULL ;
4934}
4935// Clears out as much as possible (except solver)
4936void 
4937CbcModel::gutsOfDestructor()
4938{
4939  delete referenceSolver_;
4940  referenceSolver_=NULL;
4941  int i;
4942  for (i=0;i<numberCutGenerators_;i++) {
4943    delete generator_[i];
4944    delete virginGenerator_[i];
4945  }
4946  delete [] generator_;
4947  delete [] virginGenerator_;
4948  generator_=NULL;
4949  virginGenerator_=NULL;
4950  for (i=0;i<numberHeuristics_;i++)
4951    delete heuristic_[i];
4952  delete [] heuristic_;
4953  heuristic_=NULL;
4954  delete nodeCompare_;
4955  nodeCompare_=NULL;
4956  delete problemFeasibility_;
4957  problemFeasibility_=NULL;
4958  delete [] originalColumns_;
4959  originalColumns_=NULL;
4960  delete strategy_;
4961#if NEW_UPDATE_OBJECT>1
4962  delete [] updateItems_;
4963  updateItems_=NULL;
4964  numberUpdateItems_=0;
4965  maximumNumberUpdateItems_=0;
4966#endif
4967  gutsOfDestructor2();
4968}
4969// Clears out enough to reset CbcModel
4970void 
4971CbcModel::gutsOfDestructor2()
4972{
4973  delete [] integerInfo_;
4974  integerInfo_=NULL;
4975  delete [] integerVariable_;
4976  integerVariable_=NULL;
4977  int i;
4978  if (ownObjects_) {
4979    for (i=0;i<numberObjects_;i++)
4980      delete object_[i];
4981    delete [] object_;
4982  }
4983  ownObjects_=true;
4984  object_=NULL;
4985  numberIntegers_=0;
4986  numberObjects_=0;
4987  // Below here is whatever consensus is
4988  ownership_ = 0x80000000;
4989  delete branchingMethod_;
4990  branchingMethod_=NULL;
4991  delete cutModifier_;
4992  cutModifier_=NULL;
4993  resetModel();
4994}
4995// Clears out enough to reset CbcModel
4996void 
4997CbcModel::resetModel()
4998{
4999  delete emptyWarmStart_ ;
5000  emptyWarmStart_ =NULL;
5001  delete continuousSolver_;
5002  continuousSolver_=NULL;
5003  delete [] bestSolution_;
5004  bestSolution_=NULL;
5005  delete [] currentSolution_;
5006  currentSolution_=NULL;
5007  delete [] continuousSolution_;
5008  continuousSolution_=NULL;
5009  solverCharacteristics_=NULL;
5010  delete [] usedInSolution_;
5011  usedInSolution_ = NULL;
5012  testSolution_=NULL;
5013  lastHeuristic_ = NULL;
5014  delete [] addedCuts_;
5015  addedCuts_=NULL;
5016  nextRowCut_ = NULL;
5017  currentNode_ = NULL;
5018  delete [] walkback_;
5019  walkback_=NULL;
5020#ifdef NODE_LAST
5021  delete [] lastNodeInfo_ ;
5022  lastNodeInfo_ = NULL;
5023  delete [] lastNumberCuts_ ;
5024  lastNumberCuts_ = NULL;
5025  delete [] lastCut_;
5026  lastCut_ = NULL;
5027#endif
5028  delete [] whichGenerator_;
5029  whichGenerator_ = NULL;
5030  for (int i=0;i<maximumStatistics_;i++)
5031    delete statistics_[i];
5032  delete [] statistics_;
5033  statistics_=NULL;
5034  maximumDepthActual_ = 0;
5035  numberDJFixed_ =0.0;
5036  delete probingInfo_;
5037  probingInfo_ = NULL;
5038  maximumStatistics_=0;
5039  delete [] analyzeResults_;
5040  analyzeResults_=NULL;
5041  bestObjective_=COIN_DBL_MAX;
5042  bestPossibleObjective_=COIN_DBL_MAX;
5043  sumChangeObjective1_=0.0;
5044  sumChangeObjective2_=0.0;
5045  numberSolutions_=0;
5046  stateOfSearch_=0;
5047  delete [] hotstartSolution_;
5048  hotstartSolution_=NULL;
5049  delete [] hotstartPriorities_;
5050  hotstartPriorities_=NULL;
5051  numberHeuristicSolutions_=0;
5052  numberNodes_=0;
5053  numberNodes2_=0;
5054  numberIterations_=0;
5055  status_=-1;
5056  secondaryStatus_=-1;
5057  maximumNumberCuts_=0;
5058  phase_=0;
5059  currentNumberCuts_=0;
5060  maximumDepth_=0;
5061  nextRowCut_=NULL;
5062  currentNode_=NULL;
5063  // clear out tree
5064  if (tree_&&tree_->size())
5065    tree_->cleanTree(this, -1.0e100,bestPossibleObjective_) ;
5066  subTreeModel_=NULL;
5067  numberStoppedSubTrees_=0;
5068  numberInfeasibleNodes_=0;
5069  numberGlobalViolations_=0;
5070  numberExtraIterations_ = 0;
5071  numberExtraNodes_ = 0;
5072  continuousObjective_=0.0;
5073  originalContinuousObjective_=0.0;
5074  continuousInfeasibilities_=0;
5075  numberFixedAtRoot_=0;
5076  numberFixedNow_=0;
5077  stoppedOnGap_=false;
5078  eventHappened_=false;
5079  numberLongStrong_=0;
5080  numberOldActiveCuts_=0;
5081  numberNewCuts_=0;
5082  searchStrategy_=-1;
5083  numberStrongIterations_=0;
5084  // Parameters which need to be reset
5085  setCutoff(COIN_DBL_MAX);
5086  dblParam_[CbcCutoffIncrement] = 1e-5;
5087  dblParam_[CbcCurrentCutoff] = 1.0e100;
5088  dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
5089  dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
5090}
5091/* Most of copy constructor
5092      mode - 0 copy but don't delete before
5093             1 copy and delete before
5094             2 copy and delete before (but use virgin generators)
5095*/
5096void 
5097CbcModel::gutsOfCopy(const CbcModel & rhs,int mode)
5098{
5099  minimumDrop_ = rhs.minimumDrop_;
5100  specialOptions_ = rhs.specialOptions_;
5101  numberStrong_ = rhs.numberStrong_;
5102  numberBeforeTrust_ = rhs.numberBeforeTrust_;
5103  numberPenalties_ = rhs.numberPenalties_;
5104  printFrequency_ = rhs.printFrequency_;
5105# ifdef COIN_HAS_CLP
5106  fastNodeDepth_ = rhs.fastNodeDepth_;
5107#endif
5108  howOftenGlobalScan_ = rhs.howOftenGlobalScan_;
5109  maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_;
5110  maximumCutPasses_ =  rhs.maximumCutPasses_;
5111  preferredWay_ = rhs.preferredWay_;
5112  resolveAfterTakeOffCuts_ = rhs.resolveAfterTakeOffCuts_;
5113  maximumNumberIterations_ = rhs.maximumNumberIterations_;
5114  numberThreads_ = rhs.numberThreads_;
5115  threadMode_ = rhs.threadMode_;
5116  memcpy(intParam_,rhs.intParam_,sizeof(intParam_));
5117  memcpy(dblParam_,rhs.dblParam_,sizeof(dblParam_));
5118  int i;
5119  if (mode) {
5120    for (i=0;i<numberCutGenerators_;i++) {
5121      delete generator_[i];
5122      delete virginGenerator_[i];
5123    }
5124    delete [] generator_;
5125    delete [] virginGenerator_;
5126    for (i=0;i<numberHeuristics_;i++) {
5127      delete heuristic_[i];
5128    }
5129    delete [] heuristic_;
5130    delete eventHandler_;
5131    delete branchingMethod_;
5132  }
5133  numberCutGenerators_ = rhs.numberCutGenerators_;
5134  if (numberCutGenerators_) {
5135    generator_ = new CbcCutGenerator * [numberCutGenerators_];
5136    virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
5137    int i;
5138    for (i=0;i<numberCutGenerators_;i++) {
5139      if (mode<2)
5140        generator_[i]=new CbcCutGenerator(*rhs.generator_[i]);
5141      else
5142        generator_[i]=new CbcCutGenerator(*rhs.virginGenerator_[i]);
5143      virginGenerator_[i]=new CbcCutGenerator(*rhs.virginGenerator_[i]);
5144    }
5145  } else {
5146    generator_=NULL;
5147    virginGenerator_=NULL;
5148  }
5149  numberHeuristics_ = rhs.numberHeuristics_;
5150  if (numberHeuristics_) {
5151    heuristic_ = new CbcHeuristic * [numberHeuristics_];
5152    int i;
5153    for (i=0;i<numberHeuristics_;i++) {
5154      heuristic_[i]=rhs.heuristic_[i]->clone();
5155    }
5156  } else {
5157    heuristic_=NULL;
5158  }
5159  if (rhs.eventHandler_)
5160    eventHandler_ = rhs.eventHandler_->clone() ; 
5161  else
5162    eventHandler_ = NULL ; 
5163  if (rhs.branchingMethod_)
5164    branchingMethod_=rhs.branchingMethod_->clone();
5165  else
5166    branchingMethod_=NULL;
5167  messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
5168  whenCuts_ = rhs.whenCuts_;
5169  synchronizeModel();
5170}
5171// Move status, nodes etc etc across
5172void 
5173CbcModel::moveInfo(const CbcModel & rhs)
5174{
5175  bestObjective_ = rhs.bestObjective_;
5176  bestPossibleObjective_=rhs.bestPossibleObjective_;
5177  numberSolutions_=rhs.numberSolutions_;
5178  numberHeuristicSolutions_=rhs.numberHeuristicSolutions_;
5179  numberNodes_ = rhs.numberNodes_;
5180  numberNodes2_ = rhs.numberNodes2_;
5181  numberIterations_ = rhs.numberIterations_;
5182  status_ = rhs.status_;
5183  secondaryStatus_ = rhs.secondaryStatus_;
5184  numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
5185  numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_;
5186  continuousObjective_=rhs.continuousObjective_;
5187  originalContinuousObjective_ = rhs.originalContinuousObjective_;
5188  continuousInfeasibilities_ = rhs.continuousInfeasibilities_;
5189  numberFixedAtRoot_ = rhs.numberFixedAtRoot_;
5190  numberFixedNow_ = rhs.numberFixedNow_;
5191  stoppedOnGap_ = rhs.stoppedOnGap_;
5192  eventHappened_ = rhs.eventHappened_;
5193  numberLongStrong_ = rhs.numberLongStrong_;
5194  numberStrongIterations_ = rhs.numberStrongIterations_;
5195  strongInfo_[0]=rhs.strongInfo_[0];
5196  strongInfo_[1]=rhs.strongInfo_[1];
5197  strongInfo_[2]=rhs.strongInfo_[2];
5198  strongInfo_[3]=rhs.strongInfo_[3];
5199  strongInfo_[4]=rhs.strongInfo_[4];
5200  strongInfo_[5]=rhs.strongInfo_[5];
5201  strongInfo_[6]=rhs.strongInfo_[6];
5202  numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
5203  maximumDepth_= rhs.maximumDepth_;
5204}
5205// Save a copy of the current solver so can be reset to
5206void 
5207CbcModel::saveReferenceSolver()
5208{
5209  delete referenceSolver_;
5210  referenceSolver_= solver_->clone();
5211}
5212
5213// Uses a copy of reference solver to be current solver
5214void 
5215CbcModel::resetToReferenceSolver()
5216{
5217  delete solver_;
5218  solver_ = referenceSolver_->clone();
5219  // clear many things
5220  gutsOfDestructor2();
5221  // Reset cutoff
5222  // Solvers know about direction
5223  double direction = solver_->getObjSense();
5224  double value;
5225  solver_->getDblParam(OsiDualObjectiveLimit,value); 
5226  setCutoff(value*direction);
5227}
5228
5229// Are there a numerical difficulties?
5230bool 
5231CbcModel::isAbandoned() const
5232{
5233  return status_ == 2;
5234}
5235// Is optimality proven?
5236bool 
5237CbcModel::isProvenOptimal() const
5238{
5239  if (!status_ && bestObjective_<1.0e30)
5240    return true;
5241  else
5242    return false;
5243}
5244// Is  infeasiblity proven (or none better than cutoff)?
5245bool 
5246CbcModel::isProvenInfeasible() const
5247{
5248  if (!status_ && bestObjective_>=1.0e30)
5249    return true;
5250  else
5251    return false;
5252}
5253// Was continuous solution unbounded
5254bool 
5255CbcModel::isContinuousUnbounded() const
5256{
5257  if (!status_ && secondaryStatus_==7)
5258    return true;
5259  else
5260    return false;
5261}
5262// Was continuous solution unbounded
5263bool 
5264CbcModel::isProvenDualInfeasible() const
5265{
5266  if (!status_ && secondaryStatus_==7)
5267    return true;
5268  else
5269    return false;
5270}
5271// Node limit reached?
5272bool 
5273CbcModel::isNodeLimitReached() const
5274{
5275  return numberNodes_ >= intParam_[CbcMaxNumNode];
5276}
5277// Time limit reached?
5278bool 
5279CbcModel::isSecondsLimitReached() const
5280{
5281  if (status_==1&&secondaryStatus_==4)
5282    return true;
5283  else
5284    return false;
5285}
5286// Solution limit reached?
5287bool 
5288CbcModel::isSolutionLimitReached() const
5289{
5290  return numberSolutions_ >= intParam_[CbcMaxNumSol];
5291}
5292// Set language
5293void 
5294CbcModel::newLanguage(CoinMessages::Language language)
5295{
5296  messages_ = CbcMessage(language);
5297}
5298void 
5299CbcModel::setNumberStrong(int number)
5300{
5301  if (number<0)
5302    numberStrong_=0;
5303   else
5304    numberStrong_=number;
5305}
5306void 
5307CbcModel::setNumberBeforeTrust(int number)
5308{
5309  if (number<-3) {
5310    numberBeforeTrust_=0;
5311  } else {
5312    numberBeforeTrust_=number;
5313    //numberStrong_ = CoinMax(numberStrong_,1);
5314  }
5315}
5316void 
5317CbcModel::setNumberPenalties(int number)
5318{
5319  if (number<=0) {
5320    numberPenalties_=0;
5321  } else {
5322    numberPenalties_=number;
5323  }
5324}
5325void 
5326CbcModel::setPenaltyScaleFactor(double value)
5327{
5328  if (value<=0) {
5329    penaltyScaleFactor_=3.0;
5330  } else {
5331    penaltyScaleFactor_=value;
5332  }
5333}
5334void 
5335CbcModel::setHowOftenGlobalScan(int number)
5336{
5337  if (number<-1)
5338    howOftenGlobalScan_=0;
5339   else
5340    howOftenGlobalScan_=number;
5341}
5342
5343// Add one generator
5344void 
5345CbcModel::addCutGenerator(CglCutGenerator * generator,
5346                          int howOften, const char * name,
5347                          bool normal, bool atSolution,
5348                          bool whenInfeasible,int howOftenInSub,
5349                          int whatDepth, int whatDepthInSub)
5350{
5351  CbcCutGenerator ** temp = generator_;
5352  generator_ = new CbcCutGenerator * [numberCutGenerators_+1];
5353  memcpy(generator_,temp,numberCutGenerators_*sizeof(CbcCutGenerator *));
5354  delete[] temp ;
5355  generator_[numberCutGenerators_]= 
5356    new CbcCutGenerator(this,generator, howOften, name,
5357                        normal,atSolution,whenInfeasible,howOftenInSub,
5358                        whatDepth, whatDepthInSub);
5359  // and before any changes
5360  temp = virginGenerator_;
5361  virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_+1];
5362  memcpy(virginGenerator_,temp,numberCutGenerators_*sizeof(CbcCutGenerator *));
5363  delete[] temp ;
5364  virginGenerator_[numberCutGenerators_++]= 
5365    new CbcCutGenerator(this,generator, howOften, name,
5366                        normal,atSolution,whenInfeasible,howOftenInSub,
5367                        whatDepth, whatDepthInSub);
5368                                                         
5369}
5370// Add one heuristic
5371void 
5372CbcModel::addHeuristic(CbcHeuristic * generator, const char *name,
5373                       int before)
5374{
5375  CbcHeuristic ** temp = heuristic_;
5376  heuristic_ = new CbcHeuristic * [numberHeuristics_+1];
5377  memcpy(heuristic_,temp,numberHeuristics_*sizeof(CbcHeuristic *));
5378  delete [] temp;
5379  int where;
5380  if (before<0||before>=numberHeuristics_) {
5381    where=numberHeuristics_;
5382  } else {
5383    // move up
5384    for (int i=numberHeuristics_;i>before;i--) 
5385      heuristic_[i]=heuristic_[i-1];
5386    where=before;
5387  }
5388  heuristic_[where]=generator->clone();
5389  if (name)
5390    heuristic_[where]->setHeuristicName(name) ; 
5391  heuristic_[where]->setSeed(987654321+where);
5392  numberHeuristics_++ ;
5393}
5394
5395/*
5396  The last subproblem handled by the solver is not necessarily related to the
5397  one being recreated, so the first action is to remove all cuts from the
5398  constraint system.  Next, traverse the tree from node to the root to
5399  determine the basis size required for this subproblem and create an empty
5400  basis with the right capacity.  Finally, traverse the tree from root to
5401  node, adjusting bounds in the constraint system, adjusting the basis, and
5402  collecting the cuts that must be added to the constraint system.
5403  applyToModel does the heavy lifting.
5404
5405  addCuts1 is used in contexts where all that's desired is the list of cuts:
5406  the node is already fathomed, and we're collecting cuts so that we can
5407  adjust reference counts as we prune nodes. Arguably the two functions
5408  should be separated. The culprit is applyToModel, which performs cut
5409  collection and model adjustment.
5410
5411  Certainly in the contexts where all we need is a list of cuts, there's no
5412  point in passing in a valid basis --- an empty basis will do just fine.
5413*/
5414bool CbcModel::addCuts1 (CbcNode * node, CoinWarmStartBasis *&lastws)
5415{ 
5416  int nNode=0;
5417  int numberColumns = getNumCols();
5418  CbcNodeInfo * nodeInfo = node->nodeInfo();
5419
5420/*
5421  Accumulate the path from node to the root in walkback_, and accumulate a
5422  cut count in currentNumberCuts.
5423
5424  original comment: when working then just unwind until where new node joins
5425  old node (for cuts?)
5426*/
5427  int currentNumberCuts = 0;
5428  while (nodeInfo) {
5429    //printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo);
5430    walkback_[nNode++]=nodeInfo;
5431    currentNumberCuts += nodeInfo->numberCuts() ;
5432    nodeInfo = nodeInfo->parent() ;
5433    if (nNode==maximumDepth_) {
5434      redoWalkBack();
5435    }
5436  }
5437  currentNumberCuts_=currentNumberCuts;
5438  if (currentNumberCuts > maximumNumberCuts_) {
5439    maximumNumberCuts_ = currentNumberCuts;
5440    delete [] addedCuts_;
5441    addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
5442  }
5443/*
5444  This last bit of code traverses the path collected in walkback_ from the
5445  root back to node. At the end of the loop,
5446   * lastws will be an appropriate basis for node;
5447   * variable bounds in the constraint system will be set to be correct for
5448     node; and
5449   * addedCuts_ will be set to a list of cuts that need to be added to the
5450     constraint system at node.
5451  applyToModel does all the heavy lifting.
5452*/
5453  //#define CBC_PRINT2
5454#ifdef CBC_PRINT2
5455  printf("Starting bounds at node %d\n",numberNodes_);
5456#endif
5457  bool sameProblem=false;
5458#ifdef NODE_LAST
5459  if ((specialOptions_&4096)==0) {
5460    {
5461      int n1=numberRowsAtContinuous_;
5462      for (int i=0;i<lastDepth_;i++)
5463        n1 += lastNumberCuts_[i];
5464      int n2=numberRowsAtContinuous_;
5465      for (int i=0;i<nNode;i++)
5466        n2 += walkback_[i]->numberCuts();
5467      //printf("ROWS a %d - old thinks %d new %d\n",solver_->getNumRows(),n1,n2);
5468    }
5469    int nDel=0;
5470    int nAdd=0;
5471    int n=CoinMin(lastDepth_,nNode);
5472    int i;
5473    int difference=lastDepth_-nNode;
5474    int iZ=lastDepth_;
5475    int iN=0;
5476    // Last is reversed to minimize copying
5477    if (difference>0) {
5478      for (i=0;i<difference;i++) {
5479        // delete rows
5480        nDel += lastNumberCuts_[--iZ];
5481      }
5482    } else if (difference<0) {
5483      for (i=0;i<-difference;i++) {
5484        // add rows
5485        nAdd += walkback_[i]->numberCuts();
5486      }
5487      iN=-difference;
5488    }
5489    for (i=0;i<n;i++) {
5490      iZ--;
5491      if (lastNodeInfo_[iZ]==walkback_[iN]) {
5492        break;
5493      } else {
5494        // delete rows
5495        nDel += lastNumberCuts_[iZ];
5496        // add rows
5497        nAdd += walkback_[iN++]->numberCuts();
5498      }
5499    }
5500    assert (i<n||lastDepth_==0);
5501    //printf("lastDepth %d thisDepth %d match at %d, rows+-= %d %d\n",
5502    //   lastDepth_,nNode,n-i,nAdd,nDel);
5503    sameProblem = (!nAdd)&&(!nDel);
5504    if (lastDepth_) {
5505      while (iN>=0) {
5506        lastNumberCuts_[iZ] = walkback_[iN]->numberCuts();
5507        lastNodeInfo_[iZ++]=walkback_[iN--];
5508      }
5509    } else {
5510      lastNumberCuts_[0]=walkback_[0]->numberCuts();
5511      lastNodeInfo_[0]=walkback_[0];
5512    }
5513    lastDepth_=nNode;
5514  }
5515#endif
5516  currentDepth_=nNode;
5517/*
5518  Remove all cuts from the constraint system.
5519  (original comment includes ``see note below for later efficiency'', but
5520  the reference isn't clear to me).
5521*/
5522/*
5523  Create an empty basis with sufficient capacity for the constraint system
5524  we'll construct: original system plus cuts. Make sure we have capacity to
5525  record those cuts in addedCuts_.
5526
5527  The method of adjusting the basis at a FullNodeInfo object (the root, for
5528  example) is to use a copy constructor to duplicate the basis held in the
5529  nodeInfo, then resize it and return the new basis object. Guaranteed,
5530  lastws will point to a different basis when it returns. We pass in a basis
5531  because we need the parameter to return the allocated basis, and it's an
5532  easy way to pass in the size. But we take a hit for memory allocation.
5533*/
5534  lastws->setSize(numberColumns,numberRowsAtContinuous_+currentNumberCuts);
5535  currentNumberCuts=0;
5536  while (nNode) {
5537    --nNode;
5538    walkback_[nNode]->applyToModel(this,lastws,
5539                                   addedCuts_,currentNumberCuts);
5540  }
5541#ifndef NDEBUG
5542  if (!lastws->fullBasis()) {
5543#ifdef COIN_DEVELOP
5544    printf("******* bad basis\n");
5545#endif
5546    int numberRows = lastws->getNumArtificial();
5547    int i;
5548    for (i=0;i<numberRows;i++)
5549      lastws->setArtifStatus(i,CoinWarmStartBasis::basic);
5550    int numberColumns = lastws->getNumStructural();
5551    for (i=0;i<numberColumns;i++) {
5552      if (lastws->getStructStatus(i)==CoinWarmStartBasis::basic)
5553        lastws->setStructStatus(i,CoinWarmStartBasis::atLowerBound);
5554    }
5555#if 0
5556  } else {
5557    // OPTION - take off slack cuts
5558    // First see if any cuts are slack
5559    int numberAdded = currentNumberCuts;
5560    if (saveNode<2&&false) {
5561      printf("nNode %d cuts %d\n",saveNode,currentNumberCuts);
5562      for (int i=0;i<currentNumberCuts;i++)
5563        addedCuts_[i]->print();
5564    }
5565    if (numberAdded&&saveNode<5&&!parentModel_) {
5566#if 0
5567      currentNumberCuts=0;
5568      for (int j=numberRowsAtContinuous_;
5569           j<numberAdded+numberRowsAtContinuous_;j++) {
5570        CoinWarmStartBasis::Status status = lastws->getArtifStatus(j);
5571        if (status!=CoinWarmStartBasis::basic) {
5572          lastws->setArtifStatus(currentNumberCuts+numberRowsAtContinuous_,
5573                                 status);
5574          addedCuts_[currentNumberCuts++]=addedCuts_[j-numberRowsAtContinuous_];
5575        }
5576      }
5577      if (currentNumberCuts<numberAdded) {
5578        printf("deleting %d rows\n",numberAdded-currentNumberCuts);
5579        lastws->resize(currentNumberCuts+numberRowsAtContinuous_,
5580                       lastws->getNumStructural());
5581        currentNumberCuts_=currentNumberCuts;
5582      }
5583#else
5584      int nDelete=0;
5585      for (int j=numberRowsAtContinuous_;
5586           j<numberAdded+numberRowsAtContinuous_;j++) {
5587        CoinWarmStartBasis::Status status = lastws->getArtifStatus(j);
5588        if (status==CoinWarmStartBasis::basic)
5589          nDelete++;
5590      }
5591      if (nDelete)
5592        printf("depth %d can delete %d\n",saveNode-1,nDelete);
5593#endif
5594    }
5595#endif
5596  }
5597#endif
5598  if (0) {
5599    int numberDebugValues=18;
5600    double * debugValues = new double[numberDebugValues];
5601    CoinZeroN(debugValues,numberDebugValues);
5602    debugValues[1]=6.0;
5603    debugValues[3]=60.0;
5604    debugValues[4]=6.0;
5605    debugValues[6]=60.0;
5606    debugValues[7]=16.0;
5607    debugValues[9]=70.0;
5608    debugValues[10]=7.0;
5609    debugValues[12]=70.0;
5610    debugValues[13]=12.0;
5611    debugValues[15]=75.0;
5612    int nBad=0;
5613    for (int j=0;j<numberColumns;j++) {
5614      if (integerInfo_[j]) {
5615        if(solver_->getColLower()[j]>debugValues[j]||
5616           solver_->getColUpper()[j]<debugValues[j]) {
5617          printf("** (%g) ** ",debugValues[j]);
5618          nBad++;
5619        }
5620        printf("%d bounds %g %g\n",j,solver_->getColLower()[j],solver_->getColUpper()[j]);
5621      }
5622    }
5623    if (nBad)
5624      printf("%d BAD\n",nBad);
5625    else
5626      printf("OKAY\n");
5627    delete [] debugValues;
5628  }
5629  return sameProblem;
5630}
5631
5632/*
5633  adjustCuts might be a better name: If the node is feasible, we sift through
5634  the cuts collected by addCuts1, add the ones that are tight and omit the
5635  ones that are loose. If the node is infeasible, we just adjust the
5636  reference counts to reflect that we're about to prune this node and its
5637  descendants.
5638*/
5639int CbcModel::addCuts (CbcNode *node, CoinWarmStartBasis *&lastws,bool canFix)
5640{
5641/*
5642  addCuts1 performs step 1 of restoring the subproblem at this node; see the
5643  comments there.
5644*/
5645#ifdef NODE_LAST
5646  bool sameProblem=
5647#endif
5648    addCuts1(node,lastws);
5649  int i;
5650  int numberColumns = getNumCols();
5651  if (solver_->getNumRows()>maximumRows_) {
5652    maximumRows_ = solver_->getNumRows();
5653    workingBasis_.resize(maximumRows_,numberColumns);
5654  }
5655  CbcNodeInfo * nodeInfo = node->nodeInfo();
5656  double cutoff = getCutoff() ;
5657  int currentNumberCuts=currentNumberCuts_;
5658  if (canFix) {
5659    bool feasible=true;
5660    const double *lower = solver_->getColLower() ;
5661    const double *upper = solver_->getColUpper() ;
5662    double * newLower = analyzeResults_;
5663    double * objLower = newLower+numberIntegers_;
5664    double * newUpper = objLower+numberIntegers_;
5665    double * objUpper = newUpper+numberIntegers_;
5666    int n=0;
5667    for (i=0;i<numberIntegers_;i++) {
5668      int iColumn = integerVariable_[i];
5669      bool changed=false;
5670      double lo = 0.0;
5671      double up = 0.0;
5672      if (objLower[i]>cutoff) {
5673        lo = lower[iColumn];
5674        up = upper[iColumn];
5675        if (lo<newLower[i]) {
5676          lo = newLower[i];
5677          solver_->setColLower(iColumn,lo);
5678          changed=true;
5679          n++;
5680        }
5681        if (objUpper[i]>cutoff) {
5682          if (up>newUpper[i]) {
5683            up = newUpper[i];
5684            solver_->setColUpper(iColumn,up);
5685            changed=true;
5686            n++;
5687          }
5688        }
5689      } else if (objUpper[i]>cutoff) {
5690        lo = lower[iColumn];
5691        up = upper[iColumn];
5692        if (up>newUpper[i]) {
5693          up = newUpper[i];
5694          solver_->setColUpper(iColumn,up);
5695          changed=true;
5696          n++;
5697        }
5698      }
5699      if (changed&&lo>up) {
5700        feasible=false;
5701        break;
5702      }
5703    }
5704    if (!feasible) {
5705      printf("analysis says node infeas\n");
5706      cutoff=-COIN_DBL_MAX;
5707    }
5708  }
5709/*
5710  If the node can't be fathomed by bound, reinstall tight cuts in the
5711  constraint system. Even if there are no cuts, we'll want to set the
5712  reconstructed basis in the solver.
5713*/
5714  if (node->objectiveValue() < cutoff||numberThreads_)
5715  { 
5716    //#   define CBC_CHECK_BASIS
5717#   ifdef CBC_CHECK_BASIS
5718    printf("addCuts: expanded basis; rows %d+%d\n",
5719           numberRowsAtContinuous_,currentNumberCuts);
5720    lastws->print();
5721#   endif
5722/*
5723  Adjust the basis and constraint system so that we retain only active cuts.
5724  There are three steps:
5725    1) Scan the basis. Sort the cuts into effective cuts to be kept and
5726       loose cuts to be dropped.
5727    2) Drop the loose cuts and resize the basis to fit.
5728    3) Install the tight cuts in the constraint system (applyRowCuts) and
5729       and install the basis (setWarmStart).
5730  Use of compressRows conveys we're compressing the basis and not just
5731  tweaking the artificialStatus_ array.
5732*/
5733    if (currentNumberCuts > 0) {
5734      int numberToAdd = 0;
5735      const OsiRowCut **addCuts;
5736      int numberToDrop = 0 ;
5737      int *cutsToDrop ;
5738      addCuts = new const OsiRowCut* [currentNumberCuts];
5739      cutsToDrop = new int[currentNumberCuts] ;
5740      assert (currentNumberCuts+numberRowsAtContinuous_<=lastws->getNumArtificial());
5741      for (i=0;i<currentNumberCuts;i++) {
5742        CoinWarmStartBasis::Status status = 
5743          lastws->getArtifStatus(i+numberRowsAtContinuous_);
5744        if (addedCuts_[i] &&
5745            (status != CoinWarmStartBasis::basic ||
5746             (addedCuts_[i]->effectiveness()>1.0e10&&
5747              !addedCuts_[i]->canDropCut(solver_,i+numberRowsAtContinuous_)))) {
5748#         ifdef CHECK_CUT_COUNTS
5749          printf("Using cut %d %x as row %d\n",i,addedCuts_[i],
5750                 numberRowsAtContinuous_+numberToAdd);
5751#         endif
5752          addCuts[numberToAdd++] = addedCuts_[i];
5753        } else {
5754#         ifdef CHECK_CUT_COUNTS
5755          printf("Dropping cut %d %x\n",i,addedCuts_[i]);
5756#         endif
5757          addedCuts_[i]=NULL;
5758          cutsToDrop[numberToDrop++] = numberRowsAtContinuous_+i ;
5759        }
5760      }
5761      assert (lastws->fullBasis());
5762      int numberRowsNow=numberRowsAtContinuous_+numberToAdd;
5763      lastws->compressRows(numberToDrop,cutsToDrop) ;
5764      lastws->resize(numberRowsNow,numberColumns);
5765#ifdef NODE_LAST
5766      bool canMissStuff=false;
5767      if ((specialOptions_&4096)==0) {
5768        bool redoCuts=true;
5769        if (CoinAbs(lastNumberCuts2_-numberToAdd)<5) {
5770          int numberToCheck=CoinMin(lastNumberCuts2_,numberToAdd);
5771          int i1=0;
5772          int i2=0;
5773          int nDiff=0;
5774          int nSame=0;
5775          if (lastNumberCuts2_==numberToAdd) {
5776            for (int i=0;i<numberToCheck;i++) {
5777              if (lastCut_[i1++]!=addCuts[i2++]) {
5778                nDiff++;
5779              } else {
5780                nSame++;
5781              }
5782            }
5783          } else if (lastNumberCuts2_>numberToAdd) {
5784            int nDiff2 = lastNumberCuts2_-numberToAdd;
5785            for (int i=0;i<numberToCheck;i++) {
5786              if (lastCut_[i1]!=addCuts[i2]) {
5787                nDiff++;
5788                while (nDiff2) {
5789                  i1++;
5790                  nDiff2--;
5791                  if (lastCut_[i1]==addCuts[i2]) {
5792                    nSame++;
5793                    break;
5794                  } else {
5795                    nDiff++;
5796                  }
5797                }
5798              } else {
5799                nSame++;
5800              }
5801            }
5802            nDiff += nDiff2;
5803          } else {
5804            int nDiff2 = numberToAdd-lastNumberCuts2_;
5805            for (int i=0;i<numberToCheck;i++) {
5806              if (lastCut_[i1]!=addCuts[i2]) {
5807                nDiff++;
5808                while (nDiff2) {
5809                  i2++;
5810                  nDiff2--;
5811                  if (lastCut_[i1]==addCuts[<