source: trunk/CbcNode.cpp @ 300

Last change on this file since 300 was 300, checked in by lou, 15 years ago

addCuts: separate debug code levels for clarity. FULL_DEBUG -> CBC_CHECK_BASIS

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