source: trunk/Cbc/src/CbcModel.cpp @ 1654

Last change on this file since 1654 was 1654, checked in by forrest, 8 years ago

allow postprocessing when preprocessing inside CbcModel? solves problem

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