source: trunk/CbcNode.cpp @ 277

Last change on this file since 277 was 277, checked in by lou, 14 years ago

Revise cbc build process for better control of solvers included in build
(COIN_USE_XXX -> CBC_USE_XXX). Add CbcEventHandler? for independence from
clp.

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