source: stable/2.8/Cbc/src/CbcNode.cpp @ 2079

Last change on this file since 2079 was 2079, checked in by forrest, 5 years ago

changes for non simplex solvers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 203.8 KB
Line 
1/* $Id: CbcNode.cpp 2079 2014-09-24 09:54:25Z forrest $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#if defined(_MSC_VER)
7// Turn off compiler warning about long names
8#  pragma warning(disable:4786)
9#endif
10
11#include "CbcConfig.h"
12//#define DEBUG_SOLUTION
13#ifdef DEBUG_SOLUTION
14#define COIN_DETAIL
15#endif
16#include <string>
17//#define CBC_DEBUG 1
18//#define CHECK_CUT_COUNTS
19//#define CHECK_NODE
20//#define CBC_CHECK_BASIS
21#include <cassert>
22#include <cfloat>
23#define CUTS
24#include "OsiSolverInterface.hpp"
25#include "OsiChooseVariable.hpp"
26#include "OsiAuxInfo.hpp"
27#include "OsiSolverBranch.hpp"
28#include "CoinWarmStartBasis.hpp"
29#include "CoinTime.hpp"
30#include "CbcModel.hpp"
31#include "CbcNode.hpp"
32#include "CbcStatistics.hpp"
33#include "CbcStrategy.hpp"
34#include "CbcBranchActual.hpp"
35#include "CbcBranchDynamic.hpp"
36#include "OsiRowCut.hpp"
37#include "OsiRowCutDebugger.hpp"
38#include "OsiCuts.hpp"
39#include "CbcCountRowCut.hpp"
40#include "CbcFeasibilityBase.hpp"
41#include "CbcMessage.hpp"
42#ifdef COIN_HAS_CLP
43#include "OsiClpSolverInterface.hpp"
44#include "ClpSimplexOther.hpp"
45#endif
46using namespace std;
47#include "CglCutGenerator.hpp"
48
49
50CbcNode::CbcNode() :
51        nodeInfo_(NULL),
52        objectiveValue_(1.0e100),
53        guessedObjectiveValue_(1.0e100),
54        sumInfeasibilities_(0.0),
55        branch_(NULL),
56        depth_(-1),
57        numberUnsatisfied_(0),
58        nodeNumber_(-1),
59        state_(0)
60{
61#ifdef CHECK_NODE
62    printf("CbcNode %x Constructor\n", this);
63#endif
64}
65// Print
66void
67CbcNode::print() const
68{
69    printf("number %d obj %g depth %d sumun %g nunsat %d state %d\n",
70           nodeNumber_, objectiveValue_, depth_, sumInfeasibilities_, numberUnsatisfied_, state_);
71}
72CbcNode::CbcNode(CbcModel * model,
73                 CbcNode * lastNode) :
74        nodeInfo_(NULL),
75        objectiveValue_(1.0e100),
76        guessedObjectiveValue_(1.0e100),
77        sumInfeasibilities_(0.0),
78        branch_(NULL),
79        depth_(-1),
80        numberUnsatisfied_(0),
81        nodeNumber_(-1),
82        state_(0)
83{
84#ifdef CHECK_NODE
85    printf("CbcNode %x Constructor from model\n", this);
86#endif
87    model->setObjectiveValue(this, lastNode);
88
89    if (lastNode) {
90        if (lastNode->nodeInfo_) {
91            lastNode->nodeInfo_->increment();
92        }
93    }
94    nodeNumber_ = model->getNodeCount();
95}
96
97#define CBC_NEW_CREATEINFO
98#ifdef CBC_NEW_CREATEINFO
99
100/*
101  New createInfo, with basis manipulation hidden inside mergeBasis. Allows
102  solvers to override and carry over all information from one basis to
103  another.
104*/
105
106void
107CbcNode::createInfo (CbcModel *model,
108                     CbcNode *lastNode,
109                     const CoinWarmStartBasis *lastws,
110                     const double *lastLower, const double *lastUpper,
111                     int numberOldActiveCuts, int numberNewCuts)
112
113{
114    OsiSolverInterface *solver = model->solver();
115    CbcStrategy *strategy = model->strategy();
116    /*
117      The root --- no parent. Create full basis and bounds information.
118    */
119    if (!lastNode) {
120        if (!strategy)
121            nodeInfo_ = new CbcFullNodeInfo(model, solver->getNumRows());
122        else
123            nodeInfo_ = strategy->fullNodeInfo(model, solver->getNumRows());
124    } else {
125        /*
126          Not the root. Create an edit from the parent's basis & bound information.
127          This is not quite as straightforward as it seems. We need to reintroduce
128          cuts we may have dropped out of the basis, in the correct position, because
129          this whole process is strictly positional. Start by grabbing the current
130          basis.
131        */
132        bool mustDeleteBasis;
133        const CoinWarmStartBasis *ws =
134            dynamic_cast<const CoinWarmStartBasis*>(solver->getPointerToWarmStart(mustDeleteBasis));
135        assert(ws != NULL); // make sure not volume
136        //int numberArtificials = lastws->getNumArtificial();
137        int numberColumns = solver->getNumCols();
138        int numberRowsAtContinuous = model->numberRowsAtContinuous();
139        int currentNumberCuts = model->currentNumberCuts();
140#   ifdef CBC_CHECK_BASIS
141        std::cout
142            << "Before expansion: orig " << numberRowsAtContinuous
143            << ", old " << numberOldActiveCuts
144            << ", new " << numberNewCuts
145            << ", current " << currentNumberCuts << "." << std::endl ;
146        ws->print();
147#   endif
148        /*
149          Clone the basis and resize it to hold the structural constraints, plus
150          all the cuts: old cuts, both active and inactive (currentNumberCuts),
151          and new cuts (numberNewCuts). This will become the expanded basis.
152        */
153        CoinWarmStartBasis *expanded =
154            dynamic_cast<CoinWarmStartBasis *>(ws->clone()) ;
155        int iCompact = numberRowsAtContinuous + numberOldActiveCuts + numberNewCuts ;
156        // int nPartial = numberRowsAtContinuous+currentNumberCuts;
157        int iFull = numberRowsAtContinuous + currentNumberCuts + numberNewCuts;
158        // int maxBasisLength = ((iFull+15)>>4)+((numberColumns+15)>>4);
159        // printf("l %d full %d\n",maxBasisLength,iFull);
160        expanded->resize(iFull, numberColumns);
161#   ifdef CBC_CHECK_BASIS
162        std::cout
163            << "\tFull basis " << iFull << " rows, "
164            << numberColumns << " columns; compact "
165            << iCompact << " rows." << std::endl ;
166#   endif
167        /*
168          Now flesh out the expanded basis. The clone already has the
169          correct status information for the variables and for the structural
170          (numberRowsAtContinuous) constraints. Any indices beyond nPartial must be
171          cuts created while processing this node --- they can be copied en bloc
172          into the correct position in the expanded basis. The space reserved for
173          xferRows is a gross overestimate.
174        */
175        CoinWarmStartBasis::XferVec xferRows ;
176        xferRows.reserve(iFull - numberRowsAtContinuous + 1) ;
177        if (numberNewCuts) {
178            xferRows.push_back(
179                CoinWarmStartBasis::XferEntry(iCompact - numberNewCuts,
180                                              iFull - numberNewCuts, numberNewCuts)) ;
181        }
182        /*
183          From nPartial down, record the entries we want to copy from the current
184          basis (the entries for the active cuts; non-zero in the list returned
185          by addedCuts). Fill the expanded basis with entries showing a status of
186          basic for the deactivated (loose) cuts.
187        */
188        CbcCountRowCut **cut = model->addedCuts();
189        iFull -= (numberNewCuts + 1) ;
190        iCompact -= (numberNewCuts + 1) ;
191        int runLen = 0 ;
192        CoinWarmStartBasis::XferEntry entry(-1, -1, -1) ;
193        while (iFull >= numberRowsAtContinuous) {
194            for ( ; iFull >= numberRowsAtContinuous &&
195                    cut[iFull-numberRowsAtContinuous] ; iFull--)
196                runLen++ ;
197            if (runLen) {
198                iCompact -= runLen ;
199                entry.first = iCompact + 1 ;
200                entry.second = iFull + 1 ;
201                entry.third = runLen ;
202                runLen = 0 ;
203                xferRows.push_back(entry) ;
204            }
205            for ( ; iFull >= numberRowsAtContinuous &&
206                    !cut[iFull-numberRowsAtContinuous] ; iFull--)
207                expanded->setArtifStatus(iFull, CoinWarmStartBasis::basic);
208        }
209        /*
210          Finally, call mergeBasis to copy over entries from the current basis to
211          the expanded basis. Since we cloned the expanded basis from the active basis
212          and haven't changed the number of variables, only row status entries need
213          to be copied.
214        */
215        expanded->mergeBasis(ws, &xferRows, 0) ;
216
217#ifdef CBC_CHECK_BASIS
218        std::cout << "Expanded basis:" << std::endl ;
219        expanded->print() ;
220        std::cout << "Diffing against:" << std::endl ;
221        lastws->print() ;
222#endif
223        assert (expanded->getNumArtificial() >= lastws->getNumArtificial());
224#ifdef CLP_INVESTIGATE
225        if (!expanded->fullBasis()) {
226            int iFull = numberRowsAtContinuous + currentNumberCuts + numberNewCuts;
227            printf("cont %d old %d new %d current %d full inc %d full %d\n",
228                   numberRowsAtContinuous, numberOldActiveCuts, numberNewCuts,
229                   currentNumberCuts, iFull, iFull - numberNewCuts);
230        }
231#endif
232
233        /*
234          Now that we have two bases in proper positional correspondence, creating
235          the actual diff is dead easy.
236
237          Note that we're going to compare the expanded basis here to the stripped
238          basis (lastws) produced by addCuts. It doesn't affect the correctness (the
239          diff process has no knowledge of the meaning of an entry) but it does
240          mean that we'll always generate a whack of diff entries because the expanded
241          basis is considerably larger than the stripped basis.
242        */
243        CoinWarmStartDiff *basisDiff = expanded->generateDiff(lastws) ;
244
245        /*
246          Diff the bound vectors. It's assumed the number of structural variables
247          is not changing. For branching objects that change bounds on integer
248          variables, we should see at least one bound change as a consequence
249          of applying the branch that generated this subproblem from its parent.
250          This need not hold for other types of branching objects (hyperplane
251          branches, for example).
252        */
253        const double * lower = solver->getColLower();
254        const double * upper = solver->getColUpper();
255
256        double *boundChanges = new double [2*numberColumns] ;
257        int *variables = new int [2*numberColumns] ;
258        int numberChangedBounds = 0;
259
260        int i;
261        for (i = 0; i < numberColumns; i++) {
262            if (lower[i] != lastLower[i]) {
263                variables[numberChangedBounds] = i;
264                boundChanges[numberChangedBounds++] = lower[i];
265            }
266            if (upper[i] != lastUpper[i]) {
267                variables[numberChangedBounds] = i | 0x80000000;
268                boundChanges[numberChangedBounds++] = upper[i];
269            }
270#ifdef CBC_DEBUG
271            if (lower[i] != lastLower[i]) {
272                std::cout
273                    << "lower on " << i << " changed from "
274                    << lastLower[i] << " to " << lower[i] << std::endl ;
275            }
276            if (upper[i] != lastUpper[i]) {
277                std::cout
278                    << "upper on " << i << " changed from "
279                    << lastUpper[i] << " to " << upper[i] << std::endl ;
280            }
281#endif
282        }
283#ifdef CBC_DEBUG
284        std::cout << numberChangedBounds << " changed bounds." << std::endl ;
285#endif
286        //if (lastNode->branchingObject()->boundBranch())
287        //assert (numberChangedBounds);
288        /*
289          Hand the lot over to the CbcPartialNodeInfo constructor, then clean up and
290          return.
291        */
292        if (!strategy)
293            nodeInfo_ =
294                new CbcPartialNodeInfo(lastNode->nodeInfo_, this, numberChangedBounds,
295                                       variables, boundChanges, basisDiff) ;
296        else
297            nodeInfo_ =
298                strategy->partialNodeInfo(model, lastNode->nodeInfo_, this,
299                                          numberChangedBounds, variables, boundChanges,
300                                          basisDiff) ;
301        delete basisDiff ;
302        delete [] boundChanges;
303        delete [] variables;
304        delete expanded ;
305        if  (mustDeleteBasis)
306            delete ws;
307    }
308    // Set node number
309    nodeInfo_->setNodeNumber(model->getNodeCount2());
310    state_ |= 2; // say active
311}
312
313#else   // CBC_NEW_CREATEINFO
314
315/*
316  Original createInfo, with bare manipulation of basis vectors. Fails if solver
317  maintains additional information in basis.
318*/
319
320void
321CbcNode::createInfo (CbcModel *model,
322                     CbcNode *lastNode,
323                     const CoinWarmStartBasis *lastws,
324                     const double *lastLower, const double *lastUpper,
325                     int numberOldActiveCuts, int numberNewCuts)
326{
327    OsiSolverInterface * solver = model->solver();
328    CbcStrategy * strategy = model->strategy();
329    /*
330      The root --- no parent. Create full basis and bounds information.
331    */
332    if (!lastNode) {
333        if (!strategy)
334            nodeInfo_ = new CbcFullNodeInfo(model, solver->getNumRows());
335        else
336            nodeInfo_ = strategy->fullNodeInfo(model, solver->getNumRows());
337    }
338    /*
339      Not the root. Create an edit from the parent's basis & bound information.
340      This is not quite as straightforward as it seems. We need to reintroduce
341      cuts we may have dropped out of the basis, in the correct position, because
342      this whole process is strictly positional. Start by grabbing the current
343      basis.
344    */
345    else {
346        bool mustDeleteBasis;
347        const CoinWarmStartBasis* ws =
348            dynamic_cast<const CoinWarmStartBasis*>(solver->getPointerToWarmStart(mustDeleteBasis));
349        assert(ws != NULL); // make sure not volume
350        //int numberArtificials = lastws->getNumArtificial();
351        int numberColumns = solver->getNumCols();
352
353        const double * lower = solver->getColLower();
354        const double * upper = solver->getColUpper();
355
356        int i;
357        /*
358        Create a clone and resize it to hold all the structural constraints, plus
359        all the cuts: old cuts, both active and inactive (currentNumberCuts), and
360        new cuts (numberNewCuts).
361
362        TODO: You'd think that the set of constraints (logicals) in the expanded
363        basis should match the set represented in lastws. At least, that's
364        what I thought. But at the point I first looked hard at this bit of
365        code, it turned out that lastws was the stripped basis produced at
366        the end of addCuts(), rather than the raw basis handed back by
367        addCuts1(). The expanded basis here is equivalent to the raw basis of
368        addCuts1(). I said ``whoa, that's not good, I must have introduced a
369        bug'' and went back to John's code to see where I'd gone wrong.
370        And discovered the same `error' in his code.
371
372        After a bit of thought, my conclusion is that correctness is not
373        affected by whether lastws is the stripped or raw basis. The diffs
374        have no semantics --- just a set of changes that need to be made
375        to convert lastws into expanded. I think the only effect is that we
376        store a lot more diffs (everything in expanded that's not covered by
377        the stripped basis). But I need to give this more thought. There
378        may well be some subtle error cases.
379
380        In the mean time, I've twiddled addCuts() to set lastws to the raw
381        basis. Makes me (Lou) less nervous to compare apples to apples.
382        */
383        CoinWarmStartBasis *expanded =
384            dynamic_cast<CoinWarmStartBasis *>(ws->clone()) ;
385        int numberRowsAtContinuous = model->numberRowsAtContinuous();
386        int iFull = numberRowsAtContinuous + model->currentNumberCuts() +
387                    numberNewCuts;
388        //int numberArtificialsNow = iFull;
389        //int maxBasisLength = ((iFull+15)>>4)+((numberColumns+15)>>4);
390        //printf("l %d full %d\n",maxBasisLength,iFull);
391        if (expanded)
392            expanded->resize(iFull, numberColumns);
393#ifdef CBC_CHECK_BASIS
394        printf("Before expansion: orig %d, old %d, new %d, current %d\n",
395               numberRowsAtContinuous, numberOldActiveCuts, numberNewCuts,
396               model->currentNumberCuts()) ;
397        ws->print();
398#endif
399        /*
400        Now fill in the expanded basis. Any indices beyond nPartial must
401        be cuts created while processing this node --- they can be copied directly
402        into the expanded basis. From nPartial down, pull the status of active cuts
403        from ws, interleaving with a B entry for the deactivated (loose) cuts.
404        */
405        int numberDropped = model->currentNumberCuts() - numberOldActiveCuts;
406        int iCompact = iFull - numberDropped;
407        CbcCountRowCut ** cut = model->addedCuts();
408        int nPartial = model->currentNumberCuts() + numberRowsAtContinuous;
409        iFull--;
410        for (; iFull >= nPartial; iFull--) {
411            CoinWarmStartBasis::Status status = ws->getArtifStatus(--iCompact);
412            //assert (status != CoinWarmStartBasis::basic); // may be permanent cut
413            expanded->setArtifStatus(iFull, status);
414        }
415        for (; iFull >= numberRowsAtContinuous; iFull--) {
416            if (cut[iFull-numberRowsAtContinuous]) {
417                CoinWarmStartBasis::Status status = ws->getArtifStatus(--iCompact);
418                // If no cut generator being used then we may have basic variables
419                //if (model->getMaximumCutPasses()&&
420                //  status == CoinWarmStartBasis::basic)
421                //printf("cut basic\n");
422                expanded->setArtifStatus(iFull, status);
423            } else {
424                expanded->setArtifStatus(iFull, CoinWarmStartBasis::basic);
425            }
426        }
427#ifdef CBC_CHECK_BASIS
428        printf("Expanded basis\n");
429        expanded->print() ;
430        printf("Diffing against\n") ;
431        lastws->print() ;
432#endif
433        /*
434        Now that we have two bases in proper positional correspondence, creating
435        the actual diff is dead easy.
436        */
437
438        CoinWarmStartDiff *basisDiff = expanded->generateDiff(lastws) ;
439        /*
440        Diff the bound vectors. It's assumed the number of structural variables is
441        not changing. Assuming that branching objects all involve integer variables,
442        we should see at least one bound change as a consequence of processing this
443        subproblem. Different types of branching objects could break this assertion.
444        Not true at all - we have not applied current branch - JJF.
445        */
446        double *boundChanges = new double [2*numberColumns] ;
447        int *variables = new int [2*numberColumns] ;
448        int numberChangedBounds = 0;
449        for (i = 0; i < numberColumns; i++) {
450            if (lower[i] != lastLower[i]) {
451                variables[numberChangedBounds] = i;
452                boundChanges[numberChangedBounds++] = lower[i];
453            }
454            if (upper[i] != lastUpper[i]) {
455                variables[numberChangedBounds] = i | 0x80000000;
456                boundChanges[numberChangedBounds++] = upper[i];
457            }
458#ifdef CBC_DEBUG
459            if (lower[i] != lastLower[i])
460                printf("lower on %d changed from %g to %g\n",
461                       i, lastLower[i], lower[i]);
462            if (upper[i] != lastUpper[i])
463                printf("upper on %d changed from %g to %g\n",
464                       i, lastUpper[i], upper[i]);
465#endif
466        }
467#ifdef CBC_DEBUG
468        printf("%d changed bounds\n", numberChangedBounds) ;
469#endif
470        //if (lastNode->branchingObject()->boundBranch())
471        //assert (numberChangedBounds);
472        /*
473        Hand the lot over to the CbcPartialNodeInfo constructor, then clean up and
474        return.
475        */
476        if (!strategy)
477            nodeInfo_ =
478                new CbcPartialNodeInfo(lastNode->nodeInfo_, this, numberChangedBounds,
479                                       variables, boundChanges, basisDiff) ;
480        else
481            nodeInfo_ = strategy->partialNodeInfo(model, lastNode->nodeInfo_, this, numberChangedBounds,
482                                                  variables, boundChanges, basisDiff) ;
483        delete basisDiff ;
484        delete [] boundChanges;
485        delete [] variables;
486        delete expanded ;
487        if  (mustDeleteBasis)
488            delete ws;
489    }
490    // Set node number
491    nodeInfo_->setNodeNumber(model->getNodeCount2());
492    state_ |= 2; // say active
493}
494
495#endif  // CBC_NEW_CREATEINFO
496/*
497  The routine scans through the object list of the model looking for objects
498  that indicate infeasibility. It tests each object using strong branching
499  and selects the one with the least objective degradation.  A corresponding
500  branching object is left attached to lastNode.
501
502  If strong branching is disabled, a candidate object is chosen essentially
503  at random (whatever object ends up in pos'n 0 of the candidate array).
504
505  If a branching candidate is found to be monotone, bounds are set to fix the
506  variable and the routine immediately returns (the caller is expected to
507  reoptimize).
508
509  If a branching candidate is found to result in infeasibility in both
510  directions, the routine immediately returns an indication of infeasibility.
511
512  Returns:  0   both branch directions are feasible
513  -1    branching variable is monotone
514  -2    infeasible
515
516  Original comments:
517  Here could go cuts etc etc
518  For now just fix on objective from strong branching.
519*/
520
521int CbcNode::chooseBranch (CbcModel *model, CbcNode *lastNode, int numberPassesLeft)
522
523{
524    if (lastNode)
525        depth_ = lastNode->depth_ + 1;
526    else
527        depth_ = 0;
528    delete branch_;
529    branch_ = NULL;
530    OsiSolverInterface * solver = model->solver();
531# ifdef COIN_HAS_CLP
532    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
533    int saveClpOptions = 0;
534    if (osiclp) {
535        // for faster hot start
536        saveClpOptions = osiclp->specialOptions();
537        osiclp->setSpecialOptions(saveClpOptions | 8192);
538    }
539# else
540    OsiSolverInterface *osiclp = NULL ;
541# endif
542    double saveObjectiveValue = solver->getObjValue();
543    double objectiveValue = CoinMax(solver->getObjSense() * saveObjectiveValue, objectiveValue_);
544    const double * lower = solver->getColLower();
545    const double * upper = solver->getColUpper();
546    // See what user thinks
547    int anyAction = model->problemFeasibility()->feasible(model, 0);
548    if (anyAction) {
549        // will return -2 if infeasible , 0 if treat as integer
550        return anyAction - 1;
551    }
552    double integerTolerance =
553        model->getDblParam(CbcModel::CbcIntegerTolerance);
554    // point to useful information
555    OsiBranchingInformation usefulInfo = model->usefulInformation();
556    // and modify
557    usefulInfo.depth_ = depth_;
558    int i;
559    bool beforeSolution = model->getSolutionCount() == 0;
560    int numberStrong = model->numberStrong();
561    // switch off strong if hotstart
562    const double * hotstartSolution = model->hotstartSolution();
563    const int * hotstartPriorities = model->hotstartPriorities();
564    int numberObjects = model->numberObjects();
565    int numberColumns = model->getNumCols();
566    double * saveUpper = new double[numberColumns];
567    double * saveLower = new double[numberColumns];
568    for (i = 0; i < numberColumns; i++) {
569        saveLower[i] = lower[i];
570        saveUpper[i] = upper[i];
571    }
572
573    // Save solution in case heuristics need good solution later
574
575    double * saveSolution = new double[numberColumns];
576    memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
577    model->reserveCurrentSolution(saveSolution);
578    if (hotstartSolution) {
579        numberStrong = 0;
580        if ((model->moreSpecialOptions()&1024) != 0) {
581            int nBad = 0;
582            int nUnsat = 0;
583            int nDiff = 0;
584            for (int i = 0; i < numberObjects; i++) {
585                OsiObject * object = model->modifiableObject(i);
586                const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object);
587                if (thisOne) {
588                    int iColumn = thisOne->columnNumber();
589                    double targetValue = hotstartSolution[iColumn];
590                    double value = saveSolution[iColumn];
591                    if (fabs(value - floor(value + 0.5)) > 1.0e-6) {
592                        nUnsat++;
593#ifdef CLP_INVESTIGATE
594                        printf("H %d is %g target %g\n", iColumn, value, targetValue);
595#endif
596                    } else if (fabs(targetValue - value) > 1.0e-6) {
597                        nDiff++;
598                    }
599                    if (targetValue < saveLower[iColumn] ||
600                            targetValue > saveUpper[iColumn]) {
601#ifdef CLP_INVESTIGATE
602                        printf("%d has target %g and current bounds %g and %g\n",
603                               iColumn, targetValue, saveLower[iColumn], saveUpper[iColumn]);
604#endif
605                        nBad++;
606                    }
607                }
608            }
609#ifdef CLP_INVESTIGATE
610            printf("Hot %d unsatisfied, %d outside limits, %d different\n",
611                   nUnsat, nBad, nDiff);
612#endif
613            if (nBad) {
614                // switch off as not possible
615                hotstartSolution = NULL;
616                model->setHotstartSolution(NULL, NULL);
617                usefulInfo.hotstartSolution_ = NULL;
618            }
619        }
620    }
621    int numberStrongDone = 0;
622    int numberUnfinished = 0;
623    int numberStrongInfeasible = 0;
624    int numberStrongIterations = 0;
625    int saveNumberStrong = numberStrong;
626    bool checkFeasibility = numberObjects > model->numberIntegers();
627    int maximumStrong = CoinMax(CoinMin(numberStrong, numberObjects), 1);
628    /*
629      Get a branching decision object. Use the default decision criteria unless
630      the user has loaded a decision method into the model.
631    */
632    CbcBranchDecision *decision = model->branchingMethod();
633    CbcDynamicPseudoCostBranchingObject * dynamicBranchingObject =
634        dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(decision);
635    if (!decision || dynamicBranchingObject)
636        decision = new CbcBranchDefaultDecision();
637    decision->initialize(model);
638    CbcStrongInfo * choice = new CbcStrongInfo[maximumStrong];
639    // May go round twice if strong branching fixes all local candidates
640    bool finished = false;
641    double estimatedDegradation = 0.0;
642    while (!finished) {
643        finished = true;
644        // Some objects may compute an estimate of best solution from here
645        estimatedDegradation = 0.0;
646        //int numberIntegerInfeasibilities=0; // without odd ones
647        numberStrongDone = 0;
648        numberUnfinished = 0;
649        numberStrongInfeasible = 0;
650        numberStrongIterations = 0;
651
652        // We may go round this loop twice (only if we think we have solution)
653        for (int iPass = 0; iPass < 2; iPass++) {
654
655            // compute current state
656            //int numberObjectInfeasibilities; // just odd ones
657            //model->feasibleSolution(
658            //                      numberIntegerInfeasibilities,
659            //                      numberObjectInfeasibilities);
660            // Some objects may compute an estimate of best solution from here
661            estimatedDegradation = 0.0;
662            numberUnsatisfied_ = 0;
663            // initialize sum of "infeasibilities"
664            sumInfeasibilities_ = 0.0;
665            int bestPriority = COIN_INT_MAX;
666            /*
667              Scan for branching objects that indicate infeasibility. Choose the best
668              maximumStrong candidates, using priority as the first criteria, then
669              integer infeasibility.
670
671              The algorithm is to fill the choice array with a set of good candidates (by
672              infeasibility) with priority bestPriority.  Finding a candidate with
673              priority better (less) than bestPriority flushes the choice array. (This
674              serves as initialization when the first candidate is found.)
675
676              A new candidate is added to choices only if its infeasibility exceeds the
677              current max infeasibility (mostAway). When a candidate is added, it
678              replaces the candidate with the smallest infeasibility (tracked by
679              iSmallest).
680            */
681            int iSmallest = 0;
682            double mostAway = 1.0e-100;
683            for (i = 0 ; i < maximumStrong ; i++)
684                choice[i].possibleBranch = NULL ;
685            numberStrong = 0;
686            bool canDoOneHot = false;
687            for (i = 0; i < numberObjects; i++) {
688                OsiObject * object = model->modifiableObject(i);
689                int preferredWay;
690                double infeasibility = object->infeasibility(&usefulInfo, preferredWay);
691                int priorityLevel = object->priority();
692                if (hotstartSolution) {
693                    // we are doing hot start
694                    const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object);
695                    if (thisOne) {
696                        int iColumn = thisOne->columnNumber();
697                        bool canDoThisHot = true;
698                        double targetValue = hotstartSolution[iColumn];
699                        if (saveUpper[iColumn] > saveLower[iColumn]) {
700                            double value = saveSolution[iColumn];
701                            if (hotstartPriorities)
702                                priorityLevel = hotstartPriorities[iColumn];
703                            //double originalLower = thisOne->originalLower();
704                            //double originalUpper = thisOne->originalUpper();
705                            // switch off if not possible
706                            if (targetValue >= saveLower[iColumn] && targetValue <= saveUpper[iColumn]) {
707                                /* priority outranks rest always if negative
708                                   otherwise can be downgraded if at correct level.
709                                   Infeasibility may be increased to choose 1.0 values first.
710                                   choose one near wanted value
711                                */
712                                if (fabs(value - targetValue) > integerTolerance) {
713                                    //if (infeasibility>0.01)
714                                    //infeasibility = fabs(1.0e6-fabs(value-targetValue));
715                                    //else
716                                    infeasibility = fabs(value - targetValue);
717                                    //if (targetValue==1.0)
718                                    //infeasibility += 1.0;
719                                    if (value > targetValue) {
720                                        preferredWay = -1;
721                                    } else {
722                                        preferredWay = 1;
723                                    }
724                                    priorityLevel = CoinAbs(priorityLevel);
725                                } else if (priorityLevel < 0) {
726                                    priorityLevel = CoinAbs(priorityLevel);
727                                    if (targetValue == saveLower[iColumn]) {
728                                        infeasibility = integerTolerance + 1.0e-12;
729                                        preferredWay = -1;
730                                    } else if (targetValue == saveUpper[iColumn]) {
731                                        infeasibility = integerTolerance + 1.0e-12;
732                                        preferredWay = 1;
733                                    } else {
734                                        // can't
735                                        priorityLevel += 10000000;
736                                        canDoThisHot = false;
737                                    }
738                                } else {
739                                    priorityLevel += 10000000;
740                                    canDoThisHot = false;
741                                }
742                            } else {
743                                // switch off if not possible
744                                canDoThisHot = false;
745                            }
746                            if (canDoThisHot)
747                                canDoOneHot = true;
748                        } else if (targetValue < saveLower[iColumn] || targetValue > saveUpper[iColumn]) {
749                        }
750                    } else {
751                        priorityLevel += 10000000;
752                    }
753                }
754                if (infeasibility) {
755                    // Increase estimated degradation to solution
756                    estimatedDegradation += CoinMin(object->upEstimate(), object->downEstimate());
757                    numberUnsatisfied_++;
758                    sumInfeasibilities_ += infeasibility;
759                    // Better priority? Flush choices.
760                    if (priorityLevel < bestPriority) {
761                        int j;
762                        iSmallest = 0;
763                        for (j = 0; j < maximumStrong; j++) {
764                            choice[j].upMovement = 0.0;
765                            delete choice[j].possibleBranch;
766                            choice[j].possibleBranch = NULL;
767                        }
768                        bestPriority = priorityLevel;
769                        mostAway = 1.0e-100;
770                        numberStrong = 0;
771                    } else if (priorityLevel > bestPriority) {
772                        continue;
773                    }
774                    // Check for suitability based on infeasibility.
775                    if (infeasibility > mostAway) {
776                        //add to list
777                        choice[iSmallest].upMovement = infeasibility;
778                        delete choice[iSmallest].possibleBranch;
779                        CbcObject * obj =
780                            dynamic_cast <CbcObject *>(object) ;
781                        assert (obj);
782                        choice[iSmallest].possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay);
783                        numberStrong = CoinMax(numberStrong, iSmallest + 1);
784                        // Save which object it was
785                        choice[iSmallest].objectNumber = i;
786                        int j;
787                        iSmallest = -1;
788                        mostAway = 1.0e50;
789                        for (j = 0; j < maximumStrong; j++) {
790                            if (choice[j].upMovement < mostAway) {
791                                mostAway = choice[j].upMovement;
792                                iSmallest = j;
793                            }
794                        }
795                    }
796                }
797            }
798            if (!canDoOneHot && hotstartSolution) {
799                // switch off as not possible
800                hotstartSolution = NULL;
801                model->setHotstartSolution(NULL, NULL);
802                usefulInfo.hotstartSolution_ = NULL;
803            }
804            if (numberUnsatisfied_) {
805                // some infeasibilities - go to next steps
806#ifdef CLP_INVESTIGATE
807                if (hotstartSolution) {
808                    int k = choice[0].objectNumber;
809                    OsiObject * object = model->modifiableObject(k);
810                    const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object);
811                    assert (thisOne);
812                    int iColumn = thisOne->columnNumber();
813                    double targetValue = hotstartSolution[iColumn];
814                    double value = saveSolution[iColumn];
815                    printf("Branch on %d has target %g (value %g) and current bounds %g and %g\n",
816                           iColumn, targetValue, value, saveLower[iColumn], saveUpper[iColumn]);
817                }
818#endif
819                break;
820            } else if (!iPass) {
821                // looks like a solution - get paranoid
822                bool roundAgain = false;
823                // get basis
824                CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart());
825                if (!ws)
826                    break;
827                for (i = 0; i < numberColumns; i++) {
828                    double value = saveSolution[i];
829                    if (value < lower[i]) {
830                        saveSolution[i] = lower[i];
831                        roundAgain = true;
832                        ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound);
833                    } else if (value > upper[i]) {
834                        saveSolution[i] = upper[i];
835                        roundAgain = true;
836                        ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound);
837                    }
838                }
839                if (roundAgain && saveNumberStrong) {
840                    // restore basis
841                    solver->setWarmStart(ws);
842                    delete ws;
843                    solver->resolve();
844                    memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
845                    model->reserveCurrentSolution(saveSolution);
846                    if (!solver->isProvenOptimal()) {
847                        // infeasible
848                        anyAction = -2;
849                        break;
850                    }
851                } else {
852                    delete ws;
853                    break;
854                }
855            }
856        }
857        /* Some solvers can do the strong branching calculations faster if
858           they do them all at once.  At present only Clp does for ordinary
859           integers but I think this coding would be easy to modify
860        */
861        bool allNormal = true; // to say if we can do fast strong branching
862        // Say which one will be best
863        int bestChoice = 0;
864        double worstInfeasibility = 0.0;
865        for (i = 0; i < numberStrong; i++) {
866            choice[i].numIntInfeasUp = numberUnsatisfied_;
867            choice[i].numIntInfeasDown = numberUnsatisfied_;
868            choice[i].fix = 0; // say not fixed
869            if (!dynamic_cast <const CbcSimpleInteger *> (model->object(choice[i].objectNumber)))
870                allNormal = false; // Something odd so lets skip clever fast branching
871            if ( !model->object(choice[i].objectNumber)->boundBranch())
872                numberStrong = 0; // switch off
873            if ( choice[i].possibleBranch->numberBranches() > 2)
874                numberStrong = 0; // switch off
875            // Do best choice in case switched off
876            if (choice[i].upMovement > worstInfeasibility) {
877                worstInfeasibility = choice[i].upMovement;
878                bestChoice = i;
879            }
880        }
881        // If we have hit max time don't do strong branching
882        bool hitMaxTime = (model->getCurrentSeconds() >
883                            model->getDblParam(CbcModel::CbcMaximumSeconds));
884        // also give up if we are looping round too much
885        if (hitMaxTime || numberPassesLeft <= 0)
886            numberStrong = 0;
887        /*
888          Is strong branching enabled? If so, set up and do it. Otherwise, we'll
889          fall through to simple branching.
890
891          Setup for strong branching involves saving the current basis (for restoration
892          afterwards) and setting up for hot starts.
893        */
894        if (numberStrong && saveNumberStrong) {
895
896            bool solveAll = false; // set true to say look at all even if some fixed (experiment)
897            solveAll = true;
898            // worth trying if too many times
899            // Save basis
900            CoinWarmStart * ws = solver->getWarmStart();
901            // save limit
902            int saveLimit;
903            solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit);
904            if (beforeSolution && saveLimit < 100)
905                solver->setIntParam(OsiMaxNumIterationHotStart, 100); // go to end
906#     ifdef COIN_HAS_CLP
907            /* If we are doing all strong branching in one go then we create new arrays
908               to store information.  If clp NULL then doing old way.
909               Going down -
910               outputSolution[2*i] is final solution.
911               outputStuff[2*i] is status (0 - finished, 1 infeas, other unknown
912               outputStuff[2*i+numberStrong] is number iterations
913               On entry newUpper[i] is new upper bound, on exit obj change
914               Going up -
915               outputSolution[2*i+1] is final solution.
916               outputStuff[2*i+1] is status (0 - finished, 1 infeas, other unknown
917               outputStuff[2*i+1+numberStrong] is number iterations
918            On entry newLower[i] is new lower bound, on exit obj change
919            */
920            ClpSimplex * clp = NULL;
921            double * newLower = NULL;
922            double * newUpper = NULL;
923            double ** outputSolution = NULL;
924            int * outputStuff = NULL;
925            // Go back to normal way if user wants it
926            if (osiclp && (osiclp->specialOptions()&16) != 0 && osiclp->specialOptions() > 0)
927                allNormal = false;
928            if (osiclp && !allNormal) {
929                // say do fast
930                int easy = 1;
931                osiclp->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
932            }
933            if (osiclp && allNormal) {
934                clp = osiclp->getModelPtr();
935                // Clp - do a different way
936                newLower = new double[numberStrong];
937                newUpper = new double[numberStrong];
938                outputSolution = new double * [2*numberStrong];
939                outputStuff = new int [4*numberStrong];
940                int * which = new int[numberStrong];
941                int startFinishOptions;
942                int specialOptions = osiclp->specialOptions();
943                int clpOptions = clp->specialOptions();
944                int returnCode = 0;
945#define CRUNCH
946#ifdef CRUNCH
947                // Crunch down problem
948                int numberRows = clp->numberRows();
949                // Use dual region
950                double * rhs = clp->dualRowSolution();
951                int * whichRow = new int[3*numberRows];
952                int * whichColumn = new int[2*numberColumns];
953                int nBound;
954                ClpSimplex * small = static_cast<ClpSimplexOther *> (clp)->crunch(rhs, whichRow, whichColumn, nBound, true);
955                if (!small) {
956                    anyAction = -2;
957                    //printf("XXXX Inf by inspection\n");
958                    delete [] whichColumn;
959                    whichColumn = NULL;
960                    delete [] whichRow;
961                    whichRow = NULL;
962                    break;
963                } else {
964                    clp = small;
965                }
966#else
967                int saveLogLevel = clp->logLevel();
968                int saveMaxIts = clp->maximumIterations();
969#endif
970                clp->setLogLevel(0);
971                if ((specialOptions&1) == 0) {
972                    startFinishOptions = 0;
973                    clp->setSpecialOptions(clpOptions | (64 | 1024));
974                } else {
975                    startFinishOptions = 1 + 2 + 4;
976                    //startFinishOptions=1+4; // for moment re-factorize
977                    if ((specialOptions&4) == 0)
978                        clp->setSpecialOptions(clpOptions | (64 | 128 | 512 | 1024 | 4096));
979                    else
980                        clp->setSpecialOptions(clpOptions | (64 | 128 | 512 | 1024 | 2048 | 4096));
981                }
982                // User may want to clean up before strong branching
983                if ((clp->specialOptions()&32) != 0) {
984                    clp->primal(1);
985                    if (clp->numberIterations())
986                        model->messageHandler()->message(CBC_ITERATE_STRONG, *model->messagesPointer())
987                        << clp->numberIterations()
988                        << CoinMessageEol;
989                }
990                clp->setMaximumIterations(saveLimit);
991#ifdef CRUNCH
992                int * backColumn = whichColumn + numberColumns;
993#endif
994                for (i = 0; i < numberStrong; i++) {
995                    int iObject = choice[i].objectNumber;
996                    const OsiObject * object = model->object(iObject);
997                    const CbcSimpleInteger * simple = static_cast <const CbcSimpleInteger *> (object);
998                    int iSequence = simple->columnNumber();
999                    newLower[i] = ceil(saveSolution[iSequence]);
1000                    newUpper[i] = floor(saveSolution[iSequence]);
1001#ifdef CRUNCH
1002                    iSequence = backColumn[iSequence];
1003                    assert (iSequence >= 0);
1004#endif
1005                    which[i] = iSequence;
1006                    outputSolution[2*i] = new double [numberColumns];
1007                    outputSolution[2*i+1] = new double [numberColumns];
1008                }
1009                //clp->writeMps("bad");
1010                returnCode = clp->strongBranching(numberStrong, which,
1011                                                  newLower, newUpper, outputSolution,
1012                                                  outputStuff, outputStuff + 2 * numberStrong, !solveAll, false,
1013                                                  startFinishOptions);
1014#ifndef CRUNCH
1015                clp->setSpecialOptions(clpOptions); // restore
1016                clp->setMaximumIterations(saveMaxIts);
1017                clp->setLogLevel(saveLogLevel);
1018#endif
1019                if (returnCode == -2) {
1020                    // bad factorization!!!
1021                    // Doing normal way
1022                    // Mark hot start
1023                    solver->markHotStart();
1024                    clp = NULL;
1025                } else {
1026#ifdef CRUNCH
1027                    // extract solution
1028                    //bool checkSol=true;
1029                    for (i = 0; i < numberStrong; i++) {
1030                        int iObject = choice[i].objectNumber;
1031                        const OsiObject * object = model->object(iObject);
1032                        const CbcSimpleInteger * simple = static_cast <const CbcSimpleInteger *> (object);
1033                        int iSequence = simple->columnNumber();
1034                        which[i] = iSequence;
1035                        double * sol = outputSolution[2*i];
1036                        double * sol2 = outputSolution[2*i+1];
1037                        //bool x=true;
1038                        //bool x2=true;
1039                        for (int iColumn = numberColumns - 1; iColumn >= 0; iColumn--) {
1040                            int jColumn = backColumn[iColumn];
1041                            if (jColumn >= 0) {
1042                                sol[iColumn] = sol[jColumn];
1043                                sol2[iColumn] = sol2[jColumn];
1044                            } else {
1045                                sol[iColumn] = saveSolution[iColumn];
1046                                sol2[iColumn] = saveSolution[iColumn];
1047                            }
1048                        }
1049                    }
1050#endif
1051                }
1052#ifdef CRUNCH
1053                delete [] whichColumn;
1054                delete [] whichRow;
1055                delete small;
1056#endif
1057                delete [] which;
1058            } else {
1059                // Doing normal way
1060                // Mark hot start
1061                solver->markHotStart();
1062            }
1063#     else      /* COIN_HAS_CLP */
1064
1065            OsiSolverInterface *clp = NULL ;
1066            double **outputSolution = NULL ;
1067            int *outputStuff = NULL ;
1068            double * newLower = NULL ;
1069            double * newUpper = NULL ;
1070
1071            solver->markHotStart();
1072
1073#     endif     /* COIN_HAS_CLP */
1074            /*
1075              Open a loop to do the strong branching LPs. For each candidate variable,
1076              solve an LP with the variable forced down, then up. If a direction turns
1077              out to be infeasible or monotonic (i.e., over the dual objective cutoff),
1078              force the objective change to be big (1.0e100). If we determine the problem
1079              is infeasible, or find a monotone variable, escape the loop.
1080
1081              TODO: The `restore bounds' part might be better encapsulated as an
1082            unbranch() method. Branching objects more exotic than simple integers
1083            or cliques might not restrict themselves to variable bounds.
1084
1085              TODO: Virtuous solvers invalidate the current solution (or give bogus
1086            results :-) when the bounds are changed out from under them. So we
1087            need to do all the work associated with finding a new solution before
1088            restoring the bounds.
1089            */
1090            for (i = 0 ; i < numberStrong ; i++) {
1091                double objectiveChange ;
1092                double newObjectiveValue = 1.0e100;
1093                // status is 0 finished, 1 infeasible and other
1094                int iStatus;
1095                /*
1096                  Try the down direction first. (Specify the initial branching alternative as
1097                  down with a call to way(-1). Each subsequent call to branch() performs the
1098                  specified branch and advances the branch object state to the next branch
1099                  alternative.)
1100                */
1101                if (!clp) {
1102                    choice[i].possibleBranch->way(-1) ;
1103                    choice[i].possibleBranch->branch() ;
1104                    bool feasible = true;
1105                    if (checkFeasibility) {
1106                        // check branching did not make infeasible
1107                        int iColumn;
1108                        int numberColumns = solver->getNumCols();
1109                        const double * columnLower = solver->getColLower();
1110                        const double * columnUpper = solver->getColUpper();
1111                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1112                            if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5)
1113                                feasible = false;
1114                        }
1115                    }
1116                    if (feasible) {
1117                        solver->solveFromHotStart() ;
1118                        numberStrongDone++;
1119                        numberStrongIterations += solver->getIterationCount();
1120                        /*
1121                        We now have an estimate of objective degradation that we can use for strong
1122                        branching. If we're over the cutoff, the variable is monotone up.
1123                        If we actually made it to optimality, check for a solution, and if we have
1124                        a good one, call setBestSolution to process it. Note that this may reduce the
1125                        cutoff, so we check again to see if we can declare this variable monotone.
1126                        */
1127                        if (solver->isProvenOptimal())
1128                            iStatus = 0; // optimal
1129                        else if (solver->isIterationLimitReached()
1130                                 && !solver->isDualObjectiveLimitReached())
1131                            iStatus = 2; // unknown
1132                        else
1133                            iStatus = 1; // infeasible
1134                        newObjectiveValue = solver->getObjSense() * solver->getObjValue();
1135                        choice[i].numItersDown = solver->getIterationCount();
1136                    } else {
1137                        iStatus = 1; // infeasible
1138                        newObjectiveValue = 1.0e100;
1139                        choice[i].numItersDown = 0;
1140                    }
1141                } else {
1142                    iStatus = outputStuff[2*i];
1143                    choice[i].numItersDown = outputStuff[2*numberStrong+2*i];
1144                    numberStrongDone++;
1145                    numberStrongIterations += choice[i].numItersDown;
1146                    newObjectiveValue = objectiveValue + newUpper[i];
1147                    solver->setColSolution(outputSolution[2*i]);
1148                }
1149                objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_, 0.0);
1150                if (!iStatus) {
1151                    choice[i].finishedDown = true ;
1152                    if (newObjectiveValue >= model->getCutoff()) {
1153                        objectiveChange = 1.0e100; // say infeasible
1154                        numberStrongInfeasible++;
1155                    } else {
1156                        // See if integer solution
1157                        if (model->feasibleSolution(choice[i].numIntInfeasDown,
1158                                                    choice[i].numObjInfeasDown)
1159                                && model->problemFeasibility()->feasible(model, -1) >= 0) {
1160                            model->setBestSolution(CBC_STRONGSOL,
1161                                                   newObjectiveValue,
1162                                                   solver->getColSolution()) ;
1163                            // only needed for odd solvers
1164                            newObjectiveValue = solver->getObjSense() * solver->getObjValue();
1165                            objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0) ;
1166                            model->setLastHeuristic(NULL);
1167                            model->incrementUsed(solver->getColSolution());
1168                            if (newObjectiveValue >= model->getCutoff()) {      //  *new* cutoff
1169                                objectiveChange = 1.0e100 ;
1170                                numberStrongInfeasible++;
1171                            }
1172                        }
1173                    }
1174                } else if (iStatus == 1) {
1175                    objectiveChange = 1.0e100 ;
1176                    numberStrongInfeasible++;
1177                } else {
1178                    // Can't say much as we did not finish
1179                    choice[i].finishedDown = false ;
1180                    numberUnfinished++;
1181                }
1182                choice[i].downMovement = objectiveChange ;
1183
1184                // restore bounds
1185                if (!clp) {
1186                    for (int j = 0; j < numberColumns; j++) {
1187                        if (saveLower[j] != lower[j])
1188                            solver->setColLower(j, saveLower[j]);
1189                        if (saveUpper[j] != upper[j])
1190                            solver->setColUpper(j, saveUpper[j]);
1191                    }
1192                }
1193                //printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
1194                //     choice[i].objectNumber,iStatus,newObjectiveValue,choice[i].numItersDown,
1195                //     choice[i].downMovement,choice[i].finishedDown,choice[i].numIntInfeasDown,
1196                //     choice[i].numObjInfeasDown);
1197
1198                // repeat the whole exercise, forcing the variable up
1199                if (!clp) {
1200                    bool feasible = true;
1201                    // If odd branching then maybe just one possibility
1202                    if (choice[i].possibleBranch->numberBranchesLeft() > 0) {
1203                        choice[i].possibleBranch->branch();
1204                        if (checkFeasibility) {
1205                            // check branching did not make infeasible
1206                            int iColumn;
1207                            int numberColumns = solver->getNumCols();
1208                            const double * columnLower = solver->getColLower();
1209                            const double * columnUpper = solver->getColUpper();
1210                            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1211                                if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5)
1212                                    feasible = false;
1213                            }
1214                        }
1215                    } else {
1216                        // second branch infeasible
1217                        feasible = false;
1218                    }
1219                    if (feasible) {
1220                        solver->solveFromHotStart() ;
1221                        numberStrongDone++;
1222                        numberStrongIterations += solver->getIterationCount();
1223                        /*
1224                        We now have an estimate of objective degradation that we can use for strong
1225                        branching. If we're over the cutoff, the variable is monotone up.
1226                        If we actually made it to optimality, check for a solution, and if we have
1227                        a good one, call setBestSolution to process it. Note that this may reduce the
1228                        cutoff, so we check again to see if we can declare this variable monotone.
1229                        */
1230                        if (solver->isProvenOptimal())
1231                            iStatus = 0; // optimal
1232                        else if (solver->isIterationLimitReached()
1233                                 && !solver->isDualObjectiveLimitReached())
1234                            iStatus = 2; // unknown
1235                        else
1236                            iStatus = 1; // infeasible
1237                        newObjectiveValue = solver->getObjSense() * solver->getObjValue();
1238                        choice[i].numItersUp = solver->getIterationCount();
1239                    } else {
1240                        iStatus = 1; // infeasible
1241                        newObjectiveValue = 1.0e100;
1242                        choice[i].numItersDown = 0;
1243                    }
1244                } else {
1245                    iStatus = outputStuff[2*i+1];
1246                    choice[i].numItersUp = outputStuff[2*numberStrong+2*i+1];
1247                    numberStrongDone++;
1248                    numberStrongIterations += choice[i].numItersUp;
1249                    newObjectiveValue = objectiveValue + newLower[i];
1250                    solver->setColSolution(outputSolution[2*i+1]);
1251                }
1252                objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_, 0.0);
1253                if (!iStatus) {
1254                    choice[i].finishedUp = true ;
1255                    if (newObjectiveValue >= model->getCutoff()) {
1256                        objectiveChange = 1.0e100; // say infeasible
1257                        numberStrongInfeasible++;
1258                    } else {
1259                        // See if integer solution
1260                        if (model->feasibleSolution(choice[i].numIntInfeasUp,
1261                                                    choice[i].numObjInfeasUp)
1262                                && model->problemFeasibility()->feasible(model, -1) >= 0) {
1263                            model->setBestSolution(CBC_STRONGSOL,
1264                                                   newObjectiveValue,
1265                                                   solver->getColSolution()) ;
1266                            // only needed for odd solvers
1267                            newObjectiveValue = solver->getObjSense() * solver->getObjValue();
1268                            objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0) ;
1269                            model->setLastHeuristic(NULL);
1270                            model->incrementUsed(solver->getColSolution());
1271                            if (newObjectiveValue >= model->getCutoff()) {      //  *new* cutoff
1272                                objectiveChange = 1.0e100 ;
1273                                numberStrongInfeasible++;
1274                            }
1275                        }
1276                    }
1277                } else if (iStatus == 1) {
1278                    objectiveChange = 1.0e100 ;
1279                    numberStrongInfeasible++;
1280                } else {
1281                    // Can't say much as we did not finish
1282                    choice[i].finishedUp = false ;
1283                    numberUnfinished++;
1284                }
1285                choice[i].upMovement = objectiveChange ;
1286
1287                // restore bounds
1288                if (!clp) {
1289                    for (int j = 0; j < numberColumns; j++) {
1290                        if (saveLower[j] != lower[j])
1291                            solver->setColLower(j, saveLower[j]);
1292                        if (saveUpper[j] != upper[j])
1293                            solver->setColUpper(j, saveUpper[j]);
1294                    }
1295                }
1296
1297                //printf("Up on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
1298                //     choice[i].objectNumber,iStatus,newObjectiveValue,choice[i].numItersUp,
1299                //     choice[i].upMovement,choice[i].finishedUp,choice[i].numIntInfeasUp,
1300                //     choice[i].numObjInfeasUp);
1301
1302                /*
1303                  End of evaluation for this candidate variable. Possibilities are:
1304                  * Both sides below cutoff; this variable is a candidate for branching.
1305                  * Both sides infeasible or above the objective cutoff: no further action
1306                  here. Break from the evaluation loop and assume the node will be purged
1307                  by the caller.
1308                  * One side below cutoff: Install the branch (i.e., fix the variable). Break
1309                  from the evaluation loop and assume the node will be reoptimised by the
1310                  caller.
1311                */
1312                // reset
1313                choice[i].possibleBranch->resetNumberBranchesLeft();
1314                if (choice[i].upMovement < 1.0e100) {
1315                    if (choice[i].downMovement < 1.0e100) {
1316                        // feasible - no action
1317                    } else {
1318                        // up feasible, down infeasible
1319                        anyAction = -1;
1320                        //printf("Down infeasible for choice %d sequence %d\n",i,
1321                        // model->object(choice[i].objectNumber)->columnNumber());
1322                        if (!solveAll) {
1323                            choice[i].possibleBranch->way(1);
1324                            choice[i].possibleBranch->branch();
1325                            break;
1326                        } else {
1327                            choice[i].fix = 1;
1328                        }
1329                    }
1330                } else {
1331                    if (choice[i].downMovement < 1.0e100) {
1332                        // down feasible, up infeasible
1333                        anyAction = -1;
1334                        //printf("Up infeasible for choice %d sequence %d\n",i,
1335                        // model->object(choice[i].objectNumber)->columnNumber());
1336                        if (!solveAll) {
1337                            choice[i].possibleBranch->way(-1);
1338                            choice[i].possibleBranch->branch();
1339                            break;
1340                        } else {
1341                            choice[i].fix = -1;
1342                        }
1343                    } else {
1344                        // neither side feasible
1345                        anyAction = -2;
1346                        //printf("Both infeasible for choice %d sequence %d\n",i,
1347                        // model->object(choice[i].objectNumber)->columnNumber());
1348                        break;
1349                    }
1350                }
1351                bool hitMaxTime = (model->getCurrentSeconds() >
1352                                    model->getDblParam(CbcModel::CbcMaximumSeconds));
1353                if (hitMaxTime) {
1354                    numberStrong = i + 1;
1355                    break;
1356                }
1357            }
1358            if (!clp) {
1359                // Delete the snapshot
1360                solver->unmarkHotStart();
1361            } else {
1362                delete [] newLower;
1363                delete [] newUpper;
1364                delete [] outputStuff;
1365                int i;
1366                for (i = 0; i < 2*numberStrong; i++)
1367                    delete [] outputSolution[i];
1368                delete [] outputSolution;
1369            }
1370            solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit);
1371            // restore basis
1372            solver->setWarmStart(ws);
1373            // Unless infeasible we will carry on
1374            // But we could fix anyway
1375            if (anyAction == -1 && solveAll) {
1376                // apply and take off
1377                for (i = 0 ; i < numberStrong ; i++) {
1378                    if (choice[i].fix) {
1379                        choice[i].possibleBranch->way(choice[i].fix) ;
1380                        choice[i].possibleBranch->branch() ;
1381                    }
1382                }
1383                bool feasible = true;
1384                if (checkFeasibility) {
1385                    // check branching did not make infeasible
1386                    int iColumn;
1387                    int numberColumns = solver->getNumCols();
1388                    const double * columnLower = solver->getColLower();
1389                    const double * columnUpper = solver->getColUpper();
1390                    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1391                        if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5)
1392                            feasible = false;
1393                    }
1394                }
1395                if (feasible) {
1396                    // can do quick optimality check
1397                    int easy = 2;
1398                    solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
1399                    solver->resolve() ;
1400                    solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
1401                    feasible = solver->isProvenOptimal();
1402                }
1403                if (feasible) {
1404                    memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
1405                    model->reserveCurrentSolution(saveSolution);
1406                    memcpy(saveLower, solver->getColLower(), numberColumns*sizeof(double));
1407                    memcpy(saveUpper, solver->getColUpper(), numberColumns*sizeof(double));
1408                    // Clean up all candidates whih are fixed
1409                    int numberLeft = 0;
1410                    for (i = 0 ; i < numberStrong ; i++) {
1411                        CbcStrongInfo thisChoice = choice[i];
1412                        choice[i].possibleBranch = NULL;
1413                        const OsiObject * object = model->object(thisChoice.objectNumber);
1414                        double infeasibility = object->checkInfeasibility(&usefulInfo);
1415                        if (!infeasibility) {
1416                            // take out
1417                            delete thisChoice.possibleBranch;
1418                        } else {
1419                            choice[numberLeft++] = thisChoice;
1420                        }
1421                    }
1422                    numberStrong = numberLeft;
1423                    for (; i < maximumStrong; i++) {
1424                        delete choice[i].possibleBranch;
1425                        choice[i].possibleBranch = NULL;
1426                    }
1427                    // If all fixed then round again
1428                    if (!numberLeft) {
1429                        finished = false;
1430                        numberStrong = 0;
1431                        saveNumberStrong = 0;
1432                        maximumStrong = 1;
1433                    } else {
1434                        anyAction = 0;
1435                    }
1436                    // If these two uncommented then different action
1437                    anyAction = -1;
1438                    finished = true;
1439                    //printf("some fixed but continuing %d left\n",numberLeft);
1440                } else {
1441                    anyAction = -2; // say infeasible
1442                }
1443            }
1444            delete ws;
1445            //int numberNodes = model->getNodeCount();
1446            // update number of strong iterations etc
1447            model->incrementStrongInfo(numberStrongDone, numberStrongIterations,
1448                                       anyAction == -2 ? 0 : numberStrongInfeasible, anyAction == -2);
1449
1450            /*
1451              anyAction >= 0 indicates that strong branching didn't produce any monotone
1452              variables. Sift through the candidates for the best one.
1453
1454              QUERY: Setting numberNodes looks to be a distributed noop. numberNodes is
1455              local to this code block. Perhaps should be numberNodes_ from model?
1456              Unclear what this calculation is doing.
1457            */
1458            if (anyAction >= 0) {
1459
1460                // get average cost per iteration and assume stopped ones
1461                // would stop after 50% more iterations at average cost??? !!! ???
1462                double averageCostPerIteration = 0.0;
1463                double totalNumberIterations = 1.0;
1464                int smallestNumberInfeasibilities = COIN_INT_MAX;
1465                for (i = 0; i < numberStrong; i++) {
1466                    totalNumberIterations += choice[i].numItersDown +
1467                                             choice[i].numItersUp ;
1468                    averageCostPerIteration += choice[i].downMovement +
1469                                               choice[i].upMovement;
1470                    smallestNumberInfeasibilities =
1471                        CoinMin(CoinMin(choice[i].numIntInfeasDown ,
1472                                        choice[i].numIntInfeasUp ),
1473                                smallestNumberInfeasibilities);
1474                }
1475                //if (smallestNumberInfeasibilities>=numberIntegerInfeasibilities)
1476                //numberNodes=1000000; // switch off search for better solution
1477                averageCostPerIteration /= totalNumberIterations;
1478                // all feasible - choose best bet
1479
1480                // New method does all at once so it can be more sophisticated
1481                // in deciding how to balance actions.
1482                // But it does need arrays
1483                double * changeUp = new double [numberStrong];
1484                int * numberInfeasibilitiesUp = new int [numberStrong];
1485                double * changeDown = new double [numberStrong];
1486                int * numberInfeasibilitiesDown = new int [numberStrong];
1487                CbcBranchingObject ** objects = new CbcBranchingObject * [ numberStrong];
1488                for (i = 0 ; i < numberStrong ; i++) {
1489                    int iColumn = choice[i].possibleBranch->variable() ;
1490                    model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
1491                    << i << iColumn
1492                    << choice[i].downMovement << choice[i].numIntInfeasDown
1493                    << choice[i].upMovement << choice[i].numIntInfeasUp
1494                    << choice[i].possibleBranch->value()
1495                    << CoinMessageEol;
1496                    changeUp[i] = choice[i].upMovement;
1497                    numberInfeasibilitiesUp[i] = choice[i].numIntInfeasUp;
1498                    changeDown[i] = choice[i].downMovement;
1499                    numberInfeasibilitiesDown[i] = choice[i].numIntInfeasDown;
1500                    objects[i] = choice[i].possibleBranch;
1501                }
1502                int whichObject = decision->bestBranch(objects, numberStrong, numberUnsatisfied_,
1503                                                       changeUp, numberInfeasibilitiesUp,
1504                                                       changeDown, numberInfeasibilitiesDown,
1505                                                       objectiveValue_);
1506                // move branching object and make sure it will not be deleted
1507                if (whichObject >= 0) {
1508                    branch_ = objects[whichObject];
1509                    if (model->messageHandler()->logLevel() > 3)
1510                        printf("Choosing column %d\n", choice[whichObject].possibleBranch->variable()) ;
1511                    choice[whichObject].possibleBranch = NULL;
1512                }
1513                delete [] changeUp;
1514                delete [] numberInfeasibilitiesUp;
1515                delete [] changeDown;
1516                delete [] numberInfeasibilitiesDown;
1517                delete [] objects;
1518            }
1519#     ifdef COIN_HAS_CLP
1520            if (osiclp && !allNormal) {
1521                // back to normal
1522                osiclp->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
1523            }
1524#     endif
1525        }
1526        /*
1527          Simple branching. Probably just one, but we may have got here
1528          because of an odd branch e.g. a cut
1529        */
1530        else {
1531            // not strong
1532            // C) create branching object
1533            branch_ = choice[bestChoice].possibleBranch;
1534            choice[bestChoice].possibleBranch = NULL;
1535        }
1536    }
1537    // Set guessed solution value
1538    guessedObjectiveValue_ = objectiveValue_ + estimatedDegradation;
1539    /*
1540      Cleanup, then we're outta here.
1541    */
1542    if (!model->branchingMethod() || dynamicBranchingObject)
1543        delete decision;
1544
1545    for (i = 0; i < maximumStrong; i++)
1546        delete choice[i].possibleBranch;
1547    delete [] choice;
1548    delete [] saveLower;
1549    delete [] saveUpper;
1550
1551    // restore solution
1552    solver->setColSolution(saveSolution);
1553    delete [] saveSolution;
1554# ifdef COIN_HAS_CLP
1555    if (osiclp)
1556        osiclp->setSpecialOptions(saveClpOptions);
1557# endif
1558    return anyAction;
1559}
1560
1561/*
1562  Version for dynamic pseudo costs.
1563
1564  **** For now just return if anything odd
1565  later allow even if odd
1566
1567  The routine scans through the object list of the model looking for objects
1568  that indicate infeasibility. It tests each object using strong branching
1569  and selects the one with the least objective degradation.  A corresponding
1570  branching object is left attached to lastNode.
1571  This version gives preference in evaluation to variables which
1572  have not been evaluated many times.  It also uses numberStrong
1573  to say give up if last few tries have not changed incumbent.
1574  See Achterberg, Koch and Martin.
1575
1576  If strong branching is disabled, a candidate object is chosen essentially
1577  at random (whatever object ends up in pos'n 0 of the candidate array).
1578
1579  If a branching candidate is found to be monotone, bounds are set to fix the
1580  variable and the routine immediately returns (the caller is expected to
1581  reoptimize).
1582
1583  If a branching candidate is found to result in infeasibility in both
1584  directions, the routine immediately returns an indication of infeasibility.
1585
1586  Returns:  0   both branch directions are feasible
1587  -1    branching variable is monotone
1588  -2    infeasible
1589  -3   Use another method
1590
1591  For now just fix on objective from strong branching.
1592*/
1593
1594int CbcNode::chooseDynamicBranch (CbcModel *model, CbcNode *lastNode,
1595                                  OsiSolverBranch * & /*branches*/,
1596                                  int numberPassesLeft)
1597
1598{
1599    if (lastNode)
1600        depth_ = lastNode->depth_ + 1;
1601    else
1602        depth_ = 0;
1603    // Go to other choose if hot start
1604    if (model->hotstartSolution() &&
1605            (((model->moreSpecialOptions()&1024) == 0) || false))
1606        return -3;
1607    delete branch_;
1608    branch_ = NULL;
1609    OsiSolverInterface * solver = model->solver();
1610    // get information on solver type
1611    const OsiAuxInfo * auxInfo = solver->getAuxiliaryInfo();
1612    const OsiBabSolver * auxiliaryInfo = dynamic_cast<const OsiBabSolver *> (auxInfo);
1613    if (!auxiliaryInfo) {
1614        // use one from CbcModel
1615        auxiliaryInfo = model->solverCharacteristics();
1616    }
1617    int numberObjects = model->numberObjects();
1618    // If very odd set of objects then use older chooseBranch
1619    bool useOldWay = false;
1620    // point to useful information
1621    OsiBranchingInformation usefulInfo = model->usefulInformation();
1622    if (numberObjects > model->numberIntegers()) {
1623        for (int i = model->numberIntegers(); i < numberObjects; i++) {
1624            OsiObject * object = model->modifiableObject(i);
1625            CbcObject * obj =   dynamic_cast <CbcObject *>(object) ;
1626            if (!obj || !obj->optionalObject()) {
1627                double infeasibility = object->checkInfeasibility(&usefulInfo);
1628                if (infeasibility) {
1629                    useOldWay = true;
1630                    break;
1631                }
1632            } else {
1633              obj->initializeForBranching(model);
1634            }
1635        }
1636    }
1637    if ((model->specialOptions()&128) != 0)
1638        useOldWay = false; // allow
1639    // For now return if not simple
1640    if (useOldWay)
1641        return -3;
1642    // Modify useful info
1643    usefulInfo.depth_ = depth_;
1644    if ((model->specialOptions()&128) != 0) {
1645        // SOS - shadow prices
1646        int numberRows = solver->getNumRows();
1647        const double * pi = usefulInfo.pi_;
1648        double sumPi = 0.0;
1649        for (int i = 0; i < numberRows; i++)
1650            sumPi += fabs(pi[i]);
1651        sumPi /= static_cast<double> (numberRows);
1652        // and scale back
1653        sumPi *= 0.01;
1654        usefulInfo.defaultDual_ = sumPi; // switch on
1655        int numberColumns = solver->getNumCols();
1656        int size = CoinMax(numberColumns, 2 * numberRows);
1657        usefulInfo.usefulRegion_ = new double [size];
1658        CoinZeroN(usefulInfo.usefulRegion_, size);
1659        usefulInfo.indexRegion_ = new int [size];
1660        // pi may change
1661        usefulInfo.pi_ = CoinCopyOfArray(usefulInfo.pi_, numberRows);
1662    }
1663    assert (auxiliaryInfo);
1664    double cutoff = model->getCutoff();
1665    const double * lower = solver->getColLower();
1666    const double * upper = solver->getColUpper();
1667    // See if user thinks infeasible
1668    int anyAction = model->problemFeasibility()->feasible(model, 0);
1669    if (anyAction) {
1670        // will return -2 if infeasible , 0 if treat as integer
1671        return anyAction - 1;
1672    }
1673    int i;
1674    int saveStateOfSearch = model->stateOfSearch() % 10;
1675    int numberStrong = model->numberStrong();
1676    /* Ranging is switched off.
1677       The idea is that you can find out the effect of one iteration
1678       on each unsatisfied variable cheaply.  Then use this
1679       if you have not got much else to go on.
1680    */
1681    //#define RANGING
1682#ifdef RANGING
1683    // must have clp
1684#ifndef COIN_HAS_CLP
1685#  warning("Ranging switched off as not Clp");
1686#undef RANGING
1687#endif
1688    // Pass number
1689    int kPass = 0;
1690    int numberRows = solver->getNumRows();
1691#endif
1692    int numberColumns = model->getNumCols();
1693    double * saveUpper = new double[numberColumns];
1694    double * saveLower = new double[numberColumns];
1695    for (i = 0; i < numberColumns; i++) {
1696        saveLower[i] = lower[i];
1697        saveUpper[i] = upper[i];
1698    }
1699
1700    // Save solution in case heuristics need good solution later
1701
1702    double * saveSolution = new double[numberColumns];
1703    memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
1704    model->reserveCurrentSolution(saveSolution);
1705    const double * hotstartSolution = model->hotstartSolution();
1706    const int * hotstartPriorities = model->hotstartPriorities();
1707    double integerTolerance =
1708        model->getDblParam(CbcModel::CbcIntegerTolerance);
1709    if (hotstartSolution) {
1710        if ((model->moreSpecialOptions()&1024) != 0) {
1711            int nBad = 0;
1712            int nUnsat = 0;
1713            int nDiff = 0;
1714            for (int i = 0; i < numberObjects; i++) {
1715                OsiObject * object = model->modifiableObject(i);
1716                const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object);
1717                if (thisOne) {
1718                    int iColumn = thisOne->columnNumber();
1719                    double targetValue = hotstartSolution[iColumn];
1720                    double value = saveSolution[iColumn];
1721                    if (fabs(value - floor(value + 0.5)) > 1.0e-6) {
1722                        nUnsat++;
1723#ifdef CLP_INVESTIGATE
1724                        printf("H %d is %g target %g\n", iColumn, value, targetValue);
1725#endif
1726                    } else if (fabs(targetValue - value) > 1.0e-6) {
1727                        nDiff++;
1728                    }
1729                    if (targetValue < saveLower[iColumn] ||
1730                            targetValue > saveUpper[iColumn]) {
1731#ifdef CLP_INVESTIGATE
1732                        printf("%d has target %g and current bounds %g and %g\n",
1733                               iColumn, targetValue, saveLower[iColumn], saveUpper[iColumn]);
1734#endif
1735                        nBad++;
1736                    }
1737                }
1738            }
1739#ifdef CLP_INVESTIGATE
1740            printf("Hot %d unsatisfied, %d outside limits, %d different\n",
1741                   nUnsat, nBad, nDiff);
1742#endif
1743            if (nBad) {
1744                // switch off as not possible
1745                hotstartSolution = NULL;
1746                model->setHotstartSolution(NULL, NULL);
1747                usefulInfo.hotstartSolution_ = NULL;
1748            }
1749        }
1750    }
1751    /*
1752      Get a branching decision object. Use the default dynamic decision criteria unless
1753      the user has loaded a decision method into the model.
1754    */
1755    CbcBranchDecision *decision = model->branchingMethod();
1756    if (!decision)
1757        decision = new CbcBranchDynamicDecision();
1758    int xMark = 0;
1759    // Get arrays to sort
1760    double * sort = new double[numberObjects];
1761    int * whichObject = new int[numberObjects];
1762#ifdef RANGING
1763    int xPen = 0;
1764    int * objectMark = new int[2*numberObjects+1];
1765#endif
1766    // Arrays with movements
1767    double * upEstimate = new double[numberObjects];
1768    double * downEstimate = new double[numberObjects];
1769    double estimatedDegradation = 0.0;
1770    int numberNodes = model->getNodeCount();
1771    int saveLogLevel = model->logLevel();
1772#ifdef JJF_ZERO
1773    if ((numberNodes % 500) == 0) {
1774        model->setLogLevel(6);
1775        // Get average up and down costs
1776        double averageUp = 0.0;
1777        double averageDown = 0.0;
1778        int numberUp = 0;
1779        int numberDown = 0;
1780        int i;
1781        for ( i = 0; i < numberObjects; i++) {
1782            OsiObject * object = model->modifiableObject(i);
1783            CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
1784                dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
1785            assert(dynamicObject);
1786            int  numberUp2 = 0;
1787            int numberDown2 = 0;
1788            double up = 0.0;
1789            double down = 0.0;
1790            if (dynamicObject->numberTimesUp()) {
1791                numberUp++;
1792                averageUp += dynamicObject->upDynamicPseudoCost();
1793                numberUp2 += dynamicObject->numberTimesUp();
1794                up = dynamicObject->upDynamicPseudoCost();
1795            }
1796            if (dynamicObject->numberTimesDown()) {
1797                numberDown++;
1798                averageDown += dynamicObject->downDynamicPseudoCost();
1799                numberDown2 += dynamicObject->numberTimesDown();
1800                down = dynamicObject->downDynamicPseudoCost();
1801            }
1802            if (numberUp2 || numberDown2)
1803                printf("col %d - up %d times cost %g, - down %d times cost %g\n",
1804                       dynamicObject->columnNumber(), numberUp2, up, numberDown2, down);
1805        }
1806        if (numberUp)
1807            averageUp /= static_cast<double> (numberUp);
1808        else
1809            averageUp = 1.0;
1810        if (numberDown)
1811            averageDown /= static_cast<double> (numberDown);
1812        else
1813            averageDown = 1.0;
1814        printf("total - up %d vars average %g, - down %d vars average %g\n",
1815               numberUp, averageUp, numberDown, averageDown);
1816    }
1817#endif
1818    int numberBeforeTrust = model->numberBeforeTrust();
1819    // May go round twice if strong branching fixes all local candidates
1820    bool finished = false;
1821    int numberToFix = 0;
1822# ifdef COIN_HAS_CLP
1823    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
1824    int saveClpOptions = 0;
1825    if (osiclp) {
1826        // for faster hot start
1827        saveClpOptions = osiclp->specialOptions();
1828        osiclp->setSpecialOptions(saveClpOptions | 8192);
1829    }
1830# else
1831    OsiSolverInterface *osiclp = NULL ;
1832# endif
1833    //const CglTreeProbingInfo * probingInfo = NULL; //model->probingInfo();
1834    // Old code left in with DEPRECATED_STRATEGY
1835    assert (model->searchStrategy() == -1 ||
1836            model->searchStrategy() == 1 ||
1837            model->searchStrategy() == 2);
1838#ifdef DEPRECATED_STRATEGY
1839    int saveSearchStrategy2 = model->searchStrategy();
1840#endif
1841    // Get average up and down costs
1842    {
1843        double averageUp = 0.0;
1844        double averageDown = 0.0;
1845        int numberUp = 0;
1846        int numberDown = 0;
1847        int i;
1848        for ( i = 0; i < numberObjects; i++) {
1849            OsiObject * object = model->modifiableObject(i);
1850            CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
1851                dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
1852            if (dynamicObject) {
1853                if (dynamicObject->numberTimesUp()) {
1854                    numberUp++;
1855                    averageUp += dynamicObject->upDynamicPseudoCost();
1856                }
1857                if (dynamicObject->numberTimesDown()) {
1858                    numberDown++;
1859                    averageDown += dynamicObject->downDynamicPseudoCost();
1860                }
1861            }
1862        }
1863        if (numberUp)
1864            averageUp /= static_cast<double> (numberUp);
1865        else
1866            averageUp = 1.0;
1867        if (numberDown)
1868            averageDown /= static_cast<double> (numberDown);
1869        else
1870            averageDown = 1.0;
1871        for ( i = 0; i < numberObjects; i++) {
1872            OsiObject * object = model->modifiableObject(i);
1873            CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
1874                dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
1875            if (dynamicObject) {
1876                if (!dynamicObject->numberTimesUp())
1877                    dynamicObject->setUpDynamicPseudoCost(averageUp);
1878                if (!dynamicObject->numberTimesDown())
1879                    dynamicObject->setDownDynamicPseudoCost(averageDown);
1880            }
1881        }
1882    }
1883    /*
1884      1 strong
1885      2 no strong
1886      3 strong just before solution
1887      4 no strong just before solution
1888      5 strong first time or before solution
1889      6 strong first time
1890    */
1891    int useShadow = model->moreSpecialOptions() & 7;
1892    if (useShadow > 2) {
1893        if (model->getSolutionCount()) {
1894            if (numberNodes || useShadow < 5) {
1895                useShadow = 0;
1896                // zap pseudo shadow prices
1897                model->pseudoShadow(-1);
1898                // and switch off
1899                model->setMoreSpecialOptions(model->moreSpecialOptions()&(~1023));
1900            } else {
1901                useShadow = 1;
1902            }
1903        } else if (useShadow < 5) {
1904            useShadow -= 2;
1905        } else {
1906            useShadow = 1;
1907        }
1908    }
1909    if (useShadow) {
1910        // pseudo shadow prices
1911        model->pseudoShadow((model->moreSpecialOptions() >> 3)&63);
1912    }
1913#ifdef DEPRECATED_STRATEGY
1914    { // in for tabbing
1915    } else if (saveSearchStrategy2 < 1999) {
1916        // pseudo shadow prices
1917        model->pseudoShadow(NULL, NULL);
1918    } else if (saveSearchStrategy2 < 2999) {
1919        // leave old ones
1920    } else if (saveSearchStrategy2 < 3999) {
1921        // pseudo shadow prices at root
1922        if (!numberNodes)
1923            model->pseudoShadow(NULL, NULL);
1924    } else {
1925        abort();
1926    }
1927    if (saveSearchStrategy2 >= 0)
1928        saveSearchStrategy2 = saveSearchStrategy2 % 1000;
1929    if (saveSearchStrategy2 == 999)
1930        saveSearchStrategy2 = -1;
1931    int saveSearchStrategy = saveSearchStrategy2 < 99 ? saveSearchStrategy2 : saveSearchStrategy2 - 100;
1932#endif //DEPRECATED_STRATEGY
1933    int numberNotTrusted = 0;
1934    int numberStrongDone = 0;
1935    int numberUnfinished = 0;
1936    int numberStrongInfeasible = 0;
1937    int numberStrongIterations = 0;
1938    int strongType=0;
1939#define DO_ALL_AT_ROOT
1940#ifdef DO_ALL_AT_ROOT
1941    int saveSatisfiedVariables=0;
1942    int saveNumberToDo=0;
1943#endif
1944    // so we can save lots of stuff
1945    CbcStrongInfo choice;
1946    CbcDynamicPseudoCostBranchingObject * choiceObject = NULL;
1947    if (model->allDynamic()) {
1948        CbcSimpleIntegerDynamicPseudoCost * object = NULL;
1949        choiceObject = new CbcDynamicPseudoCostBranchingObject(model, 0, -1, 0.5, object);
1950    }
1951    choice.possibleBranch = choiceObject;
1952    numberPassesLeft = CoinMax(numberPassesLeft, 2);
1953    //#define DEBUG_SOLUTION
1954#ifdef DEBUG_SOLUTION
1955    bool onOptimalPath=false;
1956    if ((model->specialOptions()&1) != 0) {
1957      const OsiRowCutDebugger *debugger = model->continuousSolver()->getRowCutDebugger() ;
1958      if (debugger) {
1959        const OsiRowCutDebugger *debugger2 = model->solver()->getRowCutDebugger() ;
1960        printf("On optimal in CbcNode %s\n",debugger2 ? "" : "but bad cuts");
1961        onOptimalPath=true;
1962      }
1963    }
1964#endif
1965    while (!finished) {
1966        numberPassesLeft--;
1967        finished = true;
1968        decision->initialize(model);
1969        // Some objects may compute an estimate of best solution from here
1970        estimatedDegradation = 0.0;
1971        numberToFix = 0;
1972        int numberToDo = 0;
1973        int iBestNot = -1;
1974        int iBestGot = -1;
1975        double best = 0.0;
1976        numberNotTrusted = 0;
1977        numberStrongDone = 0;
1978        numberUnfinished = 0;
1979        numberStrongInfeasible = 0;
1980        numberStrongIterations = 0;
1981#ifdef RANGING
1982        int * which = objectMark + numberObjects + 1;
1983        int neededPenalties;
1984        int optionalPenalties;
1985#endif
1986        // We may go round this loop three times (only if we think we have solution)
1987        for (int iPass = 0; iPass < 3; iPass++) {
1988
1989            // Some objects may compute an estimate of best solution from here
1990            estimatedDegradation = 0.0;
1991            numberUnsatisfied_ = 0;
1992            // initialize sum of "infeasibilities"
1993            sumInfeasibilities_ = 0.0;
1994            int bestPriority = COIN_INT_MAX;
1995#ifdef JJF_ZERO
1996            int number01 = 0;
1997            const cliqueEntry * entry = NULL;
1998            const int * toZero = NULL;
1999            const int * toOne = NULL;
2000            const int * backward = NULL;
2001            int numberUnsatisProbed = 0;
2002            int numberUnsatisNotProbed = 0; // 0-1
2003            if (probingInfo) {
2004                number01 = probingInfo->numberIntegers();
2005                entry = probingInfo->fixEntries();
2006                toZero = probingInfo->toZero();
2007                toOne = probingInfo->toOne();
2008                backward = probingInfo->backward();
2009                if (!toZero[number01] || number01 < numberObjects || true) {
2010                    // no info
2011                    probingInfo = NULL;
2012                }
2013            }
2014#endif
2015            /*
2016              Scan for branching objects that indicate infeasibility. Choose candidates
2017              using priority as the first criteria, then integer infeasibility.
2018
2019              The algorithm is to fill the array with a set of good candidates (by
2020              infeasibility) with priority bestPriority.  Finding a candidate with
2021              priority better (less) than bestPriority flushes the choice array. (This
2022              serves as initialization when the first candidate is found.)
2023
2024            */
2025            numberToDo = 0;
2026#ifdef RANGING
2027            neededPenalties = 0;
2028            optionalPenalties = numberObjects;
2029#endif
2030            iBestNot = -1;
2031            double bestNot = 0.0;
2032            iBestGot = -1;
2033            best = 0.0;
2034            /* Problem type as set by user or found by analysis.  This will be extended
2035            0 - not known
2036            1 - Set partitioning <=
2037            2 - Set partitioning ==
2038            3 - Set covering
2039            4 - all +- 1 or all +1 and odd
2040            */
2041            int problemType = model->problemType();
2042            bool canDoOneHot = false;
2043            for (i = 0; i < numberObjects; i++) {
2044                OsiObject * object = model->modifiableObject(i);
2045                CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2046                    dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2047                double infeasibility = object->checkInfeasibility(&usefulInfo);
2048                int priorityLevel = object->priority();
2049                if (hotstartSolution) {
2050                    // we are doing hot start
2051                    const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object);
2052                    if (thisOne) {
2053                        int iColumn = thisOne->columnNumber();
2054                        bool canDoThisHot = true;
2055                        double targetValue = hotstartSolution[iColumn];
2056                        if (saveUpper[iColumn] > saveLower[iColumn]) {
2057                            double value = saveSolution[iColumn];
2058                            if (hotstartPriorities)
2059                                priorityLevel = hotstartPriorities[iColumn];
2060                            //double originalLower = thisOne->originalLower();
2061                            //double originalUpper = thisOne->originalUpper();
2062                            // switch off if not possible
2063                            if (targetValue >= saveLower[iColumn] && targetValue <= saveUpper[iColumn]) {
2064                                /* priority outranks rest always if negative
2065                                   otherwise can be downgraded if at correct level.
2066                                   Infeasibility may be increased to choose 1.0 values first.
2067                                   choose one near wanted value
2068                                */
2069                                if (fabs(value - targetValue) > integerTolerance) {
2070                                    //if (infeasibility>0.01)
2071                                    //infeasibility = fabs(1.0e6-fabs(value-targetValue));
2072                                    //else
2073                                    infeasibility = fabs(value - targetValue);
2074                                    priorityLevel = CoinAbs(priorityLevel);
2075                                } else if (priorityLevel < 0) {
2076                                    priorityLevel = CoinAbs(priorityLevel);
2077                                    if (targetValue == saveLower[iColumn] ||
2078                                    targetValue == saveUpper[iColumn]) {
2079                                        infeasibility = integerTolerance + 1.0e-12;
2080                                    } else {
2081                                        // can't
2082                                        priorityLevel += 10000000;
2083                                        canDoThisHot = false;
2084                                    }
2085                                } else {
2086                                    priorityLevel += 10000000;
2087                                    canDoThisHot = false;
2088                                }
2089                            } else {
2090                                // switch off if not possible
2091                                canDoThisHot = false;
2092                            }
2093                            if (canDoThisHot)
2094                                canDoOneHot = true;
2095                        } else if (targetValue < saveLower[iColumn] || targetValue > saveUpper[iColumn]) {
2096                        }
2097                    } else {
2098                        priorityLevel += 10000000;
2099                    }
2100                }
2101#define ZERO_ONE 0
2102#define ZERO_FAKE 1.0e20;
2103#if ZERO_ONE==1
2104                // branch on 0-1 first (temp)
2105                if (fabs(saveSolution[dynamicObject->columnNumber()]) < 1.0)
2106                    priorityLevel--;
2107#endif
2108#if ZERO_ONE==2
2109                if (fabs(saveSolution[dynamicObject->columnNumber()]) < 1.0)
2110                    infeasibility *= ZERO_FAKE;
2111#endif
2112                if (infeasibility) {
2113                    int iColumn = numberColumns + i;
2114                    bool gotDown = false;
2115                    int numberThisDown = 0;
2116                    bool gotUp = false;
2117                    int numberThisUp = 0;
2118                    double downGuess = object->downEstimate();
2119                    double upGuess = object->upEstimate();
2120                    if (dynamicObject) {
2121                        // Use this object's numberBeforeTrust
2122                        int numberBeforeTrustThis = dynamicObject->numberBeforeTrust();
2123                        iColumn = dynamicObject->columnNumber();
2124                        gotDown = false;
2125                        numberThisDown = dynamicObject->numberTimesDown();
2126                        if (numberThisDown >= numberBeforeTrustThis)
2127                            gotDown = true;
2128                        gotUp = false;
2129                        numberThisUp = dynamicObject->numberTimesUp();
2130                        if (numberThisUp >= numberBeforeTrustThis)
2131                            gotUp = true;
2132                        if (!depth_ && false) {
2133                            // try closest to 0.5
2134                            double part = saveSolution[iColumn] - floor(saveSolution[iColumn]);
2135                            infeasibility = fabs(0.5 - part);
2136                        }
2137                        if (problemType > 0 && problemType < 4 && false) {
2138                            // try closest to 0.5
2139                            double part = saveSolution[iColumn] - floor(saveSolution[iColumn]);
2140                            infeasibility = 0.5 - fabs(0.5 - part);
2141                        }
2142#ifdef JJF_ZERO
2143                        if (probingInfo) {
2144                            int iSeq = backward[iColumn];
2145                            assert (iSeq >= 0);
2146                            infeasibility = 1.0 + (toZero[iSeq+1] - toZero[iSeq]) +
2147                                            5.0 * CoinMin(toOne[iSeq] - toZero[iSeq], toZero[iSeq+1] - toOne[iSeq]);
2148                            if (toZero[iSeq+1] > toZero[iSeq]) {
2149                                numberUnsatisProbed++;
2150                            } else {
2151                                numberUnsatisNotProbed++;
2152                            }
2153                        }
2154#endif
2155                    } else {
2156                        // see if SOS
2157                        CbcSOS * sosObject =
2158                            dynamic_cast <CbcSOS *>(object) ;
2159                        if (sosObject) {
2160                            gotDown = false;
2161                            numberThisDown = sosObject->numberTimesDown();
2162                            if (numberThisDown >= numberBeforeTrust)
2163                                gotDown = true;
2164                            gotUp = false;
2165                            numberThisUp = sosObject->numberTimesUp();
2166                            if (numberThisUp >= numberBeforeTrust)
2167                                gotUp = true;
2168                        } else {
2169                            gotDown = true;
2170                            numberThisDown = 999999;
2171                            downGuess = 1.0e20;
2172                            gotUp = true;
2173                            numberThisUp = 999999;
2174                            upGuess = 1.0e20;
2175                            numberPassesLeft = 0;
2176                        }
2177                    }
2178                    // Increase estimated degradation to solution
2179                    estimatedDegradation += CoinMin(downGuess, upGuess);
2180                    downEstimate[i] = downGuess;
2181                    upEstimate[i] = upGuess;
2182                    numberUnsatisfied_++;
2183                    sumInfeasibilities_ += infeasibility;
2184                    // Better priority? Flush choices.
2185                    if (priorityLevel < bestPriority) {
2186                        numberToDo = 0;
2187                        bestPriority = priorityLevel;
2188                        iBestGot = -1;
2189                        best = 0.0;
2190                        numberNotTrusted = 0;
2191#ifdef RANGING
2192                        neededPenalties = 0;
2193                        optionalPenalties = numberObjects;
2194#endif
2195                    } else if (priorityLevel > bestPriority) {
2196                        continue;
2197                    }
2198                    if (!gotUp || !gotDown)
2199                        numberNotTrusted++;
2200                    // Check for suitability based on infeasibility.
2201                    if ((gotDown && gotUp) && numberStrong > 0) {
2202                        sort[numberToDo] = -infeasibility;
2203                        if (infeasibility > best) {
2204                            best = infeasibility;
2205                            iBestGot = numberToDo;
2206                        }
2207#ifdef RANGING
2208                        if (dynamicObject) {
2209                            objectMark[--optionalPenalties] = numberToDo;
2210                            which[optionalPenalties] = iColumn;
2211                        }
2212#endif
2213                    } else {
2214#ifdef RANGING
2215                        if (dynamicObject) {
2216                            objectMark[neededPenalties] = numberToDo;
2217                            which[neededPenalties++] = iColumn;
2218                        }
2219#endif
2220                        sort[numberToDo] = -10.0 * infeasibility;
2221                        if (!(numberThisUp + numberThisDown))
2222                            sort[numberToDo] *= 100.0; // make even more likely
2223                        if (iColumn < numberColumns) {
2224                            double part = saveSolution[iColumn] - floor(saveSolution[iColumn]);
2225                            if (1.0 - fabs(part - 0.5) > bestNot) {
2226                                iBestNot = numberToDo;
2227                                bestNot = 1.0 - fabs(part - 0.5);
2228                            }
2229                        } else {
2230                            // SOS
2231                            if (-sort[numberToDo] > bestNot) {
2232                                iBestNot = numberToDo;
2233                                bestNot = -sort[numberToDo];
2234                            }
2235                        }
2236                    }
2237                    if (model->messageHandler()->logLevel() > 3) {
2238                        printf("%d (%d) down %d %g up %d %g - infeas %g - sort %g solution %g\n",
2239                               i, iColumn, numberThisDown, object->downEstimate(), numberThisUp, object->upEstimate(),
2240                               infeasibility, sort[numberToDo], saveSolution[iColumn]);
2241                    }
2242                    whichObject[numberToDo++] = i;
2243                } else {
2244                    // for debug
2245                    downEstimate[i] = -1.0;
2246                    upEstimate[i] = -1.0;
2247                }
2248            }
2249            if (numberUnsatisfied_) {
2250                //if (probingInfo&&false)
2251                //printf("nunsat %d, %d probed, %d other 0-1\n",numberUnsatisfied_,
2252                // numberUnsatisProbed,numberUnsatisNotProbed);
2253                // some infeasibilities - go to next steps
2254                if (!canDoOneHot && hotstartSolution) {
2255                    // switch off as not possible
2256                    hotstartSolution = NULL;
2257                    model->setHotstartSolution(NULL, NULL);
2258                    usefulInfo.hotstartSolution_ = NULL;
2259                }
2260                break;
2261            } else if (!iPass) {
2262                // may just need resolve
2263                model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
2264                double newObjValue = solver->getObjSense()*solver->getObjValue();
2265                objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
2266                if (!solver->isProvenOptimal()) {
2267                    // infeasible
2268                    anyAction = -2;
2269                    break;
2270                }
2271                // Double check looks OK - just look at rows with all integers
2272                if (model->allDynamic()) {
2273                    double * solution = CoinCopyOfArray(saveSolution, numberColumns);
2274                    for (int i = 0; i < numberColumns; i++) {
2275                        if (model->isInteger(i))
2276                            solution[i] = floor(solution[i] + 0.5);
2277                    }
2278                    int numberRows = solver->getNumRows();
2279                    double * rowActivity = new double [numberRows];
2280                    CoinZeroN(rowActivity, numberRows);
2281                    solver->getMatrixByCol()->times(solution, rowActivity);
2282                    //const double * element = model->solver()->getMatrixByCol()->getElements();
2283                    const int * row = model->solver()->getMatrixByCol()->getIndices();
2284                    const CoinBigIndex * columnStart = model->solver()->getMatrixByCol()->getVectorStarts();
2285                    const int * columnLength = model->solver()->getMatrixByCol()->getVectorLengths();
2286                    int nFree = 0;
2287                    int nFreeNon = 0;
2288                    int nFixedNon = 0;
2289                    double mostAway = 0.0;
2290                    int whichAway = -1;
2291                    const double * columnLower = solver->getColLower();
2292                    const double * columnUpper = solver->getColUpper();
2293                    for (int i = 0; i < numberColumns; i++) {
2294                        if (!model->isInteger(i)) {
2295                            // mark rows as flexible
2296                            CoinBigIndex start = columnStart[i];
2297                            CoinBigIndex end = start + columnLength[i];
2298                            for (CoinBigIndex j = start; j < end; j++) {
2299                                int iRow = row[j];
2300                                rowActivity[iRow] = COIN_DBL_MAX;
2301                            }
2302                        } else if (columnLower[i] < columnUpper[i]) {
2303                            if (fabs(solution[i] - saveSolution[i]) > 
2304                                integerTolerance) {
2305                                nFreeNon++;
2306                                if (fabs(solution[i] - saveSolution[i]) > mostAway) {
2307                                    mostAway = fabs(solution[i] - saveSolution[i]);
2308                                    whichAway = i;
2309                                }
2310                            } else {
2311                                nFree++;
2312                            }
2313                        } else if (solution[i] != saveSolution[i]) {
2314                            nFixedNon++;
2315                        }
2316                    }
2317                    const double * lower = solver->getRowLower();
2318                    const double * upper = solver->getRowUpper();
2319                    bool satisfied = true;
2320                    for (int i = 0; i < numberRows; i++) {
2321                        double value = rowActivity[i];
2322                        if (value != COIN_DBL_MAX) {
2323                            if (value > upper[i] + 1.0e-5 || value < lower[i] - 1.0e-5) {
2324                                satisfied = false;
2325                            }
2326                        }
2327                    }
2328                    delete [] rowActivity;
2329                    delete [] solution;
2330                    if (!satisfied) {
2331#ifdef CLP_INVESTIGATE
2332                        printf("%d free ok %d free off target %d fixed off target\n",
2333                               nFree, nFreeNon, nFixedNon);
2334#endif
2335                        if (nFreeNon) {
2336                            // try branching on these
2337                            delete branch_;
2338                            for (int i = 0; i < numberObjects; i++) {
2339                                OsiObject * object = model->modifiableObject(i);
2340                                CbcSimpleIntegerDynamicPseudoCost * obj =
2341                                    dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2342                                assert (obj);
2343                                int iColumn = obj->columnNumber();
2344                                if (iColumn == whichAway) {
2345                                    int preferredWay = (saveSolution[iColumn] > solution[iColumn])
2346                                                       ? -1 : +1;
2347                                    usefulInfo.integerTolerance_ = 0.0;
2348                                    branch_ = obj->createCbcBranch(solver, &usefulInfo, preferredWay);
2349                                    break;
2350                                }
2351                            }
2352                            anyAction = 0;
2353                            break;
2354                        }
2355                    }
2356                }
2357            } else if (iPass == 1) {
2358                // looks like a solution - get paranoid
2359                bool roundAgain = false;
2360                // get basis
2361                CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart());
2362                if (!ws)
2363                    break;
2364                double tolerance;
2365                solver->getDblParam(OsiPrimalTolerance, tolerance);
2366                for (i = 0; i < numberColumns; i++) {
2367                    double value = saveSolution[i];
2368                    if (value < lower[i] - tolerance) {
2369                        saveSolution[i] = lower[i];
2370                        roundAgain = true;
2371                        ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound);
2372                    } else if (value > upper[i] + tolerance) {
2373                        saveSolution[i] = upper[i];
2374                        roundAgain = true;
2375                        ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound);
2376                    }
2377                }
2378                if (roundAgain) {
2379                    // restore basis
2380                    solver->setWarmStart(ws);
2381                    solver->setColSolution(saveSolution);
2382                    delete ws;
2383                    bool takeHint;
2384                    OsiHintStrength strength;
2385                    solver->getHintParam(OsiDoDualInResolve, takeHint, strength);
2386                    solver->setHintParam(OsiDoDualInResolve, false, OsiHintDo) ;
2387                    model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
2388                    double newObjValue = solver->getObjSense()*solver->getObjValue();
2389                    objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
2390                    solver->setHintParam(OsiDoDualInResolve, takeHint, strength) ;
2391                    if (!solver->isProvenOptimal()) {
2392                        // infeasible
2393                        anyAction = -2;
2394                        break;
2395                    }
2396                } else {
2397                    delete ws;
2398                    break;
2399                }
2400            }
2401        }
2402        if (anyAction == -2) {
2403            break;
2404        }
2405        // skip if solution
2406        if (!numberUnsatisfied_)
2407            break;
2408        int skipAll = (numberNotTrusted == 0 || numberToDo == 1) ? 1 : 0;
2409        bool doneHotStart = false;
2410        //DEPRECATED_STRATEGYint searchStrategy = saveSearchStrategy>=0 ? (saveSearchStrategy%10) : -1;
2411        int searchStrategy = model->searchStrategy();
2412        // But adjust depending on ratio of iterations
2413        if (searchStrategy > 0) {
2414          if (numberBeforeTrust >= /*5*/ 10 && numberBeforeTrust <= 10) {
2415                if (searchStrategy != 2) {
2416                    assert (searchStrategy == 1);
2417                    if (depth_ > 5) {
2418                        int numberIterations = model->getIterationCount();
2419                        int numberStrongIterations = model->numberStrongIterations();
2420                        if (numberStrongIterations > numberIterations + 10000) {
2421                            searchStrategy = 2;
2422                            skipAll = 1;
2423                        } else if (numberStrongIterations*4 + 1000 < numberIterations) {
2424                            searchStrategy = 3;
2425                            skipAll = 0;
2426                        }
2427                    } else {
2428                        searchStrategy = 3;
2429                        skipAll = 0;
2430                    }
2431                }
2432            }
2433        }
2434        // worth trying if too many times
2435        // Save basis
2436        CoinWarmStart * ws = NULL;
2437        // save limit
2438        int saveLimit = 0;
2439        solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit);
2440        if (!numberPassesLeft)
2441            skipAll = 1;
2442        if (!skipAll) {
2443            ws = solver->getWarmStart();
2444            int limit = 100;
2445            if (!saveStateOfSearch && saveLimit < limit && saveLimit == 100)
2446                solver->setIntParam(OsiMaxNumIterationHotStart, limit);
2447        }
2448        // Say which one will be best
2449        int whichChoice = 0;
2450        int bestChoice;
2451        if (iBestGot >= 0)
2452            bestChoice = iBestGot;
2453        else
2454            bestChoice = iBestNot;
2455        assert (bestChoice >= 0);
2456        // If we have hit max time don't do strong branching
2457        bool hitMaxTime = (model->getCurrentSeconds() >
2458                            model->getDblParam(CbcModel::CbcMaximumSeconds));
2459        // also give up if we are looping round too much
2460        if (hitMaxTime || numberPassesLeft <= 0 || useShadow == 2) {
2461            int iObject = whichObject[bestChoice];
2462            OsiObject * object = model->modifiableObject(iObject);
2463            int preferredWay;
2464            object->infeasibility(&usefulInfo, preferredWay);
2465            CbcObject * obj =
2466                dynamic_cast <CbcObject *>(object) ;
2467            assert (obj);
2468            branch_ = obj->createCbcBranch(solver, &usefulInfo, preferredWay);
2469            {
2470                CbcBranchingObject * branchObj =
2471                    dynamic_cast <CbcBranchingObject *>(branch_) ;
2472                assert (branchObj);
2473                branchObj->way(preferredWay);
2474            }
2475            delete ws;
2476            ws = NULL;
2477            break;
2478        } else {
2479            // say do fast
2480            int easy = 1;
2481            if (!skipAll)
2482                solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
2483            int iDo;
2484#define RESET_BOUNDS
2485#ifdef RANGING
2486            bool useRanging = model->allDynamic() && !skipAll;
2487            if (useRanging) {
2488                double currentObjective = solver->getObjValue() * solver->getObjSense();
2489                double gap = cutoff - currentObjective;
2490                // relax a bit
2491                gap *= 1.0000001;
2492                gap = CoinMax(1.0e-5, gap);
2493                // off penalties if too much
2494                double needed = neededPenalties;
2495                needed *= numberRows;
2496                if (numberNodes) {
2497                    if (needed > 1.0e6) {
2498                        neededPenalties = 0;
2499                    } else if (gap < 1.0e5) {
2500                        // maybe allow some not needed
2501                        int extra = static_cast<int> ((1.0e6 - needed) / numberRows);
2502                        int nStored = numberObjects - optionalPenalties;
2503                        extra = CoinMin(extra, nStored);
2504                        for (int i = 0; i < extra; i++) {
2505                            objectMark[neededPenalties] = objectMark[optionalPenalties+i];
2506                            which[neededPenalties++] = which[optionalPenalties+i];;
2507                        }
2508                    }
2509                }
2510                if (osiclp && neededPenalties) {
2511                    assert (!doneHotStart);
2512                    xPen += neededPenalties;
2513                    which--;
2514                    which[0] = neededPenalties;
2515                    osiclp->passInRanges(which);
2516                    // Mark hot start and get ranges
2517                    if (kPass) {
2518                        // until can work out why solution can go funny
2519                        int save = osiclp->specialOptions();
2520                        osiclp->setSpecialOptions(save | 256);
2521                        solver->markHotStart();
2522#ifdef RESET_BOUNDS
2523                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
2524                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
2525#endif
2526                        osiclp->setSpecialOptions(save);
2527                    } else {
2528                        solver->markHotStart();
2529#ifdef RESET_BOUNDS
2530                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
2531                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
2532#endif
2533                    }
2534                    doneHotStart = true;
2535                    xMark++;
2536                    kPass++;
2537                    osiclp->passInRanges(NULL);
2538                    const double * downCost = osiclp->upRange();
2539                    const double * upCost = osiclp->downRange();
2540                    bool problemFeasible = true;
2541                    int numberFixed = 0;
2542                    for (int i = 0; i < neededPenalties; i++) {
2543                        int j = objectMark[i];
2544                        int iObject = whichObject[j];
2545                        OsiObject * object = model->modifiableObject(iObject);
2546                        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2547                            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2548                        // Use this object's numberBeforeTrust
2549                        int numberBeforeTrustThis = dynamicObject->numberBeforeTrust();
2550                        int iSequence = dynamicObject->columnNumber();
2551                        double value = saveSolution[iSequence];
2552                        value -= floor(value);
2553                        double upPenalty = CoinMin(upCost[i], 1.0e110) * (1.0 - value);
2554                        double downPenalty = CoinMin(downCost[i], 1.0e110) * value;
2555                        int numberThisDown = dynamicObject->numberTimesDown();
2556                        int numberThisUp = dynamicObject->numberTimesUp();
2557                        if (!numberBeforeTrustThis) {
2558                            // override
2559                            downEstimate[iObject] = downPenalty;
2560                            upEstimate[iObject] = upPenalty;
2561                            double min1 = CoinMin(downEstimate[iObject],
2562                                                  upEstimate[iObject]);
2563                            double max1 = CoinMax(downEstimate[iObject],
2564                                                  upEstimate[iObject]);
2565                            min1 = 0.8 * min1 + 0.2 * max1;
2566                            sort[j] = - min1;
2567                        } else if (numberThisDown < numberBeforeTrustThis ||
2568                                   numberThisUp < numberBeforeTrustThis) {
2569                            double invTrust = 1.0 / static_cast<double> (numberBeforeTrustThis);
2570                            if (numberThisDown < numberBeforeTrustThis) {
2571                                double fraction = numberThisDown * invTrust;
2572                                downEstimate[iObject] = fraction * downEstimate[iObject] + (1.0 - fraction) * downPenalty;
2573                            }
2574                            if (numberThisUp < numberBeforeTrustThis) {
2575                                double fraction = numberThisUp * invTrust;
2576                                upEstimate[iObject] = fraction * upEstimate[iObject] + (1.0 - fraction) * upPenalty;
2577                            }
2578                            double min1 = CoinMin(downEstimate[iObject],
2579                                                  upEstimate[iObject]);
2580                            double max1 = CoinMax(downEstimate[iObject],
2581                                                  upEstimate[iObject]);
2582                            min1 = 0.8 * min1 + 0.2 * max1;
2583                            min1 *= 10.0;
2584                            if (!(numberThisDown + numberThisUp))
2585                                min1 *= 100.0;
2586                            sort[j] = - min1;
2587                        }
2588                        // seems unreliable
2589                        if (false&&CoinMax(downPenalty, upPenalty) > gap) {
2590                            COIN_DETAIL_PRINT(printf("gap %g object %d has down range %g, up %g\n",
2591                                                     gap, i, downPenalty, upPenalty));
2592                            //sort[j] -= 1.0e50; // make more likely to be chosen
2593                            int number;
2594                            if (downPenalty > gap) {
2595                                number = dynamicObject->numberTimesDown();
2596                                if (upPenalty > gap)
2597                                    problemFeasible = false;
2598                                CbcBranchingObject * branch = dynamicObject->createCbcBranch(solver, &usefulInfo, 1);
2599                                //branch->fix(solver,saveLower,saveUpper,1);
2600                                delete branch;
2601                            } else {
2602                                number = dynamicObject->numberTimesUp();
2603                                CbcBranchingObject * branch = dynamicObject->createCbcBranch(solver, &usefulInfo, 1);
2604                                //branch->fix(solver,saveLower,saveUpper,-1);
2605                                delete branch;
2606                            }
2607                            if (number >= numberBeforeTrustThis)
2608                              dynamicObject->setNumberBeforeTrust(CoinMin(number + 1,5*numberBeforeTrust));
2609                            numberFixed++;
2610                        }
2611                        if (!numberNodes)
2612                            COIN_DETAIL_PRINT(printf("%d pen down ps %g -> %g up ps %g -> %g\n",
2613                                                     iObject, downPenalty, downPenalty, upPenalty, upPenalty));
2614                    }
2615                    if (numberFixed && problemFeasible) {
2616                        assert(doneHotStart);
2617                        solver->unmarkHotStart();
2618                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
2619                        double newObjValue = solver->getObjSense()*solver->getObjValue();
2620                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
2621                        solver->markHotStart();
2622#ifdef RESET_BOUNDS
2623                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
2624                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
2625#endif
2626                        problemFeasible = solver->isProvenOptimal();
2627                    }
2628                    if (!problemFeasible) {
2629                      COIN_DETAIL_PRINT(fprintf(stdout, "both ways infeas on ranging - code needed\n"));
2630                        anyAction = -2;
2631                        if (!choiceObject) {
2632                            delete choice.possibleBranch;
2633                            choice.possibleBranch = NULL;
2634                        }
2635                        //printf("Both infeasible for choice %d sequence %d\n",i,
2636                        // model->object(choice.objectNumber)->columnNumber());
2637                        // Delete the snapshot
2638                        solver->unmarkHotStart();
2639                        // back to normal
2640                        solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
2641                        // restore basis
2642                        solver->setWarmStart(ws);
2643                        doneHotStart = false;
2644                        delete ws;
2645                        ws = NULL;
2646                        break;
2647                    }
2648                }
2649            }
2650#endif          /* RANGING */
2651            {
2652                int numberIterations = model->getIterationCount();
2653                //numberIterations += (model->numberExtraIterations()>>2);
2654                const int * strongInfo = model->strongInfo();
2655                //int numberDone = strongInfo[0]-strongInfo[3];
2656                int numberFixed = strongInfo[1] - strongInfo[4];
2657                int numberInfeasible = strongInfo[2] - strongInfo[5];
2658                assert (!strongInfo[3]);
2659                assert (!strongInfo[4]);
2660                assert (!strongInfo[5]);
2661                int numberStrongIterations = model->numberStrongIterations();
2662                int numberRows = solver->getNumRows();
2663                if (numberStrongIterations > numberIterations + CoinMin(100, 10*numberRows) && depth_ >= 4 && numberNodes > 100) {
2664                    if (20*numberInfeasible + 4*numberFixed < numberNodes) {
2665                        // Say never do
2666                        if (numberBeforeTrust == 5)
2667                          skipAll = -1;
2668                    }
2669                }
2670            }
2671            // make sure best will be first
2672            if (iBestGot >= 0)
2673                sort[iBestGot] = -COIN_DBL_MAX;
2674            // Actions 0 - exit for repeat, 1 resolve and try old choice,2 exit for continue
2675            if (anyAction)
2676                numberToDo = 0; // skip as we will be trying again
2677            // Sort
2678            CoinSort_2(sort, sort + numberToDo, whichObject);
2679            // Change in objective opposite infeasible
2680            double worstFeasible = 0.0;
2681            // Just first if strong off
2682            if (!numberStrong)
2683                numberToDo = CoinMin(numberToDo, 1);
2684            if (searchStrategy == 2)
2685                numberToDo = CoinMin(numberToDo, 20);
2686            iDo = 0;
2687            int saveLimit2;
2688            solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit2);
2689            int numberTest = numberNotTrusted > 0 ? numberStrong : (numberStrong + 1) / 2;
2690            if (searchStrategy == 3) {
2691                // Previously decided we need strong
2692                numberTest = numberStrong;
2693            }
2694            // Try nearly always off
2695            if (skipAll >= 0) {
2696                if (searchStrategy < 2) {
2697                    //if ((numberNodes%20)!=0) {
2698                    if ((model->specialOptions()&8) == 0) {
2699                        numberTest = 0;
2700                    }
2701                    //} else {
2702                    //numberTest=2*numberStrong;
2703                    //skipAll=0;
2704                    //}
2705                }
2706            } else {
2707                // Just take first
2708                numberTest = 1;
2709            }
2710            int testDepth = (skipAll >= 0) ? 8 : 4;
2711            if (depth_ < testDepth && numberStrong) {
2712                if (searchStrategy != 2) {
2713                    int numberRows = solver->getNumRows();
2714                    // whether to do this or not is important - think
2715                    if (numberRows < 300 || numberRows + numberColumns < 2500) {
2716                        if (depth_ < 7)
2717                            numberStrong = CoinMin(3 * numberStrong, numberToDo);
2718                        if (!depth_)
2719                            numberStrong = CoinMin(6 * numberStrong, numberToDo);
2720                    }
2721                    numberTest = numberStrong;
2722                    skipAll = 0;
2723                }
2724            }
2725            // Do at least 5 strong
2726            if (numberColumns < 1000 && (depth_ < 15 || numberNodes < 1000000))
2727                numberTest = CoinMax(numberTest, 5);
2728            if ((model->specialOptions()&8) == 0) {
2729                if (skipAll) {
2730                    numberTest = 0;
2731                }
2732            } else {
2733                // do 5 as strong is fixing
2734                numberTest = CoinMax(numberTest, 5);
2735            }
2736            // see if switched off
2737            if (skipAll < 0) {
2738                numberTest = 0;
2739            }
2740            int realMaxHotIterations = 999999;
2741            if (skipAll < 0)
2742                numberToDo = 1;
2743            strongType=0;
2744#ifdef DO_ALL_AT_ROOT
2745            if (model->strongStrategy()) {
2746              int iStrategy=model->strongStrategy();
2747              int kDepth = iStrategy/100;
2748              if (kDepth)
2749                iStrategy -= 100*kDepth;
2750              else
2751                kDepth=5;
2752              double objValue = solver->getObjSense()*solver->getObjValue();
2753              double bestPossible = model->getBestPossibleObjValue();
2754              bestPossible += 1.0e-7*(1.0+fabs(bestPossible));
2755              int jStrategy = iStrategy/10;
2756              if (jStrategy) {
2757                if ((jStrategy&1)!=0&&!depth_)
2758                  strongType=2;
2759                else if ((jStrategy&2)!=0&&depth_<=kDepth)
2760                  strongType=2;
2761                else if ((jStrategy&4)!=0&&objValue<bestPossible)
2762                  strongType=2;
2763                iStrategy-=10*jStrategy;
2764              }
2765              if (!strongType) {
2766                if ((iStrategy&1)!=0&&!depth_)
2767                  strongType=1;
2768                else if ((iStrategy&2)!=0&&depth_<=kDepth)
2769                  strongType=1;
2770                else if ((iStrategy&4)!=0&&objValue<bestPossible)
2771                  strongType=1;
2772              }
2773              saveNumberToDo=numberToDo;
2774              if (strongType==2) {
2775                // add in satisfied
2776                const int * integerVariable = model->integerVariable();
2777                int numberIntegers = model->numberIntegers();
2778                if (numberIntegers==numberObjects) {
2779                  numberToDo=0;
2780                  for (int i=0;i<numberIntegers;i++) {
2781                    int iColumn=integerVariable[i];
2782                    if (saveUpper[iColumn]>saveLower[iColumn]) {
2783                      whichObject [numberToDo++]=i;
2784                    }
2785                  }
2786                  saveSatisfiedVariables=numberToDo-saveNumberToDo;
2787                } else {
2788                  strongType=1;
2789                }
2790              }
2791              if (strongType) {
2792                numberTest = numberToDo;
2793                numberStrong=numberToDo;
2794                skipAll=0;
2795                searchStrategy=0;
2796                solver->setIntParam(OsiMaxNumIterationHotStart, 100000);
2797                //printf("Strong branching type %d\n",strongType);
2798              }
2799            }
2800#endif
2801            for ( iDo = 0; iDo < numberToDo; iDo++) {
2802                int iObject = whichObject[iDo];
2803                OsiObject * object = model->modifiableObject(iObject);
2804                CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
2805                    dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
2806                int iColumn = dynamicObject ? dynamicObject->columnNumber() : numberColumns + iObject;
2807                int preferredWay;
2808                double infeasibility = object->infeasibility(&usefulInfo, preferredWay);
2809                double predictedChange=0.0;
2810                // may have become feasible
2811                if (!infeasibility) {
2812                  if(strongType!=2||solver->getColLower()[iColumn]==solver->getColUpper()[iColumn])
2813                    continue;
2814                }
2815#ifndef NDEBUG
2816                if (iColumn < numberColumns) {
2817                    const double * solution = model->testSolution();
2818                    assert (saveSolution[iColumn] == solution[iColumn]);
2819                }
2820#endif
2821                CbcSimpleInteger * obj =
2822                    dynamic_cast <CbcSimpleInteger *>(object) ;
2823                if (obj) {
2824                    if (choiceObject) {
2825                        obj->fillCreateBranch(choiceObject, &usefulInfo, preferredWay);
2826                        choiceObject->setObject(dynamicObject);
2827                    } else {
2828                        choice.possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay);
2829                    }
2830                } else {
2831                    CbcObject * obj =
2832                        dynamic_cast <CbcObject *>(object) ;
2833                    assert (obj);
2834                    choice.possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay);
2835                }
2836                // Save which object it was
2837                choice.objectNumber = iObject;
2838                choice.numIntInfeasUp = numberUnsatisfied_;
2839                choice.numIntInfeasDown = numberUnsatisfied_;
2840                if (strongType!=2) {
2841                  choice.upMovement = upEstimate[iObject];
2842                  choice.downMovement = downEstimate[iObject];
2843                } else {
2844                  choice.upMovement = 0.1;
2845                  choice.downMovement = 0.1;
2846                }
2847                  assert (choice.upMovement >= 0.0);
2848                  assert (choice.downMovement >= 0.0);
2849                choice.fix = 0; // say not fixed
2850                // see if can skip strong branching
2851                int canSkip = choice.possibleBranch->fillStrongInfo(choice);
2852                if ((numberTest <= 0 || skipAll)) {
2853                    if (iDo > 20) {
2854                        if (!choiceObject) {
2855                            delete choice.possibleBranch;
2856                            choice.possibleBranch = NULL;
2857                        }
2858                        break; // give up anyway
2859                    }
2860                }
2861                if (model->messageHandler()->logLevel() > 3 && numberBeforeTrust && dynamicObject)
2862                    dynamicObject->print(1, choice.possibleBranch->value());
2863                if (strongType)
2864                  canSkip=0;
2865                if (skipAll < 0)
2866                    canSkip = 1;
2867                if (!canSkip) {
2868                    if (!doneHotStart) {
2869                        // Mark hot start
2870                        doneHotStart = true;
2871                        solver->markHotStart();
2872#ifdef RESET_BOUNDS
2873                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
2874                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
2875#endif
2876                        if (!solver->isProvenOptimal()) {
2877                          skipAll=-2;
2878                          canSkip = 1;
2879                        }
2880                        xMark++;
2881                    }
2882                }
2883                if (!canSkip) {
2884                    numberTest--;
2885                    // just do a few
2886                    if (searchStrategy == 2)
2887                        solver->setIntParam(OsiMaxNumIterationHotStart, 10);
2888                    double objectiveChange ;
2889                    double newObjectiveValue = 1.0e100;
2890                    int j;
2891                    // status is 0 finished, 1 infeasible and other
2892                    int iStatus;
2893                    /*
2894                      Try the down direction first. (Specify the initial branching alternative as
2895                      down with a call to way(-1). Each subsequent call to branch() performs the
2896                      specified branch and advances the branch object state to the next branch
2897                      alternative.)
2898                    */
2899                    choice.possibleBranch->way(-1) ;
2900                    predictedChange = choice.possibleBranch->branch() ;
2901                    solver->solveFromHotStart() ;
2902                    bool needHotStartUpdate = false;
2903                    numberStrongDone++;
2904                    numberStrongIterations += solver->getIterationCount();
2905                    /*
2906                      We now have an estimate of objective degradation that we can use for strong
2907                      branching. If we're over the cutoff, the variable is monotone up.
2908                      If we actually made it to optimality, check for a solution, and if we have
2909                      a good one, call setBestSolution to process it. Note that this may reduce the
2910                      cutoff, so we check again to see if we can declare this variable monotone.
2911                    */
2912                    if (solver->isProvenOptimal())
2913                        iStatus = 0; // optimal
2914                    else if (solver->isIterationLimitReached() 
2915                             && !solver->isDualObjectiveLimitReached()) {
2916                        iStatus = 2; // unknown
2917                    } else {
2918                        iStatus = 1; // infeasible
2919#ifdef CONFLICT_CUTS
2920# ifdef COIN_HAS_CLP
2921                        if (osiclp&&(model->moreSpecialOptions()&4194304)!=0) {
2922                          const CbcFullNodeInfo * topOfTree =
2923                            model->topOfTree();
2924                          if (topOfTree) {
2925                            OsiRowCut * cut = osiclp->smallModelCut(topOfTree->lower(),
2926                                                                    topOfTree->upper(),
2927                                                                    model->numberRowsAtContinuous(),
2928                                                                    model->whichGenerator());
2929                            if (cut) {
2930                              printf("XXXXXX found conflict cut in strong branching\n");
2931                              //cut->print();
2932                              if ((model->specialOptions()&1) != 0) {
2933                                const OsiRowCutDebugger *debugger = model->continuousSolver()->getRowCutDebugger() ;
2934                                if (debugger) {
2935                                  if (debugger->invalidCut(*cut)) {
2936                                    model->continuousSolver()->applyRowCuts(1,cut);
2937                                    model->continuousSolver()->writeMps("bad");
2938                                  }
2939                                  CoinAssert (!debugger->invalidCut(*cut));
2940                                }
2941                              }
2942                              model->makeGlobalCut(cut) ;
2943                            }
2944                          }
2945                        }
2946#endif
2947#endif
2948                    }
2949                    // say infeasible if branch says so
2950                    if (predictedChange==COIN_DBL_MAX)
2951                      iStatus=1;
2952                    if (iStatus != 2 && solver->getIterationCount() >
2953                            realMaxHotIterations)
2954                        numberUnfinished++;
2955                    newObjectiveValue = solver->getObjSense() * solver->getObjValue();
2956                    choice.numItersDown = solver->getIterationCount();
2957                    objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_, 0.0);
2958                    // Update branching information if wanted
2959                    CbcBranchingObject * cbcobj = dynamic_cast<CbcBranchingObject *> (choice.possibleBranch);
2960                    if (cbcobj) {
2961                        CbcObject * object = cbcobj->object();
2962                        assert (object) ;
2963                        CbcObjectUpdateData update = object->createUpdateInformation(solver, this, cbcobj);
2964                        update.objectNumber_ = choice.objectNumber;
2965                        model->addUpdateInformation(update);
2966                    } else {
2967                        decision->updateInformation( solver, this);
2968                    }
2969                    if (!iStatus) {
2970                        choice.finishedDown = true ;
2971                        if (newObjectiveValue >= cutoff) {
2972                            objectiveChange = 1.0e100; // say infeasible
2973                            numberStrongInfeasible++;
2974                        } else {
2975#define CBCNODE_TIGHTEN_BOUNDS
2976#ifdef CBCNODE_TIGHTEN_BOUNDS
2977                            // Can we tighten bounds?
2978                            if (iColumn < numberColumns && cutoff < 1.0e20
2979                                    && objectiveChange > 1.0e-5) {
2980                                double value = saveSolution[iColumn];
2981                                double down = value - floor(value-integerTolerance);
2982                                double changePer = objectiveChange / (down + 1.0e-7);
2983                                double distance = (cutoff - objectiveValue_) / changePer;
2984                                distance += 1.0e-3;
2985                                if (distance < 5.0) {
2986                                    double newLower = ceil(value - distance);
2987                                    if (newLower > saveLower[iColumn]) {
2988                                        //printf("Could increase lower bound on %d from %g to %g\n",
2989                                        //   iColumn,saveLower[iColumn],newLower);
2990                                        saveLower[iColumn] = newLower;
2991                                        solver->setColLower(iColumn, newLower);
2992                                    }
2993                                }
2994                            }
2995#endif
2996                            // See if integer solution
2997                            if (model->feasibleSolution(choice.numIntInfeasDown,
2998                                                        choice.numObjInfeasDown)
2999                                    && model->problemFeasibility()->feasible(model, -1) >= 0) {
3000                                if (auxiliaryInfo->solutionAddsCuts()) {
3001                                    needHotStartUpdate = true;
3002                                    solver->unmarkHotStart();
3003                                }
3004                                model->setLogLevel(saveLogLevel);
3005                                model->setBestSolution(CBC_STRONGSOL,
3006                                                       newObjectiveValue,
3007                                                       solver->getColSolution()) ;
3008                                if (needHotStartUpdate) {
3009                                    model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3010                                    newObjectiveValue = solver->getObjSense() * solver->getObjValue();
3011                                    objectiveValue_ = CoinMax(objectiveValue_,newObjectiveValue);
3012                                    objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_, 0.0);
3013                                    model->feasibleSolution(choice.numIntInfeasDown,
3014                                                            choice.numObjInfeasDown);
3015                                }
3016                                model->setLastHeuristic(NULL);
3017                                model->incrementUsed(solver->getColSolution());
3018                                cutoff = model->getCutoff();
3019                                if (newObjectiveValue >= cutoff) {      //  *new* cutoff
3020                                    objectiveChange = 1.0e100 ;
3021                                    numberStrongInfeasible++;
3022                                }
3023                            }
3024                        }
3025                    } else if (iStatus == 1) {
3026                        objectiveChange = 1.0e100 ;
3027                        numberStrongInfeasible++;
3028                    } else {
3029                        // Can't say much as we did not finish
3030                        choice.finishedDown = false ;
3031                        numberUnfinished++;
3032                    }
3033                    choice.downMovement = objectiveChange ;
3034
3035                    // restore bounds
3036                    for ( j = 0; j < numberColumns; j++) {
3037                        if (saveLower[j] != lower[j])
3038                            solver->setColLower(j, saveLower[j]);
3039                        if (saveUpper[j] != upper[j])
3040                            solver->setColUpper(j, saveUpper[j]);
3041                    }
3042                    if (needHotStartUpdate) {
3043                        needHotStartUpdate = false;
3044                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3045                        double newObjValue = solver->getObjSense()*solver->getObjValue();
3046                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
3047                        //we may again have an integer feasible solution
3048                        int numberIntegerInfeasibilities;
3049                        int numberObjectInfeasibilities;
3050                        if (model->feasibleSolution(
3051                                    numberIntegerInfeasibilities,
3052                                    numberObjectInfeasibilities)) {
3053#ifdef BONMIN
3054                            //In this case node has become integer feasible, let us exit the loop
3055                            std::cout << "Node has become integer feasible" << std::endl;
3056                            numberUnsatisfied_ = 0;
3057                            break;
3058#endif
3059                            double objValue = solver->getObjValue();
3060                            model->setLogLevel(saveLogLevel);
3061                            model->setBestSolution(CBC_STRONGSOL,
3062                                                   objValue,
3063                                                   solver->getColSolution()) ;
3064                            model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3065                            double newObjValue = solver->getObjSense()*solver->getObjValue();
3066                            objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
3067                            cutoff = model->getCutoff();
3068                        }
3069                        solver->markHotStart();
3070#ifdef RESET_BOUNDS
3071                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
3072                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
3073#endif
3074                        if (!solver->isProvenOptimal()) {
3075                          skipAll=-2;
3076                          canSkip = 1;
3077                        }
3078                        xMark++;
3079                    }
3080#if 0 //def DO_ALL_AT_ROOT
3081                    if (strongType)
3082                        printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
3083                               choice.objectNumber, iStatus, newObjectiveValue, choice.numItersDown,
3084                               choice.downMovement, choice.finishedDown, choice.numIntInfeasDown,
3085                               choice.numObjInfeasDown);
3086#endif
3087
3088                    // repeat the whole exercise, forcing the variable up
3089                    predictedChange=choice.possibleBranch->branch();
3090                    solver->solveFromHotStart() ;
3091                    numberStrongDone++;
3092                    numberStrongIterations += solver->getIterationCount();
3093                    /*
3094                      We now have an estimate of objective degradation that we can use for strong
3095                      branching. If we're over the cutoff, the variable is monotone up.
3096                      If we actually made it to optimality, check for a solution, and if we have
3097                      a good one, call setBestSolution to process it. Note that this may reduce the
3098                      cutoff, so we check again to see if we can declare this variable monotone.
3099                    */
3100                    if (solver->isProvenOptimal())
3101                        iStatus = 0; // optimal
3102                    else if (solver->isIterationLimitReached()
3103                             && !solver->isDualObjectiveLimitReached()) {
3104                        iStatus = 2; // unknown
3105                    } else {
3106                        iStatus = 1; // infeasible
3107#ifdef CONFLICT_CUTS
3108# ifdef COIN_HAS_CLP
3109                        if (osiclp&&(model->moreSpecialOptions()&4194304)!=0) {
3110                          const CbcFullNodeInfo * topOfTree =
3111                            model->topOfTree();
3112                          if (topOfTree) {
3113                            OsiRowCut * cut = osiclp->smallModelCut(topOfTree->lower(),
3114                                                                    topOfTree->upper(),
3115                                                                    model->numberRowsAtContinuous(),
3116                                                                    model->whichGenerator());
3117                            if (cut) {
3118                              printf("XXXXXX found conflict cut in strong branching\n");
3119                              //cut->print();
3120                              if ((model->specialOptions()&1) != 0) {
3121                                const OsiRowCutDebugger *debugger = model->continuousSolver()->getRowCutDebugger() ;
3122                                if (debugger) {
3123                                  if (debugger->invalidCut(*cut)) {
3124                                    model->continuousSolver()->applyRowCuts(1,cut);
3125                                    model->continuousSolver()->writeMps("bad");
3126                                  }
3127                                  CoinAssert (!debugger->invalidCut(*cut));
3128                                }
3129                              }
3130                              model->makeGlobalCut(cut) ;
3131                            }
3132                          }
3133                        }
3134#endif
3135#endif
3136                    }
3137                    // say infeasible if branch says so
3138                    if (predictedChange==COIN_DBL_MAX)
3139                      iStatus=1;
3140                    if (iStatus != 2 && solver->getIterationCount() >
3141                            realMaxHotIterations)
3142                        numberUnfinished++;
3143                    newObjectiveValue = solver->getObjSense() * solver->getObjValue();
3144                    choice.numItersUp = solver->getIterationCount();
3145                    objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_, 0.0);
3146                    // Update branching information if wanted
3147                    cbcobj = dynamic_cast<CbcBranchingObject *> (choice.possibleBranch);
3148                    if (cbcobj) {
3149                        CbcObject * object = cbcobj->object();
3150                        assert (object) ;
3151                        CbcObjectUpdateData update = object->createUpdateInformation(solver, this, cbcobj);
3152                        update.objectNumber_ = choice.objectNumber;
3153                        model->addUpdateInformation(update);
3154                    } else {
3155                        decision->updateInformation( solver, this);
3156                    }
3157                    if (!iStatus) {
3158                        choice.finishedUp = true ;
3159                        if (newObjectiveValue >= cutoff) {
3160                            objectiveChange = 1.0e100; // say infeasible
3161                            numberStrongInfeasible++;
3162                        } else {
3163#ifdef CBCNODE_TIGHTEN_BOUNDS
3164                            // Can we tighten bounds?
3165                            if (iColumn < numberColumns && cutoff < 1.0e20
3166                                    && objectiveChange > 1.0e-5) {
3167                                double value = saveSolution[iColumn];
3168                                double up = ceil(value+integerTolerance) - value;
3169                                double changePer = objectiveChange / (up + 1.0e-7);
3170                                double distance = (cutoff - objectiveValue_) / changePer;
3171                                distance += 1.0e-3;
3172                                if (distance < 5.0) {
3173                                    double newUpper = floor(value + distance);
3174                                    if (newUpper < saveUpper[iColumn]) {
3175                                        //printf("Could decrease upper bound on %d from %g to %g\n",
3176                                        //   iColumn,saveUpper[iColumn],newUpper);
3177                                        saveUpper[iColumn] = newUpper;
3178                                        solver->setColUpper(iColumn, newUpper);
3179                                    }
3180                                }
3181                            }
3182#endif
3183                            // See if integer solution
3184                            if (model->feasibleSolution(choice.numIntInfeasUp,
3185                                                        choice.numObjInfeasUp)
3186                                    && model->problemFeasibility()->feasible(model, -1) >= 0) {
3187#ifdef BONMIN
3188                                std::cout << "Node has become integer feasible" << std::endl;
3189                                numberUnsatisfied_ = 0;
3190                                break;
3191#endif
3192                                if (auxiliaryInfo->solutionAddsCuts()) {
3193                                    needHotStartUpdate = true;
3194                                    solver->unmarkHotStart();
3195                                }
3196                                model->setLogLevel(saveLogLevel);
3197                                model->setBestSolution(CBC_STRONGSOL,
3198                                                       newObjectiveValue,
3199                                                       solver->getColSolution()) ;
3200                                if (choice.finishedDown) {
3201                                  double cutoff = model->getCutoff();
3202                                  double downObj = objectiveValue_
3203                                    + choice.downMovement ;
3204                                  if (downObj >= cutoff) {     
3205                                    choice.downMovement = 1.0e100 ;
3206                                    numberStrongInfeasible++;
3207                                }
3208
3209                                }
3210                                if (needHotStartUpdate) {
3211                                    model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3212                                    newObjectiveValue = solver->getObjSense() * solver->getObjValue();
3213                                    objectiveValue_ = CoinMax(objectiveValue_,newObjectiveValue);
3214                                    objectiveChange = CoinMax(newObjectiveValue  - objectiveValue_, 0.0);
3215                                    model->feasibleSolution(choice.numIntInfeasDown,
3216                                                            choice.numObjInfeasDown);
3217                                }
3218                                model->setLastHeuristic(NULL);
3219                                model->incrementUsed(solver->getColSolution());
3220                                cutoff = model->getCutoff();
3221                                if (newObjectiveValue >= cutoff) {      //  *new* cutoff
3222                                    objectiveChange = 1.0e100 ;
3223                                    numberStrongInfeasible++;
3224                                }
3225                            }
3226                        }
3227                    } else if (iStatus == 1) {
3228                        objectiveChange = 1.0e100 ;
3229                        numberStrongInfeasible++;
3230                    } else {
3231                        // Can't say much as we did not finish
3232                        choice.finishedUp = false ;
3233                        numberUnfinished++;
3234                    }
3235                    choice.upMovement = objectiveChange ;
3236
3237                    // restore bounds
3238                    for ( j = 0; j < numberColumns; j++) {
3239                        if (saveLower[j] != lower[j])
3240                            solver->setColLower(j, saveLower[j]);
3241                        if (saveUpper[j] != upper[j])
3242                            solver->setColUpper(j, saveUpper[j]);
3243                    }
3244                    if (needHotStartUpdate) {
3245                        needHotStartUpdate = false;
3246                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3247                        double newObjValue = solver->getObjSense()*solver->getObjValue();
3248                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
3249                        //we may again have an integer feasible solution
3250                        int numberIntegerInfeasibilities;
3251                        int numberObjectInfeasibilities;
3252                        if (model->feasibleSolution(
3253                                    numberIntegerInfeasibilities,
3254                                    numberObjectInfeasibilities)) {
3255                            double objValue = solver->getObjValue();
3256                            model->setLogLevel(saveLogLevel);
3257                            model->setBestSolution(CBC_STRONGSOL,
3258                                                   objValue,
3259                                                   solver->getColSolution()) ;
3260                            model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3261                            double newObjValue = solver->getObjSense()*solver->getObjValue();
3262                            objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
3263                            cutoff = model->getCutoff();
3264                        }
3265                        solver->markHotStart();
3266#ifdef RESET_BOUNDS
3267                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
3268                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
3269#endif
3270                        if (!solver->isProvenOptimal()) {
3271                          skipAll=-2;
3272                          canSkip = 1;
3273                        }
3274                        xMark++;
3275                    }
3276
3277#if 0 //def DO_ALL_AT_ROOT
3278                    if (strongType)
3279                        printf("Up on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n",
3280                               choice.objectNumber, iStatus, newObjectiveValue, choice.numItersUp,
3281                               choice.upMovement, choice.finishedUp, choice.numIntInfeasUp,
3282                               choice.numObjInfeasUp);
3283#endif
3284                }
3285
3286                solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit2);
3287                /*
3288                  End of evaluation for this candidate variable. Possibilities are:
3289                  * Both sides below cutoff; this variable is a candidate for branching.
3290                  * Both sides infeasible or above the objective cutoff: no further action
3291                  here. Break from the evaluation loop and assume the node will be purged
3292                  by the caller.
3293                  * One side below cutoff: Install the branch (i.e., fix the variable). Break
3294                  from the evaluation loop and assume the node will be reoptimised by the
3295                  caller.
3296                */
3297                // reset
3298                choice.possibleBranch->resetNumberBranchesLeft();
3299                if (choice.upMovement < 1.0e100) {
3300                    if (choice.downMovement < 1.0e100) {
3301                        // In case solution coming in was odd
3302                        choice.upMovement = CoinMax(0.0, choice.upMovement);
3303                        choice.downMovement = CoinMax(0.0, choice.downMovement);
3304#if ZERO_ONE==2
3305                        // branch on 0-1 first (temp)
3306                        if (fabs(choice.possibleBranch->value()) < 1.0) {
3307                            choice.upMovement *= ZERO_FAKE;
3308                            choice.downMovement *= ZERO_FAKE;
3309                        }
3310#endif
3311                        // feasible - see which best
3312                        if (!canSkip) {
3313                            if (model->messageHandler()->logLevel() > 3)
3314                                printf("sort %g downest %g upest %g ", sort[iDo], downEstimate[iObject],
3315                                       upEstimate[iObject]);
3316                            model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
3317                            << iObject << iColumn
3318                            << choice.downMovement << choice.numIntInfeasDown
3319                            << choice.upMovement << choice.numIntInfeasUp
3320                            << choice.possibleBranch->value()
3321                            << CoinMessageEol;
3322                        }
3323                        int betterWay=0;
3324                        // If was feasible (extra strong branching) skip
3325                        if (infeasibility) {
3326                            CbcBranchingObject * branchObj =
3327                                dynamic_cast <CbcBranchingObject *>(branch_) ;
3328                            if (branch_)
3329                                assert (branchObj);
3330                            betterWay = decision->betterBranch(choice.possibleBranch,
3331                                                               branchObj,
3332                                                               choice.upMovement,
3333                                                               choice.numIntInfeasUp ,
3334                                                               choice.downMovement,
3335                                                               choice.numIntInfeasDown );
3336                        }
3337                        if (betterWay) {
3338                            // C) create branching object
3339                            if (choiceObject) {
3340                                delete branch_;
3341                                branch_ = choice.possibleBranch->clone();
3342                            } else {
3343                                delete branch_;
3344                                branch_ = choice.possibleBranch;
3345                                choice.possibleBranch = NULL;
3346                            }
3347                            {
3348                                CbcBranchingObject * branchObj =
3349                                    dynamic_cast <CbcBranchingObject *>(branch_) ;
3350                                assert (branchObj);
3351                                //branchObj->way(preferredWay);
3352                                branchObj->way(betterWay);
3353                            }
3354                            bestChoice = choice.objectNumber;
3355                            whichChoice = iDo;
3356                            if (numberStrong <= 1) {
3357                                delete ws;
3358                                ws = NULL;
3359                                break;
3360                            }
3361                        } else {
3362                            if (!choiceObject) {
3363                                delete choice.possibleBranch;
3364                                choice.possibleBranch = NULL;
3365                            }
3366                            if (iDo >= 2*numberStrong) {
3367                                delete ws;
3368                                ws = NULL;
3369                                break;
3370                            }
3371                            if (!dynamicObject || dynamicObject->numberTimesUp() > 1) {
3372                                if (iDo - whichChoice >= numberStrong) {
3373                                    if (!choiceObject) {
3374                                        delete choice.possibleBranch;
3375                                        choice.possibleBranch = NULL;
3376                                    }
3377                                    break; // give up
3378                                }
3379                            } else {
3380                                if (iDo - whichChoice >= 2*numberStrong) {
3381                                    delete ws;
3382                                    ws = NULL;
3383                                    if (!choiceObject) {
3384                                        delete choice.possibleBranch;
3385                                        choice.possibleBranch = NULL;
3386                                    }
3387                                    break; // give up
3388                                }
3389                            }
3390                        }
3391                    } else {
3392                        // up feasible, down infeasible
3393                        anyAction = -1;
3394                        worstFeasible = CoinMax(worstFeasible, choice.upMovement);
3395                        model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
3396                        << iObject << iColumn
3397                        << choice.downMovement << choice.numIntInfeasDown
3398                        << choice.upMovement << choice.numIntInfeasUp
3399                        << choice.possibleBranch->value()
3400                        << CoinMessageEol;
3401                        //printf("Down infeasible for choice %d sequence %d\n",i,
3402                        // model->object(choice.objectNumber)->columnNumber());
3403                        choice.fix = 1;
3404                        numberToFix++;
3405                        choice.possibleBranch->fix(solver, saveLower, saveUpper, 1);
3406                        if (!choiceObject) {
3407                            delete choice.possibleBranch;
3408                            choice.possibleBranch = NULL;
3409                        } else {
3410                            //choiceObject = new CbcDynamicPseudoCostBranchingObject(*choiceObject);
3411                            choice.possibleBranch = choiceObject;
3412                        }
3413                        assert(doneHotStart);
3414                        solver->unmarkHotStart();
3415                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3416                        double newObjValue = solver->getObjSense()*solver->getObjValue();
3417                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
3418                        bool goneInfeasible = (!solver->isProvenOptimal()||solver->isDualObjectiveLimitReached());
3419                        solver->markHotStart();
3420#ifdef RESET_BOUNDS
3421                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
3422                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
3423#endif
3424                        if (!solver->isProvenOptimal()) {
3425                          skipAll=-2;
3426                          canSkip = 1;
3427                        }
3428                        xMark++;
3429                        // may be infeasible (if other way stopped on iterations)
3430                        if (goneInfeasible) {
3431                            // neither side feasible
3432                            anyAction = -2;
3433                            if (!choiceObject) {
3434                                delete choice.possibleBranch;
3435                                choice.possibleBranch = NULL;
3436                            }
3437                            //printf("Both infeasible for choice %d sequence %d\n",i,
3438                            // model->object(choice.objectNumber)->columnNumber());
3439                            delete ws;
3440                            ws = NULL;
3441                            break;
3442                        }
3443                    }
3444                } else {
3445                    if (choice.downMovement < 1.0e100) {
3446                        // down feasible, up infeasible
3447                        anyAction = -1;
3448                        worstFeasible = CoinMax(worstFeasible, choice.downMovement);
3449                        model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
3450                        << iObject << iColumn
3451                        << choice.downMovement << choice.numIntInfeasDown
3452                        << choice.upMovement << choice.numIntInfeasUp
3453                        << choice.possibleBranch->value()
3454                        << CoinMessageEol;
3455                        choice.fix = -1;
3456                        numberToFix++;
3457                        choice.possibleBranch->fix(solver, saveLower, saveUpper, -1);
3458                        if (!choiceObject) {
3459                            delete choice.possibleBranch;
3460                            choice.possibleBranch = NULL;
3461                        } else {
3462                            //choiceObject = new CbcDynamicPseudoCostBranchingObject(*choiceObject);
3463                            choice.possibleBranch = choiceObject;
3464                        }
3465                        assert(doneHotStart);
3466                        solver->unmarkHotStart();
3467                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
3468                        double newObjValue = solver->getObjSense()*solver->getObjValue();
3469                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
3470                        bool goneInfeasible = (!solver->isProvenOptimal()||solver->isDualObjectiveLimitReached());
3471                        solver->markHotStart();
3472#ifdef RESET_BOUNDS
3473                        memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double));
3474                        memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double));
3475#endif
3476                        if (!solver->isProvenOptimal()) {
3477                          skipAll=-2;
3478                          canSkip = 1;
3479                        }
3480                        xMark++;
3481                        // may be infeasible (if other way stopped on iterations)
3482                        if (goneInfeasible) {
3483                            // neither side feasible
3484                            anyAction = -2;
3485                            if (!choiceObject) {
3486                                delete choice.possibleBranch;
3487                                choice.possibleBranch = NULL;
3488                            }
3489                            delete ws;
3490                            ws = NULL;
3491                            break;
3492                        }
3493                    } else {
3494                        // neither side feasible
3495                        anyAction = -2;
3496                        if (!choiceObject) {
3497                            delete choice.possibleBranch;
3498                            choice.possibleBranch = NULL;
3499                        }
3500                        delete ws;
3501                        ws = NULL;
3502                        break;
3503                    }
3504                }
3505                // Check max time
3506                hitMaxTime = (model->getCurrentSeconds() >
3507                               model->getDblParam(CbcModel::CbcMaximumSeconds));
3508                if (hitMaxTime) {
3509                    // make sure rest are fast
3510                    for ( int jDo = iDo + 1; jDo < numberToDo; jDo++) {
3511                        int iObject = whichObject[iDo];
3512                        OsiObject * object = model->modifiableObject(iObject);
3513                        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3514                            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3515                        if (dynamicObject)
3516                            dynamicObject->setNumberBeforeTrust(0);
3517                    }
3518                    numberTest = 0;
3519                }
3520                if (!choiceObject) {
3521                    delete choice.possibleBranch;
3522                }
3523            }
3524            if (model->messageHandler()->logLevel() > 3) {
3525                if (anyAction == -2) {
3526                    printf("infeasible\n");
3527                } else if (anyAction == -1) {
3528                    printf("%d fixed AND choosing %d iDo %d iChosenWhen %d numberToDo %d\n", numberToFix, bestChoice,
3529                           iDo, whichChoice, numberToDo);
3530                } else {
3531                    int iObject = whichObject[whichChoice];
3532                    OsiObject * object = model->modifiableObject(iObject);
3533                    CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3534                        dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3535                    if (dynamicObject) {
3536                        int iColumn = dynamicObject->columnNumber();
3537                        printf("choosing %d (column %d) iChosenWhen %d numberToDo %d\n", bestChoice,
3538                               iColumn, whichChoice, numberToDo);
3539                    }
3540                }
3541            }
3542            if (doneHotStart) {
3543                // Delete the snapshot
3544                solver->unmarkHotStart();
3545                // back to normal
3546                solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
3547                // restore basis
3548                solver->setWarmStart(ws);
3549            }
3550            solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit);
3551            // Unless infeasible we will carry on
3552            // But we could fix anyway
3553            if (numberToFix && !hitMaxTime) {
3554                if (anyAction != -2) {
3555                    // apply and take off
3556                    bool feasible = true;
3557                    // can do quick optimality check
3558                    int easy = 2;
3559                    solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
3560                    model->resolve(NULL, 11, saveSolution, saveLower, saveUpper) ;
3561                    double newObjValue = solver->getObjSense()*solver->getObjValue();
3562                    objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
3563                    solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
3564                    feasible = solver->isProvenOptimal();
3565                    if (feasible) {
3566                        anyAction = 0;
3567                    } else {
3568                        anyAction = -2;
3569                        finished = true;
3570                    }
3571                }
3572            }
3573            // If  fixed then round again
3574            // See if candidate still possible
3575            if (branch_) {
3576                 const OsiObject * object = model->object(bestChoice);
3577                 double infeasibility = object->checkInfeasibility(&usefulInfo);
3578                 if (!infeasibility) {
3579                   // take out
3580                   delete branch_;
3581                   branch_ = NULL;
3582                 } else {
3583                   // get preferred way
3584                   int preferredWay;
3585                   object->infeasibility(&usefulInfo, preferredWay);
3586                   CbcBranchingObject * branchObj =
3587                     dynamic_cast <CbcBranchingObject *>(branch_) ;
3588                   assert (branchObj);
3589                   branchObj->way(preferredWay);
3590#ifdef CBCNODE_TIGHTEN_BOUNDS
3591                   bool fixed = branchObj->tighten(solver);
3592                   if (fixed) {
3593                     //printf("Variable now fixed!\n");
3594                     // take out
3595                     delete branch_;
3596                     branch_ = NULL;
3597                   }
3598#endif
3599                 }
3600            }
3601            if (!branch_ && anyAction != -2 && !hitMaxTime) {
3602                finished = false;
3603            }
3604            delete ws;
3605        }
3606    }
3607    // update number of strong iterations etc
3608    model->incrementStrongInfo(numberStrongDone, numberStrongIterations,
3609                               anyAction == -2 ? 0 : numberToFix, anyAction == -2);
3610    if (model->searchStrategy() == -1) {
3611#ifndef COIN_DEVELOP
3612        if (solver->messageHandler()->logLevel() > 1)
3613#endif
3614            printf("%d strong, %d iters, %d inf, %d not finished, %d not trusted\n",
3615                   numberStrongDone, numberStrongIterations, numberStrongInfeasible, numberUnfinished,
3616                   numberNotTrusted);
3617        // decide what to do
3618        int strategy = 1;
3619        if (((numberUnfinished*4 > numberStrongDone &&
3620                numberStrongInfeasible*40 < numberStrongDone) ||
3621                numberStrongInfeasible < 0) && model->numberStrong() < 10 && model->numberBeforeTrust() <= 20 && model->numberObjects() > CoinMax(1000, solver->getNumRows())) {
3622            strategy = 2;
3623#ifdef COIN_DEVELOP
3624            //if (model->logLevel()>1)
3625            printf("going to strategy 2\n");
3626#endif
3627            // Weaken
3628            model->setNumberStrong(2);
3629            model->setNumberBeforeTrust(1);
3630            model->synchronizeNumberBeforeTrust();
3631        }
3632        if (numberNodes)
3633            strategy = 1;  // should only happen after hot start
3634        model->setSearchStrategy(strategy);
3635    } else if (numberStrongDone) {
3636        //printf("%d strongB, %d iters, %d inf, %d not finished, %d not trusted\n",
3637        //   numberStrongDone,numberStrongIterations,numberStrongInfeasible,numberUnfinished,
3638        //   numberNotTrusted);
3639    }
3640    if (model->searchStrategy() == 1 && numberNodes > 500 && numberNodes < -510) {
3641#ifndef COIN_DEVELOP
3642        if (solver->messageHandler()->logLevel() > 1)
3643#endif
3644            printf("after %d nodes - %d strong, %d iters, %d inf, %d not finished, %d not trusted\n",
3645                   numberNodes, numberStrongDone, numberStrongIterations, numberStrongInfeasible, numberUnfinished,
3646                   numberNotTrusted);
3647        // decide what to do
3648        if (numberUnfinished*10 > numberStrongDone + 1 ||
3649                !numberStrongInfeasible) {
3650          COIN_DETAIL_PRINT(printf("going to strategy 2\n"));
3651            // Weaken
3652            model->setNumberStrong(2);
3653            model->setNumberBeforeTrust(1);
3654            model->synchronizeNumberBeforeTrust();
3655            model->setSearchStrategy(2);
3656        }
3657    }
3658    if (numberUnfinished*10 < numberStrongDone &&
3659        model->numberStrongIterations()*20 < model->getIterationCount()&&
3660                                !auxiliaryInfo->solutionAddsCuts()) {
3661        //printf("increasing trust\n");
3662        model->synchronizeNumberBeforeTrust(2);
3663    }
3664
3665    // Set guessed solution value
3666    guessedObjectiveValue_ = objectiveValue_ + estimatedDegradation;
3667#ifdef DO_ALL_AT_ROOT
3668    if (strongType) {
3669      char general[200];
3670      if (strongType==1)
3671        sprintf(general,"Strong branching on all %d unsatisfied, %d iterations (depth %d)\n",
3672                saveNumberToDo,numberStrongIterations,depth_);
3673      else
3674        sprintf(general,"Strong branching on all %d unfixed variables (%d unsatisfied), %d iterations (depth %d)\n",
3675                saveNumberToDo+saveSatisfiedVariables,saveNumberToDo,numberStrongIterations,depth_);
3676      model->messageHandler()->message(CBC_FPUMP2,model->messages())
3677        << general << CoinMessageEol ;
3678    }
3679#endif
3680#ifdef DEBUG_SOLUTION
3681    if(onOptimalPath&&anyAction==-2) {
3682      printf("Gone off optimal path in CbcNode\n");
3683      assert(!onOptimalPath||anyAction!=-2);
3684    }
3685#endif
3686    /*
3687      Cleanup, then we're finished
3688    */
3689    if (!model->branchingMethod())
3690        delete decision;
3691
3692    delete choiceObject;
3693    delete [] sort;
3694    delete [] whichObject;
3695#ifdef RANGING
3696    delete [] objectMark;
3697#endif
3698    delete [] saveLower;
3699    delete [] saveUpper;
3700    delete [] upEstimate;
3701    delete [] downEstimate;
3702# ifdef COIN_HAS_CLP
3703    if (osiclp) {
3704        osiclp->setSpecialOptions(saveClpOptions);
3705    }
3706# endif
3707    // restore solution
3708    solver->setColSolution(saveSolution);
3709    model->reserveCurrentSolution(saveSolution);
3710    delete [] saveSolution;
3711    model->setStateOfSearch(saveStateOfSearch);
3712    model->setLogLevel(saveLogLevel);
3713    // delete extra regions
3714    if (usefulInfo.usefulRegion_) {
3715        delete [] usefulInfo.usefulRegion_;
3716        delete [] usefulInfo.indexRegion_;
3717        delete [] usefulInfo.pi_;
3718        usefulInfo.usefulRegion_ = NULL;
3719        usefulInfo.indexRegion_ = NULL;
3720        usefulInfo.pi_ = NULL;
3721    }
3722    useShadow = model->moreSpecialOptions() & 7;
3723    if ((useShadow == 5 && model->getSolutionCount()) || useShadow == 6) {
3724        // zap pseudo shadow prices
3725        model->pseudoShadow(-1);
3726        // and switch off
3727        model->setMoreSpecialOptions(model->moreSpecialOptions()&(~1023));
3728    }
3729    return anyAction;
3730}
3731int CbcNode::analyze (CbcModel *model, double * results)
3732{
3733    int i;
3734    int numberIterationsAllowed = model->numberAnalyzeIterations();
3735    OsiSolverInterface * solver = model->solver();
3736    objectiveValue_ = solver->getObjSense() * solver->getObjValue();
3737    double cutoff = model->getCutoff();
3738    const double * lower = solver->getColLower();
3739    const double * upper = solver->getColUpper();
3740    const double * dj = solver->getReducedCost();
3741    int numberObjects = model->numberObjects();
3742    int numberColumns = model->getNumCols();
3743    // Initialize arrays
3744    int numberIntegers = model->numberIntegers();
3745    int * back = new int[numberColumns];
3746    const int * integerVariable = model->integerVariable();
3747    for (i = 0; i < numberColumns; i++)
3748        back[i] = -1;
3749    // What results is
3750    double * newLower = results;
3751    double * objLower = newLower + numberIntegers;
3752    double * newUpper = objLower + numberIntegers;
3753    double * objUpper = newUpper + numberIntegers;
3754    for (i = 0; i < numberIntegers; i++) {
3755        int iColumn = integerVariable[i];
3756        back[iColumn] = i;
3757        newLower[i] = 0.0;
3758        objLower[i] = -COIN_DBL_MAX;
3759        newUpper[i] = 0.0;
3760        objUpper[i] = -COIN_DBL_MAX;
3761    }
3762    double * saveUpper = new double[numberColumns];
3763    double * saveLower = new double[numberColumns];
3764    // Save solution in case heuristics need good solution later
3765
3766    double * saveSolution = new double[numberColumns];
3767    memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
3768    model->reserveCurrentSolution(saveSolution);
3769    for (i = 0; i < numberColumns; i++) {
3770        saveLower[i] = lower[i];
3771        saveUpper[i] = upper[i];
3772    }
3773    // Get arrays to sort
3774    double * sort = new double[numberObjects];
3775    int * whichObject = new int[numberObjects];
3776    int numberToFix = 0;
3777    int numberToDo = 0;
3778    double integerTolerance =
3779        model->getDblParam(CbcModel::CbcIntegerTolerance);
3780    // point to useful information
3781    OsiBranchingInformation usefulInfo = model->usefulInformation();
3782    // and modify
3783    usefulInfo.depth_ = depth_;
3784
3785    // compute current state
3786    int numberObjectInfeasibilities; // just odd ones
3787    int numberIntegerInfeasibilities;
3788    model->feasibleSolution(
3789        numberIntegerInfeasibilities,
3790        numberObjectInfeasibilities);
3791# ifdef COIN_HAS_CLP
3792    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
3793    int saveClpOptions = 0;
3794    bool fastIterations = (model->specialOptions() & 8) != 0;
3795    if (osiclp && fastIterations) {
3796        // for faster hot start
3797        saveClpOptions = osiclp->specialOptions();
3798        osiclp->setSpecialOptions(saveClpOptions | 8192);
3799    }
3800# else
3801    bool fastIterations = false ;
3802# endif
3803    /*
3804      Scan for branching objects that indicate infeasibility. Choose candidates
3805      using priority as the first criteria, then integer infeasibility.
3806
3807      The algorithm is to fill the array with a set of good candidates (by
3808      infeasibility) with priority bestPriority.  Finding a candidate with
3809      priority better (less) than bestPriority flushes the choice array. (This
3810      serves as initialization when the first candidate is found.)
3811
3812    */
3813    numberToDo = 0;
3814    for (i = 0; i < numberObjects; i++) {
3815        OsiObject * object = model->modifiableObject(i);
3816        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3817            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3818        if (!dynamicObject)
3819            continue;
3820        double infeasibility = object->checkInfeasibility(&usefulInfo);
3821        int iColumn = dynamicObject->columnNumber();
3822        if (saveUpper[iColumn] == saveLower[iColumn])
3823            continue;
3824        if (infeasibility)
3825            sort[numberToDo] = -1.0e10 - infeasibility;
3826        else
3827            sort[numberToDo] = -fabs(dj[iColumn]);
3828        whichObject[numberToDo++] = i;
3829    }
3830    // Save basis
3831    CoinWarmStart * ws = solver->getWarmStart();
3832    int saveLimit;
3833    solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit);
3834    int targetIterations = CoinMax(500, numberIterationsAllowed / numberObjects);
3835    if (saveLimit < targetIterations)
3836        solver->setIntParam(OsiMaxNumIterationHotStart, targetIterations);
3837    // Mark hot start
3838    solver->markHotStart();
3839    // Sort
3840    CoinSort_2(sort, sort + numberToDo, whichObject);
3841    double * currentSolution = model->currentSolution();
3842    double objMin = 1.0e50;
3843    double objMax = -1.0e50;
3844    bool needResolve = false;
3845    /*
3846      Now calculate the cost forcing the variable up and down.
3847    */
3848    int iDo;
3849    for (iDo = 0; iDo < numberToDo; iDo++) {
3850        CbcStrongInfo choice;
3851        int iObject = whichObject[iDo];
3852        OsiObject * object = model->modifiableObject(iObject);
3853        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
3854            dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
3855        if (!dynamicObject)
3856            continue;
3857        int iColumn = dynamicObject->columnNumber();
3858        int preferredWay;
3859        /*
3860          Update the information held in the object.
3861        */
3862        object->infeasibility(&usefulInfo, preferredWay);
3863        double value = currentSolution[iColumn];
3864        double nearest = floor(value + 0.5);
3865        double lowerValue = floor(value);
3866        bool satisfied = false;
3867        if (fabs(value - nearest) <= integerTolerance || value < saveLower[iColumn] || value > saveUpper[iColumn]) {
3868            satisfied = true;
3869            double newValue;
3870            if (nearest < saveUpper[iColumn]) {
3871                newValue = nearest + 1.0001 * integerTolerance;
3872                lowerValue = nearest;
3873            } else {
3874                newValue = nearest - 1.0001 * integerTolerance;
3875                lowerValue = nearest - 1;
3876            }
3877            currentSolution[iColumn] = newValue;
3878        }
3879        double upperValue = lowerValue + 1.0;
3880        //CbcSimpleInteger * obj =
3881        //dynamic_cast <CbcSimpleInteger *>(object) ;
3882        //if (obj) {
3883        //choice.possibleBranch=obj->createCbcBranch(solver,&usefulInfo,preferredWay);
3884        //} else {
3885        CbcObject * obj =
3886            dynamic_cast <CbcObject *>(object) ;
3887        assert (obj);
3888        choice.possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay);
3889        //}
3890        currentSolution[iColumn] = value;
3891        // Save which object it was
3892        choice.objectNumber = iObject;
3893        choice.numIntInfeasUp = numberUnsatisfied_;
3894        choice.numIntInfeasDown = numberUnsatisfied_;
3895        choice.downMovement = 0.0;
3896        choice.upMovement = 0.0;
3897        choice.numItersDown = 0;
3898        choice.numItersUp = 0;
3899        choice.fix = 0; // say not fixed
3900        double objectiveChange ;
3901        double newObjectiveValue = 1.0e100;
3902        int j;
3903        // status is 0 finished, 1 infeasible and other
3904        int iStatus;
3905        /*
3906          Try the down direction first. (Specify the initial branching alternative as
3907          down with a call to way(-1). Each subsequent call to branch() performs the
3908          specified branch and advances the branch object state to the next branch
3909          alternative.)
3910        */
3911        choice.possibleBranch->way(-1) ;
3912        choice.possibleBranch->branch() ;
3913        if (fabs(value - lowerValue) > integerTolerance) {
3914            solver->solveFromHotStart() ;
3915            /*
3916              We now have an estimate of objective degradation that we can use for strong
3917              branching. If we're over the cutoff, the variable is monotone up.
3918              If we actually made it to optimality, check for a solution, and if we have
3919              a good one, call setBestSolution to process it. Note that this may reduce the
3920              cutoff, so we check again to see if we can declare this variable monotone.
3921            */
3922            if (solver->isProvenOptimal())
3923                iStatus = 0; // optimal
3924            else if (solver->isIterationLimitReached()
3925                     && !solver->isDualObjectiveLimitReached())
3926                iStatus = 2; // unknown
3927            else
3928                iStatus = 1; // infeasible
3929            newObjectiveValue = solver->getObjSense() * solver->getObjValue();
3930            choice.numItersDown = solver->getIterationCount();
3931            numberIterationsAllowed -= choice.numItersDown;
3932            objectiveChange = newObjectiveValue  - objectiveValue_;
3933            if (!iStatus) {
3934                choice.finishedDown = true ;
3935                if (newObjectiveValue >= cutoff) {
3936                    objectiveChange = 1.0e100; // say infeasible
3937                } else {
3938                    // See if integer solution
3939                    if (model->feasibleSolution(choice.numIntInfeasDown,
3940                                                choice.numObjInfeasDown)
3941                            && model->problemFeasibility()->feasible(model, -1) >= 0) {
3942                        model->setBestSolution(CBC_STRONGSOL,
3943                                               newObjectiveValue,
3944                                               solver->getColSolution()) ;
3945                        model->setLastHeuristic(NULL);
3946                        model->incrementUsed(solver->getColSolution());
3947                        cutoff = model->getCutoff();
3948                        if (newObjectiveValue >= cutoff)        //  *new* cutoff
3949                            objectiveChange = 1.0e100 ;
3950                    }
3951                }
3952            } else if (iStatus == 1) {
3953                objectiveChange = 1.0e100 ;
3954            } else {
3955                // Can't say much as we did not finish
3956                choice.finishedDown = false ;
3957            }
3958            choice.downMovement = objectiveChange ;
3959        }
3960        // restore bounds
3961        for ( j = 0; j < numberColumns; j++) {
3962            if (saveLower[j] != lower[j])
3963                solver->setColLower(j, saveLower[j]);
3964            if (saveUpper[j] != upper[j])
3965                solver->setColUpper(j, saveUpper[j]);
3966        }
3967        // repeat the whole exercise, forcing the variable up
3968        choice.possibleBranch->branch();
3969        if (fabs(value - upperValue) > integerTolerance) {
3970            solver->solveFromHotStart() ;
3971            /*
3972              We now have an estimate of objective degradation that we can use for strong
3973              branching. If we're over the cutoff, the variable is monotone up.
3974              If we actually made it to optimality, check for a solution, and if we have
3975              a good one, call setBestSolution to process it. Note that this may reduce the
3976              cutoff, so we check again to see if we can declare this variable monotone.
3977            */
3978            if (solver->isProvenOptimal())
3979                iStatus = 0; // optimal
3980            else if (solver->isIterationLimitReached()
3981                     && !solver->isDualObjectiveLimitReached())
3982                iStatus = 2; // unknown
3983            else
3984                iStatus = 1; // infeasible
3985            newObjectiveValue = solver->getObjSense() * solver->getObjValue();
3986            choice.numItersUp = solver->getIterationCount();
3987            numberIterationsAllowed -= choice.numItersUp;
3988            objectiveChange = newObjectiveValue  - objectiveValue_;
3989            if (!iStatus) {
3990                choice.finishedUp = true ;
3991                if (newObjectiveValue >= cutoff) {
3992                    objectiveChange = 1.0e100; // say infeasible
3993                } else {
3994                    // See if integer solution
3995                    if (model->feasibleSolution(choice.numIntInfeasUp,
3996                                                choice.numObjInfeasUp)
3997                            && model->problemFeasibility()->feasible(model, -1) >= 0) {
3998                        model->setBestSolution(CBC_STRONGSOL,
3999                                               newObjectiveValue,
4000                                               solver->getColSolution()) ;
4001                        model->setLastHeuristic(NULL);
4002                        model->incrementUsed(solver->getColSolution());
4003                        cutoff = model->getCutoff();
4004                        if (newObjectiveValue >= cutoff)        //  *new* cutoff
4005                            objectiveChange = 1.0e100 ;
4006                    }
4007                }
4008            } else if (iStatus == 1) {
4009                objectiveChange = 1.0e100 ;
4010            } else {
4011                // Can't say much as we did not finish
4012                choice.finishedUp = false ;
4013            }
4014            choice.upMovement = objectiveChange ;
4015
4016            // restore bounds
4017            for ( j = 0; j < numberColumns; j++) {
4018                if (saveLower[j] != lower[j])
4019                    solver->setColLower(j, saveLower[j]);
4020                if (saveUpper[j] != upper[j])
4021                    solver->setColUpper(j, saveUpper[j]);
4022            }
4023        }
4024        // If objective goes above certain amount we can set bound
4025        int jInt = back[iColumn];
4026        newLower[jInt] = upperValue;
4027        if (choice.finishedDown)
4028            objLower[jInt] = choice.downMovement + objectiveValue_;
4029        else
4030            objLower[jInt] = objectiveValue_;
4031        newUpper[jInt] = lowerValue;
4032        if (choice.finishedUp)
4033            objUpper[jInt] = choice.upMovement + objectiveValue_;
4034        else
4035            objUpper[jInt] = objectiveValue_;
4036        objMin = CoinMin(CoinMin(objLower[jInt], objUpper[jInt]), objMin);
4037        /*
4038          End of evaluation for this candidate variable. Possibilities are:
4039          * Both sides below cutoff; this variable is a candidate for branching.
4040          * Both sides infeasible or above the objective cutoff: no further action
4041          here. Break from the evaluation loop and assume the node will be purged
4042          by the caller.
4043          * One side below cutoff: Install the branch (i.e., fix the variable). Break
4044          from the evaluation loop and assume the node will be reoptimised by the
4045          caller.
4046        */
4047        if (choice.upMovement < 1.0e100) {
4048            if (choice.downMovement < 1.0e100) {
4049                objMax = CoinMax(CoinMax(objLower[jInt], objUpper[jInt]), objMax);
4050                // In case solution coming in was odd
4051                choice.upMovement = CoinMax(0.0, choice.upMovement);
4052                choice.downMovement = CoinMax(0.0, choice.downMovement);
4053                // feasible -
4054                model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
4055                << iObject << iColumn
4056                << choice.downMovement << choice.numIntInfeasDown
4057                << choice.upMovement << choice.numIntInfeasUp
4058                << value
4059                << CoinMessageEol;
4060            } else {
4061                // up feasible, down infeasible
4062                if (!satisfied)
4063                    needResolve = true;
4064                choice.fix = 1;
4065                numberToFix++;
4066                saveLower[iColumn] = upperValue;
4067                solver->setColLower(iColumn, upperValue);
4068            }
4069        } else {
4070            if (choice.downMovement < 1.0e100) {
4071                // down feasible, up infeasible
4072                if (!satisfied)
4073                    needResolve = true;
4074                choice.fix = -1;
4075                numberToFix++;
4076                saveUpper[iColumn] = lowerValue;
4077                solver->setColUpper(iColumn, lowerValue);
4078            } else {
4079                // neither side feasible
4080                COIN_DETAIL_PRINT(printf("Both infeasible for choice %d sequence %d\n", i,
4081                                         model->object(choice.objectNumber)->columnNumber()));
4082                delete ws;
4083                ws = NULL;
4084                //solver->writeMps("bad");
4085                numberToFix = -1;
4086                delete choice.possibleBranch;
4087                choice.possibleBranch = NULL;
4088                break;
4089            }
4090        }
4091        delete choice.possibleBranch;
4092        if (numberIterationsAllowed <= 0)
4093            break;
4094        //printf("obj %d, col %d, down %g up %g value %g\n",iObject,iColumn,
4095        //     choice.downMovement,choice.upMovement,value);
4096    }
4097    COIN_DETAIL_PRINT(printf("Best possible solution %g, can fix more if solution of %g found - looked at %d variables in %d iterations\n",
4098                             objMin, objMax, iDo, model->numberAnalyzeIterations() - numberIterationsAllowed));
4099    model->setNumberAnalyzeIterations(numberIterationsAllowed);
4100    // Delete the snapshot
4101    solver->unmarkHotStart();
4102    // back to normal
4103    solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
4104    solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit);
4105    // restore basis
4106    solver->setWarmStart(ws);
4107    delete ws;
4108
4109    delete [] sort;
4110    delete [] whichObject;
4111    delete [] saveLower;
4112    delete [] saveUpper;
4113    delete [] back;
4114    // restore solution
4115    solver->setColSolution(saveSolution);
4116# ifdef COIN_HAS_CLP
4117    if (osiclp)
4118        osiclp->setSpecialOptions(saveClpOptions);
4119# endif
4120    model->reserveCurrentSolution(saveSolution);
4121    delete [] saveSolution;
4122    if (needResolve)
4123        solver->resolve();
4124    return numberToFix;
4125}
4126
4127
4128CbcNode::CbcNode(const CbcNode & rhs)
4129        : CoinTreeNode(rhs)
4130{
4131#ifdef CHECK_NODE
4132    printf("CbcNode %x Constructor from rhs %x\n", this, &rhs);
4133#endif
4134    if (rhs.nodeInfo_)
4135        nodeInfo_ = rhs.nodeInfo_->clone();
4136    else
4137        nodeInfo_ = NULL;
4138    objectiveValue_ = rhs.objectiveValue_;
4139    guessedObjectiveValue_ = rhs.guessedObjectiveValue_;
4140    sumInfeasibilities_ = rhs.sumInfeasibilities_;
4141    if (rhs.branch_)
4142        branch_ = rhs.branch_->clone();
4143    else
4144        branch_ = NULL;
4145    depth_ = rhs.depth_;
4146    numberUnsatisfied_ = rhs.numberUnsatisfied_;
4147    nodeNumber_ = rhs.nodeNumber_;
4148    state_ = rhs.state_;
4149    if (nodeInfo_)
4150        assert ((state_&2) != 0);
4151    else
4152        assert ((state_&2) == 0);
4153}
4154
4155CbcNode &
4156CbcNode::operator=(const CbcNode & rhs)
4157{
4158    if (this != &rhs) {
4159        delete nodeInfo_;
4160        if (rhs.nodeInfo_)
4161            nodeInfo_ = rhs.nodeInfo_->clone();
4162        else
4163            nodeInfo_ = NULL;
4164        objectiveValue_ = rhs.objectiveValue_;
4165        guessedObjectiveValue_ = rhs.guessedObjectiveValue_;
4166        sumInfeasibilities_ = rhs.sumInfeasibilities_;
4167        if (rhs.branch_)
4168            branch_ = rhs.branch_->clone();
4169        else
4170            branch_ = NULL,
4171                      depth_ = rhs.depth_;
4172        numberUnsatisfied_ = rhs.numberUnsatisfied_;
4173        nodeNumber_ = rhs.nodeNumber_;
4174        state_ = rhs.state_;
4175        if (nodeInfo_)
4176            assert ((state_&2) != 0);
4177        else
4178            assert ((state_&2) == 0);
4179    }
4180    return *this;
4181}
4182CbcNode::~CbcNode ()
4183{
4184#ifdef CHECK_NODE
4185    if (nodeInfo_) {
4186        printf("CbcNode %x Destructor nodeInfo %x (%d)\n",
4187               this, nodeInfo_, nodeInfo_->numberPointingToThis());
4188        //assert(nodeInfo_->numberPointingToThis()>=0);
4189    } else {
4190        printf("CbcNode %x Destructor nodeInfo %x (?)\n",
4191               this, nodeInfo_);
4192    }
4193#endif
4194    if (nodeInfo_) {
4195        // was if (nodeInfo_&&(state_&2)!=0) {
4196        nodeInfo_->nullOwner();
4197        int numberToDelete = nodeInfo_->numberBranchesLeft();
4198        //    CbcNodeInfo * parent = nodeInfo_->parent();
4199        //assert (nodeInfo_->numberPointingToThis()>0);
4200        if (nodeInfo_->decrement(numberToDelete) == 0 || (state_&2) == 0) {
4201            if ((state_&2) == 0)
4202                nodeInfo_->nullParent();
4203            delete nodeInfo_;
4204        } else {
4205            //printf("node %x nodeinfo %x parent %x\n",this,nodeInfo_,nodeInfo_->parent());
4206            // anyway decrement parent
4207            //if (parent)
4208            ///parent->decrement(1);
4209        }
4210    }
4211    delete branch_;
4212}
4213// Decrement  active cut counts
4214void
4215CbcNode::decrementCuts(int change)
4216{
4217    if (nodeInfo_)
4218        assert ((state_&2) != 0);
4219    else
4220        assert ((state_&2) == 0);
4221    if (nodeInfo_) {
4222        nodeInfo_->decrementCuts(change);
4223    }
4224}
4225void
4226CbcNode::decrementParentCuts(CbcModel * model, int change)
4227{
4228    if (nodeInfo_)
4229        assert ((state_&2) != 0);
4230    else
4231        assert ((state_&2) == 0);
4232    if (nodeInfo_) {
4233        nodeInfo_->decrementParentCuts(model, change);
4234    }
4235}
4236
4237/*
4238  Initialize reference counts (numberPointingToThis, numberBranchesLeft_)
4239  in the attached nodeInfo_.
4240*/
4241void
4242CbcNode::initializeInfo()
4243{
4244    assert(nodeInfo_ && branch_) ;
4245    nodeInfo_->initializeInfo(branch_->numberBranches());
4246    assert ((state_&2) != 0);
4247    assert (nodeInfo_->numberBranchesLeft() ==
4248            branch_->numberBranchesLeft());
4249}
4250// Nulls out node info
4251void
4252CbcNode::nullNodeInfo()
4253{
4254    nodeInfo_ = NULL;
4255    // say not active
4256    state_ &= ~2;
4257}
4258
4259int
4260CbcNode::branch(OsiSolverInterface * solver)
4261{
4262    double changeInGuessed;
4263    assert (nodeInfo_->numberBranchesLeft() ==
4264            branch_->numberBranchesLeft());
4265    if (!solver)
4266        changeInGuessed = branch_->branch();
4267    else
4268        changeInGuessed = branch_->branch(solver);
4269    guessedObjectiveValue_ += changeInGuessed;
4270    //#define PRINTIT
4271#ifdef PRINTIT
4272    int numberLeft = nodeInfo_->numberBranchesLeft();
4273    CbcNodeInfo * parent = nodeInfo_->parent();
4274    int parentNodeNumber = -1;
4275    CbcBranchingObject * object1 =
4276        dynamic_cast<CbcBranchingObject *>(branch_) ;
4277    //OsiObject * object = object1->
4278    //int sequence = object->columnNumber);
4279    int id = -1;
4280    double value = 0.0;
4281    if (object1) {
4282        id = object1->variable();
4283        value = object1->value();
4284    }
4285    printf("id %d value %g objvalue %g\n", id, value, objectiveValue_);
4286    if (parent)
4287        parentNodeNumber = parent->nodeNumber();
4288    printf("Node number %d, %s, way %d, depth %d, parent node number %d\n",
4289           nodeInfo_->nodeNumber(), (numberLeft == 2) ? "leftBranch" : "rightBranch",
4290           way(), depth_, parentNodeNumber);
4291    assert (parentNodeNumber != nodeInfo_->nodeNumber());
4292#endif
4293    return nodeInfo_->branchedOn();
4294}
4295/* Active arm of the attached OsiBranchingObject.
4296
4297   In the simplest instance, coded -1 for the down arm of the branch, +1 for
4298   the up arm. But see OsiBranchingObject::way()
4299   Use nodeInfo--.numberBranchesLeft_ to see how active
4300
4301   Except that there is no OsiBranchingObject::way(), and this'll fail in any
4302   event because we have various OsiXXXBranchingObjects which aren't descended
4303   from CbcBranchingObjects. I think branchIndex() is the appropriate
4304   equivalent, but could be wrong. (lh, 061220)
4305
4306   071212: I'm finally getting back to cbc-generic and rescuing a lot of my
4307   annotation from branches/devel (which was killed in summer). I'm going to
4308   put back an assert(obj) just to see what happens. It's still present as of
4309   the most recent change to CbcNode (r833).
4310
4311   080104: Yep, we can arrive here with an OsiBranchingObject. Removed the
4312   assert, it's served its purpose.
4313
4314   080226: John finally noticed this problem and added a way() method to the
4315   OsiBranchingObject hierarchy. Removing my workaround.
4316
4317*/
4318int
4319CbcNode::way() const
4320{
4321    if (branch_) {
4322        CbcBranchingObject * obj =
4323            dynamic_cast <CbcBranchingObject *>(branch_) ;
4324        if (obj) {
4325            return obj->way();
4326        } else {
4327            OsiTwoWayBranchingObject * obj2 =
4328                dynamic_cast <OsiTwoWayBranchingObject *>(branch_) ;
4329            assert (obj2);
4330            return obj2->way();
4331        }
4332    } else {
4333        return 0;
4334    }
4335}
4336/* Create a branching object for the node
4337
4338   The routine scans the object list of the model and selects a set of
4339   unsatisfied objects as candidates for branching. The candidates are
4340   evaluated, and an appropriate branch object is installed.
4341
4342   The numberPassesLeft is decremented to stop fixing one variable each time
4343   and going on and on (e.g. for stock cutting, air crew scheduling)
4344
4345   If evaluation determines that an object is monotone or infeasible,
4346   the routine returns immediately. In the case of a monotone object,
4347   the branch object has already been called to modify the model.
4348
4349   Return value:
4350   <ul>
4351   <li>  0: A branching object has been installed
4352   <li> -1: A monotone object was discovered
4353   <li> -2: An infeasible object was discovered
4354   </ul>
4355   Branch state:
4356   <ul>
4357   <li> -1: start
4358   <li> -1: A monotone object was discovered
4359   <li> -2: An infeasible object was discovered
4360   </ul>
4361*/
4362int
4363CbcNode::chooseOsiBranch (CbcModel * model,
4364                          CbcNode * lastNode,
4365                          OsiBranchingInformation * usefulInfo,
4366                          int branchState)
4367{
4368    int returnStatus = 0;
4369    if (lastNode)
4370        depth_ = lastNode->depth_ + 1;
4371    else
4372        depth_ = 0;
4373    OsiSolverInterface * solver = model->solver();
4374    objectiveValue_ = solver->getObjValue() * solver->getObjSense();
4375    usefulInfo->objectiveValue_ = objectiveValue_;
4376    usefulInfo->depth_ = depth_;
4377    const double * saveInfoSol = usefulInfo->solution_;
4378    double * saveSolution = new double[solver->getNumCols()];
4379    memcpy(saveSolution, solver->getColSolution(), solver->getNumCols()*sizeof(double));
4380    usefulInfo->solution_ = saveSolution;
4381    OsiChooseVariable * choose = model->branchingMethod()->chooseMethod();
4382    int numberUnsatisfied = -1;
4383    if (branchState < 0) {
4384        // initialize
4385        // initialize sum of "infeasibilities"
4386        sumInfeasibilities_ = 0.0;
4387        numberUnsatisfied = choose->setupList(usefulInfo, true);
4388        numberUnsatisfied_ = numberUnsatisfied;
4389        branchState = 0;
4390        if (numberUnsatisfied_ < 0) {
4391            // infeasible
4392            delete [] saveSolution;
4393            return -2;
4394        }
4395    }
4396    // unset best
4397    int best = -1;
4398    choose->setBestObjectIndex(-1);
4399    if (numberUnsatisfied) {
4400        if (branchState > 0 || !choose->numberOnList()) {
4401            // we need to return at once - don't do strong branching or anything
4402            if (choose->numberOnList() || !choose->numberStrong()) {
4403                best = choose->candidates()[0];
4404                choose->setBestObjectIndex(best);
4405            } else {
4406                // nothing on list - need to try again - keep any solution
4407                numberUnsatisfied = choose->setupList(usefulInfo, false);
4408                numberUnsatisfied_ = numberUnsatisfied;
4409                if (numberUnsatisfied) {
4410                    best = choose->candidates()[0];
4411                    choose->setBestObjectIndex(best);
4412                }
4413            }
4414        } else {
4415            // carry on with strong branching or whatever
4416            int returnCode = choose->chooseVariable(solver, usefulInfo, true);
4417            // update number of strong iterations etc
4418            model->incrementStrongInfo(choose->numberStrongDone(), choose->numberStrongIterations(),
4419                                       returnCode == -1 ? 0 : choose->numberStrongFixed(), returnCode == -1);
4420            if (returnCode > 1) {
4421                // has fixed some
4422                returnStatus = -1;
4423            } else if (returnCode == -1) {
4424                // infeasible
4425                returnStatus = -2;
4426            } else if (returnCode == 0) {
4427                // normal
4428                returnStatus = 0;
4429                numberUnsatisfied = 1;
4430            } else {
4431                // ones on list satisfied - double check
4432                numberUnsatisfied = choose->setupList(usefulInfo, false);
4433                numberUnsatisfied_ = numberUnsatisfied;
4434                if (numberUnsatisfied) {
4435                    best = choose->candidates()[0];
4436                    choose->setBestObjectIndex(best);
4437                }
4438            }
4439        }
4440    }
4441    delete branch_;
4442    branch_ = NULL;
4443    guessedObjectiveValue_ = COIN_DBL_MAX;//objectiveValue_; // for now
4444    if (!returnStatus) {
4445        if (numberUnsatisfied) {
4446            // create branching object
4447            const OsiObject * obj = model->solver()->object(choose->bestObjectIndex());
4448            //const OsiSolverInterface * solver = usefulInfo->solver_;
4449            branch_ = obj->createBranch(model->solver(), usefulInfo, obj->whichWay());
4450        }
4451    }
4452    usefulInfo->solution_ = saveInfoSol;
4453    delete [] saveSolution;
4454    // may have got solution
4455    if (choose->goodSolution()
4456            && model->problemFeasibility()->feasible(model, -1) >= 0) {
4457        // yes
4458        double objValue = choose->goodObjectiveValue();
4459        model->setBestSolution(CBC_STRONGSOL,
4460                               objValue,
4461                               choose->goodSolution()) ;
4462        model->setLastHeuristic(NULL);
4463        model->incrementUsed(choose->goodSolution());
4464        choose->clearGoodSolution();
4465    }
4466    return returnStatus;
4467}
4468int
4469CbcNode::chooseClpBranch (CbcModel * model,
4470                          CbcNode * lastNode)
4471{
4472    assert(lastNode);
4473    depth_ = lastNode->depth_ + 1;
4474    delete branch_;
4475    branch_ = NULL;
4476    OsiSolverInterface * solver = model->solver();
4477    //double saveObjectiveValue = solver->getObjValue();
4478    //double objectiveValue = CoinMax(solver->getObjSense()*saveObjectiveValue,objectiveValue_);
4479    const double * lower = solver->getColLower();
4480    const double * upper = solver->getColUpper();
4481    // point to useful information
4482    OsiBranchingInformation usefulInfo = model->usefulInformation();
4483    // and modify
4484    usefulInfo.depth_ = depth_;
4485    int i;
4486    //bool beforeSolution = model->getSolutionCount()==0;
4487    int numberObjects = model->numberObjects();
4488    int numberColumns = model->getNumCols();
4489    double * saveUpper = new double[numberColumns];
4490    double * saveLower = new double[numberColumns];
4491
4492    // Save solution in case heuristics need good solution later
4493
4494    double * saveSolution = new double[numberColumns];
4495    memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
4496    model->reserveCurrentSolution(saveSolution);
4497    for (i = 0; i < numberColumns; i++) {
4498        saveLower[i] = lower[i];
4499        saveUpper[i] = upper[i];
4500    }
4501    // Save basis
4502    CoinWarmStart * ws = solver->getWarmStart();
4503    numberUnsatisfied_ = 0;
4504    // initialize sum of "infeasibilities"
4505    sumInfeasibilities_ = 0.0;
4506    // Note looks as if off end (hidden one)
4507    OsiObject * object = model->modifiableObject(numberObjects);
4508    CbcGeneralDepth * thisOne = dynamic_cast <CbcGeneralDepth *> (object);
4509    assert (thisOne);
4510    OsiClpSolverInterface * clpSolver
4511    = dynamic_cast<OsiClpSolverInterface *> (solver);
4512    assert (clpSolver);
4513    ClpSimplex * simplex = clpSolver->getModelPtr();
4514    int preferredWay;
4515    double infeasibility = object->infeasibility(&usefulInfo, preferredWay);
4516    if (thisOne->whichSolution() >= 0) {
4517        ClpNode * nodeInfo=NULL;
4518        if ((model->moreSpecialOptions()&33554432)==0) {
4519          nodeInfo = thisOne->nodeInfo(thisOne->whichSolution());
4520          nodeInfo->applyNode(simplex, 2);
4521        } else {
4522          // from diving
4523          CbcSubProblem ** nodes = reinterpret_cast<CbcSubProblem **>
4524            (model->temporaryPointer());
4525          assert (nodes);
4526          int numberDo=thisOne->numberNodes()-1;
4527          for (int iNode=0;iNode<numberDo;iNode++)
4528            nodes[iNode]->apply(solver,1);
4529          nodes[numberDo]->apply(solver,9+16);
4530        }
4531        int saveLogLevel = simplex->logLevel();
4532        simplex->setLogLevel(0);
4533        simplex->dual();
4534        simplex->setLogLevel(saveLogLevel);
4535        double cutoff = model->getCutoff();
4536        bool goodSolution = true;
4537        if (simplex->status()) {
4538            //simplex->writeMps("bad7.mps",2);
4539            if (nodeInfo) {
4540              if (nodeInfo->objectiveValue() > cutoff - 1.0e-2)
4541                goodSolution = false;
4542              else
4543                assert (!simplex->status());
4544            } else {
4545              // debug diving
4546              assert (!simplex->status());
4547            }
4548        }
4549        if (goodSolution) {
4550            double newObjectiveValue = solver->getObjSense() * solver->getObjValue();
4551            // See if integer solution
4552            int numInf;
4553            int numInf2;
4554            bool gotSol = model->feasibleSolution(numInf, numInf2);
4555            if (!gotSol) {
4556              COIN_DETAIL_PRINT(printf("numinf %d\n", numInf));
4557                double * sol = simplex->primalColumnSolution();
4558                for (int i = 0; i < numberColumns; i++) {
4559                    if (simplex->isInteger(i)) {
4560                        double value = floor(sol[i] + 0.5);
4561                        if (fabs(value - sol[i]) > 1.0e-7) {
4562                          COIN_DETAIL_PRINT(printf("%d value %g\n", i, sol[i]));
4563                            if (fabs(value - sol[i]) < 1.0e-3) {
4564                                sol[i] = value;
4565                            }
4566                        }
4567                    }
4568                }
4569                simplex->writeMps("bad8.mps", 2);
4570                bool gotSol = model->feasibleSolution(numInf, numInf2);
4571                if (!gotSol)
4572                    assert (gotSol);
4573            }
4574            model->setBestSolution(CBC_STRONGSOL,
4575                                   newObjectiveValue,
4576                                   solver->getColSolution()) ;
4577            model->setLastHeuristic(NULL);
4578            model->incrementUsed(solver->getColSolution());
4579        }
4580    }
4581    // restore bounds
4582    {
4583        for (int j = 0; j < numberColumns; j++) {
4584            if (saveLower[j] != lower[j])
4585                solver->setColLower(j, saveLower[j]);
4586            if (saveUpper[j] != upper[j])
4587                solver->setColUpper(j, saveUpper[j]);
4588        }
4589    }
4590    // restore basis
4591    solver->setWarmStart(ws);
4592    delete ws;
4593    int anyAction;
4594    //#define CHECK_PATH
4595#ifdef CHECK_PATH
4596    extern int gotGoodNode_Z;
4597    if (gotGoodNode_Z >= 0)
4598        printf("good node %d %g\n", gotGoodNode_Z, infeasibility);
4599#endif
4600    if (infeasibility > 0.0) {
4601        if (infeasibility == COIN_DBL_MAX) {
4602            anyAction = -2; // infeasible
4603        } else {
4604            branch_ = thisOne->createCbcBranch(solver, &usefulInfo, preferredWay);
4605            if (branch_) {
4606              // Set to first one (and change when re-pushing)
4607              CbcGeneralBranchingObject * branch =
4608                dynamic_cast <CbcGeneralBranchingObject *> (branch_);
4609              branch->state(objectiveValue_, sumInfeasibilities_,
4610                            numberUnsatisfied_, 0);
4611              branch->setNode(this);
4612              anyAction = 0;
4613            } else {
4614              anyAction = -2; // mark as infeasible
4615            }
4616        }
4617    } else {
4618        anyAction = -1;
4619    }
4620#ifdef CHECK_PATH
4621    gotGoodNode_Z = -1;
4622#endif
4623    // Set guessed solution value
4624    guessedObjectiveValue_ = objectiveValue_ + 1.0e-5;
4625    delete [] saveLower;
4626    delete [] saveUpper;
4627
4628    // restore solution
4629    solver->setColSolution(saveSolution);
4630    delete [] saveSolution;
4631    return anyAction;
4632}
4633/* Double checks in case node can change its mind!
4634   Returns objective value
4635   Can change objective etc */
4636double
4637CbcNode::checkIsCutoff(double cutoff)
4638{
4639    branch_->checkIsCutoff(cutoff);
4640    return objectiveValue_;
4641}
4642
Note: See TracBrowser for help on using the repository browser.