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

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

for osi methods

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