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

Last change on this file since 2094 was 2094, checked in by forrest, 6 years ago

for memory leaks and heuristics and some experimental stuff

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