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

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

Fix SOS problem and also bad bestSolution_

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