source: stable/2.9/Cbc/src/CbcNode.cpp @ 2272

Last change on this file since 2272 was 2272, checked in by tkr, 2 years ago

Merging r2269 from trunk

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