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

Last change on this file since 1364 was 1364, checked in by EdwinStraver, 11 years ago

Added comments from Lou

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