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

Last change on this file since 1239 was 1239, checked in by stefan, 11 years ago

on windows/cl use CoinGetTimeOfDay? instead of gettimeofday

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