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

Last change on this file since 954 was 954, checked in by forrest, 12 years ago

changes to try and improve code

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