source: branches/sandbox/Cbc/src/CbcModel.cpp @ 1286

Last change on this file since 1286 was 1286, checked in by EdwinStraver, 10 years ago

Changed formatting using AStyle -A4 -p

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 682.0 KB
Line 
1/* $Id: CbcModel.cpp 1286 2009-11-09 23:33:07Z EdwinStraver $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4#if defined(_MSC_VER)
5// Turn off compiler warning about long names
6#  pragma warning(disable:4786)
7#endif
8
9#include "CbcConfig.h"
10
11#include <string>
12//#define CBC_DEBUG 1
13//#define CHECK_CUT_COUNTS
14//#define CHECK_NODE_FULL
15//#define NODE_LOG
16//#define GLOBAL_CUTS_JUST_POINTERS
17#ifdef CGL_DEBUG_GOMORY
18extern int gomory_try;
19#endif
20#include <cassert>
21#include <cmath>
22#include <cfloat>
23
24#ifdef COIN_HAS_CLP
25// include Presolve from Clp
26#include "ClpPresolve.hpp"
27#include "OsiClpSolverInterface.hpp"
28#include "ClpNode.hpp"
29#include "ClpDualRowDantzig.hpp"
30#include "ClpSimplexPrimal.hpp"
31#endif
32
33#include "CbcEventHandler.hpp"
34
35#include "OsiSolverInterface.hpp"
36#include "OsiAuxInfo.hpp"
37#include "OsiSolverBranch.hpp"
38#include "OsiChooseVariable.hpp"
39#include "CoinWarmStartBasis.hpp"
40#include "CoinPackedMatrix.hpp"
41#include "CoinHelperFunctions.hpp"
42#include "CbcBranchActual.hpp"
43#include "CbcBranchDynamic.hpp"
44#include "CbcHeuristic.hpp"
45#include "CbcHeuristicFPump.hpp"
46#include "CbcHeuristicDive.hpp"
47#include "CbcModel.hpp"
48#include "CbcTreeLocal.hpp"
49#include "CbcStatistics.hpp"
50#include "CbcStrategy.hpp"
51#include "CbcMessage.hpp"
52#include "OsiRowCut.hpp"
53#include "OsiColCut.hpp"
54#include "OsiRowCutDebugger.hpp"
55#include "OsiCuts.hpp"
56#include "CbcCountRowCut.hpp"
57#include "CbcCutGenerator.hpp"
58#include "CbcFeasibilityBase.hpp"
59#include "CbcFathom.hpp"
60// include Probing
61#include "CglProbing.hpp"
62#include "CglGomory.hpp"
63#include "CglTwomir.hpp"
64// include preprocessing
65#include "CglPreProcess.hpp"
66#include "CglDuplicateRow.hpp"
67#include "CglStored.hpp"
68#include "CglClique.hpp"
69
70#include "CoinTime.hpp"
71#include "CoinMpsIO.hpp"
72
73#include "CbcCompareActual.hpp"
74#include "CbcTree.hpp"
75#ifdef CBC_THREAD
76#include <pthread.h>
77#ifdef HAVE_CLOCK_GETTIME
78inline int my_gettime(struct timespec* tp)
79{
80    return clock_gettime(CLOCK_REALTIME, tp);
81}
82#else
83#ifndef _MSC_VER
84inline int my_gettime(struct timespec* tp)
85{
86    struct timeval tv;
87    int ret = gettimeofday(&tv, NULL);
88    tp->tv_sec = tv.tv_sec;
89    tp->tv_nsec = tv.tv_usec * 1000;
90    return ret;
91}
92#else
93inline int my_gettime(struct timespec* tp)
94{
95    double t = CoinGetTimeOfDay();
96    tp->tv_sec = (int)floor(t);
97    tp->tv_nsec = (int)((tp->tv_sec - floor(t)) / 1000000.0);
98    return 0;
99}
100#endif
101#endif
102
103struct Coin_pthread_t {
104    pthread_t   thr;
105    long                status;
106};
107
108// To Pass across to doOneNode
109typedef struct {
110    CbcModel * baseModel;
111    CbcModel * thisModel;
112    CbcNode * node; // filled in every time
113    CbcNode * createdNode; // filled in every time on return
114    Coin_pthread_t threadIdOfBase;
115    pthread_mutex_t * mutex; // for locking data
116    pthread_mutex_t * mutex2; // for waking up threads
117    pthread_cond_t * condition2; // for waking up thread
118    int returnCode; // -1 available, 0 busy, 1 finished , 2??
119    double timeLocked;
120    double timeWaitingToLock;
121    double timeWaitingToStart;
122    double timeInThread;
123    int numberTimesLocked;
124    int numberTimesUnlocked;
125    int numberTimesWaitingToStart;
126    int saveStuff[2];
127    int dantzigState; // 0 unset, -1 waiting to be set, 1 set
128    struct timespec absTime;
129    bool locked;
130    int nDeleteNode;
131    CbcNode ** delNode;
132    int maxDeleteNode;
133    int nodesThisTime;
134    int iterationsThisTime;
135} threadStruct;
136static void * doNodesThread(void * voidInfo);
137static void * doCutsThread(void * voidInfo);
138static void * doHeurThread(void * voidInfo);
139#endif
140/* Various functions local to CbcModel.cpp */
141
142namespace {
143
144//-------------------------------------------------------------------
145// Returns the greatest common denominator of two
146// positive integers, a and b, found using Euclid's algorithm
147//-------------------------------------------------------------------
148static int gcd(int a, int b)
149{
150    int remainder = -1;
151    // make sure a<=b (will always remain so)
152    if (a > b) {
153        // Swap a and b
154        int temp = a;
155        a = b;
156        b = temp;
157    }
158    // if zero then gcd is nonzero (zero may occur in rhs of packed)
159    if (!a) {
160        if (b) {
161            return b;
162        } else {
163            printf("**** gcd given two zeros!!\n");
164            abort();
165        }
166    }
167    while (remainder) {
168        remainder = b % a;
169        b = a;
170        a = remainder;
171    }
172    return b;
173}
174
175
176
177#ifdef CHECK_NODE_FULL
178
179/*
180  Routine to verify that tree linkage is correct. The invariant that is tested
181  is
182
183  reference count = (number of actual references) + (number of branches left)
184
185  The routine builds a set of paired arrays, info and count, by traversing the
186  tree. Each CbcNodeInfo is recorded in info, and the number of times it is
187  referenced (via the parent field) is recorded in count. Then a final check is
188  made to see if the numberPointingToThis_ field agrees.
189*/
190
191void verifyTreeNodes (const CbcTree * branchingTree, const CbcModel &model)
192
193{
194    if (model.getNodeCount() == 661) return;
195    printf("*** CHECKING tree after %d nodes\n", model.getNodeCount()) ;
196
197    int j ;
198    int nNodes = branchingTree->size() ;
199# define MAXINFO 1000
200    int *count = new int [MAXINFO] ;
201    CbcNodeInfo **info = new CbcNodeInfo*[MAXINFO] ;
202    int nInfo = 0 ;
203    /*
204      Collect all CbcNodeInfo objects in info, by starting from each live node and
205      traversing back to the root. Nodes in the live set should have unexplored
206      branches remaining.
207
208      TODO: The `while (nodeInfo)' loop could be made to break on reaching a
209        common ancester (nodeInfo is found in info[k]). Alternatively, the
210        check could change to signal an error if nodeInfo is not found above a
211        common ancestor.
212    */
213    for (j = 0 ; j < nNodes ; j++) {
214        CbcNode *node = branchingTree->nodePointer(j) ;
215        if (!node)
216            continue;
217        CbcNodeInfo *nodeInfo = node->nodeInfo() ;
218        int change = node->nodeInfo()->numberBranchesLeft() ;
219        assert(change) ;
220        while (nodeInfo) {
221            int k ;
222            for (k = 0 ; k < nInfo ; k++) {
223                if (nodeInfo == info[k]) break ;
224            }
225            if (k == nInfo) {
226                assert(nInfo < MAXINFO) ;
227                nInfo++ ;
228                info[k] = nodeInfo ;
229                count[k] = 0 ;
230            }
231            nodeInfo = nodeInfo->parent() ;
232        }
233    }
234    /*
235      Walk the info array. For each nodeInfo, look up its parent in info and
236      increment the corresponding count.
237    */
238    for (j = 0 ; j < nInfo ; j++) {
239        CbcNodeInfo *nodeInfo = info[j] ;
240        nodeInfo = nodeInfo->parent() ;
241        if (nodeInfo) {
242            int k ;
243            for (k = 0 ; k < nInfo ; k++) {
244                if (nodeInfo == info[k]) break ;
245            }
246            assert (k < nInfo) ;
247            count[k]++ ;
248        }
249    }
250    /*
251      Walk the info array one more time and check that the invariant holds. The
252      number of references (numberPointingToThis()) should equal the sum of the
253      number of actual references (held in count[]) plus the number of potential
254      references (unexplored branches, numberBranchesLeft()).
255    */
256    for (j = 0; j < nInfo; j++) {
257        CbcNodeInfo * nodeInfo = info[j] ;
258        if (nodeInfo) {
259            int k ;
260            for (k = 0; k < nInfo; k++)
261                if (nodeInfo == info[k])
262                    break ;
263            printf("Nodeinfo %x - %d left, %d count\n",
264                   nodeInfo,
265                   nodeInfo->numberBranchesLeft(),
266                   nodeInfo->numberPointingToThis()) ;
267            assert(nodeInfo->numberPointingToThis() ==
268                   count[k] + nodeInfo->numberBranchesLeft()) ;
269        }
270    }
271
272    delete [] count ;
273    delete [] info ;
274
275    return ;
276}
277
278#endif  /* CHECK_NODE_FULL */
279
280
281
282#ifdef CHECK_CUT_COUNTS
283
284/*
285  Routine to verify that cut reference counts are correct.
286*/
287void verifyCutCounts (const CbcTree * branchingTree, CbcModel &model)
288
289{
290    printf("*** CHECKING cuts after %d nodes\n", model.getNodeCount()) ;
291
292    int j ;
293    int nNodes = branchingTree->size() ;
294
295    /*
296      cut.tempNumber_ exists for the purpose of doing this verification. Clear it
297      in all cuts. We traverse the tree by starting from each live node and working
298      back to the root. At each CbcNodeInfo, check for cuts.
299    */
300    for (j = 0 ; j < nNodes ; j++) {
301        CbcNode *node = branchingTree->nodePointer(j) ;
302        CbcNodeInfo * nodeInfo = node->nodeInfo() ;
303        assert (node->nodeInfo()->numberBranchesLeft()) ;
304        while (nodeInfo) {
305            int k ;
306            for (k = 0 ; k < nodeInfo->numberCuts() ; k++) {
307                CbcCountRowCut *cut = nodeInfo->cuts()[k] ;
308                if (cut) cut->tempNumber_ = 0;
309            }
310            nodeInfo = nodeInfo->parent() ;
311        }
312    }
313    /*
314      Walk the live set again, this time collecting the list of cuts in use at each
315      node. addCuts1 will collect the cuts in model.addedCuts_. Take into account
316      that when we recreate the basis for a node, we compress out the slack cuts.
317    */
318    for (j = 0 ; j < nNodes ; j++) {
319        CoinWarmStartBasis *debugws = model.getEmptyBasis() ;
320        CbcNode *node = branchingTree->nodePointer(j) ;
321        CbcNodeInfo *nodeInfo = node->nodeInfo();
322        int change = node->nodeInfo()->numberBranchesLeft() ;
323        printf("Node %d %x (info %x) var %d way %d obj %g", j, node,
324               node->nodeInfo(), node->columnNumber(), node->way(),
325               node->objectiveValue()) ;
326
327        model.addCuts1(node, debugws) ;
328
329        int i ;
330        int numberRowsAtContinuous = model.numberRowsAtContinuous() ;
331        CbcCountRowCut **addedCuts = model.addedCuts() ;
332        for (i = 0 ; i < model.currentNumberCuts() ; i++) {
333            CoinWarmStartBasis::Status status =
334                debugws->getArtifStatus(i + numberRowsAtContinuous) ;
335            if (status != CoinWarmStartBasis::basic && addedCuts[i]) {
336                addedCuts[i]->tempNumber_ += change ;
337            }
338        }
339
340        while (nodeInfo) {
341            nodeInfo = nodeInfo->parent() ;
342            if (nodeInfo) printf(" -> %x", nodeInfo);
343        }
344        printf("\n") ;
345        delete debugws ;
346    }
347    /*
348      The moment of truth: We've tallied up the references by direct scan of the  search tree. Check for agreement with the count in the cut.
349
350      TODO: Rewrite to check and print mismatch only when tempNumber_ == 0?
351    */
352    for (j = 0 ; j < nNodes ; j++) {
353        CbcNode *node = branchingTree->nodePointer(j) ;
354        CbcNodeInfo *nodeInfo = node->nodeInfo();
355        while (nodeInfo) {
356            int k ;
357            for (k = 0 ; k < nodeInfo->numberCuts() ; k++) {
358                CbcCountRowCut *cut = nodeInfo->cuts()[k] ;
359                if (cut && cut->tempNumber_ >= 0) {
360                    if (cut->tempNumber_ != cut->numberPointingToThis())
361                        printf("mismatch %x %d %x %d %d\n", nodeInfo, k,
362                               cut, cut->tempNumber_, cut->numberPointingToThis()) ;
363                    else
364                        printf("   match %x %d %x %d %d\n", nodeInfo, k,
365                               cut, cut->tempNumber_, cut->numberPointingToThis()) ;
366                    cut->tempNumber_ = -1 ;
367                }
368            }
369            nodeInfo = nodeInfo->parent() ;
370        }
371    }
372
373    return ;
374}
375
376#endif /* CHECK_CUT_COUNTS */
377
378
379#ifdef CHECK_CUT_SIZE
380
381/*
382  Routine to verify that cut reference counts are correct.
383*/
384void verifyCutSize (const CbcTree * branchingTree, CbcModel &model)
385{
386
387    int j ;
388    int nNodes = branchingTree->size() ;
389    int totalCuts = 0;
390
391    /*
392      cut.tempNumber_ exists for the purpose of doing this verification. Clear it
393      in all cuts. We traverse the tree by starting from each live node and working
394      back to the root. At each CbcNodeInfo, check for cuts.
395    */
396    for (j = 0 ; j < nNodes ; j++) {
397        CbcNode *node = branchingTree->nodePointer(j) ;
398        CbcNodeInfo * nodeInfo = node->nodeInfo() ;
399        assert (node->nodeInfo()->numberBranchesLeft()) ;
400        while (nodeInfo) {
401            totalCuts += nodeInfo->numberCuts();
402            nodeInfo = nodeInfo->parent() ;
403        }
404    }
405    printf("*** CHECKING cuts (size) after %d nodes - %d cuts\n", model.getNodeCount(), totalCuts) ;
406    return ;
407}
408
409#endif /* CHECK_CUT_SIZE */
410
411}
412
413/* End unnamed namespace for CbcModel.cpp */
414
415
416void
417CbcModel::analyzeObjective ()
418/*
419  Try to find a minimum change in the objective function. The first scan
420  checks that there are no continuous variables with non-zero coefficients,
421  and grabs the largest objective coefficient associated with an unfixed
422  integer variable. The second scan attempts to scale up the objective
423  coefficients to a point where they are sufficiently close to integer that
424  we can pretend they are integer, and calculate a gcd over the coefficients
425  of interest. This will be the minimum increment for the scaled coefficients.
426  The final action is to scale the increment back for the original coefficients
427  and install it, if it's better than the existing value.
428
429  John's note: We could do better than this.
430
431  John's second note - apologies for changing s to z
432*/
433{
434    const double *objective = getObjCoefficients() ;
435    const double *lower = getColLower() ;
436    const double *upper = getColUpper() ;
437    /*
438      Scan continuous and integer variables to see if continuous
439      are cover or network with integral rhs.
440    */
441    double continuousMultiplier = 1.0;
442    double * coeffMultiplier = NULL;
443    double largestObj = 0.0;
444    double smallestObj = COIN_DBL_MAX;
445    {
446        const double *rowLower = getRowLower() ;
447        const double *rowUpper = getRowUpper() ;
448        int numberRows = solver_->getNumRows() ;
449        double * rhs = new double [numberRows];
450        memset(rhs, 0, numberRows*sizeof(double));
451        int iColumn;
452        int numberColumns = solver_->getNumCols() ;
453        // Column copy of matrix
454        bool allPlusOnes = true;
455        bool allOnes = true;
456        int problemType = -1;
457        const double * element = solver_->getMatrixByCol()->getElements();
458        const int * row = solver_->getMatrixByCol()->getIndices();
459        const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts();
460        const int * columnLength = solver_->getMatrixByCol()->getVectorLengths();
461        int numberInteger = 0;
462        int numberIntegerObj = 0;
463        int numberGeneralIntegerObj = 0;
464        int numberIntegerWeight = 0;
465        int numberContinuousObj = 0;
466        double cost = COIN_DBL_MAX;
467        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
468            if (upper[iColumn] == lower[iColumn]) {
469                CoinBigIndex start = columnStart[iColumn];
470                CoinBigIndex end = start + columnLength[iColumn];
471                for (CoinBigIndex j = start; j < end; j++) {
472                    int iRow = row[j];
473                    rhs[iRow] += lower[iColumn] * element[j];
474                }
475            } else {
476                double objValue = objective[iColumn];
477                if (solver_->isInteger(iColumn))
478                    numberInteger++;
479                if (objValue) {
480                    if (!solver_->isInteger(iColumn)) {
481                        numberContinuousObj++;
482                    } else {
483                        largestObj = CoinMax(largestObj, fabs(objValue));
484                        smallestObj = CoinMin(smallestObj, fabs(objValue));
485                        numberIntegerObj++;
486                        if (cost == COIN_DBL_MAX)
487                            cost = objValue;
488                        else if (cost != objValue)
489                            cost = -COIN_DBL_MAX;
490                        int gap = static_cast<int> (upper[iColumn] - lower[iColumn]);
491                        if (gap > 1) {
492                            numberGeneralIntegerObj++;
493                            numberIntegerWeight += gap;
494                        }
495                    }
496                }
497            }
498        }
499        int iType = 0;
500        if (!numberContinuousObj && numberIntegerObj <= 5 && numberIntegerWeight <= 100 &&
501                numberIntegerObj*3 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100)
502            iType = 3 + 4;
503        else if (!numberContinuousObj && numberIntegerObj <= 100 &&
504                 numberIntegerObj*5 < numberObjects_ && numberIntegerWeight <= 100 &&
505                 !parentModel_ &&
506                 solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX)
507            iType = 2 + 4;
508        else if (!numberContinuousObj && numberIntegerObj <= 100 &&
509                 numberIntegerObj*5 < numberObjects_ &&
510                 !parentModel_ &&
511                 solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX)
512            iType = 8;
513        int iTest = getMaximumNodes();
514        if (iTest >= 987654320 && iTest < 987654330 && numberObjects_ && !parentModel_) {
515            iType = iTest - 987654320;
516            printf("Testing %d integer variables out of %d objects (%d integer) have cost of %g - %d continuous\n",
517                   numberIntegerObj, numberObjects_, numberInteger, cost, numberContinuousObj);
518            if (iType == 9)
519                exit(77);
520            if (numberContinuousObj)
521                iType = 0;
522        }
523
524        //if (!numberContinuousObj&&(numberIntegerObj<=5||cost!=-COIN_DBL_MAX)&&
525        //numberIntegerObj*3<numberObjects_&&!parentModel_&&solver_->getNumRows()>100) {
526        if (iType) {
527            /*
528            A) put high priority on (if none)
529            B) create artificial objective (if clp)
530            */
531            int iPriority = -1;
532            for (int i = 0; i < numberObjects_; i++) {
533                int k = object_[i]->priority();
534                if (iPriority == -1)
535                    iPriority = k;
536                else if (iPriority != k)
537                    iPriority = -2;
538            }
539            bool branchOnSatisfied = ((iType & 1) != 0);
540            bool createFake = ((iType & 2) != 0);
541            bool randomCost = ((iType & 4) != 0);
542            if (iPriority >= 0) {
543                char general[200];
544                if (cost == -COIN_DBL_MAX) {
545                    sprintf(general, "%d integer variables out of %d objects (%d integer) have costs - high priority",
546                            numberIntegerObj, numberObjects_, numberInteger);
547                } else if (cost == COIN_DBL_MAX) {
548                    sprintf(general, "No integer variables out of %d objects (%d integer) have costs",
549                            numberObjects_, numberInteger);
550                    branchOnSatisfied = false;
551                } else {
552                    sprintf(general, "%d integer variables out of %d objects (%d integer) have cost of %g - high priority",
553                            numberIntegerObj, numberObjects_, numberInteger, cost);
554                }
555                messageHandler()->message(CBC_GENERAL,
556                                          messages())
557                << general << CoinMessageEol ;
558                sprintf(general, "branch on satisfied %c create fake objective %c random cost %c",
559                        branchOnSatisfied ? 'Y' : 'N',
560                        createFake ? 'Y' : 'N',
561                        randomCost ? 'Y' : 'N');
562                messageHandler()->message(CBC_GENERAL,
563                                          messages())
564                << general << CoinMessageEol ;
565                // switch off clp type branching
566                fastNodeDepth_ = -1;
567                int highPriority = (branchOnSatisfied) ? -999 : 100;
568                for (int i = 0; i < numberObjects_; i++) {
569                    CbcSimpleInteger * thisOne = dynamic_cast <CbcSimpleInteger *> (object_[i]);
570                    object_[i]->setPriority(1000);
571                    if (thisOne) {
572                        int iColumn = thisOne->columnNumber();
573                        if (objective[iColumn])
574                            thisOne->setPriority(highPriority);
575                    }
576                }
577            }
578#ifdef COIN_HAS_CLP
579            OsiClpSolverInterface * clpSolver
580            = dynamic_cast<OsiClpSolverInterface *> (solver_);
581            if (clpSolver && createFake) {
582                // Create artificial objective to be used when all else fixed
583                int numberColumns = clpSolver->getNumCols();
584                double * fakeObj = new double [numberColumns];
585                // Column copy
586                const CoinPackedMatrix  * matrixByCol = clpSolver->getMatrixByCol();
587                //const double * element = matrixByCol.getElements();
588                //const int * row = matrixByCol.getIndices();
589                //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
590                const int * columnLength = matrixByCol->getVectorLengths();
591                const double * solution = clpSolver->getColSolution();
592#if 0
593                int nAtBound = 0;
594                for (int i = 0; i < numberColumns; i++) {
595                    double lowerValue = lower[i];
596                    double upperValue = upper[i];
597                    if (clpSolver->isInteger(i)) {
598                        double lowerValue = lower[i];
599                        double upperValue = upper[i];
600                        double value = solution[i];
601                        if (value < lowerValue + 1.0e-6 ||
602                                value > upperValue - 1.0e-6)
603                            nAtBound++;
604                    }
605                }
606#endif
607                CoinDrand48(true, 1234567);
608                for (int i = 0; i < numberColumns; i++) {
609                    double lowerValue = lower[i];
610                    double upperValue = upper[i];
611                    double value = (randomCost) ? ceil((CoinDrand48() + 0.5) * 1000)
612                                   : i + 1 + columnLength[i] * 1000;
613                    value *= 0.001;
614                    //value += columnLength[i];
615                    if (lowerValue > -1.0e5 || upperValue < 1.0e5) {
616                        if (fabs(lowerValue) > fabs(upperValue))
617                            value = - value;
618                        if (clpSolver->isInteger(i)) {
619                            double solValue = solution[i];
620                            // Better to add in 0.5 or 1.0??
621                            if (solValue < lowerValue + 1.0e-6)
622                                value = fabs(value) + 0.5; //fabs(value*1.5);
623                            else if (solValue > upperValue - 1.0e-6)
624                                value = -fabs(value) - 0.5; //-fabs(value*1.5);
625                        }
626                    } else {
627                        value = 0.0;
628                    }
629                    fakeObj[i] = value;
630                }
631                // pass to solver
632                clpSolver->setFakeObjective(fakeObj);
633                delete [] fakeObj;
634            }
635#endif
636        } else if (largestObj < smallestObj*5.0 && !parentModel_ &&
637                   !numberContinuousObj &&
638                   !numberGeneralIntegerObj &&
639                   numberIntegerObj*2 < numberColumns) {
640            // up priorities on costed
641            int iPriority = -1;
642            for (int i = 0; i < numberObjects_; i++) {
643                int k = object_[i]->priority();
644                if (iPriority == -1)
645                    iPriority = k;
646                else if (iPriority != k)
647                    iPriority = -2;
648            }
649            if (iPriority >= 100) {
650#ifdef CLP_INVESTIGATE
651                printf("Setting variables with obj to high priority\n");
652#endif
653                for (int i = 0; i < numberObjects_; i++) {
654                    CbcSimpleInteger * obj =
655                        dynamic_cast <CbcSimpleInteger *>(object_[i]) ;
656                    if (obj) {
657                        int iColumn = obj->columnNumber();
658                        if (objective[iColumn])
659                            object_[i]->setPriority(iPriority - 1);
660                    }
661                }
662            }
663        }
664        int iRow;
665        for (iRow = 0; iRow < numberRows; iRow++) {
666            if (rowLower[iRow] > -1.0e20 &&
667                    fabs(rowLower[iRow] - rhs[iRow] - floor(rowLower[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) {
668                continuousMultiplier = 0.0;
669                break;
670            }
671            if (rowUpper[iRow] < 1.0e20 &&
672                    fabs(rowUpper[iRow] - rhs[iRow] - floor(rowUpper[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) {
673                continuousMultiplier = 0.0;
674                break;
675            }
676            // set rhs to limiting value
677            if (rowLower[iRow] != rowUpper[iRow]) {
678                if (rowLower[iRow] > -1.0e20) {
679                    if (rowUpper[iRow] < 1.0e20) {
680                        // no good
681                        continuousMultiplier = 0.0;
682                        break;
683                    } else {
684                        rhs[iRow] = rowLower[iRow] - rhs[iRow];
685                        if (problemType < 0)
686                            problemType = 3; // set cover
687                        else if (problemType != 3)
688                            problemType = 4;
689                    }
690                } else {
691                    rhs[iRow] = rowUpper[iRow] - rhs[iRow];
692                    if (problemType < 0)
693                        problemType = 1; // set partitioning <=
694                    else if (problemType != 1)
695                        problemType = 4;
696                }
697            } else {
698                rhs[iRow] = rowUpper[iRow] - rhs[iRow];
699                if (problemType < 0)
700                    problemType = 3; // set partitioning ==
701                else if (problemType != 2)
702                    problemType = 2;
703            }
704            if (fabs(rhs[iRow] - 1.0) > 1.0e-12)
705                problemType = 4;
706        }
707        if (continuousMultiplier) {
708            // 1 network, 2 cover, 4 negative cover
709            int possible = 7;
710            bool unitRhs = true;
711            // See which rows could be set cover
712            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
713                if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
714                    CoinBigIndex start = columnStart[iColumn];
715                    CoinBigIndex end = start + columnLength[iColumn];
716                    for (CoinBigIndex j = start; j < end; j++) {
717                        double value = element[j];
718                        if (value == 1.0) {
719                        } else if (value == -1.0) {
720                            rhs[row[j]] = -0.5;
721                            allPlusOnes = false;
722                        } else {
723                            rhs[row[j]] = -COIN_DBL_MAX;
724                            allOnes = false;
725                        }
726                    }
727                }
728            }
729            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
730                if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
731                    if (!isInteger(iColumn)) {
732                        CoinBigIndex start = columnStart[iColumn];
733                        CoinBigIndex end = start + columnLength[iColumn];
734                        double rhsValue = 0.0;
735                        // 1 all ones, -1 all -1s, 2 all +- 1, 3 no good
736                        int type = 0;
737                        for (CoinBigIndex j = start; j < end; j++) {
738                            double value = element[j];
739                            if (fabs(value) != 1.0) {
740                                type = 3;
741                                break;
742                            } else if (value == 1.0) {
743                                if (!type)
744                                    type = 1;
745                                else if (type != 1)
746                                    type = 2;
747                            } else {
748                                if (!type)
749                                    type = -1;
750                                else if (type != -1)
751                                    type = 2;
752                            }
753                            int iRow = row[j];
754                            if (rhs[iRow] == -COIN_DBL_MAX) {
755                                type = 3;
756                                break;
757                            } else if (rhs[iRow] == -0.5) {
758                                // different values
759                                unitRhs = false;
760                            } else if (rhsValue) {
761                                if (rhsValue != rhs[iRow])
762                                    unitRhs = false;
763                            } else {
764                                rhsValue = rhs[iRow];
765                            }
766                        }
767                        // if no elements OK
768                        if (type == 3) {
769                            // no good
770                            possible = 0;
771                            break;
772                        } else if (type == 2) {
773                            if (end - start > 2) {
774                                // no good
775                                possible = 0;
776                                break;
777                            } else {
778                                // only network
779                                possible &= 1;
780                                if (!possible)
781                                    break;
782                            }
783                        } else if (type == 1) {
784                            // only cover
785                            possible &= 2;
786                            if (!possible)
787                                break;
788                        } else if (type == -1) {
789                            // only negative cover
790                            possible &= 4;
791                            if (!possible)
792                                break;
793                        }
794                    }
795                }
796            }
797            if ((possible == 2 || possible == 4) && !unitRhs) {
798#if COIN_DEVELOP>1
799                printf("XXXXXX Continuous all +1 but different rhs\n");
800#endif
801                possible = 0;
802            }
803            // may be all integer
804            if (possible != 7) {
805                if (!possible)
806                    continuousMultiplier = 0.0;
807                else if (possible == 1)
808                    continuousMultiplier = 1.0;
809                else
810                    continuousMultiplier = 0.0; // 0.5 was incorrect;
811#if COIN_DEVELOP>1
812                if (continuousMultiplier)
813                    printf("XXXXXX multiplier of %g\n", continuousMultiplier);
814#endif
815                if (continuousMultiplier == 0.5) {
816                    coeffMultiplier = new double [numberColumns];
817                    bool allOne = true;
818                    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
819                        coeffMultiplier[iColumn] = 1.0;
820                        if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
821                            if (!isInteger(iColumn)) {
822                                CoinBigIndex start = columnStart[iColumn];
823                                int iRow = row[start];
824                                double value = rhs[iRow];
825                                assert (value >= 0.0);
826                                if (value != 0.0 && value != 1.0)
827                                    allOne = false;
828                                coeffMultiplier[iColumn] = 0.5 * value;
829                            }
830                        }
831                    }
832                    if (allOne) {
833                        // back to old way
834                        delete [] coeffMultiplier;
835                        coeffMultiplier = NULL;
836                    }
837                }
838            } else {
839                // all integer
840                problemType_ = problemType;
841#if COIN_DEVELOP>1
842                printf("Problem type is %d\n", problemType_);
843#endif
844            }
845        }
846
847        // But try again
848        if (continuousMultiplier < 1.0) {
849            memset(rhs, 0, numberRows*sizeof(double));
850            int * count = new int [numberRows];
851            memset(count, 0, numberRows*sizeof(int));
852            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
853                CoinBigIndex start = columnStart[iColumn];
854                CoinBigIndex end = start + columnLength[iColumn];
855                if (upper[iColumn] == lower[iColumn]) {
856                    for (CoinBigIndex j = start; j < end; j++) {
857                        int iRow = row[j];
858                        rhs[iRow] += lower[iColumn] * element[j];
859                    }
860                } else if (solver_->isInteger(iColumn)) {
861                    for (CoinBigIndex j = start; j < end; j++) {
862                        int iRow = row[j];
863                        if (fabs(element[j] - floor(element[j] + 0.5)) > 1.0e-10)
864                            rhs[iRow]  = COIN_DBL_MAX;
865                    }
866                } else {
867                    for (CoinBigIndex j = start; j < end; j++) {
868                        int iRow = row[j];
869                        count[iRow]++;
870                        if (fabs(element[j]) != 1.0)
871                            rhs[iRow]  = COIN_DBL_MAX;
872                    }
873                }
874            }
875            // now look at continuous
876            bool allGood = true;
877            double direction = solver_->getObjSense() ;
878            int numberObj = 0;
879            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
880                if (upper[iColumn] > lower[iColumn]) {
881                    double objValue = objective[iColumn] * direction;
882                    if (objValue && !solver_->isInteger(iColumn)) {
883                        numberObj++;
884                        CoinBigIndex start = columnStart[iColumn];
885                        CoinBigIndex end = start + columnLength[iColumn];
886                        if (objValue > 0.0) {
887                            // wants to be as low as possible
888                            if (lower[iColumn] < -1.0e10 || fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
889                                allGood = false;
890                                break;
891                            } else if (upper[iColumn] < 1.0e10 && fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
892                                allGood = false;
893                                break;
894                            }
895                            bool singletonRow = true;
896                            bool equality = false;
897                            for (CoinBigIndex j = start; j < end; j++) {
898                                int iRow = row[j];
899                                if (count[iRow] > 1)
900                                    singletonRow = false;
901                                else if (rowLower[iRow] == rowUpper[iRow])
902                                    equality = true;
903                                double rhsValue = rhs[iRow];
904                                double lowerValue = rowLower[iRow];
905                                double upperValue = rowUpper[iRow];
906                                if (rhsValue < 1.0e20) {
907                                    if (lowerValue > -1.0e20)
908                                        lowerValue -= rhsValue;
909                                    if (upperValue < 1.0e20)
910                                        upperValue -= rhsValue;
911                                }
912                                if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
913                                        || fabs(element[j]) != 1.0) {
914                                    // no good
915                                    allGood = false;
916                                    break;
917                                }
918                                if (element[j] > 0.0) {
919                                    if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
920                                        // no good
921                                        allGood = false;
922                                        break;
923                                    }
924                                } else {
925                                    if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
926                                        // no good
927                                        allGood = false;
928                                        break;
929                                    }
930                                }
931                            }
932                            if (!singletonRow && end > start + 1 && !equality)
933                                allGood = false;
934                            if (!allGood)
935                                break;
936                        } else {
937                            // wants to be as high as possible
938                            if (upper[iColumn] > 1.0e10 || fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
939                                allGood = false;
940                                break;
941                            } else if (lower[iColumn] > -1.0e10 && fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
942                                allGood = false;
943                                break;
944                            }
945                            bool singletonRow = true;
946                            bool equality = false;
947                            for (CoinBigIndex j = start; j < end; j++) {
948                                int iRow = row[j];
949                                if (count[iRow] > 1)
950                                    singletonRow = false;
951                                else if (rowLower[iRow] == rowUpper[iRow])
952                                    equality = true;
953                                double rhsValue = rhs[iRow];
954                                double lowerValue = rowLower[iRow];
955                                double upperValue = rowUpper[iRow];
956                                if (rhsValue < 1.0e20) {
957                                    if (lowerValue > -1.0e20)
958                                        lowerValue -= rhsValue;
959                                    if (upperValue < 1.0e20)
960                                        upperValue -= rhsValue;
961                                }
962                                if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
963                                        || fabs(element[j]) != 1.0) {
964                                    // no good
965                                    allGood = false;
966                                    break;
967                                }
968                                if (element[j] < 0.0) {
969                                    if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
970                                        // no good
971                                        allGood = false;
972                                        break;
973                                    }
974                                } else {
975                                    if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
976                                        // no good
977                                        allGood = false;
978                                        break;
979                                    }
980                                }
981                            }
982                            if (!singletonRow && end > start + 1 && !equality)
983                                allGood = false;
984                            if (!allGood)
985                                break;
986                        }
987                    }
988                }
989            }
990            delete [] count;
991            if (allGood) {
992#if COIN_DEVELOP>1
993                if (numberObj)
994                    printf("YYYY analysis says all continuous with costs will be integer\n");
995#endif
996                continuousMultiplier = 1.0;
997            }
998        }
999        delete [] rhs;
1000    }
1001    /*
1002      Take a first scan to see if there are unfixed continuous variables in the
1003      objective.  If so, the minimum objective change could be arbitrarily small.
1004      Also pick off the maximum coefficient of an unfixed integer variable.
1005
1006      If the objective is found to contain only integer variables, set the
1007      fathoming discipline to strict.
1008    */
1009    double maximumCost = 0.0 ;
1010    //double trueIncrement=0.0;
1011    int iColumn ;
1012    int numberColumns = getNumCols() ;
1013    double scaleFactor = 1.0; // due to rhs etc
1014    if ((specialOptions_&65536) == 0) {
1015        /* be on safe side (later look carefully as may be able to
1016           to get 0.5 say if bounds are multiples of 0.5 */
1017        for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
1018            if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
1019                double value;
1020                value = fabs(lower[iColumn]);
1021                if (floor(value + 0.5) != value) {
1022                    scaleFactor = CoinMin(scaleFactor, 0.5);
1023                    if (floor(2.0*value + 0.5) != 2.0*value) {
1024                        scaleFactor = CoinMin(scaleFactor, 0.25);
1025                        if (floor(4.0*value + 0.5) != 4.0*value) {
1026                            scaleFactor = 0.0;
1027                        }
1028                    }
1029                }
1030                value = fabs(upper[iColumn]);
1031                if (floor(value + 0.5) != value) {
1032                    scaleFactor = CoinMin(scaleFactor, 0.5);
1033                    if (floor(2.0*value + 0.5) != 2.0*value) {
1034                        scaleFactor = CoinMin(scaleFactor, 0.25);
1035                        if (floor(4.0*value + 0.5) != 4.0*value) {
1036                            scaleFactor = 0.0;
1037                        }
1038                    }
1039                }
1040            }
1041        }
1042    }
1043    bool possibleMultiple = continuousMultiplier != 0.0 && scaleFactor != 0.0 ;
1044    if (possibleMultiple) {
1045        for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
1046            if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
1047                maximumCost = CoinMax(maximumCost, fabs(objective[iColumn])) ;
1048            }
1049        }
1050    }
1051    setIntParam(CbcModel::CbcFathomDiscipline, possibleMultiple) ;
1052    /*
1053      If a nontrivial increment is possible, try and figure it out. We're looking
1054      for gcd(c<j>) for all c<j> that are coefficients of unfixed integer
1055      variables. Since the c<j> might not be integers, try and inflate them
1056      sufficiently that they look like integers (and we'll deflate the gcd
1057      later).
1058
1059      2520.0 is used as it is a nice multiple of 2,3,5,7
1060    */
1061    if (possibleMultiple && maximumCost) {
1062        int increment = 0 ;
1063        double multiplier = 2520.0 ;
1064        while (10.0*multiplier*maximumCost < 1.0e8)
1065            multiplier *= 10.0 ;
1066        int bigIntegers = 0; // Count of large costs which are integer
1067        for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
1068            if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
1069                double objValue = fabs(objective[iColumn]);
1070                if (!isInteger(iColumn)) {
1071                    if (!coeffMultiplier)
1072                        objValue *= continuousMultiplier;
1073                    else
1074                        objValue *= coeffMultiplier[iColumn];
1075                }
1076                if (objValue) {
1077                    double value = objValue * multiplier ;
1078                    if (value < 2.1e9) {
1079                        int nearest = static_cast<int> (floor(value + 0.5)) ;
1080                        if (fabs(value - floor(value + 0.5)) > 1.0e-8) {
1081                            increment = 0 ;
1082                            break ;
1083                        } else if (!increment) {
1084                            increment = nearest ;
1085                        } else {
1086                            increment = gcd(increment, nearest) ;
1087                        }
1088                    } else {
1089                        // large value - may still be multiple of 1.0
1090                        if (fabs(objValue - floor(objValue + 0.5)) > 1.0e-8) {
1091                            increment = 0;
1092                            break;
1093                        } else {
1094                            bigIntegers++;
1095                        }
1096                    }
1097                }
1098            }
1099        }
1100        delete [] coeffMultiplier;
1101        /*
1102          If the increment beats the current value for objective change, install it.
1103        */
1104        if (increment) {
1105            double value = increment ;
1106            double cutoff = getDblParam(CbcModel::CbcCutoffIncrement) ;
1107            if (bigIntegers) {
1108                // allow for 1.0
1109                increment = gcd(increment, static_cast<int> (multiplier));
1110                value = increment;
1111            }
1112            value /= multiplier ;
1113            value *= scaleFactor;
1114            //trueIncrement=CoinMax(cutoff,value);;
1115            if (value*0.999 > cutoff) {
1116                messageHandler()->message(CBC_INTEGERINCREMENT,
1117                                          messages())
1118                << value << CoinMessageEol ;
1119                setDblParam(CbcModel::CbcCutoffIncrement, value*0.999) ;
1120            }
1121        }
1122    }
1123
1124    return ;
1125}
1126
1127
1128/**
1129  \todo
1130  Normally, it looks like we enter here from command dispatch in the main
1131  routine, after calling the solver for an initial solution
1132  (CbcModel::initialSolve, which simply calls the solver's initialSolve
1133  routine.) The first thing we do is call resolve. Presumably there are
1134  circumstances where this is nontrivial? There's also a call from
1135  CbcModel::originalModel (tied up with integer presolve), which should be
1136  checked.
1137
1138*/
1139
1140/*
1141  The overall flow can be divided into three stages:
1142    * Prep: Check that the lp relaxation remains feasible at the root. If so,
1143      do all the setup for B&C.
1144    * Process the root node: Generate cuts, apply heuristics, and in general do
1145      the best we can to resolve the problem without B&C.
1146    * Do B&C search until we hit a limit or exhaust the search tree.
1147
1148  Keep in mind that in general there is no node in the search tree that
1149  corresponds to the active subproblem. The active subproblem is represented
1150  by the current state of the model,  of the solver, and of the constraint
1151  system held by the solver.
1152*/
1153#ifdef COIN_HAS_CPX
1154#include "OsiCpxSolverInterface.hpp"
1155#include "cplex.h"
1156#endif
1157void CbcModel::branchAndBound(int doStatistics)
1158
1159{
1160    /*
1161      Capture a time stamp before we start.
1162    */
1163    dblParam_[CbcStartSeconds] = CoinCpuTime();
1164    dblParam_[CbcSmallestChange] = COIN_DBL_MAX;
1165    dblParam_[CbcSumChange] = 0.0;
1166    dblParam_[CbcLargestChange] = 0.0;
1167    intParam_[CbcNumberBranches] = 0;
1168    strongInfo_[0] = 0;
1169    strongInfo_[1] = 0;
1170    strongInfo_[2] = 0;
1171    strongInfo_[3] = 0;
1172    strongInfo_[4] = 0;
1173    strongInfo_[5] = 0;
1174    strongInfo_[6] = 0;
1175    numberStrongIterations_ = 0;
1176    currentNode_ = NULL;
1177    // See if should do cuts old way
1178    if (parallelMode() < 0) {
1179        specialOptions_ |= 4096 + 8192;
1180    } else if (parallelMode() > 0) {
1181        specialOptions_ |= 4096;
1182    }
1183    int saveMoreSpecialOptions = moreSpecialOptions_;
1184    if (dynamic_cast<CbcTreeLocal *> (tree_))
1185        specialOptions_ |= 4096 + 8192;
1186#ifdef COIN_HAS_CLP
1187    {
1188        OsiClpSolverInterface * clpSolver
1189        = dynamic_cast<OsiClpSolverInterface *> (solver_);
1190        if (clpSolver) {
1191            // pass in disaster handler
1192            CbcDisasterHandler handler(this);
1193            clpSolver->passInDisasterHandler(&handler);
1194            // Initialise solvers seed
1195            clpSolver->getModelPtr()->setRandomSeed(1234567);
1196#if 0
1197            // reduce factorization frequency
1198            int frequency = clpSolver->getModelPtr()->factorizationFrequency();
1199            clpSolver->getModelPtr()->setFactorizationFrequency(CoinMin(frequency, 120));
1200#endif
1201        }
1202    }
1203#endif
1204    // original solver (only set if pre-processing)
1205    OsiSolverInterface * originalSolver = NULL;
1206    int numberOriginalObjects = numberObjects_;
1207    OsiObject ** originalObject = NULL;
1208    // Save whether there were any objects
1209    bool noObjects = (numberObjects_ == 0);
1210    // Set up strategies
1211    if (strategy_) {
1212        // May do preprocessing
1213        originalSolver = solver_;
1214        strategy_->setupOther(*this);
1215        if (strategy_->preProcessState()) {
1216            // pre-processing done
1217            if (strategy_->preProcessState() < 0) {
1218                // infeasible
1219                handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ;
1220                status_ = 0 ;
1221                secondaryStatus_ = 1;
1222                originalContinuousObjective_ = COIN_DBL_MAX;
1223                return ;
1224            } else if (numberObjects_ && object_) {
1225                numberOriginalObjects = numberObjects_;
1226                // redo sequence
1227                numberIntegers_ = 0;
1228                int numberColumns = getNumCols();
1229                int nOrig = originalSolver->getNumCols();
1230                CglPreProcess * process = strategy_->process();
1231                assert (process);
1232                const int * originalColumns = process->originalColumns();
1233                // allow for cliques etc
1234                nOrig = CoinMax(nOrig, originalColumns[numberColumns-1] + 1);
1235                // try and redo debugger
1236                OsiRowCutDebugger * debugger = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
1237                if (debugger)
1238                    debugger->redoSolution(numberColumns, originalColumns);
1239                if (bestSolution_) {
1240                    // need to redo - in case no better found in BAB
1241                    // just get integer part right
1242                    for (int i = 0; i < numberColumns; i++) {
1243                        int jColumn = originalColumns[i];
1244                        bestSolution_[i] = bestSolution_[jColumn];
1245                    }
1246                }
1247                originalObject = object_;
1248                // object number or -1
1249                int * temp = new int[nOrig];
1250                int iColumn;
1251                for (iColumn = 0; iColumn < nOrig; iColumn++)
1252                    temp[iColumn] = -1;
1253                int iObject;
1254                int nNonInt = 0;
1255                for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
1256                    iColumn = originalObject[iObject]->columnNumber();
1257                    if (iColumn < 0) {
1258                        nNonInt++;
1259                    } else {
1260                        temp[iColumn] = iObject;
1261                    }
1262                }
1263                int numberNewIntegers = 0;
1264                int numberOldIntegers = 0;
1265                int numberOldOther = 0;
1266                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1267                    int jColumn = originalColumns[iColumn];
1268                    if (temp[jColumn] >= 0) {
1269                        int iObject = temp[jColumn];
1270                        CbcSimpleInteger * obj =
1271                            dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
1272                        if (obj)
1273                            numberOldIntegers++;
1274                        else
1275                            numberOldOther++;
1276                    } else if (isInteger(iColumn)) {
1277                        numberNewIntegers++;
1278                    }
1279                }
1280                /*
1281                  Allocate an array to hold the indices of the integer variables.
1282                  Make a large enough array for all objects
1283                */
1284                numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt;
1285                object_ = new OsiObject * [numberObjects_];
1286                delete [] integerVariable_;
1287                integerVariable_ = new int [numberNewIntegers+numberOldIntegers];
1288                /*
1289                  Walk the variables again, filling in the indices and creating objects for
1290                  the integer variables. Initially, the objects hold the index and upper &
1291                  lower bounds.
1292                */
1293                numberIntegers_ = 0;
1294                int n = originalColumns[numberColumns-1] + 1;
1295                int * backward = new int[n];
1296                int i;
1297                for ( i = 0; i < n; i++)
1298                    backward[i] = -1;
1299                for (i = 0; i < numberColumns; i++)
1300                    backward[originalColumns[i]] = i;
1301                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1302                    int jColumn = originalColumns[iColumn];
1303                    if (temp[jColumn] >= 0) {
1304                        int iObject = temp[jColumn];
1305                        CbcSimpleInteger * obj =
1306                            dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
1307                        if (obj) {
1308                            object_[numberIntegers_] = originalObject[iObject]->clone();
1309                            // redo ids etc
1310                            //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns);
1311                            object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward);
1312                            integerVariable_[numberIntegers_++] = iColumn;
1313                        }
1314                    } else if (isInteger(iColumn)) {
1315                        object_[numberIntegers_] =
1316                            new CbcSimpleInteger(this, iColumn);
1317                        integerVariable_[numberIntegers_++] = iColumn;
1318                    }
1319                }
1320                delete [] backward;
1321                numberObjects_ = numberIntegers_;
1322                // Now append other column stuff
1323                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1324                    int jColumn = originalColumns[iColumn];
1325                    if (temp[jColumn] >= 0) {
1326                        int iObject = temp[jColumn];
1327                        CbcSimpleInteger * obj =
1328                            dynamic_cast <CbcSimpleInteger *>(originalObject[iObject]) ;
1329                        if (!obj) {
1330                            object_[numberObjects_] = originalObject[iObject]->clone();
1331                            // redo ids etc
1332                            CbcObject * obj =
1333                                dynamic_cast <CbcObject *>(object_[numberObjects_]) ;
1334                            assert (obj);
1335                            obj->redoSequenceEtc(this, numberColumns, originalColumns);
1336                            numberObjects_++;
1337                        }
1338                    }
1339                }
1340                // now append non column stuff
1341                for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
1342                    iColumn = originalObject[iObject]->columnNumber();
1343                    if (iColumn < 0) {
1344                        // already has column numbers changed
1345                        object_[numberObjects_] = originalObject[iObject]->clone();
1346#if 0
1347                        // redo ids etc
1348                        CbcObject * obj =
1349                            dynamic_cast <CbcObject *>(object_[numberObjects_]) ;
1350                        assert (obj);
1351                        obj->redoSequenceEtc(this, numberColumns, originalColumns);
1352#endif
1353                        numberObjects_++;
1354                    }
1355                }
1356                delete [] temp;
1357                if (!numberObjects_)
1358                    handler_->message(CBC_NOINT, messages_) << CoinMessageEol ;
1359            } else {
1360                int numberColumns = getNumCols();
1361                CglPreProcess * process = strategy_->process();
1362                assert (process);
1363                const int * originalColumns = process->originalColumns();
1364                // try and redo debugger
1365                OsiRowCutDebugger * debugger = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
1366                if (debugger)
1367                    debugger->redoSolution(numberColumns, originalColumns);
1368            }
1369        } else {
1370            //no preprocessing
1371            originalSolver = NULL;
1372        }
1373        strategy_->setupCutGenerators(*this);
1374        strategy_->setupHeuristics(*this);
1375        // Set strategy print level to models
1376        strategy_->setupPrinting(*this, handler_->logLevel());
1377    }
1378    eventHappened_ = false;
1379    CbcEventHandler *eventHandler = getEventHandler() ;
1380    if (eventHandler)
1381        eventHandler->setModel(this);
1382#define CLIQUE_ANALYSIS
1383#ifdef CLIQUE_ANALYSIS
1384    // set up for probing
1385    if (!parentModel_)
1386        probingInfo_ = new CglTreeProbingInfo(solver_);
1387    else
1388        probingInfo_ = NULL;
1389#else
1390    probingInfo_ = NULL;
1391#endif
1392
1393    // Try for dominated columns
1394    if ((specialOptions_&64) != 0) {
1395        CglDuplicateRow dupcuts(solver_);
1396        dupcuts.setMode(2);
1397        CglStored * storedCuts = dupcuts.outDuplicates(solver_);
1398        if (storedCuts) {
1399            printf("adding dup cuts\n");
1400            addCutGenerator(storedCuts, 1, "StoredCuts from dominated",
1401                            true, false, false, -200);
1402        }
1403    }
1404    if (!nodeCompare_)
1405        nodeCompare_ = new CbcCompareDefault();;
1406    // See if hot start wanted
1407    CbcCompareBase * saveCompare = NULL;
1408    if (hotstartSolution_) {
1409        if (strategy_ && strategy_->preProcessState() > 0) {
1410            CglPreProcess * process = strategy_->process();
1411            assert (process);
1412            int n = solver_->getNumCols();
1413            const int * originalColumns = process->originalColumns();
1414            // columns should be in order ... but
1415            double * tempS = new double[n];
1416            for (int i = 0; i < n; i++) {
1417                int iColumn = originalColumns[i];
1418                tempS[i] = hotstartSolution_[iColumn];
1419            }
1420            delete [] hotstartSolution_;
1421            hotstartSolution_ = tempS;
1422            if (hotstartPriorities_) {
1423                int * tempP = new int [n];
1424                for (int i = 0; i < n; i++) {
1425                    int iColumn = originalColumns[i];
1426                    tempP[i] = hotstartPriorities_[iColumn];
1427                }
1428                delete [] hotstartPriorities_;
1429                hotstartPriorities_ = tempP;
1430            }
1431        }
1432        saveCompare = nodeCompare_;
1433        // depth first
1434        nodeCompare_ = new CbcCompareDepth();
1435    }
1436    if (!problemFeasibility_)
1437        problemFeasibility_ = new CbcFeasibilityBase();
1438# ifdef CBC_DEBUG
1439    std::string problemName ;
1440    solver_->getStrParam(OsiProbName, problemName) ;
1441    printf("Problem name - %s\n", problemName.c_str()) ;
1442    solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0) ;
1443# endif
1444    /*
1445      Assume we're done, and see if we're proven wrong.
1446    */
1447    status_ = 0 ;
1448    secondaryStatus_ = 0;
1449    phase_ = 0;
1450    /*
1451      Scan the variables, noting the integer variables. Create an
1452      CbcSimpleInteger object for each integer variable.
1453    */
1454    findIntegers(false) ;
1455    // Say not dynamic pseudo costs
1456    ownership_ &= ~0x40000000;
1457    // If dynamic pseudo costs then do
1458    if (numberBeforeTrust_)
1459        convertToDynamic();
1460    // Set up char array to say if integer
1461    delete [] integerInfo_;
1462    {
1463        int n = solver_->getNumCols();
1464        integerInfo_ = new char [n];
1465        for (int i = 0; i < n; i++) {
1466            if (solver_->isInteger(i))
1467                integerInfo_[i] = 1;
1468            else
1469                integerInfo_[i] = 0;
1470        }
1471    }
1472    if (preferredWay_) {
1473        // set all unset ones
1474        for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
1475            CbcObject * obj =
1476                dynamic_cast <CbcObject *>(object_[iObject]) ;
1477            if (obj && !obj->preferredWay())
1478                obj->setPreferredWay(preferredWay_);
1479        }
1480    }
1481    /*
1482      Ensure that objects on the lists of OsiObjects, heuristics, and cut
1483      generators attached to this model all refer to this model.
1484    */
1485    synchronizeModel() ;
1486    if (!solverCharacteristics_) {
1487        OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
1488        if (solverCharacteristics) {
1489            solverCharacteristics_ = solverCharacteristics;
1490        } else {
1491            // replace in solver
1492            OsiBabSolver defaultC;
1493            solver_->setAuxiliaryInfo(&defaultC);
1494            solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
1495        }
1496    }
1497
1498    solverCharacteristics_->setSolver(solver_);
1499    // Set so we can tell we are in initial phase in resolve
1500    continuousObjective_ = -COIN_DBL_MAX ;
1501    /*
1502      Solve the relaxation.
1503
1504      Apparently there are circumstances where this will be non-trivial --- i.e.,
1505      we've done something since initialSolve that's trashed the solution to the
1506      continuous relaxation.
1507    */
1508    /* Tell solver we are in Branch and Cut
1509       Could use last parameter for subtle differences */
1510    solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
1511#ifdef COIN_HAS_CLP
1512    {
1513        OsiClpSolverInterface * clpSolver
1514        = dynamic_cast<OsiClpSolverInterface *> (solver_);
1515        if (clpSolver) {
1516            ClpSimplex * clpSimplex = clpSolver->getModelPtr();
1517            if ((specialOptions_&32) == 0) {
1518                // take off names
1519                clpSimplex->dropNames();
1520            }
1521            // no crunch if mostly continuous
1522            if ((clpSolver->specialOptions()&(1 + 8)) != (1 + 8)) {
1523                int numberColumns = solver_->getNumCols();
1524                if (numberColumns > 1000 && numberIntegers_*4 < numberColumns)
1525                    clpSolver->setSpecialOptions(clpSolver->specialOptions()&(~1));
1526            }
1527            //#define NO_CRUNCH
1528#ifdef NO_CRUNCH
1529            printf("TEMP switching off crunch\n");
1530            int iOpt = clpSolver->specialOptions();
1531            iOpt &= ~1;
1532            iOpt |= 65536;
1533            clpSolver->setSpecialOptions(iOpt);
1534#endif
1535        }
1536    }
1537#endif
1538    bool feasible;
1539    // If NLP then we assume already solved outside branchAndbound
1540    if (!solverCharacteristics_->solverType() || solverCharacteristics_->solverType() == 4) {
1541        feasible = resolve(NULL, 0) != 0 ;
1542    } else {
1543        // pick up given status
1544        feasible = (solver_->isProvenOptimal() &&
1545                    !solver_->isDualObjectiveLimitReached()) ;
1546    }
1547    if (problemFeasibility_->feasible(this, 0) < 0) {
1548        feasible = false; // pretend infeasible
1549    }
1550    numberSavedSolutions_ = 0;
1551    int saveNumberStrong = numberStrong_;
1552    int saveNumberBeforeTrust = numberBeforeTrust_;
1553    /*
1554      If the linear relaxation of the root is infeasible, bail out now. Otherwise,
1555      continue with processing the root node.
1556    */
1557    if (!feasible) {
1558        status_ = 0 ;
1559        if (!solver_->isProvenDualInfeasible()) {
1560            handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ;
1561            secondaryStatus_ = 1;
1562        } else {
1563            handler_->message(CBC_UNBOUNDED, messages_) << CoinMessageEol ;
1564            secondaryStatus_ = 7;
1565        }
1566        originalContinuousObjective_ = COIN_DBL_MAX;
1567        solverCharacteristics_ = NULL;
1568        return ;
1569    } else if (!numberObjects_) {
1570        // nothing to do
1571        solverCharacteristics_ = NULL;
1572        bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
1573        int numberColumns = solver_->getNumCols();
1574        delete [] bestSolution_;
1575        bestSolution_ = new double[numberColumns];
1576        CoinCopyN(solver_->getColSolution(), numberColumns, bestSolution_);
1577        return ;
1578    }
1579    // Convert to Osi if wanted
1580    bool useOsiBranching = false;
1581    //OsiBranchingInformation * persistentInfo = NULL;
1582    if (branchingMethod_ && branchingMethod_->chooseMethod()) {
1583        useOsiBranching = true;
1584        //persistentInfo = new OsiBranchingInformation(solver_);
1585        if (numberOriginalObjects) {
1586            for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
1587                CbcObject * obj =
1588                    dynamic_cast <CbcObject *>(object_[iObject]) ;
1589                if (obj) {
1590                    CbcSimpleInteger * obj2 =
1591                        dynamic_cast <CbcSimpleInteger *>(obj) ;
1592                    if (obj2) {
1593                        // back to Osi land
1594                        object_[iObject] = obj2->osiObject();
1595                        delete obj;
1596                    } else {
1597                        OsiSimpleInteger * obj3 =
1598                            dynamic_cast <OsiSimpleInteger *>(obj) ;
1599                        if (!obj3) {
1600                            OsiSOS * obj4 =
1601                                dynamic_cast <OsiSOS *>(obj) ;
1602                            if (!obj4) {
1603                                CbcSOS * obj5 =
1604                                    dynamic_cast <CbcSOS *>(obj) ;
1605                                if (obj5) {
1606                                    // back to Osi land
1607                                    object_[iObject] = obj5->osiObject(solver_);
1608                                } else {
1609                                    printf("Code up CbcObject type in Osi land\n");
1610                                    abort();
1611                                }
1612                            }
1613                        }
1614                    }
1615                }
1616            }
1617            // and add to solver
1618            //if (!solver_->numberObjects()) {
1619            solver_->addObjects(numberObjects_, object_);
1620            //} else {
1621            //if (solver_->numberObjects()!=numberOriginalObjects) {
1622            //printf("should have trapped that solver has objects before\n");
1623            //abort();
1624            //}
1625            //}
1626        } else {
1627            // do from solver
1628            deleteObjects(false);
1629            solver_->findIntegersAndSOS(false);
1630            numberObjects_ = solver_->numberObjects();
1631            object_ = solver_->objects();
1632            ownObjects_ = false;
1633        }
1634        branchingMethod_->chooseMethod()->setSolver(solver_);
1635    }
1636    // take off heuristics if have to
1637    {
1638        int numberOdd = 0;
1639        int numberSOS = 0;
1640        for (int i = 0; i < numberObjects_; i++) {
1641            if (!object_[i]->canDoHeuristics())
1642                numberOdd++;
1643            CbcSOS * obj =
1644                dynamic_cast <CbcSOS *>(object_[i]) ;
1645            if (obj)
1646                numberSOS++;
1647        }
1648        if (numberOdd) {
1649            if (numberHeuristics_) {
1650                int k = 0;
1651                for (int i = 0; i < numberHeuristics_; i++) {
1652                    if (!heuristic_[i]->canDealWithOdd())
1653                        delete heuristic_[i];
1654                    else
1655                        heuristic_[k++] = heuristic_[i];
1656                }
1657                if (!k) {
1658                    delete [] heuristic_;
1659                    heuristic_ = NULL;
1660                }
1661                numberHeuristics_ = k;
1662                handler_->message(CBC_HEURISTICS_OFF, messages_) << numberOdd << CoinMessageEol ;
1663            }
1664        } else if (numberSOS) {
1665            specialOptions_ |= 128; // say can do SOS in dynamic mode
1666            // switch off fast nodes for now
1667            fastNodeDepth_ = -1;
1668        }
1669        if (numberThreads_ > 0) {
1670            // switch off fast nodes for now
1671            fastNodeDepth_ = -1;
1672        }
1673    }
1674    // Save objective (just so user can access it)
1675    originalContinuousObjective_ = solver_->getObjValue();
1676    bestPossibleObjective_ = originalContinuousObjective_;
1677    sumChangeObjective1_ = 0.0;
1678    sumChangeObjective2_ = 0.0;
1679    /*
1680      OsiRowCutDebugger knows an optimal answer for a subset of MIP problems.
1681      Assuming it recognises the problem, when called upon it will check a cut to
1682      see if it cuts off the optimal answer.
1683    */
1684    // If debugger exists set specialOptions_ bit
1685    if (solver_->getRowCutDebuggerAlways()) {
1686        specialOptions_ |= 1;
1687    }
1688
1689# ifdef CBC_DEBUG
1690    if ((specialOptions_&1) == 0)
1691        solver_->activateRowCutDebugger(problemName.c_str()) ;
1692    if (solver_->getRowCutDebuggerAlways())
1693        specialOptions_ |= 1;
1694# endif
1695
1696    /*
1697      Begin setup to process a feasible root node.
1698    */
1699    bestObjective_ = CoinMin(bestObjective_, 1.0e50) ;
1700    if (!bestSolution_) {
1701        numberSolutions_ = 0 ;
1702        numberHeuristicSolutions_ = 0 ;
1703    }
1704    stateOfSearch_ = 0;
1705    // Everything is minimization
1706    {
1707        // needed to sync cutoffs
1708        double value ;
1709        solver_->getDblParam(OsiDualObjectiveLimit, value) ;
1710        dblParam_[CbcCurrentCutoff] = value * solver_->getObjSense();
1711    }
1712    double cutoff = getCutoff() ;
1713    double direction = solver_->getObjSense() ;
1714    dblParam_[CbcOptimizationDirection] = direction;
1715    if (cutoff < 1.0e20 && direction < 0.0)
1716        messageHandler()->message(CBC_CUTOFF_WARNING1,
1717                                  messages())
1718        << cutoff << -cutoff << CoinMessageEol ;
1719    if (cutoff > bestObjective_)
1720        cutoff = bestObjective_ ;
1721    setCutoff(cutoff) ;
1722    /*
1723      We probably already have a current solution, but just in case ...
1724    */
1725    int numberColumns = getNumCols() ;
1726    if (!currentSolution_)
1727        currentSolution_ = new double[numberColumns] ;
1728    testSolution_ = currentSolution_;
1729    /*
1730      Create a copy of the solver, thus capturing the original (root node)
1731      constraint system (aka the continuous system).
1732    */
1733    continuousSolver_ = solver_->clone() ;
1734
1735    numberRowsAtContinuous_ = getNumRows() ;
1736    solver_->saveBaseModel();
1737    /*
1738      Check the objective to see if we can deduce a nontrivial increment. If
1739      it's better than the current value for CbcCutoffIncrement, it'll be
1740      installed.
1741    */
1742    if (solverCharacteristics_->reducedCostsAccurate())
1743        analyzeObjective() ;
1744    {
1745        // may be able to change cutoff now
1746        double cutoff = getCutoff();
1747        double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
1748        if (cutoff > bestObjective_ - increment) {
1749            cutoff = bestObjective_ - increment ;
1750            setCutoff(cutoff) ;
1751        }
1752    }
1753#ifdef COIN_HAS_CLP
1754    // Possible save of pivot method
1755    ClpDualRowPivot * savePivotMethod = NULL;
1756    {
1757        // pass tolerance and increment to solver
1758        OsiClpSolverInterface * clpSolver
1759        = dynamic_cast<OsiClpSolverInterface *> (solver_);
1760        if (clpSolver)
1761            clpSolver->setStuff(getIntegerTolerance(), getCutoffIncrement());
1762    }
1763#endif
1764    /*
1765      Set up for cut generation. addedCuts_ holds the cuts which are relevant for
1766      the active subproblem. whichGenerator will be used to record the generator
1767      that produced a given cut.
1768    */
1769    maximumWhich_ = 1000 ;
1770    delete [] whichGenerator_;
1771    whichGenerator_ = new int[maximumWhich_] ;
1772    memset(whichGenerator_, 0, maximumWhich_*sizeof(int));
1773    maximumNumberCuts_ = 0 ;
1774    currentNumberCuts_ = 0 ;
1775    delete [] addedCuts_ ;
1776    addedCuts_ = NULL ;
1777    OsiObject ** saveObjects = NULL;
1778    maximumRows_ = numberRowsAtContinuous_;
1779    currentDepth_ = 0;
1780    workingBasis_.resize(maximumRows_, numberColumns);
1781    /*
1782      Set up an empty heap and associated data structures to hold the live set
1783      (problems which require further exploration).
1784    */
1785    CbcCompareDefault * compareActual
1786    = dynamic_cast<CbcCompareDefault *> (nodeCompare_);
1787    if (compareActual) {
1788        compareActual->setBestPossible(direction*solver_->getObjValue());
1789        compareActual->setCutoff(getCutoff());
1790        if (false && !numberThreads_ && !parentModel_) {
1791            printf("CbcTreeArray ? threads ? parentArray\n");
1792            // Setup new style tree
1793            delete tree_;
1794            tree_ = new CbcTreeArray();
1795        }
1796    }
1797    tree_->setComparison(*nodeCompare_) ;
1798    /*
1799      Used to record the path from a node to the root of the search tree, so that
1800      we can then traverse from the root to the node when restoring a subproblem.
1801    */
1802    maximumDepth_ = 10 ;
1803    delete [] walkback_ ;
1804    walkback_ = new CbcNodeInfo * [maximumDepth_] ;
1805    lastDepth_ = 0;
1806    delete [] lastNodeInfo_ ;
1807    lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
1808    delete [] lastNumberCuts_ ;
1809    lastNumberCuts_ = new int [maximumDepth_] ;
1810    maximumCuts_ = 100;
1811    lastNumberCuts2_ = 0;
1812    delete [] lastCut_;
1813    lastCut_ = new const OsiRowCut * [maximumCuts_];
1814    /*
1815      Used to generate bound edits for CbcPartialNodeInfo.
1816    */
1817    double * lowerBefore = new double [numberColumns] ;
1818    double * upperBefore = new double [numberColumns] ;
1819    /*
1820
1821      Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
1822      lifting. It will iterate a generate/reoptimise loop (including reduced cost
1823      fixing) until no cuts are generated, the change in objective falls off,  or
1824      the limit on the number of rounds of cut generation is exceeded.
1825
1826      At the end of all this, any cuts will be recorded in cuts and also
1827      installed in the solver's constraint system. We'll have reoptimised, and
1828      removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
1829      adjusted accordingly).
1830
1831      Tell cut generators they can be a bit more aggressive at root node
1832
1833      TODO: Why don't we make a copy of the solution after solveWithCuts?
1834      TODO: If numberUnsatisfied == 0, don't we have a solution?
1835    */
1836    phase_ = 1;
1837    int iCutGenerator;
1838    for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
1839        CglCutGenerator * generator = generator_[iCutGenerator]->generator();
1840        generator->setAggressiveness(generator->getAggressiveness() + 100);
1841    }
1842    OsiCuts cuts ;
1843    int anyAction = -1 ;
1844    numberOldActiveCuts_ = 0 ;
1845    numberNewCuts_ = 0 ;
1846    // Array to mark solution
1847    delete [] usedInSolution_;
1848    usedInSolution_ = new int[numberColumns];
1849    CoinZeroN(usedInSolution_, numberColumns);
1850    /*
1851      For printing totals and for CbcNode (numberNodes_)
1852    */
1853    numberIterations_ = 0 ;
1854    numberSolves_ = 0 ;
1855    numberNodes_ = 0 ;
1856    numberNodes2_ = 0 ;
1857    maximumStatistics_ = 0;
1858    maximumDepthActual_ = 0;
1859    numberDJFixed_ = 0.0;
1860    // Do heuristics
1861    doHeuristicsAtRoot();
1862    if ( intParam_[CbcMaxNumNode] < 0)
1863        eventHappened_ = true; // stop as fast as possible
1864    stoppedOnGap_ = false ;
1865    // See if can stop on gap
1866    bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
1867    double testGap = CoinMax(dblParam_[CbcAllowableGap],
1868                             CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
1869                             * dblParam_[CbcAllowableFractionGap]);
1870    if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0) {
1871        if (bestPossibleObjective_ < getCutoff())
1872            stoppedOnGap_ = true ;
1873        feasible = false;
1874        //eventHappened_=true; // stop as fast as possible
1875    }
1876    statistics_ = NULL;
1877    // Do on switch
1878    if (doStatistics > 0 && doStatistics <= 100) {
1879        maximumStatistics_ = 10000;
1880        statistics_ = new CbcStatistics * [maximumStatistics_];
1881        memset(statistics_, 0, maximumStatistics_*sizeof(CbcStatistics *));
1882    }
1883    // See if we can add integers
1884    if (noObjects && numberIntegers_ < solver_->getNumCols() && (specialOptions_&65536) != 0 && !parentModel_) {
1885        int numberColumns = continuousSolver_->getNumCols();
1886        int numberRows = continuousSolver_->getNumRows();
1887        int * del = new int [CoinMax(numberColumns, numberRows)];
1888        int * original = new int [numberColumns];
1889        char * possibleRow = new char [numberRows];
1890        {
1891            const CoinPackedMatrix * rowCopy = continuousSolver_->getMatrixByRow();
1892            const int * column = rowCopy->getIndices();
1893            const int * rowLength = rowCopy->getVectorLengths();
1894            const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
1895            const double * rowLower = continuousSolver_->getRowLower();
1896            const double * rowUpper = continuousSolver_->getRowUpper();
1897            const double * element = rowCopy->getElements();
1898            for (int i = 0; i < numberRows; i++) {
1899                int nLeft = 0;
1900                bool possible = false;
1901                if (rowLower[i] < -1.0e20) {
1902                    double value = rowUpper[i];
1903                    if (fabs(value - floor(value + 0.5)) < 1.0e-8)
1904                        possible = true;
1905                } else if (rowUpper[i] > 1.0e20) {
1906                    double value = rowLower[i];
1907                    if (fabs(value - floor(value + 0.5)) < 1.0e-8)
1908                        possible = true;
1909                } else {
1910                    double value = rowUpper[i];
1911                    if (rowLower[i] == rowUpper[i] &&
1912                            fabs(value - floor(value + 0.5)) < 1.0e-8)
1913                        possible = true;
1914                }
1915                for (CoinBigIndex j = rowStart[i];
1916                        j < rowStart[i] + rowLength[i]; j++) {
1917                    int iColumn = column[j];
1918                    if (continuousSolver_->isInteger(iColumn)) {
1919                        if (fabs(element[j]) != 1.0)
1920                            possible = false;
1921                    } else {
1922                        nLeft++;
1923                    }
1924                }
1925                if (possible || !nLeft)
1926                    possibleRow[i] = 1;
1927                else
1928                    possibleRow[i] = 0;
1929            }
1930        }
1931        int nDel = 0;
1932        for (int i = 0; i < numberColumns; i++) {
1933            original[i] = i;
1934            if (continuousSolver_->isInteger(i))
1935                del[nDel++] = i;
1936        }
1937        int nExtra = 0;
1938        OsiSolverInterface * copy1 = continuousSolver_->clone();
1939        int nPass = 0;
1940        while (nDel && nPass < 10) {
1941            nPass++;
1942            OsiSolverInterface * copy2 = copy1->clone();
1943            int nLeft = 0;
1944            for (int i = 0; i < nDel; i++)
1945                original[del[i]] = -1;
1946            for (int i = 0; i < numberColumns; i++) {
1947                int kOrig = original[i];
1948                if (kOrig >= 0)
1949                    original[nLeft++] = kOrig;
1950            }
1951            assert (nLeft == numberColumns - nDel);
1952            copy2->deleteCols(nDel, del);
1953            numberColumns = copy2->getNumCols();
1954            const CoinPackedMatrix * rowCopy = copy2->getMatrixByRow();
1955            numberRows = rowCopy->getNumRows();
1956            const int * column = rowCopy->getIndices();
1957            const int * rowLength = rowCopy->getVectorLengths();
1958            const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
1959            const double * rowLower = copy2->getRowLower();
1960            const double * rowUpper = copy2->getRowUpper();
1961            const double * element = rowCopy->getElements();
1962            const CoinPackedMatrix * columnCopy = copy2->getMatrixByCol();
1963            const int * columnLength = columnCopy->getVectorLengths();
1964            nDel = 0;
1965            // Could do gcd stuff on ones with costs
1966            for (int i = 0; i < numberRows; i++) {
1967                if (!rowLength[i]) {
1968                    del[nDel++] = i;
1969                    possibleRow[i] = 1;
1970                } else if (possibleRow[i]) {
1971                    if (rowLength[i] == 1) {
1972                        int k = rowStart[i];
1973                        int iColumn = column[k];
1974                        if (!copy2->isInteger(iColumn)) {
1975                            double mult = 1.0 / fabs(element[k]);
1976                            if (rowLower[i] < -1.0e20) {
1977                                double value = rowUpper[i] * mult;
1978                                if (fabs(value - floor(value + 0.5)) < 1.0e-8) {
1979                                    del[nDel++] = i;
1980                                    if (columnLength[iColumn] == 1) {
1981                                        copy2->setInteger(iColumn);
1982                                        int kOrig = original[iColumn];
1983                                        setOptionalInteger(kOrig);
1984                                    }
1985                                }
1986                            } else if (rowUpper[i] > 1.0e20) {
1987                                double value = rowLower[i] * mult;
1988                                if (fabs(value - floor(value + 0.5)) < 1.0e-8) {
1989                                    del[nDel++] = i;
1990                                    if (columnLength[iColumn] == 1) {
1991                                        copy2->setInteger(iColumn);
1992                                        int kOrig = original[iColumn];
1993                                        setOptionalInteger(kOrig);
1994                                    }
1995                                }
1996                            } else {
1997                                double value = rowUpper[i] * mult;
1998                                if (rowLower[i] == rowUpper[i] &&
1999                                        fabs(value - floor(value + 0.5)) < 1.0e-8) {
2000                                    del[nDel++] = i;
2001                                    copy2->setInteger(iColumn);
2002                                    int kOrig = original[iColumn];
2003                                    setOptionalInteger(kOrig);
2004                                }
2005                            }
2006                        }
2007                    } else {
2008                        // only if all singletons
2009                        bool possible = false;
2010                        if (rowLower[i] < -1.0e20) {
2011                            double value = rowUpper[i];
2012                            if (fabs(value - floor(value + 0.5)) < 1.0e-8)
2013                                possible = true;
2014                        } else if (rowUpper[i] > 1.0e20) {
2015                            double value = rowLower[i];
2016                            if (fabs(value - floor(value + 0.5)) < 1.0e-8)
2017                                possible = true;
2018                        } else {
2019                            double value = rowUpper[i];
2020                            if (rowLower[i] == rowUpper[i] &&
2021                                    fabs(value - floor(value + 0.5)) < 1.0e-8)
2022                                possible = true;
2023                        }
2024                        if (possible) {
2025                            for (CoinBigIndex j = rowStart[i];
2026                                    j < rowStart[i] + rowLength[i]; j++) {
2027                                int iColumn = column[j];
2028                                if (columnLength[iColumn] != 1 || fabs(element[j]) != 1.0) {
2029                                    possible = false;
2030                                    break;
2031                                }
2032                            }
2033                            if (possible) {
2034                                for (CoinBigIndex j = rowStart[i];
2035                                        j < rowStart[i] + rowLength[i]; j++) {
2036                                    int iColumn = column[j];
2037                                    if (!copy2->isInteger(iColumn)) {
2038                                        copy2->setInteger(iColumn);
2039                                        int kOrig = original[iColumn];
2040                                        setOptionalInteger(kOrig);
2041                                    }
2042                                }
2043                                del[nDel++] = i;
2044                            }
2045                        }
2046                    }
2047                }
2048            }
2049            if (nDel) {
2050                copy2->deleteRows(nDel, del);
2051            }
2052            if (nDel != numberRows) {
2053                nDel = 0;
2054                for (int i = 0; i < numberColumns; i++) {
2055                    if (copy2->isInteger(i)) {
2056                        del[nDel++] = i;
2057                        nExtra++;
2058                    }
2059                }
2060            } else {
2061                nDel = 0;
2062            }
2063            delete copy1;
2064            copy1 = copy2->clone();
2065            delete copy2;
2066        }
2067        // See if what's left is a network
2068        bool couldBeNetwork = false;
2069        if (copy1->getNumRows() && copy1->getNumCols()) {
2070#ifdef COIN_HAS_CLP
2071            OsiClpSolverInterface * clpSolver
2072            = dynamic_cast<OsiClpSolverInterface *> (copy1);
2073            if (false && clpSolver) {
2074                numberRows = clpSolver->getNumRows();
2075                char * rotate = new char[numberRows];
2076                int n = clpSolver->getModelPtr()->findNetwork(rotate, 1.0);
2077                delete [] rotate;
2078#ifdef CLP_INVESTIGATE
2079                printf("INTA network %d rows out of %d\n", n, numberRows);
2080#endif
2081                if (CoinAbs(n) == numberRows) {
2082                    couldBeNetwork = true;
2083                    for (int i = 0; i < numberRows; i++) {
2084                        if (!possibleRow[i]) {
2085                            couldBeNetwork = false;
2086#ifdef CLP_INVESTIGATE
2087                            printf("but row %d is bad\n", i);
2088#endif
2089                            break;
2090                        }
2091                    }
2092                }
2093            } else
2094#endif
2095            {
2096                numberColumns = copy1->getNumCols();
2097                numberRows = copy1->getNumRows();
2098                const double * rowLower = copy1->getRowLower();
2099                const double * rowUpper = copy1->getRowUpper();
2100                couldBeNetwork = true;
2101                for (int i = 0; i < numberRows; i++) {
2102                    if (rowLower[i] > -1.0e20 && fabs(rowLower[i] - floor(rowLower[i] + 0.5)) > 1.0e-12) {
2103                        couldBeNetwork = false;
2104                        break;
2105                    }
2106                    if (rowUpper[i] < 1.0e20 && fabs(rowUpper[i] - floor(rowUpper[i] + 0.5)) > 1.0e-12) {
2107                        couldBeNetwork = false;
2108                        break;
2109                    }
2110                }
2111                if (couldBeNetwork) {
2112                    const CoinPackedMatrix  * matrixByCol = copy1->getMatrixByCol();
2113                    const double * element = matrixByCol->getElements();
2114                    //const int * row = matrixByCol->getIndices();
2115                    const CoinBigIndex * columnStart = matrixByCol->getVectorStarts();
2116                    const int * columnLength = matrixByCol->getVectorLengths();
2117                    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
2118                        CoinBigIndex start = columnStart[iColumn];
2119                        CoinBigIndex end = start + columnLength[iColumn];
2120                        if (end > start + 2) {
2121                            couldBeNetwork = false;
2122                            break;
2123                        }
2124                        int type = 0;
2125                        for (CoinBigIndex j = start; j < end; j++) {
2126                            double value = element[j];
2127                            if (fabs(value) != 1.0) {
2128                                couldBeNetwork = false;
2129                                break;
2130                            } else if (value == 1.0) {
2131                                if ((type&1) == 0)
2132                                    type |= 1;
2133                                else
2134                                    type = 7;
2135                            } else if (value == -1.0) {
2136                                if ((type&2) == 0)
2137                                    type |= 2;
2138                                else
2139                                    type = 7;
2140                            }
2141                        }
2142                        if (type > 3) {
2143                            couldBeNetwork = false;
2144                            break;
2145                        }
2146                    }
2147                }
2148            }
2149        }
2150        if (couldBeNetwork) {
2151            for (int i = 0; i < numberColumns; i++)
2152                setOptionalInteger(original[i]);
2153        }
2154        if (nExtra || couldBeNetwork) {
2155            numberColumns = copy1->getNumCols();
2156            numberRows = copy1->getNumRows();
2157            if (!numberColumns || !numberRows) {
2158                int numberColumns = solver_->getNumCols();
2159                for (int i = 0; i < numberColumns; i++)
2160                    assert(solver_->isInteger(i));
2161            }
2162#ifdef CLP_INVESTIGATE
2163            if (couldBeNetwork || nExtra)
2164                printf("INTA %d extra integers, %d left%s\n", nExtra,
2165                       numberColumns,
2166                       couldBeNetwork ? ", all network" : "");
2167#endif
2168            findIntegers(true, 2);
2169            convertToDynamic();
2170        }
2171#ifdef CLP_INVESTIGATE
2172        if (!couldBeNetwork && copy1->getNumCols() &&
2173                copy1->getNumRows()) {
2174            printf("INTA %d rows and %d columns remain\n",
2175                   copy1->getNumRows(), copy1->getNumCols());
2176            if (copy1->getNumCols() < 200) {
2177                copy1->writeMps("moreint");
2178                printf("INTA Written remainder to moreint.mps.gz %d rows %d cols\n",
2179                       copy1->getNumRows(), copy1->getNumCols());
2180            }
2181        }
2182#endif
2183        delete copy1;
2184        delete [] del;
2185        delete [] original;
2186        delete [] possibleRow;
2187        // double check increment
2188        analyzeObjective();
2189    }
2190    {
2191        int iObject ;
2192        int preferredWay ;
2193        int numberUnsatisfied = 0 ;
2194        delete [] currentSolution_;
2195        currentSolution_ = new double [numberColumns];
2196        testSolution_ = currentSolution_;
2197        memcpy(currentSolution_, solver_->getColSolution(),
2198               numberColumns*sizeof(double)) ;
2199        // point to useful information
2200        OsiBranchingInformation usefulInfo = usefulInformation();
2201
2202        for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
2203            double infeasibility =
2204                object_[iObject]->infeasibility(&usefulInfo, preferredWay) ;
2205            if (infeasibility ) numberUnsatisfied++ ;
2206        }
2207        // replace solverType
2208        if (solverCharacteristics_->tryCuts())  {
2209
2210            if (numberUnsatisfied)   {
2211                // User event
2212                if (!eventHappened_ && feasible)
2213                    feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
2214                                             NULL);
2215                else
2216                    feasible = false;
2217            }   else if (solverCharacteristics_->solutionAddsCuts() ||
2218                       solverCharacteristics_->alwaysTryCutsAtRootNode()) {
2219                // may generate cuts and turn the solution
2220                //to an infeasible one
2221                feasible = solveWithCuts(cuts, 1,
2222                                         NULL);
2223            }
2224        }
2225        // check extra info on feasibility
2226        if (!solverCharacteristics_->mipFeasible())
2227            feasible = false;
2228    }
2229    // make cut generators less aggressive
2230    for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
2231        CglCutGenerator * generator = generator_[iCutGenerator]->generator();
2232        generator->setAggressiveness(generator->getAggressiveness() - 100);
2233    }
2234    currentNumberCuts_ = numberNewCuts_ ;
2235    // See if can stop on gap
2236    bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
2237    testGap = CoinMax(dblParam_[CbcAllowableGap],
2238                      CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
2239                      * dblParam_[CbcAllowableFractionGap]);
2240    if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0) {
2241        if (bestPossibleObjective_ < getCutoff())
2242            stoppedOnGap_ = true ;
2243        feasible = false;
2244    }
2245    // User event
2246    if (eventHappened_)
2247        feasible = false;
2248#if defined(COIN_HAS_CLP)&&defined(COIN_HAS_CPX)
2249    if (feasible && (specialOptions_&16384) != 0 && fastNodeDepth_ == -2 && !parentModel_) {
2250        // Use Cplex to do search!
2251        double time1 = CoinCpuTime();
2252        OsiClpSolverInterface * clpSolver
2253        = dynamic_cast<OsiClpSolverInterface *> (solver_);
2254        OsiCpxSolverInterface cpxSolver;
2255        double direction = clpSolver->getObjSense();
2256        cpxSolver.setObjSense(direction);
2257        // load up cplex
2258        const CoinPackedMatrix * matrix = continuousSolver_->getMatrixByCol();
2259        const double * rowLower = continuousSolver_->getRowLower();
2260        const double * rowUpper = continuousSolver_->getRowUpper();
2261        const double * columnLower = continuousSolver_->getColLower();
2262        const double * columnUpper = continuousSolver_->getColUpper();
2263        const double * objective = continuousSolver_->getObjCoefficients();
2264        cpxSolver.loadProblem(*matrix, columnLower, columnUpper,
2265                              objective, rowLower, rowUpper);
2266        double * setSol = new double [numberIntegers_];
2267        int * setVar = new int [numberIntegers_];
2268        // cplex doesn't know about objective offset
2269        double offset = clpSolver->getModelPtr()->objectiveOffset();
2270        for (int i = 0; i < numberIntegers_; i++) {
2271            int iColumn = integerVariable_[i];
2272            cpxSolver.setInteger(iColumn);
2273            if (bestSolution_) {
2274                setSol[i] = bestSolution_[iColumn];
2275                setVar[i] = iColumn;
2276            }
2277        }
2278        CPXENVptr env = cpxSolver.getEnvironmentPtr();
2279        CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
2280        cpxSolver.switchToMIP();
2281        if (bestSolution_) {
2282            CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol);
2283        }
2284        if (clpSolver->getNumRows() > continuousSolver_->getNumRows() && false) {
2285            // add cuts
2286            const CoinPackedMatrix * matrix = clpSolver->getMatrixByRow();
2287            const double * rhs = clpSolver->getRightHandSide();
2288            const char * rowSense = clpSolver->getRowSense();
2289            const double * elementByRow = matrix->getElements();
2290            const int * column = matrix->getIndices();
2291            const CoinBigIndex * rowStart = matrix->getVectorStarts();
2292            const int * rowLength = matrix->getVectorLengths();
2293            int nStart = continuousSolver_->getNumRows();
2294            int nRows = clpSolver->getNumRows();
2295            int size = rowStart[nRows-1] + rowLength[nRows-1] -
2296                       rowStart[nStart];
2297            int nAdd = 0;
2298            double * rmatval = new double [size];
2299            int * rmatind = new int [size];
2300            int * rmatbeg = new int [nRows-nStart+1];
2301            size = 0;
2302            rmatbeg[0] = 0;
2303            for (int i = nStart; i < nRows; i++) {
2304                for (int k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) {
2305                    rmatind[size] = column[k];
2306                    rmatval[size++] = elementByRow[k];
2307                }
2308                nAdd++;
2309                rmatbeg[nAdd] = size;
2310            }
2311            CPXaddlazyconstraints(env, lpPtr, nAdd, size,
2312                                  rhs, rowSense, rmatbeg,
2313                                  rmatind, rmatval, NULL);
2314            CPXsetintparam( env, CPX_PARAM_REDUCE,
2315                            // CPX_PREREDUCE_NOPRIMALORDUAL (0)
2316                            CPX_PREREDUCE_PRIMALONLY);
2317        }
2318        if (getCutoff() < 1.0e50) {
2319            double useCutoff = getCutoff() + offset;
2320            if (bestObjective_ < 1.0e50)
2321                useCutoff = bestObjective_ + offset + 1.0e-7;
2322            cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff*
2323                                  direction);
2324            if ( direction > 0.0 )
2325                CPXsetdblparam( env, CPX_PARAM_CUTUP, useCutoff ) ; // min
2326            else
2327                CPXsetdblparam( env, CPX_PARAM_CUTLO, useCutoff ) ; // max
2328        }
2329        CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]);
2330        delete [] setSol;
2331        delete [] setVar;
2332        char printBuffer[200];
2333        if (offset) {
2334            sprintf(printBuffer, "Add %g to all Cplex messages for true objective",
2335                    -offset);
2336            messageHandler()->message(CBC_GENERAL, messages())
2337            << printBuffer << CoinMessageEol ;
2338            cpxSolver.setDblParam(OsiObjOffset, offset);
2339        }
2340        cpxSolver.branchAndBound();
2341        double timeTaken = CoinCpuTime() - time1;
2342        sprintf(printBuffer, "Cplex took %g seconds",
2343                timeTaken);
2344        messageHandler()->message(CBC_GENERAL, messages())
2345        << printBuffer << CoinMessageEol ;
2346        numberExtraNodes_ = CPXgetnodecnt(env, lpPtr);
2347        numberExtraIterations_ = CPXgetmipitcnt(env, lpPtr);
2348        double value = cpxSolver.getObjValue() * direction;
2349        if (cpxSolver.isProvenOptimal() && value <= getCutoff()) {
2350            feasible = true;
2351            clpSolver->setWarmStart(NULL);
2352            // try and do solution
2353            double * newSolution =
2354                CoinCopyOfArray(cpxSolver.getColSolution(),
2355                                getNumCols());
2356            setBestSolution(CBC_STRONGSOL, value, newSolution) ;
2357            delete [] newSolution;
2358        }
2359        feasible = false;
2360    }
2361#endif
2362    if (fastNodeDepth_ == 1000 &&/*!parentModel_*/(specialOptions_&2048) == 0) {
2363        fastNodeDepth_ = -1;
2364        CbcObject * obj =
2365            new CbcFollowOn(this);
2366        obj->setPriority(1);
2367        addObjects(1, &obj);
2368    }
2369    int saveNumberSolves = numberSolves_;
2370    int saveNumberIterations = numberIterations_;
2371    if (fastNodeDepth_ >= 0 &&/*!parentModel_*/(specialOptions_&2048) == 0) {
2372        // add in a general depth object doClp
2373        int type = (fastNodeDepth_ <= 100) ? fastNodeDepth_ : -(fastNodeDepth_ - 100);
2374        CbcObject * obj =
2375            new CbcGeneralDepth(this, type);
2376        addObjects(1, &obj);
2377        // mark as done
2378        fastNodeDepth_ += 1000000;
2379        delete obj;
2380        // fake number of objects
2381        numberObjects_--;
2382        if (parallelMode() < -1) {
2383            // But make sure position is correct
2384            OsiObject * obj2 = object_[numberObjects_];
2385            obj = dynamic_cast<CbcObject *> (obj2);
2386            assert (obj);
2387            obj->setPosition(numberObjects_);
2388        }
2389    }
2390#ifdef COIN_HAS_CLP
2391#ifdef NO_CRUNCH
2392    if (true) {
2393        OsiClpSolverInterface * clpSolver
2394        = dynamic_cast<OsiClpSolverInterface *> (solver_);
2395        if (clpSolver && !parentModel_) {
2396            ClpSimplex * clpSimplex = clpSolver->getModelPtr();
2397            clpSimplex->setSpecialOptions(clpSimplex->specialOptions() | 131072);
2398            //clpSimplex->startPermanentArrays();
2399            clpSimplex->setPersistenceFlag(2);
2400        }
2401    }
2402#endif
2403#endif
2404// Save copy of solver
2405    OsiSolverInterface * saveSolver = NULL;
2406    if (!parentModel_ && (specialOptions_&(512 + 32768)) != 0)
2407        saveSolver = solver_->clone();
2408    double checkCutoffForRestart = 1.0e100;
2409    if (saveSolver && (specialOptions_&32768) != 0) {
2410        // See if worth trying reduction
2411        checkCutoffForRestart = getCutoff();
2412        bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() &&
2413                            (checkCutoffForRestart < 1.0e20);
2414        int numberColumns = getNumCols();
2415        if (tryNewSearch) {
2416#ifdef CLP_INVESTIGATE
2417            printf("after %d nodes, cutoff %g - looking\n",
2418                   numberNodes_, getCutoff());
2419#endif
2420            saveSolver->resolve();
2421            double direction = saveSolver->getObjSense() ;
2422            double gap = checkCutoffForRestart - saveSolver->getObjValue() * direction ;
2423            double tolerance;
2424            saveSolver->getDblParam(OsiDualTolerance, tolerance) ;
2425            if (gap <= 0.0)
2426                gap = tolerance;
2427            gap += 100.0 * tolerance;
2428            double integerTolerance = getDblParam(CbcIntegerTolerance) ;
2429
2430            const double *lower = saveSolver->getColLower() ;
2431            const double *upper = saveSolver->getColUpper() ;
2432            const double *solution = saveSolver->getColSolution() ;
2433            const double *reducedCost = saveSolver->getReducedCost() ;
2434
2435            int numberFixed = 0 ;
2436            int numberFixed2 = 0;
2437            for (int i = 0 ; i < numberIntegers_ ; i++) {
2438                int iColumn = integerVariable_[i] ;
2439                double djValue = direction * reducedCost[iColumn] ;
2440                if (upper[iColumn] - lower[iColumn] > integerTolerance) {
2441                    if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
2442                        saveSolver->setColUpper(iColumn, lower[iColumn]) ;
2443                        numberFixed++ ;
2444                    } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
2445                        saveSolver->setColLower(iColumn, upper[iColumn]) ;
2446                        numberFixed++ ;
2447                    }
2448                } else {
2449                    numberFixed2++;
2450                }
2451            }
2452#ifdef COIN_DEVELOP
2453            if ((specialOptions_&1) != 0) {
2454                const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ;
2455                if (debugger) {
2456                    printf("Contains optimal\n") ;
2457                    OsiSolverInterface * temp = saveSolver->clone();
2458                    const double * solution = debugger->optimalSolution();
2459                    const double *lower = temp->getColLower() ;
2460                    const double *upper = temp->getColUpper() ;
2461                    int n = temp->getNumCols();
2462                    for (int i = 0; i < n; i++) {
2463                        if (temp->isInteger(i)) {
2464                            double value = floor(solution[i] + 0.5);
2465                            assert (value >= lower[i] && value <= upper[i]);
2466                            temp->setColLower(i, value);
2467                            temp->setColUpper(i, value);
2468                        }
2469                    }
2470                    temp->writeMps("reduced_fix");
2471                    delete temp;
2472                    saveSolver->writeMps("reduced");
2473                } else {
2474                    abort();
2475                }
2476            }
2477            printf("Restart could fix %d integers (%d already fixed)\n",
2478                   numberFixed + numberFixed2, numberFixed2);
2479#endif
2480            numberFixed += numberFixed2;
2481            if (numberFixed*20 < numberColumns)
2482                tryNewSearch = false;
2483        }
2484        if (tryNewSearch) {
2485            // back to solver without cuts?
2486            OsiSolverInterface * solver2 = continuousSolver_->clone();
2487            const double *lower = saveSolver->getColLower() ;
2488            const double *upper = saveSolver->getColUpper() ;
2489            for (int i = 0 ; i < numberIntegers_ ; i++) {
2490                int iColumn = integerVariable_[i] ;
2491                solver2->setColLower(iColumn, lower[iColumn]);
2492                solver2->setColUpper(iColumn, upper[iColumn]);
2493            }
2494            // swap
2495            delete saveSolver;
2496            saveSolver = solver2;
2497            double * newSolution = new double[numberColumns];
2498            double objectiveValue = checkCutoffForRestart;
2499            CbcSerendipity heuristic(*this);
2500            if (bestSolution_)
2501                heuristic.setInputSolution(bestSolution_, bestObjective_);
2502            heuristic.setFractionSmall(0.5);
2503            heuristic.setFeasibilityPumpOptions(1008013);
2504            // Use numberNodes to say how many are original rows
2505            heuristic.setNumberNodes(continuousSolver_->getNumRows());
2506#ifdef COIN_DEVELOP
2507            if (continuousSolver_->getNumRows() <
2508                    saveSolver->getNumRows())
2509                printf("%d rows added ZZZZZ\n",
2510                       solver_->getNumRows() - continuousSolver_->getNumRows());
2511#endif
2512            int returnCode = heuristic.smallBranchAndBound(saveSolver,
2513                             -1, newSolution,
2514                             objectiveValue,
2515                             checkCutoffForRestart, "Reduce");
2516            if (returnCode < 0) {
2517#ifdef COIN_DEVELOP
2518                printf("Restart - not small enough to do search after fixing\n");
2519#endif
2520                delete [] newSolution;
2521            } else {
2522                if ((returnCode&1) != 0) {
2523                    // increment number of solutions so other heuristics can test
2524                    numberSolutions_++;
2525                    numberHeuristicSolutions_++;
2526                    lastHeuristic_ = NULL;
2527                    setBestSolution(CBC_ROUNDING, objectiveValue, newSolution) ;
2528                }
2529                delete [] newSolution;
2530                feasible = false; // stop search
2531            }
2532        }
2533    }
2534    /*
2535      We've taken the continuous relaxation as far as we can. Time to branch.
2536      The first order of business is to actually create a node. chooseBranch
2537      currently uses strong branching to evaluate branch object candidates,
2538      unless forced back to simple branching. If chooseBranch concludes that a
2539      branching candidate is monotone (anyAction == -1) or infeasible (anyAction
2540      == -2) when forced to integer values, it returns here immediately.
2541
2542      Monotone variables trigger a call to resolve(). If the problem remains
2543      feasible, try again to choose a branching variable. At the end of the loop,
2544      resolved == true indicates that some variables were fixed.
2545
2546      Loss of feasibility will result in the deletion of newNode.
2547    */
2548
2549    bool resolved = false ;
2550    CbcNode *newNode = NULL ;
2551    numberFixedAtRoot_ = 0;
2552    numberFixedNow_ = 0;
2553    int numberIterationsAtContinuous = numberIterations_;
2554    //solverCharacteristics_->setSolver(solver_);
2555    if (feasible) {
2556        //#define HOTSTART -1
2557#if HOTSTART<0
2558        if (bestSolution_ && !parentModel_ && !hotstartSolution_ &&
2559                (moreSpecialOptions_&1024) != 0) {
2560            // Set priorities so only branch on ones we need to
2561            // use djs and see if only few branches needed
2562#ifndef NDEBUG
2563            double integerTolerance = getIntegerTolerance() ;
2564#endif
2565            bool possible = true;
2566            const double * saveLower = continuousSolver_->getColLower();
2567            const double * saveUpper = continuousSolver_->getColUpper();
2568            for (int i = 0; i < numberObjects_; i++) {
2569                const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object_[i]);
2570                if (thisOne) {
2571                    int iColumn = thisOne->columnNumber();
2572                    if (saveUpper[iColumn] > saveLower[iColumn] + 1.5) {
2573                        possible = false;
2574                        break;
2575                    }
2576                } else {
2577                    possible = false;
2578                    break;
2579                }
2580            }
2581            if (possible) {
2582                OsiSolverInterface * solver = continuousSolver_->clone();
2583                int numberColumns = solver->getNumCols();
2584                for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2585                    double value = bestSolution_[iColumn] ;
2586                    value = CoinMax(value, saveLower[iColumn]) ;
2587                    value = CoinMin(value, saveUpper[iColumn]) ;
2588                    value = floor(value + 0.5);
2589                    if (solver->isInteger(iColumn)) {
2590                        solver->setColLower(iColumn, value);
2591                        solver->setColUpper(iColumn, value);
2592                    }
2593                }
2594                solver->setHintParam(OsiDoDualInResolve, false, OsiHintTry);
2595                // objlim and all slack
2596                double direction = solver->getObjSense();
2597                solver->setDblParam(OsiDualObjectiveLimit, 1.0e50*direction);
2598                CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (solver->getEmptyWarmStart());
2599                solver->setWarmStart(basis);
2600                delete basis;
2601                bool changed = true;
2602                hotstartPriorities_ = new int [numberColumns];
2603                for (int iColumn = 0; iColumn < numberColumns; iColumn++)
2604                    hotstartPriorities_[iColumn] = 1;
2605                while (changed) {
2606                    changed = false;
2607                    solver->resolve();
2608                    if (!solver->isProvenOptimal()) {
2609                        possible = false;
2610                        break;
2611                    }
2612                    const double * dj = solver->getReducedCost();
2613                    const double * colLower = solver->getColLower();
2614                    const double * colUpper = solver->getColUpper();
2615                    const double * solution = solver->getColSolution();
2616                    int nAtLbNatural = 0;
2617                    int nAtUbNatural = 0;
2618                    int nZeroDj = 0;
2619                    int nForced = 0;
2620                    for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2621                        double value = solution[iColumn] ;
2622                        value = CoinMax(value, saveLower[iColumn]) ;
2623                        value = CoinMin(value, saveUpper[iColumn]) ;
2624                        if (solver->isInteger(iColumn)) {
2625                            assert(fabs(value - solution[iColumn]) <= integerTolerance) ;
2626                            if (hotstartPriorities_[iColumn] == 1) {
2627                                if (dj[iColumn] < -1.0e-6) {
2628                                    // negative dj
2629                                    if (saveUpper[iColumn] == colUpper[iColumn]) {
2630                                        nAtUbNatural++;
2631                                        hotstartPriorities_[iColumn] = 2;
2632                                        solver->setColLower(iColumn, saveLower[iColumn]);
2633                                        solver->setColUpper(iColumn, saveUpper[iColumn]);
2634                                    } else {
2635                                        nForced++;
2636                                    }
2637                                } else if (dj[iColumn] > 1.0e-6) {
2638                                    // positive dj
2639                                    if (saveLower[iColumn] == colLower[iColumn]) {
2640                                        nAtLbNatural++;
2641                                        hotstartPriorities_[iColumn] = 2;
2642                                        solver->setColLower(iColumn, saveLower[iColumn]);
2643                                        solver->setColUpper(iColumn, saveUpper[iColumn]);
2644                                    } else {
2645                                        nForced++;
2646                                    }
2647                                } else {
2648                                    // zero dj
2649                                    nZeroDj++;
2650                                }
2651                            }
2652                        }
2653                    }
2654#ifdef CLP_INVESTIGATE
2655                    printf("%d forced, %d naturally at lower, %d at upper - %d zero dj\n",
2656                           nForced, nAtLbNatural, nAtUbNatural, nZeroDj);
2657#endif
2658                    if (nAtLbNatural || nAtUbNatural) {
2659                        changed = true;
2660                    } else {
2661                        if (nForced + nZeroDj > 50 ||
2662                                (nForced + nZeroDj)*4 > numberIntegers_)
2663                            possible = false;
2664                    }
2665                }
2666                delete solver;
2667            }
2668            if (possible) {
2669                setHotstartSolution(bestSolution_);
2670                if (!saveCompare) {
2671                    // create depth first comparison
2672                    saveCompare = nodeCompare_;
2673                    // depth first
2674                    nodeCompare_ = new CbcCompareDepth();
2675                    tree_->setComparison(*nodeCompare_) ;
2676                }
2677            } else {
2678                delete [] hotstartPriorities_;
2679                hotstartPriorities_ = NULL;
2680            }
2681        }
2682#endif
2683#if HOTSTART>0
2684        if (hotstartSolution_ && !hotstartPriorities_) {
2685            // Set up hot start
2686            OsiSolverInterface * solver = solver_->clone();
2687            double direction = solver_->getObjSense() ;
2688            int numberColumns = solver->getNumCols();
2689            double * saveLower = CoinCopyOfArray(solver->getColLower(), numberColumns);
2690            double * saveUpper = CoinCopyOfArray(solver->getColUpper(), numberColumns);
2691            // move solution
2692            solver->setColSolution(hotstartSolution_);
2693            // point to useful information
2694            const double * saveSolution = testSolution_;
2695            testSolution_ = solver->getColSolution();
2696            OsiBranchingInformation usefulInfo = usefulInformation();
2697            testSolution_ = saveSolution;
2698            /*
2699            Run through the objects and use feasibleRegion() to set variable bounds
2700            so as to fix the variables specified in the objects at their value in this
2701            solution. Since the object list contains (at least) one object for every
2702            integer variable, this has the effect of fixing all integer variables.
2703            */
2704            for (int i = 0; i < numberObjects_; i++)
2705                object_[i]->feasibleRegion(solver, &usefulInfo);
2706            solver->resolve();
2707            assert (solver->isProvenOptimal());
2708            double gap = CoinMax((solver->getObjValue() - solver_->getObjValue()) * direction, 0.0) ;
2709            const double * dj = solver->getReducedCost();
2710            const double * colLower = solver->getColLower();
2711            const double * colUpper = solver->getColUpper();
2712            const double * solution = solver->getColSolution();
2713            int nAtLbNatural = 0;
2714            int nAtUbNatural = 0;
2715            int nAtLbNaturalZero = 0;
2716            int nAtUbNaturalZero = 0;
2717            int nAtLbFixed = 0;
2718            int nAtUbFixed = 0;
2719            int nAtOther = 0;
2720            int nAtOtherNatural = 0;
2721            int nNotNeeded = 0;
2722            delete [] hotstartSolution_;
2723            hotstartSolution_ = new double [numberColumns];
2724            delete [] hotstartPriorities_;
2725            hotstartPriorities_ = new int [numberColumns];
2726            int * order = (int *) saveUpper;
2727            int nFix = 0;
2728            double bestRatio = COIN_DBL_MAX;
2729            for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2730                double value = solution[iColumn] ;
2731                value = CoinMax(value, saveLower[iColumn]) ;
2732                value = CoinMin(value, saveUpper[iColumn]) ;
2733                double sortValue = COIN_DBL_MAX;
2734                if (solver->isInteger(iColumn)) {
2735                    assert(fabs(value - solution[iColumn]) <= 1.0e-5) ;
2736                    double value2 = floor(value + 0.5);
2737                    if (dj[iColumn] < -1.0e-6) {
2738                        // negative dj
2739                        //assert (value2==colUpper[iColumn]);
2740                        if (saveUpper[iColumn] == colUpper[iColumn]) {
2741                            nAtUbNatural++;
2742                            sortValue = 0.0;
2743                            double value = -dj[iColumn];
2744                            if (value > gap)
2745                                nFix++;
2746                            else if (gap < value*bestRatio)
2747                                bestRatio = gap / value;
2748                            if (saveLower[iColumn] != colLower[iColumn]) {
2749                                nNotNeeded++;
2750                                sortValue = 1.0e20;
2751                            }
2752                        } else if (saveLower[iColumn] == colUpper[iColumn]) {
2753                            nAtLbFixed++;
2754                            sortValue = dj[iColumn];
2755                        } else {
2756                            nAtOther++;
2757                            sortValue = 0.0;
2758                            if (saveLower[iColumn] != colLower[iColumn] &&
2759                                    saveUpper[iColumn] != colUpper[iColumn]) {
2760                                nNotNeeded++;
2761                                sortValue = 1.0e20;
2762                            }
2763                        }
2764                    } else if (dj[iColumn] > 1.0e-6) {
2765                        // positive dj
2766                        //assert (value2==colLower[iColumn]);
2767                        if (saveLower[iColumn] == colLower[iColumn]) {
2768                            nAtLbNatural++;
2769                            sortValue = 0.0;
2770                            double value = dj[iColumn];
2771                            if (value > gap)
2772                                nFix++;
2773                            else if (gap < value*bestRatio)
2774                                bestRatio = gap / value;
2775                            if (saveUpper[iColumn] != colUpper[iColumn]) {
2776                                nNotNeeded++;
2777                                sortValue = 1.0e20;
2778                            }
2779                        } else if (saveUpper[iColumn] == colLower[iColumn]) {
2780                            nAtUbFixed++;
2781                            sortValue = -dj[iColumn];
2782                        } else {
2783                            nAtOther++;
2784                            sortValue = 0.0;
2785                            if (saveLower[iColumn] != colLower[iColumn] &&
2786                                    saveUpper[iColumn] != colUpper[iColumn]) {
2787                                nNotNeeded++;
2788                                sortValue = 1.0e20;
2789                            }
2790                        }
2791                    } else {
2792                        // zero dj
2793                        if (value2 == saveUpper[iColumn]) {
2794                            nAtUbNaturalZero++;
2795                            sortValue = 0.0;
2796                            if (saveLower[iColumn] != colLower[iColumn]) {
2797                                nNotNeeded++;
2798                                sortValue = 1.0e20;
2799                            }
2800                        } else if (value2 == saveLower[iColumn]) {
2801                            nAtLbNaturalZero++;
2802                            sortValue = 0.0;
2803                        } else {
2804                            nAtOtherNatural++;
2805                            sortValue = 0.0;
2806                            if (saveLower[iColumn] != colLower[iColumn] &&
2807                                    saveUpper[iColumn] != colUpper[iColumn]) {
2808                                nNotNeeded++;
2809                                sortValue = 1.0e20;
2810                            }
2811                        }
2812                    }
2813#if HOTSTART==3
2814                    sortValue = -fabs(dj[iColumn]);
2815#endif
2816                }
2817                hotstartSolution_[iColumn] = value ;
2818                saveLower[iColumn] = sortValue;
2819                order[iColumn] = iColumn;
2820            }
2821            printf("** can fix %d columns - best ratio for others is %g on gap of %g\n",
2822                   nFix, bestRatio, gap);
2823            int nNeg = 0;
2824            CoinSort_2(saveLower, saveLower + numberColumns, order);
2825            for (int i = 0; i < numberColumns; i++) {
2826                if (saveLower[i] < 0.0) {
2827                    nNeg++;
2828#if HOTSTART==2||HOTSTART==3
2829                    // swap sign ?
2830                    saveLower[i] = -saveLower[i];
2831#endif
2832                }
2833            }
2834            CoinSort_2(saveLower, saveLower + nNeg, order);
2835            for (int i = 0; i < numberColumns; i++) {
2836#if HOTSTART==1
2837                hotstartPriorities_[order[i]] = 100;
2838#else
2839                hotstartPriorities_[order[i]] = -(i + 1);
2840#endif
2841            }
2842            printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n",
2843                   nAtLbNatural,
2844                   nAtUbNatural,
2845                   nAtLbNaturalZero,
2846                   nAtUbNaturalZero,
2847                   nAtLbFixed,
2848                   nAtUbFixed,
2849                   nAtOther,
2850                   nAtOtherNatural, nNotNeeded, nNeg);
2851            delete [] saveLower;
2852            delete [] saveUpper;
2853            if (!saveCompare) {
2854                // create depth first comparison
2855                saveCompare = nodeCompare_;
2856                // depth first
2857                nodeCompare_ = new CbcCompareDepth();
2858                tree_->setComparison(*nodeCompare_) ;
2859            }
2860        }
2861#endif
2862        if (probingInfo_) {
2863            int number01 = probingInfo_->numberIntegers();
2864            //const fixEntry * entry = probingInfo_->fixEntries();
2865            const int * toZero = probingInfo_->toZero();
2866            //const int * toOne = probingInfo_->toOne();
2867            //const int * integerVariable = probingInfo_->integerVariable();
2868            if (toZero[number01]) {
2869                if (probingInfo_->packDown()) {
2870#ifdef CLP_INVESTIGATE
2871                    printf("%d implications on %d 0-1\n", toZero[number01], number01);
2872#endif
2873                    CglImplication implication(probingInfo_);
2874                    addCutGenerator(&implication, 1, "ImplicationCuts", true, false, false, -200);
2875                } else {
2876                    delete probingInfo_;
2877                    probingInfo_ = NULL;
2878                }
2879            } else {
2880                delete probingInfo_;
2881
2882                probingInfo_ = NULL;
2883            }
2884        }
2885        newNode = new CbcNode ;
2886        // Set objective value (not so obvious if NLP etc)
2887        setObjectiveValue(newNode, NULL);
2888        anyAction = -1 ;
2889        // To make depth available we may need a fake node
2890        CbcNode fakeNode;
2891        if (!currentNode_) {
2892            // Not true if sub trees assert (!numberNodes_);
2893            currentNode_ = &fakeNode;
2894        }
2895        phase_ = 3;
2896        // only allow 1000 passes
2897        int numberPassesLeft = 1000;
2898        // This is first crude step
2899        if (numberAnalyzeIterations_) {
2900            delete [] analyzeResults_;
2901            analyzeResults_ = new double [4*numberIntegers_];
2902            numberFixedAtRoot_ = newNode->analyze(this, analyzeResults_);
2903            if (numberFixedAtRoot_ > 0) {
2904                printf("%d fixed by analysis\n", numberFixedAtRoot_);
2905                setPointers(solver_);
2906                numberFixedNow_ = numberFixedAtRoot_;
2907            } else if (numberFixedAtRoot_ < 0) {
2908                printf("analysis found to be infeasible\n");
2909                anyAction = -2;
2910                delete newNode ;
2911                newNode = NULL ;
2912                feasible = false ;
2913            }
2914        }
2915        OsiSolverBranch * branches = NULL;
2916        anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts, resolved,
2917                                 NULL, NULL, NULL, branches);
2918        if (anyAction == -2 || newNode->objectiveValue() >= cutoff) {
2919            if (anyAction != -2) {
2920                // zap parent nodeInfo
2921#ifdef COIN_DEVELOP
2922                printf("zapping CbcNodeInfo %x\n", reinterpret_cast<int>(newNode->nodeInfo()->parent()));
2923#endif
2924                if (newNode->nodeInfo())
2925                    newNode->nodeInfo()->nullParent();
2926            }
2927            delete newNode ;
2928            newNode = NULL ;
2929            feasible = false ;
2930        }
2931    }
2932    /*
2933      At this point, the root subproblem is infeasible or fathomed by bound
2934      (newNode == NULL), or we're live with an objective value that satisfies the
2935      current objective cutoff.
2936    */
2937    assert (!newNode || newNode->objectiveValue() <= cutoff) ;
2938    // Save address of root node as we don't want to delete it
2939    // initialize for print out
2940    int lastDepth = 0;
2941    int lastUnsatisfied = 0;
2942    if (newNode)
2943        lastUnsatisfied = newNode->numberUnsatisfied();
2944    /*
2945      The common case is that the lp relaxation is feasible but doesn't satisfy
2946      integrality (i.e., newNode->branchingObject(), indicating we've been able to
2947      select a branching variable). Remove any cuts that have gone slack due to
2948      forcing monotone variables. Then tack on an CbcFullNodeInfo object and full
2949      basis (via createInfo()) and stash the new cuts in the nodeInfo (via
2950      addCuts()). If, by some miracle, we have an integral solution at the root
2951      (newNode->branchingObject() is NULL), takeOffCuts() will ensure that the solver holds
2952      a valid solution for use by setBestSolution().
2953    */
2954    CoinWarmStartBasis *lastws = NULL ;
2955    if (feasible && newNode->branchingObject()) {
2956        if (resolved) {
2957            takeOffCuts(cuts, false, NULL) ;
2958#     ifdef CHECK_CUT_COUNTS
2959            { printf("Number of rows after chooseBranch fix (root)"
2960                         "(active only) %d\n",
2961                         numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_) ;
2962                const CoinWarmStartBasis* debugws =
2963                    dynamic_cast <const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
2964                debugws->print() ;
2965                delete debugws ;
2966            }
2967#     endif
2968        }
2969        //newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
2970        //newNode->nodeInfo()->addCuts(cuts,
2971        //                       newNode->numberBranches(),whichGenerator_) ;
2972        if (lastws) delete lastws ;
2973        lastws = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
2974    }
2975    /*
2976      Continuous data to be used later
2977    */
2978    continuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
2979    continuousInfeasibilities_ = 0 ;
2980    if (newNode) {
2981        continuousObjective_ = newNode->objectiveValue() ;
2982        delete [] continuousSolution_;
2983        continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
2984                                              numberColumns);
2985        continuousInfeasibilities_ = newNode->numberUnsatisfied() ;
2986    }
2987    /*
2988      Bound may have changed so reset in objects
2989    */
2990    {
2991        int i ;
2992        for (i = 0; i < numberObjects_; i++)
2993            object_[i]->resetBounds(solver_) ;
2994    }
2995    /*
2996      Feasible? Then we should have either a live node prepped for future
2997      expansion (indicated by variable() >= 0), or (miracle of miracles) an
2998      integral solution at the root node.
2999
3000      initializeInfo sets the reference counts in the nodeInfo object.  Since
3001      this node is still live, push it onto the heap that holds the live set.
3002    */
3003    double bestValue = 0.0 ;
3004    if (newNode) {
3005        bestValue = newNode->objectiveValue();
3006        if (newNode->branchingObject()) {
3007            newNode->initializeInfo() ;
3008            tree_->push(newNode) ;
3009            if (statistics_) {
3010                if (numberNodes2_ == maximumStatistics_) {
3011                    maximumStatistics_ = 2 * maximumStatistics_;
3012                    CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
3013                    memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *));
3014                    memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *));
3015                    delete [] statistics_;
3016                    statistics_ = temp;
3017                }
3018                assert (!statistics_[numberNodes2_]);
3019                statistics_[numberNodes2_] = new CbcStatistics(newNode, this);
3020            }
3021            numberNodes2_++;
3022#     ifdef CHECK_NODE
3023            printf("Node %x on tree\n", newNode) ;
3024#     endif
3025        } else {
3026            // continuous is integer
3027            double objectiveValue = newNode->objectiveValue();
3028            setBestSolution(CBC_SOLUTION, objectiveValue,
3029                            solver_->getColSolution()) ;
3030            delete newNode ;
3031            newNode = NULL ;
3032        }
3033    }
3034
3035    if (printFrequency_ <= 0) {
3036        printFrequency_ = 1000 ;
3037        if (getNumCols() > 2000)
3038            printFrequency_ = 100 ;
3039    }
3040    /*
3041      It is possible that strong branching fixes one variable and then the code goes round
3042      again and again.  This can take too long.  So we need to warn user - just once.
3043    */
3044    numberLongStrong_ = 0;
3045    CbcNode * createdNode = NULL;
3046#ifdef CBC_THREAD
3047    CbcModel ** threadModel = NULL;
3048    Coin_pthread_t * threadId = NULL;
3049    int * threadCount = NULL;
3050    pthread_mutex_t mutex;
3051    pthread_cond_t condition_main;
3052    pthread_mutex_t condition_mutex;
3053    pthread_mutex_t * mutex2 = NULL;
3054    pthread_cond_t * condition2 = NULL;
3055    threadStruct * threadInfo = NULL;
3056    bool locked = false;
3057    int threadStats[6];
3058    int defaultParallelIterations = 400;
3059    int defaultParallelNodes = 2;
3060    memset(threadStats, 0, sizeof(threadStats));
3061    double timeWaiting = 0.0;
3062    // For now just one model
3063    if (numberThreads_) {
3064        nodeCompare_->sayThreaded(); // need to use addresses
3065        threadId = new Coin_pthread_t [numberThreads_];
3066        threadCount = new int [numberThreads_];
3067        CoinZeroN(threadCount, numberThreads_);
3068        pthread_mutex_init(&mutex, NULL);
3069        pthread_cond_init(&condition_main, NULL);
3070        pthread_mutex_init(&condition_mutex, NULL);
3071        threadModel = new CbcModel * [numberThreads_+1];
3072        threadInfo = new threadStruct [numberThreads_+1];
3073        mutex2 = new pthread_mutex_t [numberThreads_];
3074        condition2 = new pthread_cond_t [numberThreads_];
3075        if (parallelMode() < -1) {
3076            // May need for deterministic
3077            saveObjects = new OsiObject * [numberObjects_];
3078            for (int i = 0; i < numberObjects_; i++) {
3079                saveObjects[i] = object_[i]->clone();
3080            }
3081        }
3082        // we don't want a strategy object
3083        CbcStrategy * saveStrategy = strategy_;
3084        strategy_ = NULL;
3085        for (int i = 0; i < numberThreads_; i++) {
3086            pthread_mutex_init(mutex2 + i, NULL);
3087            pthread_cond_init(condition2 + i, NULL);
3088            threadId[i].status = 0;
3089            threadInfo[i].baseModel = this;
3090            threadModel[i] = new CbcModel(*this, true);
3091            threadModel[i]->synchronizeHandlers(1);
3092#ifdef COIN_HAS_CLP
3093            // Solver may need to know about model
3094            CbcModel * thisModel = threadModel[i];
3095            CbcOsiSolver * solver =
3096                dynamic_cast<CbcOsiSolver *>(thisModel->solver()) ;
3097            if (solver)
3098                solver->setCbcModel(thisModel);
3099#endif
3100            mutex_ = reinterpret_cast<void *> (threadInfo + i);
3101            threadModel[i]->moveToModel(this, -1);
3102            threadInfo[i].thisModel = threadModel[i];
3103            threadInfo[i].node = NULL;
3104            threadInfo[i].createdNode = NULL;
3105            threadInfo[i].threadIdOfBase.thr = pthread_self();
3106            threadInfo[i].mutex = &mutex;
3107            threadInfo[i].mutex2 = mutex2 + i;
3108            threadInfo[i].condition2 = condition2 + i;
3109            threadInfo[i].returnCode = -1;
3110            threadInfo[i].timeLocked = 0.0;
3111            threadInfo[i].timeWaitingToLock = 0.0;
3112            threadInfo[i].timeWaitingToStart = 0.0;
3113            threadInfo[i].timeInThread = 0.0;
3114            threadInfo[i].numberTimesLocked = 0;
3115            threadInfo[i].numberTimesUnlocked = 0;
3116            threadInfo[i].numberTimesWaitingToStart = 0;
3117            threadInfo[i].dantzigState = 0; // 0 unset, -1 waiting to be set, 1 set
3118            threadInfo[i].locked = false;
3119            threadInfo[i].delNode = NULL;
3120            threadInfo[i].maxDeleteNode = 0;
3121            threadInfo[i].nDeleteNode = 0;
3122            threadInfo[i].nodesThisTime = 0;
3123            threadInfo[i].iterationsThisTime = 0;
3124            pthread_create(&(threadId[i].thr), NULL, doNodesThread, threadInfo + i);
3125            threadId[i].status = 1;
3126        }
3127        strategy_ = saveStrategy;
3128        // Do a partial one for base model
3129        threadInfo[numberThreads_].baseModel = this;
3130        threadModel[numberThreads_] = this;
3131        mutex_ = reinterpret_cast<void *> (threadInfo + numberThreads_);
3132        threadInfo[numberThreads_].node = NULL;
3133        threadInfo[numberThreads_].mutex = &mutex;
3134        threadInfo[numberThreads_].condition2 = &condition_main;
3135        threadInfo[numberThreads_].mutex2 = &condition_mutex;
3136        threadInfo[numberThreads_].timeLocked = 0.0;
3137        threadInfo[numberThreads_].timeWaitingToLock = 0.0;
3138        threadInfo[numberThreads_].numberTimesLocked = 0;
3139        threadInfo[numberThreads_].numberTimesUnlocked = 0;
3140        threadInfo[numberThreads_].locked = false;
3141    }
3142#endif
3143#ifdef COIN_HAS_CLP
3144    {
3145        OsiClpSolverInterface * clpSolver
3146        = dynamic_cast<OsiClpSolverInterface *> (solver_);
3147        if (clpSolver && !parentModel_) {
3148            clpSolver->computeLargestAway();
3149        }
3150    }
3151#endif
3152    /*
3153      At last, the actual branch-and-cut search loop, which will iterate until
3154      the live set is empty or we hit some limit (integrality gap, time, node
3155      count, etc.). The overall flow is to rebuild a subproblem, reoptimise using
3156      solveWithCuts(), choose a branching pattern with chooseBranch(), and finally
3157      add the node to the live set.
3158
3159      The first action is to winnow the live set to remove nodes which are worse
3160      than the current objective cutoff.
3161    */
3162    if (solver_->getRowCutDebuggerAlways()) {
3163        OsiRowCutDebugger * debuggerX = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
3164        const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
3165        if (!debugger) {
3166            // infeasible!!
3167            printf("before search\n");
3168            const double * lower = solver_->getColLower();
3169            const double * upper = solver_->getColUpper();
3170            const double * solution = debuggerX->optimalSolution();
3171            int numberColumns = solver_->getNumCols();
3172            for (int i = 0; i < numberColumns; i++) {
3173                if (solver_->isInteger(i)) {
3174                    if (solution[i] < lower[i] - 1.0e-6 || solution[i] > upper[i] + 1.0e-6)
3175                        printf("**** ");
3176                    printf("%d %g <= %g <= %g\n",
3177                           i, lower[i], solution[i], upper[i]);
3178                }
3179            }
3180            //abort();
3181        }
3182    }
3183    {
3184        // may be able to change cutoff now
3185        double cutoff = getCutoff();
3186        double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
3187        if (cutoff > bestObjective_ - increment) {
3188            cutoff = bestObjective_ - increment ;
3189            setCutoff(cutoff) ;
3190        }
3191    }
3192#ifdef CBC_THREAD
3193    bool goneParallel = false;
3194#endif
3195#define MAX_DEL_NODE 1
3196    CbcNode * delNode[MAX_DEL_NODE+1];
3197    int nDeleteNode = 0;
3198    // For Printing etc when parallel
3199    int lastEvery1000 = 0;
3200    int lastPrintEvery = 0;
3201    while (true) {
3202#ifdef CBC_THREAD
3203        if (parallelMode() > 0 && !locked) {
3204            lockThread();
3205            locked = true;
3206        }
3207#endif
3208#ifdef COIN_HAS_CLP
3209        // Possible change of pivot method
3210        if (!savePivotMethod && !parentModel_) {
3211            OsiClpSolverInterface * clpSolver
3212            = dynamic_cast<OsiClpSolverInterface *> (solver_);
3213            if (clpSolver && numberNodes_ >= 100 && numberNodes_ < 200) {
3214                if (numberIterations_ < (numberSolves_ + numberNodes_)*10) {
3215                    //if (numberIterations_<numberNodes_*20) {
3216                    ClpSimplex * simplex = clpSolver->getModelPtr();
3217                    ClpDualRowPivot * pivotMethod = simplex->dualRowPivot();
3218                    ClpDualRowDantzig * pivot =
3219                        dynamic_cast< ClpDualRowDantzig*>(pivotMethod);
3220                    if (!pivot) {
3221                        savePivotMethod = pivotMethod->clone(true);
3222                        ClpDualRowDantzig dantzig;
3223                        simplex->setDualRowPivotAlgorithm(dantzig);
3224#ifdef COIN_DEVELOP
3225                        printf("%d node, %d iterations ->Dantzig\n", numberNodes_,
3226                               numberIterations_);
3227#endif
3228#ifdef CBC_THREAD
3229                        for (int i = 0; i < numberThreads_; i++) {
3230                            threadInfo[i].dantzigState = -1;
3231                        }
3232#endif
3233                    }
3234                }
3235            }
3236        }
3237#endif
3238        if (tree_->empty()) {
3239#ifdef CBC_THREAD
3240            if (parallelMode() > 0) {
3241#ifdef COIN_DEVELOP
3242                printf("empty\n");
3243#endif
3244                // may still be outstanding nodes
3245                int iThread;
3246                for (iThread = 0; iThread < numberThreads_; iThread++) {
3247                    if (threadId[iThread].status) {
3248                        if (threadInfo[iThread].returnCode == 0)
3249                            break;
3250                    }
3251                }
3252                if (iThread < numberThreads_) {
3253#ifdef COIN_DEVELOP
3254                    printf("waiting for thread %d code 0\n", iThread);
3255#endif
3256                    if (parallelMode() > 0) {
3257                        unlockThread();
3258                        locked = false;
3259                    }
3260                    pthread_cond_signal(threadInfo[iThread].condition2); // unlock in case
3261                    while (true) {
3262                        pthread_mutex_lock(&condition_mutex);
3263                        struct timespec absTime;
3264                        my_gettime(&absTime);
3265                        double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3266                        absTime.tv_nsec += 1000000; // millisecond
3267                        if (absTime.tv_nsec >= 1000000000) {
3268                            absTime.tv_nsec -= 1000000000;
3269                            absTime.tv_sec++;
3270                        }
3271                        pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
3272                        my_gettime(&absTime);
3273                        double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3274                        timeWaiting += time2 - time;
3275                        pthread_mutex_unlock(&condition_mutex);
3276                        if (threadInfo[iThread].returnCode != 0)
3277                            break;
3278                        pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3279                    }
3280                    threadModel[iThread]->moveToModel(this, 1);
3281                    assert (threadInfo[iThread].returnCode == 1);
3282                    if (threadInfo[iThread].dantzigState == -1) {
3283                        // 0 unset, -1 waiting to be set, 1 set
3284                        threadInfo[iThread].dantzigState = 1;
3285                        CbcModel * model = threadInfo[iThread].thisModel;
3286                        OsiClpSolverInterface * clpSolver2
3287                        = dynamic_cast<OsiClpSolverInterface *> (model->solver());
3288                        assert (clpSolver2);
3289                        ClpSimplex * simplex2 = clpSolver2->getModelPtr();
3290                        ClpDualRowDantzig dantzig;
3291                        simplex2->setDualRowPivotAlgorithm(dantzig);
3292                    }
3293                    // say available
3294                    threadInfo[iThread].returnCode = -1;
3295                    threadStats[4]++;
3296#ifdef COIN_DEVELOP
3297                    printf("thread %d code now -1\n", iThread);
3298#endif
3299                    continue;
3300                } else {
3301#ifdef COIN_DEVELOP
3302                    printf("no threads at code 0 \n");
3303#endif
3304                    // now check if any have just finished
3305                    for (iThread = 0; iThread < numberThreads_; iThread++) {
3306                        if (threadId[iThread].status) {
3307                            if (threadInfo[iThread].returnCode == 1)
3308                                break;
3309                        }
3310                    }
3311                    if (iThread < numberThreads_) {
3312                        if (parallelMode() > 0) {
3313                            unlockThread();
3314                            locked = false;
3315                        }
3316                        threadModel[iThread]->moveToModel(this, 1);
3317                        assert (threadInfo[iThread].returnCode == 1);
3318                        // say available
3319                        threadInfo[iThread].returnCode = -1;
3320                        threadStats[4]++;
3321#ifdef COIN_DEVELOP
3322                        printf("thread %d code now -1\n", iThread);
3323#endif
3324                        continue;
3325                    }
3326                }
3327                if (!tree_->empty()) {
3328#ifdef COIN_DEVELOP
3329                    printf("tree not empty!!!!!!\n");
3330#endif
3331                    continue;
3332                }
3333                for (iThread = 0; iThread < numberThreads_; iThread++) {
3334                    if (threadId[iThread].status) {
3335                        if (threadInfo[iThread].returnCode != -1) {
3336                            printf("bad end of tree\n");
3337                            abort();
3338                        }
3339                    }
3340                }
3341#ifdef COIN_DEVELOP
3342                printf("finished ************\n");
3343#endif
3344                unlockThread();
3345                locked = false; // not needed as break
3346            }
3347#endif
3348            break;
3349        }
3350#ifdef CBC_THREAD
3351        if (parallelMode() > 0) {
3352            unlockThread();
3353            locked = false;
3354        }
3355#endif
3356        // If done 100 nodes see if worth trying reduction
3357        if (numberNodes_ == 50 || numberNodes_ == 100) {
3358#ifdef COIN_HAS_CLP
3359            OsiClpSolverInterface * clpSolver
3360            = dynamic_cast<OsiClpSolverInterface *> (solver_);
3361            if (clpSolver && ((specialOptions_&131072) == 0) && true) {
3362                ClpSimplex * simplex = clpSolver->getModelPtr();
3363                int perturbation = simplex->perturbation();
3364#ifdef CLP_INVESTIGATE
3365                printf("Testing its n,s %d %d solves n,s %d %d - pert %d\n",
3366                       numberIterations_, saveNumberIterations,
3367                       numberSolves_, saveNumberSolves, perturbation);
3368#endif
3369                if (perturbation == 50 && (numberIterations_ - saveNumberIterations) <
3370                        8*(numberSolves_ - saveNumberSolves)) {
3371                    // switch off perturbation
3372                    simplex->setPerturbation(100);
3373#ifdef PERTURB_IN_FATHOM
3374                    // but allow in fathom
3375                    specialOptions_ |= 131072;
3376#endif
3377#ifdef CLP_INVESTIGATE
3378                    printf("Perturbation switched off\n");
3379#endif
3380                }
3381            }
3382#endif
3383            if (saveSolver) {
3384                bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() &&
3385                                    (getCutoff() < 1.0e20 && getCutoff() < checkCutoffForRestart);
3386                int numberColumns = getNumCols();
3387                if (tryNewSearch) {
3388                    checkCutoffForRestart = getCutoff() ;
3389#ifdef CLP_INVESTIGATE
3390                    printf("after %d nodes, cutoff %g - looking\n",
3391                           numberNodes_, getCutoff());
3392#endif
3393                    saveSolver->resolve();
3394                    double direction = saveSolver->getObjSense() ;
3395                    double gap = checkCutoffForRestart - saveSolver->getObjValue() * direction ;
3396                    double tolerance;
3397                    saveSolver->getDblParam(OsiDualTolerance, tolerance) ;
3398                    if (gap <= 0.0)
3399                        gap = tolerance;
3400                    gap += 100.0 * tolerance;
3401                    double integerTolerance = getDblParam(CbcIntegerTolerance) ;
3402
3403                    const double *lower = saveSolver->getColLower() ;
3404                    const double *upper = saveSolver->getColUpper() ;
3405                    const double *solution = saveSolver->getColSolution() ;
3406                    const double *reducedCost = saveSolver->getReducedCost() ;
3407
3408                    int numberFixed = 0 ;
3409                    int numberFixed2 = 0;
3410#ifdef COIN_DEVELOP
3411                    printf("gap %g\n", gap);
3412#endif
3413                    for (int i = 0 ; i < numberIntegers_ ; i++) {
3414                        int iColumn = integerVariable_[i] ;
3415                        double djValue = direction * reducedCost[iColumn] ;
3416                        if (upper[iColumn] - lower[iColumn] > integerTolerance) {
3417                            if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
3418                                //printf("%d to lb on dj of %g - bounds %g %g\n",
3419                                //     iColumn,djValue,lower[iColumn],upper[iColumn]);
3420                                saveSolver->setColUpper(iColumn, lower[iColumn]) ;
3421                                numberFixed++ ;
3422                            } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
3423                                //printf("%d to ub on dj of %g - bounds %g %g\n",
3424                                //     iColumn,djValue,lower[iColumn],upper[iColumn]);
3425                                saveSolver->setColLower(iColumn, upper[iColumn]) ;
3426                                numberFixed++ ;
3427                            }
3428                        } else {
3429                            //printf("%d has dj of %g - already fixed to %g\n",
3430                            //     iColumn,djValue,lower[iColumn]);
3431                            numberFixed2++;
3432                        }
3433                    }
3434#ifdef COIN_DEVELOP
3435                    if ((specialOptions_&1) != 0) {
3436                        const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ;
3437                        if (debugger) {
3438                            printf("Contains optimal\n") ;
3439                            OsiSolverInterface * temp = saveSolver->clone();
3440                            const double * solution = debugger->optimalSolution();
3441                            const double *lower = temp->getColLower() ;
3442                            const double *upper = temp->getColUpper() ;
3443                            int n = temp->getNumCols();
3444                            for (int i = 0; i < n; i++) {
3445                                if (temp->isInteger(i)) {
3446                                    double value = floor(solution[i] + 0.5);
3447                                    assert (value >= lower[i] && value <= upper[i]);
3448                                    temp->setColLower(i, value);
3449                                    temp->setColUpper(i, value);
3450                                }
3451                            }
3452                            temp->writeMps("reduced_fix");
3453                            delete temp;
3454                            saveSolver->writeMps("reduced");
3455                        } else {
3456                            abort();
3457                        }
3458                    }
3459                    printf("Restart could fix %d integers (%d already fixed)\n",
3460                           numberFixed + numberFixed2, numberFixed2);
3461#endif
3462                    numberFixed += numberFixed2;
3463                    if (numberFixed*10 < numberColumns)
3464                        tryNewSearch = false;
3465                }
3466                if (tryNewSearch) {
3467                    // back to solver without cuts?
3468                    OsiSolverInterface * solver2 = saveSolver->clone();
3469                    const double *lower = saveSolver->getColLower() ;
3470                    const double *upper = saveSolver->getColUpper() ;
3471                    for (int i = 0 ; i < numberIntegers_ ; i++) {
3472                        int iColumn = integerVariable_[i] ;
3473                        solver2->setColLower(iColumn, lower[iColumn]);
3474                        solver2->setColUpper(iColumn, upper[iColumn]);
3475                    }
3476                    // swap
3477                    delete saveSolver;
3478                    saveSolver = solver2;
3479                    double * newSolution = new double[numberColumns];
3480                    double objectiveValue = checkCutoffForRestart;
3481                    CbcSerendipity heuristic(*this);
3482                    if (bestSolution_)
3483                        heuristic.setInputSolution(bestSolution_, bestObjective_);
3484                    heuristic.setFractionSmall(0.6);
3485                    heuristic.setFeasibilityPumpOptions(1008013);
3486                    // Use numberNodes to say how many are original rows
3487                    heuristic.setNumberNodes(continuousSolver_->getNumRows());
3488#ifdef COIN_DEVELOP
3489                    if (continuousSolver_->getNumRows() <
3490                            solver_->getNumRows())
3491                        printf("%d rows added ZZZZZ\n",
3492                               solver_->getNumRows() - continuousSolver_->getNumRows());
3493#endif
3494                    int returnCode = heuristic.smallBranchAndBound(saveSolver,
3495                                     -1, newSolution,
3496                                     objectiveValue,
3497                                     checkCutoffForRestart, "Reduce");
3498                    if (returnCode < 0) {
3499#ifdef COIN_DEVELOP
3500                        printf("Restart - not small enough to do search after fixing\n");
3501#endif
3502                        delete [] newSolution;
3503                    } else {
3504                        if ((returnCode&1) != 0) {
3505                            // increment number of solutions so other heuristics can test
3506                            numberSolutions_++;
3507                            numberHeuristicSolutions_++;
3508                            lastHeuristic_ = NULL;
3509                            setBestSolution(CBC_ROUNDING, objectiveValue, newSolution) ;
3510                        }
3511                        delete [] newSolution;
3512                        if (tree_->size()) {
3513                            double dummyBest;
3514                            tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
3515                        }
3516                        break;
3517                    }
3518                }
3519                delete saveSolver;
3520                saveSolver = NULL;
3521            }
3522        }
3523        /*
3524          Check for abort on limits: node count, solution count, time, integrality gap.
3525        */
3526        if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
3527                numberSolutions_ < intParam_[CbcMaxNumSol] &&
3528                !maximumSecondsReached() &&
3529                !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 ||
3530                                                      numberIterations_ < maximumNumberIterations_))) {
3531            // out of loop
3532            break;
3533        }
3534#ifdef BONMIN
3535        assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible());
3536#endif
3537        if (cutoff > getCutoff()) {
3538            double newCutoff = getCutoff();
3539            if (analyzeResults_) {
3540                // see if we could fix any (more)
3541                int n = 0;
3542                double * newLower = analyzeResults_;
3543                double * objLower = newLower + numberIntegers_;
3544                double * newUpper = objLower + numberIntegers_;
3545                double * objUpper = newUpper + numberIntegers_;
3546                for (int i = 0; i < numberIntegers_; i++) {
3547                    if (objLower[i] > newCutoff) {
3548                        n++;
3549                        if (objUpper[i] > newCutoff) {
3550                            newCutoff = -COIN_DBL_MAX;
3551                            break;
3552                        }
3553                    } else if (objUpper[i] > newCutoff) {
3554                        n++;
3555                    }
3556                }
3557                if (newCutoff == -COIN_DBL_MAX) {
3558                    printf("Root analysis says finished\n");
3559                } else if (n > numberFixedNow_) {
3560                    printf("%d more fixed by analysis - now %d\n", n - numberFixedNow_, n);
3561                    numberFixedNow_ = n;
3562                }
3563            }
3564            if (eventHandler) {
3565                if (!eventHandler->event(CbcEventHandler::solution)) {
3566                    eventHappened_ = true; // exit
3567                }
3568                newCutoff = getCutoff();
3569            }
3570            if (parallelMode() > 0)
3571                lockThread();
3572            // Do from deepest
3573            tree_->cleanTree(this, newCutoff, bestPossibleObjective_) ;
3574            nodeCompare_->newSolution(this) ;
3575            nodeCompare_->newSolution(this, continuousObjective_,
3576                                      continuousInfeasibilities_) ;
3577            tree_->setComparison(*nodeCompare_) ;
3578            if (tree_->empty()) {
3579                if (parallelMode() > 0)
3580                    unlockThread();
3581                // For threads we need to check further
3582                //break; // finished
3583                continue;
3584            }
3585            if (parallelMode() > 0)
3586                unlockThread();
3587        }
3588        cutoff = getCutoff() ;
3589        /*
3590            Periodic activities: Opportunities to
3591            + tweak the nodeCompare criteria,
3592            + check if we've closed the integrality gap enough to quit,
3593            + print a summary line to let the user know we're working
3594        */
3595        if (numberNodes_ >= lastEvery1000) {
3596            if (parallelMode() > 0)
3597                lockThread();
3598#ifdef COIN_HAS_CLP
3599            // Possible change of pivot method
3600            if (!savePivotMethod && !parentModel_) {
3601                OsiClpSolverInterface * clpSolver
3602                = dynamic_cast<OsiClpSolverInterface *> (solver_);
3603                if (clpSolver && numberNodes_ >= 1000 && numberNodes_ < 2000) {
3604                    if (numberIterations_ < (numberSolves_ + numberNodes_)*10) {
3605                        ClpSimplex * simplex = clpSolver->getModelPtr();
3606                        ClpDualRowPivot * pivotMethod = simplex->dualRowPivot();
3607                        ClpDualRowDantzig * pivot =
3608                            dynamic_cast< ClpDualRowDantzig*>(pivotMethod);
3609                        if (!pivot) {
3610                            savePivotMethod = pivotMethod->clone(true);
3611                            ClpDualRowDantzig dantzig;
3612                            simplex->setDualRowPivotAlgorithm(dantzig);
3613#ifdef COIN_DEVELOP
3614                            printf("%d node, %d iterations ->Dantzig\n", numberNodes_,
3615                                   numberIterations_);
3616#endif
3617#ifdef CBC_THREAD
3618                            for (int i = 0; i < numberThreads_; i++) {
3619                                threadInfo[i].dantzigState = -1;
3620                            }
3621#endif
3622                        }
3623                    }
3624                }
3625            }
3626#endif
3627            lastEvery1000 = numberNodes_ + 1000;
3628            bool redoTree = nodeCompare_->every1000Nodes(this, numberNodes_) ;
3629#ifdef CHECK_CUT_SIZE
3630            verifyCutSize (tree_, *this);
3631#endif
3632            // redo tree if wanted
3633            if (redoTree)
3634                tree_->setComparison(*nodeCompare_) ;
3635            if (parallelMode() > 0)
3636                unlockThread();
3637        }
3638        if (saveCompare && !hotstartSolution_) {
3639            // hotstart switched off
3640            delete nodeCompare_; // off depth first
3641            nodeCompare_ = saveCompare;
3642            saveCompare = NULL;
3643            // redo tree
3644            if (parallelMode() > 0)
3645                lockThread();
3646            tree_->setComparison(*nodeCompare_) ;
3647            if (parallelMode() > 0)
3648                unlockThread();
3649        }
3650        if (numberNodes_ >= lastPrintEvery) {
3651            lastPrintEvery = numberNodes_ + printFrequency_;
3652            if (parallelMode() > 0)
3653                lockThread();
3654            int nNodes = tree_->size() ;
3655
3656            //MODIF PIERRE
3657            bestPossibleObjective_ = tree_->getBestPossibleObjective();
3658            if (parallelMode() > 0)
3659                unlockThread();
3660#ifdef CLP_INVESTIGATE
3661            if (getCutoff() < 1.0e20) {
3662                if (fabs(getCutoff() - (bestObjective_ - getCutoffIncrement())) > 1.0e-6 &&
3663                        !parentModel_)
3664                    printf("model cutoff in status %g, best %g, increment %g\n",
3665                           getCutoff(), bestObjective_, getCutoffIncrement());
3666                assert (getCutoff() < bestObjective_ - getCutoffIncrement() +
3667                        1.0e-6 + 1.0e-10*fabs(bestObjective_));
3668            }
3669#endif
3670            if (!intParam_[CbcPrinting]) {
3671                messageHandler()->message(CBC_STATUS, messages())
3672                << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3673                << getCurrentSeconds()
3674                << CoinMessageEol ;
3675            } else if (intParam_[CbcPrinting] == 1) {
3676                messageHandler()->message(CBC_STATUS2, messages())
3677                << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3678                << lastDepth << lastUnsatisfied << numberIterations_
3679                << getCurrentSeconds()
3680                << CoinMessageEol ;
3681            } else if (!numberExtraIterations_) {
3682                messageHandler()->message(CBC_STATUS2, messages())
3683                << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3684                << lastDepth << lastUnsatisfied << numberIterations_
3685                << getCurrentSeconds()
3686                << CoinMessageEol ;
3687            } else {
3688                messageHandler()->message(CBC_STATUS3, messages())
3689                << numberNodes_ << numberExtraNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3690                << lastDepth << lastUnsatisfied << numberIterations_ << numberExtraIterations_
3691                << getCurrentSeconds()
3692                << CoinMessageEol ;
3693            }
3694            if (eventHandler && !eventHandler->event(CbcEventHandler::treeStatus)) {
3695                eventHappened_ = true; // exit
3696            }
3697        }
3698        // See if can stop on gap
3699        double testGap = CoinMax(dblParam_[CbcAllowableGap],
3700                                 CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
3701                                 * dblParam_[CbcAllowableFractionGap]);
3702        if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0) {
3703            stoppedOnGap_ = true ;
3704        }
3705
3706#ifdef CHECK_NODE_FULL
3707        verifyTreeNodes(tree_, *this) ;
3708#   endif
3709#   ifdef CHECK_CUT_COUNTS
3710        verifyCutCounts(tree_, *this) ;
3711#   endif
3712        /*
3713          Now we come to the meat of the loop. To create the active subproblem, we'll
3714          pop the most promising node in the live set, rebuild the subproblem it
3715          represents, and then execute the current arm of the branch to create the
3716          active subproblem.
3717        */
3718        CbcNode * node = NULL;
3719#ifdef CBC_THREAD
3720        if (!parallelMode() || parallelMode() == -1) {
3721#endif
3722            node = tree_->bestNode(cutoff) ;
3723            // Possible one on tree worse than cutoff
3724            if (!node || node->objectiveValue() > cutoff)
3725                continue;
3726            // Do main work of solving node here
3727            doOneNode(this, node, createdNode);
3728#ifdef CBC_THREAD
3729        } else if (parallelMode() > 0) {
3730            node = tree_->bestNode(cutoff) ;
3731            // Possible one on tree worse than cutoff
3732            if (!node || node->objectiveValue() > cutoff)
3733                continue;
3734            threadStats[0]++;
3735            //need to think
3736            int iThread;
3737            // Start one off if any available
3738            for (iThread = 0; iThread < numberThreads_; iThread++) {
3739                if (threadInfo[iThread].returnCode == -1)
3740                    break;
3741            }
3742            if (iThread < numberThreads_) {
3743                threadInfo[iThread].node = node;
3744                assert (threadInfo[iThread].returnCode == -1);
3745                // say in use
3746                threadModel[iThread]->moveToModel(this, 0);
3747                // This has to be AFTER moveToModel
3748                threadInfo[iThread].returnCode = 0;
3749                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3750                threadCount[iThread]++;
3751            }
3752            lockThread();
3753            locked = true;
3754            // see if any finished
3755            for (iThread = 0; iThread < numberThreads_; iThread++) {
3756                if (threadInfo[iThread].returnCode > 0)
3757                    break;
3758            }
3759            unlockThread();
3760            locked = false;
3761            if (iThread < numberThreads_) {
3762                threadModel[iThread]->moveToModel(this, 1);
3763                assert (threadInfo[iThread].returnCode == 1);
3764                // say available
3765                threadInfo[iThread].returnCode = -1;
3766                // carry on
3767                threadStats[3]++;
3768            } else {
3769                // Start one off if any available
3770                for (iThread = 0; iThread < numberThreads_; iThread++) {
3771                    if (threadInfo[iThread].returnCode == -1)
3772                        break;
3773                }
3774                if (iThread < numberThreads_) {
3775                    lockThread();
3776                    locked = true;
3777                    // If any on tree get
3778                    if (!tree_->empty()) {
3779                        //node = tree_->bestNode(cutoff) ;
3780                        //assert (node);
3781                        threadStats[1]++;
3782                        continue; // ** get another node
3783                    }
3784                    unlockThread();
3785                    locked = false;
3786                }
3787                // wait (for debug could sleep and use test)
3788                bool finished = false;
3789                while (!finished) {
3790                    pthread_mutex_lock(&condition_mutex);
3791                    struct timespec absTime;
3792                    my_gettime(&absTime);
3793                    double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3794                    absTime.tv_nsec += 1000000; // millisecond
3795                    if (absTime.tv_nsec >= 1000000000) {
3796                        absTime.tv_nsec -= 1000000000;
3797                        absTime.tv_sec++;
3798                    }
3799                    pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
3800                    my_gettime(&absTime);
3801                    double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3802                    timeWaiting += time2 - time;
3803                    pthread_mutex_unlock(&condition_mutex);
3804                    for (iThread = 0; iThread < numberThreads_; iThread++) {
3805                        if (threadInfo[iThread].returnCode > 0) {
3806                            finished = true;
3807                            break;
3808                        } else if (threadInfo[iThread].returnCode == 0) {
3809                            pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3810                        }
3811                    }
3812                }
3813                assert (iThread < numberThreads_);
3814                // move information to model
3815                threadModel[iThread]->moveToModel(this, 1);
3816                node = threadInfo[iThread].node;
3817                threadInfo[iThread].node = NULL;
3818                assert (threadInfo[iThread].returnCode == 1);
3819                // say available
3820                threadInfo[iThread].returnCode = -1;
3821                // carry on
3822                threadStats[2]++;
3823            }
3824        } else {
3825            // Deterministic parallel
3826            if (tree_->size() < CoinMin(numberThreads_, 8) && !goneParallel) {
3827                node = tree_->bestNode(cutoff) ;
3828                // Possible one on tree worse than cutoff
3829                if (!node || node->objectiveValue() > cutoff)
3830                    continue;
3831                // Do main work of solving node here
3832                doOneNode(this, node, createdNode);
3833                assert (createdNode);
3834                if (!createdNode->active()) {
3835                    delete createdNode;
3836                    createdNode = NULL;
3837                } else {
3838                    // Say one more pointing to this
3839                    node->nodeInfo()->increment() ;
3840                    tree_->push(createdNode) ;
3841                }
3842                if (node->active()) {
3843                    assert (node->nodeInfo());
3844                    if (node->nodeInfo()->numberBranchesLeft()) {
3845                        tree_->push(node) ;
3846                    } else {
3847                        node->setActive(false);
3848                    }
3849                } else {
3850                    if (node->nodeInfo()) {
3851                        if (!node->nodeInfo()->numberBranchesLeft())
3852                            node->nodeInfo()->allBranchesGone(); // can clean up
3853                        // So will delete underlying stuff
3854                        node->setActive(true);
3855                    }
3856                    delNode[nDeleteNode++] = node;
3857                    node = NULL;
3858                }
3859                if (nDeleteNode >= MAX_DEL_NODE) {
3860                    for (int i = 0; i < nDeleteNode; i++) {
3861                        //printf("trying to del %d %x\n",i,delNode[i]);
3862                        delete delNode[i];
3863                        //printf("done to del %d %x\n",i,delNode[i]);
3864                    }
3865                    nDeleteNode = 0;
3866                }
3867            } else {
3868                // Split
3869                int saveTreeSize = tree_->size();
3870                goneParallel = true;
3871                int nAffected = splitModel(numberThreads_, threadModel, defaultParallelNodes);
3872                int iThread;
3873                // do all until finished
3874                for (iThread = 0; iThread < numberThreads_; iThread++) {
3875                    // obviously tune
3876                    threadInfo[iThread].nDeleteNode = defaultParallelIterations;
3877                }
3878                // Save current state
3879                int iObject;
3880                for (iObject = 0; iObject < numberObjects_; iObject++) {
3881                    saveObjects[iObject]->updateBefore(object_[iObject]);
3882                }
3883                for (iThread = 0; iThread < numberThreads_; iThread++) {
3884                    threadInfo[iThread].returnCode = 0;
3885                    pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3886                }
3887                // wait
3888                bool finished = false;
3889                while (!finished) {
3890                    pthread_mutex_lock(&condition_mutex);
3891                    struct timespec absTime;
3892                    my_gettime(&absTime);
3893                    double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3894                    absTime.tv_nsec += 1000000; // millisecond
3895                    if (absTime.tv_nsec >= 1000000000) {
3896                        absTime.tv_nsec -= 1000000000;
3897                        absTime.tv_sec++;
3898                    }
3899                    pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
3900                    my_gettime(&absTime);
3901                    double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3902                    timeWaiting += time2 - time;
3903                    pthread_mutex_unlock(&condition_mutex);
3904                    finished = true;
3905                    for (iThread = 0; iThread < numberThreads_; iThread++) {
3906                        if (threadInfo[iThread].returnCode <= 0) {
3907                            finished = false;
3908                        }
3909                    }
3910                }
3911                // Unmark marked
3912                for (int i = 0; i < nAffected; i++) {
3913                    walkback_[i]->unmark();
3914                }
3915                int iModel;
3916                double scaleFactor = 1.0;
3917                for (iModel = 0; iModel < numberThreads_; iModel++) {
3918                    //printf("model %d tree size %d\n",iModel,threadModel[iModel]->tree_->size());
3919                    if (saveTreeSize > 4*numberThreads_*defaultParallelNodes) {
3920                        if (!threadModel[iModel]->tree_->size()) {
3921                            scaleFactor *= 1.05;
3922                        }
3923                    }
3924                    threadModel[iModel]->moveToModel(this, 11);
3925                    // Update base model
3926                    OsiObject ** threadObject = threadModel[iModel]->object_;
3927                    for (iObject = 0; iObject < numberObjects_; iObject++) {
3928                        object_[iObject]->updateAfter(threadObject[iObject], saveObjects[iObject]);
3929                    }
3930                }
3931                if (scaleFactor != 1.0) {
3932                    int newNumber = static_cast<int> (defaultParallelNodes * scaleFactor + 0.5001);
3933                    if (newNumber*2 < defaultParallelIterations) {
3934                        if (defaultParallelNodes == 1)
3935                            newNumber = 2;
3936                        if (newNumber != defaultParallelNodes) {
3937                            char general[200];
3938                            sprintf(general, "Changing tree size from %d to %d",
3939                                    defaultParallelNodes, newNumber);
3940                            messageHandler()->message(CBC_GENERAL,
3941                                                      messages())
3942                            << general << CoinMessageEol ;
3943                            defaultParallelNodes = newNumber;
3944                        }
3945                    }
3946                }
3947                //printf("Tree sizes %d %d %d - affected %d\n",saveTreeSize,saveTreeSize2,tree_->size(),nAffected);
3948            }
3949        }
3950#endif
3951    }
3952    if (nDeleteNode) {
3953        for (int i = 0; i < nDeleteNode; i++) {
3954            delete delNode[i];
3955        }
3956        nDeleteNode = 0;
3957    }
3958#ifdef CBC_THREAD
3959    if (numberThreads_) {
3960        int i;
3961        // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
3962        double time = 0.0;
3963        for (i = 0; i < numberThreads_; i++)
3964            time += threadInfo[i].timeInThread;
3965        bool goodTimer = time < (getCurrentSeconds());
3966        for (i = 0; i < numberThreads_; i++) {
3967            while (threadInfo[i].returnCode == 0) {
3968                pthread_cond_signal(threadInfo[i].condition2); // unlock
3969                pthread_mutex_lock(&condition_mutex);
3970                struct timespec absTime;
3971                my_gettime(&absTime);
3972                absTime.tv_nsec += 1000000; // millisecond
3973                if (absTime.tv_nsec >= 1000000000) {
3974                    absTime.tv_nsec -= 1000000000;
3975                    absTime.tv_sec++;
3976                }
3977                pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
3978                my_gettime(&absTime);
3979                pthread_mutex_unlock(&condition_mutex);
3980            }
3981            pthread_cond_signal(threadInfo[i].condition2); // unlock
3982            pthread_mutex_lock(&condition_mutex); // not sure necessary but have had one hang on interrupt
3983            threadModel[i]->numberThreads_ = 0; // say exit
3984            if (parallelMode() < 0)
3985                delete [] threadInfo[i].delNode;
3986            threadInfo[i].returnCode = 0;
3987            pthread_mutex_unlock(&condition_mutex);
3988            pthread_cond_signal(threadInfo[i].condition2); // unlock
3989            //if (!stopped)
3990            //pthread_join(threadId[i],NULL);
3991            int returnCode;
3992            returnCode = pthread_join(threadId[i].thr, NULL);
3993            threadId[i].status = 0;
3994            assert (!returnCode);
3995            //else
3996            //pthread_kill(threadId[i]); // kill rather than try and synchronize
3997            threadModel[i]->moveToModel(this, 2);
3998            pthread_mutex_destroy (threadInfo[i].mutex2);
3999            pthread_cond_destroy (threadInfo[i].condition2);
4000            assert (threadInfo[i].numberTimesLocked == threadInfo[i].numberTimesUnlocked);
4001            handler_->message(CBC_THREAD_STATS, messages_)
4002            << "Thread";
4003            handler_->printing(true)
4004            << i << threadCount[i] << threadInfo[i].timeWaitingToStart;
4005            handler_->printing(goodTimer) << threadInfo[i].timeInThread;
4006            handler_->printing(false) << 0.0;
4007            handler_->printing(true) << threadInfo[i].numberTimesLocked
4008            << threadInfo[i].timeLocked << threadInfo[i].timeWaitingToLock
4009            << CoinMessageEol;
4010        }
4011        assert (threadInfo[numberThreads_].numberTimesLocked == threadInfo[numberThreads_].numberTimesUnlocked);
4012        handler_->message(CBC_THREAD_STATS, messages_)
4013        << "Main thread";
4014        handler_->printing(false) << 0 << 0 << 0.0;
4015        handler_->printing(false) << 0.0;
4016        handler_->printing(true) << timeWaiting;
4017        handler_->printing(true) << threadInfo[numberThreads_].numberTimesLocked
4018        << threadInfo[numberThreads_].timeLocked << threadInfo[numberThreads_].timeWaitingToLock
4019        << CoinMessageEol;
4020        pthread_mutex_destroy (&mutex);
4021        pthread_cond_destroy (&condition_main);
4022        pthread_mutex_destroy (&condition_mutex);
4023        // delete models (here in case some point to others)
4024        for (i = 0; i < numberThreads_; i++) {
4025            // make sure handler will be deleted
4026            threadModel[i]->defaultHandler_ = true;
4027            delete threadModel[i];
4028        }
4029        delete [] mutex2;
4030        delete [] condition2;
4031        delete [] threadId;
4032        delete [] threadInfo;
4033        delete [] threadModel;
4034        delete [] threadCount;
4035        mutex_ = NULL;
4036        // adjust time to allow for children on some systems
4037        dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren();
4038    }
4039#endif
4040    /*
4041      End of the non-abort actions. The next block of code is executed if we've
4042      aborted because we hit one of the limits. Clean up by deleting the live set
4043      and break out of the node processing loop. Note that on an abort, node may
4044      have been pushed back onto the tree for further processing, in which case
4045      it'll be deleted in cleanTree. We need to check.
4046    */
4047    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
4048            numberSolutions_ < intParam_[CbcMaxNumSol] &&
4049            !maximumSecondsReached() &&
4050            !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 ||
4051                                                  numberIterations_ < maximumNumberIterations_))) {
4052        if (tree_->size()) {
4053            double dummyBest;
4054            tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
4055        }
4056        delete nextRowCut_;
4057        if (stoppedOnGap_) {
4058            messageHandler()->message(CBC_GAP, messages())
4059            << bestObjective_ - bestPossibleObjective_
4060            << dblParam_[CbcAllowableGap]
4061            << dblParam_[CbcAllowableFractionGap]*100.0
4062            << CoinMessageEol ;
4063            secondaryStatus_ = 2;
4064            status_ = 0 ;
4065        } else if (isNodeLimitReached()) {
4066            handler_->message(CBC_MAXNODES, messages_) << CoinMessageEol ;
4067            secondaryStatus_ = 3;
4068            status_ = 1 ;
4069        } else if (maximumSecondsReached()) {
4070            handler_->message(CBC_MAXTIME, messages_) << CoinMessageEol ;
4071            secondaryStatus_ = 4;
4072            status_ = 1 ;
4073        } else if (eventHappened_) {
4074            handler_->message(CBC_EVENT, messages_) << CoinMessageEol ;
4075            secondaryStatus_ = 5;
4076            status_ = 5 ;
4077        } else {
4078            handler_->message(CBC_MAXSOLS, messages_) << CoinMessageEol ;
4079            secondaryStatus_ = 6;
4080            status_ = 1 ;
4081        }
4082    }
4083    /*
4084      That's it, we've exhausted the search tree, or broken out of the loop because
4085      we hit some limit on evaluation.
4086
4087      We may have got an intelligent tree so give it one more chance
4088    */
4089    // Tell solver we are not in Branch and Cut
4090    solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ;
4091    tree_->endSearch();
4092    //  If we did any sub trees - did we give up on any?
4093    if ( numberStoppedSubTrees_)
4094        status_ = 1;
4095    numberNodes_ += numberExtraNodes_;
4096    numberIterations_ += numberExtraIterations_;
4097    if (eventHandler) {
4098        eventHandler->event(CbcEventHandler::endSearch);
4099    }
4100    if (!status_) {
4101        // Set best possible unless stopped on gap
4102        if (secondaryStatus_ != 2)
4103            bestPossibleObjective_ = bestObjective_;
4104        handler_->message(CBC_END_GOOD, messages_)
4105        << bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds()
4106        << CoinMessageEol ;
4107    } else {
4108        handler_->message(CBC_END, messages_)
4109        << bestObjective_ << bestPossibleObjective_
4110        << numberIterations_ << numberNodes_ << getCurrentSeconds()
4111        << CoinMessageEol ;
4112    }
4113    if (numberStrongIterations_)
4114        handler_->message(CBC_STRONG_STATS, messages_)
4115        << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2]
4116        << strongInfo_[1] << CoinMessageEol ;
4117    if (!numberExtraNodes_)
4118        handler_->message(CBC_OTHER_STATS, messages_)
4119        << maximumDepthActual_
4120        << numberDJFixed_ << CoinMessageEol ;
4121    else
4122        handler_->message(CBC_OTHER_STATS2, messages_)
4123        << maximumDepthActual_
4124        << numberDJFixed_ << numberExtraNodes_ << numberExtraIterations_
4125        << CoinMessageEol ;
4126    if (doStatistics == 100) {
4127        for (int i = 0; i < numberObjects_; i++) {
4128            CbcSimpleIntegerDynamicPseudoCost * obj =
4129                dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
4130            if (obj)
4131                obj->print();
4132        }
4133    }
4134    if (statistics_) {
4135        // report in some way
4136        int * lookup = new int[numberObjects_];
4137        int i;
4138        for (i = 0; i < numberObjects_; i++)
4139            lookup[i] = -1;
4140        bool goodIds = false; //true;
4141        for (i = 0; i < numberObjects_; i++) {
4142            int iColumn = object_[i]->columnNumber();
4143            if (iColumn >= 0 && iColumn < numberColumns) {
4144                if (lookup[i] == -1) {
4145                    lookup[i] = iColumn;
4146                } else {
4147                    goodIds = false;
4148                    break;
4149                }
4150            } else {
4151                goodIds = false;
4152                break;
4153            }
4154        }
4155        if (!goodIds) {
4156            delete [] lookup;
4157            lookup = NULL;
4158        }
4159        if (doStatistics >= 3) {
4160            printf("  node parent depth column   value                    obj      inf\n");
4161            for ( i = 0; i < numberNodes2_; i++) {
4162                statistics_[i]->print(lookup);
4163            }
4164        }
4165        if (doStatistics > 1) {
4166            // Find last solution
4167            int k;
4168            for (k = numberNodes2_ - 1; k >= 0; k--) {
4169                if (statistics_[k]->endingObjective() != COIN_DBL_MAX &&
4170                        !statistics_[k]->endingInfeasibility())
4171                    break;
4172            }
4173            if (k >= 0) {
4174                int depth = statistics_[k]->depth();
4175                int * which = new int[depth+1];
4176                for (i = depth; i >= 0; i--) {
4177                    which[i] = k;
4178                    k = statistics_[k]->parentNode();
4179                }
4180                printf("  node parent depth column   value                    obj      inf\n");
4181                for (i = 0; i <= depth; i++) {
4182                    statistics_[which[i]]->print(lookup);
4183                }
4184                delete [] which;
4185            }
4186        }
4187        // now summary
4188        int maxDepth = 0;
4189        double averageSolutionDepth = 0.0;
4190        int numberSolutions = 0;
4191        double averageCutoffDepth = 0.0;
4192        double averageSolvedDepth = 0.0;
4193        int numberCutoff = 0;
4194        int numberDown = 0;
4195        int numberFirstDown = 0;
4196        double averageInfDown = 0.0;
4197        double averageObjDown = 0.0;
4198        int numberCutoffDown = 0;
4199        int numberUp = 0;
4200        int numberFirstUp = 0;
4201        double averageInfUp = 0.0;
4202        double averageObjUp = 0.0;
4203        int numberCutoffUp = 0;
4204        double averageNumberIterations1 = 0.0;
4205        double averageValue = 0.0;
4206        for ( i = 0; i < numberNodes2_; i++) {
4207            int depth =  statistics_[i]->depth();
4208            int way =  statistics_[i]->way();
4209            double value = statistics_[i]->value();
4210            double startingObjective =  statistics_[i]->startingObjective();
4211            int startingInfeasibility = statistics_[i]->startingInfeasibility();
4212            double endingObjective = statistics_[i]->endingObjective();
4213            int endingInfeasibility = statistics_[i]->endingInfeasibility();
4214            maxDepth = CoinMax(depth, maxDepth);
4215            // Only for completed
4216            averageNumberIterations1 += statistics_[i]->numberIterations();
4217            averageValue += value;
4218            if (endingObjective != COIN_DBL_MAX && !endingInfeasibility) {
4219                numberSolutions++;
4220                averageSolutionDepth += depth;
4221            }
4222            if (endingObjective == COIN_DBL_MAX) {
4223                numberCutoff++;
4224                averageCutoffDepth += depth;
4225                if (way < 0) {
4226                    numberDown++;
4227                    numberCutoffDown++;
4228                    if (way == -1)
4229                        numberFirstDown++;
4230                } else {
4231                    numberUp++;
4232                    numberCutoffUp++;
4233                    if (way == 1)
4234                        numberFirstUp++;
4235                }
4236            } else {
4237                averageSolvedDepth += depth;
4238                if (way < 0) {
4239                    numberDown++;
4240                    averageInfDown += startingInfeasibility - endingInfeasibility;
4241                    averageObjDown += endingObjective - startingObjective;
4242                    if (way == -1)
4243                        numberFirstDown++;
4244                } else {
4245                    numberUp++;
4246                    averageInfUp += startingInfeasibility - endingInfeasibility;
4247                    averageObjUp += endingObjective - startingObjective;
4248                    if (way == 1)
4249                        numberFirstUp++;
4250                }
4251            }
4252        }
4253        // Now print
4254        if (numberSolutions)
4255            averageSolutionDepth /= static_cast<double> (numberSolutions);
4256        int numberSolved = numberNodes2_ - numberCutoff;
4257        double averageNumberIterations2 = numberIterations_ - averageNumberIterations1
4258                                          - numberIterationsAtContinuous;
4259        if (numberCutoff) {
4260            averageCutoffDepth /= static_cast<double> (numberCutoff);
4261            averageNumberIterations2 /= static_cast<double> (numberCutoff);
4262        }
4263        if (numberNodes2_)
4264            averageValue /= static_cast<double> (numberNodes2_);
4265        if (numberSolved) {
4266            averageNumberIterations1 /= static_cast<double> (numberSolved);
4267            averageSolvedDepth /= static_cast<double> (numberSolved);
4268        }
4269        printf("%d solution(s) were found (by branching) at an average depth of %g\n",
4270               numberSolutions, averageSolutionDepth);
4271        printf("average value of variable being branched on was %g\n",
4272               averageValue);
4273        printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n",
4274               numberCutoff, averageCutoffDepth, averageNumberIterations2);
4275        printf("%d nodes were solved at an average depth of %g with iteration count of %g\n",
4276               numberSolved, averageSolvedDepth, averageNumberIterations1);
4277        if (numberDown) {
4278            averageInfDown /= static_cast<double> (numberDown);
4279            averageObjDown /= static_cast<double> (numberDown);
4280        }
4281        printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
4282               numberDown, numberFirstDown, numberDown - numberFirstDown, numberCutoffDown,
4283               averageInfDown, averageObjDown);
4284        if (numberUp) {
4285            averageInfUp /= static_cast<double> (numberUp);
4286            averageObjUp /= static_cast<double> (numberUp);
4287        }
4288        printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
4289               numberUp, numberFirstUp, numberUp - numberFirstUp, numberCutoffUp,
4290               averageInfUp, averageObjUp);
4291        for ( i = 0; i < numberNodes2_; i++)
4292            delete statistics_[i];
4293        delete [] statistics_;
4294        statistics_ = NULL;
4295        maximumStatistics_ = 0;
4296        delete [] lookup;
4297    }
4298    /*
4299      If we think we have a solution, restore and confirm it with a call to
4300      setBestSolution().  We need to reset the cutoff value so as not to fathom
4301      the solution on bounds.  Note that calling setBestSolution( ..., true)
4302      leaves the continuousSolver_ bounds vectors fixed at the solution value.
4303
4304      Running resolve() here is a failsafe --- setBestSolution has already
4305      reoptimised using the continuousSolver_. If for some reason we fail to
4306      prove optimality, run the problem again after instructing the solver to
4307      tell us more.
4308
4309      If all looks good, replace solver_ with continuousSolver_, so that the
4310      outside world will be able to obtain information about the solution using
4311      public methods.
4312    */
4313    if (bestSolution_ && (solverCharacteristics_->solverType() < 2 || solverCharacteristics_->solverType() == 4)) {
4314        setCutoff(1.0e50) ; // As best solution should be worse than cutoff
4315        phase_ = 5;
4316        double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
4317        if ((specialOptions_&4) == 0)
4318            bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve
4319        setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1) ;
4320        continuousSolver_->resolve() ;
4321        if (!continuousSolver_->isProvenOptimal()) {
4322            continuousSolver_->messageHandler()->setLogLevel(2) ;
4323            continuousSolver_->initialSolve() ;
4324        }
4325        delete solver_ ;
4326        // above deletes solverCharacteristics_
4327        solverCharacteristics_ = NULL;
4328        solver_ = continuousSolver_ ;
4329        setPointers(solver_);
4330        continuousSolver_ = NULL ;
4331    }
4332    /*
4333      Clean up dangling objects. continuousSolver_ may already be toast.
4334    */
4335    delete lastws ;
4336    if (saveObjects) {
4337        for (int i = 0; i < numberObjects_; i++)
4338            delete saveObjects[i];
4339        delete [] saveObjects;
4340    }
4341    numberStrong_ = saveNumberStrong;
4342    numberBeforeTrust_ = saveNumberBeforeTrust;
4343    delete [] whichGenerator_ ;
4344    whichGenerator_ = NULL;
4345    delete [] lowerBefore ;
4346    delete [] upperBefore ;
4347    delete [] walkback_ ;
4348    walkback_ = NULL ;
4349    delete [] lastNodeInfo_ ;
4350    lastNodeInfo_ = NULL;
4351    delete [] lastNumberCuts_ ;
4352    lastNumberCuts_ = NULL;
4353    delete [] lastCut_;
4354    lastCut_ = NULL;
4355    delete [] addedCuts_ ;
4356    addedCuts_ = NULL ;
4357    //delete persistentInfo;
4358    // Get rid of characteristics
4359    solverCharacteristics_ = NULL;
4360    if (continuousSolver_) {
4361        delete continuousSolver_ ;
4362        continuousSolver_ = NULL ;
4363    }
4364    /*
4365      Destroy global cuts by replacing with an empty OsiCuts object.
4366    */
4367    globalCuts_ = OsiCuts() ;
4368    if (!bestSolution_) {
4369        // make sure lp solver is infeasible
4370        int numberColumns = solver_->getNumCols();
4371        const double * columnLower = solver_->getColLower();
4372        int iColumn;
4373        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4374            if (solver_->isInteger(iColumn))
4375                solver_->setColUpper(iColumn, columnLower[iColumn]);
4376        }
4377        solver_->initialSolve();
4378    }
4379#ifdef COIN_HAS_CLP
4380    {
4381        OsiClpSolverInterface * clpSolver
4382        = dynamic_cast<OsiClpSolverInterface *> (solver_);
4383        if (clpSolver) {
4384            // Possible restore of pivot method
4385            if (savePivotMethod) {
4386                // model may have changed
4387                savePivotMethod->setModel(NULL);
4388                clpSolver->getModelPtr()->setDualRowPivotAlgorithm(*savePivotMethod);
4389                delete savePivotMethod;
4390            }
4391            clpSolver->setLargestAway(-1.0);
4392        }
4393    }
4394#endif
4395    if (fastNodeDepth_ >= 1000000 && !parentModel_) {
4396        // delete object off end
4397        delete object_[numberObjects_];
4398        fastNodeDepth_ -= 1000000;
4399    }
4400    delete saveSolver;
4401    if (strategy_ && strategy_->preProcessState() > 0) {
4402        // undo preprocessing
4403        CglPreProcess * process = strategy_->process();
4404        assert (process);
4405        int n = originalSolver->getNumCols();
4406        if (bestSolution_) {
4407            delete [] bestSolution_;
4408            bestSolution_ = new double [n];
4409            process->postProcess(*solver_);
4410        }
4411        strategy_->deletePreProcess();
4412        // Solution now back in originalSolver
4413        delete solver_;
4414        solver_ = originalSolver;
4415        if (bestSolution_) {
4416            bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
4417            memcpy(bestSolution_, solver_->getColSolution(), n*sizeof(double));
4418        }
4419        // put back original objects if there were any
4420        if (originalObject) {
4421            int iColumn;
4422            assert (ownObjects_);
4423            for (iColumn = 0; iColumn < numberObjects_; iColumn++)
4424                delete object_[iColumn];
4425            delete [] object_;
4426            numberObjects_ = numberOriginalObjects;
4427            object_ = originalObject;
4428            delete [] integerVariable_;
4429            numberIntegers_ = 0;
4430            for (iColumn = 0; iColumn < n; iColumn++) {
4431                if (solver_->isInteger(iColumn))
4432                    numberIntegers_++;
4433            }
4434            integerVariable_ = new int[numberIntegers_];
4435            numberIntegers_ = 0;
4436            for (iColumn = 0; iColumn < n; iColumn++) {
4437                if (solver_->isInteger(iColumn))
4438                    integerVariable_[numberIntegers_++] = iColumn;
4439            }
4440        }
4441    }
4442#ifdef COIN_HAS_CLP
4443    {
4444        OsiClpSolverInterface * clpSolver
4445        = dynamic_cast<OsiClpSolverInterface *> (solver_);
4446        if (clpSolver)
4447            clpSolver->setFakeObjective(reinterpret_cast<double *> (NULL));
4448    }
4449#endif
4450    moreSpecialOptions_ = saveMoreSpecialOptions;
4451    return ;
4452}
4453
4454
4455// Solve the initial LP relaxation
4456void
4457CbcModel::initialSolve()
4458{
4459    assert (solver_);
4460    // Check if bounds are all integral (as may get messed up later)
4461    checkModel();
4462    if (!solverCharacteristics_) {
4463        OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
4464        if (solverCharacteristics) {
4465            solverCharacteristics_ = solverCharacteristics;
4466        } else {
4467            // replace in solver
4468            OsiBabSolver defaultC;
4469            solver_->setAuxiliaryInfo(&defaultC);
4470            solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
4471        }
4472    }
4473    solverCharacteristics_->setSolver(solver_);
4474    solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
4475    solver_->initialSolve();
4476    solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ;
4477    if (!solver_->isProvenOptimal())
4478        solver_->resolve();
4479    // But set up so Jon Lee will be happy
4480    status_ = -1;
4481    secondaryStatus_ = -1;
4482    originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
4483    delete [] continuousSolution_;
4484    continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
4485                                          solver_->getNumCols());
4486    setPointers(solver_);
4487    solverCharacteristics_ = NULL;
4488}
4489
4490/*! \brief Get an empty basis object
4491
4492  Return an empty CoinWarmStartBasis object with the requested capacity,
4493  appropriate for the current solver. The object is cloned from the object
4494  cached as emptyWarmStart_. If there is no cached object, the routine
4495  queries the solver for a warm start object, empties it, and caches the
4496  result.
4497*/
4498
4499CoinWarmStartBasis *CbcModel::getEmptyBasis (int ns, int na) const
4500
4501{
4502    CoinWarmStartBasis *emptyBasis ;
4503    /*
4504      Acquire an empty basis object, if we don't yet have one.
4505    */
4506    if (emptyWarmStart_ == 0) {
4507        if (solver_ == 0) {
4508            throw CoinError("Cannot construct basis without solver!",
4509                            "getEmptyBasis", "CbcModel") ;
4510        }
4511        emptyBasis =
4512            dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
4513        if (emptyBasis == 0) {
4514            throw CoinError(
4515                "Solver does not appear to use a basis-oriented warm start.",
4516                "getEmptyBasis", "CbcModel") ;
4517        }
4518        emptyBasis->setSize(0, 0) ;
4519        emptyWarmStart_ = dynamic_cast<CoinWarmStart *>(emptyBasis) ;
4520    }
4521    /*
4522      Clone the empty basis object, resize it as requested, and return.
4523    */
4524    emptyBasis = dynamic_cast<CoinWarmStartBasis *>(emptyWarmStart_->clone()) ;
4525    assert(emptyBasis) ;
4526    if (ns != 0 || na != 0) emptyBasis->setSize(ns, na) ;
4527
4528    return (emptyBasis) ;
4529}
4530
4531
4532/** Default Constructor
4533
4534  Creates an empty model without an associated solver.
4535*/
4536CbcModel::CbcModel()
4537
4538        :
4539        solver_(NULL),
4540        ownership_(0x80000000),
4541        continuousSolver_(NULL),
4542        referenceSolver_(NULL),
4543        defaultHandler_(true),
4544        emptyWarmStart_(NULL),
4545        bestObjective_(COIN_DBL_MAX),
4546        bestPossibleObjective_(COIN_DBL_MAX),
4547        sumChangeObjective1_(0.0),
4548        sumChangeObjective2_(0.0),
4549        bestSolution_(NULL),
4550        savedSolutions_(NULL),
4551        currentSolution_(NULL),
4552        testSolution_(NULL),
4553        minimumDrop_(1.0e-4),
4554        numberSolutions_(0),
4555        numberSavedSolutions_(0),
4556        maximumSavedSolutions_(0),
4557        stateOfSearch_(0),
4558        whenCuts_(-1),
4559        hotstartSolution_(NULL),
4560        hotstartPriorities_(NULL),
4561        numberHeuristicSolutions_(0),
4562        numberNodes_(0),
4563        numberNodes2_(0),
4564        numberIterations_(0),
4565        numberSolves_(0),
4566        status_(-1),
4567        secondaryStatus_(-1),
4568        numberIntegers_(0),
4569        numberRowsAtContinuous_(0),
4570        maximumNumberCuts_(0),
4571        phase_(0),
4572        currentNumberCuts_(0),
4573        maximumDepth_(0),
4574        walkback_(NULL),
4575        lastNodeInfo_(NULL),
4576        lastCut_(NULL),
4577        lastDepth_(0),
4578        lastNumberCuts2_(0),
4579        maximumCuts_(0),
4580        lastNumberCuts_(NULL),
4581        addedCuts_(NULL),
4582        nextRowCut_(NULL),
4583        currentNode_(NULL),
4584        integerVariable_(NULL),
4585        integerInfo_(NULL),
4586        continuousSolution_(NULL),
4587        usedInSolution_(NULL),
4588        specialOptions_(0),
4589        moreSpecialOptions_(0),
4590        subTreeModel_(NULL),
4591        numberStoppedSubTrees_(0),
4592        mutex_(NULL),
4593        presolve_(0),
4594        numberStrong_(5),
4595        numberBeforeTrust_(10),
4596        numberPenalties_(20),
4597        stopNumberIterations_(-1),
4598        penaltyScaleFactor_(3.0),
4599        numberAnalyzeIterations_(0),
4600        analyzeResults_(NULL),
4601        numberInfeasibleNodes_(0),
4602        problemType_(0),
4603        printFrequency_(0),
4604        numberCutGenerators_(0),
4605        generator_(NULL),
4606        virginGenerator_(NULL),
4607        numberHeuristics_(0),
4608        heuristic_(NULL),
4609        lastHeuristic_(NULL),
4610# ifdef COIN_HAS_CLP
4611        fastNodeDepth_(-1),
4612#endif
4613        eventHandler_(NULL),
4614        numberObjects_(0),
4615        object_(NULL),
4616        ownObjects_(true),
4617        originalColumns_(NULL),
4618        howOftenGlobalScan_(1),
4619        numberGlobalViolations_(0),
4620        numberExtraIterations_(0),
4621        numberExtraNodes_(0),
4622        continuousObjective_(COIN_DBL_MAX),
4623        originalContinuousObjective_(COIN_DBL_MAX),
4624        continuousInfeasibilities_(COIN_INT_MAX),
4625        maximumCutPassesAtRoot_(20),
4626        maximumCutPasses_(10),
4627        preferredWay_(0),
4628        currentPassNumber_(0),
4629        maximumWhich_(1000),
4630        maximumRows_(0),
4631        currentDepth_(0),
4632        whichGenerator_(NULL),
4633        maximumStatistics_(0),
4634        statistics_(NULL),
4635        maximumDepthActual_(0),
4636        numberDJFixed_(0.0),
4637        probingInfo_(NULL),
4638        numberFixedAtRoot_(0),
4639        numberFixedNow_(0),
4640        stoppedOnGap_(false),
4641        eventHappened_(false),
4642        numberLongStrong_(0),
4643        numberOldActiveCuts_(0),
4644        numberNewCuts_(0),
4645        searchStrategy_(-1),
4646        numberStrongIterations_(0),
4647        resolveAfterTakeOffCuts_(true),
4648        maximumNumberIterations_(-1),
4649        continuousPriority_(COIN_INT_MAX),
4650        numberUpdateItems_(0),
4651        maximumNumberUpdateItems_(0),
4652        updateItems_(NULL),
4653        numberThreads_(0),
4654        threadMode_(0)
4655{
4656    memset(intParam_, 0, sizeof(intParam_));
4657    intParam_[CbcMaxNumNode] = 2147483647;
4658    intParam_[CbcMaxNumSol] = 9999999;
4659
4660    memset(dblParam_, 0, sizeof(dblParam_));
4661    dblParam_[CbcIntegerTolerance] = 1e-6;
4662    dblParam_[CbcCutoffIncrement] = 1e-5;
4663    dblParam_[CbcAllowableGap] = 1.0e-10;
4664    dblParam_[CbcMaximumSeconds] = 1.0e100;
4665    dblParam_[CbcCurrentCutoff] = 1.0e100;
4666    dblParam_[CbcOptimizationDirection] = 1.0;
4667    dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
4668    dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
4669    strongInfo_[0] = 0;
4670    strongInfo_[1] = 0;
4671    strongInfo_[2] = 0;
4672    strongInfo_[3] = 0;
4673    strongInfo_[4] = 0;
4674    strongInfo_[5] = 0;
4675    strongInfo_[6] = 0;
4676    solverCharacteristics_ = NULL;
4677    nodeCompare_ = new CbcCompareDefault();;
4678    problemFeasibility_ = new CbcFeasibilityBase();
4679    tree_ = new CbcTree();
4680    branchingMethod_ = NULL;
4681    cutModifier_ = NULL;
4682    strategy_ = NULL;
4683    parentModel_ = NULL;
4684    cbcColLower_ = NULL;
4685    cbcColUpper_ = NULL;
4686    cbcRowLower_ = NULL;
4687    cbcRowUpper_ = NULL;
4688    cbcColSolution_ = NULL;
4689    cbcRowPrice_ = NULL;
4690    cbcReducedCost_ = NULL;
4691    cbcRowActivity_ = NULL;
4692    appData_ = NULL;
4693    handler_ = new CoinMessageHandler();
4694    handler_->setLogLevel(2);
4695    messages_ = CbcMessage();
4696    //eventHandler_ = new CbcEventHandler() ;
4697}
4698
4699/** Constructor from solver.
4700
4701  Creates a model complete with a clone of the solver passed as a parameter.
4702*/
4703
4704CbcModel::CbcModel(const OsiSolverInterface &rhs)
4705        :
4706        continuousSolver_(NULL),
4707        referenceSolver_(NULL),
4708        defaultHandler_(true),
4709        emptyWarmStart_(NULL),
4710        bestObjective_(COIN_DBL_MAX),
4711        bestPossibleObjective_(COIN_DBL_MAX),
4712        sumChangeObjective1_(0.0),
4713        sumChangeObjective2_(0.0),
4714        minimumDrop_(1.0e-4),
4715        numberSolutions_(0),
4716        numberSavedSolutions_(0),
4717        maximumSavedSolutions_(0),
4718        stateOfSearch_(0),
4719        whenCuts_(-1),
4720        hotstartSolution_(NULL),
4721        hotstartPriorities_(NULL),
4722        numberHeuristicSolutions_(0),
4723        numberNodes_(0),
4724        numberNodes2_(0),
4725        numberIterations_(0),
4726        numberSolves_(0),
4727        status_(-1),
4728        secondaryStatus_(-1),
4729        numberRowsAtContinuous_(0),
4730        maximumNumberCuts_(0),
4731        phase_(0),
4732        currentNumberCuts_(0),
4733        maximumDepth_(0),
4734        walkback_(NULL),
4735        lastNodeInfo_(NULL),
4736        lastCut_(NULL),
4737        lastDepth_(0),
4738        lastNumberCuts2_(0),
4739        maximumCuts_(0),
4740        lastNumberCuts_(NULL),
4741        addedCuts_(NULL),
4742        nextRowCut_(NULL),
4743        currentNode_(NULL),
4744        integerInfo_(NULL),
4745        specialOptions_(0),
4746        moreSpecialOptions_(0),
4747        subTreeModel_(NULL),
4748        numberStoppedSubTrees_(0),
4749        mutex_(NULL),
4750        presolve_(0),
4751        numberStrong_(5),
4752        numberBeforeTrust_(10),
4753        numberPenalties_(20),
4754        stopNumberIterations_(-1),
4755        penaltyScaleFactor_(3.0),
4756        numberAnalyzeIterations_(0),
4757        analyzeResults_(NULL),
4758        numberInfeasibleNodes_(0),
4759        problemType_(0),
4760        printFrequency_(0),
4761        numberCutGenerators_(0),
4762        generator_(NULL),
4763        virginGenerator_(NULL),
4764        numberHeuristics_(0),
4765        heuristic_(NULL),
4766        lastHeuristic_(NULL),
4767# ifdef COIN_HAS_CLP
4768        fastNodeDepth_(-1),
4769#endif
4770        eventHandler_(NULL),
4771        numberObjects_(0),
4772        object_(NULL),
4773        ownObjects_(true),
4774        originalColumns_(NULL),
4775        howOftenGlobalScan_(1),
4776        numberGlobalViolations_(0),
4777        numberExtraIterations_(0),
4778        numberExtraNodes_(0),
4779        continuousObjective_(COIN_DBL_MAX),
4780        originalContinuousObjective_(COIN_DBL_MAX),
4781        continuousInfeasibilities_(COIN_INT_MAX),
4782        maximumCutPassesAtRoot_(20),
4783        maximumCutPasses_(10),
4784        preferredWay_(0),
4785        currentPassNumber_(0),
4786        maximumWhich_(1000),
4787        maximumRows_(0),
4788        currentDepth_(0),
4789        whichGenerator_(NULL),
4790        maximumStatistics_(0),
4791        statistics_(NULL),
4792        maximumDepthActual_(0),
4793        numberDJFixed_(0.0),
4794        probingInfo_(NULL),
4795        numberFixedAtRoot_(0),
4796        numberFixedNow_(0),
4797        stoppedOnGap_(false),
4798        eventHappened_(false),
4799        numberLongStrong_(0),
4800        numberOldActiveCuts_(0),
4801        numberNewCuts_(0),
4802        searchStrategy_(-1),
4803        numberStrongIterations_(0),
4804        resolveAfterTakeOffCuts_(true),
4805        maximumNumberIterations_(-1),
4806        continuousPriority_(COIN_INT_MAX),
4807        numberUpdateItems_(0),
4808        maximumNumberUpdateItems_(0),
4809        updateItems_(NULL),
4810        numberThreads_(0),
4811        threadMode_(0)
4812{
4813    memset(intParam_, 0, sizeof(intParam_));
4814    intParam_[CbcMaxNumNode] = 2147483647;
4815    intParam_[CbcMaxNumSol] = 9999999;
4816
4817    memset(dblParam_, 0, sizeof(dblParam_));
4818    dblParam_[CbcIntegerTolerance] = 1e-6;
4819    dblParam_[CbcCutoffIncrement] = 1e-5;
4820    dblParam_[CbcAllowableGap] = 1.0e-10;
4821    dblParam_[CbcMaximumSeconds] = 1.0e100;
4822    dblParam_[CbcCurrentCutoff] = 1.0e100;
4823    dblParam_[CbcOptimizationDirection] = 1.0;
4824    dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
4825    dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
4826    strongInfo_[0] = 0;
4827    strongInfo_[1] = 0;
4828    strongInfo_[2] = 0;
4829    strongInfo_[3] = 0;
4830    strongInfo_[4] = 0;
4831    strongInfo_[5] = 0;
4832    strongInfo_[6] = 0;
4833    solverCharacteristics_ = NULL;
4834    nodeCompare_ = new CbcCompareDefault();;
4835    problemFeasibility_ = new CbcFeasibilityBase();
4836    tree_ = new CbcTree();
4837    branchingMethod_ = NULL;
4838    cutModifier_ = NULL;
4839    strategy_ = NULL;
4840    parentModel_ = NULL;
4841    appData_ = NULL;
4842    handler_ = new CoinMessageHandler();
4843    handler_->setLogLevel(2);
4844    messages_ = CbcMessage();
4845    //eventHandler_ = new CbcEventHandler() ;
4846    solver_ = rhs.clone();
4847    referenceSolver_ = solver_->clone();
4848    ownership_ = 0x80000000;
4849    cbcColLower_ = NULL;
4850    cbcColUpper_ = NULL;
4851    cbcRowLower_ = NULL;
4852    cbcRowUpper_ = NULL;
4853    cbcColSolution_ = NULL;
4854    cbcRowPrice_ = NULL;
4855    cbcReducedCost_ = NULL;
4856    cbcRowActivity_ = NULL;
4857
4858    // Initialize solution and integer variable vectors
4859    bestSolution_ = NULL; // to say no solution found
4860    savedSolutions_ = NULL;
4861    numberIntegers_ = 0;
4862    int numberColumns = solver_->getNumCols();
4863    int iColumn;
4864    if (numberColumns) {
4865        // Space for current solution
4866        currentSolution_ = new double[numberColumns];
4867        continuousSolution_ = new double[numberColumns];
4868        usedInSolution_ = new int[numberColumns];
4869        CoinZeroN(usedInSolution_, numberColumns);
4870        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4871            if ( solver_->isInteger(iColumn))
4872                numberIntegers_++;
4873        }
4874    } else {
4875        // empty model
4876        currentSolution_ = NULL;
4877        continuousSolution_ = NULL;
4878        usedInSolution_ = NULL;
4879    }
4880    testSolution_ = currentSolution_;
4881    if (numberIntegers_) {
4882        integerVariable_ = new int [numberIntegers_];
4883        numberIntegers_ = 0;
4884        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4885            if ( solver_->isInteger(iColumn))
4886                integerVariable_[numberIntegers_++] = iColumn;
4887        }
4888    } else {
4889        integerVariable_ = NULL;
4890    }
4891}
4892
4893/*
4894  Assign a solver to the model (model assumes ownership)
4895
4896  The integer variable vector is initialized if it's not already present.
4897  If deleteSolver then current solver deleted (if model owned)
4898
4899  Assuming ownership matches usage in OsiSolverInterface
4900  (cf. assignProblem, loadProblem).
4901
4902  TODO: What to do about solver parameters? A simple copy likely won't do it,
4903        because the SI must push the settings into the underlying solver. In
4904        the context of switching solvers in cbc, this means that command line
4905        settings will get lost. Stash the command line somewhere and reread it
4906        here, maybe?
4907
4908  TODO: More generally, how much state should be transferred from the old
4909        solver to the new solver? Best perhaps to see how usage develops.
4910        What's done here mimics the CbcModel(OsiSolverInterface) constructor.
4911*/
4912void
4913CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver)
4914
4915{
4916    // resize best solution if exists
4917    if (bestSolution_ && solver && solver_) {
4918        int nOld = solver_->getNumCols();
4919        int nNew = solver->getNumCols();
4920        if (nNew > nOld) {
4921            double * temp = new double[nNew];
4922            memcpy(temp, bestSolution_, nOld*sizeof(double));
4923            memset(temp + nOld, 0, (nNew - nOld)*sizeof(double));
4924            delete [] bestSolution_;
4925            bestSolution_ = temp;
4926        }
4927    }
4928    // Keep the current message level for solver (if solver exists)
4929    if (solver_)
4930        solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel()) ;
4931
4932    if (modelOwnsSolver() && deleteSolver) {
4933        solverCharacteristics_ = NULL;
4934        delete solver_ ;
4935    }
4936    solver_ = solver;
4937    solver = NULL ;
4938    setModelOwnsSolver(true) ;
4939    /*
4940      Basis information is solver-specific.
4941    */
4942    if (emptyWarmStart_) {
4943        delete emptyWarmStart_  ;
4944        emptyWarmStart_ = 0 ;
4945    }
4946    bestSolutionBasis_ = CoinWarmStartBasis();
4947    /*
4948      Initialize integer variable vector.
4949    */
4950    numberIntegers_ = 0;
4951    int numberColumns = solver_->getNumCols();
4952    int iColumn;
4953    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4954        if ( solver_->isInteger(iColumn))
4955            numberIntegers_++;
4956    }
4957    delete [] integerVariable_;
4958    if (numberIntegers_) {
4959        integerVariable_ = new int [numberIntegers_];
4960        numberIntegers_ = 0;
4961        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4962            if ( solver_->isInteger(iColumn))
4963                integerVariable_[numberIntegers_++] = iColumn;
4964        }
4965    } else {
4966        integerVariable_ = NULL;
4967    }
4968
4969    return ;
4970}
4971
4972// Copy constructor.
4973
4974CbcModel::CbcModel(const CbcModel & rhs, bool cloneHandler)
4975        :
4976        continuousSolver_(NULL),
4977        referenceSolver_(NULL),
4978        defaultHandler_(rhs.defaultHandler_),
4979        emptyWarmStart_(NULL),
4980        bestObjective_(rhs.bestObjective_),
4981        bestPossibleObjective_(rhs.bestPossibleObjective_),
4982        sumChangeObjective1_(rhs.sumChangeObjective1_),
4983        sumChangeObjective2_(rhs.sumChangeObjective2_),
4984        minimumDrop_(rhs.minimumDrop_),
4985        numberSolutions_(rhs.numberSolutions_),
4986        numberSavedSolutions_(rhs.numberSavedSolutions_),
4987        maximumSavedSolutions_(rhs.maximumSavedSolutions_),
4988        stateOfSearch_(rhs.stateOfSearch_),
4989        whenCuts_(rhs.whenCuts_),
4990        numberHeuristicSolutions_(rhs.numberHeuristicSolutions_),
4991        numberNodes_(rhs.numberNodes_),
4992        numberNodes2_(rhs.numberNodes2_),
4993        numberIterations_(rhs.numberIterations_),
4994        numberSolves_(rhs.numberSolves_),
4995        status_(rhs.status_),
4996        secondaryStatus_(rhs.secondaryStatus_),
4997        specialOptions_(rhs.specialOptions_),
4998        moreSpecialOptions_(rhs.moreSpecialOptions_),
4999        subTreeModel_(rhs.subTreeModel_),
5000        numberStoppedSubTrees_(rhs.numberStoppedSubTrees_),
5001        mutex_(NULL),
5002        presolve_(rhs.presolve_),
5003        numberStrong_(rhs.numberStrong_),
5004        numberBeforeTrust_(rhs.numberBeforeTrust_),
5005        numberPenalties_(rhs.numberPenalties_),
5006        stopNumberIterations_(rhs.stopNumberIterations_),
5007        penaltyScaleFactor_(rhs.penaltyScaleFactor_),
5008        numberAnalyzeIterations_(rhs.numberAnalyzeIterations_),
5009        analyzeResults_(NULL),
5010        numberInfeasibleNodes_(rhs.numberInfeasibleNodes_),
5011        problemType_(rhs.problemType_),
5012        printFrequency_(rhs.printFrequency_),
5013# ifdef COIN_HAS_CLP
5014        fastNodeDepth_(rhs.fastNodeDepth_),
5015#endif
5016        howOftenGlobalScan_(rhs.howOftenGlobalScan_),
5017        numberGlobalViolations_(rhs.numberGlobalViolations_),
5018        numberExtraIterations_(rhs.numberExtraIterations_),
5019        numberExtraNodes_(rhs.numberExtraNodes_),
5020        continuousObjective_(rhs.continuousObjective_),
5021        originalContinuousObjective_(rhs.originalContinuousObjective_),
5022        continuousInfeasibilities_(rhs.continuousInfeasibilities_),
5023        maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_),
5024        maximumCutPasses_( rhs.maximumCutPasses_),
5025        preferredWay_(rhs.preferredWay_),
5026        currentPassNumber_(rhs.currentPassNumber_),
5027        maximumWhich_(rhs.maximumWhich_),
5028        maximumRows_(0),
5029        currentDepth_(0),
5030        whichGenerator_(NULL),
5031        maximumStatistics_(0),
5032        statistics_(NULL),
5033        maximumDepthActual_(0),
5034        numberDJFixed_(0.0),
5035        probingInfo_(NULL),
5036        numberFixedAtRoot_(rhs.numberFixedAtRoot_),
5037        numberFixedNow_(rhs.numberFixedNow_),
5038        stoppedOnGap_(rhs.stoppedOnGap_),
5039        eventHappened_(rhs.eventHappened_),
5040        numberLongStrong_(rhs.numberLongStrong_),
5041        numberOldActiveCuts_(rhs.numberOldActiveCuts_),
5042        numberNewCuts_(rhs.numberNewCuts_),
5043        searchStrategy_(rhs.searchStrategy_),
5044        numberStrongIterations_(rhs.numberStrongIterations_),
5045        resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_),
5046        maximumNumberIterations_(rhs.maximumNumberIterations_),
5047        continuousPriority_(rhs.continuousPriority_),
5048        numberUpdateItems_(rhs.numberUpdateItems_),
5049        maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_),
5050        updateItems_(NULL),
5051        numberThreads_(rhs.numberThreads_),
5052        threadMode_(rhs.threadMode_)
5053{
5054    memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
5055    memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
5056    strongInfo_[0] = rhs.strongInfo_[0];
5057    strongInfo_[1] = rhs.strongInfo_[1];
5058    strongInfo_[2] = rhs.strongInfo_[2];
5059    strongInfo_[3] = rhs.strongInfo_[3];
5060    strongInfo_[4] = rhs.strongInfo_[4];
5061    strongInfo_[5] = rhs.strongInfo_[5];
5062    strongInfo_[6] = rhs.strongInfo_[6];
5063    solverCharacteristics_ = NULL;
5064    if (rhs.emptyWarmStart_) emptyWarmStart_ = rhs.emptyWarmStart_->clone() ;
5065    if (defaultHandler_ || cloneHandler) {
5066        handler_ = new CoinMessageHandler();
5067        handler_->setLogLevel(2);
5068    } else {
5069        handler_ = rhs.handler_;
5070    }
5071    messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
5072    numberCutGenerators_ = rhs.numberCutGenerators_;
5073    if (numberCutGenerators_) {
5074        generator_ = new CbcCutGenerator * [numberCutGenerators_];
5075        virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
5076        int i;
5077        for (i = 0; i < numberCutGenerators_; i++) {
5078            generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
5079            virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
5080        }
5081    } else {
5082        generator_ = NULL;
5083        virginGenerator_ = NULL;
5084    }
5085    globalCuts_ = rhs.globalCuts_;
5086    numberHeuristics_ = rhs.numberHeuristics_;
5087    if (numberHeuristics_) {
5088        heuristic_ = new CbcHeuristic * [numberHeuristics_];
5089        int i;
5090        for (i = 0; i < numberHeuristics_; i++) {
5091            heuristic_[i] = rhs.heuristic_[i]->clone();
5092        }
5093    } else {
5094        heuristic_ = NULL;
5095    }
5096    lastHeuristic_ = NULL;
5097    if (rhs.eventHandler_) {
5098        eventHandler_ = rhs.eventHandler_->clone() ;
5099    } else {
5100        eventHandler_ = NULL ;
5101    }
5102    ownObjects_ = rhs.ownObjects_;
5103    if (ownObjects_) {
5104        numberObjects_ = rhs.numberObjects_;
5105        if (numberObjects_) {
5106            object_ = new OsiObject * [numberObjects_];
5107            int i;
5108            for (i = 0; i < numberObjects_; i++) {
5109                object_[i] = (rhs.object_[i])->clone();
5110                CbcObject * obj = dynamic_cast <CbcObject *>(object_[i]) ;
5111                // Could be OsiObjects
5112                if (obj)
5113                    obj->setModel(this);
5114            }
5115        } else {
5116            object_ = NULL;
5117        }
5118    } else {
5119        // assume will be redone
5120        numberObjects_ = 0;
5121        object_ = NULL;
5122    }
5123    if (rhs.referenceSolver_)
5124        referenceSolver_ = rhs.referenceSolver_->clone();
5125    else
5126        referenceSolver_ = NULL;
5127    solver_ = rhs.solver_->clone();
5128    if (rhs.originalColumns_) {
5129        int numberColumns = solver_->getNumCols();
5130        originalColumns_ = new int [numberColumns];
5131        memcpy(originalColumns_, rhs.originalColumns_, numberColumns*sizeof(int));
5132    } else {
5133        originalColumns_ = NULL;
5134    }
5135    if (maximumNumberUpdateItems_) {
5136        updateItems_ = new CbcObjectUpdateData [maximumNumberUpdateItems_];
5137        for (int i = 0; i < maximumNumberUpdateItems_; i++)
5138            updateItems_[i] = rhs.updateItems_[i];
5139    }
5140    if (maximumWhich_ && rhs.whichGenerator_)
5141        whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_, maximumWhich_);
5142    nodeCompare_ = rhs.nodeCompare_->clone();
5143    problemFeasibility_ = rhs.problemFeasibility_->clone();
5144    tree_ = rhs.tree_->clone();
5145    if (rhs.branchingMethod_)
5146        branchingMethod_ = rhs.branchingMethod_->clone();
5147    else
5148        branchingMethod_ = NULL;
5149    if (rhs.cutModifier_)
5150        cutModifier_ = rhs.cutModifier_->clone();
5151    else
5152        cutModifier_ = NULL;
5153    cbcColLower_ = NULL;
5154    cbcColUpper_ = NULL;
5155    cbcRowLower_ = NULL;
5156    cbcRowUpper_ = NULL;
5157    cbcColSolution_ = NULL;
5158    cbcRowPrice_ = NULL;
5159    cbcReducedCost_ = NULL;
5160    cbcRowActivity_ = NULL;
5161    if (rhs.strategy_)
5162        strategy_ = rhs.strategy_->clone();
5163    else
5164        strategy_ = NULL;
5165    parentModel_ = rhs.parentModel_;
5166    appData_ = rhs.appData_;
5167    messages_ = rhs.messages_;
5168    ownership_ = 0x80000000;
5169    messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
5170    numberIntegers_ = rhs.numberIntegers_;
5171    randomNumberGenerator_ = rhs.randomNumberGenerator_;
5172    if (numberIntegers_) {
5173        integerVariable_ = new int [numberIntegers_];
5174        memcpy(integerVariable_, rhs.integerVariable_, numberIntegers_*sizeof(int));
5175        integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, solver_->getNumCols());
5176    } else {
5177        integerVariable_ = NULL;
5178        integerInfo_ = NULL;
5179    }
5180    if (rhs.hotstartSolution_) {
5181        int numberColumns = solver_->getNumCols();
5182        hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns);
5183        hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns);
5184    } else {
5185        hotstartSolution_ = NULL;
5186        hotstartPriorities_ = NULL;
5187    }
5188    if (rhs.bestSolution_) {
5189        int numberColumns = solver_->getNumCols();
5190        bestSolution_ = new double[numberColumns];
5191        memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double));
5192    } else {
5193        bestSolution_ = NULL;
5194    }
5195    int numberColumns = solver_->getNumCols();
5196    if (maximumSavedSolutions_ && rhs.savedSolutions_) {
5197        savedSolutions_ = new double * [maximumSavedSolutions_];
5198        for (int i = 0; i < maximumSavedSolutions_; i++)
5199            savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2);
5200    } else {
5201        savedSolutions_ = NULL;
5202    }
5203    // Space for current solution
5204    currentSolution_ = new double[numberColumns];
5205    continuousSolution_ = new double[numberColumns];
5206    usedInSolution_ = new int[numberColumns];
5207    CoinZeroN(usedInSolution_, numberColumns);
5208    testSolution_ = currentSolution_;
5209    numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
5210    maximumNumberCuts_ = rhs.maximumNumberCuts_;
5211    phase_ = rhs.phase_;
5212    currentNumberCuts_ = rhs.currentNumberCuts_;
5213    maximumDepth_ = rhs.maximumDepth_;
5214    // These are only used as temporary arrays so need not be filled
5215    if (maximumNumberCuts_) {
5216        addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
5217    } else {
5218        addedCuts_ = NULL;
5219    }
5220    bestSolutionBasis_ = rhs.bestSolutionBasis_;
5221    nextRowCut_ = NULL;
5222    currentNode_ = NULL;
5223    if (maximumDepth_) {
5224        walkback_ = new CbcNodeInfo * [maximumDepth_];
5225        lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
5226        lastNumberCuts_ = new int [maximumDepth_] ;
5227    } else {
5228        walkback_ = NULL;
5229        lastNodeInfo_ = NULL;
5230        lastNumberCuts_ = NULL;
5231    }
5232    maximumCuts_ = rhs.maximumCuts_;
5233    if (maximumCuts_) {
5234        lastCut_ = new const OsiRowCut * [maximumCuts_] ;
5235    } else {
5236        lastCut_ = NULL;
5237    }
5238    synchronizeModel();
5239    if (cloneHandler && !defaultHandler_) {
5240        delete handler_;
5241        CoinMessageHandler * handler = rhs.handler_->clone();
5242        passInMessageHandler(handler);
5243    }
5244}
5245
5246// Assignment operator
5247CbcModel &
5248CbcModel::operator=(const CbcModel & rhs)
5249{
5250    if (this != &rhs) {
5251        if (modelOwnsSolver()) {
5252            solverCharacteristics_ = NULL;
5253            delete solver_;
5254            solver_ = NULL;
5255        }
5256        gutsOfDestructor();
5257        if (defaultHandler_) {
5258            delete handler_;
5259            handler_ = NULL;
5260        }
5261        defaultHandler_ = rhs.defaultHandler_;
5262        if (defaultHandler_) {
5263            handler_ = new CoinMessageHandler();
5264            handler_->setLogLevel(2);
5265        } else {
5266            handler_ = rhs.handler_;
5267        }
5268        messages_ = rhs.messages_;
5269        messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
5270        if (rhs.solver_) {
5271            solver_ = rhs.solver_->clone() ;
5272        } else {
5273            solver_ = 0 ;
5274        }
5275        ownership_ = 0x80000000;
5276        delete continuousSolver_ ;
5277        if (rhs.continuousSolver_) {
5278            continuousSolver_ = rhs.continuousSolver_->clone() ;
5279        } else {
5280            continuousSolver_ = 0 ;
5281        }
5282        delete referenceSolver_;
5283        if (rhs.referenceSolver_) {
5284            referenceSolver_ = rhs.referenceSolver_->clone() ;
5285        } else {
5286            referenceSolver_ = NULL ;
5287        }
5288
5289        delete emptyWarmStart_ ;
5290        if (rhs.emptyWarmStart_) {
5291            emptyWarmStart_ = rhs.emptyWarmStart_->clone() ;
5292        } else {
5293            emptyWarmStart_ = 0 ;
5294        }
5295
5296        bestObjective_ = rhs.bestObjective_;
5297        bestPossibleObjective_ = rhs.bestPossibleObjective_;
5298        sumChangeObjective1_ = rhs.sumChangeObjective1_;
5299        sumChangeObjective2_ = rhs.sumChangeObjective2_;
5300        delete [] bestSolution_;
5301        if (rhs.bestSolution_) {
5302            int numberColumns = rhs.getNumCols();
5303            bestSolution_ = new double[numberColumns];
5304            memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double));
5305        } else {
5306            bestSolution_ = NULL;
5307        }
5308        for (int i = 0; i < maximumSavedSolutions_; i++)
5309            delete [] savedSolutions_[i];
5310        delete [] savedSolutions_;
5311        savedSolutions_ = NULL;
5312        int numberColumns = rhs.getNumCols();
5313        if (numberColumns) {
5314            // Space for current solution
5315            currentSolution_ = new double[numberColumns];
5316            continuousSolution_ = new double[numberColumns];
5317            usedInSolution_ = new int[numberColumns];
5318            CoinZeroN(usedInSolution_, numberColumns);
5319