source: stable/2.7/Cbc/src/CbcModel.cpp @ 1664

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

changes for bonmin (and gcc 4.6)

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