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

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

fixes for odd SOS

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