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

Last change on this file since 354 was 354, checked in by ladanyi, 14 years ago

finished switch to subversion

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 133.4 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()>4) {
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|8192);
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=0;
2043  int numberUnfinished=0;
2044  int numberStrongInfeasible=0;
2045  int numberStrongIterations=0;
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          skipAll=false;
2500        }
2501      } else if (searchStrategy!=3) {
2502        doQuickly=true;
2503        numberTest=numberStrong;
2504      }
2505#endif
2506      if (depth_<10&&numberStrong) {
2507        if (searchStrategy!=2) {
2508          doQuickly=false;
2509          if (depth_<7)
2510            numberStrong *=3;
2511          if (!depth_) 
2512            numberStrong=CoinMin(6*numberStrong,numberToDo);
2513          numberTest=numberStrong;
2514          skipAll=false;
2515        }
2516        model->setStateOfSearch(2); // use min min
2517      }
2518      // could adjust using average iterations per branch
2519      // double average = ((double)model->getIterationCount())/
2520      //((double) model->getNodeCount()+1.0);
2521      // if too many and big then just do 10 its
2522      if (!skipAll&&saveStateOfSearch) {
2523        //if (numberNotTrusted>3*numberStrong&&numberRows>250&&numberColumns>1000&&saveLimit==100)
2524          // off solver->setIntParam(OsiMaxNumIterationHotStart,10);
2525      }
2526      // make negative for test
2527      distanceToCutoff = - distanceToCutoff;
2528      if (numberObjects>-100) {
2529        // larger
2530        distanceToCutoff *= 100.0;
2531      }
2532        distanceToCutoff = -COIN_DBL_MAX;
2533      // Do at least 5 strong
2534      if (numberColumns<1000&&(depth_<15||numberNodes<1000000))
2535        numberTest = CoinMax(numberTest,5);
2536      if ((model->specialOptions()&8)==0) {
2537        if (skipAll) {
2538          numberTest=0;
2539          doQuickly=true;
2540        }
2541      } else {
2542        // do 5 as strong is fixing
2543        numberTest = CoinMax(numberTest,5);
2544      }
2545      } else {
2546      int numberTest=numberNotTrusted>0 ? numberStrong : (numberStrong+1)/2;
2547      int numberTest2 = 2*numberStrong;
2548      if (searchStrategy>=3) {
2549        // Previously decided we need strong
2550        doQuickly=false;
2551        if (depth_<7)
2552          numberStrong *=3;
2553        if (!depth_) 
2554          numberStrong=CoinMin(6*numberStrong,numberToDo);
2555        numberTest = numberStrong;
2556        numberTest2 *= 2;
2557      } else if (searchStrategy==2||(searchStrategy==1&&depth_<6)) {
2558        numberStrong *=2;
2559        if (!depth_) 
2560          numberStrong=CoinMin(2*numberStrong,numberToDo);
2561        numberTest = numberStrong;
2562      } else if (searchStrategy==1&&numberNotTrusted) {
2563        numberTest = numberStrong;
2564      } else {
2565        numberTest=0;
2566        skipAll=true;
2567      }
2568      distanceToCutoff=model->getCutoff()-objectiveValue_;
2569      // make negative for test
2570      distanceToCutoff = - distanceToCutoff;
2571      if (numberObjects>-100) {
2572        // larger
2573        distanceToCutoff *= 100.0;
2574      }
2575      distanceToCutoff = -COIN_DBL_MAX;
2576      if (skipAll) {
2577        numberTest=0;
2578        doQuickly=true;
2579      }
2580      }
2581#if 0
2582      // temp - always switch off
2583      if (0) {
2584        int numberIterations = model->getIterationCount();
2585        int numberStrongIterations = model->numberStrongIterations();
2586        if (numberStrongIterations>numberIterations+10000&&depth_>=5) {
2587          skipAll=true;
2588          newWay=false;
2589          numberTest=0;
2590          doQuickly=true;
2591        }
2592      }
2593      // temp - always switch on
2594      if (0) {
2595        int numberIterations = model->getIterationCount();
2596        int numberStrongIterations = model->numberStrongIterations();
2597        if (2*numberStrongIterations<numberIterations||depth_<=5) {
2598          skipAll=false;
2599          newWay=false;
2600          numberTest=CoinMax(numberTest,numberStrong);
2601          doQuickly=false;
2602        }
2603      }
2604#endif
2605      px[0]=numberTest;
2606      px[1]=numberTest2;
2607      px[2]= doQuickly ? 1 : -1;
2608      px[3]=numberStrong;
2609      //printf("skipAll %c doQuickly %c numberTest %d numberTest2 %d numberNot %d\n",
2610      //     skipAll ? 'Y' : 'N',doQuickly ? 'Y' : 'N',numberTest,numberTest2,numberNotTrusted);
2611      // See if we want mini tree
2612      bool wantMiniTree=false;
2613      if (model->sizeMiniTree()&&depth_>7&&saveStateOfSearch>0)
2614        wantMiniTree=true;
2615      numberMini=0;
2616      //if (skipAll&&numberTest==0&&doQuickly)
2617      //numberToDo = 1; // trust previous stuff
2618      bool couldChooseFirst = false ; //(skipAll&&numberTest==0&&doQuickly);
2619      for ( iDo=0;iDo<numberToDo;iDo++) {
2620        CbcStrongInfo choice;
2621        int iObject = whichObject[iDo];
2622        CbcObject * object = model->modifiableObject(iObject);
2623        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2624          dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2625        int iColumn = dynamicObject->columnNumber();
2626        int preferredWay;
2627        object->infeasibility(preferredWay);
2628        choice.possibleBranch=object->createBranch(preferredWay);
2629        // Save which object it was
2630        choice.objectNumber=iObject;
2631        choice.numIntInfeasUp = numberUnsatisfied_;
2632        choice.numIntInfeasDown = numberUnsatisfied_;
2633        choice.upMovement = upEstimate[iObject];
2634        choice.downMovement = downEstimate[iObject];
2635        assert (choice.upMovement>=0.0);
2636        assert (choice.downMovement>=0.0);
2637        choice.fix=0; // say not fixed
2638        // see if can skip strong branching
2639        int canSkip = choice.possibleBranch->fillStrongInfo(choice);
2640        if (!newWay) {
2641        if (!doQuickly||(numberTest>0&&searchStrategy!=2))
2642          canSkip=0;
2643        } else {
2644        if (skipAll)
2645          canSkip=1;
2646        else if (numberTest>0&&searchStrategy>=3)
2647          canSkip=0;
2648        }
2649        if (!numberBeforeTrust) {
2650          canSkip=1;
2651        }
2652        if (sort[iDo]<distanceToCutoff)
2653          canSkip=0;
2654        if (((numberTest2<=0&&numberTest<=0)||skipAll)&&sort[iDo]>distanceToCutoff) {
2655          canSkip=1; // always skip
2656          if (iDo>20) {
2657            delete choice.possibleBranch;
2658            choice.possibleBranch=NULL;
2659            break; // give up anyway
2660          }
2661        }
2662        if (model->messageHandler()->logLevel()>3&&numberBeforeTrust) 
2663          dynamicObject->print(1,choice.possibleBranch->value());
2664        // was if (!canSkip)
2665        if (newWay)
2666        numberTest2--;
2667        if (!canSkip) {
2668          //#ifndef RANGING
2669          if (!doneHotStart) {
2670            // Mark hot start
2671            doneHotStart=true;
2672            assert (auxiliaryInfo->warmStart());
2673            solver->markHotStart();
2674            xMark++;
2675          }
2676          //#endif
2677          assert (!couldChooseFirst);
2678          numberTest--;
2679          if (!newWay)
2680          numberTest2--;
2681          // just do a few
2682          //if (canSkip)
2683          //solver->setIntParam(OsiMaxNumIterationHotStart,10);
2684          double objectiveChange ;
2685          double newObjectiveValue=1.0e100;
2686          int j;
2687          // status is 0 finished, 1 infeasible and other
2688          int iStatus;
2689          /*
2690            Try the down direction first. (Specify the initial branching alternative as
2691            down with a call to way(-1). Each subsequent call to branch() performs the
2692            specified branch and advances the branch object state to the next branch
2693            alternative.)
2694          */
2695          choice.possibleBranch->way(-1) ;
2696          decision->saveBranchingObject( choice.possibleBranch);
2697          choice.possibleBranch->branch() ;
2698          solver->solveFromHotStart() ;
2699          bool needHotStartUpdate=false;
2700          numberStrongDone++;
2701          numberStrongIterations += solver->getIterationCount();
2702          /*
2703            We now have an estimate of objective degradation that we can use for strong
2704            branching. If we're over the cutoff, the variable is monotone up.
2705            If we actually made it to optimality, check for a solution, and if we have
2706            a good one, call setBestSolution to process it. Note that this may reduce the
2707            cutoff, so we check again to see if we can declare this variable monotone.
2708          */
2709          if (solver->isProvenOptimal())
2710            iStatus=0; // optimal
2711          else if (solver->isIterationLimitReached()
2712                   &&!solver->isDualObjectiveLimitReached())
2713            iStatus=2; // unknown
2714          else
2715            iStatus=1; // infeasible
2716          newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2717          choice.numItersDown = solver->getIterationCount();
2718          objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2719          decision->updateInformation( solver,this);
2720          if (!iStatus) {
2721            choice.finishedDown = true ;
2722            if (newObjectiveValue>=cutoff) {
2723              objectiveChange = 1.0e100; // say infeasible
2724              numberStrongInfeasible++;
2725            } else {
2726              // See if integer solution
2727              if (model->feasibleSolution(choice.numIntInfeasDown,
2728                                          choice.numObjInfeasDown)
2729                  &&model->problemFeasibility()->feasible(model,-1)>=0) {
2730                if (auxiliaryInfo->solutionAddsCuts()) {
2731                  needHotStartUpdate=true;
2732                  solver->unmarkHotStart();
2733                }
2734                model->setBestSolution(CBC_STRONGSOL,
2735                                       newObjectiveValue,
2736                                       solver->getColSolution()) ;
2737                if (needHotStartUpdate) {
2738                  solver->resolve();
2739                  newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2740                  objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2741                  model->feasibleSolution(choice.numIntInfeasDown,
2742                                          choice.numObjInfeasDown);
2743                }
2744                model->setLastHeuristic(NULL);
2745                model->incrementUsed(solver->getColSolution());
2746                cutoff =model->getCutoff();
2747                if (newObjectiveValue >= cutoff) {      //  *new* cutoff
2748                  objectiveChange = 1.0e100 ;
2749                  numberStrongInfeasible++;
2750                }
2751              }
2752            }
2753          } else if (iStatus==1) {
2754            objectiveChange = 1.0e100 ;
2755            numberStrongInfeasible++;
2756          } else {
2757            // Can't say much as we did not finish
2758            choice.finishedDown = false ;
2759            numberUnfinished++;
2760          }
2761          choice.downMovement = objectiveChange ;
2762         
2763          // restore bounds
2764          for ( j=0;j<numberColumns;j++) {
2765            if (saveLower[j] != lower[j])
2766              solver->setColLower(j,saveLower[j]);
2767            if (saveUpper[j] != upper[j])
2768              solver->setColUpper(j,saveUpper[j]);
2769          }
2770          if(needHotStartUpdate) {
2771            needHotStartUpdate = false;
2772            solver->resolve();
2773            //we may again have an integer feasible solution
2774            int numberIntegerInfeasibilities;
2775            int numberObjectInfeasibilities;
2776            if (model->feasibleSolution(
2777                                        numberIntegerInfeasibilities,
2778                                        numberObjectInfeasibilities)) {
2779#ifdef BONMIN
2780              //In this case node has become integer feasible, let us exit the loop
2781              std::cout<<"Node has become integer feasible"<<std::endl;
2782              numberUnsatisfied_ = 0;
2783              break;
2784#endif
2785              double objValue = solver->getObjValue();
2786              model->setBestSolution(CBC_STRONGSOL,
2787                                     objValue,
2788                                     solver->getColSolution()) ;
2789              solver->resolve();
2790              cutoff =model->getCutoff();
2791            }
2792            solver->markHotStart();
2793          }
2794          //printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
2795          //printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
2796          //     choice.objectNumber,iStatus,newObjectiveValue,choice.numItersDown,
2797          //     choice.downMovement,choice.finishedDown,choice.numIntInfeasDown,
2798          //     choice.numObjInfeasDown);
2799         
2800          // repeat the whole exercise, forcing the variable up
2801          decision->saveBranchingObject( choice.possibleBranch);
2802          choice.possibleBranch->branch();
2803          solver->solveFromHotStart() ;
2804          numberStrongDone++;
2805          numberStrongIterations += solver->getIterationCount();
2806          /*
2807            We now have an estimate of objective degradation that we can use for strong
2808            branching. If we're over the cutoff, the variable is monotone up.
2809            If we actually made it to optimality, check for a solution, and if we have
2810            a good one, call setBestSolution to process it. Note that this may reduce the
2811            cutoff, so we check again to see if we can declare this variable monotone.
2812          */
2813          if (solver->isProvenOptimal())
2814            iStatus=0; // optimal
2815          else if (solver->isIterationLimitReached()
2816                   &&!solver->isDualObjectiveLimitReached())
2817            iStatus=2; // unknown
2818          else
2819            iStatus=1; // infeasible
2820          newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2821          choice.numItersUp = solver->getIterationCount();
2822          objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2823          decision->updateInformation( solver,this);
2824          if (!iStatus) {
2825            choice.finishedUp = true ;
2826            if (newObjectiveValue>=cutoff) {
2827              objectiveChange = 1.0e100; // say infeasible
2828              numberStrongInfeasible++;
2829            } else {
2830              // See if integer solution
2831              if (model->feasibleSolution(choice.numIntInfeasUp,
2832                                          choice.numObjInfeasUp)
2833                  &&model->problemFeasibility()->feasible(model,-1)>=0) {
2834#ifdef BONMIN
2835                std::cout<<"Node has become integer feasible"<<std::endl;
2836                numberUnsatisfied_ = 0;
2837                break;
2838#endif
2839                if (auxiliaryInfo->solutionAddsCuts()) {
2840                  needHotStartUpdate=true;
2841                  solver->unmarkHotStart();
2842                }
2843                model->setBestSolution(CBC_STRONGSOL,
2844                                       newObjectiveValue,
2845                                       solver->getColSolution()) ;
2846                if (needHotStartUpdate) {
2847                  solver->resolve();
2848                  newObjectiveValue = solver->getObjSense()*solver->getObjValue();
2849                  objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_,0.0);
2850                  model->feasibleSolution(choice.numIntInfeasDown,
2851                                          choice.numObjInfeasDown);
2852                }
2853                model->setLastHeuristic(NULL);
2854                model->incrementUsed(solver->getColSolution());
2855                cutoff =model->getCutoff();
2856                if (newObjectiveValue >= cutoff) {      //  *new* cutoff
2857                  objectiveChange = 1.0e100 ;
2858                  numberStrongInfeasible++;
2859                }
2860              }
2861            }
2862          } else if (iStatus==1) {
2863            objectiveChange = 1.0e100 ;
2864            numberStrongInfeasible++;
2865          } else {
2866            // Can't say much as we did not finish
2867            choice.finishedUp = false ;
2868            numberUnfinished++;
2869          }
2870          choice.upMovement = objectiveChange ;
2871         
2872          // restore bounds
2873          for ( j=0;j<numberColumns;j++) {
2874            if (saveLower[j] != lower[j])
2875              solver->setColLower(j,saveLower[j]);
2876            if (saveUpper[j] != upper[j])
2877              solver->setColUpper(j,saveUpper[j]);
2878          }
2879          if(needHotStartUpdate) {
2880            needHotStartUpdate = false;
2881            solver->resolve();
2882            //we may again have an integer feasible solution
2883            int numberIntegerInfeasibilities;
2884            int numberObjectInfeasibilities;
2885            if (model->feasibleSolution(
2886                                        numberIntegerInfeasibilities,
2887                                        numberObjectInfeasibilities)) {
2888              double objValue = solver->getObjValue();
2889              model->setBestSolution(CBC_STRONGSOL,
2890                                     objValue,
2891                                     solver->getColSolution()) ;
2892              solver->resolve();
2893              cutoff =model->getCutoff();
2894            }
2895            solver->markHotStart();
2896          }
2897         
2898          //printf("Up on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
2899          //     choice.objectNumber,iStatus,newObjectiveValue,choice.numItersUp,
2900          //     choice.upMovement,choice.finishedUp,choice.numIntInfeasUp,
2901          //     choice.numObjInfeasUp);
2902        }
2903   
2904        solver->setIntParam(OsiMaxNumIterationHotStart,saveLimit2); 
2905        /*
2906          End of evaluation for this candidate variable. Possibilities are:
2907          * Both sides below cutoff; this variable is a candidate for branching.
2908          * Both sides infeasible or above the objective cutoff: no further action
2909          here. Break from the evaluation loop and assume the node will be purged
2910          by the caller.
2911          * One side below cutoff: Install the branch (i.e., fix the variable). Break
2912          from the evaluation loop and assume the node will be reoptimised by the
2913          caller.
2914        */
2915        // reset
2916        choice.possibleBranch->resetNumberBranchesLeft();
2917        if (choice.upMovement<1.0e100) {
2918          if(choice.downMovement<1.0e100) {
2919            // In case solution coming in was odd
2920            choice.upMovement = CoinMax(0.0,choice.upMovement);
2921            choice.downMovement = CoinMax(0.0,choice.downMovement);
2922            if (couldChooseFirst)
2923              printf("candidate %d up %g down %g sort %g\n",iDo,choice.upMovement,choice.downMovement,sort[iDo]);
2924#if ZERO_ONE==2
2925            // branch on 0-1 first (temp)
2926            if (fabs(choice.possibleBranch->value())<1.0) {
2927              choice.upMovement *= ZERO_FAKE;
2928              choice.downMovement *= ZERO_FAKE;
2929            }
2930#endif
2931            // feasible - see which best
2932            if (!canSkip) {
2933              if (iColumn==-46) {
2934                printf("sort %g downest %g upest %g ",sort[iDo],downEstimate[iObject],
2935                     upEstimate[iObject]);
2936                printf("downMove %g upMove %g value %g current pseudo %g %g\n",
2937                       choice.downMovement,choice.upMovement,choice.possibleBranch->value(),
2938                       dynamicObject->downDynamicPseudoCost(),dynamicObject->upDynamicPseudoCost());
2939              }
2940              if (model->messageHandler()->logLevel()>3) 
2941                printf("sort %g downest %g upest %g ",sort[iDo],downEstimate[iObject],
2942                     upEstimate[iObject]);
2943              model->messageHandler()->message(CBC_STRONG,model->messages())
2944                << iObject << iColumn
2945                <<choice.downMovement<<choice.numIntInfeasDown
2946                <<choice.upMovement<<choice.numIntInfeasUp
2947                <<choice.possibleBranch->value()
2948                <<CoinMessageEol;
2949            }
2950            //if (!stateOfSearch)
2951            //choice.numIntInfeasDown=99999; // temp fudge
2952            if (wantMiniTree)
2953              decision->setBestCriterion(-1.0);
2954            double bestCriterion = -1.0;
2955            //double gap = saveUpper[iColumn]-saveLower[iColumn];
2956            // Give precedence to ones with gap of 1.0
2957            //assert(gap>0.0);
2958            double factor = 1.0; //changeFactor/CoinMin(gap,100.0);
2959            int betterWay = decision->betterBranch(choice.possibleBranch,
2960                                                   branch_,
2961                                                   choice.upMovement*factor,
2962                                                   choice.numIntInfeasUp ,
2963                                                   choice.downMovement*factor,
2964                                                   choice.numIntInfeasDown );
2965            if (wantMiniTree) {
2966              double criterion = decision->getBestCriterion();
2967              sort[numberMini]=-criterion;
2968              whichObject[numberMini++]=whichObject[iDo];
2969              assert (betterWay);
2970              if (criterion>bestCriterion) 
2971                bestCriterion=criterion;
2972              else
2973                betterWay=0;
2974            }
2975            if (iDo>=changeStrategy) {
2976              // make less likely
2977              changeStrategy+=numberStrong;
2978              changeFactor *= 0.9;
2979            }
2980            if (betterWay) {
2981              delete branch_;
2982              // C) create branching object
2983              branch_ = choice.possibleBranch;
2984              choice.possibleBranch=NULL;
2985              branch_->way(betterWay);
2986              if (couldChooseFirst)
2987                printf("choosing %d way %d\n",iDo,betterWay);
2988              bestChoice = choice.objectNumber;
2989              whichChoice = iDo;
2990              if (numberStrong<=1) {
2991                delete ws;
2992                ws=NULL;
2993                break;
2994              }
2995            } else {
2996              delete choice.possibleBranch;
2997              choice.possibleBranch=NULL;
2998              if (iDo>=2*numberStrong) {
2999                delete ws;
3000                ws=NULL;
3001                break;
3002              }
3003              if (!dynamicObject||dynamicObject->numberTimesUp()>1) {
3004                if (iDo-whichChoice>=numberStrong) {
3005                  delete choice.possibleBranch;
3006                  choice.possibleBranch=NULL;
3007                  break; // give up
3008                }
3009              } else {
3010                if (iDo-whichChoice>=2*numberStrong) {
3011                  delete ws;
3012                  ws=NULL;
3013                  delete choice.possibleBranch;
3014                  choice.possibleBranch=NULL;
3015                  break; // give up
3016                }
3017              }
3018            }
3019          } else {
3020            // up feasible, down infeasible
3021            anyAction=-1;
3022            worstFeasible = CoinMax(worstFeasible,choice.upMovement);
3023            //printf("Down infeasible for choice %d sequence %d\n",i,
3024            // model->object(choice.objectNumber)->columnNumber());
3025            if (!solveAll) {
3026              choice.possibleBranch->way(1);
3027              choice.possibleBranch->branch();
3028              delete choice.possibleBranch;
3029              choice.possibleBranch=NULL;
3030              delete ws;
3031              ws=NULL;
3032              break;
3033            } else {
3034              choice.fix=1;
3035              fixObject[numberToFix++]=choice;
3036              choice.possibleBranch=NULL;
3037#define FIXNOW
3038#ifdef FIXNOW
3039              double value = ceil(saveSolution[iColumn]);
3040              saveLower[iColumn]=value;
3041              solver->setColLower(iColumn,value);
3042              assert(doneHotStart);
3043              solver->unmarkHotStart();
3044              solver->markHotStart();
3045#endif
3046            }
3047          }
3048        } else {
3049          if(choice.downMovement<1.0e100) {
3050            // down feasible, up infeasible
3051            anyAction=-1;
3052            worstFeasible = CoinMax(worstFeasible,choice.downMovement);
3053            //printf("Up infeasible for choice %d sequence %d\n",i,
3054            // model->object(choice.objectNumber)->columnNumber());
3055            if (!solveAll) {
3056              choice.possibleBranch->way(-1);
3057              choice.possibleBranch->branch();
3058              delete choice.possibleBranch;
3059              choice.possibleBranch=NULL;
3060              delete ws;
3061              ws=NULL;
3062              break;
3063            } else {
3064              choice.fix=-1;
3065              fixObject[numberToFix++]=choice;
3066              choice.possibleBranch=NULL;
3067#ifdef FIXNOW
3068              double value = floor(saveSolution[iColumn]);
3069              saveUpper[iColumn]=value;
3070              solver->setColUpper(iColumn,value);
3071              assert(doneHotStart);
3072              solver->unmarkHotStart();
3073              solver->markHotStart();
3074#endif
3075            }
3076          } else {
3077            // neither side feasible
3078            anyAction=-2;
3079            delete choice.possibleBranch;
3080            choice.possibleBranch=NULL;
3081            //printf("Both infeasible for choice %d sequence %d\n",i,
3082            // model->object(choice.objectNumber)->columnNumber());
3083            delete ws;
3084            ws=NULL;
3085            break;
3086          }
3087        }
3088        // Check max time
3089        hitMaxTime = ( CoinCpuTime()-model->getDblParam(CbcModel::CbcStartSeconds) > 
3090                       model->getDblParam(CbcModel::CbcMaximumSeconds));
3091        if (hitMaxTime) {
3092          // make sure rest are fast
3093          doQuickly=true;
3094          for ( int jDo=iDo+1;jDo<numberToDo;jDo++) {
3095            int iObject = whichObject[iDo];
3096            CbcObject * object = model->modifiableObject(iObject);
3097            CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3098              dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3099            dynamicObject->setNumberBeforeTrust(0);
3100          }
3101          numberTest=0;
3102          distanceToCutoff=-COIN_DBL_MAX;
3103        }
3104        delete choice.possibleBranch;
3105      }
3106      double averageChange = model->sumChangeObjective()/((double) model->getNodeCount());
3107      if (depth_<10||worstFeasible>0.2*averageChange) 
3108        solveAll=false;
3109      if (model->messageHandler()->logLevel()>3||false) { 
3110        if (anyAction==-2)
3111          printf("infeasible\n");
3112        else if(anyAction==-1)
3113          if (!solveAll)
3114            printf("%d fixed\n",numberToFix);
3115          else
3116            printf("%d fixed AND choosing %d iDo %d iChosenWhen %d numberToDo %d\n",numberToFix,bestChoice,
3117                   iDo,whichChoice,numberToDo);
3118        else
3119          printf("choosing %d iDo %d iChosenWhen %d numberToDo %d\n",bestChoice,
3120                 iDo,whichChoice,numberToDo);
3121      }
3122      if (doneHotStart) {
3123        // Delete the snapshot
3124        solver->unmarkHotStart();
3125        // back to normal
3126        solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
3127        // restore basis
3128        solver->setWarmStart(ws);
3129      }
3130      solver->setIntParam(OsiMaxNumIterationHotStart,saveLimit);
3131      // Unless infeasible we will carry on
3132      // But we could fix anyway
3133      if (numberToFix&&!hitMaxTime) {
3134        if (anyAction==-2) {
3135          // take off
3136          for (i = 0 ; i < numberToFix ; i++) {
3137            delete fixObject[i].possibleBranch;
3138          }
3139        } else {
3140          // apply and take off
3141          for (i = 0 ; i < numberToFix ; i++) {
3142#ifndef FIXNOW
3143            fixObject[i].possibleBranch->way(fixObject[i].fix) ;
3144            fixObject[i].possibleBranch->branch() ;
3145#endif
3146            delete fixObject[i].possibleBranch;
3147          }
3148          bool feasible=true;
3149#if ACTION <2
3150          if (solveAll) {
3151            // can do quick optimality check
3152            int easy=2;
3153            solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
3154            solver->resolve() ;
3155            solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
3156            feasible = solver->isProvenOptimal();
3157            if (feasible) {
3158              anyAction=0;
3159              numberMini=0;
3160              memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
3161              model->reserveCurrentSolution(saveSolution);
3162              memcpy(saveLower,solver->getColLower(),numberColumns*sizeof(double));
3163              memcpy(saveUpper,solver->getColUpper(),numberColumns*sizeof(double));
3164              model->setPointers(solver);
3165              // See if candidate still possible
3166              if (branch_) {
3167                const CbcObject * object = model->object(bestChoice);
3168                int preferredWay;
3169                double infeasibility = object->infeasibility(preferredWay);
3170                if (!infeasibility) {
3171                  // take out
3172                  delete branch_;
3173                  branch_=NULL;
3174                } else {
3175                  branch_->way(preferredWay);
3176                }
3177              }
3178            } else {
3179              anyAction=-2;
3180              finished=true;
3181            }
3182          }
3183#endif
3184          // If  fixed then round again
3185          if (!branch_&&anyAction!=-2) {
3186            finished=false;
3187          }
3188          // If these in then different action
3189#if ACTION == 1
3190          if (!anyAction)
3191            anyAction=-1;
3192          finished=true;
3193#endif
3194        }
3195      }
3196      delete ws;
3197    }
3198  }
3199  if (model->messageHandler()->logLevel()>2) 
3200    printf("%d strong, %d iters, %d pen, %d mark, %d fixed, action %d nnott %d nt %d, %d dq %s ns %d\n",
3201         numberStrongDone,numberStrongIterations,xPen,xMark,
3202           numberToFix,anyAction,numberNotTrusted,px[0],px[1],px[2]>0 ? "y" : "n",px[3]);
3203  // update number of strong iterations etc
3204  model->incrementStrongInfo(numberStrongDone,numberStrongIterations,
3205                             anyAction==-2 ? 0:numberToFix,anyAction==-2);
3206  if (!newWay) {
3207  if (((model->searchStrategy()+1)%1000)==0) {
3208    if (solver->messageHandler()->logLevel()>1)
3209      printf("%d strong, %d iters, %d inf, %d not finished, %d not trusted\n",
3210             numberStrongDone,numberStrongIterations,numberStrongInfeasible,numberUnfinished,
3211             numberNotTrusted);
3212    // decide what to do
3213    int strategy=1;
3214    if (numberUnfinished*4>numberStrongDone&&numberStrongInfeasible*10<numberStrongDone) {
3215      strategy=2;
3216      if (model->logLevel()>1)
3217        printf("going to strategy 2\n");
3218    }
3219    if (numberNodes)
3220      strategy=1;  // should only happen after hot start
3221    model->setSearchStrategy(strategy);
3222  }
3223  }
3224  //if (numberToFix&&depth_<5)
3225  //printf("%d fixed by strong at depth %d\n",numberToFix,depth_);
3226  // Set guessed solution value
3227  guessedObjectiveValue_ = objectiveValue_+estimatedDegradation;
3228 
3229  // Get collection of branches if mini tree wanted
3230  if (anyAction==0&&numberMini&&numberMini>1) {
3231    // Sort
3232    CoinSort_2(sort,sort+numberMini,whichObject);
3233    delete branch_;
3234    branch_=NULL;
3235    numberMini = CoinMin(numberMini,model->sizeMiniTree());
3236    anyAction=numberMini;
3237    branches = new OsiSolverBranch[numberMini];
3238    for (int iDo=0;iDo<numberMini;iDo++) {
3239      int iObject = whichObject[iDo];
3240      CbcObject * object = model->modifiableObject(iObject);
3241      OsiSolverBranch * oneBranch = object->solverBranch();
3242      branches[iDo]=*oneBranch;
3243      delete oneBranch;
3244    }
3245  }
3246/*
3247  Cleanup, then we're finished
3248*/
3249  if (!model->branchingMethod())
3250    delete decision;
3251   
3252  delete [] fixObject;
3253  delete [] sort;
3254  delete [] whichObject;
3255  delete [] objectMark;
3256  delete [] saveLower;
3257  delete [] saveUpper;
3258  delete [] upEstimate;
3259  delete [] downEstimate;
3260# ifdef COIN_HAS_CLP
3261  if (osiclp) 
3262    osiclp->setSpecialOptions(saveClpOptions);
3263# endif
3264  // restore solution
3265  solver->setColSolution(saveSolution);
3266  model->reserveCurrentSolution(saveSolution);
3267  delete [] saveSolution;
3268  model->setStateOfSearch(saveStateOfSearch);
3269  return anyAction;
3270}
3271int CbcNode::analyze (CbcModel *model, double * results)
3272{
3273  int i;
3274  int numberIterationsAllowed = model->numberAnalyzeIterations();
3275  OsiSolverInterface * solver = model->solver();
3276  objectiveValue_ = solver->getObjSense()*solver->getObjValue();
3277  double cutoff =model->getCutoff();
3278  const double * lower = solver->getColLower();
3279  const double * upper = solver->getColUpper();
3280  const double * dj = solver->getReducedCost();
3281  int numberObjects = model->numberObjects();
3282  int numberColumns = model->getNumCols();
3283  // Initialize arrays
3284  int numberIntegers = model->numberIntegers();
3285  int * back = new int[numberColumns];
3286  const int * integerVariable = model->integerVariable();
3287  for (i=0;i<numberColumns;i++) 
3288    back[i]=-1;
3289  // What results is
3290  double * newLower = results;
3291  double * objLower = newLower+numberIntegers;
3292  double * newUpper = objLower+numberIntegers;
3293  double * objUpper = newUpper+numberIntegers;
3294  for (i=0;i<numberIntegers;i++) {
3295    int iColumn = integerVariable[i];
3296    back[iColumn]=i;
3297    newLower[i]=0.0;
3298    objLower[i]=-COIN_DBL_MAX;
3299    newUpper[i]=0.0;
3300    objUpper[i]=-COIN_DBL_MAX;
3301  }
3302  double * saveUpper = new double[numberColumns];
3303  double * saveLower = new double[numberColumns];
3304  int anyAction=0;
3305  // Save solution in case heuristics need good solution later
3306 
3307  double * saveSolution = new double[numberColumns];
3308  memcpy(saveSolution,solver->getColSolution(),numberColumns*sizeof(double));
3309  model->reserveCurrentSolution(saveSolution);
3310  for (i=0;i<numberColumns;i++) {
3311    saveLower[i] = lower[i];
3312    saveUpper[i] = upper[i];
3313  }
3314  // Get arrays to sort
3315  double * sort = new double[numberObjects];
3316  int * whichObject = new int[numberObjects];
3317  int numberToFix=0;
3318  int numberToDo=0;
3319     
3320  // compute current state
3321  int numberObjectInfeasibilities; // just odd ones
3322  int numberIntegerInfeasibilities;
3323  model->feasibleSolution(
3324                          numberIntegerInfeasibilities,
3325                          numberObjectInfeasibilities);
3326# ifdef COIN_HAS_CLP
3327  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
3328  int saveClpOptions=0;
3329  bool fastIterations = (model->specialOptions()&8)!=0;
3330  if (osiclp&&fastIterations) {
3331    // for faster hot start
3332    saveClpOptions = osiclp->specialOptions();
3333    osiclp->setSpecialOptions(saveClpOptions|8192);
3334  }
3335# else
3336  bool fastIterations = false ;
3337# endif
3338  /*
3339    Scan for branching objects that indicate infeasibility. Choose candidates
3340    using priority as the first criteria, then integer infeasibility.
3341   
3342    The algorithm is to fill the array with a set of good candidates (by
3343    infeasibility) with priority bestPriority.  Finding a candidate with
3344    priority better (less) than bestPriority flushes the choice array. (This
3345    serves as initialization when the first candidate is found.)
3346   
3347  */
3348  numberToDo=0;
3349  for (i=0;i<numberObjects;i++) {
3350    CbcObject * object = model->modifiableObject(i);
3351    CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3352      dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3353    if(!dynamicObject)
3354      continue;
3355    int preferredWay;
3356    double infeasibility = object->infeasibility(preferredWay);
3357    int iColumn = dynamicObject->columnNumber();
3358    if (saveUpper[iColumn]==saveLower[iColumn])
3359      continue;
3360    if (infeasibility)
3361      sort[numberToDo]=-1.0e10-infeasibility;
3362    else
3363      sort[numberToDo]=-fabs(dj[iColumn]);
3364    whichObject[numberToDo++]=i;
3365  }
3366  // Save basis
3367  CoinWarmStart * ws = solver->getWarmStart();
3368  int saveLimit;
3369  solver->getIntParam(OsiMaxNumIterationHotStart,saveLimit);
3370  int targetIterations = CoinMax(500,numberIterationsAllowed/numberObjects);
3371  if (saveLimit<targetIterations)
3372    solver->setIntParam(OsiMaxNumIterationHotStart,targetIterations); 
3373  // Mark hot start
3374  solver->markHotStart();
3375  // Sort
3376  CoinSort_2(sort,sort+numberToDo,whichObject);
3377  //double distanceToCutoff=model->getCutoff()-objectiveValue_;
3378  double * currentSolution = model->currentSolution();
3379  double integerTolerance = 
3380    model->getDblParam(CbcModel::CbcIntegerTolerance);
3381  double objMin = 1.0e50;
3382  double objMax = -1.0e50;
3383  bool needResolve=false;
3384  int iDo;
3385  for (iDo=0;iDo<numberToDo;iDo++) {
3386    CbcStrongInfo choice;
3387    int iObject = whichObject[iDo];
3388    CbcObject * object = model->modifiableObject(iObject);
3389    CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3390      dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3391    int iColumn = dynamicObject->columnNumber();
3392    int preferredWay;
3393    object->infeasibility(preferredWay);
3394    double value = currentSolution[iColumn];
3395    double nearest = floor(value+0.5);
3396    double lowerValue = floor(value);
3397    bool satisfied=false;
3398    if (fabs(value-nearest)<=integerTolerance||value<saveLower[iColumn]||value>saveUpper[iColumn]) {
3399      satisfied=true;
3400      double newValue;
3401      if (nearest<saveUpper[iColumn]) {
3402        newValue = nearest + 1.0001*integerTolerance;
3403        lowerValue = nearest;
3404      } else {
3405        newValue = nearest - 1.0001*integerTolerance;
3406        lowerValue = nearest-1;
3407      }
3408      currentSolution[iColumn]=newValue;
3409    }
3410    double upperValue = lowerValue+1.0;
3411    choice.possibleBranch=object->createBranch(preferredWay);
3412    currentSolution[iColumn]=value;
3413    // Save which object it was
3414    choice.objectNumber=iObject;
3415    choice.numIntInfeasUp = numberUnsatisfied_;
3416    choice.numIntInfeasDown = numberUnsatisfied_;
3417    choice.downMovement = 0.0;
3418    choice.upMovement = 0.0;
3419    choice.numItersDown = 0;
3420    choice.numItersUp = 0;
3421    choice.fix=0; // say not fixed
3422    double objectiveChange ;
3423    double newObjectiveValue=1.0e100;
3424    int j;
3425    // status is 0 finished, 1 infeasible and other
3426    int iStatus;
3427    /*
3428      Try the down direction first. (Specify the initial branching alternative as
3429      down with a call to way(-1). Each subsequent call to branch() performs the
3430      specified branch and advances the branch object state to the next branch
3431      alternative.)
3432    */
3433    choice.possibleBranch->way(-1) ;
3434    choice.possibleBranch->branch() ;
3435    if (fabs(value-lowerValue)>integerTolerance) {
3436      solver->solveFromHotStart() ;
3437      /*
3438        We now have an estimate of objective degradation that we can use for strong
3439        branching. If we're over the cutoff, the variable is monotone up.
3440        If we actually made it to optimality, check for a solution, and if we have
3441        a good one, call setBestSolution to process it. Note that this may reduce the
3442        cutoff, so we check again to see if we can declare this variable monotone.
3443      */
3444      if (solver->isProvenOptimal())
3445        iStatus=0; // optimal
3446      else if (solver->isIterationLimitReached()
3447               &&!solver->isDualObjectiveLimitReached())
3448        iStatus=2; // unknown
3449      else
3450        iStatus=1; // infeasible
3451      newObjectiveValue = solver->getObjSense()*solver->getObjValue();
3452      choice.numItersDown = solver->getIterationCount();
3453      numberIterationsAllowed -= choice.numItersDown;
3454      objectiveChange = newObjectiveValue  - objectiveValue_;
3455      if (!iStatus) {
3456        choice.finishedDown = true ;
3457        if (newObjectiveValue>=cutoff) {
3458          objectiveChange = 1.0e100; // say infeasible
3459        } else {
3460          // See if integer solution
3461          if (model->feasibleSolution(choice.numIntInfeasDown,
3462                                      choice.numObjInfeasDown)
3463              &&model->problemFeasibility()->feasible(model,-1)>=0) {
3464            model->setBestSolution(CBC_STRONGSOL,
3465                                   newObjectiveValue,
3466                                   solver->getColSolution()) ;
3467            model->setLastHeuristic(NULL);
3468            model->incrementUsed(solver->getColSolution());
3469            cutoff =model->getCutoff();
3470            if (newObjectiveValue >= cutoff)    //  *new* cutoff
3471              objectiveChange = 1.0e100 ;
3472          }
3473        }
3474      } else if (iStatus==1) {
3475        objectiveChange = 1.0e100 ;
3476      } else {
3477        // Can't say much as we did not finish
3478        choice.finishedDown = false ;
3479      }
3480      choice.downMovement = objectiveChange ;
3481    }
3482    // restore bounds
3483    for ( j=0;j<numberColumns;j++) {
3484      if (saveLower[j] != lower[j])
3485        solver->setColLower(j,saveLower[j]);
3486      if (saveUpper[j] != upper[j])
3487        solver->setColUpper(j,saveUpper[j]);
3488    }
3489    // repeat the whole exercise, forcing the variable up
3490    choice.possibleBranch->branch();
3491    if (fabs(value-upperValue)>integerTolerance) {
3492      solver->solveFromHotStart() ;
3493      /*
3494        We now have an estimate of objective degradation that we can use for strong
3495        branching. If we're over the cutoff, the variable is monotone up.
3496        If we actually made it to optimality, check for a solution, and if we have
3497        a good one, call setBestSolution to process it. Note that this may reduce the
3498        cutoff, so we check again to see if we can declare this variable monotone.
3499      */
3500      if (solver->isProvenOptimal())
3501        iStatus=0; // optimal
3502      else if (solver->isIterationLimitReached()
3503               &&!solver->isDualObjectiveLimitReached())
3504        iStatus=2; // unknown
3505      else
3506        iStatus=1; // infeasible
3507      newObjectiveValue = solver->getObjSense()*solver->getObjValue();
3508      choice.numItersUp = solver->getIterationCount();
3509      numberIterationsAllowed -= choice.numItersUp;
3510      objectiveChange = newObjectiveValue  - objectiveValue_;
3511      if (!iStatus) {
3512        choice.finishedUp = true ;
3513        if (newObjectiveValue>=cutoff) {
3514          objectiveChange = 1.0e100; // say infeasible
3515        } else {
3516          // See if integer solution
3517          if (model->feasibleSolution(choice.numIntInfeasUp,
3518                                      choice.numObjInfeasUp)
3519              &&model->problemFeasibility()->feasible(model,-1)>=0) {
3520            model->setBestSolution(CBC_STRONGSOL,
3521                                   newObjectiveValue,
3522                                   solver->getColSolution()) ;
3523            model->setLastHeuristic(NULL);
3524            model->incrementUsed(solver->getColSolution());
3525            cutoff =model->getCutoff();
3526            if (newObjectiveValue >= cutoff)    //  *new* cutoff
3527              objectiveChange = 1.0e100 ;
3528          }
3529        }
3530      } else if (iStatus==1) {
3531        objectiveChange = 1.0e100 ;
3532      } else {
3533        // Can't say much as we did not finish
3534        choice.finishedUp = false ;
3535      }
3536      choice.upMovement = objectiveChange ;
3537     
3538      // restore bounds
3539      for ( j=0;j<numberColumns;j++) {
3540        if (saveLower[j] != lower[j])
3541          solver->setColLower(j,saveLower[j]);
3542        if (saveUpper[j] != upper[j])
3543          solver->setColUpper(j,saveUpper[j]);
3544      }
3545    }
3546    // If objective goes above certain amount we can set bound
3547    int jInt = back[iColumn];
3548    newLower[jInt]=upperValue;
3549    if (choice.finishedDown||!fastIterations)
3550      objLower[jInt]=choice.downMovement+objectiveValue_;
3551    else
3552      objLower[jInt]=objectiveValue_;
3553    newUpper[jInt]=lowerValue;
3554    if (choice.finishedUp||!fastIterations)
3555      objUpper[jInt]=choice.upMovement+objectiveValue_;
3556    else
3557      objUpper[jInt]=objectiveValue_;
3558    objMin = CoinMin(CoinMin(objLower[jInt],objUpper[jInt]),objMin);
3559    /*
3560      End of evaluation for this candidate variable. Possibilities are:
3561      * Both sides below cutoff; this variable is a candidate for branching.
3562      * Both sides infeasible or above the objective cutoff: no further action
3563      here. Break from the evaluation loop and assume the node will be purged
3564      by the caller.
3565      * One side below cutoff: Install the branch (i.e., fix the variable). Break
3566      from the evaluation loop and assume the node will be reoptimised by the
3567      caller.
3568    */
3569    if (choice.upMovement<1.0e100) {
3570      if(choice.downMovement<1.0e100) {
3571        objMax = CoinMax(CoinMax(objLower[jInt],objUpper[jInt]),objMax);
3572        // In case solution coming in was odd
3573        choice.upMovement = CoinMax(0.0,choice.upMovement);
3574        choice.downMovement = CoinMax(0.0,choice.downMovement);
3575        // feasible -
3576        model->messageHandler()->message(CBC_STRONG,model->messages())
3577          << iObject << iColumn
3578          <<choice.downMovement<<choice.numIntInfeasDown
3579          <<choice.upMovement<<choice.numIntInfeasUp
3580          <<value
3581          <<CoinMessageEol;
3582      } else {
3583        // up feasible, down infeasible
3584        anyAction=-1;
3585        if (!satisfied)
3586          needResolve=true;
3587        choice.fix=1;
3588        numberToFix++;
3589        saveLower[iColumn]=upperValue;
3590        solver->setColLower(iColumn,upperValue);
3591      }
3592    } else {
3593      if(choice.downMovement<1.0e100) {
3594        // down feasible, up infeasible
3595        anyAction=-1;
3596        if (!satisfied)
3597          needResolve=true;
3598        choice.fix=-1;
3599        numberToFix++;
3600        saveUpper[iColumn]=lowerValue;
3601        solver->setColUpper(iColumn,lowerValue);
3602      } else {
3603        // neither side feasible
3604        anyAction=-2;
3605        printf("Both infeasible for choice %d sequence %d\n",i,
3606               model->object(choice.objectNumber)->columnNumber());
3607        delete ws;
3608        ws=NULL;
3609        solver->writeMps("bad");
3610        numberToFix=-1;
3611        delete choice.possibleBranch;
3612        choice.possibleBranch=NULL;
3613        break;
3614      }
3615    }
3616    delete choice.possibleBranch;
3617    if (numberIterationsAllowed<=0)
3618      break;
3619    //printf("obj %d, col %d, down %g up %g value %g\n",iObject,iColumn,
3620    //     choice.downMovement,choice.upMovement,value);
3621  }
3622  printf("Best possible solution %g, can fix more if solution of %g found - looked at %d variables in %d iterations\n",
3623         objMin,objMax,iDo,model->numberAnalyzeIterations()-numberIterationsAllowed);
3624  model->setNumberAnalyzeIterations(numberIterationsAllowed);
3625  // Delete the snapshot
3626  solver->unmarkHotStart();
3627  // back to normal
3628  solver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
3629  solver->setIntParam(OsiMaxNumIterationHotStart,saveLimit);
3630  // restore basis
3631  solver->setWarmStart(ws);
3632  delete ws;
3633   
3634  delete [] sort;
3635  delete [] whichObject;
3636  delete [] saveLower;
3637  delete [] saveUpper;
3638  delete [] back;
3639  // restore solution
3640  solver->setColSolution(saveSolution);
3641# ifdef COIN_HAS_CLP
3642  if (osiclp) 
3643    osiclp->setSpecialOptions(saveClpOptions);
3644# endif
3645  model->reserveCurrentSolution(saveSolution);
3646  delete [] saveSolution;
3647  if (needResolve)
3648    solver->resolve();
3649  return numberToFix;
3650}
3651
3652
3653CbcNode::CbcNode(const CbcNode & rhs) 
3654{ 
3655#ifdef CHECK_NODE
3656  printf("CbcNode %x Constructor from rhs %x\n",this,&rhs);
3657#endif
3658  if (rhs.nodeInfo_)
3659    nodeInfo_ = rhs.nodeInfo_->clone();
3660  else
3661    nodeInfo_=NULL;
3662  objectiveValue_=rhs.objectiveValue_;
3663  guessedObjectiveValue_ = rhs.guessedObjectiveValue_;
3664  if (rhs.branch_)
3665    branch_=rhs.branch_->clone();
3666  else
3667    branch_=NULL;
3668  depth_ = rhs.depth_;
3669  numberUnsatisfied_ = rhs.numberUnsatisfied_;
3670}
3671
3672CbcNode &
3673CbcNode::operator=(const CbcNode & rhs)
3674{
3675  if (this != &rhs) {
3676    delete nodeInfo_;
3677    if (nodeInfo_)
3678      nodeInfo_ = rhs.nodeInfo_->clone();
3679    else
3680      nodeInfo_ = NULL;
3681    objectiveValue_=rhs.objectiveValue_;
3682    guessedObjectiveValue_ = rhs.guessedObjectiveValue_;
3683    if (rhs.branch_)
3684      branch_=rhs.branch_->clone();
3685    else
3686      branch_=NULL,
3687    depth_ = rhs.depth_;
3688    numberUnsatisfied_ = rhs.numberUnsatisfied_;
3689  }
3690  return *this;
3691}
3692
3693
3694CbcNode::~CbcNode ()
3695{
3696#ifdef CHECK_NODE
3697  if (nodeInfo_) 
3698    printf("CbcNode %x Destructor nodeInfo %x (%d)\n",
3699         this,nodeInfo_,nodeInfo_->numberPointingToThis());
3700  else
3701    printf("CbcNode %x Destructor nodeInfo %x (?)\n",
3702         this,nodeInfo_);
3703#endif
3704  if (nodeInfo_) {
3705    nodeInfo_->nullOwner();
3706    int numberToDelete=nodeInfo_->numberBranchesLeft();
3707    //    CbcNodeInfo * parent = nodeInfo_->parent();
3708    if (nodeInfo_->decrement(numberToDelete)==0) {
3709      delete nodeInfo_;
3710    } else {
3711      //printf("node %x nodeinfo %x parent %x\n",this,nodeInfo_,parent);
3712      // anyway decrement parent
3713      //if (parent)
3714      ///parent->decrement(1);
3715    }
3716  }
3717  delete branch_;
3718}
3719// Decrement  active cut counts
3720void 
3721CbcNode::decrementCuts(int change)
3722{
3723  if(nodeInfo_) {
3724    nodeInfo_->decrementCuts(change);
3725  }
3726}
3727void 
3728CbcNode::decrementParentCuts(int change)
3729{
3730  if(nodeInfo_) {
3731    nodeInfo_->decrementParentCuts(change);
3732  }
3733}
3734
3735/*
3736  Initialize reference counts (numberPointingToThis, numberBranchesLeft_)
3737  in the attached nodeInfo_.
3738*/
3739void
3740CbcNode::initializeInfo()
3741{
3742  assert(nodeInfo_ && branch_) ;
3743  nodeInfo_->initializeInfo(branch_->numberBranches());
3744}
3745// Nulls out node info
3746void 
3747CbcNode::nullNodeInfo()
3748{
3749  nodeInfo_=NULL;
3750}
3751
3752int
3753CbcNode::branch()
3754{
3755  double changeInGuessed=branch_->branch(true);
3756  guessedObjectiveValue_+= changeInGuessed;
3757  //#define PRINTIT
3758#ifdef PRINTIT
3759  int numberLeft = nodeInfo_->numberBranchesLeft();
3760  CbcNodeInfo * parent = nodeInfo_->parent();
3761  int parentNodeNumber = -1;
3762  //CbcBranchingObject * object1 = branch_->object_;
3763  //CbcObject * object = object1->
3764  //int sequence = object->columnNumber);
3765  int id=-1;
3766  double value=0.0;
3767  if (branch_) {
3768    id = branch_->variable();
3769    value = branch_->value();
3770  }
3771  printf("id %d value %g objvalue %g\n",id,value,objectiveValue_);
3772  if (parent)
3773    parentNodeNumber = parent->nodeNumber();
3774  printf("Node number %d, %s, way %d, depth %d, parent node number %d\n",
3775         nodeInfo_->nodeNumber(),(numberLeft==2) ? "leftBranch" : "rightBranch",
3776         way(),depth_,parentNodeNumber);
3777#endif
3778  return nodeInfo_->branchedOn();
3779}
Note: See TracBrowser for help on using the repository browser.