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

Last change on this file since 1377 was 1377, checked in by lou, 10 years ago

Removed all code related to NEW_STYLE_SOLVER from CbcSolver?. A few minor
comments added to CbcModel?.

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