source: trunk/Cbc/src/CbcNode.cpp @ 325

Last change on this file since 325 was 325, checked in by andreasw, 14 years ago

changed Config.h behavior

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 131.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
14#define CBC_WEAK_STRONG
15#include <cassert>
16#include <cfloat>
17#define CUTS
18#include "OsiSolverInterface.hpp"
19#include "OsiAuxInfo.hpp"
20#include "OsiSolverBranch.hpp"
21#include "CoinWarmStartBasis.hpp"
22#include "CoinTime.hpp"
23#include "CbcModel.hpp"
24#include "CbcNode.hpp"
25#include "CbcStatistics.hpp"
26#include "CbcStrategy.hpp"
27#include "CbcBranchActual.hpp"
28#include "CbcBranchDynamic.hpp"
29#include "OsiRowCut.hpp"
30#include "OsiRowCutDebugger.hpp"
31#include "OsiCuts.hpp"
32#include "CbcCountRowCut.hpp"
33#include "CbcFeasibilityBase.hpp"
34#include "CbcMessage.hpp"
35#ifdef COIN_HAS_CLP
36#include "OsiClpSolverInterface.hpp"
37#include "ClpSimplexOther.hpp"
38#endif
39using namespace std;
40#include "CglCutGenerator.hpp"
41// Default Constructor
42CbcNodeInfo::CbcNodeInfo ()
43  :
44  numberPointingToThis_(0),
45  parent_(NULL),
46  owner_(NULL),
47  numberCuts_(0),
48  nodeNumber_(0),
49  cuts_(NULL),
50  numberRows_(0),
51  numberBranchesLeft_(0)
52{
53#ifdef CHECK_NODE
54  printf("CbcNodeInfo %x Constructor\n",this);
55#endif
56}
57// Constructor given parent
58CbcNodeInfo::CbcNodeInfo (CbcNodeInfo * parent)
59  :
60  numberPointingToThis_(2),
61  parent_(parent),
62  owner_(NULL),
63  numberCuts_(0),
64  nodeNumber_(0),
65  cuts_(NULL),
66  numberRows_(0),
67  numberBranchesLeft_(2)
68{
69#ifdef CHECK_NODE
70  printf("CbcNodeInfo %x Constructor from parent %x\n",this,parent_);
71#endif
72  if (parent_) {
73    numberRows_ = parent_->numberRows_+parent_->numberCuts_;
74  }
75}
76// Copy Constructor
77CbcNodeInfo::CbcNodeInfo (const CbcNodeInfo & rhs)
78  :
79  numberPointingToThis_(rhs.numberPointingToThis_),
80  parent_(rhs.parent_),
81  owner_(rhs.owner_),
82  numberCuts_(rhs.numberCuts_),
83  nodeNumber_(rhs.nodeNumber_),
84  cuts_(NULL),
85  numberRows_(rhs.numberRows_),
86  numberBranchesLeft_(rhs.numberBranchesLeft_)
87{
88#ifdef CHECK_NODE
89  printf("CbcNodeInfo %x Copy constructor\n",this);
90#endif
91  if (numberCuts_) {
92    cuts_ = new CbcCountRowCut * [numberCuts_];
93    int n=0;
94    for (int i=0;i<numberCuts_;i++) {
95      CbcCountRowCut * thisCut = rhs.cuts_[i];
96      if (thisCut) {
97        // I think this is correct - new one should take priority
98        thisCut->setInfo(this,n);
99        thisCut->increment(numberBranchesLeft_); 
100        cuts_[n++] = thisCut;
101      }
102    }
103    numberCuts_=n;
104  }
105}
106// Constructor given parent and owner
107CbcNodeInfo::CbcNodeInfo (CbcNodeInfo * parent, CbcNode * owner)
108  :
109  numberPointingToThis_(2),
110  parent_(parent),
111  owner_(owner),
112  numberCuts_(0),
113  nodeNumber_(0),
114  cuts_(NULL),
115  numberRows_(0),
116  numberBranchesLeft_(2)
117{
118#ifdef CHECK_NODE
119  printf("CbcNodeInfo %x Constructor from parent %x\n",this,parent_);
120#endif
121  if (parent_) {
122    numberRows_ = parent_->numberRows_+parent_->numberCuts_;
123  }
124}
125
126/**
127  Take care to detach from the owning CbcNode and decrement the reference
128  count in the parent.  If this is the last nodeInfo object pointing to the
129  parent, make a recursive call to delete the parent.
130*/
131CbcNodeInfo::~CbcNodeInfo()
132{
133#ifdef CHECK_NODE
134  printf("CbcNodeInfo %x Destructor parent %x\n",this,parent_);
135#endif
136
137  assert(!numberPointingToThis_);
138  // But they may be some left (max nodes?)
139  for (int i=0;i<numberCuts_;i++) 
140    delete cuts_[i];
141
142  delete [] cuts_;
143  if (owner_) 
144    owner_->nullNodeInfo();
145  if (parent_) {
146    int numberLinks = parent_->decrement();
147    if (!numberLinks) delete parent_;
148  }
149}
150
151
152//#define ALLCUTS
153void
154CbcNodeInfo::decrementCuts(int change)
155{
156  int i;
157  // get rid of all remaining if negative
158  int changeThis;
159  if (change<0)
160    changeThis = numberBranchesLeft_;
161  else
162    changeThis = change;
163 // decrement cut counts
164  for (i=0;i<numberCuts_;i++) {
165    if (cuts_[i]) {
166      int number = cuts_[i]->decrement(changeThis);
167      if (!number) {
168        //printf("info %x del cut %d %x\n",this,i,cuts_[i]);
169        delete cuts_[i];
170        cuts_[i]=NULL;
171      }
172    }
173  }
174}
175void
176CbcNodeInfo::decrementParentCuts(int change)
177{
178  if (parent_) {
179    // get rid of all remaining if negative
180    int changeThis;
181    if (change<0)
182      changeThis = numberBranchesLeft_;
183    else
184      changeThis = change;
185    int i;
186    // Get over-estimate of space needed for basis
187    CoinWarmStartBasis dummy;
188    dummy.setSize(0,numberRows_+numberCuts_);
189    buildRowBasis(dummy);
190    /* everything is zero (i.e. free) so we can use to see
191       if latest basis */
192    CbcNodeInfo * thisInfo = parent_;
193    while (thisInfo) 
194      thisInfo = thisInfo->buildRowBasis(dummy);
195    // decrement cut counts
196    thisInfo = parent_;
197    int numberRows=numberRows_;
198    while (thisInfo) {
199      for (i=thisInfo->numberCuts_-1;i>=0;i--) {
200        CoinWarmStartBasis::Status status = dummy.getArtifStatus(--numberRows);
201#ifdef ALLCUTS
202        status = CoinWarmStartBasis::isFree;
203#endif
204        if (thisInfo->cuts_[i]) {
205          int number=1;
206          if (status!=CoinWarmStartBasis::basic) {
207            // tight - drop 1 or 2
208            if (change<0)
209              number = thisInfo->cuts_[i]->decrement(changeThis);
210            else
211              number = thisInfo->cuts_[i]->decrement(change);
212          }
213          if (!number) {
214            delete thisInfo->cuts_[i];
215            thisInfo->cuts_[i]=NULL;
216          }
217        }
218      }
219      thisInfo = thisInfo->parent_;
220    }
221  }
222}
223
224void
225CbcNodeInfo::incrementParentCuts(int change)
226{
227  if (parent_) {
228    int i;
229    // Get over-estimate of space needed for basis
230    CoinWarmStartBasis dummy;
231    dummy.setSize(0,numberRows_+numberCuts_);
232    /* everything is zero (i.e. free) so we can use to see
233       if latest basis */
234    buildRowBasis(dummy);
235    CbcNodeInfo * thisInfo = parent_;
236    while (thisInfo) 
237      thisInfo = thisInfo->buildRowBasis(dummy);
238    // increment cut counts
239    thisInfo = parent_;
240    int numberRows=numberRows_;
241    while (thisInfo) {
242      for (i=thisInfo->numberCuts_-1;i>=0;i--) {
243        CoinWarmStartBasis::Status status = dummy.getArtifStatus(--numberRows);
244#ifdef ALLCUTS
245        status = CoinWarmStartBasis::isFree;
246#endif
247        if (thisInfo->cuts_[i]&&status!=CoinWarmStartBasis::basic) {
248          thisInfo->cuts_[i]->increment(change);
249        }
250      }
251      thisInfo = thisInfo->parent_;
252    }
253  }
254}
255
256/*
257  Append cuts to the cuts_ array in a nodeInfo. The initial reference count
258  is set to numberToBranchOn, which will normally be the number of arms
259  defined for the CbcBranchingObject attached to the CbcNode that owns this
260  CbcNodeInfo.
261*/
262void
263CbcNodeInfo::addCuts (OsiCuts & cuts, int numberToBranchOn,
264                      int * whichGenerator)
265{
266  int numberCuts = cuts.sizeRowCuts();
267  if (numberCuts) {
268    int i;
269    if (!numberCuts_) {
270      cuts_ = new CbcCountRowCut * [numberCuts];
271    } else {
272      CbcCountRowCut ** temp = new CbcCountRowCut * [numberCuts+numberCuts_];
273      memcpy(temp,cuts_,numberCuts_*sizeof(CbcCountRowCut *));
274      delete [] cuts_;
275      cuts_ = temp;
276    }
277    for (i=0;i<numberCuts;i++) {
278      CbcCountRowCut * thisCut = new CbcCountRowCut(*cuts.rowCutPtr(i),
279                                                    this,numberCuts_);
280      thisCut->increment(numberToBranchOn); 
281      cuts_[numberCuts_++] = thisCut;
282#ifdef CBC_DEBUG
283#if CBC_DEBUG>1
284      int n=thisCut->row().getNumElements();
285      printf("Cut %d has %d entries, rhs %g %g =>",i,n,thisCut->lb(),
286             thisCut->ub());
287      int j;
288      const int * index = thisCut->row().getIndices();
289      const double * element = thisCut->row().getElements();
290      for (j=0;j<n;j++) {
291        printf(" (%d,%g)",index[j],element[j]);
292        assert(fabs(element[j])>1.00e-12);
293      }
294      printf("\n");
295#else
296      int n=thisCut->row().getNumElements();
297      int j;
298      const double * element = thisCut->row().getElements();
299      for (j=0;j<n;j++) {
300        assert(fabs(element[j])>1.00e-12);
301      }
302#endif
303#endif
304    }
305  }
306}
307
308void
309CbcNodeInfo::addCuts(int numberCuts, CbcCountRowCut ** cut, 
310                     int numberToBranchOn)
311{
312  if (numberCuts) {
313    int i;
314    if (!numberCuts_) {
315      cuts_ = new CbcCountRowCut * [numberCuts];
316    } else {
317      CbcCountRowCut ** temp = new CbcCountRowCut * [numberCuts+numberCuts_];
318      memcpy(temp,cuts_,numberCuts_*sizeof(CbcCountRowCut *));
319      delete [] cuts_;
320      cuts_ = temp;
321    }
322    for (i=0;i<numberCuts;i++) {
323      CbcCountRowCut * thisCut = cut[i];
324      thisCut->setInfo(this,numberCuts_);
325      //printf("info %x cut %d %x\n",this,i,thisCut);
326      thisCut->increment(numberToBranchOn); 
327      cuts_[numberCuts_++] = thisCut;
328#ifdef CBC_DEBUG
329      int n=thisCut->row().getNumElements();
330#if CBC_DEBUG>1
331      printf("Cut %d has %d entries, rhs %g %g =>",i,n,thisCut->lb(),
332             thisCut->ub());
333#endif
334      int j;
335#if CBC_DEBUG>1
336      const int * index = thisCut->row().getIndices();
337#endif
338      const double * element = thisCut->row().getElements();
339      for (j=0;j<n;j++) {
340#if CBC_DEBUG>1
341        printf(" (%d,%g)",index[j],element[j]);
342#endif
343        assert(fabs(element[j])>1.00e-12);
344      }
345      printf("\n");
346#endif
347    }
348  }
349}
350
351// delete cuts
352void
353CbcNodeInfo::deleteCuts(int numberToDelete, CbcCountRowCut ** cuts)
354{
355  int i;
356  int j;
357  int last=-1;
358  for (i=0;i<numberToDelete;i++) {
359    CbcCountRowCut * next = cuts[i];
360    for (j=last+1;j<numberCuts_;j++) {
361      if (next==cuts_[j])
362        break;
363    }
364    if (j==numberCuts_) {
365      // start from beginning
366      for (j=0;j<last;j++) {
367        if (next==cuts_[j])
368          break;
369      }
370      assert(j<last);
371    }
372    last=j;
373    int number = cuts_[j]->decrement();
374    if (!number)
375      delete cuts_[j];
376    cuts_[j]=NULL;
377  }
378  j=0;
379  for (i=0;i<numberCuts_;i++) {
380    if (cuts_[i])
381      cuts_[j++]=cuts_[i];
382  }
383  numberCuts_ = j;
384}
385
386// delete cuts
387void
388CbcNodeInfo::deleteCuts(int numberToDelete, int * which)
389{
390  int i;
391  for (i=0;i<numberToDelete;i++) {
392    int iCut=which[i];
393    int number = cuts_[iCut]->decrement();
394    if (!number)
395      delete cuts_[iCut];
396    cuts_[iCut]=NULL;
397  }
398  int j=0;
399  for (i=0;i<numberCuts_;i++) {
400    if (cuts_[i])
401      cuts_[j++]=cuts_[i];
402  }
403  numberCuts_ = j;
404}
405
406// Really delete a cut
407void 
408CbcNodeInfo::deleteCut(int whichOne)
409{
410  assert(whichOne<numberCuts_);
411  cuts_[whichOne]=NULL;
412}
413
414CbcFullNodeInfo::CbcFullNodeInfo() :
415  CbcNodeInfo(),
416  basis_(),
417  numberIntegers_(0),
418  lower_(NULL),
419  upper_(NULL)
420{
421}
422CbcFullNodeInfo::CbcFullNodeInfo(CbcModel * model,
423                                 int numberRowsAtContinuous) :
424  CbcNodeInfo()
425{
426  OsiSolverInterface * solver = model->solver();
427  numberRows_ = numberRowsAtContinuous;
428  numberIntegers_ = model->numberIntegers();
429  int numberColumns = model->getNumCols();
430  lower_ = new double [numberColumns];
431  upper_ = new double [numberColumns];
432  const double * lower = solver->getColLower();
433  const double * upper = solver->getColUpper();
434  int i;
435
436  for (i=0;i<numberColumns;i++) {
437    lower_[i]=lower[i];
438    upper_[i]=upper[i];
439  }
440
441  basis_ =  dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart());
442}
443
444CbcFullNodeInfo::CbcFullNodeInfo(const CbcFullNodeInfo & rhs) :
445  CbcNodeInfo(rhs)
446{ 
447  basis_= dynamic_cast<CoinWarmStartBasis *>(rhs.basis_->clone()) ;
448  numberIntegers_=rhs.numberIntegers_;
449  lower_=NULL;
450  upper_=NULL;
451  if (rhs.lower_!=NULL) {
452    int numberColumns = basis_->getNumStructural();
453    lower_ = new double [numberColumns];
454    upper_ = new double [numberColumns];
455    assert (upper_!=NULL);
456    memcpy(lower_,rhs.lower_,numberColumns*sizeof(double));
457    memcpy(upper_,rhs.upper_,numberColumns*sizeof(double));
458  }
459}
460
461CbcNodeInfo * 
462CbcFullNodeInfo::clone() const
463{ 
464  return (new CbcFullNodeInfo(*this));
465}
466
467CbcFullNodeInfo::~CbcFullNodeInfo ()
468{
469  delete basis_ ;
470  delete [] lower_;
471  delete [] upper_;
472}
473
474/*
475   The basis supplied as a parameter is deleted and replaced with a new basis
476   appropriate for the node, and lower and upper bounds on variables are
477   reset according to the stored bounds arrays. Any cuts associated with this
478   node are added to the list in addCuts, but not actually added to the
479   constraint system in the model.
480
481   Why pass in a basis at all? The short answer is ``We need the parameter to
482   pass out a basis, so might as well use it to pass in the size.''
483   
484   A longer answer is that in practice we take a memory allocation hit up in
485   addCuts1 (the only place applyToModel is called) when we setSize() the
486   basis that's passed in. It's immediately tossed here in favour of a clone
487   of the basis attached to this nodeInfo. This can probably be fixed, given
488   a bit of thought.
489*/
490
491void CbcFullNodeInfo::applyToModel (CbcModel *model,
492                                    CoinWarmStartBasis *&basis,
493                                    CbcCountRowCut **addCuts,
494                                    int &currentNumberCuts) const 
495
496{ OsiSolverInterface *solver = model->solver() ;
497
498  // branch - do bounds
499  int i;
500  solver->setColLower(lower_);
501  solver->setColUpper(upper_);
502  int numberColumns = model->getNumCols();
503  // move basis - but make sure size stays
504  // for bon-min - should not be needed int numberRows = model->getNumRows();
505  int numberRows=basis->getNumArtificial();
506  delete basis ;
507  if (basis_) {
508    basis = dynamic_cast<CoinWarmStartBasis *>(basis_->clone()) ;
509    basis->resize(numberRows,numberColumns);
510  } else {
511    // We have a solver without a basis
512    basis=NULL;
513  }
514  for (i=0;i<numberCuts_;i++) 
515    addCuts[currentNumberCuts+i]= cuts_[i];
516  currentNumberCuts += numberCuts_;
517  assert(!parent_);
518  return ;
519}
520
521/* Builds up row basis backwards (until original model).
522   Returns NULL or previous one to apply .
523   Depends on Free being 0 and impossible for cuts
524*/
525CbcNodeInfo * 
526CbcFullNodeInfo::buildRowBasis(CoinWarmStartBasis & basis ) const 
527{
528  const unsigned int * saved = 
529    (const unsigned int *) basis_->getArtificialStatus();
530  unsigned int * now = 
531    (unsigned int *) basis.getArtificialStatus();
532  int number=basis_->getNumArtificial()>>4;;
533  int i;
534  for (i=0;i<number;i++) { 
535    if (!now[i])
536      now[i] = saved[i];
537  }
538  return NULL;
539}
540
541// Default constructor
542CbcPartialNodeInfo::CbcPartialNodeInfo()
543
544  : CbcNodeInfo(),
545    basisDiff_(NULL),
546    variables_(NULL),
547    newBounds_(NULL),
548    numberChangedBounds_(0)
549
550{ /* this space intentionally left blank */ }
551
552// Constructor from current state
553CbcPartialNodeInfo::CbcPartialNodeInfo (CbcNodeInfo *parent, CbcNode *owner,
554                                        int numberChangedBounds,
555                                        const int *variables,
556                                        const double *boundChanges,
557                                        const CoinWarmStartDiff *basisDiff)
558 : CbcNodeInfo(parent,owner)
559{
560  basisDiff_ = basisDiff->clone() ;
561
562  numberChangedBounds_ = numberChangedBounds;
563  variables_ = new int [numberChangedBounds_];
564  newBounds_ = new double [numberChangedBounds_];
565
566  int i ;
567  for (i=0;i<numberChangedBounds_;i++) {
568    variables_[i]=variables[i];
569    newBounds_[i]=boundChanges[i];
570  }
571}
572
573CbcPartialNodeInfo::CbcPartialNodeInfo (const CbcPartialNodeInfo & rhs)
574
575  : CbcNodeInfo(rhs.parent_)
576
577{ basisDiff_ = rhs.basisDiff_->clone() ;
578
579  numberChangedBounds_ = rhs.numberChangedBounds_;
580  variables_ = new int [numberChangedBounds_];
581  newBounds_ = new double [numberChangedBounds_];
582
583  int i ;
584  for (i=0;i<numberChangedBounds_;i++) {
585    variables_[i]=rhs.variables_[i];
586    newBounds_[i]=rhs.newBounds_[i];
587  }
588}
589
590CbcNodeInfo * 
591CbcPartialNodeInfo::clone() const
592{ 
593  return (new CbcPartialNodeInfo(*this));
594}
595
596
597CbcPartialNodeInfo::~CbcPartialNodeInfo ()
598{
599  delete basisDiff_ ;
600  delete [] variables_;
601  delete [] newBounds_;
602}
603
604
605/**
606   The basis supplied as a parameter is incrementally modified, and lower and
607   upper bounds on variables in the model are incrementally modified. Any
608   cuts associated with this node are added to the list in addCuts.
609*/
610
611void CbcPartialNodeInfo::applyToModel (CbcModel *model,
612                                       CoinWarmStartBasis *&basis,
613                                       CbcCountRowCut **addCuts,
614                                       int &currentNumberCuts) const 
615
616{ OsiSolverInterface *solver = model->solver();
617
618  basis->applyDiff(basisDiff_) ;
619
620  // branch - do bounds
621  int i;
622  for (i=0;i<numberChangedBounds_;i++) {
623    int variable = variables_[i];
624    if ((variable&0x80000000)==0) {
625      // lower bound changing
626      solver->setColLower(variable,newBounds_[i]);
627    } else {
628      // upper bound changing
629      solver->setColUpper(variable&0x7fffffff,newBounds_[i]);
630    }
631  }
632  for (i=0;i<numberCuts_;i++) {
633    addCuts[currentNumberCuts+i]= cuts_[i];
634    if (cuts_[i]&&model->messageHandler()->logLevel()>2) {
635      cuts_[i]->print();
636    }
637  }
638   
639  currentNumberCuts += numberCuts_;
640  return ;
641}
642
643/* Builds up row basis backwards (until original model).
644   Returns NULL or previous one to apply .
645   Depends on Free being 0 and impossible for cuts
646*/
647
648CbcNodeInfo * 
649CbcPartialNodeInfo::buildRowBasis(CoinWarmStartBasis & basis ) const 
650
651{ basis.applyDiff(basisDiff_) ;
652
653  return parent_ ; }
654
655
656CbcNode::CbcNode() :
657  nodeInfo_(NULL),
658  objectiveValue_(1.0e100),
659  guessedObjectiveValue_(1.0e100),
660  branch_(NULL),
661  depth_(-1),
662  numberUnsatisfied_(0)
663{
664#ifdef CHECK_NODE
665  printf("CbcNode %x Constructor\n",this);
666#endif
667}
668
669CbcNode::CbcNode(CbcModel * model,
670                 CbcNode * lastNode) :
671  nodeInfo_(NULL),
672  objectiveValue_(1.0e100),
673  guessedObjectiveValue_(1.0e100),
674  branch_(NULL),
675  depth_(-1),
676  numberUnsatisfied_(0)
677{
678#ifdef CHECK_NODE
679  printf("CbcNode %x Constructor from model\n",this);
680#endif
681  model->setObjectiveValue(this,lastNode);
682
683  if (lastNode)
684    lastNode->nodeInfo_->increment();
685}
686
687
688void
689CbcNode::createInfo (CbcModel *model,
690                     CbcNode *lastNode,
691                     const CoinWarmStartBasis *lastws,
692                     const double *lastLower, const double *lastUpper,
693                     int numberOldActiveCuts,int numberNewCuts)
694{ OsiSolverInterface * solver = model->solver();
695 CbcStrategy * strategy = model->strategy();
696/*
697  The root --- no parent. Create full basis and bounds information.
698*/
699  if (!lastNode)
700  { 
701    if (!strategy)
702      nodeInfo_=new CbcFullNodeInfo(model,solver->getNumRows());
703    else
704      nodeInfo_ = strategy->fullNodeInfo(model,solver->getNumRows());
705  }
706/*
707  Not the root. Create an edit from the parent's basis & bound information.
708  This is not quite as straightforward as it seems. We need to reintroduce
709  cuts we may have dropped out of the basis, in the correct position, because
710  this whole process is strictly positional. Start by grabbing the current
711  basis.
712*/
713  else
714  { const CoinWarmStartBasis* ws =
715      dynamic_cast<const CoinWarmStartBasis*>(solver->getWarmStart());
716    assert(ws!=NULL); // make sure not volume
717    //int numberArtificials = lastws->getNumArtificial();
718    int numberColumns = solver->getNumCols();
719   
720    const double * lower = solver->getColLower();
721    const double * upper = solver->getColUpper();
722
723    int i;
724/*
725  Create a clone and resize it to hold all the structural constraints, plus
726  all the cuts: old cuts, both active and inactive (currentNumberCuts), and
727  new cuts (numberNewCuts).
728
729  TODO: You'd think that the set of constraints (logicals) in the expanded
730        basis should match the set represented in lastws. At least, that's
731        what I thought. But at the point I first looked hard at this bit of
732        code, it turned out that lastws was the stripped basis produced at
733        the end of addCuts(), rather than the raw basis handed back by
734        addCuts1(). The expanded basis here is equivalent to the raw basis of
735        addCuts1(). I said ``whoa, that's not good, I must have introduced a
736        bug'' and went back to John's code to see where I'd gone wrong.
737        And discovered the same `error' in his code.
738
739        After a bit of thought, my conclusion is that correctness is not
740        affected by whether lastws is the stripped or raw basis. The diffs
741        have no semantics --- just a set of changes that need to be made
742        to convert lastws into expanded. I think the only effect is that we
743        store a lot more diffs (everything in expanded that's not covered by
744        the stripped basis). But I need to give this more thought. There
745        may well be some subtle error cases.
746
747        In the mean time, I've twiddled addCuts() to set lastws to the raw
748        basis. Makes me (Lou) less nervous to compare apples to apples.
749*/
750    CoinWarmStartBasis *expanded = 
751      dynamic_cast<CoinWarmStartBasis *>(ws->clone()) ;
752    int numberRowsAtContinuous = model->numberRowsAtContinuous();
753    int iFull = numberRowsAtContinuous+model->currentNumberCuts()+
754      numberNewCuts;
755    //int numberArtificialsNow = iFull;
756    //int maxBasisLength = ((iFull+15)>>4)+((numberColumns+15)>>4);
757    //printf("l %d full %d\n",maxBasisLength,iFull);
758    if (expanded) 
759      expanded->resize(iFull,numberColumns);
760#ifdef CBC_CHECK_BASIS
761    printf("Before expansion: orig %d, old %d, new %d, current %d\n",
762           numberRowsAtContinuous,numberOldActiveCuts,numberNewCuts,
763           model->currentNumberCuts()) ;
764    ws->print();
765#endif
766/*
767  Now fill in the expanded basis. Any indices beyond nPartial must
768  be cuts created while processing this node --- they can be copied directly
769  into the expanded basis. From nPartial down, pull the status of active cuts
770  from ws, interleaving with a B entry for the deactivated (loose) cuts.
771*/
772    int numberDropped = model->currentNumberCuts()-numberOldActiveCuts;
773    int iCompact=iFull-numberDropped;
774    CbcCountRowCut ** cut = model->addedCuts();
775    int nPartial = model->currentNumberCuts()+numberRowsAtContinuous;
776    iFull--;
777    for (;iFull>=nPartial;iFull--) {
778      CoinWarmStartBasis::Status status = ws->getArtifStatus(--iCompact);
779      //assert (status != CoinWarmStartBasis::basic); // may be permanent cut
780      expanded->setArtifStatus(iFull,status);
781    }
782    for (;iFull>=numberRowsAtContinuous;iFull--) {
783      if (cut[iFull-numberRowsAtContinuous]) {
784        CoinWarmStartBasis::Status status = ws->getArtifStatus(--iCompact);
785        // If no cut generator being used then we may have basic variables
786        //if (model->getMaximumCutPasses()&&
787        //  status == CoinWarmStartBasis::basic)
788        //printf("cut basic\n");
789        expanded->setArtifStatus(iFull,status);
790      } else {
791        expanded->setArtifStatus(iFull,CoinWarmStartBasis::basic);
792      }
793    }
794#ifdef CBC_CHECK_BASIS
795    printf("Expanded basis\n");
796    expanded->print() ;
797    printf("Diffing against\n") ;
798    lastws->print() ;
799#endif   
800/*
801  Now that we have two bases in proper positional correspondence, creating
802  the actual diff is dead easy.
803*/
804
805    CoinWarmStartDiff *basisDiff = expanded->generateDiff(lastws) ;
806/*
807  Diff the bound vectors. It's assumed the number of structural variables is
808  not changing. Assuming that branching objects all involve integer variables,
809  we should see at least one bound change as a consequence of processing this
810  subproblem. Different types of branching objects could break this assertion.
811  Not true at all - we have not applied current branch - JJF.
812*/
813    double *boundChanges = new double [2*numberColumns] ;
814    int *variables = new int [2*numberColumns] ;
815    int numberChangedBounds=0;
816    for (i=0;i<numberColumns;i++) {
817      if (lower[i]!=lastLower[i]) {
818        variables[numberChangedBounds]=i;
819        boundChanges[numberChangedBounds++]=lower[i];
820      }
821      if (upper[i]!=lastUpper[i]) {
822        variables[numberChangedBounds]=i|0x80000000;
823        boundChanges[numberChangedBounds++]=upper[i];
824      }
825#ifdef CBC_DEBUG
826      if (lower[i]!=lastLower[i])
827        printf("lower on %d changed from %g to %g\n",
828               i,lastLower[i],lower[i]);
829      if (upper[i]!=lastUpper[i])
830        printf("upper on %d changed from %g to %g\n",
831               i,lastUpper[i],upper[i]);
832#endif
833    }
834#ifdef CBC_DEBUG
835    printf("%d changed bounds\n",numberChangedBounds) ;
836#endif
837    //if (lastNode->branchingObject()->boundBranch())
838    //assert (numberChangedBounds);
839/*
840  Hand the lot over to the CbcPartialNodeInfo constructor, then clean up and
841  return.
842*/
843    if (!strategy)
844      nodeInfo_ =
845        new CbcPartialNodeInfo(lastNode->nodeInfo_,this,numberChangedBounds,
846                               variables,boundChanges,basisDiff) ;
847    else
848      nodeInfo_ = strategy->partialNodeInfo(model, lastNode->nodeInfo_,this,numberChangedBounds,
849                               variables,boundChanges,basisDiff) ;
850    delete basisDiff ;
851    delete [] boundChanges;
852    delete [] variables;
853    delete expanded ;
854    delete ws;
855  }
856  // Set node number
857  nodeInfo_->setNodeNumber(model->getNodeCount2());
858}
859
860/*
861  The routine scans through the object list of the model looking for objects
862  that indicate infeasibility. It tests each object using strong branching
863  and selects the one with the least objective degradation.  A corresponding
864  branching object is left attached to lastNode.
865
866  If strong branching is disabled, a candidate object is chosen essentially
867  at random (whatever object ends up in pos'n 0 of the candidate array).
868
869  If a branching candidate is found to be monotone, bounds are set to fix the
870  variable and the routine immediately returns (the caller is expected to
871  reoptimize).
872
873  If a branching candidate is found to result in infeasibility in both
874  directions, the routine immediately returns an indication of infeasibility.
875
876  Returns:  0   both branch directions are feasible
877           -1   branching variable is monotone
878           -2   infeasible
879
880  Original comments:
881    Here could go cuts etc etc
882    For now just fix on objective from strong branching.
883*/
884
885int CbcNode::chooseBranch (CbcModel *model, CbcNode *lastNode,int numberPassesLeft)
886
887{ if (lastNode)
888    depth_ = lastNode->depth_+1;
889  else
890    depth_ = 0;
891  delete branch_;
892  branch_=NULL;
893  OsiSolverInterface * solver = model->solver();
894  double saveObjectiveValue = solver->getObjValue();
895  double objectiveValue = CoinMax(solver->getObjSense()*saveObjectiveValue,objectiveValue_);
896  const double * lower = solver->getColLower();
897  const double * upper = solver->getColUpper();
898  // See what user thinks
899  int anyAction=model->problemFeasibility()->feasible(model,0);
900  if (anyAction) {
901    // will return -2 if infeasible , 0 if treat as integer
902    return anyAction-1;
903  }
904  double integerTolerance = 
905    model->getDblParam(CbcModel::CbcIntegerTolerance);
906  int i;
907  bool beforeSolution = model->getSolutionCount()==0;
908  int numberStrong=model->numberStrong();
909  // switch off strong if hotstart
910  if (model->hotstartSolution())
911    numberStrong=0;
912  int numberStrongDone=0;
913  int numberUnfinished=0;
914  int numberStrongInfeasible=0;
915  int numberStrongIterations=0;
916  int saveNumberStrong=numberStrong;
917  int numberObjects = model->numberObjects();
918  bool checkFeasibility = numberObjects>model->numberIntegers();
919  int maximumStrong = CoinMax(CoinMin(model->numberStrong(),numberObjects),1);
920  int numberColumns = model->getNumCols();
921  double * saveUpper = new double[numberColumns];
922  double * saveLower = new double[numberColumns];
923
924  // Save solution in case heuristics need good solution later
925 
926  double * saveSolution = new double[numberColumns];
927  memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
928  model->reserveCurrentSolution(saveSolution);
929  /*
930    Get a branching decision object. Use the default decision criteria unless
931    the user has loaded a decision method into the model.
932  */
933  CbcBranchDecision *decision = model->branchingMethod();
934  if (!decision)
935    decision = new CbcBranchDefaultDecision();
936
937  CbcStrongInfo * choice = new CbcStrongInfo[maximumStrong];
938  for (i=0;i<numberColumns;i++) {
939    saveLower[i] = lower[i];
940    saveUpper[i] = upper[i];
941  }
942  // May go round twice if strong branching fixes all local candidates
943  bool finished=false;
944  double estimatedDegradation=0.0; 
945  while(!finished) {
946    finished=true;
947    // Some objects may compute an estimate of best solution from here
948    estimatedDegradation=0.0; 
949    //int numberIntegerInfeasibilities=0; // without odd ones
950    numberStrongDone=0;
951    numberUnfinished=0;
952    numberStrongInfeasible=0;
953    numberStrongIterations=0;
954   
955    // We may go round this loop twice (only if we think we have solution)
956    for (int iPass=0;iPass<2;iPass++) {
957     
958      // compute current state
959      //int numberObjectInfeasibilities; // just odd ones
960      //model->feasibleSolution(
961      //                      numberIntegerInfeasibilities,
962      //                      numberObjectInfeasibilities);
963      const double * hotstartSolution = model->hotstartSolution();
964      const int * hotstartPriorities = model->hotstartPriorities();
965     
966      // Some objects may compute an estimate of best solution from here
967      estimatedDegradation=0.0; 
968      numberUnsatisfied_ = 0;
969      int bestPriority=INT_MAX;
970      /*
971        Scan for branching objects that indicate infeasibility. Choose the best
972        maximumStrong candidates, using priority as the first criteria, then
973        integer infeasibility.
974       
975        The algorithm is to fill the choice array with a set of good candidates (by
976        infeasibility) with priority bestPriority.  Finding a candidate with
977        priority better (less) than bestPriority flushes the choice array. (This
978        serves as initialization when the first candidate is found.)
979       
980        A new candidate is added to choices only if its infeasibility exceeds the
981        current max infeasibility (mostAway). When a candidate is added, it
982        replaces the candidate with the smallest infeasibility (tracked by
983        iSmallest).
984      */
985      int iSmallest = 0;
986      double mostAway = 1.0e-100;
987      for (i = 0 ; i < maximumStrong ; i++)
988        choice[i].possibleBranch = NULL ;
989      numberStrong=0;
990      bool canDoOneHot=false;
991      for (i=0;i<numberObjects;i++) {
992        CbcObject * object = model->modifiableObject(i);
993        int preferredWay;
994        double infeasibility = object->infeasibility(preferredWay);
995        int priorityLevel = object->priority();
996        if (hotstartSolution) {
997          // we are doing hot start
998          const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object);
999          if (thisOne) {
1000            int iColumn = thisOne->modelSequence();
1001            bool canDoThisHot=true;
1002            double targetValue = hotstartSolution[iColumn];
1003            if (saveUpper[iColumn]>saveLower[iColumn]) {
1004              double value = saveSolution[iColumn];
1005              if (hotstartPriorities)
1006                priorityLevel=hotstartPriorities[iColumn]; 
1007              //double originalLower = thisOne->originalLower();
1008              //double originalUpper = thisOne->originalUpper();
1009              // switch off if not possible
1010              if (targetValue>=saveLower[iColumn]&&targetValue<=saveUpper[iColumn]) {
1011                /* priority outranks rest always if negative
1012                   otherwise can be downgraded if at correct level.
1013                   Infeasibility may be increased to choose 1.0 values first.
1014                   choose one near wanted value
1015                */
1016                if (fabs(value-targetValue)>integerTolerance) {
1017                  infeasibility = 1.0-fabs(value-targetValue);
1018                  if (targetValue==1.0)
1019                    infeasibility += 1.0;
1020                  if (value>targetValue) {
1021                    preferredWay=-1;
1022                  } else {
1023                    preferredWay=1;
1024                  }
1025                  priorityLevel = CoinAbs(priorityLevel);
1026                } else if (priorityLevel<0) {
1027                  priorityLevel = CoinAbs(priorityLevel);
1028                  if (targetValue==saveLower[iColumn]) {
1029                    infeasibility = integerTolerance+1.0e-12;
1030                    preferredWay=-1;
1031                  } else if (targetValue==saveUpper[iColumn]) {
1032                    infeasibility = integerTolerance+1.0e-12;
1033                    preferredWay=1;
1034                  } else {
1035                    // can't
1036                    priorityLevel += 10000000;
1037                    canDoThisHot=false;
1038                  }
1039                } else {
1040                  priorityLevel += 10000000;
1041                  canDoThisHot=false;
1042                }
1043              } else {
1044                // switch off if not possible
1045                canDoThisHot=false;
1046              }
1047              if (canDoThisHot)
1048                canDoOneHot=true;
1049            } else if (targetValue<saveLower[iColumn]||targetValue>saveUpper[iColumn]) {
1050            }
1051          } else {
1052            priorityLevel += 10000000;
1053          }
1054        }
1055        if (infeasibility) {
1056          // Increase estimated degradation to solution
1057          estimatedDegradation += CoinMin(object->upEstimate(),object->downEstimate());
1058          numberUnsatisfied_++;
1059          // Better priority? Flush choices.
1060          if (priorityLevel<bestPriority) {
1061            int j;
1062            iSmallest=0;
1063            for (j=0;j<maximumStrong;j++) {
1064              choice[j].upMovement=0.0;
1065              delete choice[j].possibleBranch;
1066              choice[j].possibleBranch=NULL;
1067            }
1068            bestPriority = priorityLevel;
1069            mostAway=1.0e-100;
1070            numberStrong=0;
1071          } else if (priorityLevel>bestPriority) {
1072            continue;
1073          }
1074          // Check for suitability based on infeasibility.
1075          if (infeasibility>mostAway) {
1076            //add to list
1077            choice[iSmallest].upMovement=infeasibility;
1078            delete choice[iSmallest].possibleBranch;
1079            choice[iSmallest].possibleBranch=object->createBranch(preferredWay);
1080            numberStrong = CoinMax(numberStrong,iSmallest+1);
1081            // Save which object it was
1082            choice[iSmallest].objectNumber=i;
1083            int j;
1084            iSmallest=-1;
1085            mostAway = 1.0e50;
1086            for (j=0;j<maximumStrong;j++) {
1087              if (choice[j].upMovement<mostAway) {
1088                mostAway=choice[j].upMovement;
1089                iSmallest=j;
1090              }
1091            }
1092          }
1093        }
1094      }
1095      if (!canDoOneHot&&hotstartSolution) {
1096        // switch off as not possible
1097        hotstartSolution=NULL;
1098        model->setHotstartSolution(NULL,NULL);
1099      }
1100      if (numberUnsatisfied_) {
1101        // some infeasibilities - go to next steps
1102        break;
1103      } else if (!iPass) {
1104        // looks like a solution - get paranoid
1105        bool roundAgain=false;
1106        // get basis
1107        CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart());
1108        if (!ws)
1109          break;
1110        for (i=0;i<numberColumns;i++) {
1111          double value = saveSolution[i];
1112          if (value<lower[i]) {
1113            saveSolution[i]=lower[i];
1114            roundAgain=true;
1115            ws->setStructStatus(i,CoinWarmStartBasis::atLowerBound);
1116          } else if (value>upper[i]) {
1117            saveSolution[i]=upper[i];
1118            roundAgain=true;
1119            ws->setStructStatus(i,CoinWarmStartBasis::atUpperBound);
1120          } 
1121        }
1122        if (roundAgain&&saveNumberStrong) {
1123          // restore basis
1124          solver->setWarmStart(ws);
1125          delete ws;
1126          solver->resolve();
1127          memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
1128          model->reserveCurrentSolution(saveSolution);
1129          if (!solver->isProvenOptimal()) {
1130            // infeasible
1131            anyAction=-2;
1132            break;
1133          }
1134        } else {
1135          delete ws;
1136          break;
1137        }
1138      }
1139    }
1140    /* Some solvers can do the strong branching calculations faster if
1141       they do them all at once.  At present only Clp does for ordinary
1142       integers but I think this coding would be easy to modify
1143    */
1144    bool allNormal=true; // to say if we can do fast strong branching
1145    // Say which one will be best
1146    int bestChoice=0;
1147    double worstInfeasibility=0.0;
1148    for (i=0;i<numberStrong;i++) {
1149      choice[i].numIntInfeasUp = numberUnsatisfied_;
1150      choice[i].numIntInfeasDown = numberUnsatisfied_;
1151      choice[i].fix=0; // say not fixed
1152      if (!dynamic_cast <const CbcSimpleInteger *> (model->object(choice[i].objectNumber)))
1153        allNormal=false; // Something odd so lets skip clever fast branching
1154      if ( !model->object(choice[i].objectNumber)->boundBranch())
1155        numberStrong=0; // switch off
1156      if ( choice[i].possibleBranch->numberBranches()>2)
1157        numberStrong=0; // switch off
1158      // Do best choice in case switched off
1159      if (choice[i].upMovement>worstInfeasibility) {
1160        worstInfeasibility=choice[i].upMovement;
1161        bestChoice=i;
1162      }
1163    }
1164    // If we have hit max time don't do strong branching
1165    bool hitMaxTime = ( CoinCpuTime()-model->getDblParam(CbcModel::CbcStartSeconds) > 
1166                        model->getDblParam(CbcModel::CbcMaximumSeconds));
1167    // also give up if we are looping round too much
1168    if (hitMaxTime||numberPassesLeft<=0)
1169      numberStrong=0;
1170    /*
1171      Is strong branching enabled? If so, set up and do it. Otherwise, we'll
1172      fall through to simple branching.
1173     
1174      Setup for strong branching involves saving the current basis (for restoration
1175      afterwards) and setting up for hot starts.
1176    */
1177    if (numberStrong&&saveNumberStrong) {
1178     
1179      bool solveAll=false; // set true to say look at all even if some fixed (experiment)
1180      solveAll=true;
1181      // worth trying if too many times
1182      // Save basis
1183      CoinWarmStart * ws = solver->getWarmStart();
1184      // save limit
1185      int saveLimit;
1186      solver->getIntParam(OsiMaxNumIterationHotStart,saveLimit);
1187      if (beforeSolution&&saveLimit<100)
1188        solver->setIntParam(OsiMaxNumIterationHotStart,100); // go to end
1189#     ifdef COIN_HAS_CLP     
1190      /* If we are doing all strong branching in one go then we create new arrays
1191         to store information.  If clp NULL then doing old way.
1192         Going down -
1193         outputSolution[2*i] is final solution.
1194         outputStuff[2*i] is status (0 - finished, 1 infeas, other unknown
1195         outputStuff[2*i+numberStrong] is number iterations
1196         On entry newUpper[i] is new upper bound, on exit obj change
1197         Going up -
1198         outputSolution[2*i+1] is final solution.
1199         outputStuff[2*i+1] is status (0 - finished, 1 infeas, other unknown
1200         outputStuff[2*i+1+numberStrong] is number iterations
1201       On entry newLower[i] is new lower bound, on exit obj change
1202      */
1203      OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
1204      ClpSimplex * clp=NULL;
1205      double * newLower = NULL;
1206      double * newUpper = NULL;
1207      double ** outputSolution=NULL;
1208      int * outputStuff=NULL;
1209      // Go back to normal way if user wants it
1210      if (osiclp&&(osiclp->specialOptions()&16)!=0&&osiclp->specialOptions()>0)
1211        allNormal=false;
1212      if (osiclp&&!allNormal) {
1213        // say do fast
1214        int easy=1;
1215        osiclp->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
1216      }
1217      if (osiclp&& allNormal) {
1218        clp = osiclp->getModelPtr();
1219        // Clp - do a different way
1220        newLower = new double[numberStrong];
1221        newUpper = new double[numberStrong];
1222        outputSolution = new double * [2*numberStrong];
1223        outputStuff = new int [4*numberStrong];
1224        int * which = new int[numberStrong];
1225        int startFinishOptions;
1226        int specialOptions = osiclp->specialOptions();
1227        int clpOptions = clp->specialOptions();
1228        int returnCode=0;
1229#define CRUNCH
1230#ifdef CRUNCH
1231        // Crunch down problem
1232        int numberRows = clp->numberRows();
1233        // Use dual region
1234        double * rhs = clp->dualRowSolution();
1235        int * whichRow = new int[3*numberRows];
1236        int * whichColumn = new int[2*numberColumns];
1237        int nBound;
1238        ClpSimplex * small = ((ClpSimplexOther *) clp)->crunch(rhs,whichRow,whichColumn,nBound,true);
1239        if (!small) {
1240          anyAction=-2;
1241          //printf("XXXX Inf by inspection\n");
1242          delete [] whichColumn;
1243          whichColumn=NULL;
1244          delete [] whichRow;
1245          whichRow=NULL;
1246          break;
1247        } else {
1248          clp = small;
1249        }
1250#else
1251        int saveLogLevel = clp->logLevel();
1252        int saveMaxIts = clp->maximumIterations();
1253#endif
1254        clp->setLogLevel(0);
1255        if((specialOptions&1)==0) {
1256          startFinishOptions=0;
1257          clp->setSpecialOptions(clpOptions|(64|1024));
1258        } else {
1259          startFinishOptions=1+2+4;
1260          //startFinishOptions=1+4; // for moment re-factorize
1261          if((specialOptions&4)==0) 
1262            clp->setSpecialOptions(clpOptions|(64|128|512|1024|4096));
1263          else
1264            clp->setSpecialOptions(clpOptions|(64|128|512|1024|2048|4096));
1265        }
1266        // User may want to clean up before strong branching
1267        if ((clp->specialOptions()&32)!=0) {
1268          clp->primal(1);
1269          if (clp->numberIterations())
1270            model->messageHandler()->message(CBC_ITERATE_STRONG,model->messages())
1271              << clp->numberIterations()
1272              <<CoinMessageEol;
1273        }
1274        clp->setMaximumIterations(saveLimit);
1275#ifdef CRUNCH
1276        int * backColumn = whichColumn+numberColumns;
1277#endif
1278        for (i=0;i<numberStrong;i++) {
1279          int iObject = choice[i].objectNumber;
1280          const CbcObject * object = model->object(iObject);
1281          const CbcSimpleInteger * simple = dynamic_cast <const CbcSimpleInteger *> (object);
1282          int iSequence = simple->modelSequence();
1283          newLower[i]= ceil(saveSolution[iSequence]);
1284          newUpper[i]= floor(saveSolution[iSequence]);
1285#ifdef CRUNCH
1286          iSequence = backColumn[iSequence];
1287          assert (iSequence>=0);
1288#endif
1289          which[i]=iSequence;
1290          outputSolution[2*i]= new double [numberColumns];
1291          outputSolution[2*i+1]= new double [numberColumns];
1292        }
1293        //clp->writeMps("bad");
1294        returnCode=clp->strongBranching(numberStrong,which,
1295                                            newLower, newUpper,outputSolution,
1296                                            outputStuff,outputStuff+2*numberStrong,!solveAll,false,
1297                                            startFinishOptions);
1298#ifndef CRUNCH
1299        clp->setSpecialOptions(clpOptions); // restore
1300        clp->setMaximumIterations(saveMaxIts);
1301        clp->setLogLevel(saveLogLevel);
1302#endif
1303        if (returnCode==-2) {
1304          // bad factorization!!!
1305          // Doing normal way
1306          // Mark hot start
1307          solver->markHotStart();
1308          clp = NULL;
1309        } else {
1310#ifdef CRUNCH
1311          // extract solution
1312          //bool checkSol=true;
1313          for (i=0;i<numberStrong;i++) {
1314            int iObject = choice[i].objectNumber;
1315            const CbcObject * object = model->object(iObject);
1316            const CbcSimpleInteger * simple = dynamic_cast <const CbcSimpleInteger *> (object);
1317            int iSequence = simple->modelSequence();
1318            which[i]=iSequence;
1319            double * sol = outputSolution[2*i];
1320            double * sol2 = outputSolution[2*i+1];
1321            //bool x=true;
1322            //bool x2=true;
1323            for (int iColumn=numberColumns-1;iColumn>=0;iColumn--) {
1324              int jColumn = backColumn[iColumn];
1325              if (jColumn>=0) {
1326                sol[iColumn]=sol[jColumn];
1327                sol2[iColumn]=sol2[jColumn];
1328              } else {
1329                sol[iColumn]=saveSolution[iColumn];
1330                sol2[iColumn]=saveSolution[iColumn];
1331              }
1332            }
1333          }
1334#endif
1335        }
1336#ifdef CRUNCH
1337        delete [] whichColumn;
1338        delete [] whichRow;
1339        delete small;
1340#endif
1341        delete [] which;
1342      } else {
1343        // Doing normal way
1344        // Mark hot start
1345        solver->markHotStart();
1346      }
1347#     else      /* COIN_HAS_CLP */
1348
1349      OsiSolverInterface *clp = NULL ;
1350      double **outputSolution = NULL ;
1351      int *outputStuff = NULL ;
1352      double * newLower = NULL ;
1353      double * newUpper = NULL ;
1354
1355      solver->markHotStart();
1356
1357#     endif     /* COIN_HAS_CLP */
1358      /*
1359        Open a loop to do the strong branching LPs. For each candidate variable,
1360        solve an LP with the variable forced down, then up. If a direction turns
1361        out to be infeasible or monotonic (i.e., over the dual objective cutoff),
1362        force the objective change to be big (1.0e100). If we determine the problem
1363        is infeasible, or find a monotone variable, escape the loop.
1364       
1365        TODO: The `restore bounds' part might be better encapsulated as an
1366        unbranch() method. Branching objects more exotic than simple integers
1367        or cliques might not restrict themselves to variable bounds.
1368
1369        TODO: Virtuous solvers invalidate the current solution (or give bogus
1370        results :-) when the bounds are changed out from under them. So we
1371        need to do all the work associated with finding a new solution before
1372        restoring the bounds.
1373      */
1374      for (i = 0 ; i < numberStrong ; i++)
1375        { double objectiveChange ;
1376        double newObjectiveValue=1.0e100;
1377        // status is 0 finished, 1 infeasible and other
1378        int iStatus;
1379        /*
1380          Try the down direction first. (Specify the initial branching alternative as
1381          down with a call to way(-1). Each subsequent call to branch() performs the
1382          specified branch and advances the branch object state to the next branch
1383          alternative.)
1384        */
1385        if (!clp) {
1386          choice[i].possibleBranch->way(-1) ;
1387          choice[i].possibleBranch->branch() ;
1388          bool feasible=true;
1389          if (checkFeasibility) {
1390            // check branching did not make infeasible
1391            int iColumn;
1392            int numberColumns = solver->getNumCols();
1393            const double * columnLower = solver->getColLower();
1394            const double * columnUpper = solver->getColUpper();
1395            for (iColumn= 0;iColumn<numberColumns;iColumn++) {
1396              if (columnLower[iColumn]>columnUpper[iColumn]+1.0e-5)
1397                feasible=false;
1398            }
1399          }
1400          if (feasible) {
1401            solver->solveFromHotStart() ;
1402            numberStrongDone++;
1403            numberStrongIterations += solver->getIterationCount();
1404            /*
1405              We now have an estimate of objective degradation that we can use for strong
1406              branching. If we're over the cutoff, the variable is monotone up.
1407              If we actually made it to optimality, check for a solution, and if we have
1408              a good one, call setBestSolution to process it. Note that this may reduce the
1409              cutoff, so we check again to see if we can declare this variable monotone.
1410            */
1411            if (solver->isProvenOptimal())
1412              iStatus=0; // optimal
1413            else if (solver->isIterationLimitReached()
1414                     &&!solver->isDualObjectiveLimitReached())
1415              iStatus=2; // unknown
1416            else
1417              iStatus=1; // infeasible
1418            newObjectiveValue = solver->getObjSense()*solver->getObjValue();
1419            choice[i].numItersDown = solver->getIterationCount();
1420          } else {
1421            iStatus=1; // infeasible
1422            newObjectiveValue = 1.0e100;
1423            choice[i].numItersDown = 0;
1424          }
1425        } else {
1426          iStatus = outputStuff[2*i];
1427          choice[i].numItersDown = outputStuff[2*numberStrong+2*i];
1428          numberStrongDone++;
1429          numberStrongIterations += choice[i].numItersDown;
1430          newObjectiveValue = objectiveValue+newUpper[i];
1431          solver->setColSolution(outputSolution[2*i]);
1432        }
1433        objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
1434        if (!iStatus) {
1435          choice[i].finishedDown = true ;
1436          if (newObjectiveValue>=model->getCutoff()) {
1437            objectiveChange = 1.0e100; // say infeasible
1438            numberStrongInfeasible++;
1439          } else {
1440            // See if integer solution
1441            if (model->feasibleSolution(choice[i].numIntInfeasDown,
1442                                        choice[i].numObjInfeasDown)
1443                &&model->problemFeasibility()->feasible(model,-1)>=0) {
1444              model->setBestSolution(CBC_STRONGSOL,
1445                                     newObjectiveValue,
1446                                     solver->getColSolution()) ;
1447              // only needed for odd solvers
1448              newObjectiveValue = solver->getObjSense()*solver->getObjValue();
1449              objectiveChange = CoinMax(newObjectiveValue-objectiveValue_,0.0) ;
1450              model->setLastHeuristic(NULL);
1451              model->incrementUsed(solver->getColSolution());
1452              if (newObjectiveValue >= model->getCutoff()) {    //  *new* cutoff
1453                objectiveChange = 1.0e100 ;
1454                numberStrongInfeasible++;
1455              }
1456            }
1457          }
1458        } else if (iStatus==1) {
1459          objectiveChange = 1.0e100 ;
1460          numberStrongInfeasible++;
1461        } else {
1462          // Can't say much as we did not finish
1463          choice[i].finishedDown = false ;
1464          numberUnfinished++;
1465        }
1466        choice[i].downMovement = objectiveChange ;
1467       
1468        // restore bounds
1469        if (!clp)
1470          { for (int j=0;j<numberColumns;j++) {
1471            if (saveLower[j] != lower[j])
1472              solver->setColLower(j,saveLower[j]);
1473            if (saveUpper[j] != upper[j])
1474              solver->setColUpper(j,saveUpper[j]);
1475          }
1476          }
1477        //printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
1478        //     choice[i].objectNumber,iStatus,newObjectiveValue,choice[i].numItersDown,
1479        //     choice[i].downMovement,choice[i].finishedDown,choice[i].numIntInfeasDown,
1480        //     choice[i].numObjInfeasDown);
1481       
1482        // repeat the whole exercise, forcing the variable up
1483        if (!clp) {
1484          bool feasible=true;
1485          // If odd branching then maybe just one possibility
1486          if(choice[i].possibleBranch->numberBranchesLeft()>0) {
1487            choice[i].possibleBranch->branch();
1488            if (checkFeasibility) {
1489              // check branching did not make infeasible
1490              int iColumn;
1491              int numberColumns = solver->getNumCols();
1492              const double * columnLower = solver->getColLower();
1493              const double * columnUpper = solver->getColUpper();
1494              for (iColumn= 0;iColumn<numberColumns;iColumn++) {
1495                if (columnLower[iColumn]>columnUpper[iColumn]+1.0e-5)
1496                  feasible=false;
1497              }
1498            }
1499          } else {
1500            // second branch infeasible
1501            feasible=false;
1502          }
1503          if (feasible) {
1504            solver->solveFromHotStart() ;
1505            numberStrongDone++;
1506            numberStrongIterations += solver->getIterationCount();
1507            /*
1508              We now have an estimate of objective degradation that we can use for strong
1509              branching. If we're over the cutoff, the variable is monotone up.
1510              If we actually made it to optimality, check for a solution, and if we have
1511              a good one, call setBestSolution to process it. Note that this may reduce the
1512              cutoff, so we check again to see if we can declare this variable monotone.
1513            */
1514            if (solver->isProvenOptimal())
1515              iStatus=0; // optimal
1516            else if (solver->isIterationLimitReached()
1517                     &&!solver->isDualObjectiveLimitReached())
1518              iStatus=2; // unknown
1519            else
1520              iStatus=1; // infeasible
1521            newObjectiveValue = solver->getObjSense()*solver->getObjValue();
1522            choice[i].numItersUp = solver->getIterationCount();
1523          } else {
1524            iStatus=1; // infeasible
1525            newObjectiveValue = 1.0e100;
1526            choice[i].numItersDown = 0;
1527          }
1528        } else {
1529          iStatus = outputStuff[2*i+1];
1530          choice[i].numItersUp = outputStuff[2*numberStrong+2*i+1];
1531          numberStrongDone++;
1532          numberStrongIterations += choice[i].numItersUp;
1533          newObjectiveValue = objectiveValue+newLower[i];
1534          solver->setColSolution(outputSolution[2*i+1]);
1535        }
1536        objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
1537        if (!iStatus) {
1538          choice[i].finishedUp = true ;
1539          if (newObjectiveValue>=model->getCutoff()) {
1540            objectiveChange = 1.0e100; // say infeasible
1541            numberStrongInfeasible++;
1542          } else {
1543            // See if integer solution
1544            if (model->feasibleSolution(choice[i].numIntInfeasUp,
1545                                        choice[i].numObjInfeasUp)
1546                &&model->problemFeasibility()->feasible(model,-1)>=0) {
1547              model->setBestSolution(CBC_STRONGSOL,
1548                                     newObjectiveValue,
1549                                     solver->getColSolution()) ;
1550              // only needed for odd solvers
1551              newObjectiveValue = solver->getObjSense()*solver->getObjValue();
1552              objectiveChange = CoinMax(newObjectiveValue-objectiveValue_,0.0) ;
1553              model->setLastHeuristic(NULL);
1554              model->incrementUsed(solver->getColSolution());
1555              if (newObjectiveValue >= model->getCutoff()) {    //  *new* cutoff
1556                objectiveChange = 1.0e100 ;
1557                numberStrongInfeasible++;
1558              }
1559            }
1560          }
1561        } else if (iStatus==1) {
1562          objectiveChange = 1.0e100 ;
1563          numberStrongInfeasible++;
1564        } else {
1565          // Can't say much as we did not finish
1566          choice[i].finishedUp = false ;
1567          numberUnfinished++;
1568        }
1569        choice[i].upMovement = objectiveChange ;
1570       
1571        // restore bounds
1572        if (!clp)
1573          { for (int j=0;j<numberColumns;j++) {
1574            if (saveLower[j] != lower[j])
1575              solver->setColLower(j,saveLower[j]);
1576            if (saveUpper[j] != upper[j])
1577              solver->setColUpper(j,saveUpper[j]);
1578          }
1579          }
1580       
1581        //printf("Up on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
1582        //     choice[i].objectNumber,iStatus,newObjectiveValue,choice[i].numItersUp,
1583        //     choice[i].upMovement,choice[i].finishedUp,choice[i].numIntInfeasUp,
1584        //     choice[i].numObjInfeasUp);
1585       
1586        /*
1587          End of evaluation for this candidate variable. Possibilities are:
1588          * Both sides below cutoff; this variable is a candidate for branching.
1589          * Both sides infeasible or above the objective cutoff: no further action
1590          here. Break from the evaluation loop and assume the node will be purged
1591          by the caller.
1592          * One side below cutoff: Install the branch (i.e., fix the variable). Break
1593          from the evaluation loop and assume the node will be reoptimised by the
1594          caller.
1595        */
1596        // reset
1597        choice[i].possibleBranch->resetNumberBranchesLeft();
1598        if (choice[i].upMovement<1.0e100) {
1599          if(choice[i].downMovement<1.0e100) {
1600            // feasible - no action
1601          } else {
1602            // up feasible, down infeasible
1603            anyAction=-1;
1604            //printf("Down infeasible for choice %d sequence %d\n",i,
1605            // model->object(choice[i].objectNumber)->columnNumber());
1606            if (!solveAll) {
1607              choice[i].possibleBranch->way(1);
1608              choice[i].possibleBranch->branch();
1609              break;
1610            } else {
1611              choice[i].fix=1;
1612            }
1613          }
1614        } else {
1615          if(choice[i].downMovement<1.0e100) {
1616            // down feasible, up infeasible
1617            anyAction=-1;
1618            //printf("Up infeasible for choice %d sequence %d\n",i,
1619            // model->object(choice[i].objectNumber)->columnNumber());
1620            if (!solveAll) {
1621              choice[i].possibleBranch->way(-1);
1622              choice[i].possibleBranch->branch();
1623              break;
1624            } else {
1625              choice[i].fix=-1;
1626            }
1627          } else {
1628            // neither side feasible
1629            anyAction=-2;
1630            //printf("Both infeasible for choice %d sequence %d\n",i,
1631            // model->object(choice[i].objectNumber)->columnNumber());
1632            break;
1633          }
1634        }
1635        bool hitMaxTime = ( CoinCpuTime()-model->getDblParam(CbcModel::CbcStartSeconds) > 
1636                            model->getDblParam(CbcModel::CbcMaximumSeconds));
1637        if (hitMaxTime) {
1638          numberStrong=i+1;
1639          break;
1640        }
1641        }
1642      if (!clp) {
1643        // Delete the snapshot
1644        solver->unmarkHotStart();
1645      } else {
1646        delete [] newLower;
1647        delete [] newUpper;
1648        delete [] outputStuff;
1649        int i;
1650        for (i=0;i<2*numberStrong;i++)
1651          delete [] outputSolution[i];
1652        delete [] outputSolution;
1653      }
1654      solver->setIntParam(OsiMaxNumIterationHotStart,saveLimit);
1655      // restore basis
1656      solver->setWarmStart(ws);
1657      // Unless infeasible we will carry on
1658      // But we could fix anyway
1659      if (anyAction==-1&&solveAll) {
1660        // apply and take off
1661        for (i = 0 ; i < numberStrong ; i++) {
1662          if (choice[i].fix) {
1663            choice[i].possibleBranch->way(choice[i].fix) ;
1664            choice[i].possibleBranch->branch() ;
1665          }
1666        }
1667        bool feasible=true;
1668        if (checkFeasibility) {
1669          // check branching did not make infeasible
1670          int iColumn;
1671          int numberColumns = solver->getNumCols();
1672          const double * columnLower = solver->getColLower();
1673          const double * columnUpper = solver->getColUpper();
1674          for (iColumn= 0;iColumn<numberColumns;iColumn++) {
1675            if (columnLower[iColumn]>columnUpper[iColumn]+1.0e-5)
1676              feasible=false;
1677          }
1678        }
1679        if (feasible) {
1680          // can do quick optimality check
1681          int easy=2;
1682          solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
1683          solver->resolve() ;
1684          solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
1685          feasible = solver->isProvenOptimal();
1686        }
1687        if (feasible) {
1688          memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
1689          model->reserveCurrentSolution(saveSolution);
1690          memcpy(saveLower,solver->getColLower(),numberColumns*sizeof(double));
1691          memcpy(saveUpper,solver->getColUpper(),numberColumns*sizeof(double));
1692          // Clean up all candidates whih are fixed
1693          int numberLeft=0;
1694          for (i = 0 ; i < numberStrong ; i++) {
1695            CbcStrongInfo thisChoice = choice[i];
1696            choice[i].possibleBranch=NULL;
1697            const CbcObject * object = model->object(thisChoice.objectNumber);
1698            int preferredWay;
1699            double infeasibility = object->infeasibility(preferredWay);
1700            if (!infeasibility) {
1701              // take out
1702              delete thisChoice.possibleBranch;
1703            } else {
1704              choice[numberLeft++]=thisChoice;
1705            }
1706          }
1707          numberStrong=numberLeft;
1708          for (;i<maximumStrong;i++) {
1709            delete choice[i].possibleBranch;
1710            choice[i].possibleBranch=NULL;
1711          }
1712          // If all fixed then round again
1713          if (!numberLeft) {
1714            finished=false;
1715            numberStrong=0;
1716            saveNumberStrong=0;
1717            maximumStrong=1;
1718          } else {
1719            anyAction=0;
1720          }
1721          // If these two uncommented then different action
1722          anyAction=-1;
1723          finished=true;
1724          //printf("some fixed but continuing %d left\n",numberLeft);
1725        } else {
1726          anyAction=-2; // say infeasible
1727        }
1728      }
1729      delete ws;
1730      int numberNodes = model->getNodeCount();
1731      // update number of strong iterations etc
1732      model->incrementStrongInfo(numberStrongDone,numberStrongIterations,
1733                                 anyAction==-2 ? 0:numberStrongInfeasible,anyAction==-2);
1734     
1735      /*
1736        anyAction >= 0 indicates that strong branching didn't produce any monotone
1737        variables. Sift through the candidates for the best one.
1738       
1739        QUERY: Setting numberNodes looks to be a distributed noop. numberNodes is
1740        local to this code block. Perhaps should be numberNodes_ from model?
1741        Unclear what this calculation is doing.
1742      */
1743      if (anyAction>=0) {
1744       
1745        // get average cost per iteration and assume stopped ones
1746        // would stop after 50% more iterations at average cost??? !!! ???
1747        double averageCostPerIteration=0.0;
1748        double totalNumberIterations=1.0;
1749        int smallestNumberInfeasibilities=INT_MAX;
1750        for (i=0;i<numberStrong;i++) {
1751          totalNumberIterations += choice[i].numItersDown +
1752            choice[i].numItersUp ;
1753          averageCostPerIteration += choice[i].downMovement +
1754            choice[i].upMovement;
1755          smallestNumberInfeasibilities= 
1756            CoinMin(CoinMin(choice[i].numIntInfeasDown ,
1757                            choice[i].numIntInfeasUp ),
1758                    smallestNumberInfeasibilities);
1759        }
1760        //if (smallestNumberInfeasibilities>=numberIntegerInfeasibilities)
1761        //numberNodes=1000000; // switch off search for better solution
1762        numberNodes=1000000; // switch off anyway
1763        averageCostPerIteration /= totalNumberIterations;
1764        // all feasible - choose best bet
1765       
1766        // New method does all at once so it can be more sophisticated
1767        // in deciding how to balance actions.
1768        // But it does need arrays
1769        double * changeUp = new double [numberStrong];
1770        int * numberInfeasibilitiesUp = new int [numberStrong];
1771        double * changeDown = new double [numberStrong];
1772        int * numberInfeasibilitiesDown = new int [numberStrong];
1773        CbcBranchingObject ** objects = new CbcBranchingObject * [ numberStrong];
1774        for (i = 0 ; i < numberStrong ; i++) {
1775          int iColumn = choice[i].possibleBranch->variable() ;
1776          model->messageHandler()->message(CBC_STRONG,model->messages())
1777            << i << iColumn
1778            <<choice[i].downMovement<<choice[i].numIntInfeasDown
1779            <<choice[i].upMovement<<choice[i].numIntInfeasUp
1780            <<choice[i].possibleBranch->value()
1781            <<CoinMessageEol;
1782          changeUp[i]=choice[i].upMovement;
1783          numberInfeasibilitiesUp[i] = choice[i].numIntInfeasUp;
1784          changeDown[i]=choice[i].downMovement;
1785          numberInfeasibilitiesDown[i] = choice[i].numIntInfeasDown;
1786          objects[i] = choice[i].possibleBranch;
1787        }
1788        int whichObject = decision->bestBranch(objects,numberStrong,numberUnsatisfied_,
1789                                               changeUp,numberInfeasibilitiesUp,
1790                                               changeDown,numberInfeasibilitiesDown,
1791                                               objectiveValue_);
1792        // move branching object and make sure it will not be deleted
1793        if (whichObject>=0) {
1794          branch_ = objects[whichObject];
1795          if (model->messageHandler()->logLevel()>3) 
1796            printf("Choosing column %d\n",choice[whichObject].possibleBranch->variable()) ;
1797          choice[whichObject].possibleBranch=NULL;
1798        }
1799        delete [] changeUp;
1800        delete [] numberInfeasibilitiesUp;
1801        delete [] changeDown;
1802        delete [] numberInfeasibilitiesDown;
1803        delete [] objects;
1804      }
1805#     ifdef COIN_HAS_CLP
1806      if (osiclp&&!allNormal) {
1807        // back to normal
1808        osiclp->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
1809      }
1810#     endif
1811    }
1812    /*
1813      Simple branching. Probably just one, but we may have got here
1814      because of an odd branch e.g. a cut
1815    */
1816    else {
1817      // not strong
1818      // C) create branching object
1819      branch_ = choice[bestChoice].possibleBranch;
1820      choice[bestChoice].possibleBranch=NULL;
1821    }
1822  }
1823  // Set guessed solution value
1824  guessedObjectiveValue_ = objectiveValue_+estimatedDegradation;
1825/*
1826  Cleanup, then we're outta here.
1827*/
1828  if (!model->branchingMethod())
1829    delete decision;
1830   
1831  for (i=0;i<maximumStrong;i++)
1832    delete choice[i].possibleBranch;
1833  delete [] choice;
1834  delete [] saveLower;
1835  delete [] saveUpper;
1836 
1837  // restore solution
1838  solver->setColSolution(saveSolution);
1839  delete [] saveSolution;
1840  return anyAction;
1841}
1842
1843/*
1844  Version for dynamic pseudo costs.
1845
1846  **** For now just return if anything odd
1847  later allow even if odd
1848
1849  The routine scans through the object list of the model looking for objects
1850  that indicate infeasibility. It tests each object using strong branching
1851  and selects the one with the least objective degradation.  A corresponding
1852  branching object is left attached to lastNode.
1853  This version gives preference in evaluation to variables which
1854  have not been evaluated many times.  It also uses numberStrong
1855  to say give up if last few tries have not changed incumbent.
1856  See Achterberg, Koch and Martin.
1857
1858  If strong branching is disabled, a candidate object is chosen essentially
1859  at random (whatever object ends up in pos'n 0 of the candidate array).
1860
1861  If a branching candidate is found to be monotone, bounds are set to fix the
1862  variable and the routine immediately returns (the caller is expected to
1863  reoptimize).
1864
1865  If a branching candidate is found to result in infeasibility in both
1866  directions, the routine immediately returns an indication of infeasibility.
1867
1868  Returns:  0   both branch directions are feasible
1869           -1   branching variable is monotone
1870           -2   infeasible
1871           -3   Use another method
1872
1873           For now just fix on objective from strong branching.
1874*/
1875
1876int CbcNode::chooseDynamicBranch (CbcModel *model, CbcNode *lastNode,
1877                                  OsiSolverBranch * & branches,int numberPassesLeft)
1878
1879{ if (lastNode)
1880    depth_ = lastNode->depth_+1;
1881  else
1882    depth_ = 0;
1883  delete branch_;
1884  branch_=NULL;
1885  OsiSolverInterface * solver = model->solver();
1886  // get information on solver type
1887  const OsiAuxInfo * auxInfo = solver->getAuxiliaryInfo();
1888  const OsiBabSolver * auxiliaryInfo = dynamic_cast<const OsiBabSolver *> (auxInfo);
1889  //assert(objectiveValue_ == solver->getObjSense()*solver->getObjValue());
1890  double cutoff =model->getCutoff();
1891  double distanceToCutoff=cutoff-objectiveValue_;
1892  const double * lower = solver->getColLower();
1893  const double * upper = solver->getColUpper();
1894  // See what user thinks
1895  int anyAction=model->problemFeasibility()->feasible(model,0);
1896  if (anyAction) {
1897    // will return -2 if infeasible , 0 if treat as integer
1898    return anyAction-1;
1899  }
1900  int i;
1901  int saveStateOfSearch = model->stateOfSearch();
1902  int numberStrong=model->numberStrong();
1903  if (!auxiliaryInfo->warmStart())
1904    numberStrong=0;
1905  // But make more likely to get out after some times
1906  int changeStrategy=numberStrong;
1907  double changeFactor=1.0;
1908  // Use minimum of this and one stored in objects
1909  //int numberBeforeTrust = model->numberBeforeTrust();
1910  int numberObjects = model->numberObjects();
1911  bool checkFeasibility = numberObjects>model->numberIntegers();
1912  // For now return if not simple
1913  if (checkFeasibility)
1914    return -3;
1915  // Return if doing hot start (in BAB sense)
1916  if (model->hotstartSolution()) 
1917    return -3;
1918#define RANGING
1919#ifdef RANGING
1920  // Pass number
1921  int kPass=0;
1922  int numberRows = solver->getNumRows();
1923#endif
1924  int numberColumns = model->getNumCols();
1925  double * saveUpper = new double[numberColumns];
1926  double * saveLower = new double[numberColumns];
1927
1928  // Save solution in case heuristics need good solution later
1929 
1930  double * saveSolution = new double[numberColumns];
1931  memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
1932  model->reserveCurrentSolution(saveSolution);
1933  /*
1934    Get a branching decision object. Use the default dynamic decision criteria unless
1935    the user has loaded a decision method into the model.
1936  */
1937  CbcBranchDecision *decision = model->branchingMethod();
1938  if (!decision)
1939    decision = new CbcBranchDynamicDecision();
1940  int numberMini=0;
1941  int xPen=0;
1942  int xMark=0;
1943  for (i=0;i<numberColumns;i++) {
1944    saveLower[i] = lower[i];
1945    saveUpper[i] = upper[i];
1946  }
1947  // Get arrays to sort
1948  double * sort = new double[numberObjects];
1949  int * whichObject = new int[numberObjects];
1950  int * objectMark = new int[2*numberObjects+1];
1951  // Arrays with movements
1952  double * upEstimate = new double[numberObjects];
1953  double * downEstimate = new double[numberObjects];
1954  CbcStrongInfo * fixObject = new CbcStrongInfo[numberObjects];
1955  double estimatedDegradation=0.0; 
1956  int numberNodes=model->getNodeCount();
1957  int numberBeforeTrust = model->numberBeforeTrust();
1958  int numberPenalties = model->numberPenalties();
1959  if (numberBeforeTrust>=1000000) {
1960    numberBeforeTrust = numberBeforeTrust % 1000000;
1961    numberPenalties=0;
1962  } else if (numberBeforeTrust<0) {
1963    numberPenalties=numberColumns;
1964    numberBeforeTrust=0;
1965  }
1966  // May go round twice if strong branching fixes all local candidates
1967  bool finished=false;
1968  int numberToFix=0;
1969# ifdef COIN_HAS_CLP
1970  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
1971  int saveClpOptions=0;
1972  if (osiclp) {
1973    // for faster hot start
1974    saveClpOptions = osiclp->specialOptions();
1975    osiclp->setSpecialOptions(saveClpOptions|1024);
1976  }
1977# else
1978  OsiSolverInterface *osiclp = 0 ;
1979# endif
1980  int saveSearchStrategy2 = model->searchStrategy();
1981  if (saveSearchStrategy2<999) {
1982    // Get average up and down costs
1983    double averageUp=0.0;
1984    double averageDown=0.0;
1985    {
1986      int numberUp=0;
1987      int numberDown=0;
1988      int i;
1989      for ( i=0;i<numberObjects;i++) {
1990        CbcObject * object = model->modifiableObject(i);
1991        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
1992          dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
1993        assert(dynamicObject);
1994        if (dynamicObject->numberTimesUp()) {
1995          numberUp++;
1996          averageUp += dynamicObject->upDynamicPseudoCost();
1997        }
1998        if (dynamicObject->numberTimesDown()) {
1999          numberDown++;
2000          averageDown += dynamicObject->downDynamicPseudoCost();
2001        }
2002      }
2003      if (numberUp) 
2004        averageUp /= (double) numberUp;
2005      else
2006        averageUp=1.0;
2007      if (numberDown) 
2008        averageDown /= (double) numberDown;
2009      else
2010        averageDown=1.0;
2011      for ( i=0;i<numberObjects;i++) {
2012        CbcObject * object = model->modifiableObject(i);
2013        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2014          dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2015        assert(dynamicObject);
2016        if (!dynamicObject->numberTimesUp()) 
2017          dynamicObject->setUpDynamicPseudoCost(averageUp);
2018      if (!dynamicObject->numberTimesDown()) 
2019        dynamicObject->setDownDynamicPseudoCost(averageDown);
2020      }
2021    }
2022  } else if (saveSearchStrategy2<1999) {
2023    // pseudo shadow prices
2024    model->pseudoShadow(NULL,NULL);
2025  } else if (saveSearchStrategy2<2999) {
2026    // leave old ones
2027  } else if (saveSearchStrategy2<3999) {
2028    // pseudo shadow prices at root
2029    if (!numberNodes)
2030      model->pseudoShadow(NULL,NULL);
2031  } else {
2032    abort();
2033  }
2034  if (saveSearchStrategy2>=0)
2035    saveSearchStrategy2 = saveSearchStrategy2 % 1000;
2036  if (saveSearchStrategy2==999)
2037    saveSearchStrategy2=-1;
2038  int px[4]={-1,-1,-1,-1};
2039  int saveSearchStrategy = saveSearchStrategy2<99 ? saveSearchStrategy2 : saveSearchStrategy2-100;
2040  bool newWay = saveSearchStrategy2>98;
2041  int numberNotTrusted=0;
2042  int numberStrongDone;
2043  int numberUnfinished;
2044  int numberStrongInfeasible;
2045  int numberStrongIterations;
2046  while(!finished) {
2047    finished=true;
2048    decision->initialize(model);
2049    // Some objects may compute an estimate of best solution from here
2050    estimatedDegradation=0.0; 
2051    numberToFix=0;
2052    int numberIntegerInfeasibilities=0; // without odd ones
2053    int numberToDo=0;
2054    int iBestNot=-1;
2055    int iBestGot=-1;
2056    double best=0.0;
2057    numberNotTrusted=0;
2058    numberStrongDone=0;
2059    numberUnfinished=0;
2060    numberStrongInfeasible=0;
2061    numberStrongIterations=0;
2062    int * which = objectMark+numberObjects+1;
2063    int neededPenalties;
2064    // We may go round this loop three times (only if we think we have solution)
2065    for (int iPass=0;iPass<3;iPass++) {
2066     
2067      // compute current state
2068      int numberObjectInfeasibilities; // just odd ones
2069      model->feasibleSolution(
2070                              numberIntegerInfeasibilities,
2071                              numberObjectInfeasibilities);
2072     
2073      // Some objects may compute an estimate of best solution from here
2074      estimatedDegradation=0.0; 
2075      numberUnsatisfied_ = 0;
2076      int bestPriority=INT_MAX;
2077      /*
2078        Scan for branching objects that indicate infeasibility. Choose candidates
2079        using priority as the first criteria, then integer infeasibility.
2080       
2081        The algorithm is to fill the array with a set of good candidates (by
2082        infeasibility) with priority bestPriority.  Finding a candidate with
2083        priority better (less) than bestPriority flushes the choice array. (This
2084        serves as initialization when the first candidate is found.)
2085       
2086      */
2087      numberToDo=0;
2088      neededPenalties=0;
2089      iBestNot=-1;
2090      double bestNot=0.0;
2091      iBestGot=-1;
2092      best=0.0;
2093#define PRINT_STUFF -1
2094      for (i=0;i<numberObjects;i++) {
2095        CbcObject * object = model->modifiableObject(i);
2096        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2097          dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2098        assert(dynamicObject);
2099        int preferredWay;
2100        double infeasibility = object->infeasibility(preferredWay);
2101        int priorityLevel = object->priority();
2102#define ZERO_ONE 0
2103#define ZERO_FAKE 1.0e20;
2104#if ZERO_ONE==1
2105        // branch on 0-1 first (temp)
2106        if (fabs(saveSolution[dynamicObject->columnNumber()])<1.0)
2107          priorityLevel--;
2108#endif
2109#if ZERO_ONE==2
2110        if (fabs(saveSolution[dynamicObject->columnNumber()])<1.0)
2111          infeasibility *= ZERO_FAKE;
2112#endif
2113        if (infeasibility) {
2114          int iColumn = dynamicObject->columnNumber();
2115          double gap = saveUpper[iColumn]-saveLower[iColumn];
2116          // Give precedence to ones with gap of 1.0
2117          assert(gap>0.0);
2118          infeasibility /= CoinMin(gap,100.0);
2119          if (!depth_&&false) {
2120            // try closest to 0.5
2121            double part =saveSolution[iColumn]-floor(saveSolution[iColumn]);
2122            infeasibility = fabs(0.5-part);
2123          }
2124          bool gotDown=false;
2125          int numberThisDown = dynamicObject->numberTimesDown();
2126          if (numberThisDown>=numberBeforeTrust)
2127            gotDown=true;
2128          bool gotUp=false;
2129          int numberThisUp = dynamicObject->numberTimesUp();
2130          if (numberThisUp>=numberBeforeTrust)
2131            gotUp=true;
2132          if ((numberNodes%PRINT_STUFF)==0&&PRINT_STUFF>0)
2133            printf("%d down %d %g up %d %g - infeas %g\n",
2134                   i,numberThisDown,object->downEstimate(),numberThisUp,object->upEstimate(),
2135                   infeasibility);
2136          // Increase estimated degradation to solution
2137          estimatedDegradation += CoinMin(object->upEstimate(),object->downEstimate());
2138          downEstimate[i]=object->downEstimate();
2139          upEstimate[i]=object->upEstimate();
2140          numberUnsatisfied_++;
2141          // Better priority? Flush choices.
2142          if (priorityLevel<bestPriority) {
2143            numberToDo=0;
2144            bestPriority = priorityLevel;
2145            iBestGot=-1;
2146            best=0.0;
2147            numberNotTrusted=0;
2148          } else if (priorityLevel>bestPriority) {
2149            continue;
2150          }
2151          if (!gotUp||!gotDown)
2152            numberNotTrusted++;
2153          // Check for suitability based on infeasibility.
2154          if ((gotDown&&gotUp)&&numberStrong>0) {
2155            sort[numberToDo]=-infeasibility;
2156            if (infeasibility>best) {
2157              best=infeasibility;
2158              iBestGot=numberToDo;
2159            }
2160          } else {
2161            objectMark[neededPenalties]=numberToDo;
2162            which[neededPenalties++]=dynamicObject->columnNumber();
2163            int iColumn = dynamicObject->columnNumber();
2164            double part =saveSolution[iColumn]-floor(saveSolution[iColumn]);
2165            sort[numberToDo]=-10.0*infeasibility;
2166            if (!(numberThisUp+numberThisDown))
2167              sort[numberToDo] *= 100.0; // make even more likely
2168            if (1.0-fabs(part-0.5)>bestNot) {
2169              iBestNot=numberToDo;
2170              bestNot = 1.0-fabs(part-0.5);
2171            }
2172          }
2173          whichObject[numberToDo++]=i;
2174        } else {
2175          // for debug
2176          downEstimate[i]=-1.0;
2177          upEstimate[i]=-1.0;
2178        }
2179      }
2180      if (numberUnsatisfied_) {
2181        // some infeasibilities - go to next steps
2182        break;
2183      } else if (!iPass) {
2184        // may just need resolve
2185        solver->resolve();
2186        memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
2187        model->reserveCurrentSolution(saveSolution);
2188        if (!solver->isProvenOptimal()) {
2189          // infeasible
2190          anyAction=-2;
2191          break;
2192        }
2193      } else if (iPass==1) {
2194        // looks like a solution - get paranoid
2195        bool roundAgain=false;
2196        // get basis
2197        CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart());
2198        if (!ws)
2199          break;
2200        double tolerance;
2201        solver->getDblParam(OsiPrimalTolerance,tolerance);
2202        for (i=0;i<numberColumns;i++) {
2203          double value = saveSolution[i];
2204          if (value<lower[i]-tolerance) {
2205            saveSolution[i]=lower[i];
2206            roundAgain=true;
2207            ws->setStructStatus(i,CoinWarmStartBasis::atLowerBound);
2208          } else if (value>upper[i]+tolerance) {
2209            saveSolution[i]=upper[i];
2210            roundAgain=true;
2211            ws->setStructStatus(i,CoinWarmStartBasis::atUpperBound);
2212          } 
2213        }
2214        if (roundAgain) {
2215          // restore basis
2216          solver->setWarmStart(ws);
2217          solver->setColSolution(saveSolution);
2218          delete ws;
2219          bool takeHint;
2220          OsiHintStrength strength;
2221          solver->getHintParam(OsiDoDualInResolve,takeHint,strength);
2222          solver->setHintParam(OsiDoDualInResolve,false,OsiHintDo) ;
2223          solver->resolve();
2224          solver->setHintParam(OsiDoDualInResolve,takeHint,strength) ;
2225          memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
2226          model->reserveCurrentSolution(saveSolution);
2227          if (!solver->isProvenOptimal()) {
2228            // infeasible
2229            anyAction=-2;
2230            break;
2231          }
2232        } else {
2233          delete ws;
2234          break;
2235        }
2236      }
2237    }
2238    if (anyAction==-2) {
2239      break;
2240    }
2241    bool solveAll=false; // set true to say look at all even if some fixed (experiment)
2242    solveAll=true;
2243    // skip if solution
2244    if (!numberUnsatisfied_)
2245      break;
2246    //bool skipAll = (numberBeforeTrust>20&&numberNodes>20000&&numberNotTrusted==0);
2247    bool skipAll = numberNotTrusted==0;
2248    bool doneHotStart=false;
2249#ifndef CBC_WEAK_STRONG
2250    if ((numberNodes%20)==0||(model->specialOptions()&8)!=0)
2251      skipAll=false;
2252#endif
2253    int searchStrategy = saveSearchStrategy>=0 ? (saveSearchStrategy%10) : -1;
2254    if (!newWay) {
2255    // 10 up always use %10, 20 up as 10 and allow penalties
2256    // But adjust depending on ratio of iterations
2257    if (searchStrategy>0&&saveSearchStrategy<10) {
2258      if (numberBeforeTrust>=5&&numberBeforeTrust<=10) {
2259        if (searchStrategy!=2) {
2260          int numberIterations = model->getIterationCount();
2261          int numberStrongIterations = model->numberStrongIterations();
2262          if (numberStrongIterations>numberIterations+10000) {
2263            searchStrategy=2;
2264            //skipAll=true;
2265          } else if (numberStrongIterations*4+1000<numberIterations||depth_<5) {
2266            searchStrategy=3;
2267            skipAll=false;
2268          }
2269        } else {
2270          skipAll=true;
2271        }
2272      }
2273    }
2274    } else {
2275    // But adjust depending on ratio of iterations
2276    if (saveSearchStrategy<0) {
2277      // unset
2278      if ((numberNodes%20)==0||(model->specialOptions()&8)!=0) {
2279        // Do numberStrong
2280        searchStrategy=3;
2281      } else if (depth_<5) {
2282        // Do numberStrong
2283        searchStrategy=2;
2284      } else {
2285        int numberIterations = model->getIterationCount();
2286        int numberStrongIterations = model->numberStrongIterations();
2287        int numberRows = solver->getNumRows();
2288        if (numberStrongIterations>numberIterations+CoinMin(10000,10*numberRows)) {
2289          // off
2290          searchStrategy=0;
2291        } else if (numberStrongIterations*4+1000<numberIterations) {
2292          // Do numberStrong if not trusted
2293          searchStrategy=2;
2294        } else {
2295          searchStrategy=1;
2296        }
2297      }
2298    }
2299    if (searchStrategy<3&&(!numberNotTrusted||!searchStrategy))
2300      skipAll=true;
2301    else
2302      skipAll=false;
2303    }
2304    // worth trying if too many times
2305    // Save basis
2306    CoinWarmStart * ws = NULL;
2307    // save limit
2308    int saveLimit=0;
2309    solver->getIntParam(OsiMaxNumIterationHotStart,saveLimit);
2310    if (!skipAll) {
2311      ws = solver->getWarmStart();
2312      int limit=100;
2313#if 0
2314      int averageBranchIterations = model->getIterationCount()/(model->getNodeCount()+1);
2315      if (numberNodes)
2316        limit = CoinMin(CoinMax(limit,2*averageBranchIterations),500);
2317      else
2318        limit = 500;
2319#endif
2320      if ((!saveStateOfSearch||searchStrategy>3)&&saveLimit<limit&&saveLimit==100)
2321        solver->setIntParam(OsiMaxNumIterationHotStart,limit); 
2322    }
2323    // Say which one will be best
2324    int whichChoice=0;
2325    int bestChoice;
2326    if (iBestGot>=0)
2327      bestChoice=iBestGot;
2328    else
2329      bestChoice=iBestNot;
2330    assert (bestChoice>=0);
2331    // If we have hit max time don't do strong branching
2332    bool hitMaxTime = ( CoinCpuTime()-model->getDblParam(CbcModel::CbcStartSeconds) > 
2333                        model->getDblParam(CbcModel::CbcMaximumSeconds));
2334    // also give up if we are looping round too much
2335    if (hitMaxTime||numberPassesLeft<=0||(!numberNotTrusted&&false)) {
2336      int iObject = whichObject[bestChoice];
2337      CbcObject * object = model->modifiableObject(iObject);
2338      int preferredWay;
2339      object->infeasibility(preferredWay);
2340      branch_=object->createBranch(preferredWay);
2341      branch_->way(preferredWay);
2342      delete ws;
2343      ws=NULL;
2344      break;
2345    } else {
2346      // say do fast
2347      int easy=1;
2348      if (!skipAll)
2349        solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
2350      int iDo;
2351#ifdef RANGING
2352      if ((skipAll&&numberBeforeTrust&&saveSearchStrategy<20)||saveSearchStrategy<10)
2353        numberPenalties=0;
2354      {
2355        // off penalties if too much
2356        double needed = neededPenalties;
2357        needed *= numberRows;
2358        if (needed>1.0e6&&numberNodes&&saveSearchStrategy<20) {
2359          numberPenalties=0;
2360          neededPenalties=0;
2361        }
2362      }
2363#     ifdef COIN_HAS_CLP
2364      if (osiclp&&numberPenalties&&neededPenalties) {
2365        xPen += neededPenalties;
2366        which--;
2367        which[0]=neededPenalties;
2368        osiclp->passInRanges(which);
2369        // Mark hot start and get ranges
2370        if (kPass) {
2371          // until can work out why solution can go funny
2372          int save = osiclp->specialOptions();
2373          osiclp->setSpecialOptions(save|256);
2374          solver->markHotStart();
2375          osiclp->setSpecialOptions(save);
2376        } else {
2377          solver->markHotStart();
2378        }
2379        assert (auxiliaryInfo->warmStart());
2380        doneHotStart=true;
2381        xMark++;
2382        kPass++;
2383        osiclp->passInRanges(NULL);
2384        const double * downCost=osiclp->upRange();
2385        const double * upCost=osiclp->downRange();
2386        //printf("numberTodo %d needed %d numberpenalties %d\n",numberToDo,neededPenalties,numberPenalties);
2387        double invTrust = 1.0/((double) numberBeforeTrust);
2388        for (int i=0;i<neededPenalties;i++) {
2389          int j = objectMark[i];
2390          int iObject = whichObject[j];
2391          CbcObject * object = model->modifiableObject(iObject);
2392          CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2393            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2394          int iSequence=dynamicObject->columnNumber();
2395          double value = saveSolution[iSequence];
2396          value -= floor(value);
2397          double upPenalty = CoinMin(upCost[i],1.0e110)*(1.0-value);
2398          double downPenalty = CoinMin(downCost[i],1.0e110)*value;
2399          if (!numberBeforeTrust) {
2400            // override
2401            downEstimate[iObject]=downPenalty;
2402            upEstimate[iObject]=upPenalty;
2403          } else {
2404            int numberThisDown = dynamicObject->numberTimesDown();
2405            if (numberThisDown<numberBeforeTrust) {
2406              double fraction = ((double) numberThisDown)*invTrust;
2407              downEstimate[iObject] = fraction*downEstimate[iObject]+(1.0-fraction)*downPenalty;
2408            }
2409            int numberThisUp = dynamicObject->numberTimesUp();
2410            if (numberThisUp<numberBeforeTrust) {
2411              double fraction = ((double) numberThisUp)*invTrust;
2412              upEstimate[iObject] = fraction*upEstimate[iObject]+(1.0-fraction)*upPenalty;
2413            }
2414          }
2415          sort[j] = - CoinMin(downEstimate[iObject],upEstimate[iObject]);
2416#ifdef CBC_WEAK_STRONG
2417          sort[j] -= 1.0e10; // make more likely to be chosen
2418#endif
2419          //if ((numberNodes%PRINT_STUFF)==0&&PRINT_STUFF>0)
2420          if (!numberNodes)
2421            printf("%d pen down ps %g -> %g up ps %g -> %g\n",
2422                   iObject,downCost[i],downPenalty,upCost[i],upPenalty);
2423        }
2424      } else
2425#     endif     /* COIN_HAS_CLP */
2426      {
2427        if (!skipAll) {
2428          // Mark hot start
2429          solver->markHotStart();
2430          doneHotStart=true;
2431          assert (auxiliaryInfo->warmStart());
2432          xMark++;
2433          //if (solver->isProvenPrimalInfeasible())
2434          //printf("**** Hot start says node infeasible\n");
2435        }
2436        // make sure best will be first
2437        if (iBestGot>=0)
2438          sort[iBestGot]=-1.0e120;
2439      }
2440#else           /* RANGING */
2441      if (!skipAll) {
2442        // Mark hot start
2443        doneHotStart=true;
2444        assert (auxiliaryInfo->warmStart());
2445        solver->markHotStart();
2446        xMark++;
2447      }
2448      // make sure best will be first
2449      if (iBestGot>=0)
2450        sort[iBestGot]=-COIN_DBL_MAX;
2451#endif          /* RANGING */
2452      // Actions 0 - exit for repeat, 1 resolve and try old choice,2 exit for continue
2453#define ACTION 0
2454#if ACTION<2
2455      if (anyAction)
2456        numberToDo=0; // skip as we will be trying again
2457#endif
2458      // Sort
2459      CoinSort_2(sort,sort+numberToDo,whichObject);
2460      // Change in objective opposite infeasible
2461      double worstFeasible=0.0;
2462      // Just first if strong off
2463      if (!numberStrong)
2464        numberToDo=CoinMin(numberToDo,1);
2465      iDo=0;
2466      int saveLimit2;
2467      solver->getIntParam(OsiMaxNumIterationHotStart,saveLimit2);
2468      bool doQuickly = false; // numberToDo>2*numberStrong;
2469      //printf("todo %d, strong %d\n",numberToDo,numberStrong);
2470      int numberTest=numberNotTrusted>0 ? numberStrong : (numberStrong+1)/2;
2471      int numberTest2 = 2*numberStrong;
2472      if (!newWay) {
2473      if (searchStrategy==3) {
2474        // Previously decided we need strong
2475        doQuickly=false;
2476        numberTest = numberStrong;
2477        //numberTest2 = 1000000;
2478      }
2479      if (searchStrategy<0||searchStrategy==1)
2480        //numberTest2 = 1000000;
2481#if 0
2482      if (numberBeforeTrust>20&&(numberNodes>20000||(numberNodes>200&&numberNotTrusted==0))) {
2483        if ((numberNodes%20)!=0) {
2484          numberTest=0;
2485          doQuickly=true;
2486        }
2487      }
2488#else
2489      // Try nearly always off
2490      if (searchStrategy<2) {
2491        if ((numberNodes%20)!=0) {
2492          if ((model->specialOptions()&8)==0) {
2493            numberTest=0;
2494            doQuickly=true;
2495          }
2496        } else {
2497          doQuickly=false;
2498          numberTest=2*numberStrong;
2499        }
2500      } else if (searchStrategy!=3) {
2501        doQuickly=true;
2502        numberTest=numberStrong;
2503      }
2504#endif
2505      if (depth_<10&&numberStrong) {
2506        if (searchStrategy!=2) {
2507          doQuickly=false;
2508          if (depth_<7)
2509            numberStrong *=3;
2510          if (!depth_) 
2511            numberStrong=CoinMin(6*numberStrong,numberToDo);
2512          numberTest=numberStrong;
2513        }
2514        model->setStateOfSearch(2); // use min min
2515      }
2516      // could adjust using average iterations per branch
2517      // double average = ((double)model->getIterationCount())/
2518      //((double) model->getNodeCount()+1.0);
2519      // if too many and big then just do 10 its
2520      if (!skipAll&&saveStateOfSearch) {
2521        //if (numberNotTrusted>3*numberStrong&&numberRows>250&&numberColumns>1000&&saveLimit==100)
2522          // off solver->setIntParam(OsiMaxNumIterationHotStart,10);
2523      }
2524      // make negative for test
2525      distanceToCutoff = - distanceToCutoff;
2526      if (numberObjects>-100) {
2527        // larger
2528        distanceToCutoff *= 100.0;
2529      }
2530        distanceToCutoff = -COIN_DBL_MAX;
2531      // Do at least 5 strong
2532      if (numberColumns<1000&&(depth_<15||numberNodes<1000000))
2533        numberTest = CoinMax(numberTest,5);
2534      if ((model->specialOptions()&8)==0) {
2535        if (skipAll) {
2536          numberTest=0;
2537          doQuickly=true;
2538        }
2539      } else {
2540        // do 5 as strong is fixing
2541        numberTest = CoinMax(numberTest,5);
2542      }
2543      } else {
2544      int numberTest=numberNotTrusted>0 ? numberStrong : (numberStrong+1)/2;
2545      int numberTest2 = 2*numberStrong;
2546      if (searchStrategy>=3) {
2547        // Previously decided we need strong
2548        doQuickly=false;
2549        if (depth_<7)
2550          numberStrong *=3;
2551        if (!depth_) 
2552          numberStrong=CoinMin(6*numberStrong,numberToDo);
2553        numberTest = numberStrong;
2554        numberTest2 *= 2;
2555      } else if (searchStrategy==2||(searchStrategy==1&&depth_<6)) {
2556        numberStrong *=2;
2557        if (!depth_) 
2558          numberStrong=CoinMin(2*numberStrong,numberToDo);
2559        numberTest = numberStrong;
2560      } else if (searchStrategy==1&&numberNotTrusted) {
2561        numberTest = numberStrong;
2562      } else {
2563        numberTest=0;
2564        skipAll=true;
2565      }
2566      distanceToCutoff=model->getCutoff()-objectiveValue_;
2567      // make negative for test
2568      distanceToCutoff = - distanceToCutoff;
2569      if (numberObjects>-100) {
2570        // larger
2571        distanceToCutoff *= 100.0;
2572      }
2573      distanceToCutoff = -COIN_DBL_MAX;
2574      if (skipAll) {
2575        numberTest=0;
2576        doQuickly=true;
2577      }
2578      }
2579      px[0]=numberTest;
2580      px[1]=numberTest2;
2581      px[2]= doQuickly ? 1 : -1;
2582      px[3]=numberStrong;
2583      //printf("skipAll %c doQuickly %c numberTest %d numberTest2 %d numberNot %d\n",
2584      //     skipAll ? 'Y' : 'N',doQuickly ? 'Y' : 'N',numberTest,numberTest2,numberNotTrusted);
2585      // See if we want mini tree
2586      bool wantMiniTree=false;
2587      if (model->sizeMiniTree()&&depth_>7&&saveStateOfSearch>0)
2588        wantMiniTree=true;
2589      numberMini=0;
2590      for ( iDo=0;iDo<numberToDo;iDo++) {
2591        CbcStrongInfo choice;
2592        int iObject = whichObject[iDo];
2593        CbcObject * object = model->modifiableObject(iObject);
2594        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2595          dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2596        int iColumn = dynamicObject->columnNumber();
2597        int preferredWay;
2598        object->infeasibility(preferredWay);
2599        choice.possibleBranch=object->createBranch(preferredWay);
2600        // Save which object it was
2601        choice.objectNumber=iObject;
2602        choice.numIntInfeasUp = numberUnsatisfied_;
2603        choice.numIntInfeasDown = numberUnsatisfied_;
2604        choice.upMovement = upEstimate[iObject];
2605        choice.downMovement = downEstimate[iObject];
2606        assert (choice.upMovement>=0.0);
2607        assert (choice.downMovement>=0.0);
2608        choice.fix=0; // say not fixed
2609        // see if can skip strong branching
2610        int canSkip = choice.possibleBranch->fillStrongInfo(choice);
2611        if (!newWay) {
2612        if (!doQuickly||(numberTest>0&&searchStrategy!=2))
2613          canSkip=0;
2614        } else {
2615        if (skipAll)
2616          canSkip=1;
2617        else if (numberTest>0&&searchStrategy>=3)
2618          canSkip=0;
2619        }
2620        if (!numberBeforeTrust) {
2621          canSkip=1;
2622        }
2623        if (sort[iDo]<distanceToCutoff)
2624          canSkip=0;
2625        if (((numberTest2<=0&&numberTest<=0)||skipAll)&&sort[iDo]>distanceToCutoff) {
2626          canSkip=1; // always skip
2627          if (iDo>20) {
2628            delete choice.possibleBranch;
2629            choice.possibleBranch=NULL;
2630            break; // give up anyway
2631          }
2632        }
2633        if (model->messageHandler()->logLevel()>3&&numberBeforeTrust) 
2634          dynamicObject->print(1,choice.possibleBranch->value());
2635        // was if (!canSkip)
2636        if (newWay)
2637        numberTest2--;
2638        if (!canSkip) {
2639          numberTest--;
2640          if (!newWay)
2641          numberTest2--;
2642          // just do a few
2643          //if (canSkip)
2644          //solver->setIntParam(OsiMaxNumIterationHotStart,10);
2645          double objectiveChange ;
2646          double newObjectiveValue=1.0e100;
2647          int j;
2648          // status is 0 finished, 1 infeasible and other
2649          int iStatus;
2650          /*
2651            Try the down direction first. (Specify the initial branching alternative as
2652            down with a call to way(-1). Each subsequent call to branch() performs the
2653            specified branch and advances the branch object state to the next branch
2654            alternative.)
2655          */
2656          choice.possibleBranch->way(-1) ;
2657          decision->saveBranchingObject( choice.possibleBranch);
2658          choice.possibleBranch->branch() ;
2659          solver->solveFromHotStart() ;
2660          bool needHotStartUpdate=false;
2661          numberStrongDone++;
2662          numberStrongIterations += solver->getIterationCount();
2663          /*
2664            We now have an estimate of objective degradation that we can use for strong
2665            branching. If we're over the cutoff, the variable is monotone up.
2666            If we actually made it to optimality, check for a solution, and if we have
2667            a good one, call setBestSolution to process it. Note that this may reduce the
2668            cutoff, so we check again to see if we can declare this variable monotone.
2669          */
2670          if (solver->isProvenOptimal())
2671            iStatus=0; // optimal
2672          else if (solver->isIterationLimitReached()
2673                   &&!solver->isDualObjectiveLimitReached())
2674            iStatus=2; // unknown
2675          else
2676            iStatus=1; // infeasible
2677          newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2678          choice.numItersDown = solver->getIterationCount();
2679          objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2680          decision->updateInformation( solver,this);
2681          if (!iStatus) {
2682            choice.finishedDown = true ;
2683            if (newObjectiveValue>=cutoff) {
2684              objectiveChange = 1.0e100; // say infeasible
2685              numberStrongInfeasible++;
2686            } else {
2687              // See if integer solution
2688              if (model->feasibleSolution(choice.numIntInfeasDown,
2689                                          choice.numObjInfeasDown)
2690                  &&model->problemFeasibility()->feasible(model,-1)>=0) {
2691                if (auxiliaryInfo->solutionAddsCuts()) {
2692                  needHotStartUpdate=true;
2693                  solver->unmarkHotStart();
2694                }
2695                model->setBestSolution(CBC_STRONGSOL,
2696                                       newObjectiveValue,
2697                                       solver->getColSolution()) ;
2698                if (needHotStartUpdate) {
2699                  solver->resolve();
2700                  newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2701                  objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2702                  model->feasibleSolution(choice.numIntInfeasDown,
2703                                          choice.numObjInfeasDown);
2704                }
2705                model->setLastHeuristic(NULL);
2706                model->incrementUsed(solver->getColSolution());
2707                cutoff =model->getCutoff();
2708                if (newObjectiveValue >= cutoff) {      //  *new* cutoff
2709                  objectiveChange = 1.0e100 ;
2710                  numberStrongInfeasible++;
2711                }
2712              }
2713            }
2714          } else if (iStatus==1) {
2715            objectiveChange = 1.0e100 ;
2716            numberStrongInfeasible++;
2717          } else {
2718            // Can't say much as we did not finish
2719            choice.finishedDown = false ;
2720            numberUnfinished++;
2721          }
2722          choice.downMovement = objectiveChange ;
2723         
2724          // restore bounds
2725          for ( j=0;j<numberColumns;j++) {
2726            if (saveLower[j] != lower[j])
2727              solver->setColLower(j,saveLower[j]);
2728            if (saveUpper[j] != upper[j])
2729              solver->setColUpper(j,saveUpper[j]);
2730          }
2731          if(needHotStartUpdate) {
2732            needHotStartUpdate = false;
2733            solver->resolve();
2734            //we may again have an integer feasible solution
2735            int numberIntegerInfeasibilities;
2736            int numberObjectInfeasibilities;
2737            if (model->feasibleSolution(
2738                                        numberIntegerInfeasibilities,
2739                                        numberObjectInfeasibilities)) {
2740#ifdef BONMIN
2741              //In this case node has become integer feasible, let us exit the loop
2742              std::cout<<"Node has become integer feasible"<<std::endl;
2743              numberUnsatisfied_ = 0;
2744              break;
2745#endif
2746              double objValue = solver->getObjValue();
2747              model->setBestSolution(CBC_STRONGSOL,
2748                                     objValue,
2749                                     solver->getColSolution()) ;
2750              solver->resolve();
2751              cutoff =model->getCutoff();
2752            }
2753            solver->markHotStart();
2754          }
2755          //printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
2756          //printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
2757          //     choice.objectNumber,iStatus,newObjectiveValue,choice.numItersDown,
2758          //     choice.downMovement,choice.finishedDown,choice.numIntInfeasDown,
2759          //     choice.numObjInfeasDown);
2760         
2761          // repeat the whole exercise, forcing the variable up
2762          decision->saveBranchingObject( choice.possibleBranch);
2763          choice.possibleBranch->branch();
2764          solver->solveFromHotStart() ;
2765          numberStrongDone++;
2766          numberStrongIterations += solver->getIterationCount();
2767          /*
2768            We now have an estimate of objective degradation that we can use for strong
2769            branching. If we're over the cutoff, the variable is monotone up.
2770            If we actually made it to optimality, check for a solution, and if we have
2771            a good one, call setBestSolution to process it. Note that this may reduce the
2772            cutoff, so we check again to see if we can declare this variable monotone.
2773          */
2774          if (solver->isProvenOptimal())
2775            iStatus=0; // optimal
2776          else if (solver->isIterationLimitReached()
2777                   &&!solver->isDualObjectiveLimitReached())
2778            iStatus=2; // unknown
2779          else
2780            iStatus=1; // infeasible
2781          newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2782          choice.numItersUp = solver->getIterationCount();
2783          objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2784          decision->updateInformation( solver,this);
2785          if (!iStatus) {
2786            choice.finishedUp = true ;
2787            if (newObjectiveValue>=cutoff) {
2788              objectiveChange = 1.0e100; // say infeasible
2789              numberStrongInfeasible++;
2790            } else {
2791              // See if integer solution
2792              if (model->feasibleSolution(choice.numIntInfeasUp,
2793                                          choice.numObjInfeasUp)
2794                  &&model->problemFeasibility()->feasible(model,-1)>=0) {
2795#ifdef BONMIN
2796                std::cout<<"Node has become integer feasible"<<std::endl;
2797                numberUnsatisfied_ = 0;
2798                break;
2799#endif
2800                if (auxiliaryInfo->solutionAddsCuts()) {
2801                  needHotStartUpdate=true;
2802                  solver->unmarkHotStart();
2803                }
2804                model->setBestSolution(CBC_STRONGSOL,
2805                                       newObjectiveValue,
2806                                       solver->getColSolution()) ;
2807                if (needHotStartUpdate) {
2808                  solver->resolve();
2809                  newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2810                  objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2811                  model->feasibleSolution(choice.numIntInfeasDown,
2812                                          choice.numObjInfeasDown);
2813                }
2814                model->setLastHeuristic(NULL);
2815                model->incrementUsed(solver->getColSolution());
2816                cutoff =model->getCutoff();
2817                if (newObjectiveValue >= cutoff) {      //  *new* cutoff
2818                  objectiveChange = 1.0e100 ;
2819                  numberStrongInfeasible++;
2820                }
2821              }
2822            }
2823          } else if (iStatus==1) {
2824            objectiveChange = 1.0e100 ;
2825            numberStrongInfeasible++;
2826          } else {
2827            // Can't say much as we did not finish
2828            choice.finishedUp = false ;
2829            numberUnfinished++;
2830          }
2831          choice.upMovement = objectiveChange ;
2832         
2833          // restore bounds
2834          for ( j=0;j<numberColumns;j++) {
2835            if (saveLower[j] != lower[j])
2836              solver->setColLower(j,saveLower[j]);
2837            if (saveUpper[j] != upper[j])
2838              solver->setColUpper(j,saveUpper[j]);
2839          }
2840          if(needHotStartUpdate) {
2841            needHotStartUpdate = false;
2842            solver->resolve();
2843            //we may again have an integer feasible solution
2844            int numberIntegerInfeasibilities;
2845            int numberObjectInfeasibilities;
2846            if (model->feasibleSolution(
2847                                        numberIntegerInfeasibilities,
2848                                        numberObjectInfeasibilities)) {
2849              double objValue = solver->getObjValue();
2850              model->setBestSolution(CBC_STRONGSOL,
2851                                     objValue,
2852                                     solver->getColSolution()) ;
2853              solver->resolve();
2854              cutoff =model->getCutoff();
2855            }
2856            solver->markHotStart();
2857          }
2858         
2859          //printf("Up on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
2860          //     choice.objectNumber,iStatus,newObjectiveValue,choice.numItersUp,
2861          //     choice.upMovement,choice.finishedUp,choice.numIntInfeasUp,
2862          //     choice.numObjInfeasUp);
2863        }
2864   
2865        solver->setIntParam(OsiMaxNumIterationHotStart,saveLimit2); 
2866        /*
2867          End of evaluation for this candidate variable. Possibilities are:
2868          * Both sides below cutoff; this variable is a candidate for branching.
2869          * Both sides infeasible or above the objective cutoff: no further action
2870          here. Break from the evaluation loop and assume the node will be purged
2871          by the caller.
2872          * One side below cutoff: Install the branch (i.e., fix the variable). Break
2873          from the evaluation loop and assume the node will be reoptimised by the
2874          caller.
2875        */
2876        // reset
2877        choice.possibleBranch->resetNumberBranchesLeft();
2878        if (choice.upMovement<1.0e100) {
2879          if(choice.downMovement<1.0e100) {
2880            // In case solution coming in was odd
2881            choice.upMovement = CoinMax(0.0,choice.upMovement);
2882            choice.downMovement = CoinMax(0.0,choice.downMovement);
2883#if ZERO_ONE==2
2884            // branch on 0-1 first (temp)
2885            if (fabs(choice.possibleBranch->value())<1.0) {
2886              choice.upMovement *= ZERO_FAKE;
2887              choice.downMovement *= ZERO_FAKE;
2888            }
2889#endif
2890            // feasible - see which best
2891            if (!canSkip) {
2892              if (iColumn==-46) {
2893                printf("sort %g downest %g upest %g ",sort[iDo],downEstimate[iObject],
2894                     upEstimate[iObject]);
2895                printf("downMove %g upMove %g value %g current pseudo %g %g\n",
2896                       choice.downMovement,choice.upMovement,choice.possibleBranch->value(),
2897                       dynamicObject->downDynamicPseudoCost(),dynamicObject->upDynamicPseudoCost());
2898              }
2899              if (model->messageHandler()->logLevel()>3) 
2900                printf("sort %g downest %g upest %g ",sort[iDo],downEstimate[iObject],
2901                     upEstimate[iObject]);
2902              model->messageHandler()->message(CBC_STRONG,model->messages())
2903                << iObject << iColumn
2904                <<choice.downMovement<<choice.numIntInfeasDown
2905                <<choice.upMovement<<choice.numIntInfeasUp
2906                <<choice.possibleBranch->value()
2907                <<CoinMessageEol;
2908            }
2909            //if (!stateOfSearch)
2910            //choice.numIntInfeasDown=99999; // temp fudge
2911            if (wantMiniTree)
2912              decision->setBestCriterion(-1.0);
2913            double bestCriterion = -1.0;
2914            double gap = saveUpper[iColumn]-saveLower[iColumn];
2915            // Give precedence to ones with gap of 1.0
2916            assert(gap>0.0);
2917            double factor = changeFactor/CoinMin(gap,100.0);
2918            int betterWay = decision->betterBranch(choice.possibleBranch,
2919                                                   branch_,
2920                                                   choice.upMovement*factor,
2921                                                   choice.numIntInfeasUp ,
2922                                                   choice.downMovement*factor,
2923                                                   choice.numIntInfeasDown );
2924            if (wantMiniTree) {
2925              double criterion = decision->getBestCriterion();
2926              sort[numberMini]=-criterion;
2927              whichObject[numberMini++]=whichObject[iDo];
2928              assert (betterWay);
2929              if (criterion>bestCriterion) 
2930                bestCriterion=criterion;
2931              else
2932                betterWay=0;
2933            }
2934            if (iDo>=changeStrategy) {
2935              // make less likely
2936              changeStrategy+=numberStrong;
2937              changeFactor *= 0.9;
2938            }
2939            if (betterWay) {
2940              delete branch_;
2941              // C) create branching object
2942              branch_ = choice.possibleBranch;
2943              choice.possibleBranch=NULL;
2944              branch_->way(betterWay);
2945              bestChoice = choice.objectNumber;
2946              whichChoice = iDo;
2947              if (numberStrong<=1) {
2948                delete ws;
2949                ws=NULL;
2950                break;
2951              }
2952            } else {
2953              delete choice.possibleBranch;
2954              choice.possibleBranch=NULL;
2955              if (iDo>=2*numberStrong) {
2956                delete ws;
2957                ws=NULL;
2958                break;
2959              }
2960              if (!dynamicObject||dynamicObject->numberTimesUp()>1) {
2961                if (iDo-whichChoice>=numberStrong) {
2962                  delete choice.possibleBranch;
2963                  choice.possibleBranch=NULL;
2964                  break; // give up
2965                }
2966              } else {
2967                if (iDo-whichChoice>=2*numberStrong) {
2968                  delete ws;
2969                  ws=NULL;
2970                  delete choice.possibleBranch;
2971                  choice.possibleBranch=NULL;
2972                  break; // give up
2973                }
2974              }
2975            }
2976          } else {
2977            // up feasible, down infeasible
2978            anyAction=-1;
2979            worstFeasible = CoinMax(worstFeasible,choice.upMovement);
2980            //printf("Down infeasible for choice %d sequence %d\n",i,
2981            // model->object(choice.objectNumber)->columnNumber());
2982            if (!solveAll) {
2983              choice.possibleBranch->way(1);
2984              choice.possibleBranch->branch();
2985              delete choice.possibleBranch;
2986              choice.possibleBranch=NULL;
2987              delete ws;
2988              ws=NULL;
2989              break;
2990            } else {
2991              choice.fix=1;
2992              fixObject[numberToFix++]=choice;
2993              choice.possibleBranch=NULL;
2994#define FIXNOW
2995#ifdef FIXNOW
2996              double value = ceil(saveSolution[iColumn]);
2997              saveLower[iColumn]=value;
2998              solver->setColLower(iColumn,value);
2999              assert(doneHotStart);
3000              solver->unmarkHotStart();
3001              solver->markHotStart();
3002#endif
3003            }
3004          }
3005        } else {
3006          if(choice.downMovement<1.0e100) {
3007            // down feasible, up infeasible
3008            anyAction=-1;
3009            worstFeasible = CoinMax(worstFeasible,choice.downMovement);
3010            //printf("Up infeasible for choice %d sequence %d\n",i,
3011            // model->object(choice.objectNumber)->columnNumber());
3012            if (!solveAll) {
3013              choice.possibleBranch->way(-1);
3014              choice.possibleBranch->branch();
3015              delete choice.possibleBranch;
3016              choice.possibleBranch=NULL;
3017              delete ws;
3018              ws=NULL;
3019              break;
3020            } else {
3021              choice.fix=-1;
3022              fixObject[numberToFix++]=choice;
3023              choice.possibleBranch=NULL;
3024#ifdef FIXNOW
3025              double value = floor(saveSolution[iColumn]);
3026              saveUpper[iColumn]=value;
3027              solver->setColUpper(iColumn,value);
3028              assert(doneHotStart);
3029              solver->unmarkHotStart();
3030              solver->markHotStart();
3031#endif
3032            }
3033          } else {
3034            // neither side feasible
3035            anyAction=-2;
3036            delete choice.possibleBranch;
3037            choice.possibleBranch=NULL;
3038            //printf("Both infeasible for choice %d sequence %d\n",i,
3039            // model->object(choice.objectNumber)->columnNumber());
3040            delete ws;
3041            ws=NULL;
3042            break;
3043          }
3044        }
3045        // Check max time
3046        hitMaxTime = ( CoinCpuTime()-model->getDblParam(CbcModel::CbcStartSeconds) > 
3047                       model->getDblParam(CbcModel::CbcMaximumSeconds));
3048        if (hitMaxTime) {
3049          // make sure rest are fast
3050          doQuickly=true;
3051          for ( int jDo=iDo+1;jDo<numberToDo;jDo++) {
3052            int iObject = whichObject[iDo];
3053            CbcObject * object = model->modifiableObject(iObject);
3054            CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3055              dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3056            dynamicObject->setNumberBeforeTrust(0);
3057          }
3058          numberTest=0;
3059          distanceToCutoff=-COIN_DBL_MAX;
3060        }
3061        delete choice.possibleBranch;
3062      }
3063      double averageChange = model->sumChangeObjective()/((double) model->getNodeCount());
3064      if (depth_<10||worstFeasible>0.2*averageChange) 
3065        solveAll=false;
3066      if (model->messageHandler()->logLevel()>3||false) { 
3067        if (anyAction==-2)
3068          printf("infeasible\n");
3069        else if(anyAction==-1)
3070          if (!solveAll)
3071            printf("%d fixed\n",numberToFix);
3072          else
3073            printf("%d fixed AND choosing %d iDo %d iChosenWhen %d numberToDo %d\n",numberToFix,bestChoice,
3074                   iDo,whichChoice,numberToDo);
3075        else
3076          printf("choosing %d iDo %d iChosenWhen %d numberToDo %d\n",bestChoice,
3077                 iDo,whichChoice,numberToDo);
3078      }
3079      if (doneHotStart) {
3080        // Delete the snapshot
3081        solver->unmarkHotStart();
3082        // back to normal
3083        solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
3084        // restore basis
3085        solver->setWarmStart(ws);
3086      }
3087      solver->setIntParam(OsiMaxNumIterationHotStart,saveLimit);
3088      // Unless infeasible we will carry on
3089      // But we could fix anyway
3090      if (numberToFix&&!hitMaxTime) {
3091        if (anyAction==-2) {
3092          // take off
3093          for (i = 0 ; i < numberToFix ; i++) {
3094            delete fixObject[i].possibleBranch;
3095          }
3096        } else {
3097          // apply and take off
3098          for (i = 0 ; i < numberToFix ; i++) {
3099#ifndef FIXNOW
3100            fixObject[i].possibleBranch->way(fixObject[i].fix) ;
3101            fixObject[i].possibleBranch->branch() ;
3102#endif
3103            delete fixObject[i].possibleBranch;
3104          }
3105          bool feasible=true;
3106#if ACTION <2
3107          if (solveAll) {
3108            // can do quick optimality check
3109            int easy=2;
3110            solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
3111            solver->resolve() ;
3112            solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
3113            feasible = solver->isProvenOptimal();
3114            if (feasible) {
3115              anyAction=0;
3116              numberMini=0;
3117              memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
3118              model->reserveCurrentSolution(saveSolution);
3119              memcpy(saveLower,solver->getColLower(),numberColumns*sizeof(double));
3120              memcpy(saveUpper,solver->getColUpper(),numberColumns*sizeof(double));
3121              model->setPointers(solver);
3122              // See if candidate still possible
3123              if (branch_) {
3124                const CbcObject * object = model->object(bestChoice);
3125                int preferredWay;
3126                double infeasibility = object->infeasibility(preferredWay);
3127                if (!infeasibility) {
3128                  // take out
3129                  delete branch_;
3130                  branch_=NULL;
3131                } else {
3132                  branch_->way(preferredWay);
3133                }
3134              }
3135            } else {
3136              anyAction=-2;
3137              finished=true;
3138            }
3139          }
3140#endif
3141          // If  fixed then round again
3142          if (!branch_&&anyAction!=-2) {
3143            finished=false;
3144          }
3145          // If these in then different action
3146#if ACTION == 1
3147          if (!anyAction)
3148            anyAction=-1;
3149          finished=true;
3150#endif
3151        }
3152      }
3153      delete ws;
3154    }
3155  }
3156  if (model->messageHandler()->logLevel()>2) 
3157    printf("%d strong, %d iters, %d pen, %d mark, %d fixed, action %d nnott %d nt %d, %d dq %s ns %d\n",
3158         numberStrongDone,numberStrongIterations,xPen,xMark,
3159           numberToFix,anyAction,numberNotTrusted,px[0],px[1],px[2]>0 ? "y" : "n",px[3]);
3160  // update number of strong iterations etc
3161  model->incrementStrongInfo(numberStrongDone,numberStrongIterations,
3162                             anyAction==-2 ? 0:numberToFix,anyAction==-2);
3163  if (!newWay) {
3164  if (((model->searchStrategy()+1)%1000)==0) {
3165    if (solver->messageHandler()->logLevel()>1)
3166      printf("%d strong, %d iters, %d inf, %d not finished, %d not trusted\n",
3167             numberStrongDone,numberStrongIterations,numberStrongInfeasible,numberUnfinished,
3168             numberNotTrusted);
3169    // decide what to do
3170    int strategy=1;
3171    if (numberUnfinished*4>numberStrongDone&&numberStrongInfeasible*10<numberStrongDone) {
3172      strategy=2;
3173      if (model->logLevel()>1)
3174        printf("going to strategy 2\n");
3175    }
3176    if (numberNodes)
3177      strategy=1;  // should only happen after hot start
3178    model->setSearchStrategy(strategy);
3179  }
3180  }
3181  //if (numberToFix&&depth_<5)
3182  //printf("%d fixed by strong at depth %d\n",numberToFix,depth_);
3183  // Set guessed solution value
3184  guessedObjectiveValue_ = objectiveValue_+estimatedDegradation;
3185 
3186  // Get collection of branches if mini tree wanted
3187  if (anyAction==0&&numberMini&&numberMini>1) {
3188    // Sort
3189    CoinSort_2(sort,sort+numberMini,whichObject);
3190    delete branch_;
3191    branch_=NULL;
3192    numberMini = CoinMin(numberMini,model->sizeMiniTree());
3193    anyAction=numberMini;
3194    branches = new OsiSolverBranch[numberMini];
3195    for (int iDo=0;iDo<numberMini;iDo++) {
3196      int iObject = whichObject[iDo];
3197      CbcObject * object = model->modifiableObject(iObject);
3198      OsiSolverBranch * oneBranch = object->solverBranch();
3199      branches[iDo]=*oneBranch;
3200      delete oneBranch;
3201    }
3202  }
3203/*
3204  Cleanup, then we're finished
3205*/
3206  if (!model->branchingMethod())
3207    delete decision;
3208   
3209  delete [] fixObject;
3210  delete [] sort;
3211  delete [] whichObject;
3212  delete [] objectMark;
3213  delete [] saveLower;
3214  delete [] saveUpper;
3215  delete [] upEstimate;
3216  delete [] downEstimate;
3217# ifdef COIN_HAS_CLP
3218  if (osiclp) 
3219    osiclp->setSpecialOptions(saveClpOptions);
3220# endif
3221  // restore solution
3222  solver->setColSolution(saveSolution);
3223  model->reserveCurrentSolution(saveSolution);
3224  delete [] saveSolution;
3225  model->setStateOfSearch(saveStateOfSearch);
3226  return anyAction;
3227}
3228int CbcNode::analyze (CbcModel *model, double * results)
3229{
3230  int i;
3231  int numberIterationsAllowed = model->numberAnalyzeIterations();
3232  OsiSolverInterface * solver = model->solver();
3233  objectiveValue_ = solver->getObjSense()*solver->getObjValue();
3234  double cutoff =model->getCutoff();
3235  const double * lower = solver->getColLower();
3236  const double * upper = solver->getColUpper();
3237  const double * dj = solver->getReducedCost();
3238  int numberObjects = model->numberObjects();
3239  int numberColumns = model->getNumCols();
3240  // Initialize arrays
3241  int numberIntegers = model->numberIntegers();
3242  int * back = new int[numberColumns];
3243  const int * integerVariable = model->integerVariable();
3244  for (i=0;i<numberColumns;i++) 
3245    back[i]=-1;
3246  // What results is
3247  double * newLower = results;
3248  double * objLower = newLower+numberIntegers;
3249  double * newUpper = objLower+numberIntegers;
3250  double * objUpper = newUpper+numberIntegers;
3251  for (i=0;i<numberIntegers;i++) {
3252    int iColumn = integerVariable[i];
3253    back[iColumn]=i;
3254    newLower[i]=0.0;
3255    objLower[i]=-COIN_DBL_MAX;
3256    newUpper[i]=0.0;
3257    objUpper[i]=-COIN_DBL_MAX;
3258  }
3259  double * saveUpper = new double[numberColumns];
3260  double * saveLower = new double[numberColumns];
3261  int anyAction=0;
3262  // Save solution in case heuristics need good solution later
3263 
3264  double * saveSolution = new double[numberColumns];
3265  memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
3266  model->reserveCurrentSolution(saveSolution);
3267  for (i=0;i<numberColumns;i++) {
3268    saveLower[i] = lower[i];
3269    saveUpper[i] = upper[i];
3270  }
3271  // Get arrays to sort
3272  double * sort = new double[numberObjects];
3273  int * whichObject = new int[numberObjects];
3274  int numberToFix=0;
3275  int numberToDo=0;
3276     
3277  // compute current state
3278  int numberObjectInfeasibilities; // just odd ones
3279  int numberIntegerInfeasibilities;
3280  model->feasibleSolution(
3281                          numberIntegerInfeasibilities,
3282                          numberObjectInfeasibilities);
3283# ifdef COIN_HAS_CLP
3284  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
3285  int saveClpOptions=0;
3286  bool fastIterations = (model->specialOptions()&8)!=0;
3287  if (osiclp&&fastIterations) {
3288    // for faster hot start
3289    saveClpOptions = osiclp->specialOptions();
3290    osiclp->setSpecialOptions(saveClpOptions|1024);
3291  }
3292# else
3293  bool fastIterations = false ;
3294# endif
3295  /*
3296    Scan for branching objects that indicate infeasibility. Choose candidates
3297    using priority as the first criteria, then integer infeasibility.
3298   
3299    The algorithm is to fill the array with a set of good candidates (by
3300    infeasibility) with priority bestPriority.  Finding a candidate with
3301    priority better (less) than bestPriority flushes the choice array. (This
3302    serves as initialization when the first candidate is found.)
3303   
3304  */
3305  numberToDo=0;
3306  for (i=0;i<numberObjects;i++) {
3307    CbcObject * object = model->modifiableObject(i);
3308    CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3309      dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3310    if(!dynamicObject)
3311      continue;
3312    int preferredWay;
3313    double infeasibility = object->infeasibility(preferredWay);
3314    int iColumn = dynamicObject->columnNumber();
3315    if (saveUpper[iColumn]==saveLower[iColumn])
3316      continue;
3317    if (infeasibility)
3318      sort[numberToDo]=-1.0e10-infeasibility;
3319    else
3320      sort[numberToDo]=-fabs(dj[iColumn]);
3321    whichObject[numberToDo++]=i;
3322  }
3323  // Save basis
3324  CoinWarmStart * ws = solver->getWarmStart();
3325  int saveLimit;
3326  solver->getIntParam(OsiMaxNumIterationHotStart,saveLimit);
3327  int targetIterations = CoinMax(500,numberIterationsAllowed/numberObjects);
3328  if (saveLimit<targetIterations)
3329    solver->setIntParam(OsiMaxNumIterationHotStart,targetIterations); 
3330  // Mark hot start
3331  solver->markHotStart();
3332  // Sort
3333  CoinSort_2(sort,sort+numberToDo,whichObject);
3334  //double distanceToCutoff=model->getCutoff()-objectiveValue_;
3335  double * currentSolution = model->currentSolution();
3336  double integerTolerance = 
3337    model->getDblParam(CbcModel::CbcIntegerTolerance);
3338  double objMin = 1.0e50;
3339  double objMax = -1.0e50;
3340  bool needResolve=false;
3341  int iDo;
3342  for (iDo=0;iDo<numberToDo;iDo++) {
3343    CbcStrongInfo choice;
3344    int iObject = whichObject[iDo];
3345    CbcObject * object = model->modifiableObject(iObject);
3346    CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3347      dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3348    int iColumn = dynamicObject->columnNumber();
3349    int preferredWay;
3350    object->infeasibility(preferredWay);
3351    double value = currentSolution[iColumn];
3352    double nearest = floor(value+0.5);
3353    double lowerValue = floor(value);
3354    bool satisfied=false;
3355    if (fabs(value-nearest)<=integerTolerance||value<saveLower[iColumn]||value>saveUpper[iColumn]) {
3356      satisfied=true;
3357      double newValue;
3358      if (nearest<saveUpper[iColumn]) {
3359        newValue = nearest + 1.0001*integerTolerance;
3360        lowerValue = nearest;
3361      } else {
3362        newValue = nearest - 1.0001*integerTolerance;
3363        lowerValue = nearest-1;
3364      }
3365      currentSolution[iColumn]=newValue;
3366    }
3367    double upperValue = lowerValue+1.0;
3368    choice.possibleBranch=object->createBranch(preferredWay);
3369    currentSolution[iColumn]=value;
3370    // Save which object it was
3371    choice.objectNumber=iObject;
3372    choice.numIntInfeasUp = numberUnsatisfied_;
3373    choice.numIntInfeasDown = numberUnsatisfied_;
3374    choice.downMovement = 0.0;
3375    choice.upMovement = 0.0;
3376    choice.numItersDown = 0;
3377    choice.numItersUp = 0;
3378    choice.fix=0; // say not fixed
3379    double objectiveChange ;
3380    double newObjectiveValue=1.0e100;
3381    int j;
3382    // status is 0 finished, 1 infeasible and other
3383    int iStatus;
3384    /*
3385      Try the down direction first. (Specify the initial branching alternative as
3386      down with a call to way(-1). Each subsequent call to branch() performs the
3387      specified branch and advances the branch object state to the next branch
3388      alternative.)
3389    */
3390    choice.possibleBranch->way(-1) ;
3391    choice.possibleBranch->branch() ;
3392    if (fabs(value-lowerValue)>integerTolerance) {
3393      solver->solveFromHotStart() ;
3394      /*
3395        We now have an estimate of objective degradation that we can use for strong
3396        branching. If we're over the cutoff, the variable is monotone up.
3397        If we actually made it to optimality, check for a solution, and if we have
3398        a good one, call setBestSolution to process it. Note that this may reduce the
3399        cutoff, so we check again to see if we can declare this variable monotone.
3400      */
3401      if (solver->isProvenOptimal())
3402        iStatus=0; // optimal
3403      else if (solver->isIterationLimitReached()
3404               &&!solver->isDualObjectiveLimitReached())
3405        iStatus=2; // unknown
3406      else
3407        iStatus=1; // infeasible
3408      newObjectiveValue = solver->getObjSense()*solver->getObjValue();
3409      choice.numItersDown = solver->getIterationCount();
3410      numberIterationsAllowed -= choice.numItersDown;
3411      objectiveChange = newObjectiveValue  - objectiveValue_;
3412      if (!iStatus) {
3413        choice.finishedDown = true ;
3414        if (newObjectiveValue>=cutoff) {
3415          objectiveChange = 1.0e100; // say infeasible
3416        } else {
3417          // See if integer solution
3418          if (model->feasibleSolution(choice.numIntInfeasDown,
3419                                      choice.numObjInfeasDown)
3420              &&model->problemFeasibility()->feasible(model,-1)>=0) {
3421            model->setBestSolution(CBC_STRONGSOL,
3422                                   newObjectiveValue,
3423                                   solver->getColSolution()) ;
3424            model->setLastHeuristic(NULL);
3425            model->incrementUsed(solver->getColSolution());
3426            cutoff =model->getCutoff();
3427            if (newObjectiveValue >= cutoff)    //  *new* cutoff
3428              objectiveChange = 1.0e100 ;
3429          }
3430        }
3431      } else if (iStatus==1) {
3432        objectiveChange = 1.0e100 ;
3433      } else {
3434        // Can't say much as we did not finish
3435        choice.finishedDown = false ;
3436      }
3437      choice.downMovement = objectiveChange ;
3438    }
3439    // restore bounds
3440    for ( j=0;j<numberColumns;j++) {
3441      if (saveLower[j] != lower[j])
3442        solver->setColLower(j,saveLower[j]);
3443      if (saveUpper[j] != upper[j])
3444        solver->setColUpper(j,saveUpper[j]);
3445    }
3446    // repeat the whole exercise, forcing the variable up
3447    choice.possibleBranch->branch();
3448    if (fabs(value-upperValue)>integerTolerance) {
3449      solver->solveFromHotStart() ;
3450      /*
3451        We now have an estimate of objective degradation that we can use for strong
3452        branching. If we're over the cutoff, the variable is monotone up.
3453        If we actually made it to optimality, check for a solution, and if we have
3454        a good one, call setBestSolution to process it. Note that this may reduce the
3455        cutoff, so we check again to see if we can declare this variable monotone.
3456      */
3457      if (solver->isProvenOptimal())
3458        iStatus=0; // optimal
3459      else if (solver->isIterationLimitReached()
3460               &&!solver->isDualObjectiveLimitReached())
3461        iStatus=2; // unknown
3462      else
3463        iStatus=1; // infeasible
3464      newObjectiveValue = solver->getObjSense()*solver->getObjValue();
3465      choice.numItersUp = solver->getIterationCount();
3466      numberIterationsAllowed -= choice.numItersUp;
3467      objectiveChange = newObjectiveValue  - objectiveValue_;
3468      if (!iStatus) {
3469        choice.finishedUp = true ;
3470        if (newObjectiveValue>=cutoff) {
3471          objectiveChange = 1.0e100; // say infeasible
3472        } else {
3473          // See if integer solution
3474          if (model->feasibleSolution(choice.numIntInfeasUp,
3475                                      choice.numObjInfeasUp)
3476              &&model->problemFeasibility()->feasible(model,-1)>=0) {
3477            model->setBestSolution(CBC_STRONGSOL,
3478                                   newObjectiveValue,
3479                                   solver->getColSolution()) ;
3480            model->setLastHeuristic(NULL);
3481            model->incrementUsed(solver->getColSolution());
3482            cutoff =model->getCutoff();
3483            if (newObjectiveValue >= cutoff)    //  *new* cutoff
3484              objectiveChange = 1.0e100 ;
3485          }
3486        }
3487      } else if (iStatus==1) {
3488        objectiveChange = 1.0e100 ;
3489      } else {
3490        // Can't say much as we did not finish
3491        choice.finishedUp = false ;
3492      }
3493      choice.upMovement = objectiveChange ;
3494     
3495      // restore bounds
3496      for ( j=0;j<numberColumns;j++) {
3497        if (saveLower[j] != lower[j])
3498          solver->setColLower(j,saveLower[j]);
3499        if (saveUpper[j] != upper[j])
3500          solver->setColUpper(j,saveUpper[j]);
3501      }
3502    }
3503    // If objective goes above certain amount we can set bound
3504    int jInt = back[iColumn];
3505    newLower[jInt]=upperValue;
3506    if (choice.finishedDown||!fastIterations)
3507      objLower[jInt]=choice.downMovement+objectiveValue_;
3508    else
3509      objLower[jInt]=objectiveValue_;
3510    newUpper[jInt]=lowerValue;
3511    if (choice.finishedUp||!fastIterations)
3512      objUpper[jInt]=choice.upMovement+objectiveValue_;
3513    else
3514      objUpper[jInt]=objectiveValue_;
3515    objMin = CoinMin(CoinMin(objLower[jInt],objUpper[jInt]),objMin);
3516    /*
3517      End of evaluation for this candidate variable. Possibilities are:
3518      * Both sides below cutoff; this variable is a candidate for branching.
3519      * Both sides infeasible or above the objective cutoff: no further action
3520      here. Break from the evaluation loop and assume the node will be purged
3521      by the caller.
3522      * One side below cutoff: Install the branch (i.e., fix the variable). Break
3523      from the evaluation loop and assume the node will be reoptimised by the
3524      caller.
3525    */
3526    if (choice.upMovement<1.0e100) {
3527      if(choice.downMovement<1.0e100) {
3528        objMax = CoinMax(CoinMax(objLower[jInt],objUpper[jInt]),objMax);
3529        // In case solution coming in was odd
3530        choice.upMovement = CoinMax(0.0,choice.upMovement);
3531        choice.downMovement = CoinMax(0.0,choice.downMovement);
3532        // feasible -
3533        model->messageHandler()->message(CBC_STRONG,model->messages())
3534          << iObject << iColumn
3535          <<choice.downMovement<<choice.numIntInfeasDown
3536          <<choice.upMovement<<choice.numIntInfeasUp
3537          <<value
3538          <<CoinMessageEol;
3539      } else {
3540        // up feasible, down infeasible
3541        anyAction=-1;
3542        if (!satisfied)
3543          needResolve=true;
3544        choice.fix=1;
3545        numberToFix++;
3546        saveLower[iColumn]=upperValue;
3547        solver->setColLower(iColumn,upperValue);
3548      }
3549    } else {
3550      if(choice.downMovement<1.0e100) {
3551        // down feasible, up infeasible
3552        anyAction=-1;
3553        if (!satisfied)
3554          needResolve=true;
3555        choice.fix=-1;
3556        numberToFix++;
3557        saveUpper[iColumn]=lowerValue;
3558        solver->setColUpper(iColumn,lowerValue);
3559      } else {
3560        // neither side feasible
3561        anyAction=-2;
3562        printf("Both infeasible for choice %d sequence %d\n",i,
3563               model->object(choice.objectNumber)->columnNumber());
3564        delete ws;
3565        ws=NULL;
3566        solver->writeMps("bad");
3567        numberToFix=-1;
3568        delete choice.possibleBranch;
3569        choice.possibleBranch=NULL;
3570        break;
3571      }
3572    }
3573    delete choice.possibleBranch;
3574    if (numberIterationsAllowed<=0)
3575      break;
3576    //printf("obj %d, col %d, down %g up %g value %g\n",iObject,iColumn,
3577    //     choice.downMovement,choice.upMovement,value);
3578  }
3579  printf("Best possible solution %g, can fix more if solution of %g found - looked at %d variables in %d iterations\n",
3580         objMin,objMax,iDo,model->numberAnalyzeIterations()-numberIterationsAllowed);
3581  model->setNumberAnalyzeIterations(numberIterationsAllowed);
3582  // Delete the snapshot
3583  solver->unmarkHotStart();
3584  // back to normal
3585  solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
3586  solver->setIntParam(OsiMaxNumIterationHotStart,saveLimit);
3587  // restore basis
3588  solver->setWarmStart(ws);
3589  delete ws;
3590   
3591  delete [] sort;
3592  delete [] whichObject;
3593  delete [] saveLower;
3594  delete [] saveUpper;
3595  delete [] back;
3596  // restore solution
3597  solver->setColSolution(saveSolution);
3598# ifdef COIN_HAS_CLP
3599  if (osiclp) 
3600    osiclp->setSpecialOptions(saveClpOptions);
3601# endif
3602  model->reserveCurrentSolution(saveSolution);
3603  delete [] saveSolution;
3604  if (needResolve)
3605    solver->resolve();
3606  return numberToFix;
3607}
3608
3609
3610CbcNode::CbcNode(const CbcNode & rhs) 
3611{ 
3612#ifdef CHECK_NODE
3613  printf("CbcNode %x Constructor from rhs %x\n",this,&rhs);
3614#endif
3615  if (rhs.nodeInfo_)
3616    nodeInfo_ = rhs.nodeInfo_->clone();
3617  else
3618    nodeInfo_=NULL;
3619  objectiveValue_=rhs.objectiveValue_;
3620  guessedObjectiveValue_ = rhs.guessedObjectiveValue_;
3621  if (rhs.branch_)
3622    branch_=rhs.branch_->clone();
3623  else
3624    branch_=NULL;
3625  depth_ = rhs.depth_;
3626  numberUnsatisfied_ = rhs.numberUnsatisfied_;
3627}
3628
3629CbcNode &
3630CbcNode::operator=(const CbcNode & rhs)
3631{
3632  if (this != &rhs) {
3633    delete nodeInfo_;
3634    if (nodeInfo_)
3635      nodeInfo_ = rhs.nodeInfo_->clone();
3636    else
3637      nodeInfo_ = NULL;
3638    objectiveValue_=rhs.objectiveValue_;
3639    guessedObjectiveValue_ = rhs.guessedObjectiveValue_;
3640    if (rhs.branch_)
3641      branch_=rhs.branch_->clone();
3642    else
3643      branch_=NULL,
3644    depth_ = rhs.depth_;
3645    numberUnsatisfied_ = rhs.numberUnsatisfied_;
3646  }
3647  return *this;
3648}
3649
3650
3651CbcNode::~CbcNode ()
3652{
3653#ifdef CHECK_NODE
3654  if (nodeInfo_) 
3655    printf("CbcNode %x Destructor nodeInfo %x (%d)\n",
3656         this,nodeInfo_,nodeInfo_->numberPointingToThis());
3657  else
3658    printf("CbcNode %x Destructor nodeInfo %x (?)\n",
3659         this,nodeInfo_);
3660#endif
3661  if (nodeInfo_) {
3662    nodeInfo_->nullOwner();
3663    int numberToDelete=nodeInfo_->numberBranchesLeft();
3664    //    CbcNodeInfo * parent = nodeInfo_->parent();
3665    if (nodeInfo_->decrement(numberToDelete)==0) {
3666      delete nodeInfo_;
3667    } else {
3668      //printf("node %x nodeinfo %x parent %x\n",this,nodeInfo_,parent);
3669      // anyway decrement parent
3670      //if (parent)
3671      ///parent->decrement(1);
3672    }
3673  }
3674  delete branch_;
3675}
3676// Decrement  active cut counts
3677void 
3678CbcNode::decrementCuts(int change)
3679{
3680  if(nodeInfo_) {
3681    nodeInfo_->decrementCuts(change);
3682  }
3683}
3684void 
3685CbcNode::decrementParentCuts(int change)
3686{
3687  if(nodeInfo_) {
3688    nodeInfo_->decrementParentCuts(change);
3689  }
3690}
3691
3692/*
3693  Initialize reference counts (numberPointingToThis, numberBranchesLeft_)
3694  in the attached nodeInfo_.
3695*/
3696void
3697CbcNode::initializeInfo()
3698{
3699  assert(nodeInfo_ && branch_) ;
3700  nodeInfo_->initializeInfo(branch_->numberBranches());
3701}
3702// Nulls out node info
3703void 
3704CbcNode::nullNodeInfo()
3705{
3706  nodeInfo_=NULL;
3707}
3708
3709int
3710CbcNode::branch()
3711{
3712  double changeInGuessed=branch_->branch(true);
3713  guessedObjectiveValue_+= changeInGuessed;
3714  //#define PRINTIT
3715#ifdef PRINTIT
3716  int numberLeft = nodeInfo_->numberBranchesLeft();
3717  CbcNodeInfo * parent = nodeInfo_->parent();
3718  int parentNodeNumber = -1;
3719  //CbcBranchingObject * object1 = branch_->object_;
3720  //CbcObject * object = object1->
3721  //int sequence = object->columnNumber);
3722  int id=-1;
3723  double value=0.0;
3724  if (branch_) {
3725    id = branch_->variable();
3726    value = branch_->value();
3727  }
3728  printf("id %d value %g objvalue %g\n",id,value,objectiveValue_);
3729  if (parent)
3730    parentNodeNumber = parent->nodeNumber();
3731  printf("Node number %d, %s, way %d, depth %d, parent node number %d\n",
3732         nodeInfo_->nodeNumber(),(numberLeft==2) ? "leftBranch" : "rightBranch",
3733         way(),depth_,parentNodeNumber);
3734#endif
3735  return nodeInfo_->branchedOn();
3736}
Note: See TracBrowser for help on using the repository browser.