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

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

Fixed yesterday's bugs

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