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

Last change on this file since 1409 was 1409, checked in by forrest, 12 years ago

first attempt at cleaning up threads

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