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

Last change on this file since 1237 was 1237, checked in by lou, 11 years ago

Studio CC has no template for fabs(bool).

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