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

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

fixes

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