source: trunk/CbcNode.cpp @ 211

Last change on this file since 211 was 211, checked in by forrest, 16 years ago

for analyze

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