source: trunk/Cbc/src/CbcNode.cpp @ 1880

Last change on this file since 1880 was 1880, checked in by forrest, 7 years ago

make it easier to use slow exotic cuts
more on cutoff as constraint and multiple root solver fixes
general fixing of bugs found on MIQP etc

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