source: branches/devel/Cbc/src/CbcModel.cpp @ 543

Last change on this file since 543 was 543, checked in by forrest, 13 years ago

out persistence for a bit

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