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

Last change on this file since 1652 was 1652, checked in by stefan, 8 years ago

similar to chgset 1649 in trunk

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