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

Last change on this file since 2098 was 2098, checked in by forrest, 4 years ago

fix assert in hot start

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