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

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

Removed CbcTreeArray? code

  • 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 1341 2009-12-03 17:26:41Z 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 0
2235                if (false && !numberThreads_ && !parentModel_) {
2236            printf("CbcTreeArray ? threads ? parentArray\n");
2237            // Setup new style tree
2238            delete tree_;
2239            tree_ = new CbcTreeArray();
2240        }
2241#endif
2242    }
2243    tree_->setComparison(*nodeCompare_) ;
2244    /*
2245      Used to record the path from a node to the root of the search tree, so that
2246      we can then traverse from the root to the node when restoring a subproblem.
2247    */
2248    maximumDepth_ = 10 ;
2249    delete [] walkback_ ;
2250    walkback_ = new CbcNodeInfo * [maximumDepth_] ;
2251    lastDepth_ = 0;
2252    delete [] lastNodeInfo_ ;
2253    lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ;
2254    delete [] lastNumberCuts_ ;
2255    lastNumberCuts_ = new int [maximumDepth_] ;
2256    maximumCuts_ = 100;
2257    lastNumberCuts2_ = 0;
2258    delete [] lastCut_;
2259    lastCut_ = new const OsiRowCut * [maximumCuts_];
2260    /*
2261      Used to generate bound edits for CbcPartialNodeInfo.
2262    */
2263    double * lowerBefore = new double [numberColumns] ;
2264    double * upperBefore = new double [numberColumns] ;
2265    /*
2266
2267      Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
2268      lifting. It will iterate a generate/reoptimise loop (including reduced cost
2269      fixing) until no cuts are generated, the change in objective falls off,  or
2270      the limit on the number of rounds of cut generation is exceeded.
2271
2272      At the end of all this, any cuts will be recorded in cuts and also
2273      installed in the solver's constraint system. We'll have reoptimised, and
2274      removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
2275      adjusted accordingly).
2276
2277      Tell cut generators they can be a bit more aggressive at root node
2278
2279      TODO: Why don't we make a copy of the solution after solveWithCuts?
2280      TODO: If numberUnsatisfied == 0, don't we have a solution?
2281    */
2282    phase_ = 1;
2283    int iCutGenerator;
2284    for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
2285        CglCutGenerator * generator = generator_[iCutGenerator]->generator();
2286        generator->setAggressiveness(generator->getAggressiveness() + 100);
2287    }
2288    OsiCuts cuts ;
2289    int anyAction = -1 ;
2290    numberOldActiveCuts_ = 0 ;
2291    numberNewCuts_ = 0 ;
2292    // Array to mark solution
2293    delete [] usedInSolution_;
2294    usedInSolution_ = new int[numberColumns];
2295    CoinZeroN(usedInSolution_, numberColumns);
2296    /*
2297      For printing totals and for CbcNode (numberNodes_)
2298    */
2299    numberIterations_ = 0 ;
2300    numberSolves_ = 0 ;
2301    numberNodes_ = 0 ;
2302    numberNodes2_ = 0 ;
2303    maximumStatistics_ = 0;
2304    maximumDepthActual_ = 0;
2305    numberDJFixed_ = 0.0;
2306    if (!parentModel_) {
2307        if ((specialOptions_&262144) != 0) {
2308            // create empty stored cuts
2309            //storedRowCuts_ = new CglStored(solver_->getNumCols());
2310        } else if ((specialOptions_&524288) != 0 && storedRowCuts_) {
2311            // tighten and set best solution
2312            // A) tight bounds on integer variables
2313            const double * lower = solver_->getColLower();
2314            const double * upper = solver_->getColUpper();
2315            const double * tightLower = storedRowCuts_->tightLower();
2316            const double * tightUpper = storedRowCuts_->tightUpper();
2317            int nTightened = 0;
2318            for (int i = 0; i < numberIntegers_; i++) {
2319                int iColumn = integerVariable_[i];
2320                if (tightLower[iColumn] > lower[iColumn]) {
2321                    nTightened++;
2322                    solver_->setColLower(iColumn, tightLower[iColumn]);
2323                }
2324                if (tightUpper[iColumn] < upper[iColumn]) {
2325                    nTightened++;
2326                    solver_->setColUpper(iColumn, tightUpper[iColumn]);
2327                }
2328            }
2329            if (nTightened)
2330                printf("%d tightened by alternate cuts\n", nTightened);
2331            if (storedRowCuts_->bestObjective() < bestObjective_) {
2332                // B) best solution
2333                double objValue = storedRowCuts_->bestObjective();
2334                setBestSolution(CBC_SOLUTION, objValue,
2335                                storedRowCuts_->bestSolution()) ;
2336                // Do heuristics
2337                // Allow RINS
2338                for (int i = 0; i < numberHeuristics_; i++) {
2339                    CbcHeuristicRINS * rins
2340                    = dynamic_cast<CbcHeuristicRINS *> (heuristic_[i]);
2341                    if (rins) {
2342                        rins->setLastNode(-100);
2343                    }
2344                }
2345            }
2346        }
2347    }
2348    // Do heuristics
2349    doHeuristicsAtRoot();
2350    if ( intParam_[CbcMaxNumNode] < 0)
2351        eventHappened_ = true; // stop as fast as possible
2352    stoppedOnGap_ = false ;
2353    // See if can stop on gap
2354    bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
2355    double testGap = CoinMax(dblParam_[CbcAllowableGap],
2356                             CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
2357                             * dblParam_[CbcAllowableFractionGap]);
2358    if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0) {
2359        if (bestPossibleObjective_ < getCutoff())
2360            stoppedOnGap_ = true ;
2361        feasible = false;
2362        //eventHappened_=true; // stop as fast as possible
2363    }
2364    statistics_ = NULL;
2365    // Do on switch
2366    if (doStatistics > 0 && doStatistics <= 100) {
2367        maximumStatistics_ = 10000;
2368        statistics_ = new CbcStatistics * [maximumStatistics_];
2369        memset(statistics_, 0, maximumStatistics_*sizeof(CbcStatistics *));
2370    }
2371    // See if we can add integers
2372    if (noObjects && numberIntegers_ < solver_->getNumCols() && (specialOptions_&65536) != 0 && !parentModel_)
2373                AddIntegers();
2374
2375    int iObject ;
2376    int preferredWay ;
2377    int numberUnsatisfied = 0 ;
2378    delete [] currentSolution_;
2379    currentSolution_ = new double [numberColumns];
2380    testSolution_ = currentSolution_;
2381    memcpy(currentSolution_, solver_->getColSolution(),
2382           numberColumns*sizeof(double)) ;
2383    // point to useful information
2384    OsiBranchingInformation usefulInfo = usefulInformation();
2385
2386    for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
2387        double infeasibility =
2388            object_[iObject]->infeasibility(&usefulInfo, preferredWay) ;
2389        if (infeasibility ) numberUnsatisfied++ ;
2390    }
2391    // replace solverType
2392    if (solverCharacteristics_->tryCuts())  {
2393
2394        if (numberUnsatisfied)   {
2395            // User event
2396            if (!eventHappened_ && feasible) {
2397                feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
2398                                         NULL);
2399                if ((specialOptions_&524288) != 0 && !parentModel_
2400                        && storedRowCuts_) {
2401                    if (feasible) {
2402                        /* pick up stuff and try again
2403                        add cuts, maybe keep around
2404                        do best solution and if so new heuristics
2405                        obviously tighten bounds
2406                        */
2407                        // A and B probably done on entry
2408                        // A) tight bounds on integer variables
2409                        const double * lower = solver_->getColLower();
2410                        const double * upper = solver_->getColUpper();
2411                        const double * tightLower = storedRowCuts_->tightLower();
2412                        const double * tightUpper = storedRowCuts_->tightUpper();
2413                        int nTightened = 0;
2414                        for (int i = 0; i < numberIntegers_; i++) {
2415                            int iColumn = integerVariable_[i];
2416                            if (tightLower[iColumn] > lower[iColumn]) {
2417                                nTightened++;
2418                                solver_->setColLower(iColumn, tightLower[iColumn]);
2419                            }
2420                            if (tightUpper[iColumn] < upper[iColumn]) {
2421                                nTightened++;
2422                                solver_->setColUpper(iColumn, tightUpper[iColumn]);
2423                            }
2424                        }
2425                        if (nTightened)
2426                            printf("%d tightened by alternate cuts\n", nTightened);
2427                        if (storedRowCuts_->bestObjective() < bestObjective_) {
2428                            // B) best solution
2429                            double objValue = storedRowCuts_->bestObjective();
2430                            setBestSolution(CBC_SOLUTION, objValue,
2431                                            storedRowCuts_->bestSolution()) ;
2432                            // Do heuristics
2433                            // Allow RINS
2434                            for (int i = 0; i < numberHeuristics_; i++) {
2435                                CbcHeuristicRINS * rins
2436                                = dynamic_cast<CbcHeuristicRINS *> (heuristic_[i]);
2437                                if (rins) {
2438                                    rins->setLastNode(-100);
2439                                }
2440                            }
2441                            doHeuristicsAtRoot();
2442                        }
2443#if 0
2444                        int nCuts = storedRowCuts_->sizeRowCuts();
2445                        // add to global list
2446                        for (int i = 0; i < nCuts; i++) {
2447                            OsiRowCut newCut(*storedRowCuts_->rowCutPointer(i));
2448                            newCut.setGloballyValidAsInteger(2);
2449                            newCut.mutableRow().setTestForDuplicateIndex(false);
2450                            globalCuts_.insert(newCut) ;
2451                        }
2452#else
2453                        addCutGenerator(storedRowCuts_, -99, "Stored from previous run",
2454                                        true, false, false, -200);
2455#endif
2456                        // Set cuts as active
2457                        delete [] addedCuts_ ;
2458                        maximumNumberCuts_ = cuts.sizeRowCuts();
2459                        if (maximumNumberCuts_) {
2460                            addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
2461                        } else {
2462                            addedCuts_ = NULL;
2463                        }
2464                        for (int i = 0; i < maximumNumberCuts_; i++)
2465                            addedCuts_[i] = new CbcCountRowCut(*cuts.rowCutPtr(i),
2466                                                               NULL, -1, -1, 2);
2467                        printf("size %d\n", cuts.sizeRowCuts());
2468                        cuts = OsiCuts();
2469                        currentNumberCuts_ = maximumNumberCuts_;
2470                        feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
2471                                                 NULL);
2472                        for (int i = 0; i < maximumNumberCuts_; i++)
2473                            delete addedCuts_[i];
2474                    }
2475                    delete storedRowCuts_;
2476                    storedRowCuts_ = NULL;
2477                }
2478            } else {
2479                feasible = false;
2480            }
2481        }       else if (solverCharacteristics_->solutionAddsCuts() ||
2482                   solverCharacteristics_->alwaysTryCutsAtRootNode()) {
2483            // may generate cuts and turn the solution
2484            //to an infeasible one
2485            feasible = solveWithCuts(cuts, 1,
2486                                     NULL);
2487        }
2488    }
2489    // check extra info on feasibility
2490    if (!solverCharacteristics_->mipFeasible())
2491        feasible = false;
2492
2493    // make cut generators less aggressive
2494    for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
2495        CglCutGenerator * generator = generator_[iCutGenerator]->generator();
2496        generator->setAggressiveness(generator->getAggressiveness() - 100);
2497    }
2498    currentNumberCuts_ = numberNewCuts_ ;
2499    // See if can stop on gap
2500    bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
2501    testGap = CoinMax(dblParam_[CbcAllowableGap],
2502                      CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
2503                      * dblParam_[CbcAllowableFractionGap]);
2504    if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0) {
2505        if (bestPossibleObjective_ < getCutoff())
2506            stoppedOnGap_ = true ;
2507        feasible = false;
2508    }
2509    // User event
2510    if (eventHappened_)
2511        feasible = false;
2512#if defined(COIN_HAS_CLP)&&defined(COIN_HAS_CPX)
2513    if (feasible && (specialOptions_&16384) != 0 && fastNodeDepth_ == -2 && !parentModel_) {
2514        // Use Cplex to do search!
2515        double time1 = CoinCpuTime();
2516        OsiClpSolverInterface * clpSolver
2517        = dynamic_cast<OsiClpSolverInterface *> (solver_);
2518        OsiCpxSolverInterface cpxSolver;
2519        double direction = clpSolver->getObjSense();
2520        cpxSolver.setObjSense(direction);
2521        // load up cplex
2522        const CoinPackedMatrix * matrix = continuousSolver_->getMatrixByCol();
2523        const double * rowLower = continuousSolver_->getRowLower();
2524        const double * rowUpper = continuousSolver_->getRowUpper();
2525        const double * columnLower = continuousSolver_->getColLower();
2526        const double * columnUpper = continuousSolver_->getColUpper();
2527        const double * objective = continuousSolver_->getObjCoefficients();
2528        cpxSolver.loadProblem(*matrix, columnLower, columnUpper,
2529                              objective, rowLower, rowUpper);
2530        double * setSol = new double [numberIntegers_];
2531        int * setVar = new int [numberIntegers_];
2532        // cplex doesn't know about objective offset
2533        double offset = clpSolver->getModelPtr()->objectiveOffset();
2534        for (int i = 0; i < numberIntegers_; i++) {
2535            int iColumn = integerVariable_[i];
2536            cpxSolver.setInteger(iColumn);
2537            if (bestSolution_) {
2538                setSol[i] = bestSolution_[iColumn];
2539                setVar[i] = iColumn;
2540            }
2541        }
2542        CPXENVptr env = cpxSolver.getEnvironmentPtr();
2543        CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
2544        cpxSolver.switchToMIP();
2545        if (bestSolution_) {
2546            CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol);
2547        }
2548        if (clpSolver->getNumRows() > continuousSolver_->getNumRows() && false) {
2549            // add cuts
2550            const CoinPackedMatrix * matrix = clpSolver->getMatrixByRow();
2551            const double * rhs = clpSolver->getRightHandSide();
2552            const char * rowSense = clpSolver->getRowSense();
2553            const double * elementByRow = matrix->getElements();
2554            const int * column = matrix->getIndices();
2555            const CoinBigIndex * rowStart = matrix->getVectorStarts();
2556            const int * rowLength = matrix->getVectorLengths();
2557            int nStart = continuousSolver_->getNumRows();
2558            int nRows = clpSolver->getNumRows();
2559            int size = rowStart[nRows-1] + rowLength[nRows-1] -
2560                       rowStart[nStart];
2561            int nAdd = 0;
2562            double * rmatval = new double [size];
2563            int * rmatind = new int [size];
2564            int * rmatbeg = new int [nRows-nStart+1];
2565            size = 0;
2566            rmatbeg[0] = 0;
2567            for (int i = nStart; i < nRows; i++) {
2568                for (int k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) {
2569                    rmatind[size] = column[k];
2570                    rmatval[size++] = elementByRow[k];
2571                }
2572                nAdd++;
2573                rmatbeg[nAdd] = size;
2574            }
2575            CPXaddlazyconstraints(env, lpPtr, nAdd, size,
2576                                  rhs, rowSense, rmatbeg,
2577                                  rmatind, rmatval, NULL);
2578            CPXsetintparam( env, CPX_PARAM_REDUCE,
2579                            // CPX_PREREDUCE_NOPRIMALORDUAL (0)
2580                            CPX_PREREDUCE_PRIMALONLY);
2581        }
2582        if (getCutoff() < 1.0e50) {
2583            double useCutoff = getCutoff() + offset;
2584            if (bestObjective_ < 1.0e50)
2585                useCutoff = bestObjective_ + offset + 1.0e-7;
2586            cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff*
2587                                  direction);
2588            if ( direction > 0.0 )
2589                CPXsetdblparam( env, CPX_PARAM_CUTUP, useCutoff ) ; // min
2590            else
2591                CPXsetdblparam( env, CPX_PARAM_CUTLO, useCutoff ) ; // max
2592        }
2593        CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]);
2594        delete [] setSol;
2595        delete [] setVar;
2596        char printBuffer[200];
2597        if (offset) {
2598            sprintf(printBuffer, "Add %g to all Cplex messages for true objective",
2599                    -offset);
2600            messageHandler()->message(CBC_GENERAL, messages())
2601            << printBuffer << CoinMessageEol ;
2602            cpxSolver.setDblParam(OsiObjOffset, offset);
2603        }
2604        cpxSolver.branchAndBound();
2605        double timeTaken = CoinCpuTime() - time1;
2606        sprintf(printBuffer, "Cplex took %g seconds",
2607                timeTaken);
2608        messageHandler()->message(CBC_GENERAL, messages())
2609        << printBuffer << CoinMessageEol ;
2610        numberExtraNodes_ = CPXgetnodecnt(env, lpPtr);
2611        numberExtraIterations_ = CPXgetmipitcnt(env, lpPtr);
2612        double value = cpxSolver.getObjValue() * direction;
2613        if (cpxSolver.isProvenOptimal() && value <= getCutoff()) {
2614            feasible = true;
2615            clpSolver->setWarmStart(NULL);
2616            // try and do solution
2617            double * newSolution =
2618                CoinCopyOfArray(cpxSolver.getColSolution(),
2619                                getNumCols());
2620            setBestSolution(CBC_STRONGSOL, value, newSolution) ;
2621            delete [] newSolution;
2622        }
2623        feasible = false;
2624    }
2625#endif
2626    if (fastNodeDepth_ == 1000 &&/*!parentModel_*/(specialOptions_&2048) == 0) {
2627        fastNodeDepth_ = -1;
2628        CbcObject * obj =
2629            new CbcFollowOn(this);
2630        obj->setPriority(1);
2631        addObjects(1, &obj);
2632    }
2633    int saveNumberSolves = numberSolves_;
2634    int saveNumberIterations = numberIterations_;
2635    if (fastNodeDepth_ >= 0 &&/*!parentModel_*/(specialOptions_&2048) == 0) {
2636        // add in a general depth object doClp
2637        int type = (fastNodeDepth_ <= 100) ? fastNodeDepth_ : -(fastNodeDepth_ - 100);
2638        CbcObject * obj =
2639            new CbcGeneralDepth(this, type);
2640        addObjects(1, &obj);
2641        // mark as done
2642        fastNodeDepth_ += 1000000;
2643        delete obj;
2644        // fake number of objects
2645        numberObjects_--;
2646        if (parallelMode() < -1) {
2647            // But make sure position is correct
2648            OsiObject * obj2 = object_[numberObjects_];
2649            obj = dynamic_cast<CbcObject *> (obj2);
2650            assert (obj);
2651            obj->setPosition(numberObjects_);
2652        }
2653    }
2654#ifdef COIN_HAS_CLP
2655#ifdef NO_CRUNCH
2656    if (true) {
2657        OsiClpSolverInterface * clpSolver
2658        = dynamic_cast<OsiClpSolverInterface *> (solver_);
2659        if (clpSolver && !parentModel_) {
2660            ClpSimplex * clpSimplex = clpSolver->getModelPtr();
2661            clpSimplex->setSpecialOptions(clpSimplex->specialOptions() | 131072);
2662            //clpSimplex->startPermanentArrays();
2663            clpSimplex->setPersistenceFlag(2);
2664        }
2665    }
2666#endif
2667#endif
2668// Save copy of solver
2669    OsiSolverInterface * saveSolver = NULL;
2670    if (!parentModel_ && (specialOptions_&(512 + 32768)) != 0)
2671        saveSolver = solver_->clone();
2672    double checkCutoffForRestart = 1.0e100;
2673    saveModel(saveSolver, &checkCutoffForRestart, &feasible);
2674    if ((specialOptions_&262144) != 0 && !parentModel_) {
2675        // Save stuff and return!
2676        storedRowCuts_->saveStuff(bestObjective_, bestSolution_,
2677                                  solver_->getColLower(),
2678                                  solver_->getColUpper());
2679        delete [] lowerBefore;
2680        delete [] upperBefore;
2681        delete saveSolver;
2682        return;
2683    }
2684    /*
2685      We've taken the continuous relaxation as far as we can. Time to branch.
2686      The first order of business is to actually create a node. chooseBranch
2687      currently uses strong branching to evaluate branch object candidates,
2688      unless forced back to simple branching. If chooseBranch concludes that a
2689      branching candidate is monotone (anyAction == -1) or infeasible (anyAction
2690      == -2) when forced to integer values, it returns here immediately.
2691
2692      Monotone variables trigger a call to resolve(). If the problem remains
2693      feasible, try again to choose a branching variable. At the end of the loop,
2694      resolved == true indicates that some variables were fixed.
2695
2696      Loss of feasibility will result in the deletion of newNode.
2697    */
2698
2699    bool resolved = false ;
2700    CbcNode *newNode = NULL ;
2701    numberFixedAtRoot_ = 0;
2702    numberFixedNow_ = 0;
2703    int numberIterationsAtContinuous = numberIterations_;
2704    //solverCharacteristics_->setSolver(solver_);
2705    if (feasible) {
2706        //#define HOTSTART -1
2707#if HOTSTART<0
2708        if (bestSolution_ && !parentModel_ && !hotstartSolution_ &&
2709                (moreSpecialOptions_&1024) != 0) {
2710            // Set priorities so only branch on ones we need to
2711            // use djs and see if only few branches needed
2712#ifndef NDEBUG
2713            double integerTolerance = getIntegerTolerance() ;
2714#endif
2715            bool possible = true;
2716            const double * saveLower = continuousSolver_->getColLower();
2717            const double * saveUpper = continuousSolver_->getColUpper();
2718            for (int i = 0; i < numberObjects_; i++) {
2719                const CbcSimpleInteger * thisOne = dynamic_cast <const CbcSimpleInteger *> (object_[i]);
2720                if (thisOne) {
2721                    int iColumn = thisOne->columnNumber();
2722                    if (saveUpper[iColumn] > saveLower[iColumn] + 1.5) {
2723                        possible = false;
2724                        break;
2725                    }
2726                } else {
2727                    possible = false;
2728                    break;
2729                }
2730            }
2731            if (possible) {
2732                OsiSolverInterface * solver = continuousSolver_->clone();
2733                int numberColumns = solver->getNumCols();
2734                for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2735                    double value = bestSolution_[iColumn] ;
2736                    value = CoinMax(value, saveLower[iColumn]) ;
2737                    value = CoinMin(value, saveUpper[iColumn]) ;
2738                    value = floor(value + 0.5);
2739                    if (solver->isInteger(iColumn)) {
2740                        solver->setColLower(iColumn, value);
2741                        solver->setColUpper(iColumn, value);
2742                    }
2743                }
2744                solver->setHintParam(OsiDoDualInResolve, false, OsiHintTry);
2745                // objlim and all slack
2746                double direction = solver->getObjSense();
2747                solver->setDblParam(OsiDualObjectiveLimit, 1.0e50*direction);
2748                CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (solver->getEmptyWarmStart());
2749                solver->setWarmStart(basis);
2750                delete basis;
2751                bool changed = true;
2752                hotstartPriorities_ = new int [numberColumns];
2753                for (int iColumn = 0; iColumn < numberColumns; iColumn++)
2754                    hotstartPriorities_[iColumn] = 1;
2755                while (changed) {
2756                    changed = false;
2757                    solver->resolve();
2758                    if (!solver->isProvenOptimal()) {
2759                        possible = false;
2760                        break;
2761                    }
2762                    const double * dj = solver->getReducedCost();
2763                    const double * colLower = solver->getColLower();
2764                    const double * colUpper = solver->getColUpper();
2765                    const double * solution = solver->getColSolution();
2766                    int nAtLbNatural = 0;
2767                    int nAtUbNatural = 0;
2768                    int nZeroDj = 0;
2769                    int nForced = 0;
2770                    for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2771                        double value = solution[iColumn] ;
2772                        value = CoinMax(value, saveLower[iColumn]) ;
2773                        value = CoinMin(value, saveUpper[iColumn]) ;
2774                        if (solver->isInteger(iColumn)) {
2775                            assert(fabs(value - solution[iColumn]) <= integerTolerance) ;
2776                            if (hotstartPriorities_[iColumn] == 1) {
2777                                if (dj[iColumn] < -1.0e-6) {
2778                                    // negative dj
2779                                    if (saveUpper[iColumn] == colUpper[iColumn]) {
2780                                        nAtUbNatural++;
2781                                        hotstartPriorities_[iColumn] = 2;
2782                                        solver->setColLower(iColumn, saveLower[iColumn]);
2783                                        solver->setColUpper(iColumn, saveUpper[iColumn]);
2784                                    } else {
2785                                        nForced++;
2786                                    }
2787                                } else if (dj[iColumn] > 1.0e-6) {
2788                                    // positive dj
2789                                    if (saveLower[iColumn] == colLower[iColumn]) {
2790                                        nAtLbNatural++;
2791                                        hotstartPriorities_[iColumn] = 2;
2792                                        solver->setColLower(iColumn, saveLower[iColumn]);
2793                                        solver->setColUpper(iColumn, saveUpper[iColumn]);
2794                                    } else {
2795                                        nForced++;
2796                                    }
2797                                } else {
2798                                    // zero dj
2799                                    nZeroDj++;
2800                                }
2801                            }
2802                        }
2803                    }
2804#ifdef CLP_INVESTIGATE
2805                    printf("%d forced, %d naturally at lower, %d at upper - %d zero dj\n",
2806                           nForced, nAtLbNatural, nAtUbNatural, nZeroDj);
2807#endif
2808                    if (nAtLbNatural || nAtUbNatural) {
2809                        changed = true;
2810                    } else {
2811                        if (nForced + nZeroDj > 50 ||
2812                                (nForced + nZeroDj)*4 > numberIntegers_)
2813                            possible = false;
2814                    }
2815                }
2816                delete solver;
2817            }
2818            if (possible) {
2819                setHotstartSolution(bestSolution_);
2820                if (!saveCompare) {
2821                    // create depth first comparison
2822                    saveCompare = nodeCompare_;
2823                    // depth first
2824                    nodeCompare_ = new CbcCompareDepth();
2825                    tree_->setComparison(*nodeCompare_) ;
2826                }
2827            } else {
2828                delete [] hotstartPriorities_;
2829                hotstartPriorities_ = NULL;
2830            }
2831        }
2832#endif
2833#if HOTSTART>0
2834        if (hotstartSolution_ && !hotstartPriorities_) {
2835            // Set up hot start
2836            OsiSolverInterface * solver = solver_->clone();
2837            double direction = solver_->getObjSense() ;
2838            int numberColumns = solver->getNumCols();
2839            double * saveLower = CoinCopyOfArray(solver->getColLower(), numberColumns);
2840            double * saveUpper = CoinCopyOfArray(solver->getColUpper(), numberColumns);
2841            // move solution
2842            solver->setColSolution(hotstartSolution_);
2843            // point to useful information
2844            const double * saveSolution = testSolution_;
2845            testSolution_ = solver->getColSolution();
2846            OsiBranchingInformation usefulInfo = usefulInformation();
2847            testSolution_ = saveSolution;
2848            /*
2849            Run through the objects and use feasibleRegion() to set variable bounds
2850            so as to fix the variables specified in the objects at their value in this
2851            solution. Since the object list contains (at least) one object for every
2852            integer variable, this has the effect of fixing all integer variables.
2853            */
2854            for (int i = 0; i < numberObjects_; i++)
2855                object_[i]->feasibleRegion(solver, &usefulInfo);
2856            solver->resolve();
2857            assert (solver->isProvenOptimal());
2858            double gap = CoinMax((solver->getObjValue() - solver_->getObjValue()) * direction, 0.0) ;
2859            const double * dj = solver->getReducedCost();
2860            const double * colLower = solver->getColLower();
2861            const double * colUpper = solver->getColUpper();
2862            const double * solution = solver->getColSolution();
2863            int nAtLbNatural = 0;
2864            int nAtUbNatural = 0;
2865            int nAtLbNaturalZero = 0;
2866            int nAtUbNaturalZero = 0;
2867            int nAtLbFixed = 0;
2868            int nAtUbFixed = 0;
2869            int nAtOther = 0;
2870            int nAtOtherNatural = 0;
2871            int nNotNeeded = 0;
2872            delete [] hotstartSolution_;
2873            hotstartSolution_ = new double [numberColumns];
2874            delete [] hotstartPriorities_;
2875            hotstartPriorities_ = new int [numberColumns];
2876            int * order = (int *) saveUpper;
2877            int nFix = 0;
2878            double bestRatio = COIN_DBL_MAX;
2879            for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2880                double value = solution[iColumn] ;
2881                value = CoinMax(value, saveLower[iColumn]) ;
2882                value = CoinMin(value, saveUpper[iColumn]) ;
2883                double sortValue = COIN_DBL_MAX;
2884                if (solver->isInteger(iColumn)) {
2885                    assert(fabs(value - solution[iColumn]) <= 1.0e-5) ;
2886                    double value2 = floor(value + 0.5);
2887                    if (dj[iColumn] < -1.0e-6) {
2888                        // negative dj
2889                        //assert (value2==colUpper[iColumn]);
2890                        if (saveUpper[iColumn] == colUpper[iColumn]) {
2891                            nAtUbNatural++;
2892                            sortValue = 0.0;
2893                            double value = -dj[iColumn];
2894                            if (value > gap)
2895                                nFix++;
2896                            else if (gap < value*bestRatio)
2897                                bestRatio = gap / value;
2898                            if (saveLower[iColumn] != colLower[iColumn]) {
2899                                nNotNeeded++;
2900                                sortValue = 1.0e20;
2901                            }
2902                        } else if (saveLower[iColumn] == colUpper[iColumn]) {
2903                            nAtLbFixed++;
2904                            sortValue = dj[iColumn];
2905                        } else {
2906                            nAtOther++;
2907                            sortValue = 0.0;
2908                            if (saveLower[iColumn] != colLower[iColumn] &&
2909                                    saveUpper[iColumn] != colUpper[iColumn]) {
2910                                nNotNeeded++;
2911                                sortValue = 1.0e20;
2912                            }
2913                        }
2914                    } else if (dj[iColumn] > 1.0e-6) {
2915                        // positive dj
2916                        //assert (value2==colLower[iColumn]);
2917                        if (saveLower[iColumn] == colLower[iColumn]) {
2918                            nAtLbNatural++;
2919                            sortValue = 0.0;
2920                            double value = dj[iColumn];
2921                            if (value > gap)
2922                                nFix++;
2923                            else if (gap < value*bestRatio)
2924                                bestRatio = gap / value;
2925                            if (saveUpper[iColumn] != colUpper[iColumn]) {
2926                                nNotNeeded++;
2927                                sortValue = 1.0e20;
2928                            }
2929                        } else if (saveUpper[iColumn] == colLower[iColumn]) {
2930                            nAtUbFixed++;
2931                            sortValue = -dj[iColumn];
2932                        } else {
2933                            nAtOther++;
2934                            sortValue = 0.0;
2935                            if (saveLower[iColumn] != colLower[iColumn] &&
2936                                    saveUpper[iColumn] != colUpper[iColumn]) {
2937                                nNotNeeded++;
2938                                sortValue = 1.0e20;
2939                            }
2940                        }
2941                    } else {
2942                        // zero dj
2943                        if (value2 == saveUpper[iColumn]) {
2944                            nAtUbNaturalZero++;
2945                            sortValue = 0.0;
2946                            if (saveLower[iColumn] != colLower[iColumn]) {
2947                                nNotNeeded++;
2948                                sortValue = 1.0e20;
2949                            }
2950                        } else if (value2 == saveLower[iColumn]) {
2951                            nAtLbNaturalZero++;
2952                            sortValue = 0.0;
2953                        } else {
2954                            nAtOtherNatural++;
2955                            sortValue = 0.0;
2956                            if (saveLower[iColumn] != colLower[iColumn] &&
2957                                    saveUpper[iColumn] != colUpper[iColumn]) {
2958                                nNotNeeded++;
2959                                sortValue = 1.0e20;
2960                            }
2961                        }
2962                    }
2963#if HOTSTART==3
2964                    sortValue = -fabs(dj[iColumn]);
2965#endif
2966                }
2967                hotstartSolution_[iColumn] = value ;
2968                saveLower[iColumn] = sortValue;
2969                order[iColumn] = iColumn;
2970            }
2971            printf("** can fix %d columns - best ratio for others is %g on gap of %g\n",
2972                   nFix, bestRatio, gap);
2973            int nNeg = 0;
2974            CoinSort_2(saveLower, saveLower + numberColumns, order);
2975            for (int i = 0; i < numberColumns; i++) {
2976                if (saveLower[i] < 0.0) {
2977                    nNeg++;
2978#if HOTSTART==2||HOTSTART==3
2979                    // swap sign ?
2980                    saveLower[i] = -saveLower[i];
2981#endif
2982                }
2983            }
2984            CoinSort_2(saveLower, saveLower + nNeg, order);
2985            for (int i = 0; i < numberColumns; i++) {
2986#if HOTSTART==1
2987                hotstartPriorities_[order[i]] = 100;
2988#else
2989                hotstartPriorities_[order[i]] = -(i + 1);
2990#endif
2991            }
2992            printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n",
2993                   nAtLbNatural,
2994                   nAtUbNatural,
2995                   nAtLbNaturalZero,
2996                   nAtUbNaturalZero,
2997                   nAtLbFixed,
2998                   nAtUbFixed,
2999                   nAtOther,
3000                   nAtOtherNatural, nNotNeeded, nNeg);
3001            delete [] saveLower;
3002            delete [] saveUpper;
3003            if (!saveCompare) {
3004                // create depth first comparison
3005                saveCompare = nodeCompare_;
3006                // depth first
3007                nodeCompare_ = new CbcCompareDepth();
3008                tree_->setComparison(*nodeCompare_) ;
3009            }
3010        }
3011#endif
3012        newNode = new CbcNode ;
3013        // Set objective value (not so obvious if NLP etc)
3014        setObjectiveValue(newNode, NULL);
3015        anyAction = -1 ;
3016        // To make depth available we may need a fake node
3017        CbcNode fakeNode;
3018        if (!currentNode_) {
3019            // Not true if sub trees assert (!numberNodes_);
3020            currentNode_ = &fakeNode;
3021        }
3022        phase_ = 3;
3023        // only allow 1000 passes
3024        int numberPassesLeft = 1000;
3025        // This is first crude step
3026        if (numberAnalyzeIterations_) {
3027            delete [] analyzeResults_;
3028            analyzeResults_ = new double [4*numberIntegers_];
3029            numberFixedAtRoot_ = newNode->analyze(this, analyzeResults_);
3030            if (numberFixedAtRoot_ > 0) {
3031                printf("%d fixed by analysis\n", numberFixedAtRoot_);
3032                setPointers(solver_);
3033                numberFixedNow_ = numberFixedAtRoot_;
3034            } else if (numberFixedAtRoot_ < 0) {
3035                printf("analysis found to be infeasible\n");
3036                anyAction = -2;
3037                delete newNode ;
3038                newNode = NULL ;
3039                feasible = false ;
3040            }
3041        }
3042        OsiSolverBranch * branches = NULL;
3043        anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts, resolved,
3044                                 NULL, NULL, NULL, branches);
3045        if (anyAction == -2 || newNode->objectiveValue() >= cutoff) {
3046            if (anyAction != -2) {
3047                // zap parent nodeInfo
3048#ifdef COIN_DEVELOP
3049                printf("zapping CbcNodeInfo %x\n", reinterpret_cast<int>(newNode->nodeInfo()->parent()));
3050#endif
3051                if (newNode->nodeInfo())
3052                    newNode->nodeInfo()->nullParent();
3053            }
3054            delete newNode ;
3055            newNode = NULL ;
3056            feasible = false ;
3057        }
3058    }
3059    if (newNode && probingInfo_) {
3060        int number01 = probingInfo_->numberIntegers();
3061        //const fixEntry * entry = probingInfo_->fixEntries();
3062        const int * toZero = probingInfo_->toZero();
3063        //const int * toOne = probingInfo_->toOne();
3064        //const int * integerVariable = probingInfo_->integerVariable();
3065        if (toZero[number01]) {
3066            CglTreeProbingInfo info(*probingInfo_);
3067#if 0
3068            OsiSolverInterface * fake = info.analyze(*solver_, 1);
3069            if (fake) {
3070                fake->writeMps("fake");
3071                CglFakeClique cliqueGen(fake);
3072                cliqueGen.setStarCliqueReport(false);
3073                cliqueGen.setRowCliqueReport(false);
3074                cliqueGen.setMinViolation(0.1);
3075                addCutGenerator(&cliqueGen, 1, "Fake cliques", true, false, false, -200);
3076                generator_[numberCutGenerators_-1]->setTiming(true);
3077            }
3078#endif
3079            if (probingInfo_->packDown()) {
3080#ifdef CLP_INVESTIGATE
3081                printf("%d implications on %d 0-1\n", toZero[number01], number01);
3082#endif
3083                CglImplication implication(probingInfo_);
3084                addCutGenerator(&implication, 1, "ImplicationCuts", true, false, false, -200);
3085            } else {
3086                delete probingInfo_;
3087                probingInfo_ = NULL;
3088            }
3089        } else {
3090            delete probingInfo_;
3091
3092            probingInfo_ = NULL;
3093        }
3094    }
3095    /*
3096      At this point, the root subproblem is infeasible or fathomed by bound
3097      (newNode == NULL), or we're live with an objective value that satisfies the
3098      current objective cutoff.
3099    */
3100    assert (!newNode || newNode->objectiveValue() <= cutoff) ;
3101    // Save address of root node as we don't want to delete it
3102    // initialize for print out
3103    int lastDepth = 0;
3104    int lastUnsatisfied = 0;
3105    if (newNode)
3106        lastUnsatisfied = newNode->numberUnsatisfied();
3107    /*
3108      The common case is that the lp relaxation is feasible but doesn't satisfy
3109      integrality (i.e., newNode->branchingObject(), indicating we've been able to
3110      select a branching variable). Remove any cuts that have gone slack due to
3111      forcing monotone variables. Then tack on an CbcFullNodeInfo object and full
3112      basis (via createInfo()) and stash the new cuts in the nodeInfo (via
3113      addCuts()). If, by some miracle, we have an integral solution at the root
3114      (newNode->branchingObject() is NULL), takeOffCuts() will ensure that the solver holds
3115      a valid solution for use by setBestSolution().
3116    */
3117    CoinWarmStartBasis *lastws = NULL ;
3118    if (feasible && newNode->branchingObject()) {
3119        if (resolved) {
3120            takeOffCuts(cuts, false, NULL) ;
3121#     ifdef CHECK_CUT_COUNTS
3122            { printf("Number of rows after chooseBranch fix (root)"
3123                         "(active only) %d\n",
3124                         numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_) ;
3125                const CoinWarmStartBasis* debugws =
3126                    dynamic_cast <const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
3127                debugws->print() ;
3128                delete debugws ;
3129            }
3130#     endif
3131        }
3132        //newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
3133        //newNode->nodeInfo()->addCuts(cuts,
3134        //                       newNode->numberBranches(),whichGenerator_) ;
3135        if (lastws) delete lastws ;
3136        lastws = dynamic_cast<CoinWarmStartBasis*>(solver_->getWarmStart()) ;
3137    }
3138    /*
3139      Continuous data to be used later
3140    */
3141    continuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
3142    continuousInfeasibilities_ = 0 ;
3143    if (newNode) {
3144        continuousObjective_ = newNode->objectiveValue() ;
3145        delete [] continuousSolution_;
3146        continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
3147                                              numberColumns);
3148        continuousInfeasibilities_ = newNode->numberUnsatisfied() ;
3149    }
3150    /*
3151      Bound may have changed so reset in objects
3152    */
3153    {
3154        int i ;
3155        for (i = 0; i < numberObjects_; i++)
3156            object_[i]->resetBounds(solver_) ;
3157    }
3158    /*
3159      Feasible? Then we should have either a live node prepped for future
3160      expansion (indicated by variable() >= 0), or (miracle of miracles) an
3161      integral solution at the root node.
3162
3163      initializeInfo sets the reference counts in the nodeInfo object.  Since
3164      this node is still live, push it onto the heap that holds the live set.
3165    */
3166    double bestValue = 0.0 ;
3167    if (newNode) {
3168        bestValue = newNode->objectiveValue();
3169        if (newNode->branchingObject()) {
3170            newNode->initializeInfo() ;
3171            tree_->push(newNode) ;
3172            if (statistics_) {
3173                if (numberNodes2_ == maximumStatistics_) {
3174                    maximumStatistics_ = 2 * maximumStatistics_;
3175                    CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
3176                    memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *));
3177                    memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *));
3178                    delete [] statistics_;
3179                    statistics_ = temp;
3180                }
3181                assert (!statistics_[numberNodes2_]);
3182                statistics_[numberNodes2_] = new CbcStatistics(newNode, this);
3183            }
3184            numberNodes2_++;
3185#     ifdef CHECK_NODE
3186            printf("Node %x on tree\n", newNode) ;
3187#     endif
3188        } else {
3189            // continuous is integer
3190            double objectiveValue = newNode->objectiveValue();
3191            setBestSolution(CBC_SOLUTION, objectiveValue,
3192                            solver_->getColSolution()) ;
3193            delete newNode ;
3194            newNode = NULL ;
3195        }
3196    }
3197
3198    if (printFrequency_ <= 0) {
3199        printFrequency_ = 1000 ;
3200        if (getNumCols() > 2000)
3201            printFrequency_ = 100 ;
3202    }
3203    /*
3204      It is possible that strong branching fixes one variable and then the code goes round
3205      again and again.  This can take too long.  So we need to warn user - just once.
3206    */
3207    numberLongStrong_ = 0;
3208    CbcNode * createdNode = NULL;
3209#ifdef CBC_THREAD
3210    CbcModel ** threadModel = NULL;
3211    Coin_pthread_t * threadId = NULL;
3212    int * threadCount = NULL;
3213    pthread_mutex_t mutex;
3214    pthread_cond_t condition_main;
3215    pthread_mutex_t condition_mutex;
3216    pthread_mutex_t * mutex2 = NULL;
3217    pthread_cond_t * condition2 = NULL;
3218    threadStruct * threadInfo = NULL;
3219    bool locked = false;
3220    int threadStats[6];
3221    int defaultParallelIterations = 400;
3222    int defaultParallelNodes = 2;
3223    memset(threadStats, 0, sizeof(threadStats));
3224    double timeWaiting = 0.0;
3225    // For now just one model
3226    if (numberThreads_) {
3227        nodeCompare_->sayThreaded(); // need to use addresses
3228        threadId = new Coin_pthread_t [numberThreads_];
3229        threadCount = new int [numberThreads_];
3230        CoinZeroN(threadCount, numberThreads_);
3231        pthread_mutex_init(&mutex, NULL);
3232        pthread_cond_init(&condition_main, NULL);
3233        pthread_mutex_init(&condition_mutex, NULL);
3234        threadModel = new CbcModel * [numberThreads_+1];
3235        threadInfo = new threadStruct [numberThreads_+1];
3236        mutex2 = new pthread_mutex_t [numberThreads_];
3237        condition2 = new pthread_cond_t [numberThreads_];
3238        if (parallelMode() < -1) {
3239            // May need for deterministic
3240            saveObjects = new OsiObject * [numberObjects_];
3241            for (int i = 0; i < numberObjects_; i++) {
3242                saveObjects[i] = object_[i]->clone();
3243            }
3244        }
3245        // we don't want a strategy object
3246        CbcStrategy * saveStrategy = strategy_;
3247        strategy_ = NULL;
3248        for (int i = 0; i < numberThreads_; i++) {
3249            pthread_mutex_init(mutex2 + i, NULL);
3250            pthread_cond_init(condition2 + i, NULL);
3251            threadId[i].status = 0;
3252            threadInfo[i].baseModel = this;
3253            threadModel[i] = new CbcModel(*this, true);
3254            threadModel[i]->synchronizeHandlers(1);
3255#ifdef COIN_HAS_CLP
3256            // Solver may need to know about model
3257            CbcModel * thisModel = threadModel[i];
3258            CbcOsiSolver * solver =
3259                dynamic_cast<CbcOsiSolver *>(thisModel->solver()) ;
3260            if (solver)
3261                solver->setCbcModel(thisModel);
3262#endif
3263            mutex_ = reinterpret_cast<void *> (threadInfo + i);
3264            threadModel[i]->moveToModel(this, -1);
3265            threadInfo[i].thisModel = threadModel[i];
3266            threadInfo[i].node = NULL;
3267            threadInfo[i].createdNode = NULL;
3268            threadInfo[i].threadIdOfBase.thr = pthread_self();
3269            threadInfo[i].mutex = &mutex;
3270            threadInfo[i].mutex2 = mutex2 + i;
3271            threadInfo[i].condition2 = condition2 + i;
3272            threadInfo[i].returnCode = -1;
3273            threadInfo[i].timeLocked = 0.0;
3274            threadInfo[i].timeWaitingToLock = 0.0;
3275            threadInfo[i].timeWaitingToStart = 0.0;
3276            threadInfo[i].timeInThread = 0.0;
3277            threadInfo[i].numberTimesLocked = 0;
3278            threadInfo[i].numberTimesUnlocked = 0;
3279            threadInfo[i].numberTimesWaitingToStart = 0;
3280            threadInfo[i].dantzigState = 0; // 0 unset, -1 waiting to be set, 1 set
3281            threadInfo[i].locked = false;
3282            threadInfo[i].delNode = NULL;
3283            threadInfo[i].maxDeleteNode = 0;
3284            threadInfo[i].nDeleteNode = 0;
3285            threadInfo[i].nodesThisTime = 0;
3286            threadInfo[i].iterationsThisTime = 0;
3287            pthread_create(&(threadId[i].thr), NULL, doNodesThread, threadInfo + i);
3288            threadId[i].status = 1;
3289        }
3290        strategy_ = saveStrategy;
3291        // Do a partial one for base model
3292        threadInfo[numberThreads_].baseModel = this;
3293        threadModel[numberThreads_] = this;
3294        mutex_ = reinterpret_cast<void *> (threadInfo + numberThreads_);
3295        threadInfo[numberThreads_].node = NULL;
3296        threadInfo[numberThreads_].mutex = &mutex;
3297        threadInfo[numberThreads_].condition2 = &condition_main;
3298        threadInfo[numberThreads_].mutex2 = &condition_mutex;
3299        threadInfo[numberThreads_].timeLocked = 0.0;
3300        threadInfo[numberThreads_].timeWaitingToLock = 0.0;
3301        threadInfo[numberThreads_].numberTimesLocked = 0;
3302        threadInfo[numberThreads_].numberTimesUnlocked = 0;
3303        threadInfo[numberThreads_].locked = false;
3304    }
3305#endif
3306#ifdef COIN_HAS_CLP
3307    {
3308        OsiClpSolverInterface * clpSolver
3309        = dynamic_cast<OsiClpSolverInterface *> (solver_);
3310        if (clpSolver && !parentModel_) {
3311            clpSolver->computeLargestAway();
3312        }
3313    }
3314#endif
3315    /*
3316      At last, the actual branch-and-cut search loop, which will iterate until
3317      the live set is empty or we hit some limit (integrality gap, time, node
3318      count, etc.). The overall flow is to rebuild a subproblem, reoptimise using
3319      solveWithCuts(), choose a branching pattern with chooseBranch(), and finally
3320      add the node to the live set.
3321
3322      The first action is to winnow the live set to remove nodes which are worse
3323      than the current objective cutoff.
3324    */
3325    if (solver_->getRowCutDebuggerAlways()) {
3326        OsiRowCutDebugger * debuggerX = const_cast<OsiRowCutDebugger *> (solver_->getRowCutDebuggerAlways());
3327        const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
3328        if (!debugger) {
3329            // infeasible!!
3330            printf("before search\n");
3331            const double * lower = solver_->getColLower();
3332            const double * upper = solver_->getColUpper();
3333            const double * solution = debuggerX->optimalSolution();
3334            int numberColumns = solver_->getNumCols();
3335            for (int i = 0; i < numberColumns; i++) {
3336                if (solver_->isInteger(i)) {
3337                    if (solution[i] < lower[i] - 1.0e-6 || solution[i] > upper[i] + 1.0e-6)
3338                        printf("**** ");
3339                    printf("%d %g <= %g <= %g\n",
3340                           i, lower[i], solution[i], upper[i]);
3341                }
3342            }
3343            //abort();
3344        }
3345    }
3346    {
3347        // may be able to change cutoff now
3348        double cutoff = getCutoff();
3349        double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
3350        if (cutoff > bestObjective_ - increment) {
3351            cutoff = bestObjective_ - increment ;
3352            setCutoff(cutoff) ;
3353        }
3354    }
3355#ifdef CBC_THREAD
3356    bool goneParallel = false;
3357#endif
3358#define MAX_DEL_NODE 1
3359    CbcNode * delNode[MAX_DEL_NODE+1];
3360    int nDeleteNode = 0;
3361    // For Printing etc when parallel
3362    int lastEvery1000 = 0;
3363    int lastPrintEvery = 0;
3364    int numberConsecutiveInfeasible = 0;
3365    while (true) {
3366#ifdef CBC_THREAD
3367        if (parallelMode() > 0 && !locked) {
3368            lockThread();
3369            locked = true;
3370        }
3371#endif
3372#ifdef COIN_HAS_CLP
3373        // Possible change of pivot method
3374        if (!savePivotMethod && !parentModel_) {
3375                        OsiClpSolverInterface * clpSolver
3376                        = dynamic_cast<OsiClpSolverInterface *> (solver_);
3377                        if (clpSolver && numberNodes_ >= 100 && numberNodes_ < 200) {
3378                                if (numberIterations_ < (numberSolves_ + numberNodes_)*10) {
3379                                        //if (numberIterations_<numberNodes_*20) {
3380                                        ClpSimplex * simplex = clpSolver->getModelPtr();
3381                                        ClpDualRowPivot * pivotMethod = simplex->dualRowPivot();
3382                                        ClpDualRowDantzig * pivot =
3383                                                dynamic_cast< ClpDualRowDantzig*>(pivotMethod);
3384                                        if (!pivot) {
3385                                                savePivotMethod = pivotMethod->clone(true);
3386                                                ClpDualRowDantzig dantzig;
3387                                                simplex->setDualRowPivotAlgorithm(dantzig);
3388                #ifdef COIN_DEVELOP
3389                                                printf("%d node, %d iterations ->Dantzig\n", numberNodes_,
3390                                                           numberIterations_);
3391                #endif
3392                #ifdef CBC_THREAD
3393                                                for (int i = 0; i < numberThreads_; i++) {
3394                                                        threadInfo[i].dantzigState = -1;
3395                                                }
3396                #endif
3397                                        }
3398                                }
3399                        }
3400        }
3401#endif
3402        if (tree_->empty()) {
3403#ifdef CBC_THREAD
3404            if (parallelMode() > 0) {
3405#ifdef COIN_DEVELOP
3406                printf("empty\n");
3407#endif
3408                // may still be outstanding nodes
3409                int iThread;
3410                for (iThread = 0; iThread < numberThreads_; iThread++) {
3411                    if (threadId[iThread].status) {
3412                        if (threadInfo[iThread].returnCode == 0)
3413                            break;
3414                    }
3415                }
3416                if (iThread < numberThreads_) {
3417#ifdef COIN_DEVELOP
3418                    printf("waiting for thread %d code 0\n", iThread);
3419#endif
3420                    if (parallelMode() > 0) {
3421                        unlockThread();
3422                        locked = false;
3423                    }
3424                    pthread_cond_signal(threadInfo[iThread].condition2); // unlock in case
3425                    while (true) {
3426                        pthread_mutex_lock(&condition_mutex);
3427                        struct timespec absTime;
3428                        my_gettime(&absTime);
3429                        double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3430                        absTime.tv_nsec += 1000000; // millisecond
3431                        if (absTime.tv_nsec >= 1000000000) {
3432                            absTime.tv_nsec -= 1000000000;
3433                            absTime.tv_sec++;
3434                        }
3435                        pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
3436                        my_gettime(&absTime);
3437                        double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3438                        timeWaiting += time2 - time;
3439                        pthread_mutex_unlock(&condition_mutex);
3440                        if (threadInfo[iThread].returnCode != 0)
3441                            break;
3442                        pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3443                    }
3444                    threadModel[iThread]->moveToModel(this, 1);
3445                    assert (threadInfo[iThread].returnCode == 1);
3446                    if (threadInfo[iThread].dantzigState == -1) {
3447                        // 0 unset, -1 waiting to be set, 1 set
3448                        threadInfo[iThread].dantzigState = 1;
3449                        CbcModel * model = threadInfo[iThread].thisModel;
3450                        OsiClpSolverInterface * clpSolver2
3451                        = dynamic_cast<OsiClpSolverInterface *> (model->solver());
3452                        assert (clpSolver2);
3453                        ClpSimplex * simplex2 = clpSolver2->getModelPtr();
3454                        ClpDualRowDantzig dantzig;
3455                        simplex2->setDualRowPivotAlgorithm(dantzig);
3456                    }
3457                    // say available
3458                    threadInfo[iThread].returnCode = -1;
3459                    threadStats[4]++;
3460#ifdef COIN_DEVELOP
3461                    printf("thread %d code now -1\n", iThread);
3462#endif
3463                    continue;
3464                } else {
3465#ifdef COIN_DEVELOP
3466                    printf("no threads at code 0 \n");
3467#endif
3468                    // now check if any have just finished
3469                    for (iThread = 0; iThread < numberThreads_; iThread++) {
3470                        if (threadId[iThread].status) {
3471                            if (threadInfo[iThread].returnCode == 1)
3472                                break;
3473                        }
3474                    }
3475                    if (iThread < numberThreads_) {
3476                        if (parallelMode() > 0) {
3477                            unlockThread();
3478                            locked = false;
3479                        }
3480                        threadModel[iThread]->moveToModel(this, 1);
3481                        assert (threadInfo[iThread].returnCode == 1);
3482                        // say available
3483                        threadInfo[iThread].returnCode = -1;
3484                        threadStats[4]++;
3485#ifdef COIN_DEVELOP
3486                        printf("thread %d code now -1\n", iThread);
3487#endif
3488                        continue;
3489                    }
3490                }
3491                if (!tree_->empty()) {
3492#ifdef COIN_DEVELOP
3493                    printf("tree not empty!!!!!!\n");
3494#endif
3495                    continue;
3496                }
3497                for (iThread = 0; iThread < numberThreads_; iThread++) {
3498                    if (threadId[iThread].status) {
3499                        if (threadInfo[iThread].returnCode != -1) {
3500                            printf("bad end of tree\n");
3501                            abort();
3502                        }
3503                    }
3504                }
3505#ifdef COIN_DEVELOP
3506                printf("finished ************\n");
3507#endif
3508                unlockThread();
3509                locked = false; // not needed as break
3510            }
3511#endif
3512            break;
3513        }
3514#ifdef CBC_THREAD
3515        if (parallelMode() > 0) {
3516            unlockThread();
3517            locked = false;
3518        }
3519#endif
3520        // If done 100 nodes see if worth trying reduction
3521        if (numberNodes_ == 50 || numberNodes_ == 100) {
3522#ifdef COIN_HAS_CLP
3523            OsiClpSolverInterface * clpSolver
3524            = dynamic_cast<OsiClpSolverInterface *> (solver_);
3525            if (clpSolver && ((specialOptions_&131072) == 0) && true) {
3526                ClpSimplex * simplex = clpSolver->getModelPtr();
3527                int perturbation = simplex->perturbation();
3528#ifdef CLP_INVESTIGATE
3529                printf("Testing its n,s %d %d solves n,s %d %d - pert %d\n",
3530                       numberIterations_, saveNumberIterations,
3531                       numberSolves_, saveNumberSolves, perturbation);
3532#endif
3533                if (perturbation == 50 && (numberIterations_ - saveNumberIterations) <
3534                        8*(numberSolves_ - saveNumberSolves)) {
3535                    // switch off perturbation
3536                    simplex->setPerturbation(100);
3537#ifdef PERTURB_IN_FATHOM
3538                    // but allow in fathom
3539                    specialOptions_ |= 131072;
3540#endif
3541#ifdef CLP_INVESTIGATE
3542                    printf("Perturbation switched off\n");
3543#endif
3544                }
3545            }
3546#endif
3547            if (saveSolver) {
3548                bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() &&
3549                                    (getCutoff() < 1.0e20 && getCutoff() < checkCutoffForRestart);
3550                int numberColumns = getNumCols();
3551                if (tryNewSearch) {
3552                    checkCutoffForRestart = getCutoff() ;
3553#ifdef CLP_INVESTIGATE
3554                    printf("after %d nodes, cutoff %g - looking\n",
3555                           numberNodes_, getCutoff());
3556#endif
3557                    saveSolver->resolve();
3558                    double direction = saveSolver->getObjSense() ;
3559                    double gap = checkCutoffForRestart - saveSolver->getObjValue() * direction ;
3560                    double tolerance;
3561                    saveSolver->getDblParam(OsiDualTolerance, tolerance) ;
3562                    if (gap <= 0.0)
3563                        gap = tolerance;
3564                    gap += 100.0 * tolerance;
3565                    double integerTolerance = getDblParam(CbcIntegerTolerance) ;
3566
3567                    const double *lower = saveSolver->getColLower() ;
3568                    const double *upper = saveSolver->getColUpper() ;
3569                    const double *solution = saveSolver->getColSolution() ;
3570                    const double *reducedCost = saveSolver->getReducedCost() ;
3571
3572                    int numberFixed = 0 ;
3573                    int numberFixed2 = 0;
3574#ifdef COIN_DEVELOP
3575                    printf("gap %g\n", gap);
3576#endif
3577                    for (int i = 0 ; i < numberIntegers_ ; i++) {
3578                        int iColumn = integerVariable_[i] ;
3579                        double djValue = direction * reducedCost[iColumn] ;
3580                        if (upper[iColumn] - lower[iColumn] > integerTolerance) {
3581                            if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
3582                                //printf("%d to lb on dj of %g - bounds %g %g\n",
3583                                //     iColumn,djValue,lower[iColumn],upper[iColumn]);
3584                                saveSolver->setColUpper(iColumn, lower[iColumn]) ;
3585                                numberFixed++ ;
3586                            } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
3587                                //printf("%d to ub on dj of %g - bounds %g %g\n",
3588                                //     iColumn,djValue,lower[iColumn],upper[iColumn]);
3589                                saveSolver->setColLower(iColumn, upper[iColumn]) ;
3590                                numberFixed++ ;
3591                            }
3592                        } else {
3593                            //printf("%d has dj of %g - already fixed to %g\n",
3594                            //     iColumn,djValue,lower[iColumn]);
3595                            numberFixed2++;
3596                        }
3597                    }
3598#ifdef COIN_DEVELOP
3599                    if ((specialOptions_&1) != 0) {
3600                        const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ;
3601                        if (debugger) {
3602                            printf("Contains optimal\n") ;
3603                            OsiSolverInterface * temp = saveSolver->clone();
3604                            const double * solution = debugger->optimalSolution();
3605                            const double *lower = temp->getColLower() ;
3606                            const double *upper = temp->getColUpper() ;
3607                            int n = temp->getNumCols();
3608                            for (int i = 0; i < n; i++) {
3609                                if (temp->isInteger(i)) {
3610                                    double value = floor(solution[i] + 0.5);
3611                                    assert (value >= lower[i] && value <= upper[i]);
3612                                    temp->setColLower(i, value);
3613                                    temp->setColUpper(i, value);
3614                                }
3615                            }
3616                            temp->writeMps("reduced_fix");
3617                            delete temp;
3618                            saveSolver->writeMps("reduced");
3619                        } else {
3620                            abort();
3621                        }
3622                    }
3623                    printf("Restart could fix %d integers (%d already fixed)\n",
3624                           numberFixed + numberFixed2, numberFixed2);
3625#endif
3626                    numberFixed += numberFixed2;
3627                    if (numberFixed*10 < numberColumns && numberFixed*4 < numberIntegers_)
3628                        tryNewSearch = false;
3629                }
3630                if (tryNewSearch) {
3631                    // back to solver without cuts?
3632                    OsiSolverInterface * solver2 = saveSolver->clone();
3633                    const double *lower = saveSolver->getColLower() ;
3634                    const double *upper = saveSolver->getColUpper() ;
3635                    for (int i = 0 ; i < numberIntegers_ ; i++) {
3636                        int iColumn = integerVariable_[i] ;
3637                        solver2->setColLower(iColumn, lower[iColumn]);
3638                        solver2->setColUpper(iColumn, upper[iColumn]);
3639                    }
3640                    // swap
3641                    delete saveSolver;
3642                    saveSolver = solver2;
3643                    double * newSolution = new double[numberColumns];
3644                    double objectiveValue = checkCutoffForRestart;
3645                    CbcSerendipity heuristic(*this);
3646                    if (bestSolution_)
3647                        heuristic.setInputSolution(bestSolution_, bestObjective_);
3648                    heuristic.setFractionSmall(0.8);
3649                    heuristic.setFeasibilityPumpOptions(1008013);
3650                    // Use numberNodes to say how many are original rows
3651                    heuristic.setNumberNodes(continuousSolver_->getNumRows());
3652#ifdef COIN_DEVELOP
3653                    if (continuousSolver_->getNumRows() <
3654                            solver_->getNumRows())
3655                        printf("%d rows added ZZZZZ\n",
3656                               solver_->getNumRows() - continuousSolver_->getNumRows());
3657#endif
3658                    int returnCode = heuristic.smallBranchAndBound(saveSolver,
3659                                     -1, newSolution,
3660                                     objectiveValue,
3661                                     checkCutoffForRestart, "Reduce");
3662                    if (returnCode < 0) {
3663#ifdef COIN_DEVELOP
3664                        printf("Restart - not small enough to do search after fixing\n");
3665#endif
3666                        delete [] newSolution;
3667                    } else {
3668                        if ((returnCode&1) != 0) {
3669                            // increment number of solutions so other heuristics can test
3670                            numberSolutions_++;
3671                            numberHeuristicSolutions_++;
3672                            lastHeuristic_ = NULL;
3673                            setBestSolution(CBC_ROUNDING, objectiveValue, newSolution) ;
3674                        }
3675                        delete [] newSolution;
3676                        if (tree_->size()) {
3677                            double dummyBest;
3678                            tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
3679                        }
3680                        break;
3681                    }
3682                }
3683                delete saveSolver;
3684                saveSolver = NULL;
3685            }
3686        }
3687        /*
3688          Check for abort on limits: node count, solution count, time, integrality gap.
3689        */
3690        if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
3691                numberSolutions_ < intParam_[CbcMaxNumSol] &&
3692                !maximumSecondsReached() &&
3693                !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 ||
3694                                                      numberIterations_ < maximumNumberIterations_))) {
3695            // out of loop
3696            break;
3697        }
3698#ifdef BONMIN
3699        assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible());
3700#endif
3701#define DIVE_WHEN 1000
3702#define DIVE_STOP 2000
3703        int kNode = numberNodes_ % 4000;
3704        if (numberNodes_<100000 && kNode>DIVE_WHEN && kNode <= DIVE_STOP) {
3705            if (!parallelMode()) {
3706                if (kNode == DIVE_WHEN + 1 || numberConsecutiveInfeasible > 1) {
3707                    CbcCompareDefault * compare = dynamic_cast<CbcCompareDefault *>
3708                                                  (nodeCompare_);
3709                    if (compare) {
3710                        //printf("Redoing tree\n");
3711                        compare->startDive(this);
3712                        numberConsecutiveInfeasible = 0;
3713                    }
3714                }
3715            }
3716        }
3717        if (cutoff > getCutoff()) {
3718            double newCutoff = getCutoff();
3719            if (analyzeResults_) {
3720                // see if we could fix any (more)
3721                int n = 0;
3722                double * newLower = analyzeResults_;
3723                double * objLower = newLower + numberIntegers_;
3724                double * newUpper = objLower + numberIntegers_;
3725                double * objUpper = newUpper + numberIntegers_;
3726                for (int i = 0; i < numberIntegers_; i++) {
3727                    if (objLower[i] > newCutoff) {
3728                        n++;
3729                        if (objUpper[i] > newCutoff) {
3730                            newCutoff = -COIN_DBL_MAX;
3731                            break;
3732                        }
3733                    } else if (objUpper[i] > newCutoff) {
3734                        n++;
3735                    }
3736                }
3737                if (newCutoff == -COIN_DBL_MAX) {
3738                    printf("Root analysis says finished\n");
3739                } else if (n > numberFixedNow_) {
3740                    printf("%d more fixed by analysis - now %d\n", n - numberFixedNow_, n);
3741                    numberFixedNow_ = n;
3742                }
3743            }
3744            if (eventHandler) {
3745                if (!eventHandler->event(CbcEventHandler::solution)) {
3746                    eventHappened_ = true; // exit
3747                }
3748                newCutoff = getCutoff();
3749            }
3750            if (parallelMode() > 0)
3751                lockThread();
3752            // Do from deepest
3753            tree_->cleanTree(this, newCutoff, bestPossibleObjective_) ;
3754            nodeCompare_->newSolution(this) ;
3755            nodeCompare_->newSolution(this, continuousObjective_,
3756                                      continuousInfeasibilities_) ;
3757            tree_->setComparison(*nodeCompare_) ;
3758            if (tree_->empty()) {
3759                if (parallelMode() > 0)
3760                    unlockThread();
3761                // For threads we need to check further
3762                //break; // finished
3763                continue;
3764            }
3765            if (parallelMode() > 0)
3766                unlockThread();
3767        }
3768        cutoff = getCutoff() ;
3769        /*
3770            Periodic activities: Opportunities to
3771            + tweak the nodeCompare criteria,
3772            + check if we've closed the integrality gap enough to quit,
3773            + print a summary line to let the user know we're working
3774        */
3775        if (numberNodes_ >= lastEvery1000) {
3776            if (parallelMode() > 0)
3777                lockThread();
3778#ifdef COIN_HAS_CLP
3779            // Possible change of pivot method
3780            if (!savePivotMethod && !parentModel_) {
3781                                OsiClpSolverInterface * clpSolver
3782                                        = dynamic_cast<OsiClpSolverInterface *> (solver_);
3783                                if (clpSolver && numberNodes_ >= 1000 && numberNodes_ < 2000) {
3784                                        if (numberIterations_ < (numberSolves_ + numberNodes_)*10) {
3785                                                //if (numberIterations_<numberNodes_*20) {
3786                                                ClpSimplex * simplex = clpSolver->getModelPtr();
3787                                                ClpDualRowPivot * pivotMethod = simplex->dualRowPivot();
3788                                                ClpDualRowDantzig * pivot =
3789                                                        dynamic_cast< ClpDualRowDantzig*>(pivotMethod);
3790                                                if (!pivot) {
3791                                                        savePivotMethod = pivotMethod->clone(true);
3792                                                        ClpDualRowDantzig dantzig;
3793                                                        simplex->setDualRowPivotAlgorithm(dantzig);
3794                        #ifdef COIN_DEVELOP
3795                                                        printf("%d node, %d iterations ->Dantzig\n", numberNodes_,
3796                                                                   numberIterations_);
3797                        #endif
3798                        #ifdef CBC_THREAD
3799                                                        for (int i = 0; i < numberThreads_; i++) {
3800                                                                threadInfo[i].dantzigState = -1;
3801                                                        }
3802                        #endif
3803                                                }
3804                                        }
3805                                }
3806            }
3807#endif
3808            lastEvery1000 = numberNodes_ + 1000;
3809            bool redoTree = nodeCompare_->every1000Nodes(this, numberNodes_) ;
3810#ifdef CHECK_CUT_SIZE
3811            verifyCutSize (tree_, *this);
3812#endif
3813            // redo tree if wanted
3814            if (redoTree)
3815                tree_->setComparison(*nodeCompare_) ;
3816            if (parallelMode() > 0)
3817                unlockThread();
3818        }
3819        if (saveCompare && !hotstartSolution_) {
3820            // hotstart switched off
3821            delete nodeCompare_; // off depth first
3822            nodeCompare_ = saveCompare;
3823            saveCompare = NULL;
3824            // redo tree
3825            if (parallelMode() > 0)
3826                lockThread();
3827            tree_->setComparison(*nodeCompare_) ;
3828            if (parallelMode() > 0)
3829                unlockThread();
3830        }
3831        if (numberNodes_ >= lastPrintEvery) {
3832            lastPrintEvery = numberNodes_ + printFrequency_;
3833            if (parallelMode() > 0)
3834                lockThread();
3835            int nNodes = tree_->size() ;
3836
3837            //MODIF PIERRE
3838            bestPossibleObjective_ = tree_->getBestPossibleObjective();
3839            if (parallelMode() > 0)
3840                unlockThread();
3841#ifdef CLP_INVESTIGATE
3842            if (getCutoff() < 1.0e20) {
3843                if (fabs(getCutoff() - (bestObjective_ - getCutoffIncrement())) > 1.0e-6 &&
3844                        !parentModel_)
3845                    printf("model cutoff in status %g, best %g, increment %g\n",
3846                           getCutoff(), bestObjective_, getCutoffIncrement());
3847                assert (getCutoff() < bestObjective_ - getCutoffIncrement() +
3848                        1.0e-6 + 1.0e-10*fabs(bestObjective_));
3849            }
3850#endif
3851            if (!intParam_[CbcPrinting]) {
3852                messageHandler()->message(CBC_STATUS, messages())
3853                << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3854                << getCurrentSeconds()
3855                << CoinMessageEol ;
3856            } else if (intParam_[CbcPrinting] == 1) {
3857                messageHandler()->message(CBC_STATUS2, messages())
3858                << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3859                << lastDepth << lastUnsatisfied << numberIterations_
3860                << getCurrentSeconds()
3861                << CoinMessageEol ;
3862            } else if (!numberExtraIterations_) {
3863                messageHandler()->message(CBC_STATUS2, messages())
3864                << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3865                << lastDepth << lastUnsatisfied << numberIterations_
3866                << getCurrentSeconds()
3867                << CoinMessageEol ;
3868            } else {
3869                messageHandler()->message(CBC_STATUS3, messages())
3870                << numberNodes_ << numberExtraNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
3871                << lastDepth << lastUnsatisfied << numberIterations_ << numberExtraIterations_
3872                << getCurrentSeconds()
3873                << CoinMessageEol ;
3874            }
3875            if (eventHandler && !eventHandler->event(CbcEventHandler::treeStatus)) {
3876                eventHappened_ = true; // exit
3877            }
3878        }
3879        // See if can stop on gap
3880        double testGap = CoinMax(dblParam_[CbcAllowableGap],
3881                                 CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
3882                                 * dblParam_[CbcAllowableFractionGap]);
3883        if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0) {
3884            stoppedOnGap_ = true ;
3885        }
3886
3887#ifdef CHECK_NODE_FULL
3888        verifyTreeNodes(tree_, *this) ;
3889#   endif
3890#   ifdef CHECK_CUT_COUNTS
3891        verifyCutCounts(tree_, *this) ;
3892#   endif
3893        /*
3894          Now we come to the meat of the loop. To create the active subproblem, we'll
3895          pop the most promising node in the live set, rebuild the subproblem it
3896          represents, and then execute the current arm of the branch to create the
3897          active subproblem.
3898        */
3899        CbcNode * node = NULL;
3900#ifdef CBC_THREAD
3901        if (!parallelMode() || parallelMode() == -1) {
3902#endif
3903            node = tree_->bestNode(cutoff) ;
3904            // Possible one on tree worse than cutoff
3905            if (!node || node->objectiveValue() > cutoff)
3906                continue;
3907            // Do main work of solving node here
3908            doOneNode(this, node, createdNode);
3909#if 0
3910            if (node) {
3911                if (createdNode) {
3912                    printf("Node %d depth %d, created %d depth %d\n",
3913                           node->nodeNumber(), node->depth(),
3914                           createdNode->nodeNumber(), createdNode->depth());
3915                } else {
3916                    printf("Node %d depth %d,  no created node\n",
3917                           node->nodeNumber(), node->depth());
3918                }
3919            } else if (createdNode) {
3920                printf("Node exhausted, created %d depth %d\n",
3921                       createdNode->nodeNumber(), createdNode->depth());
3922            } else {
3923                printf("Node exhausted,  no created node\n");
3924                numberConsecutiveInfeasible = 2;
3925            }
3926#endif
3927            //if (createdNode)
3928            //numberConsecutiveInfeasible=0;
3929            //else
3930            //numberConsecutiveInfeasible++;
3931#ifdef CBC_THREAD
3932        } else if (parallelMode() > 0) {
3933            node = tree_->bestNode(cutoff) ;
3934            // Possible one on tree worse than cutoff
3935            if (!node || node->objectiveValue() > cutoff)
3936                continue;
3937            threadStats[0]++;
3938            //need to think
3939            int iThread;
3940            // Start one off if any available
3941            for (iThread = 0; iThread < numberThreads_; iThread++) {
3942                if (threadInfo[iThread].returnCode == -1)
3943                    break;
3944            }
3945            if (iThread < numberThreads_) {
3946                threadInfo[iThread].node = node;
3947                assert (threadInfo[iThread].returnCode == -1);
3948                // say in use
3949                threadModel[iThread]->moveToModel(this, 0);
3950                // This has to be AFTER moveToModel
3951                threadInfo[iThread].returnCode = 0;
3952                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
3953                threadCount[iThread]++;
3954            }
3955            lockThread();
3956            locked = true;
3957            // see if any finished
3958            for (iThread = 0; iThread < numberThreads_; iThread++) {
3959                if (threadInfo[iThread].returnCode > 0)
3960                    break;
3961            }
3962            unlockThread();
3963            locked = false;
3964            if (iThread < numberThreads_) {
3965                threadModel[iThread]->moveToModel(this, 1);
3966                assert (threadInfo[iThread].returnCode == 1);
3967                // say available
3968                threadInfo[iThread].returnCode = -1;
3969                // carry on
3970                threadStats[3]++;
3971            } else {
3972                // Start one off if any available
3973                for (iThread = 0; iThread < numberThreads_; iThread++) {
3974                    if (threadInfo[iThread].returnCode == -1)
3975                        break;
3976                }
3977                if (iThread < numberThreads_) {
3978                    lockThread();
3979                    locked = true;
3980                    // If any on tree get
3981                    if (!tree_->empty()) {
3982                        //node = tree_->bestNode(cutoff) ;
3983                        //assert (node);
3984                        threadStats[1]++;
3985                        continue; // ** get another node
3986                    }
3987                    unlockThread();
3988                    locked = false;
3989                }
3990                // wait (for debug could sleep and use test)
3991                bool finished = false;
3992                while (!finished) {
3993                    pthread_mutex_lock(&condition_mutex);
3994                    struct timespec absTime;
3995                    my_gettime(&absTime);
3996                    double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
3997                    absTime.tv_nsec += 1000000; // millisecond
3998                    if (absTime.tv_nsec >= 1000000000) {
3999                        absTime.tv_nsec -= 1000000000;
4000                        absTime.tv_sec++;
4001                    }
4002                    pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
4003                    my_gettime(&absTime);
4004                    double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
4005                    timeWaiting += time2 - time;
4006                    pthread_mutex_unlock(&condition_mutex);
4007                    for (iThread = 0; iThread < numberThreads_; iThread++) {
4008                        if (threadInfo[iThread].returnCode > 0) {
4009                            finished = true;
4010                            break;
4011                        } else if (threadInfo[iThread].returnCode == 0) {
4012                            pthread_cond_signal(threadInfo[iThread].condition2); // unlock
4013                        }
4014                    }
4015                }
4016                assert (iThread < numberThreads_);
4017                // move information to model
4018                threadModel[iThread]->moveToModel(this, 1);
4019                node = threadInfo[iThread].node;
4020                threadInfo[iThread].node = NULL;
4021                assert (threadInfo[iThread].returnCode == 1);
4022                // say available
4023                threadInfo[iThread].returnCode = -1;
4024                // carry on
4025                threadStats[2]++;
4026            }
4027        } else {
4028            // Deterministic parallel
4029            if (tree_->size() < CoinMin(numberThreads_, 8) && !goneParallel) {
4030                node = tree_->bestNode(cutoff) ;
4031                // Possible one on tree worse than cutoff
4032                if (!node || node->objectiveValue() > cutoff)
4033                    continue;
4034                // Do main work of solving node here
4035                doOneNode(this, node, createdNode);
4036                assert (createdNode);
4037                if (!createdNode->active()) {
4038                    delete createdNode;
4039                    createdNode = NULL;
4040                } else {
4041                    // Say one more pointing to this
4042                    node->nodeInfo()->increment() ;
4043                    tree_->push(createdNode) ;
4044                }
4045                if (node->active()) {
4046                    assert (node->nodeInfo());
4047                    if (node->nodeInfo()->numberBranchesLeft()) {
4048                        tree_->push(node) ;
4049                    } else {
4050                        node->setActive(false);
4051                    }
4052                } else {
4053                    if (node->nodeInfo()) {
4054                        if (!node->nodeInfo()->numberBranchesLeft())
4055                            node->nodeInfo()->allBranchesGone(); // can clean up
4056                        // So will delete underlying stuff
4057                        node->setActive(true);
4058                    }
4059                    delNode[nDeleteNode++] = node;
4060                    node = NULL;
4061                }
4062                if (nDeleteNode >= MAX_DEL_NODE) {
4063                    for (int i = 0; i < nDeleteNode; i++) {
4064                        //printf("trying to del %d %x\n",i,delNode[i]);
4065                        delete delNode[i];
4066                        //printf("done to del %d %x\n",i,delNode[i]);
4067                    }
4068                    nDeleteNode = 0;
4069                }
4070            } else {
4071                // Split
4072                int saveTreeSize = tree_->size();
4073                goneParallel = true;
4074                int nAffected = splitModel(numberThreads_, threadModel, defaultParallelNodes);
4075                int iThread;
4076                // do all until finished
4077                for (iThread = 0; iThread < numberThreads_; iThread++) {
4078                    // obviously tune
4079                    threadInfo[iThread].nDeleteNode = defaultParallelIterations;
4080                }
4081                // Save current state
4082                int iObject;
4083                for (iObject = 0; iObject < numberObjects_; iObject++) {
4084                    saveObjects[iObject]->updateBefore(object_[iObject]);
4085                }
4086                for (iThread = 0; iThread < numberThreads_; iThread++) {
4087                    threadInfo[iThread].returnCode = 0;
4088                    pthread_cond_signal(threadInfo[iThread].condition2); // unlock
4089                }
4090                // wait
4091                bool finished = false;
4092                while (!finished) {
4093                    pthread_mutex_lock(&condition_mutex);
4094                    struct timespec absTime;
4095                    my_gettime(&absTime);
4096                    double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
4097                    absTime.tv_nsec += 1000000; // millisecond
4098                    if (absTime.tv_nsec >= 1000000000) {
4099                        absTime.tv_nsec -= 1000000000;
4100                        absTime.tv_sec++;
4101                    }
4102                    pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
4103                    my_gettime(&absTime);
4104                    double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
4105                    timeWaiting += time2 - time;
4106                    pthread_mutex_unlock(&condition_mutex);
4107                    finished = true;
4108                    for (iThread = 0; iThread < numberThreads_; iThread++) {
4109                        if (threadInfo[iThread].returnCode <= 0) {
4110                            finished = false;
4111                        }
4112                    }
4113                }
4114                // Unmark marked
4115                for (int i = 0; i < nAffected; i++) {
4116                    walkback_[i]->unmark();
4117                }
4118                int iModel;
4119                double scaleFactor = 1.0;
4120                for (iModel = 0; iModel < numberThreads_; iModel++) {
4121                    //printf("model %d tree size %d\n",iModel,threadModel[iModel]->tree_->size());
4122                    if (saveTreeSize > 4*numberThreads_*defaultParallelNodes) {
4123                        if (!threadModel[iModel]->tree_->size()) {
4124                            scaleFactor *= 1.05;
4125                        }
4126                    }
4127                    threadModel[iModel]->moveToModel(this, 11);
4128                    // Update base model
4129                    OsiObject ** threadObject = threadModel[iModel]->object_;
4130                    for (iObject = 0; iObject < numberObjects_; iObject++) {
4131                        object_[iObject]->updateAfter(threadObject[iObject], saveObjects[iObject]);
4132                    }
4133                }
4134                if (scaleFactor != 1.0) {
4135                    int newNumber = static_cast<int> (defaultParallelNodes * scaleFactor + 0.5001);
4136                    if (newNumber*2 < defaultParallelIterations) {
4137                        if (defaultParallelNodes == 1)
4138                            newNumber = 2;
4139                        if (newNumber != defaultParallelNodes) {
4140                            char general[200];
4141                            sprintf(general, "Changing tree size from %d to %d",
4142                                    defaultParallelNodes, newNumber);
4143                            messageHandler()->message(CBC_GENERAL,
4144                                                      messages())
4145                            << general << CoinMessageEol ;
4146                            defaultParallelNodes = newNumber;
4147                        }
4148                    }
4149                }
4150                //printf("Tree sizes %d %d %d - affected %d\n",saveTreeSize,saveTreeSize2,tree_->size(),nAffected);
4151            }
4152        }
4153#endif
4154    }
4155    if (nDeleteNode) {
4156        for (int i = 0; i < nDeleteNode; i++) {
4157            delete delNode[i];
4158        }
4159        nDeleteNode = 0;
4160    }
4161#ifdef CBC_THREAD
4162    if (numberThreads_) {
4163        int i;
4164        // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
4165        double time = 0.0;
4166        for (i = 0; i < numberThreads_; i++)
4167            time += threadInfo[i].timeInThread;
4168        bool goodTimer = time < (getCurrentSeconds());
4169        for (i = 0; i < numberThreads_; i++) {
4170            while (threadInfo[i].returnCode == 0) {
4171                pthread_cond_signal(threadInfo[i].condition2); // unlock
4172                pthread_mutex_lock(&condition_mutex);
4173                struct timespec absTime;
4174                my_gettime(&absTime);
4175                absTime.tv_nsec += 1000000; // millisecond
4176                if (absTime.tv_nsec >= 1000000000) {
4177                    absTime.tv_nsec -= 1000000000;
4178                    absTime.tv_sec++;
4179                }
4180                pthread_cond_timedwait(&condition_main, &condition_mutex, &absTime);
4181                my_gettime(&absTime);
4182                pthread_mutex_unlock(&condition_mutex);
4183            }
4184            pthread_cond_signal(threadInfo[i].condition2); // unlock
4185            pthread_mutex_lock(&condition_mutex); // not sure necessary but have had one hang on interrupt
4186            threadModel[i]->numberThreads_ = 0; // say exit
4187            if (parallelMode() < 0)
4188                delete [] threadInfo[i].delNode;
4189            threadInfo[i].returnCode = 0;
4190            pthread_mutex_unlock(&condition_mutex);
4191            pthread_cond_signal(threadInfo[i].condition2); // unlock
4192            //if (!stopped)
4193            //pthread_join(threadId[i],NULL);
4194            int returnCode;
4195            returnCode = pthread_join(threadId[i].thr, NULL);
4196            threadId[i].status = 0;
4197            assert (!returnCode);
4198            //else
4199            //pthread_kill(threadId[i]); // kill rather than try and synchronize
4200            threadModel[i]->moveToModel(this, 2);
4201            pthread_mutex_destroy (threadInfo[i].mutex2);
4202            pthread_cond_destroy (threadInfo[i].condition2);
4203            assert (threadInfo[i].numberTimesLocked == threadInfo[i].numberTimesUnlocked);
4204            handler_->message(CBC_THREAD_STATS, messages_)
4205            << "Thread";
4206            handler_->printing(true)
4207            << i << threadCount[i] << threadInfo[i].timeWaitingToStart;
4208            handler_->printing(goodTimer) << threadInfo[i].timeInThread;
4209            handler_->printing(false) << 0.0;
4210            handler_->printing(true) << threadInfo[i].numberTimesLocked
4211            << threadInfo[i].timeLocked << threadInfo[i].timeWaitingToLock
4212            << CoinMessageEol;
4213        }
4214        assert (threadInfo[numberThreads_].numberTimesLocked == threadInfo[numberThreads_].numberTimesUnlocked);
4215        handler_->message(CBC_THREAD_STATS, messages_)
4216        << "Main thread";
4217        handler_->printing(false) << 0 << 0 << 0.0;
4218        handler_->printing(false) << 0.0;
4219        handler_->printing(true) << timeWaiting;
4220        handler_->printing(true) << threadInfo[numberThreads_].numberTimesLocked
4221        << threadInfo[numberThreads_].timeLocked << threadInfo[numberThreads_].timeWaitingToLock
4222        << CoinMessageEol;
4223        pthread_mutex_destroy (&mutex);
4224        pthread_cond_destroy (&condition_main);
4225        pthread_mutex_destroy (&condition_mutex);
4226        // delete models (here in case some point to others)
4227        for (i = 0; i < numberThreads_; i++) {
4228            // make sure handler will be deleted
4229            threadModel[i]->defaultHandler_ = true;
4230            delete threadModel[i];
4231        }
4232        delete [] mutex2;
4233        delete [] condition2;
4234        delete [] threadId;
4235        delete [] threadInfo;
4236        delete [] threadModel;
4237        delete [] threadCount;
4238        mutex_ = NULL;
4239        // adjust time to allow for children on some systems
4240        dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren();
4241    }
4242#endif
4243    /*
4244      End of the non-abort actions. The next block of code is executed if we've
4245      aborted because we hit one of the limits. Clean up by deleting the live set
4246      and break out of the node processing loop. Note that on an abort, node may
4247      have been pushed back onto the tree for further processing, in which case
4248      it'll be deleted in cleanTree. We need to check.
4249    */
4250    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
4251            numberSolutions_ < intParam_[CbcMaxNumSol] &&
4252            !maximumSecondsReached() &&
4253            !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 ||
4254                                                  numberIterations_ < maximumNumberIterations_))) {
4255        if (tree_->size()) {
4256            double dummyBest;
4257            tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
4258        }
4259        delete nextRowCut_;
4260        if (stoppedOnGap_) {
4261            messageHandler()->message(CBC_GAP, messages())
4262            << bestObjective_ - bestPossibleObjective_
4263            << dblParam_[CbcAllowableGap]
4264            << dblParam_[CbcAllowableFractionGap]*100.0
4265            << CoinMessageEol ;
4266            secondaryStatus_ = 2;
4267            status_ = 0 ;
4268        } else if (isNodeLimitReached()) {
4269            handler_->message(CBC_MAXNODES, messages_) << CoinMessageEol ;
4270            secondaryStatus_ = 3;
4271            status_ = 1 ;
4272        } else if (maximumSecondsReached()) {
4273            handler_->message(CBC_MAXTIME, messages_) << CoinMessageEol ;
4274            secondaryStatus_ = 4;
4275            status_ = 1 ;
4276        } else if (eventHappened_) {
4277            handler_->message(CBC_EVENT, messages_) << CoinMessageEol ;
4278            secondaryStatus_ = 5;
4279            status_ = 5 ;
4280        } else {
4281            handler_->message(CBC_MAXSOLS, messages_) << CoinMessageEol ;
4282            secondaryStatus_ = 6;
4283            status_ = 1 ;
4284        }
4285    }
4286    /*
4287      That's it, we've exhausted the search tree, or broken out of the loop because
4288      we hit some limit on evaluation.
4289
4290      We may have got an intelligent tree so give it one more chance
4291    */
4292    // Tell solver we are not in Branch and Cut
4293    solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ;
4294    tree_->endSearch();
4295    //  If we did any sub trees - did we give up on any?
4296    if ( numberStoppedSubTrees_)
4297        status_ = 1;
4298    numberNodes_ += numberExtraNodes_;
4299    numberIterations_ += numberExtraIterations_;
4300    if (eventHandler) {
4301        eventHandler->event(CbcEventHandler::endSearch);
4302    }
4303    if (!status_) {
4304        // Set best possible unless stopped on gap
4305        if (secondaryStatus_ != 2)
4306            bestPossibleObjective_ = bestObjective_;
4307        handler_->message(CBC_END_GOOD, messages_)
4308        << bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds()
4309        << CoinMessageEol ;
4310    } else {
4311        handler_->message(CBC_END, messages_)
4312        << bestObjective_ << bestPossibleObjective_
4313        << numberIterations_ << numberNodes_ << getCurrentSeconds()
4314        << CoinMessageEol ;
4315    }
4316    if (numberStrongIterations_)
4317        handler_->message(CBC_STRONG_STATS, messages_)
4318        << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2]
4319        << strongInfo_[1] << CoinMessageEol ;
4320    if (!numberExtraNodes_)
4321        handler_->message(CBC_OTHER_STATS, messages_)
4322        << maximumDepthActual_
4323        << numberDJFixed_ << CoinMessageEol ;
4324    else
4325        handler_->message(CBC_OTHER_STATS2, messages_)
4326        << maximumDepthActual_
4327        << numberDJFixed_ << numberExtraNodes_ << numberExtraIterations_
4328        << CoinMessageEol ;
4329    if (doStatistics == 100) {
4330        for (int i = 0; i < numberObjects_; i++) {
4331            CbcSimpleIntegerDynamicPseudoCost * obj =
4332                dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[i]) ;
4333            if (obj)
4334                obj->print();
4335        }
4336    }
4337    if (statistics_) {
4338        // report in some way
4339        int * lookup = new int[numberObjects_];
4340        int i;
4341        for (i = 0; i < numberObjects_; i++)
4342            lookup[i] = -1;
4343        bool goodIds = false; //true;
4344        for (i = 0; i < numberObjects_; i++) {
4345            int iColumn = object_[i]->columnNumber();
4346            if (iColumn >= 0 && iColumn < numberColumns) {
4347                if (lookup[i] == -1) {
4348                    lookup[i] = iColumn;
4349                } else {
4350                    goodIds = false;
4351                    break;
4352                }
4353            } else {
4354                goodIds = false;
4355                break;
4356            }
4357        }
4358        if (!goodIds) {
4359            delete [] lookup;
4360            lookup = NULL;
4361        }
4362        if (doStatistics >= 3) {
4363            printf("  node parent depth column   value                    obj      inf\n");
4364            for ( i = 0; i < numberNodes2_; i++) {
4365                statistics_[i]->print(lookup);
4366            }
4367        }
4368        if (doStatistics > 1) {
4369            // Find last solution
4370            int k;
4371            for (k = numberNodes2_ - 1; k >= 0; k--) {
4372                if (statistics_[k]->endingObjective() != COIN_DBL_MAX &&
4373                        !statistics_[k]->endingInfeasibility())
4374                    break;
4375            }
4376            if (k >= 0) {
4377                int depth = statistics_[k]->depth();
4378                int * which = new int[depth+1];
4379                for (i = depth; i >= 0; i--) {
4380                    which[i] = k;
4381                    k = statistics_[k]->parentNode();
4382                }
4383                printf("  node parent depth column   value                    obj      inf\n");
4384                for (i = 0; i <= depth; i++) {
4385                    statistics_[which[i]]->print(lookup);
4386                }
4387                delete [] which;
4388            }
4389        }
4390        // now summary
4391        int maxDepth = 0;
4392        double averageSolutionDepth = 0.0;
4393        int numberSolutions = 0;
4394        double averageCutoffDepth = 0.0;
4395        double averageSolvedDepth = 0.0;
4396        int numberCutoff = 0;
4397        int numberDown = 0;
4398        int numberFirstDown = 0;
4399        double averageInfDown = 0.0;
4400        double averageObjDown = 0.0;
4401        int numberCutoffDown = 0;
4402        int numberUp = 0;
4403        int numberFirstUp = 0;
4404        double averageInfUp = 0.0;
4405        double averageObjUp = 0.0;
4406        int numberCutoffUp = 0;
4407        double averageNumberIterations1 = 0.0;
4408        double averageValue = 0.0;
4409        for ( i = 0; i < numberNodes2_; i++) {
4410            int depth =  statistics_[i]->depth();
4411            int way =  statistics_[i]->way();
4412            double value = statistics_[i]->value();
4413            double startingObjective =  statistics_[i]->startingObjective();
4414            int startingInfeasibility = statistics_[i]->startingInfeasibility();
4415            double endingObjective = statistics_[i]->endingObjective();
4416            int endingInfeasibility = statistics_[i]->endingInfeasibility();
4417            maxDepth = CoinMax(depth, maxDepth);
4418            // Only for completed
4419            averageNumberIterations1 += statistics_[i]->numberIterations();
4420            averageValue += value;
4421            if (endingObjective != COIN_DBL_MAX && !endingInfeasibility) {
4422                numberSolutions++;
4423                averageSolutionDepth += depth;
4424            }
4425            if (endingObjective == COIN_DBL_MAX) {
4426                numberCutoff++;
4427                averageCutoffDepth += depth;
4428                if (way < 0) {
4429                    numberDown++;
4430                    numberCutoffDown++;
4431                    if (way == -1)
4432                        numberFirstDown++;
4433                } else {
4434                    numberUp++;
4435                    numberCutoffUp++;
4436                    if (way == 1)
4437                        numberFirstUp++;
4438                }
4439            } else {
4440                averageSolvedDepth += depth;
4441                if (way < 0) {
4442                    numberDown++;
4443                    averageInfDown += startingInfeasibility - endingInfeasibility;
4444                    averageObjDown += endingObjective - startingObjective;
4445                    if (way == -1)
4446                        numberFirstDown++;
4447                } else {
4448                    numberUp++;
4449                    averageInfUp += startingInfeasibility - endingInfeasibility;
4450                    averageObjUp += endingObjective - startingObjective;
4451                    if (way == 1)
4452                        numberFirstUp++;
4453                }
4454            }
4455        }
4456        // Now print
4457        if (numberSolutions)
4458            averageSolutionDepth /= static_cast<double> (numberSolutions);
4459        int numberSolved = numberNodes2_ - numberCutoff;
4460        double averageNumberIterations2 = numberIterations_ - averageNumberIterations1
4461                                          - numberIterationsAtContinuous;
4462        if (numberCutoff) {
4463            averageCutoffDepth /= static_cast<double> (numberCutoff);
4464            averageNumberIterations2 /= static_cast<double> (numberCutoff);
4465        }
4466        if (numberNodes2_)
4467            averageValue /= static_cast<double> (numberNodes2_);
4468        if (numberSolved) {
4469            averageNumberIterations1 /= static_cast<double> (numberSolved);
4470            averageSolvedDepth /= static_cast<double> (numberSolved);
4471        }
4472        printf("%d solution(s) were found (by branching) at an average depth of %g\n",
4473               numberSolutions, averageSolutionDepth);
4474        printf("average value of variable being branched on was %g\n",
4475               averageValue);
4476        printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n",
4477               numberCutoff, averageCutoffDepth, averageNumberIterations2);
4478        printf("%d nodes were solved at an average depth of %g with iteration count of %g\n",
4479               numberSolved, averageSolvedDepth, averageNumberIterations1);
4480        if (numberDown) {
4481            averageInfDown /= static_cast<double> (numberDown);
4482            averageObjDown /= static_cast<double> (numberDown);
4483        }
4484        printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
4485               numberDown, numberFirstDown, numberDown - numberFirstDown, numberCutoffDown,
4486               averageInfDown, averageObjDown);
4487        if (numberUp) {
4488            averageInfUp /= static_cast<double> (numberUp);
4489            averageObjUp /= static_cast<double> (numberUp);
4490        }
4491        printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
4492               numberUp, numberFirstUp, numberUp - numberFirstUp, numberCutoffUp,
4493               averageInfUp, averageObjUp);
4494        for ( i = 0; i < numberNodes2_; i++)
4495            delete statistics_[i];
4496        delete [] statistics_;
4497        statistics_ = NULL;
4498        maximumStatistics_ = 0;
4499        delete [] lookup;
4500    }
4501    /*
4502      If we think we have a solution, restore and confirm it with a call to
4503      setBestSolution().  We need to reset the cutoff value so as not to fathom
4504      the solution on bounds.  Note that calling setBestSolution( ..., true)
4505      leaves the continuousSolver_ bounds vectors fixed at the solution value.
4506
4507      Running resolve() here is a failsafe --- setBestSolution has already
4508      reoptimised using the continuousSolver_. If for some reason we fail to
4509      prove optimality, run the problem again after instructing the solver to
4510      tell us more.
4511
4512      If all looks good, replace solver_ with continuousSolver_, so that the
4513      outside world will be able to obtain information about the solution using
4514      public methods.
4515    */
4516    if (bestSolution_ && (solverCharacteristics_->solverType() < 2 || solverCharacteristics_->solverType() == 4)) {
4517        setCutoff(1.0e50) ; // As best solution should be worse than cutoff
4518        phase_ = 5;
4519        double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
4520        if ((specialOptions_&4) == 0)
4521            bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve
4522        setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1) ;
4523        continuousSolver_->resolve() ;
4524        if (!continuousSolver_->isProvenOptimal()) {
4525            continuousSolver_->messageHandler()->setLogLevel(2) ;
4526            continuousSolver_->initialSolve() ;
4527        }
4528        delete solver_ ;
4529        // above deletes solverCharacteristics_
4530        solverCharacteristics_ = NULL;
4531        solver_ = continuousSolver_ ;
4532        setPointers(solver_);
4533        continuousSolver_ = NULL ;
4534    }
4535    /*
4536      Clean up dangling objects. continuousSolver_ may already be toast.
4537    */
4538    delete lastws ;
4539    if (saveObjects) {
4540        for (int i = 0; i < numberObjects_; i++)
4541            delete saveObjects[i];
4542        delete [] saveObjects;
4543    }
4544    numberStrong_ = saveNumberStrong;
4545    numberBeforeTrust_ = saveNumberBeforeTrust;
4546    delete [] whichGenerator_ ;
4547    whichGenerator_ = NULL;
4548    delete [] lowerBefore ;
4549    delete [] upperBefore ;
4550    delete [] walkback_ ;
4551    walkback_ = NULL ;
4552    delete [] lastNodeInfo_ ;
4553    lastNodeInfo_ = NULL;
4554    delete [] lastNumberCuts_ ;
4555    lastNumberCuts_ = NULL;
4556    delete [] lastCut_;
4557    lastCut_ = NULL;
4558    delete [] addedCuts_ ;
4559    addedCuts_ = NULL ;
4560    //delete persistentInfo;
4561    // Get rid of characteristics
4562    solverCharacteristics_ = NULL;
4563    if (continuousSolver_) {
4564        delete continuousSolver_ ;
4565        continuousSolver_ = NULL ;
4566    }
4567    /*
4568      Destroy global cuts by replacing with an empty OsiCuts object.
4569    */
4570    globalCuts_ = OsiCuts() ;
4571    if (!bestSolution_) {
4572        // make sure lp solver is infeasible
4573        int numberColumns = solver_->getNumCols();
4574        const double * columnLower = solver_->getColLower();
4575        int iColumn;
4576        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4577            if (solver_->isInteger(iColumn))
4578                solver_->setColUpper(iColumn, columnLower[iColumn]);
4579        }
4580        solver_->initialSolve();
4581    }
4582#ifdef COIN_HAS_CLP
4583    {
4584        OsiClpSolverInterface * clpSolver
4585        = dynamic_cast<OsiClpSolverInterface *> (solver_);
4586        if (clpSolver) {
4587            // Possible restore of pivot method
4588            if (savePivotMethod) {
4589                // model may have changed
4590                savePivotMethod->setModel(NULL);
4591                clpSolver->getModelPtr()->setDualRowPivotAlgorithm(*savePivotMethod);
4592                delete savePivotMethod;
4593            }
4594            clpSolver->setLargestAway(-1.0);
4595        }
4596    }
4597#endif
4598    if (fastNodeDepth_ >= 1000000 && !parentModel_) {
4599        // delete object off end
4600        delete object_[numberObjects_];
4601        fastNodeDepth_ -= 1000000;
4602    }
4603    delete saveSolver;
4604    if (strategy_ && strategy_->preProcessState() > 0) {
4605        // undo preprocessing
4606        CglPreProcess * process = strategy_->process();
4607        assert (process);
4608        int n = originalSolver->getNumCols();
4609        if (bestSolution_) {
4610            delete [] bestSolution_;
4611            bestSolution_ = new double [n];
4612            process->postProcess(*solver_);
4613        }
4614        strategy_->deletePreProcess();
4615        // Solution now back in originalSolver
4616        delete solver_;
4617        solver_ = originalSolver;
4618        if (bestSolution_) {
4619            bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
4620            memcpy(bestSolution_, solver_->getColSolution(), n*sizeof(double));
4621        }
4622        // put back original objects if there were any
4623        if (originalObject) {
4624            int iColumn;
4625            assert (ownObjects_);
4626            for (iColumn = 0; iColumn < numberObjects_; iColumn++)
4627                delete object_[iColumn];
4628            delete [] object_;
4629            numberObjects_ = numberOriginalObjects;
4630            object_ = originalObject;
4631            delete [] integerVariable_;
4632            numberIntegers_ = 0;
4633            for (iColumn = 0; iColumn < n; iColumn++) {
4634                if (solver_->isInteger(iColumn))
4635                    numberIntegers_++;
4636            }
4637            integerVariable_ = new int[numberIntegers_];
4638            numberIntegers_ = 0;
4639            for (iColumn = 0; iColumn < n; iColumn++) {
4640                if (solver_->isInteger(iColumn))
4641                    integerVariable_[numberIntegers_++] = iColumn;
4642            }
4643        }
4644    }
4645#ifdef COIN_HAS_CLP
4646    {
4647        OsiClpSolverInterface * clpSolver
4648        = dynamic_cast<OsiClpSolverInterface *> (solver_);
4649        if (clpSolver)
4650            clpSolver->setFakeObjective(reinterpret_cast<double *> (NULL));
4651    }
4652#endif
4653    moreSpecialOptions_ = saveMoreSpecialOptions;
4654    return ;
4655}
4656
4657
4658// Solve the initial LP relaxation
4659void
4660CbcModel::initialSolve()
4661{
4662    assert (solver_);
4663    // Double check optimization directions line up
4664    dblParam_[CbcOptimizationDirection] = solver_->getObjSense();
4665    // Check if bounds are all integral (as may get messed up later)
4666    checkModel();
4667    if (!solverCharacteristics_) {
4668        OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
4669        if (solverCharacteristics) {
4670            solverCharacteristics_ = solverCharacteristics;
4671        } else {
4672            // replace in solver
4673            OsiBabSolver defaultC;
4674            solver_->setAuxiliaryInfo(&defaultC);
4675            solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
4676        }
4677    }
4678    solverCharacteristics_->setSolver(solver_);
4679    solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
4680    solver_->initialSolve();
4681    solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ;
4682    if (!solver_->isProvenOptimal())
4683        solver_->resolve();
4684    // But set up so Jon Lee will be happy
4685    status_ = -1;
4686    secondaryStatus_ = -1;
4687    originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
4688    delete [] continuousSolution_;
4689    continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
4690                                          solver_->getNumCols());
4691    setPointers(solver_);
4692    solverCharacteristics_ = NULL;
4693}
4694
4695/*! \brief Get an empty basis object
4696
4697  Return an empty CoinWarmStartBasis object with the requested capacity,
4698  appropriate for the current solver. The object is cloned from the object
4699  cached as emptyWarmStart_. If there is no cached object, the routine
4700  queries the solver for a warm start object, empties it, and caches the
4701  result.
4702*/
4703
4704CoinWarmStartBasis *CbcModel::getEmptyBasis (int ns, int na) const
4705
4706{
4707    CoinWarmStartBasis *emptyBasis ;
4708    /*
4709      Acquire an empty basis object, if we don't yet have one.
4710    */
4711    if (emptyWarmStart_ == 0) {
4712        if (solver_ == 0) {
4713            throw CoinError("Cannot construct basis without solver!",
4714                            "getEmptyBasis", "CbcModel") ;
4715        }
4716        emptyBasis =
4717            dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
4718        if (emptyBasis == 0) {
4719            throw CoinError(
4720                "Solver does not appear to use a basis-oriented warm start.",
4721                "getEmptyBasis", "CbcModel") ;
4722        }
4723        emptyBasis->setSize(0, 0) ;
4724        emptyWarmStart_ = dynamic_cast<CoinWarmStart *>(emptyBasis) ;
4725    }
4726    /*
4727      Clone the empty basis object, resize it as requested, and return.
4728    */
4729    emptyBasis = dynamic_cast<CoinWarmStartBasis *>(emptyWarmStart_->clone()) ;
4730    assert(emptyBasis) ;
4731    if (ns != 0 || na != 0) emptyBasis->setSize(ns, na) ;
4732
4733    return (emptyBasis) ;
4734}
4735
4736
4737/** Default Constructor
4738
4739  Creates an empty model without an associated solver.
4740*/
4741CbcModel::CbcModel()
4742
4743        :
4744        solver_(NULL),
4745        ownership_(0x80000000),
4746        continuousSolver_(NULL),
4747        referenceSolver_(NULL),
4748        defaultHandler_(true),
4749        emptyWarmStart_(NULL),
4750        bestObjective_(COIN_DBL_MAX),
4751        bestPossibleObjective_(COIN_DBL_MAX),
4752        sumChangeObjective1_(0.0),
4753        sumChangeObjective2_(0.0),
4754        bestSolution_(NULL),
4755        savedSolutions_(NULL),
4756        currentSolution_(NULL),
4757        testSolution_(NULL),
4758        minimumDrop_(1.0e-4),
4759        numberSolutions_(0),
4760        numberSavedSolutions_(0),
4761        maximumSavedSolutions_(0),
4762        stateOfSearch_(0),
4763        whenCuts_(-1),
4764        hotstartSolution_(NULL),
4765        hotstartPriorities_(NULL),
4766        numberHeuristicSolutions_(0),
4767        numberNodes_(0),
4768        numberNodes2_(0),
4769        numberIterations_(0),
4770        numberSolves_(0),
4771        status_(-1),
4772        secondaryStatus_(-1),
4773        numberIntegers_(0),
4774        numberRowsAtContinuous_(0),
4775        maximumNumberCuts_(0),
4776        phase_(0),
4777        currentNumberCuts_(0),
4778        maximumDepth_(0),
4779        walkback_(NULL),
4780        lastNodeInfo_(NULL),
4781        lastCut_(NULL),
4782        lastDepth_(0),
4783        lastNumberCuts2_(0),
4784        maximumCuts_(0),
4785        lastNumberCuts_(NULL),
4786        addedCuts_(NULL),
4787        nextRowCut_(NULL),
4788        currentNode_(NULL),
4789        integerVariable_(NULL),
4790        integerInfo_(NULL),
4791        continuousSolution_(NULL),
4792        usedInSolution_(NULL),
4793        specialOptions_(0),
4794        moreSpecialOptions_(0),
4795        subTreeModel_(NULL),
4796        numberStoppedSubTrees_(0),
4797        mutex_(NULL),
4798        presolve_(0),
4799        numberStrong_(5),
4800        numberBeforeTrust_(10),
4801        numberPenalties_(20),
4802        stopNumberIterations_(-1),
4803        penaltyScaleFactor_(3.0),
4804        numberAnalyzeIterations_(0),
4805        analyzeResults_(NULL),
4806        numberInfeasibleNodes_(0),
4807        problemType_(0),
4808        printFrequency_(0),
4809        numberCutGenerators_(0),
4810        generator_(NULL),
4811        virginGenerator_(NULL),
4812        numberHeuristics_(0),
4813        heuristic_(NULL),
4814        lastHeuristic_(NULL),
4815# ifdef COIN_HAS_CLP
4816        fastNodeDepth_(-1),
4817#endif
4818        eventHandler_(NULL),
4819        numberObjects_(0),
4820        object_(NULL),
4821        ownObjects_(true),
4822        originalColumns_(NULL),
4823        howOftenGlobalScan_(1),
4824        numberGlobalViolations_(0),
4825        numberExtraIterations_(0),
4826        numberExtraNodes_(0),
4827        continuousObjective_(COIN_DBL_MAX),
4828        originalContinuousObjective_(COIN_DBL_MAX),
4829        continuousInfeasibilities_(COIN_INT_MAX),
4830        maximumCutPassesAtRoot_(20),
4831        maximumCutPasses_(10),
4832        preferredWay_(0),
4833        currentPassNumber_(0),
4834        maximumWhich_(1000),
4835        maximumRows_(0),
4836        currentDepth_(0),
4837        whichGenerator_(NULL),
4838        maximumStatistics_(0),
4839        statistics_(NULL),
4840        maximumDepthActual_(0),
4841        numberDJFixed_(0.0),
4842        probingInfo_(NULL),
4843        numberFixedAtRoot_(0),
4844        numberFixedNow_(0),
4845        stoppedOnGap_(false),
4846        eventHappened_(false),
4847        numberLongStrong_(0),
4848        numberOldActiveCuts_(0),
4849        numberNewCuts_(0),
4850        searchStrategy_(-1),
4851        numberStrongIterations_(0),
4852        resolveAfterTakeOffCuts_(true),
4853        maximumNumberIterations_(-1),
4854        continuousPriority_(COIN_INT_MAX),
4855        numberUpdateItems_(0),
4856        maximumNumberUpdateItems_(0),
4857        updateItems_(NULL),
4858        storedRowCuts_(NULL),
4859        numberThreads_(0),
4860        threadMode_(0)
4861{
4862    memset(intParam_, 0, sizeof(intParam_));
4863    intParam_[CbcMaxNumNode] = 2147483647;
4864    intParam_[CbcMaxNumSol] = 9999999;
4865
4866    memset(dblParam_, 0, sizeof(dblParam_));
4867    dblParam_[CbcIntegerTolerance] = 1e-6;
4868    dblParam_[CbcCutoffIncrement] = 1e-5;
4869    dblParam_[CbcAllowableGap] = 1.0e-10;
4870    dblParam_[CbcMaximumSeconds] = 1.0e100;
4871    dblParam_[CbcCurrentCutoff] = 1.0e100;
4872    dblParam_[CbcOptimizationDirection] = 1.0;
4873    dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
4874    dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
4875    strongInfo_[0] = 0;
4876    strongInfo_[1] = 0;
4877    strongInfo_[2] = 0;
4878    strongInfo_[3] = 0;
4879    strongInfo_[4] = 0;
4880    strongInfo_[5] = 0;
4881    strongInfo_[6] = 0;
4882    solverCharacteristics_ = NULL;
4883    nodeCompare_ = new CbcCompareDefault();;
4884    problemFeasibility_ = new CbcFeasibilityBase();
4885    tree_ = new CbcTree();
4886    branchingMethod_ = NULL;
4887    cutModifier_ = NULL;
4888    strategy_ = NULL;
4889    parentModel_ = NULL;
4890    cbcColLower_ = NULL;
4891    cbcColUpper_ = NULL;
4892    cbcRowLower_ = NULL;
4893    cbcRowUpper_ = NULL;
4894    cbcColSolution_ = NULL;
4895    cbcRowPrice_ = NULL;
4896    cbcReducedCost_ = NULL;
4897    cbcRowActivity_ = NULL;
4898    appData_ = NULL;
4899    handler_ = new CoinMessageHandler();
4900    handler_->setLogLevel(2);
4901    messages_ = CbcMessage();
4902    //eventHandler_ = new CbcEventHandler() ;
4903}
4904
4905/** Constructor from solver.
4906
4907  Creates a model complete with a clone of the solver passed as a parameter.
4908*/
4909
4910CbcModel::CbcModel(const OsiSolverInterface &rhs)
4911        :
4912        continuousSolver_(NULL),
4913        referenceSolver_(NULL),
4914        defaultHandler_(true),
4915        emptyWarmStart_(NULL),
4916        bestObjective_(COIN_DBL_MAX),
4917        bestPossibleObjective_(COIN_DBL_MAX),
4918        sumChangeObjective1_(0.0),
4919        sumChangeObjective2_(0.0),
4920        minimumDrop_(1.0e-4),
4921        numberSolutions_(0),
4922        numberSavedSolutions_(0),
4923        maximumSavedSolutions_(0),
4924        stateOfSearch_(0),
4925        whenCuts_(-1),
4926        hotstartSolution_(NULL),
4927        hotstartPriorities_(NULL),
4928        numberHeuristicSolutions_(0),
4929        numberNodes_(0),
4930        numberNodes2_(0),
4931        numberIterations_(0),
4932        numberSolves_(0),
4933        status_(-1),
4934        secondaryStatus_(-1),
4935        numberRowsAtContinuous_(0),
4936        maximumNumberCuts_(0),
4937        phase_(0),
4938        currentNumberCuts_(0),
4939        maximumDepth_(0),
4940        walkback_(NULL),
4941        lastNodeInfo_(NULL),
4942        lastCut_(NULL),
4943        lastDepth_(0),
4944        lastNumberCuts2_(0),
4945        maximumCuts_(0),
4946        lastNumberCuts_(NULL),
4947        addedCuts_(NULL),
4948        nextRowCut_(NULL),
4949        currentNode_(NULL),
4950        integerInfo_(NULL),
4951        specialOptions_(0),
4952        moreSpecialOptions_(0),
4953        subTreeModel_(NULL),
4954        numberStoppedSubTrees_(0),
4955        mutex_(NULL),
4956        presolve_(0),
4957        numberStrong_(5),
4958        numberBeforeTrust_(10),
4959        numberPenalties_(20),
4960        stopNumberIterations_(-1),
4961        penaltyScaleFactor_(3.0),
4962        numberAnalyzeIterations_(0),
4963        analyzeResults_(NULL),
4964        numberInfeasibleNodes_(0),
4965        problemType_(0),
4966        printFrequency_(0),
4967        numberCutGenerators_(0),
4968        generator_(NULL),
4969        virginGenerator_(NULL),
4970        numberHeuristics_(0),
4971        heuristic_(NULL),
4972        lastHeuristic_(NULL),
4973# ifdef COIN_HAS_CLP
4974        fastNodeDepth_(-1),
4975#endif
4976        eventHandler_(NULL),
4977        numberObjects_(0),
4978        object_(NULL),
4979        ownObjects_(true),
4980        originalColumns_(NULL),
4981        howOftenGlobalScan_(1),
4982        numberGlobalViolations_(0),
4983        numberExtraIterations_(0),
4984        numberExtraNodes_(0),
4985        continuousObjective_(COIN_DBL_MAX),
4986        originalContinuousObjective_(COIN_DBL_MAX),
4987        continuousInfeasibilities_(COIN_INT_MAX),
4988        maximumCutPassesAtRoot_(20),
4989        maximumCutPasses_(10),
4990        preferredWay_(0),
4991        currentPassNumber_(0),
4992        maximumWhich_(1000),
4993        maximumRows_(0),
4994        currentDepth_(0),
4995        whichGenerator_(NULL),
4996        maximumStatistics_(0),
4997        statistics_(NULL),
4998        maximumDepthActual_(0),
4999        numberDJFixed_(0.0),
5000        probingInfo_(NULL),
5001        numberFixedAtRoot_(0),
5002        numberFixedNow_(0),
5003        stoppedOnGap_(false),
5004        eventHappened_(false),
5005        numberLongStrong_(0),
5006        numberOldActiveCuts_(0),
5007        numberNewCuts_(0),
5008        searchStrategy_(-1),
5009        numberStrongIterations_(0),
5010        resolveAfterTakeOffCuts_(true),
5011        maximumNumberIterations_(-1),
5012        continuousPriority_(COIN_INT_MAX),
5013        numberUpdateItems_(0),
5014        maximumNumberUpdateItems_(0),
5015        updateItems_(NULL),
5016        storedRowCuts_(NULL),
5017        numberThreads_(0),
5018        threadMode_(0)
5019{
5020    memset(intParam_, 0, sizeof(intParam_));
5021    intParam_[CbcMaxNumNode] = 2147483647;
5022    intParam_[CbcMaxNumSol] = 9999999;
5023
5024    memset(dblParam_, 0, sizeof(dblParam_));
5025    dblParam_[CbcIntegerTolerance] = 1e-6;
5026    dblParam_[CbcCutoffIncrement] = 1e-5;
5027    dblParam_[CbcAllowableGap] = 1.0e-10;
5028    dblParam_[CbcMaximumSeconds] = 1.0e100;
5029    dblParam_[CbcCurrentCutoff] = 1.0e100;
5030    dblParam_[CbcOptimizationDirection] = 1.0;
5031    dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
5032    dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
5033    strongInfo_[0] = 0;
5034    strongInfo_[1] = 0;
5035    strongInfo_[2] = 0;
5036    strongInfo_[3] = 0;
5037    strongInfo_[4] = 0;
5038    strongInfo_[5] = 0;
5039    strongInfo_[6] = 0;
5040    solverCharacteristics_ = NULL;
5041    nodeCompare_ = new CbcCompareDefault();;
5042    problemFeasibility_ = new CbcFeasibilityBase();
5043    tree_ = new CbcTree();
5044    branchingMethod_ = NULL;
5045    cutModifier_ = NULL;
5046    strategy_ = NULL;
5047    parentModel_ = NULL;
5048    appData_ = NULL;
5049    handler_ = new CoinMessageHandler();
5050    handler_->setLogLevel(2);
5051    messages_ = CbcMessage();
5052    //eventHandler_ = new CbcEventHandler() ;
5053    solver_ = rhs.clone();
5054    referenceSolver_ = solver_->clone();
5055    ownership_ = 0x80000000;
5056    cbcColLower_ = NULL;
5057    cbcColUpper_ = NULL;
5058    cbcRowLower_ = NULL;
5059    cbcRowUpper_ = NULL;
5060    cbcColSolution_ = NULL;
5061    cbcRowPrice_ = NULL;
5062    cbcReducedCost_ = NULL;
5063    cbcRowActivity_ = NULL;
5064
5065    // Initialize solution and integer variable vectors
5066    bestSolution_ = NULL; // to say no solution found
5067    savedSolutions_ = NULL;
5068    numberIntegers_ = 0;
5069    int numberColumns = solver_->getNumCols();
5070    int iColumn;
5071    if (numberColumns) {
5072        // Space for current solution
5073        currentSolution_ = new double[numberColumns];
5074        continuousSolution_ = new double[numberColumns];
5075        usedInSolution_ = new int[numberColumns];
5076        CoinZeroN(usedInSolution_, numberColumns);
5077        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5078            if ( solver_->isInteger(iColumn))
5079                numberIntegers_++;
5080        }
5081    } else {
5082        // empty model
5083        currentSolution_ = NULL;
5084        continuousSolution_ = NULL;
5085        usedInSolution_ = NULL;
5086    }
5087    testSolution_ = currentSolution_;
5088    if (numberIntegers_) {
5089        integerVariable_ = new int [numberIntegers_];
5090        numberIntegers_ = 0;
5091        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5092            if ( solver_->isInteger(iColumn))
5093                integerVariable_[numberIntegers_++] = iColumn;
5094        }
5095    } else {
5096        integerVariable_ = NULL;
5097    }
5098}
5099
5100/*
5101  Assign a solver to the model (model assumes ownership)
5102
5103  The integer variable vector is initialized if it's not already present.
5104  If deleteSolver then current solver deleted (if model owned)
5105
5106  Assuming ownership matches usage in OsiSolverInterface
5107  (cf. assignProblem, loadProblem).
5108
5109  TODO: What to do about solver parameters? A simple copy likely won't do it,
5110        because the SI must push the settings into the underlying solver. In
5111        the context of switching solvers in cbc, this means that command line
5112        settings will get lost. Stash the command line somewhere and reread it
5113        here, maybe?
5114
5115  TODO: More generally, how much state should be transferred from the old
5116        solver to the new solver? Best perhaps to see how usage develops.
5117        What's done here mimics the CbcModel(OsiSolverInterface) constructor.
5118*/
5119void
5120CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver)
5121
5122{
5123    // resize best solution if exists
5124    if (bestSolution_ && solver && solver_) {
5125        int nOld = solver_->getNumCols();
5126        int nNew = solver->getNumCols();
5127        if (nNew > nOld) {
5128            double * temp = new double[nNew];
5129            memcpy(temp, bestSolution_, nOld*sizeof(double));
5130            memset(temp + nOld, 0, (nNew - nOld)*sizeof(double));
5131            delete [] bestSolution_;
5132            bestSolution_ = temp;
5133        }
5134    }
5135    // Keep the current message level for solver (if solver exists)
5136    if (solver_)
5137        solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel()) ;
5138
5139    if (modelOwnsSolver() && deleteSolver) {
5140        solverCharacteristics_ = NULL;
5141        delete solver_ ;
5142    }
5143    solver_ = solver;
5144    solver = NULL ;
5145    setModelOwnsSolver(true) ;
5146    /*
5147      Basis information is solver-specific.
5148    */
5149    if (emptyWarmStart_) {
5150        delete emptyWarmStart_  ;
5151        emptyWarmStart_ = 0 ;
5152    }
5153    bestSolutionBasis_ = CoinWarmStartBasis();
5154    /*
5155      Initialize integer variable vector.
5156    */
5157    numberIntegers_ = 0;
5158    int numberColumns = solver_->getNumCols();
5159    int iColumn;
5160    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5161        if ( solver_->isInteger(iColumn))
5162            numberIntegers_++;
5163    }
5164    delete [] integerVariable_;
5165    if (numberIntegers_) {
5166        integerVariable_ = new int [numberIntegers_];
5167        numberIntegers_ = 0;
5168        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5169            if ( solver_->isInteger(iColumn))
5170                integerVariable_[numberIntegers_++] = iColumn;
5171        }
5172    } else {
5173        integerVariable_ = NULL;
5174    }
5175
5176    return ;
5177}
5178
5179// Copy constructor.
5180
5181CbcModel::CbcModel(const CbcModel & rhs, bool cloneHandler)
5182        :
5183        continuousSolver_(NULL),
5184        referenceSolver_(NULL),
5185        defaultHandler_(rhs.defaultHandler_),
5186        emptyWarmStart_(NULL),
5187        bestObjective_(rhs.bestObjective_),
5188        bestPossibleObjective_(rhs.bestPossibleObjective_),
5189        sumChangeObjective1_(rhs.sumChangeObjective1_),
5190        sumChangeObjective2_(rhs.sumChangeObjective2_),
5191        minimumDrop_(rhs.minimumDrop_),
5192        numberSolutions_(rhs.numberSolutions_),
5193        numberSavedSolutions_(rhs.numberSavedSolutions_),
5194        maximumSavedSolutions_(rhs.maximumSavedSolutions_),
5195        stateOfSearch_(rhs.stateOfSearch_),
5196        whenCuts_(rhs.whenCuts_),
5197        numberHeuristicSolutions_(rhs.numberHeuristicSolutions_),
5198        numberNodes_(rhs.numberNodes_),
5199        numberNodes2_(rhs.numberNodes2_),
5200        numberIterations_(rhs.numberIterations_),
5201        numberSolves_(rhs.numberSolves_),
5202        status_(rhs.status_),
5203        secondaryStatus_(rhs.secondaryStatus_),
5204        specialOptions_(rhs.specialOptions_),
5205        moreSpecialOptions_(rhs.moreSpecialOptions_),
5206        subTreeModel_(rhs.subTreeModel_),
5207        numberStoppedSubTrees_(rhs.numberStoppedSubTrees_),
5208        mutex_(NULL),
5209        presolve_(rhs.presolve_),
5210        numberStrong_(rhs.numberStrong_),
5211        numberBeforeTrust_(rhs.numberBeforeTrust_),
5212        numberPenalties_(rhs.numberPenalties_),
5213        stopNumberIterations_(rhs.stopNumberIterations_),
5214        penaltyScaleFactor_(rhs.penaltyScaleFactor_),
5215        numberAnalyzeIterations_(rhs.numberAnalyzeIterations_),
5216        analyzeResults_(NULL),
5217        numberInfeasibleNodes_(rhs.numberInfeasibleNodes_),
5218        problemType_(rhs.problemType_),
5219        printFrequency_(rhs.printFrequency_),
5220# ifdef COIN_HAS_CLP
5221        fastNodeDepth_(rhs.fastNodeDepth_),
5222#endif
5223        howOftenGlobalScan_(rhs.howOftenGlobalScan_),
5224        numberGlobalViolations_(rhs.numberGlobalViolations_),
5225        numberExtraIterations_(rhs.numberExtraIterations_),
5226        numberExtraNodes_(rhs.numberExtraNodes_),
5227        continuousObjective_(rhs.continuousObjective_),
5228        originalContinuousObjective_(rhs.originalContinuousObjective_),
5229        continuousInfeasibilities_(rhs.continuousInfeasibilities_),
5230        maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_),
5231        maximumCutPasses_( rhs.maximumCutPasses_),
5232        preferredWay_(rhs.preferredWay_),
5233        currentPassNumber_(rhs.currentPassNumber_),
5234        maximumWhich_(rhs.maximumWhich_),
5235        maximumRows_(0),
5236        currentDepth_(0),
5237        whichGenerator_(NULL),
5238        maximumStatistics_(0),
5239        statistics_(NULL),
5240        maximumDepthActual_(0),
5241        numberDJFixed_(0.0),
5242        probingInfo_(NULL),
5243        numberFixedAtRoot_(rhs.numberFixedAtRoot_),
5244        numberFixedNow_(rhs.numberFixedNow_),
5245        stoppedOnGap_(rhs.stoppedOnGap_),
5246        eventHappened_(rhs.eventHappened_),
5247        numberLongStrong_(rhs.numberLongStrong_),
5248        numberOldActiveCuts_(rhs.numberOldActiveCuts_),
5249        numberNewCuts_(rhs.numberNewCuts_),
5250        searchStrategy_(rhs.searchStrategy_),
5251        numberStrongIterations_(rhs.numberStrongIterations_),
5252        resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_),
5253        maximumNumberIterations_(rhs.maximumNumberIterations_),
5254        continuousPriority_(rhs.continuousPriority_),
5255        numberUpdateItems_(rhs.numberUpdateItems_),
5256        maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_),
5257        updateItems_(NULL),
5258        storedRowCuts_(NULL),
5259        numberThreads_(rhs.numberThreads_),
5260        threadMode_(rhs.threadMode_)
5261{
5262    memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
5263    memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
5264    strongInfo_[0] = rhs.strongInfo_[0];
5265    strongInfo_[1] = rhs.strongInfo_[1];
5266    strongInfo_[2] = rhs.strongInfo_[2];
5267    strongInfo_[3] = rhs.strongInfo_[3];
5268    strongInfo_[4] = rhs.strongInfo_[4];
5269    strongInfo_[5] = rhs.strongInfo_[5];
5270    strongInfo_[6] = rhs.strongInfo_[6];
5271    solverCharacteristics_ = NULL;
5272    if (rhs.emptyWarmStart_) emptyWarmStart_ = rhs.emptyWarmStart_->clone() ;
5273    if (defaultHandler_ || cloneHandler) {
5274        handler_ = new CoinMessageHandler();
5275        handler_->setLogLevel(2);
5276    } else {
5277        handler_ = rhs.handler_;
5278    }
5279    messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
5280    numberCutGenerators_ = rhs.numberCutGenerators_;
5281    if (numberCutGenerators_) {
5282        generator_ = new CbcCutGenerator * [numberCutGenerators_];
5283        virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_];
5284        int i;
5285        for (i = 0; i < numberCutGenerators_; i++) {
5286            generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
5287            virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
5288        }
5289<