source: stable/2.4/Cbc/src/CbcModel.cpp @ 1647

Last change on this file since 1647 was 1647, checked in by stefan, 8 years ago

fix seldom segfault when stopping at timelimit, from #1623 in trunk

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