1 /* $Id$ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #if defined(_MSC_VER)
7 // Turn off compiler warning about long names
8 #pragma warning(disable : 4786)
9 #endif
10 
11 #include "CbcConfig.h"
12 
13 #include <string>
14 //#define CBC_DEBUG 1
15 //#define CHECK_CUT_COUNTS
16 //#define CHECK_NODE
17 //#define CHECK_NODE_FULL
18 //#define NODE_LOG
19 //#define GLOBAL_CUTS_JUST_POINTERS
20 #ifdef CGL_DEBUG_GOMORY
21 extern int gomory_try;
22 #endif
23 #include <cassert>
24 #include <cmath>
25 #include <cfloat>
26 #ifdef COIN_HAS_CLP
27 // include Presolve from Clp
28 #include "ClpPresolve.hpp"
29 #include "OsiClpSolverInterface.hpp"
30 #include "ClpNode.hpp"
31 #include "ClpDualRowDantzig.hpp"
32 #include "ClpSimplexPrimal.hpp"
33 #endif
34 
35 #include "CbcEventHandler.hpp"
36 
37 #include "OsiSolverInterface.hpp"
38 #include "OsiAuxInfo.hpp"
39 #include "OsiSolverBranch.hpp"
40 #include "OsiChooseVariable.hpp"
41 #include "CoinWarmStartBasis.hpp"
42 #include "CoinPackedMatrix.hpp"
43 #include "CoinHelperFunctions.hpp"
44 #include "CbcBranchActual.hpp"
45 #include "CbcBranchDynamic.hpp"
46 #include "CbcHeuristic.hpp"
47 #include "CbcHeuristicFPump.hpp"
48 #include "CbcHeuristicRINS.hpp"
49 #include "CbcHeuristicDive.hpp"
50 #include "CbcModel.hpp"
51 #include "CbcTreeLocal.hpp"
52 #include "CbcStatistics.hpp"
53 #include "CbcStrategy.hpp"
54 #include "CbcMessage.hpp"
55 #include "OsiRowCut.hpp"
56 #include "OsiColCut.hpp"
57 #include "OsiRowCutDebugger.hpp"
58 #include "OsiCuts.hpp"
59 #include "CbcCountRowCut.hpp"
60 #include "CbcCutGenerator.hpp"
61 #include "CbcFeasibilityBase.hpp"
62 #include "CbcFathom.hpp"
63 #include "CbcFullNodeInfo.hpp"
64 #ifdef COIN_HAS_NTY
65 #include "CbcSymmetry.hpp"
66 #endif
67 // include Probing
68 #include "CglProbing.hpp"
69 #include "CglGomory.hpp"
70 #include "CglTwomir.hpp"
71 // include preprocessing
72 #include "CglPreProcess.hpp"
73 #include "CglDuplicateRow.hpp"
74 #include "CglStored.hpp"
75 #include "CglClique.hpp"
76 #include "CglKnapsackCover.hpp"
77 
78 #include "CoinTime.hpp"
79 #include "CoinMpsIO.hpp"
80 
81 #include "CbcCompareActual.hpp"
82 #include "CbcTree.hpp"
83 // This may be dummy
84 #include "CbcThread.hpp"
85 /* Various functions local to CbcModel.cpp */
86 
87 typedef struct {
88   double useCutoff;
89   CbcModel *model;
90   int switches;
91 } rootBundle;
92 static void *doRootCbcThread(void *voidInfo);
93 
94 namespace {
95 
96 //-------------------------------------------------------------------
97 // Returns the greatest common denominator of two
98 // positive integers, a and b, found using Euclid's algorithm
99 //-------------------------------------------------------------------
gcd(int a,int b)100 static int gcd(int a, int b)
101 {
102   int remainder = -1;
103   // make sure a<=b (will always remain so)
104   if (a > b) {
105     // Swap a and b
106     int temp = a;
107     a = b;
108     b = temp;
109   }
110   // if zero then gcd is nonzero (zero may occur in rhs of packed)
111   if (!a) {
112     if (b) {
113       return b;
114     } else {
115       printf("**** gcd given two zeros!!\n");
116       abort();
117     }
118   }
119   while (remainder) {
120     remainder = b % a;
121     b = a;
122     a = remainder;
123   }
124   return b;
125 }
126 
127 #ifdef CHECK_NODE_FULL
128 
129 /*
130   Routine to verify that tree linkage is correct. The invariant that is tested
131   is
132 
133   reference count = (number of actual references) + (number of branches left)
134 
135   The routine builds a set of paired arrays, info and count, by traversing the
136   tree. Each CbcNodeInfo is recorded in info, and the number of times it is
137   referenced (via the parent field) is recorded in count. Then a final check is
138   made to see if the numberPointingToThis_ field agrees.
139 */
140 
verifyTreeNodes(const CbcTree * branchingTree,const CbcModel & model)141 void verifyTreeNodes(const CbcTree *branchingTree, const CbcModel &model)
142 
143 {
144   if (model.getNodeCount() == 661)
145     return;
146   printf("*** CHECKING tree after %d nodes\n", model.getNodeCount());
147 
148   int j;
149   int nNodes = branchingTree->size();
150 #define MAXINFO 1000
151   int *count = new int[MAXINFO];
152   CbcNodeInfo **info = new CbcNodeInfo *[MAXINFO];
153   int nInfo = 0;
154   /*
155       Collect all CbcNodeInfo objects in info, by starting from each live node and
156       traversing back to the root. Nodes in the live set should have unexplored
157       branches remaining.
158 
159       TODO: The `while (nodeInfo)' loop could be made to break on reaching a
160     	common ancester (nodeInfo is found in info[k]). Alternatively, the
161     	check could change to signal an error if nodeInfo is not found above a
162     	common ancestor.
163     */
164   for (j = 0; j < nNodes; j++) {
165     CbcNode *node = branchingTree->nodePointer(j);
166     if (!node)
167       continue;
168     CbcNodeInfo *nodeInfo = node->nodeInfo();
169     int change = node->nodeInfo()->numberBranchesLeft();
170     assert(change);
171     while (nodeInfo) {
172       int k;
173       for (k = 0; k < nInfo; k++) {
174         if (nodeInfo == info[k])
175           break;
176       }
177       if (k == nInfo) {
178         assert(nInfo < MAXINFO);
179         nInfo++;
180         info[k] = nodeInfo;
181         count[k] = 0;
182       }
183       nodeInfo = nodeInfo->parent();
184     }
185   }
186   /*
187       Walk the info array. For each nodeInfo, look up its parent in info and
188       increment the corresponding count.
189     */
190   for (j = 0; j < nInfo; j++) {
191     CbcNodeInfo *nodeInfo = info[j];
192     nodeInfo = nodeInfo->parent();
193     if (nodeInfo) {
194       int k;
195       for (k = 0; k < nInfo; k++) {
196         if (nodeInfo == info[k])
197           break;
198       }
199       assert(k < nInfo);
200       count[k]++;
201     }
202   }
203   /*
204       Walk the info array one more time and check that the invariant holds. The
205       number of references (numberPointingToThis()) should equal the sum of the
206       number of actual references (held in count[]) plus the number of potential
207       references (unexplored branches, numberBranchesLeft()).
208     */
209   for (j = 0; j < nInfo; j++) {
210     CbcNodeInfo *nodeInfo = info[j];
211     if (nodeInfo) {
212       int k;
213       for (k = 0; k < nInfo; k++)
214         if (nodeInfo == info[k])
215           break;
216       printf("Nodeinfo %x - %d left, %d count\n",
217         nodeInfo,
218         nodeInfo->numberBranchesLeft(),
219         nodeInfo->numberPointingToThis());
220       assert(nodeInfo->numberPointingToThis() == count[k] + nodeInfo->numberBranchesLeft());
221     }
222   }
223 
224   delete[] count;
225   delete[] info;
226 
227   return;
228 }
229 
230 #endif /* CHECK_NODE_FULL */
231 
232 #ifdef CHECK_CUT_COUNTS
233 
234 /*
235   Routine to verify that cut reference counts are correct.
236 */
verifyCutCounts(const CbcTree * branchingTree,CbcModel & model)237 void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model)
238 
239 {
240   printf("*** CHECKING cuts after %d nodes\n", model.getNodeCount());
241 
242   int j;
243   int nNodes = branchingTree->size();
244 
245   /*
246       cut.tempNumber_ exists for the purpose of doing this verification. Clear it
247       in all cuts. We traverse the tree by starting from each live node and working
248       back to the root. At each CbcNodeInfo, check for cuts.
249     */
250   for (j = 0; j < nNodes; j++) {
251     CbcNode *node = branchingTree->nodePointer(j);
252     CbcNodeInfo *nodeInfo = node->nodeInfo();
253     assert(node->nodeInfo()->numberBranchesLeft());
254     while (nodeInfo) {
255       int k;
256       for (k = 0; k < nodeInfo->numberCuts(); k++) {
257         CbcCountRowCut *cut = nodeInfo->cuts()[k];
258         if (cut)
259           cut->tempNumber_ = 0;
260       }
261       nodeInfo = nodeInfo->parent();
262     }
263   }
264   /*
265       Walk the live set again, this time collecting the list of cuts in use at each
266       node. addCuts1 will collect the cuts in model.addedCuts_. Take into account
267       that when we recreate the basis for a node, we compress out the slack cuts.
268     */
269   for (j = 0; j < nNodes; j++) {
270     CoinWarmStartBasis *debugws = model.getEmptyBasis();
271     CbcNode *node = branchingTree->nodePointer(j);
272     CbcNodeInfo *nodeInfo = node->nodeInfo();
273     int change = node->nodeInfo()->numberBranchesLeft();
274     printf("Node %d %x (info %x) var %d way %d obj %g", j, node,
275       node->nodeInfo(), node->columnNumber(), node->way(),
276       node->objectiveValue());
277 
278     model.addCuts1(node, debugws);
279 
280     int i;
281     int numberRowsAtContinuous = model.numberRowsAtContinuous();
282     CbcCountRowCut **addedCuts = model.addedCuts();
283     for (i = 0; i < model.currentNumberCuts(); i++) {
284       CoinWarmStartBasis::Status status = debugws->getArtifStatus(i + numberRowsAtContinuous);
285       if (status != CoinWarmStartBasis::basic && addedCuts[i]) {
286         addedCuts[i]->tempNumber_ += change;
287       }
288     }
289 
290     while (nodeInfo) {
291       nodeInfo = nodeInfo->parent();
292       if (nodeInfo)
293         printf(" -> %x", nodeInfo);
294     }
295     printf("\n");
296     delete debugws;
297   }
298   /*
299       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.
300 
301       TODO: Rewrite to check and print mismatch only when tempNumber_ == 0?
302     */
303   for (j = 0; j < nNodes; j++) {
304     CbcNode *node = branchingTree->nodePointer(j);
305     CbcNodeInfo *nodeInfo = node->nodeInfo();
306     while (nodeInfo) {
307       int k;
308       for (k = 0; k < nodeInfo->numberCuts(); k++) {
309         CbcCountRowCut *cut = nodeInfo->cuts()[k];
310         if (cut && cut->tempNumber_ >= 0) {
311           if (cut->tempNumber_ != cut->numberPointingToThis())
312             printf("mismatch %x %d %x %d %d\n", nodeInfo, k,
313               cut, cut->tempNumber_, cut->numberPointingToThis());
314           else
315             printf("   match %x %d %x %d %d\n", nodeInfo, k,
316               cut, cut->tempNumber_, cut->numberPointingToThis());
317           cut->tempNumber_ = -1;
318         }
319       }
320       nodeInfo = nodeInfo->parent();
321     }
322   }
323 
324   return;
325 }
326 
327 #endif /* CHECK_CUT_COUNTS */
328 
329 #ifdef CHECK_CUT_SIZE
330 
331 /*
332   Routine to verify that cut reference counts are correct.
333 */
verifyCutSize(const CbcTree * branchingTree,CbcModel & model)334 void verifyCutSize(const CbcTree *branchingTree, CbcModel &model)
335 {
336 
337   int j;
338   int nNodes = branchingTree->size();
339   int totalCuts = 0;
340 
341   /*
342       cut.tempNumber_ exists for the purpose of doing this verification. Clear it
343       in all cuts. We traverse the tree by starting from each live node and working
344       back to the root. At each CbcNodeInfo, check for cuts.
345     */
346   for (j = 0; j < nNodes; j++) {
347     CbcNode *node = branchingTree->nodePointer(j);
348     CbcNodeInfo *nodeInfo = node->nodeInfo();
349     assert(node->nodeInfo()->numberBranchesLeft());
350     while (nodeInfo) {
351       totalCuts += nodeInfo->numberCuts();
352       nodeInfo = nodeInfo->parent();
353     }
354   }
355   printf("*** CHECKING cuts (size) after %d nodes - %d cuts\n", model.getNodeCount(), totalCuts);
356   return;
357 }
358 
359 #endif /* CHECK_CUT_SIZE */
360 
361 }
362 
363 /* End unnamed namespace for CbcModel.cpp */
364 
analyzeObjective()365 void CbcModel::analyzeObjective()
366 /*
367   Try to find a minimum change in the objective function. The first scan
368   checks that there are no continuous variables with non-zero coefficients,
369   and grabs the largest objective coefficient associated with an unfixed
370   integer variable. The second scan attempts to scale up the objective
371   coefficients to a point where they are sufficiently close to integer that
372   we can pretend they are integer, and calculate a gcd over the coefficients
373   of interest. This will be the minimum increment for the scaled coefficients.
374   The final action is to scale the increment back for the original coefficients
375   and install it, if it's better than the existing value.
376 
377   John's note: We could do better than this.
378 
379   John's second note - apologies for changing s to z
380 */
381 {
382   const double *objective = getObjCoefficients();
383   const double *lower = getColLower();
384   const double *upper = getColUpper();
385   /*
386       Scan continuous and integer variables to see if continuous
387       are cover or network with integral rhs.
388     */
389   double continuousMultiplier = 1.0;
390   double *coeffMultiplier = NULL;
391   double largestObj = 0.0;
392   double smallestObj = COIN_DBL_MAX;
393   {
394     const double *rowLower = getRowLower();
395     const double *rowUpper = getRowUpper();
396     int numberRows = solver_->getNumRows();
397     double *rhs = new double[numberRows];
398     memset(rhs, 0, numberRows * sizeof(double));
399     int iColumn;
400     int numberColumns = solver_->getNumCols();
401     // Column copy of matrix
402     int problemType = -1;
403     const double *element = solver_->getMatrixByCol()->getElements();
404     const int *row = solver_->getMatrixByCol()->getIndices();
405     const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts();
406     const int *columnLength = solver_->getMatrixByCol()->getVectorLengths();
407     int numberInteger = 0;
408     int numberIntegerObj = 0;
409     int numberGeneralIntegerObj = 0;
410     int numberIntegerWeight = 0;
411     int numberContinuousObj = 0;
412     double cost = COIN_DBL_MAX;
413     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
414       if (upper[iColumn] == lower[iColumn]) {
415         CoinBigIndex start = columnStart[iColumn];
416         CoinBigIndex end = start + columnLength[iColumn];
417         for (CoinBigIndex j = start; j < end; j++) {
418           int iRow = row[j];
419           rhs[iRow] += lower[iColumn] * element[j];
420         }
421       } else {
422         double objValue = objective[iColumn];
423         if (solver_->isInteger(iColumn))
424           numberInteger++;
425         if (objValue) {
426           if (!solver_->isInteger(iColumn)) {
427             numberContinuousObj++;
428           } else {
429             largestObj = CoinMax(largestObj, fabs(objValue));
430             smallestObj = CoinMin(smallestObj, fabs(objValue));
431             numberIntegerObj++;
432             if (cost == COIN_DBL_MAX)
433               cost = objValue;
434             else if (cost != objValue)
435               cost = -COIN_DBL_MAX;
436             int gap = static_cast< int >(upper[iColumn] - lower[iColumn]);
437             if (gap > 1) {
438               numberGeneralIntegerObj++;
439               numberIntegerWeight += gap;
440             }
441           }
442         }
443       }
444     }
445     int iType = 0;
446     if (!numberContinuousObj && numberIntegerObj <= 5 && numberIntegerWeight <= 100 && numberIntegerObj * 3 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100)
447       iType = 1 + 4 + (((moreSpecialOptions_ & 536870912) == 0) ? 2 : 0);
448     else if (!numberContinuousObj && numberIntegerObj <= 100 && numberIntegerObj * 5 < numberObjects_ && numberIntegerWeight <= 100 && !parentModel_ && solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX)
449       iType = 4 + (((moreSpecialOptions_ & 536870912) == 0) ? 2 : 0);
450     else if (!numberContinuousObj && numberIntegerObj <= 100 && numberIntegerObj * 5 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX)
451       iType = 8;
452     int iTest = getMaximumNodes();
453     if (iTest >= 987654320 && iTest < 987654330 && numberObjects_ && !parentModel_) {
454       iType = iTest - 987654320;
455       printf("Testing %d integer variables out of %d objects (%d integer) have cost of %g - %d continuous\n",
456         numberIntegerObj, numberObjects_, numberInteger, cost, numberContinuousObj);
457       if (iType == 9)
458         exit(77);
459       if (numberContinuousObj)
460         iType = 0;
461     }
462 
463     //if (!numberContinuousObj&&(numberIntegerObj<=5||cost!=-COIN_DBL_MAX)&&
464     //numberIntegerObj*3<numberObjects_&&!parentModel_&&solver_->getNumRows()>100) {
465     if (iType) {
466       /*
467             A) put high priority on (if none)
468             B) create artificial objective (if clp)
469             */
470       int iPriority = -1;
471       for (int i = 0; i < numberObjects_; i++) {
472         int k = object_[i]->priority();
473         if (iPriority == -1)
474           iPriority = k;
475         else if (iPriority != k)
476           iPriority = -2;
477       }
478       bool branchOnSatisfied = ((iType & 1) != 0);
479       bool createFake = ((iType & 2) != 0);
480       bool randomCost = ((iType & 4) != 0);
481       if (iPriority >= 0) {
482         char general[200];
483         if (cost == -COIN_DBL_MAX) {
484           sprintf(general, "%d integer variables out of %d objects (%d integer) have costs - high priority",
485             numberIntegerObj, numberObjects_, numberInteger);
486         } else if (cost == COIN_DBL_MAX) {
487           sprintf(general, "No integer variables out of %d objects (%d integer) have costs",
488             numberObjects_, numberInteger);
489           branchOnSatisfied = false;
490         } else {
491           sprintf(general, "%d integer variables out of %d objects (%d integer) have cost of %g - high priority",
492             numberIntegerObj, numberObjects_, numberInteger, cost);
493         }
494         messageHandler()->message(CBC_GENERAL,
495           messages())
496           << general << CoinMessageEol;
497         sprintf(general, "branch on satisfied %c create fake objective %c random cost %c",
498           branchOnSatisfied ? 'Y' : 'N',
499           createFake ? 'Y' : 'N',
500           randomCost ? 'Y' : 'N');
501         messageHandler()->message(CBC_GENERAL,
502           messages())
503           << general << CoinMessageEol;
504         // switch off clp type branching
505         // no ? fastNodeDepth_ = -1;
506         int highPriority = (branchOnSatisfied) ? -999 : 100;
507         for (int i = 0; i < numberObjects_; i++) {
508           CbcSimpleInteger *thisOne = dynamic_cast< CbcSimpleInteger * >(object_[i]);
509           object_[i]->setPriority(1000);
510           if (thisOne) {
511             int iColumn = thisOne->columnNumber();
512             if (objective[iColumn])
513               thisOne->setPriority(highPriority);
514           }
515         }
516       }
517 #ifdef COIN_HAS_CLP
518       OsiClpSolverInterface *clpSolver
519         = dynamic_cast< OsiClpSolverInterface * >(solver_);
520       if (clpSolver && createFake) {
521         // Create artificial objective to be used when all else fixed
522         int numberColumns = clpSolver->getNumCols();
523         double *fakeObj = new double[numberColumns];
524         // Column copy
525         const CoinPackedMatrix *matrixByCol = clpSolver->getMatrixByCol();
526         //const double * element = matrixByCol.getElements();
527         //const int * row = matrixByCol.getIndices();
528         //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
529         const int *columnLength = matrixByCol->getVectorLengths();
530         const double *solution = clpSolver->getColSolution();
531 #ifdef JJF_ZERO
532         int nAtBound = 0;
533         for (int i = 0; i < numberColumns; i++) {
534           double lowerValue = lower[i];
535           double upperValue = upper[i];
536           if (clpSolver->isInteger(i)) {
537             double lowerValue = lower[i];
538             double upperValue = upper[i];
539             double value = solution[i];
540             if (value < lowerValue + 1.0e-6 || value > upperValue - 1.0e-6)
541               nAtBound++;
542           }
543         }
544 #endif
545         /*
546                   Generate a random objective function for problems where the given objective
547                   function is not terribly useful. (Nearly feasible, single integer variable,
548                   that sort of thing.
549                 */
550         CoinDrand48(true, 1234567);
551         for (int i = 0; i < numberColumns; i++) {
552           double lowerValue = lower[i];
553           double upperValue = upper[i];
554           double value = (randomCost) ? ceil((CoinDrand48() + 0.5) * 1000)
555                                       : i + 1 + columnLength[i] * 1000;
556           value *= 0.001;
557           //value += columnLength[i];
558           if (lowerValue > -1.0e5 || upperValue < 1.0e5) {
559             if (fabs(lowerValue) > fabs(upperValue))
560               value = -value;
561             if (clpSolver->isInteger(i)) {
562               double solValue = solution[i];
563               // Better to add in 0.5 or 1.0??
564               if (solValue < lowerValue + 1.0e-6)
565                 value = fabs(value) + 0.5; //fabs(value*1.5);
566               else if (solValue > upperValue - 1.0e-6)
567                 value = -fabs(value) - 0.5; //-fabs(value*1.5);
568             }
569           } else {
570             value = 0.0;
571           }
572           fakeObj[i] = value;
573         }
574         // pass to solver
575         clpSolver->setFakeObjective(fakeObj);
576         delete[] fakeObj;
577       }
578 #endif
579     } else if (largestObj < smallestObj * 5.0 && !parentModel_ && !numberContinuousObj && !numberGeneralIntegerObj && numberIntegerObj * 2 < CoinMin(numberColumns, 20)) {
580       // up priorities on costed
581       int iPriority = -1;
582       for (int i = 0; i < numberObjects_; i++) {
583         int k = object_[i]->priority();
584         if (iPriority == -1)
585           iPriority = k;
586         else if (iPriority != k)
587           iPriority = -2;
588       }
589       if (iPriority >= 100) {
590 #if CBC_USEFUL_PRINTING > 1
591         printf("Setting variables with obj to high priority\n");
592 #endif
593         for (int i = 0; i < numberObjects_; i++) {
594           CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
595           if (obj) {
596             int iColumn = obj->columnNumber();
597             if (objective[iColumn])
598               object_[i]->setPriority(iPriority - 1);
599           }
600         }
601       }
602     }
603     int iRow;
604     for (iRow = 0; iRow < numberRows; iRow++) {
605       if (rowLower[iRow] > -1.0e20 && fabs(rowLower[iRow] - rhs[iRow] - floor(rowLower[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) {
606         continuousMultiplier = 0.0;
607         break;
608       }
609       if (rowUpper[iRow] < 1.0e20 && fabs(rowUpper[iRow] - rhs[iRow] - floor(rowUpper[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) {
610         continuousMultiplier = 0.0;
611         break;
612       }
613       // set rhs to limiting value
614       if (rowLower[iRow] != rowUpper[iRow]) {
615         if (rowLower[iRow] > -1.0e20) {
616           if (rowUpper[iRow] < 1.0e20) {
617             // no good
618             continuousMultiplier = 0.0;
619             break;
620           } else {
621             rhs[iRow] = rowLower[iRow] - rhs[iRow];
622             if (problemType < 0)
623               problemType = 3; // set cover
624             else if (problemType != 3)
625               problemType = 4;
626           }
627         } else {
628           rhs[iRow] = rowUpper[iRow] - rhs[iRow];
629           if (problemType < 0)
630             problemType = 1; // set partitioning <=
631           else if (problemType != 1)
632             problemType = 4;
633         }
634       } else {
635         rhs[iRow] = rowUpper[iRow] - rhs[iRow];
636         if (problemType < 0)
637           problemType = 3; // set partitioning ==
638         else if (problemType != 2)
639           problemType = 2;
640       }
641       if (fabs(rhs[iRow] - 1.0) > 1.0e-12)
642         problemType = 4;
643     }
644     if (continuousMultiplier) {
645       // 1 network, 2 cover, 4 negative cover
646       int possible = 7;
647       bool unitRhs = true;
648       // See which rows could be set cover
649       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
650         if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
651           CoinBigIndex start = columnStart[iColumn];
652           CoinBigIndex end = start + columnLength[iColumn];
653           for (CoinBigIndex j = start; j < end; j++) {
654             double value = element[j];
655             if (value == 1.0) {
656             } else if (value == -1.0) {
657               rhs[row[j]] = -0.5;
658             } else {
659               rhs[row[j]] = -COIN_DBL_MAX;
660             }
661           }
662         }
663       }
664       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
665         if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
666           if (!isInteger(iColumn)) {
667             CoinBigIndex start = columnStart[iColumn];
668             CoinBigIndex end = start + columnLength[iColumn];
669             double rhsValue = 0.0;
670             // 1 all ones, -1 all -1s, 2 all +- 1, 3 no good
671             int type = 0;
672             for (CoinBigIndex j = start; j < end; j++) {
673               double value = element[j];
674               if (fabs(value) != 1.0) {
675                 type = 3;
676                 break;
677               } else if (value == 1.0) {
678                 if (!type)
679                   type = 1;
680                 else if (type != 1)
681                   type = 2;
682               } else {
683                 if (!type)
684                   type = -1;
685                 else if (type != -1)
686                   type = 2;
687               }
688               int iRow = row[j];
689               if (rhs[iRow] == -COIN_DBL_MAX) {
690                 type = 3;
691                 break;
692               } else if (rhs[iRow] == -0.5) {
693                 // different values
694                 unitRhs = false;
695               } else if (rhsValue) {
696                 if (rhsValue != rhs[iRow])
697                   unitRhs = false;
698               } else {
699                 rhsValue = rhs[iRow];
700               }
701             }
702             // if no elements OK
703             if (type == 3) {
704               // no good
705               possible = 0;
706               break;
707             } else if (type == 2) {
708               if (end - start > 2) {
709                 // no good
710                 possible = 0;
711                 break;
712               } else {
713                 // only network
714                 possible &= 1;
715                 if (!possible)
716                   break;
717               }
718             } else if (type == 1) {
719               // only cover
720               possible &= 2;
721               if (!possible)
722                 break;
723             } else if (type == -1) {
724               // only negative cover
725               possible &= 4;
726               if (!possible)
727                 break;
728             }
729           }
730         }
731       }
732       if ((possible == 2 || possible == 4) && !unitRhs) {
733 #if COIN_DEVELOP > 1
734         printf("XXXXXX Continuous all +1 but different rhs\n");
735 #endif
736         possible = 0;
737       }
738       // may be all integer
739       if (possible != 7) {
740         if (!possible)
741           continuousMultiplier = 0.0;
742         else if (possible == 1)
743           continuousMultiplier = 1.0;
744         else
745           continuousMultiplier = 0.0; // 0.5 was incorrect;
746 #if COIN_DEVELOP > 1
747         if (continuousMultiplier)
748           printf("XXXXXX multiplier of %g\n", continuousMultiplier);
749 #endif
750         if (continuousMultiplier == 0.5) {
751           coeffMultiplier = new double[numberColumns];
752           bool allOne = true;
753           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
754             coeffMultiplier[iColumn] = 1.0;
755             if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
756               if (!isInteger(iColumn)) {
757                 CoinBigIndex start = columnStart[iColumn];
758                 int iRow = row[start];
759                 double value = rhs[iRow];
760                 assert(value >= 0.0);
761                 if (value != 0.0 && value != 1.0)
762                   allOne = false;
763                 coeffMultiplier[iColumn] = 0.5 * value;
764               }
765             }
766           }
767           if (allOne) {
768             // back to old way
769             delete[] coeffMultiplier;
770             coeffMultiplier = NULL;
771           }
772         }
773       } else {
774         // all integer
775         problemType_ = problemType;
776 #if COIN_DEVELOP > 1
777         printf("Problem type is %d\n", problemType_);
778 #endif
779       }
780     }
781 
782     // But try again
783     if (continuousMultiplier < 1.0) {
784       memset(rhs, 0, numberRows * sizeof(double));
785       int *count = new int[numberRows];
786       memset(count, 0, numberRows * sizeof(int));
787       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
788         CoinBigIndex start = columnStart[iColumn];
789         CoinBigIndex end = start + columnLength[iColumn];
790         if (upper[iColumn] == lower[iColumn]) {
791           for (CoinBigIndex j = start; j < end; j++) {
792             int iRow = row[j];
793             rhs[iRow] += lower[iColumn] * element[j];
794           }
795         } else if (solver_->isInteger(iColumn)) {
796           for (CoinBigIndex j = start; j < end; j++) {
797             int iRow = row[j];
798             if (fabs(element[j] - floor(element[j] + 0.5)) > 1.0e-10)
799               rhs[iRow] = COIN_DBL_MAX;
800           }
801         } else {
802           for (CoinBigIndex j = start; j < end; j++) {
803             int iRow = row[j];
804             count[iRow]++;
805             if (fabs(element[j]) != 1.0)
806               rhs[iRow] = COIN_DBL_MAX;
807           }
808         }
809       }
810       // now look at continuous
811       bool allGood = true;
812       double direction = solver_->getObjSense();
813       int numberObj = 0;
814       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
815         if (upper[iColumn] > lower[iColumn]) {
816           double objValue = objective[iColumn] * direction;
817           if (objValue && !solver_->isInteger(iColumn)) {
818             numberObj++;
819             CoinBigIndex start = columnStart[iColumn];
820             CoinBigIndex end = start + columnLength[iColumn];
821             if (objValue > 0.0) {
822               // wants to be as low as possible
823               if (lower[iColumn] < -1.0e10 || fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
824                 allGood = false;
825                 break;
826               } else if (upper[iColumn] < 1.0e10 && fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
827                 allGood = false;
828                 break;
829               }
830               bool singletonRow = true;
831               bool equality = false;
832               for (CoinBigIndex j = start; j < end; j++) {
833                 int iRow = row[j];
834                 if (count[iRow] > 1)
835                   singletonRow = false;
836                 else if (rowLower[iRow] == rowUpper[iRow])
837                   equality = true;
838                 double rhsValue = rhs[iRow];
839                 double lowerValue = rowLower[iRow];
840                 double upperValue = rowUpper[iRow];
841                 if (rhsValue < 1.0e20) {
842                   if (lowerValue > -1.0e20)
843                     lowerValue -= rhsValue;
844                   if (upperValue < 1.0e20)
845                     upperValue -= rhsValue;
846                 }
847                 if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
848                   || fabs(element[j]) != 1.0) {
849                   // no good
850                   allGood = false;
851                   break;
852                 }
853                 if (element[j] > 0.0) {
854                   if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
855                     // no good
856                     allGood = false;
857                     break;
858                   }
859                 } else {
860                   if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
861                     // no good
862                     allGood = false;
863                     break;
864                   }
865                 }
866               }
867               if (!singletonRow && end > start + 1 && !equality)
868                 allGood = false;
869               if (!allGood)
870                 break;
871             } else {
872               // wants to be as high as possible
873               if (upper[iColumn] > 1.0e10 || fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
874                 allGood = false;
875                 break;
876               } else if (lower[iColumn] > -1.0e10 && fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
877                 allGood = false;
878                 break;
879               }
880               bool singletonRow = true;
881               bool equality = false;
882               for (CoinBigIndex j = start; j < end; j++) {
883                 int iRow = row[j];
884                 if (count[iRow] > 1)
885                   singletonRow = false;
886                 else if (rowLower[iRow] == rowUpper[iRow])
887                   equality = true;
888                 double rhsValue = rhs[iRow];
889                 double lowerValue = rowLower[iRow];
890                 double upperValue = rowUpper[iRow];
891                 if (rhsValue < 1.0e20) {
892                   if (lowerValue > -1.0e20)
893                     lowerValue -= rhsValue;
894                   if (upperValue < 1.0e20)
895                     upperValue -= rhsValue;
896                 }
897                 if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
898                   || fabs(element[j]) != 1.0) {
899                   // no good
900                   allGood = false;
901                   break;
902                 }
903                 if (element[j] < 0.0) {
904                   if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
905                     // no good
906                     allGood = false;
907                     break;
908                   }
909                 } else {
910                   if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
911                     // no good
912                     allGood = false;
913                     break;
914                   }
915                 }
916               }
917               if (!singletonRow && end > start + 1 && !equality)
918                 allGood = false;
919               if (!allGood)
920                 break;
921             }
922           }
923         }
924       }
925       delete[] count;
926       if (allGood) {
927 #if COIN_DEVELOP > 1
928         if (numberObj)
929           printf("YYYY analysis says all continuous with costs will be integer\n");
930 #endif
931         continuousMultiplier = 1.0;
932       }
933     }
934     delete[] rhs;
935   }
936   /*
937       Take a first scan to see if there are unfixed continuous variables in the
938       objective.  If so, the minimum objective change could be arbitrarily small.
939       Also pick off the maximum coefficient of an unfixed integer variable.
940 
941       If the objective is found to contain only integer variables, set the
942       fathoming discipline to strict.
943     */
944   double maximumCost = 0.0;
945   //double trueIncrement=0.0;
946   int iColumn;
947   int numberColumns = getNumCols();
948   double scaleFactor = 1.0; // due to rhs etc
949   /*
950       Original model did not have integer bounds.
951     */
952   if ((specialOptions_ & 65536) == 0) {
953     /* be on safe side (later look carefully as may be able to
954            to get 0.5 say if bounds are multiples of 0.5 */
955     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
956       if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
957         double value;
958         value = fabs(lower[iColumn]);
959         if (floor(value + 0.5) != value) {
960           scaleFactor = CoinMin(scaleFactor, 0.5);
961           if (floor(2.0 * value + 0.5) != 2.0 * value) {
962             scaleFactor = CoinMin(scaleFactor, 0.25);
963             if (floor(4.0 * value + 0.5) != 4.0 * value) {
964               scaleFactor = 0.0;
965             }
966           }
967         }
968         value = fabs(upper[iColumn]);
969         if (floor(value + 0.5) != value) {
970           scaleFactor = CoinMin(scaleFactor, 0.5);
971           if (floor(2.0 * value + 0.5) != 2.0 * value) {
972             scaleFactor = CoinMin(scaleFactor, 0.25);
973             if (floor(4.0 * value + 0.5) != 4.0 * value) {
974               scaleFactor = 0.0;
975             }
976           }
977         }
978       }
979     }
980   }
981   bool possibleMultiple = continuousMultiplier != 0.0 && scaleFactor != 0.0;
982   if (possibleMultiple) {
983     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
984       if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
985         maximumCost = CoinMax(maximumCost, fabs(objective[iColumn]));
986       }
987     }
988   }
989   setIntParam(CbcModel::CbcFathomDiscipline, possibleMultiple);
990   /*
991       If a nontrivial increment is possible, try and figure it out. We're looking
992       for gcd(c<j>) for all c<j> that are coefficients of unfixed integer
993       variables. Since the c<j> might not be integers, try and inflate them
994       sufficiently that they look like integers (and we'll deflate the gcd
995       later).
996 
997       2520.0 is used as it is a nice multiple of 2,3,5,7
998     */
999   if (possibleMultiple && maximumCost) {
1000     int increment = 0;
1001     double multiplier = 2520.0;
1002     while (10.0 * multiplier * maximumCost < 1.0e8)
1003       multiplier *= 10.0;
1004     int bigIntegers = 0; // Count of large costs which are integer
1005     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1006       if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
1007         double objValue = fabs(objective[iColumn]);
1008         if (!isInteger(iColumn)) {
1009           if (!coeffMultiplier)
1010             objValue *= continuousMultiplier;
1011           else
1012             objValue *= coeffMultiplier[iColumn];
1013         }
1014         if (objValue) {
1015           double value = objValue * multiplier;
1016           if (value < 2.1e9) {
1017             int nearest = static_cast< int >(floor(value + 0.5));
1018             if (fabs(value - floor(value + 0.5)) > 1.0e-8) {
1019               increment = 0;
1020               break;
1021             } else if (!increment) {
1022               increment = nearest;
1023             } else {
1024               increment = gcd(increment, nearest);
1025             }
1026           } else {
1027             // large value - may still be multiple of 1.0
1028             if (fabs(objValue - floor(objValue + 0.5)) > 1.0e-8) {
1029               increment = 0;
1030               break;
1031             } else {
1032               bigIntegers++;
1033             }
1034           }
1035         }
1036       }
1037     }
1038     if (coeffMultiplier) {
1039         delete[] coeffMultiplier;
1040         coeffMultiplier = NULL;
1041     }
1042     /*
1043           If the increment beats the current value for objective change, install it.
1044         */
1045     if (increment) {
1046       double value = increment;
1047       double cutoff = getDblParam(CbcModel::CbcCutoffIncrement);
1048       if (bigIntegers) {
1049         // allow for 1.0
1050         increment = gcd(increment, static_cast< int >(multiplier));
1051         value = increment;
1052       }
1053       value /= multiplier;
1054       value *= scaleFactor;
1055       //trueIncrement=CoinMax(cutoff,value);;
1056       if (value * 0.999 > cutoff) {
1057         messageHandler()->message(CBC_INTEGERINCREMENT,
1058           messages())
1059           << value << CoinMessageEol;
1060         setDblParam(CbcModel::CbcCutoffIncrement, CoinMax(value * 0.999, value - 1.0e-4));
1061       }
1062     }
1063   }
1064 
1065   if (coeffMultiplier)
1066       delete[] coeffMultiplier;
1067 
1068   return;
1069 }
1070 
1071 /*
1072 saveModel called (carved out of) BranchandBound
1073 */
saveModel(OsiSolverInterface * saveSolver,double * checkCutoffForRestart,bool * feasible)1074 void CbcModel::saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForRestart, bool *feasible)
1075 {
1076   if (saveSolver && (specialOptions_ & 32768) != 0) {
1077     // See if worth trying reduction
1078     *checkCutoffForRestart = getCutoff();
1079     bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() && (*checkCutoffForRestart < 1.0e20);
1080     int numberColumns = getNumCols();
1081     if (tryNewSearch) {
1082 #if CBC_USEFUL_PRINTING > 1
1083       printf("after %d nodes, cutoff %g - looking\n",
1084         numberNodes_, getCutoff());
1085 #endif
1086       saveSolver->resolve();
1087       double direction = saveSolver->getObjSense();
1088       double gap = *checkCutoffForRestart - saveSolver->getObjValue() * direction;
1089       double tolerance;
1090       saveSolver->getDblParam(OsiDualTolerance, tolerance);
1091       if (gap <= 0.0)
1092         gap = tolerance;
1093       gap += 100.0 * tolerance;
1094       double integerTolerance = getDblParam(CbcIntegerTolerance);
1095 
1096       const double *lower = saveSolver->getColLower();
1097       const double *upper = saveSolver->getColUpper();
1098       const double *solution = saveSolver->getColSolution();
1099       const double *reducedCost = saveSolver->getReducedCost();
1100 
1101       int numberFixed = 0;
1102       int numberFixed2 = 0;
1103       for (int i = 0; i < numberIntegers_; i++) {
1104         int iColumn = integerVariable_[i];
1105         double djValue = direction * reducedCost[iColumn];
1106         if (upper[iColumn] - lower[iColumn] > integerTolerance) {
1107           if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
1108             saveSolver->setColUpper(iColumn, lower[iColumn]);
1109             numberFixed++;
1110           } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
1111             saveSolver->setColLower(iColumn, upper[iColumn]);
1112             numberFixed++;
1113           }
1114         } else {
1115           numberFixed2++;
1116         }
1117       }
1118 #ifdef COIN_DEVELOP
1119       /*
1120               We're debugging. (specialOptions 1)
1121             */
1122       if ((specialOptions_ & 1) != 0) {
1123         const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger();
1124         if (debugger) {
1125           printf("Contains optimal\n");
1126           OsiSolverInterface *temp = saveSolver->clone();
1127           const double *solution = debugger->optimalSolution();
1128           const double *lower = temp->getColLower();
1129           const double *upper = temp->getColUpper();
1130           int n = temp->getNumCols();
1131           for (int i = 0; i < n; i++) {
1132             if (temp->isInteger(i)) {
1133               double value = floor(solution[i] + 0.5);
1134               assert(value >= lower[i] && value <= upper[i]);
1135               temp->setColLower(i, value);
1136               temp->setColUpper(i, value);
1137             }
1138           }
1139           temp->writeMps("reduced_fix");
1140           delete temp;
1141           saveSolver->writeMps("reduced");
1142         } else {
1143           abort();
1144         }
1145       }
1146       printf("Restart could fix %d integers (%d already fixed)\n",
1147         numberFixed + numberFixed2, numberFixed2);
1148 #endif
1149       numberFixed += numberFixed2;
1150       if (numberFixed * 20 < numberColumns)
1151         tryNewSearch = false;
1152     }
1153     if (tryNewSearch) {
1154       // back to solver without cuts?
1155       OsiSolverInterface *solver2 = continuousSolver_->clone();
1156       const double *lower = saveSolver->getColLower();
1157       const double *upper = saveSolver->getColUpper();
1158       for (int i = 0; i < numberIntegers_; i++) {
1159         int iColumn = integerVariable_[i];
1160         solver2->setColLower(iColumn, lower[iColumn]);
1161         solver2->setColUpper(iColumn, upper[iColumn]);
1162       }
1163       // swap
1164       delete saveSolver;
1165       saveSolver = solver2;
1166       double *newSolution = new double[numberColumns];
1167       double objectiveValue = *checkCutoffForRestart;
1168       CbcSerendipity heuristic(*this);
1169       if (bestSolution_)
1170         heuristic.setInputSolution(bestSolution_, bestObjective_);
1171       heuristic.setFractionSmall(0.9);
1172       heuristic.setFeasibilityPumpOptions(1008013);
1173       // Use numberNodes to say how many are original rows
1174       heuristic.setNumberNodes(continuousSolver_->getNumRows());
1175 #ifdef COIN_DEVELOP
1176       if (continuousSolver_->getNumRows() < saveSolver->getNumRows())
1177         printf("%d rows added ZZZZZ\n",
1178           solver_->getNumRows() - continuousSolver_->getNumRows());
1179 #endif
1180       int returnCode = heuristic.smallBranchAndBound(saveSolver,
1181         -1, newSolution,
1182         objectiveValue,
1183         *checkCutoffForRestart, "Reduce");
1184       if (returnCode < 0) {
1185 #ifdef COIN_DEVELOP
1186         printf("Restart - not small enough to do search after fixing\n");
1187 #endif
1188         delete[] newSolution;
1189       } else {
1190         if ((returnCode & 1) != 0) {
1191           // increment number of solutions so other heuristics can test
1192           numberSolutions_++;
1193           numberHeuristicSolutions_++;
1194           lastHeuristic_ = NULL;
1195           setBestSolution(CBC_ROUNDING, objectiveValue, newSolution);
1196         }
1197         delete[] newSolution;
1198         *feasible = false; // stop search
1199       }
1200 #if 0 // probably not needed def CBC_THREAD
1201             if (master_) {
1202                 lockThread();
1203                 if (parallelMode() > 0) {
1204                     while (master_->waitForThreadsInTree(0)) {
1205                         lockThread();
1206                         double dummyBest;
1207                         tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
1208                         //unlockThread();
1209                     }
1210                 }
1211                 master_->waitForThreadsInTree(2);
1212                 delete master_;
1213                 master_ = NULL;
1214                 masterThread_ = NULL;
1215             }
1216 #endif
1217     }
1218   }
1219 }
1220 /*
1221 Adds integers, called from BranchandBound()
1222 */
AddIntegers()1223 void CbcModel::AddIntegers()
1224 {
1225   int numberColumns = continuousSolver_->getNumCols();
1226   int numberRows = continuousSolver_->getNumRows();
1227   int numberOriginalIntegers = numberIntegers_;
1228   int *del = new int[CoinMax(numberColumns, numberRows)];
1229   int *original = new int[numberColumns];
1230   char *possibleRow = new char[numberRows];
1231   {
1232     const CoinPackedMatrix *rowCopy = continuousSolver_->getMatrixByRow();
1233     const int *column = rowCopy->getIndices();
1234     const int *rowLength = rowCopy->getVectorLengths();
1235     const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
1236     const double *rowLower = continuousSolver_->getRowLower();
1237     const double *rowUpper = continuousSolver_->getRowUpper();
1238     const double *element = rowCopy->getElements();
1239     for (int i = 0; i < numberRows; i++) {
1240       int nLeft = 0;
1241       bool possible = false;
1242       if (rowLower[i] < -1.0e20) {
1243         double value = rowUpper[i];
1244         if (fabs(value - floor(value + 0.5)) < 1.0e-8)
1245           possible = true;
1246       } else if (rowUpper[i] > 1.0e20) {
1247         double value = rowLower[i];
1248         if (fabs(value - floor(value + 0.5)) < 1.0e-8)
1249           possible = true;
1250       } else {
1251         double value = rowUpper[i];
1252         if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8)
1253           possible = true;
1254       }
1255       double allSame = (possible) ? 0.0 : -1.0;
1256       for (CoinBigIndex j = rowStart[i];
1257            j < rowStart[i] + rowLength[i]; j++) {
1258         int iColumn = column[j];
1259         if (continuousSolver_->isInteger(iColumn)) {
1260           if (fabs(element[j]) != 1.0)
1261             possible = false;
1262         } else {
1263           nLeft++;
1264           if (!allSame) {
1265             allSame = fabs(element[j]);
1266           } else if (allSame > 0.0) {
1267             if (allSame != fabs(element[j]))
1268               allSame = -1.0;
1269           }
1270         }
1271       }
1272       if (nLeft == rowLength[i] && allSame > 0.0)
1273         possibleRow[i] = 2;
1274       else if (possible || !nLeft)
1275         possibleRow[i] = 1;
1276       else
1277         possibleRow[i] = 0;
1278     }
1279   }
1280   int nDel = 0;
1281   for (int i = 0; i < numberColumns; i++) {
1282     original[i] = i;
1283     if (continuousSolver_->isInteger(i))
1284       del[nDel++] = i;
1285   }
1286   {
1287     // we must not exclude current best solution (rounding errors)
1288     // also not if large values
1289     const int *row = continuousSolver_->getMatrixByCol()->getIndices();
1290     const CoinBigIndex *columnStart = continuousSolver_->getMatrixByCol()->getVectorStarts();
1291     const int *columnLength = continuousSolver_->getMatrixByCol()->getVectorLengths();
1292     const double *solution = continuousSolver_->getColSolution();
1293     for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
1294       if (!continuousSolver_->isInteger(iColumn)) {
1295         double value = bestSolution_ ? bestSolution_[iColumn] : 0.0;
1296         double value2 = solution[iColumn];
1297         if (fabs(value - floor(value + 0.5)) > 1.0e-8 || fabs(value2) > 1.0e3) {
1298           CoinBigIndex start = columnStart[iColumn];
1299           CoinBigIndex end = start + columnLength[iColumn];
1300           for (CoinBigIndex j = start; j < end; j++) {
1301             int iRow = row[j];
1302             possibleRow[iRow] = 0;
1303           }
1304         }
1305       }
1306     }
1307   }
1308   int nExtra = 0;
1309   OsiSolverInterface *copy1 = continuousSolver_->clone();
1310   int nPass = 0;
1311   while (nDel && nPass < 10) {
1312     nPass++;
1313     OsiSolverInterface *copy2 = copy1->clone();
1314     int nLeft = 0;
1315     for (int i = 0; i < nDel; i++)
1316       original[del[i]] = -1;
1317     for (int i = 0; i < numberColumns; i++) {
1318       int kOrig = original[i];
1319       if (kOrig >= 0)
1320         original[nLeft++] = kOrig;
1321     }
1322     assert(nLeft == numberColumns - nDel);
1323     copy2->deleteCols(nDel, del);
1324     numberColumns = copy2->getNumCols();
1325     const CoinPackedMatrix *rowCopy = copy2->getMatrixByRow();
1326     numberRows = rowCopy->getNumRows();
1327     const int *column = rowCopy->getIndices();
1328     const int *rowLength = rowCopy->getVectorLengths();
1329     const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
1330     const double *rowLower = copy2->getRowLower();
1331     const double *rowUpper = copy2->getRowUpper();
1332     const double *element = rowCopy->getElements();
1333     const CoinPackedMatrix *columnCopy = copy2->getMatrixByCol();
1334     const int *columnLength = columnCopy->getVectorLengths();
1335     nDel = 0;
1336     // Could do gcd stuff on ones with costs
1337     for (int i = 0; i < numberRows; i++) {
1338       if (!rowLength[i]) {
1339         del[nDel++] = i;
1340       } else if (possibleRow[i]) {
1341         if (rowLength[i] == 1) {
1342           CoinBigIndex k = rowStart[i];
1343           int iColumn = column[k];
1344           if (!copy2->isInteger(iColumn)) {
1345             double mult = 1.0 / fabs(element[k]);
1346             if (rowLower[i] < -1.0e20) {
1347               // treat rhs as multiple of 1 unless elements all same
1348               double value = ((possibleRow[i] == 2) ? rowUpper[i] : 1.0) * mult;
1349               if (fabs(value - floor(value + 0.5)) < 1.0e-8) {
1350                 del[nDel++] = i;
1351                 if (columnLength[iColumn] == 1) {
1352                   copy2->setInteger(iColumn);
1353                   int kOrig = original[iColumn];
1354                   setOptionalInteger(kOrig);
1355                 }
1356               }
1357             } else if (rowUpper[i] > 1.0e20) {
1358               // treat rhs as multiple of 1 unless elements all same
1359               double value = ((possibleRow[i] == 2) ? rowLower[i] : 1.0) * mult;
1360               if (fabs(value - floor(value + 0.5)) < 1.0e-8) {
1361                 del[nDel++] = i;
1362                 if (columnLength[iColumn] == 1) {
1363                   copy2->setInteger(iColumn);
1364                   int kOrig = original[iColumn];
1365                   setOptionalInteger(kOrig);
1366                 }
1367               }
1368             } else {
1369               // treat rhs as multiple of 1 unless elements all same
1370               double value = ((possibleRow[i] == 2) ? rowUpper[i] : 1.0) * mult;
1371               if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8) {
1372                 del[nDel++] = i;
1373                 copy2->setInteger(iColumn);
1374                 int kOrig = original[iColumn];
1375                 setOptionalInteger(kOrig);
1376               }
1377             }
1378           }
1379         } else {
1380           // only if all singletons
1381           bool possible = false;
1382           if (rowLower[i] < -1.0e20) {
1383             double value = rowUpper[i];
1384             if (fabs(value - floor(value + 0.5)) < 1.0e-8)
1385               possible = true;
1386           } else if (rowUpper[i] > 1.0e20) {
1387             double value = rowLower[i];
1388             if (fabs(value - floor(value + 0.5)) < 1.0e-8)
1389               possible = true;
1390           } else {
1391             double value = rowUpper[i];
1392             if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8)
1393               possible = true;
1394           }
1395           if (possible) {
1396             for (CoinBigIndex j = rowStart[i];
1397                  j < rowStart[i] + rowLength[i]; j++) {
1398               int iColumn = column[j];
1399               if (columnLength[iColumn] != 1 || fabs(element[j]) != 1.0) {
1400                 possible = false;
1401                 break;
1402               }
1403             }
1404             if (possible) {
1405               for (CoinBigIndex j = rowStart[i];
1406                    j < rowStart[i] + rowLength[i]; j++) {
1407                 int iColumn = column[j];
1408                 if (!copy2->isInteger(iColumn)) {
1409                   copy2->setInteger(iColumn);
1410                   int kOrig = original[iColumn];
1411                   setOptionalInteger(kOrig);
1412                 }
1413               }
1414               del[nDel++] = i;
1415             }
1416           }
1417         }
1418       }
1419     }
1420     if (nDel) {
1421       copy2->deleteRows(nDel, del);
1422       // pack down possible
1423       int n = 0;
1424       for (int i = 0; i < nDel; i++)
1425         possibleRow[del[i]] = -1;
1426       for (int i = 0; i < numberRows; i++) {
1427         if (possibleRow[i] >= 0)
1428           possibleRow[n++] = possibleRow[i];
1429       }
1430     }
1431     if (nDel != numberRows) {
1432       nDel = 0;
1433       for (int i = 0; i < numberColumns; i++) {
1434         if (copy2->isInteger(i)) {
1435           del[nDel++] = i;
1436           nExtra++;
1437         }
1438       }
1439     } else {
1440       nDel = 0;
1441     }
1442     delete copy1;
1443     copy1 = copy2->clone();
1444     delete copy2;
1445   }
1446   // See if what's left is a network
1447   bool couldBeNetwork = false;
1448   if (copy1->getNumRows() && copy1->getNumCols()) {
1449 #ifdef COIN_HAS_CLP
1450     OsiClpSolverInterface *clpSolver
1451       = dynamic_cast< OsiClpSolverInterface * >(copy1);
1452     if (false && clpSolver) {
1453       numberRows = clpSolver->getNumRows();
1454       char *rotate = new char[numberRows];
1455       int n = clpSolver->getModelPtr()->findNetwork(rotate, 1.0);
1456       delete[] rotate;
1457 #if CBC_USEFUL_PRINTING > 1
1458       printf("INTA network %d rows out of %d\n", n, numberRows);
1459 #endif
1460       if (CoinAbs(n) == numberRows) {
1461         couldBeNetwork = true;
1462         for (int i = 0; i < numberRows; i++) {
1463           if (!possibleRow[i]) {
1464             couldBeNetwork = false;
1465 #if CBC_USEFUL_PRINTING > 1
1466             printf("but row %d is bad\n", i);
1467 #endif
1468             break;
1469           }
1470         }
1471       }
1472     } else
1473 #endif
1474     {
1475       numberColumns = copy1->getNumCols();
1476       numberRows = copy1->getNumRows();
1477       const double *rowLower = copy1->getRowLower();
1478       const double *rowUpper = copy1->getRowUpper();
1479       couldBeNetwork = true;
1480       for (int i = 0; i < numberRows; i++) {
1481         if (rowLower[i] > -1.0e20 && fabs(rowLower[i] - floor(rowLower[i] + 0.5)) > 1.0e-12) {
1482           couldBeNetwork = false;
1483           break;
1484         }
1485         if (rowUpper[i] < 1.0e20 && fabs(rowUpper[i] - floor(rowUpper[i] + 0.5)) > 1.0e-12) {
1486           couldBeNetwork = false;
1487           break;
1488         }
1489         if (possibleRow[i] == 0) {
1490           couldBeNetwork = false;
1491           break;
1492         }
1493       }
1494       if (couldBeNetwork) {
1495         const CoinPackedMatrix *matrixByCol = copy1->getMatrixByCol();
1496         const double *element = matrixByCol->getElements();
1497         //const int * row = matrixByCol->getIndices();
1498         const CoinBigIndex *columnStart = matrixByCol->getVectorStarts();
1499         const int *columnLength = matrixByCol->getVectorLengths();
1500         for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
1501           CoinBigIndex start = columnStart[iColumn];
1502           CoinBigIndex end = start + columnLength[iColumn];
1503           if (end > start + 2) {
1504             couldBeNetwork = false;
1505             break;
1506           }
1507           int type = 0;
1508           for (CoinBigIndex j = start; j < end; j++) {
1509             double value = element[j];
1510             if (fabs(value) != 1.0) {
1511               couldBeNetwork = false;
1512               break;
1513             } else if (value == 1.0) {
1514               if ((type & 1) == 0)
1515                 type |= 1;
1516               else
1517                 type = 7;
1518             } else if (value == -1.0) {
1519               if ((type & 2) == 0)
1520                 type |= 2;
1521               else
1522                 type = 7;
1523             }
1524           }
1525           if (type > 3) {
1526             couldBeNetwork = false;
1527             break;
1528           }
1529         }
1530       }
1531     }
1532   }
1533   if (couldBeNetwork) {
1534     for (int i = 0; i < numberColumns; i++)
1535       setOptionalInteger(original[i]);
1536   }
1537   if (nExtra || couldBeNetwork) {
1538     numberColumns = copy1->getNumCols();
1539     numberRows = copy1->getNumRows();
1540     if (!numberColumns || !numberRows) {
1541       int numberColumns = solver_->getNumCols();
1542       for (int i = 0; i < numberColumns; i++)
1543         assert(solver_->isInteger(i));
1544     }
1545 #if CBC_USEFUL_PRINTING > 1
1546     if (couldBeNetwork || nExtra)
1547       printf("INTA %d extra integers, %d left%s\n", nExtra,
1548         numberColumns,
1549         couldBeNetwork ? ", all network" : "");
1550 #endif
1551     findIntegers(true, 2);
1552     convertToDynamic();
1553   }
1554 #if CBC_USEFUL_PRINTING > 1
1555   if (!couldBeNetwork && copy1->getNumCols() && copy1->getNumRows()) {
1556     printf("INTA %d rows and %d columns remain\n",
1557       copy1->getNumRows(), copy1->getNumCols());
1558     if (copy1->getNumCols() < 200) {
1559       copy1->writeMps("moreint");
1560       printf("INTA Written remainder to moreint.mps.gz %d rows %d cols\n",
1561         copy1->getNumRows(), copy1->getNumCols());
1562     }
1563   }
1564 #endif
1565   delete copy1;
1566   delete[] del;
1567   delete[] original;
1568   delete[] possibleRow;
1569   // double check increment
1570   analyzeObjective();
1571   // If any changes - tell code
1572   if (numberOriginalIntegers < numberIntegers_)
1573     synchronizeModel();
1574 }
1575 /**
1576   \todo
1577   Normally, it looks like we enter here from command dispatch in the main
1578   routine, after calling the solver for an initial solution
1579   (CbcModel::initialSolve, which simply calls the solver's initialSolve
1580   routine.) The first thing we do is call resolve. Presumably there are
1581   circumstances where this is nontrivial? There's also a call from
1582   CbcModel::originalModel (tied up with integer presolve), which should be
1583   checked.
1584 
1585 */
1586 
1587 #ifdef CONFLICT_CUTS
1588 #if PRINT_CONFLICT == 1
1589 static int numberConflictCuts = 0;
1590 static int lastNumberConflictCuts = 0;
1591 static double lengthConflictCuts = 0.0;
1592 #endif
1593 #endif
1594 /*
1595   The overall flow can be divided into three stages:
1596     * Prep: Check that the lp relaxation remains feasible at the root. If so,
1597       do all the setup for B&C.
1598     * Process the root node: Generate cuts, apply heuristics, and in general do
1599       the best we can to resolve the problem without B&C.
1600     * Do B&C search until we hit a limit or exhaust the search tree.
1601 
1602   Keep in mind that in general there is no node in the search tree that
1603   corresponds to the active subproblem. The active subproblem is represented
1604   by the current state of the model,  of the solver, and of the constraint
1605   system held by the solver.
1606 */
1607 #ifdef COIN_HAS_CPX
1608 #include "OsiCpxSolverInterface.hpp"
1609 #include "cplex.h"
1610 #endif
branchAndBound(int doStatistics)1611 void CbcModel::branchAndBound(int doStatistics)
1612 
1613 {
1614   if (!parentModel_) {
1615     /*
1616 	Capture a time stamp before we start (unless set).
1617       */
1618     if (!dblParam_[CbcStartSeconds]) {
1619       if (!useElapsedTime())
1620         dblParam_[CbcStartSeconds] = CoinCpuTime();
1621       else
1622         dblParam_[CbcStartSeconds] = CoinGetTimeOfDay();
1623     }
1624   }
1625   dblParam_[CbcSmallestChange] = COIN_DBL_MAX;
1626   dblParam_[CbcSumChange] = 0.0;
1627   dblParam_[CbcLargestChange] = 0.0;
1628   intParam_[CbcNumberBranches] = 0;
1629   double lastBestPossibleObjective = -COIN_DBL_MAX;
1630   // when to check for restart
1631   int nextCheckRestart = 50;
1632   // Force minimization !!!!
1633   bool flipObjective = (solver_->getObjSense() < 0.0);
1634   if (flipObjective)
1635     flipModel();
1636   dblParam_[CbcOptimizationDirection] = 1.0; // was solver_->getObjSense();
1637   strongInfo_[0] = 0;
1638   strongInfo_[1] = 0;
1639   strongInfo_[2] = 0;
1640   strongInfo_[3] = 0;
1641   strongInfo_[4] = 0;
1642   strongInfo_[5] = 0;
1643   strongInfo_[6] = 0;
1644   numberStrongIterations_ = 0;
1645   currentNode_ = NULL;
1646   // See if should do cuts old way
1647   if (parallelMode() < 0) {
1648     specialOptions_ |= 4096 + 8192;
1649   } else if (parallelMode() > 0) {
1650     specialOptions_ |= 4096;
1651   }
1652   int saveMoreSpecialOptions = moreSpecialOptions_;
1653   if (dynamic_cast< CbcTreeLocal * >(tree_))
1654     specialOptions_ |= 4096 + 8192;
1655 #ifdef COIN_HAS_CLP
1656   {
1657     OsiClpSolverInterface *clpSolver
1658       = dynamic_cast< OsiClpSolverInterface * >(solver_);
1659     if (clpSolver) {
1660       // pass in disaster handler
1661       CbcDisasterHandler handler(this);
1662       clpSolver->passInDisasterHandler(&handler);
1663       // Initialise solvers seed (unless users says not)
1664       if ((specialOptions_ & 4194304) == 0)
1665         clpSolver->getModelPtr()->setRandomSeed(1234567);
1666 #ifdef JJF_ZERO
1667       // reduce factorization frequency
1668       int frequency = clpSolver->getModelPtr()->factorizationFrequency();
1669       clpSolver->getModelPtr()->setFactorizationFrequency(CoinMin(frequency, 120));
1670 #endif
1671     }
1672   }
1673 #endif
1674   // original solver (only set if pre-processing)
1675   OsiSolverInterface *originalSolver = NULL;
1676   int numberOriginalObjects = numberObjects_;
1677   OsiObject **originalObject = NULL;
1678   // Save whether there were any objects
1679   bool noObjects = (numberObjects_ == 0);
1680   // Set up strategies
1681   /*
1682       See if the user has supplied a strategy object and deal with it if present.
1683       The call to setupOther will set numberStrong_ and numberBeforeTrust_, and
1684       perform integer preprocessing, if requested.
1685 
1686       We need to hang on to a pointer to solver_. setupOther will assign a
1687       preprocessed solver to model, but will instruct assignSolver not to trash the
1688       existing one.
1689     */
1690   if (strategy_) {
1691     // May do preprocessing
1692     originalSolver = solver_;
1693     strategy_->setupOther(*this);
1694     if (strategy_->preProcessState()) {
1695       // pre-processing done
1696       if (strategy_->preProcessState() < 0) {
1697         // infeasible (or unbounded)
1698         status_ = 0;
1699         if (!solver_->isProvenDualInfeasible()) {
1700           handler_->message(CBC_INFEAS, messages_) << CoinMessageEol;
1701           secondaryStatus_ = 1;
1702         } else {
1703           handler_->message(CBC_UNBOUNDED,
1704             messages_)
1705             << CoinMessageEol;
1706           secondaryStatus_ = 7;
1707         }
1708         originalContinuousObjective_ = COIN_DBL_MAX;
1709         if (flipObjective)
1710           flipModel();
1711         return;
1712       } else if (numberObjects_ && object_) {
1713         numberOriginalObjects = numberObjects_;
1714         // redo sequence
1715         numberIntegers_ = 0;
1716         int numberColumns = getNumCols();
1717         int nOrig = originalSolver->getNumCols();
1718         CglPreProcess *process = strategy_->process();
1719         assert(process);
1720         const int *originalColumns = process->originalColumns();
1721         // allow for cliques etc
1722         nOrig = CoinMax(nOrig, originalColumns[numberColumns - 1] + 1);
1723         // try and redo debugger
1724         OsiRowCutDebugger *debugger = const_cast< OsiRowCutDebugger * >(solver_->getRowCutDebuggerAlways());
1725         if (debugger) {
1726           if (numberColumns <= debugger->numberColumns())
1727             debugger->redoSolution(numberColumns, originalColumns);
1728           else
1729             debugger = NULL; // no idea how to handle (SOS?)
1730         }
1731         // User-provided solution might have been best. Synchronise.
1732         if (bestSolution_) {
1733           // need to redo - in case no better found in BAB
1734           // just get integer part right
1735           for (int i = 0; i < numberColumns; i++) {
1736             int jColumn = originalColumns[i];
1737             bestSolution_[i] = bestSolution_[jColumn];
1738           }
1739         }
1740         originalObject = object_;
1741         // object number or -1
1742         int *temp = new int[nOrig];
1743         int iColumn;
1744         for (iColumn = 0; iColumn < nOrig; iColumn++)
1745           temp[iColumn] = -1;
1746         int iObject;
1747         int nNonInt = 0;
1748         for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
1749           iColumn = originalObject[iObject]->columnNumber();
1750           if (iColumn < 0) {
1751             nNonInt++;
1752           } else {
1753             temp[iColumn] = iObject;
1754           }
1755         }
1756         int numberNewIntegers = 0;
1757         int numberOldIntegers = 0;
1758         int numberOldOther = 0;
1759         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1760           int jColumn = originalColumns[iColumn];
1761           if (temp[jColumn] >= 0) {
1762             int iObject = temp[jColumn];
1763             CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]);
1764             if (obj)
1765               numberOldIntegers++;
1766             else
1767               numberOldOther++;
1768           } else if (isInteger(iColumn)) {
1769             numberNewIntegers++;
1770           }
1771         }
1772         /*
1773                   Allocate an array to hold the indices of the integer variables.
1774                   Make a large enough array for all objects
1775                 */
1776         numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt;
1777         object_ = new OsiObject *[numberObjects_];
1778         delete[] integerVariable_;
1779         integerVariable_ = new int[numberNewIntegers + numberOldIntegers];
1780         /*
1781                   Walk the variables again, filling in the indices and creating objects for
1782                   the integer variables. Initially, the objects hold the index and upper &
1783                   lower bounds.
1784                 */
1785         numberIntegers_ = 0;
1786         int n = originalColumns[numberColumns - 1] + 1;
1787         int *backward = new int[n];
1788         int i;
1789         for (i = 0; i < n; i++)
1790           backward[i] = -1;
1791         for (i = 0; i < numberColumns; i++)
1792           backward[originalColumns[i]] = i;
1793         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1794           int jColumn = originalColumns[iColumn];
1795           if (temp[jColumn] >= 0) {
1796             int iObject = temp[jColumn];
1797             CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]);
1798             if (obj) {
1799               object_[numberIntegers_] = originalObject[iObject]->clone();
1800               // redo ids etc
1801               //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns);
1802               object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward);
1803               integerVariable_[numberIntegers_++] = iColumn;
1804             }
1805           } else if (isInteger(iColumn)) {
1806             object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn);
1807             integerVariable_[numberIntegers_++] = iColumn;
1808           }
1809         }
1810         delete[] backward;
1811         numberObjects_ = numberIntegers_;
1812         // Now append other column stuff
1813         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1814           int jColumn = originalColumns[iColumn];
1815           if (temp[jColumn] >= 0) {
1816             int iObject = temp[jColumn];
1817             CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]);
1818             if (!obj) {
1819               object_[numberObjects_] = originalObject[iObject]->clone();
1820               // redo ids etc
1821               CbcObject *obj = dynamic_cast< CbcObject * >(object_[numberObjects_]);
1822               assert(obj);
1823               obj->redoSequenceEtc(this, numberColumns, originalColumns);
1824               numberObjects_++;
1825             }
1826           }
1827         }
1828         // now append non column stuff
1829         for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
1830           iColumn = originalObject[iObject]->columnNumber();
1831           if (iColumn < 0) {
1832             // already has column numbers changed
1833             object_[numberObjects_] = originalObject[iObject]->clone();
1834 #ifdef JJF_ZERO
1835             // redo ids etc
1836             CbcObject *obj = dynamic_cast< CbcObject * >(object_[numberObjects_]);
1837             assert(obj);
1838             obj->redoSequenceEtc(this, numberColumns, originalColumns);
1839 #endif
1840             numberObjects_++;
1841           }
1842         }
1843         delete[] temp;
1844         if (!numberObjects_)
1845           handler_->message(CBC_NOINT, messages_) << CoinMessageEol;
1846       } else {
1847         int numberColumns = getNumCols();
1848         CglPreProcess *process = strategy_->process();
1849         assert(process);
1850         const int *originalColumns = process->originalColumns();
1851         // try and redo debugger
1852         OsiRowCutDebugger *debugger = const_cast< OsiRowCutDebugger * >(solver_->getRowCutDebuggerAlways());
1853         if (debugger)
1854           debugger->redoSolution(numberColumns, originalColumns);
1855       }
1856     } else {
1857       //no preprocessing
1858       originalSolver = NULL;
1859     }
1860     strategy_->setupCutGenerators(*this);
1861     strategy_->setupHeuristics(*this);
1862     // Set strategy print level to models
1863     strategy_->setupPrinting(*this, handler_->logLevel());
1864   }
1865   eventHappened_ = false;
1866   CbcEventHandler *eventHandler = getEventHandler();
1867   if (eventHandler)
1868     eventHandler->setModel(this);
1869 #define CLIQUE_ANALYSIS
1870 #ifdef CLIQUE_ANALYSIS
1871   // set up for probing
1872   // If we're doing clever stuff with cliques, additional info here.
1873   if (!parentModel_)
1874     probingInfo_ = new CglTreeProbingInfo(solver_);
1875   else
1876     probingInfo_ = NULL;
1877 #else
1878   probingInfo_ = NULL;
1879 #endif
1880 
1881   // Try for dominated columns
1882   if ((specialOptions_ & 64) != 0) {
1883     CglDuplicateRow dupcuts(solver_);
1884     dupcuts.setMode(2);
1885     CglStored *storedCuts = dupcuts.outDuplicates(solver_);
1886     if (storedCuts) {
1887       COIN_DETAIL_PRINT(printf("adding dup cuts\n"));
1888       addCutGenerator(storedCuts, 1, "StoredCuts from dominated",
1889         true, false, false, -200);
1890     }
1891   }
1892   if (!nodeCompare_)
1893     nodeCompare_ = new CbcCompareDefault();
1894   ;
1895   // See if hot start wanted
1896   CbcCompareBase *saveCompare = NULL;
1897   // User supplied hotstart. Adapt for preprocessing.
1898   if (hotstartSolution_) {
1899     if (strategy_ && strategy_->preProcessState() > 0) {
1900       CglPreProcess *process = strategy_->process();
1901       assert(process);
1902       int n = solver_->getNumCols();
1903       const int *originalColumns = process->originalColumns();
1904       // columns should be in order ... but
1905       double *tempS = new double[n];
1906       for (int i = 0; i < n; i++) {
1907         int iColumn = originalColumns[i];
1908         tempS[i] = hotstartSolution_[iColumn];
1909       }
1910       delete[] hotstartSolution_;
1911       hotstartSolution_ = tempS;
1912       if (hotstartPriorities_) {
1913         int *tempP = new int[n];
1914         for (int i = 0; i < n; i++) {
1915           int iColumn = originalColumns[i];
1916           tempP[i] = hotstartPriorities_[iColumn];
1917         }
1918         delete[] hotstartPriorities_;
1919         hotstartPriorities_ = tempP;
1920       }
1921     }
1922     saveCompare = nodeCompare_;
1923     // depth first
1924     nodeCompare_ = new CbcCompareDepth();
1925   }
1926   if (!problemFeasibility_)
1927     problemFeasibility_ = new CbcFeasibilityBase();
1928 #ifdef CBC_DEBUG
1929   std::string problemName;
1930   solver_->getStrParam(OsiProbName, problemName);
1931   printf("Problem name - %s\n", problemName.c_str());
1932   solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0);
1933 #endif
1934   /*
1935       Assume we're done, and see if we're proven wrong.
1936     */
1937   status_ = 0;
1938   secondaryStatus_ = 0;
1939   phase_ = 0;
1940   /*
1941       Scan the variables, noting the integer variables. Create an
1942       CbcSimpleInteger object for each integer variable.
1943     */
1944   findIntegers(false);
1945   // Say not dynamic pseudo costs
1946   ownership_ &= ~0x40000000;
1947   // If dynamic pseudo costs then do
1948   if (numberBeforeTrust_)
1949     convertToDynamic();
1950   // Set up char array to say if integer (speed)
1951   delete[] integerInfo_;
1952   {
1953     int n = solver_->getNumCols();
1954     integerInfo_ = new char[n];
1955     for (int i = 0; i < n; i++) {
1956       if (solver_->isInteger(i))
1957         integerInfo_[i] = 1;
1958       else
1959         integerInfo_[i] = 0;
1960     }
1961   }
1962   if (preferredWay_) {
1963     // set all unset ones
1964     for (int iObject = 0; iObject < numberObjects_; iObject++) {
1965       CbcObject *obj = dynamic_cast< CbcObject * >(object_[iObject]);
1966       if (obj && !obj->preferredWay())
1967         obj->setPreferredWay(preferredWay_);
1968     }
1969   }
1970   /*
1971       Ensure that objects on the lists of OsiObjects, heuristics, and cut
1972       generators attached to this model all refer to this model.
1973     */
1974   synchronizeModel();
1975   if (!solverCharacteristics_) {
1976     OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
1977     if (solverCharacteristics) {
1978       solverCharacteristics_ = solverCharacteristics;
1979     } else {
1980       // replace in solver
1981       OsiBabSolver defaultC;
1982       solver_->setAuxiliaryInfo(&defaultC);
1983       solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
1984     }
1985   }
1986 
1987   solverCharacteristics_->setSolver(solver_);
1988   // Set so we can tell we are in initial phase in resolve
1989   continuousObjective_ = -COIN_DBL_MAX;
1990   /*
1991       Solve the relaxation.
1992 
1993       Apparently there are circumstances where this will be non-trivial --- i.e.,
1994       we've done something since initialSolve that's trashed the solution to the
1995       continuous relaxation.
1996     */
1997   /* Tell solver we are in Branch and Cut
1998        Could use last parameter for subtle differences */
1999   solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL);
2000 #ifdef COIN_HAS_CLP
2001   {
2002     OsiClpSolverInterface *clpSolver
2003       = dynamic_cast< OsiClpSolverInterface * >(solver_);
2004     if (clpSolver) {
2005       if ( this->keepNamesPreproc == false )
2006         solver_->setIntParam( OsiNameDiscipline, 0 );
2007       ClpSimplex *clpSimplex = clpSolver->getModelPtr();
2008       if ((specialOptions_ & 32) == 0) {
2009         // take off names (unless going to be saving)
2010         int nameDisc; solver_->getIntParam( OsiNameDiscipline, nameDisc );
2011         if ( (numberAnalyzeIterations_ >= 0 || (-numberAnalyzeIterations_ & 64) == 0) && (!nameDisc) )
2012           clpSimplex->dropNames();
2013       }
2014       // no crunch if mostly continuous
2015       if ((clpSolver->specialOptions() & (1 + 8)) != (1 + 8)) {
2016         int numberColumns = solver_->getNumCols();
2017         if (numberColumns > 1000 && numberIntegers_ * 4 < numberColumns)
2018           clpSolver->setSpecialOptions(clpSolver->specialOptions() & (~1));
2019       }
2020       //#define NO_CRUNCH
2021 #ifdef NO_CRUNCH
2022       printf("TEMP switching off crunch\n");
2023       int iOpt = clpSolver->specialOptions();
2024       iOpt &= ~1;
2025       iOpt |= 65536;
2026       clpSolver->setSpecialOptions(iOpt);
2027 #endif
2028     }
2029   }
2030 #endif
2031   bool feasible;
2032   numberSolves_ = 0;
2033   {
2034     // check
2035     int numberOdd = 0;
2036     for (int i = 0; i < numberObjects_; i++) {
2037       CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
2038       if (!obj)
2039         numberOdd++;
2040     }
2041     if (numberOdd) {
2042       moreSpecialOptions_ |= 1073741824;
2043       // also switch off checking for restart (as preprocessing may be odd)
2044       specialOptions_ &= ~(512|32768);
2045     }
2046   }
2047   // If NLP then we assume already solved outside branchAndbound
2048   if (!solverCharacteristics_->solverType() || solverCharacteristics_->solverType() == 4) {
2049     feasible = resolve(NULL, 0) != 0;
2050   } else {
2051     // pick up given status
2052     feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached());
2053   }
2054   if (problemFeasibility_->feasible(this, 0) < 0) {
2055     feasible = false; // pretend infeasible
2056   }
2057   numberSavedSolutions_ = 0;
2058   int saveNumberStrong = numberStrong_;
2059   int saveNumberBeforeTrust = numberBeforeTrust_;
2060   /*
2061       If the linear relaxation of the root is infeasible, bail out now. Otherwise,
2062       continue with processing the root node.
2063     */
2064   if (!feasible) {
2065     status_ = 0;
2066     if (!solver_->isProvenDualInfeasible()) {
2067       handler_->message(CBC_INFEAS, messages_) << CoinMessageEol;
2068       secondaryStatus_ = 1;
2069     } else {
2070       handler_->message(CBC_UNBOUNDED, messages_) << CoinMessageEol;
2071       secondaryStatus_ = 7;
2072     }
2073     originalContinuousObjective_ = COIN_DBL_MAX;
2074     if (bestSolution_ && ((specialOptions_ & 8388608) == 0 || (specialOptions_ & 2048) != 0)) {
2075       // best solution found by various heuristics - set solution
2076       char general[200];
2077       sprintf(general, "Solution of %g already found by heuristic",
2078         bestObjective_);
2079       messageHandler()->message(CBC_GENERAL,
2080         messages())
2081         << general << CoinMessageEol;
2082       setCutoff(1.0e50); // As best solution should be worse than cutoff
2083       // change cutoff as constraint if wanted
2084       if (cutoffRowNumber_ >= 0) {
2085         if (solver_->getNumRows() > cutoffRowNumber_)
2086           solver_->setRowUpper(cutoffRowNumber_, 1.0e50);
2087       }
2088       // also in continuousSolver_
2089       if (continuousSolver_) {
2090         // Solvers know about direction
2091         double direction = solver_->getObjSense();
2092         continuousSolver_->setDblParam(OsiDualObjectiveLimit, 1.0e50 * direction);
2093       } else {
2094         continuousSolver_ = solver_->clone();
2095       }
2096       phase_ = 5;
2097       double increment = getDblParam(CbcModel::CbcCutoffIncrement);
2098       if ((specialOptions_ & 4) == 0)
2099         bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve
2100       setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1);
2101       continuousSolver_->resolve();
2102       if (!continuousSolver_->isProvenOptimal()) {
2103         continuousSolver_->messageHandler()->setLogLevel(2);
2104         continuousSolver_->initialSolve();
2105       }
2106       delete solver_;
2107       solverCharacteristics_ = NULL;
2108       solver_ = continuousSolver_;
2109       setPointers(solver_);
2110       continuousSolver_ = NULL;
2111     }
2112     solverCharacteristics_ = NULL;
2113     if (flipObjective)
2114       flipModel();
2115     return;
2116   } else if (!numberObjects_) {
2117     // nothing to do
2118     // Undo preprocessing performed during BaB.
2119     if (strategy_ && strategy_->preProcessState() > 0) {
2120       // undo preprocessing
2121       CglPreProcess *process = strategy_->process();
2122       assert(process);
2123       int n = originalSolver->getNumCols();
2124       if (bestSolution_) {
2125         delete[] bestSolution_;
2126         bestSolution_ = new double[n];
2127         process->postProcess(*solver_);
2128       }
2129       strategy_->deletePreProcess();
2130       // Solution now back in originalSolver
2131       delete solver_;
2132       solver_ = originalSolver;
2133       if (bestSolution_) {
2134         bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
2135         memcpy(bestSolution_, solver_->getColSolution(), n * sizeof(double));
2136       }
2137       // put back original objects if there were any
2138       if (originalObject) {
2139         int iColumn;
2140         assert(ownObjects_);
2141         for (iColumn = 0; iColumn < numberObjects_; iColumn++)
2142           delete object_[iColumn];
2143         delete[] object_;
2144         numberObjects_ = numberOriginalObjects;
2145         object_ = originalObject;
2146         delete[] integerVariable_;
2147         numberIntegers_ = 0;
2148         for (iColumn = 0; iColumn < n; iColumn++) {
2149           if (solver_->isInteger(iColumn))
2150             numberIntegers_++;
2151         }
2152         integerVariable_ = new int[numberIntegers_];
2153         numberIntegers_ = 0;
2154         for (iColumn = 0; iColumn < n; iColumn++) {
2155           if (solver_->isInteger(iColumn))
2156             integerVariable_[numberIntegers_++] = iColumn;
2157         }
2158       }
2159     }
2160     if (flipObjective)
2161       flipModel();
2162     solverCharacteristics_ = NULL;
2163     bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
2164     int numberColumns = solver_->getNumCols();
2165     delete[] bestSolution_;
2166     bestSolution_ = new double[numberColumns];
2167     CoinCopyN(solver_->getColSolution(), numberColumns, bestSolution_);
2168     return;
2169   }
2170   /*
2171       See if we're using the Osi side of the branching hierarchy. If so, either
2172       convert existing CbcObjects to OsiObjects, or generate them fresh. In the
2173       first case, CbcModel owns the objects on the object_ list. In the second
2174       case, the solver holds the objects and object_ simply points to the
2175       solver's list.
2176 
2177       080417 The conversion code here (the block protected by `if (obj)') cannot
2178       possibly be correct. On the Osi side, descent is OsiObject -> OsiObject2 ->
2179       all other Osi object classes. On the Cbc side, it's OsiObject -> CbcObject
2180       -> all other Cbc object classes. It's structurally impossible for any Osi
2181       object to descend from CbcObject. The only thing I can see is that this is
2182       really dead code, and object detection is now handled from the Osi side.
2183     */
2184   // Convert to Osi if wanted
2185   //OsiBranchingInformation * persistentInfo = NULL;
2186   if (branchingMethod_ && branchingMethod_->chooseMethod()) {
2187     //persistentInfo = new OsiBranchingInformation(solver_);
2188     if (numberOriginalObjects) {
2189       for (int iObject = 0; iObject < numberObjects_; iObject++) {
2190         CbcObject *obj = dynamic_cast< CbcObject * >(object_[iObject]);
2191         if (obj) {
2192           CbcSimpleInteger *obj2 = dynamic_cast< CbcSimpleInteger * >(obj);
2193           if (obj2) {
2194             // back to Osi land
2195             object_[iObject] = obj2->osiObject();
2196             delete obj;
2197           } else {
2198             OsiSimpleInteger *obj3 = dynamic_cast< OsiSimpleInteger * >(obj);
2199             if (!obj3) {
2200               OsiSOS *obj4 = dynamic_cast< OsiSOS * >(obj);
2201               if (!obj4) {
2202                 CbcSOS *obj5 = dynamic_cast< CbcSOS * >(obj);
2203                 if (obj5) {
2204                   // back to Osi land
2205                   object_[iObject] = obj5->osiObject(solver_);
2206                 } else {
2207                   printf("Code up CbcObject type in Osi land\n");
2208                   abort();
2209                 }
2210               }
2211             }
2212           }
2213         }
2214       }
2215       // and add to solver
2216       //if (!solver_->numberObjects()) {
2217       solver_->addObjects(numberObjects_, object_);
2218       //} else {
2219       //if (solver_->numberObjects()!=numberOriginalObjects) {
2220       //printf("should have trapped that solver has objects before\n");
2221       //abort();
2222       //}
2223       //}
2224     } else {
2225       /*
2226               As of 080104, findIntegersAndSOS is misleading --- the default OSI
2227               implementation finds only integers.
2228             */
2229       // do from solver
2230       deleteObjects(false);
2231       solver_->findIntegersAndSOS(false);
2232       numberObjects_ = solver_->numberObjects();
2233       object_ = solver_->objects();
2234       ownObjects_ = false;
2235     }
2236     branchingMethod_->chooseMethod()->setSolver(solver_);
2237   }
2238   // take off heuristics if have to (some do not work with SOS, for example)
2239   // object should know what's safe.
2240   {
2241     int numberOdd = 0;
2242     int numberSOS = 0;
2243     for (int i = 0; i < numberObjects_; i++) {
2244       if (!object_[i]->canDoHeuristics())
2245         numberOdd++;
2246       CbcSOS *obj = dynamic_cast< CbcSOS * >(object_[i]);
2247       if (obj)
2248         numberSOS++;
2249     }
2250     if (numberOdd) {
2251       if (numberHeuristics_ && (specialOptions_ & 1024) == 0) {
2252         int k = 0;
2253         for (int i = 0; i < numberHeuristics_; i++) {
2254           if (!heuristic_[i]->canDealWithOdd())
2255             delete heuristic_[i];
2256           else
2257             heuristic_[k++] = heuristic_[i];
2258         }
2259         if (!k) {
2260           delete[] heuristic_;
2261           heuristic_ = NULL;
2262         }
2263         numberHeuristics_ = k;
2264         handler_->message(CBC_HEURISTICS_OFF, messages_) << numberOdd << CoinMessageEol;
2265       }
2266       // If odd switch off AddIntegers
2267       specialOptions_ &= ~65536;
2268       // switch off fast nodes for now
2269       fastNodeDepth_ = -1;
2270       moreSpecialOptions_ &= ~33554432; // no diving
2271     } else if (numberSOS) {
2272       specialOptions_ |= 128; // say can do SOS in dynamic mode
2273       // switch off fast nodes for now
2274       fastNodeDepth_ = -1;
2275       moreSpecialOptions_ &= ~33554432; // no diving
2276     }
2277     if (numberThreads_ > 0) {
2278       /* switch off fast nodes for now
2279 	       Trouble is that by time mini bab finishes code is
2280 	       looking at a different node
2281 	     */
2282       fastNodeDepth_ = -1;
2283     }
2284   }
2285   // Save objective (just so user can access it)
2286   originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
2287   bestPossibleObjective_ = originalContinuousObjective_;
2288   sumChangeObjective1_ = 0.0;
2289   sumChangeObjective2_ = 0.0;
2290   /*
2291       OsiRowCutDebugger knows an optimal answer for a subset of MIP problems.
2292       Assuming it recognises the problem, when called upon it will check a cut to
2293       see if it cuts off the optimal answer.
2294     */
2295   // If debugger exists set specialOptions_ bit
2296   if (solver_->getRowCutDebuggerAlways()) {
2297     specialOptions_ |= 1;
2298   }
2299 
2300 #ifdef CBC_DEBUG
2301   if ((specialOptions_ & 1) == 0)
2302     solver_->activateRowCutDebugger(problemName.c_str());
2303   if (solver_->getRowCutDebuggerAlways())
2304     specialOptions_ |= 1;
2305 #endif
2306 
2307   /*
2308       Begin setup to process a feasible root node.
2309     */
2310   bestObjective_ = CoinMin(bestObjective_, 1.0e50);
2311   if (!bestSolution_) {
2312     numberSolutions_ = 0;
2313     numberHeuristicSolutions_ = 0;
2314   }
2315   stateOfSearch_ = 0;
2316   // Everything is minimization
2317   {
2318     // needed to sync cutoffs
2319     double value;
2320     solver_->getDblParam(OsiDualObjectiveLimit, value);
2321     dblParam_[CbcCurrentCutoff] = value * solver_->getObjSense();
2322   }
2323   double cutoff = getCutoff();
2324   double direction = solver_->getObjSense();
2325   dblParam_[CbcOptimizationDirection] = direction;
2326   if (cutoff < 1.0e20 && direction < 0.0)
2327     messageHandler()->message(CBC_CUTOFF_WARNING1,
2328       messages())
2329       << cutoff << -cutoff << CoinMessageEol;
2330   if (cutoff > bestObjective_)
2331     cutoff = bestObjective_;
2332   setCutoff(cutoff);
2333   /*
2334       We probably already have a current solution, but just in case ...
2335     */
2336   int numberColumns = getNumCols();
2337   if (!currentSolution_)
2338     currentSolution_ = new double[numberColumns];
2339   testSolution_ = currentSolution_;
2340   /*
2341       Create a copy of the solver, thus capturing the original (root node)
2342       constraint system (aka the continuous system).
2343     */
2344   delete continuousSolver_;
2345   continuousSolver_ = solver_->clone();
2346 #ifdef CONFLICT_CUTS
2347   if ((moreSpecialOptions_ & 4194304) != 0) {
2348 #ifdef COIN_HAS_CLP
2349     OsiClpSolverInterface *clpSolver
2350       = dynamic_cast< OsiClpSolverInterface * >(solver_);
2351     if (clpSolver) {
2352       int specialOptions = clpSolver->getModelPtr()->specialOptions();
2353       // 2097152 switches on rays in crunch
2354       if (!parentModel_)
2355         clpSolver->getModelPtr()->setSpecialOptions(specialOptions | 32 | 2097152);
2356       else
2357         clpSolver->getModelPtr()->setSpecialOptions(specialOptions & ~(32 | 2097152));
2358     }
2359   }
2360 #endif
2361 #endif
2362 #ifdef COIN_HAS_NTY
2363   // maybe allow on fix and restart later
2364   if ((moreSpecialOptions2_ & (128 | 256)) != 0 && !parentModel_) {
2365     symmetryInfo_ = new CbcSymmetry();
2366     symmetryInfo_->setupSymmetry(this);
2367     int numberGenerators = symmetryInfo_->statsOrbits(this, 0);
2368     if (!symmetryInfo_->numberUsefulOrbits() && (moreSpecialOptions2_ & (128 | 256)) != (128 | 256)) {
2369       delete symmetryInfo_;
2370       symmetryInfo_ = NULL;
2371       moreSpecialOptions2_ &= ~(128 | 256);
2372     }
2373     if ((moreSpecialOptions2_ & (128 | 256)) == (128 | 256)) {
2374       //moreSpecialOptions2_ &= ~256;
2375     }
2376   }
2377 #endif
2378 
2379   // add cutoff as constraint if wanted
2380   if (cutoffRowNumber_ == -2) {
2381     if (!parentModel_) {
2382       int numberColumns = solver_->getNumCols();
2383       double *obj = CoinCopyOfArray(solver_->getObjCoefficients(), numberColumns);
2384       int *indices = new int[numberColumns];
2385       int n = 0;
2386       for (int i = 0; i < numberColumns; i++) {
2387         if (obj[i]) {
2388           indices[n] = i;
2389           obj[n++] = obj[i];
2390         }
2391       }
2392       if (n) {
2393         double cutoff = getCutoff();
2394         // relax a little bit
2395         cutoff += 1.0e-4;
2396         double offset;
2397         solver_->getDblParam(OsiObjOffset, offset);
2398         cutoffRowNumber_ = solver_->getNumRows();
2399         solver_->addRow(n, indices, obj, -COIN_DBL_MAX, CoinMin(cutoff, 1.0e25) + offset);
2400       } else {
2401         // no objective!
2402         cutoffRowNumber_ = -1;
2403       }
2404       delete[] indices;
2405       delete[] obj;
2406     } else {
2407       // switch off
2408       cutoffRowNumber_ = -1;
2409     }
2410   }
2411   numberRowsAtContinuous_ = getNumRows();
2412   solver_->saveBaseModel();
2413   /*
2414       Check the objective to see if we can deduce a nontrivial increment. If
2415       it's better than the current value for CbcCutoffIncrement, it'll be
2416       installed.
2417     */
2418   if (solverCharacteristics_->reducedCostsAccurate())
2419     analyzeObjective();
2420   {
2421     // may be able to change cutoff now
2422     double cutoff = getCutoff();
2423     double increment = getDblParam(CbcModel::CbcCutoffIncrement);
2424     if (cutoff > bestObjective_ - increment) {
2425       cutoff = bestObjective_ - increment;
2426       setCutoff(cutoff);
2427     }
2428   }
2429 #ifdef COIN_HAS_CLP
2430   // Possible save of pivot method
2431   ClpDualRowPivot *savePivotMethod = NULL;
2432   {
2433     // pass tolerance and increment to solver
2434     OsiClpSolverInterface *clpSolver
2435       = dynamic_cast< OsiClpSolverInterface * >(solver_);
2436     if (clpSolver)
2437       clpSolver->setStuff(getIntegerTolerance(), getCutoffIncrement());
2438 #ifdef CLP_RESOLVE
2439     if ((moreSpecialOptions_ & 1048576) != 0 && !parentModel_ && clpSolver) {
2440       resolveClp(clpSolver, 0);
2441     }
2442 #endif
2443   }
2444 #endif
2445   /*
2446       Set up for cut generation. addedCuts_ holds the cuts which are relevant for
2447       the active subproblem. whichGenerator will be used to record the generator
2448       that produced a given cut.
2449     */
2450 #define INITIAL_MAXIMUM_WHICH 1000
2451   maximumWhich_ = INITIAL_MAXIMUM_WHICH;
2452   delete[] whichGenerator_;
2453   whichGenerator_ = new int[maximumWhich_];
2454   memset(whichGenerator_, 0, maximumWhich_ * sizeof(int));
2455   maximumNumberCuts_ = 0;
2456   currentNumberCuts_ = 0;
2457   delete[] addedCuts_;
2458   addedCuts_ = NULL;
2459   OsiObject **saveObjects = NULL;
2460   maximumRows_ = numberRowsAtContinuous_;
2461   currentDepth_ = 0;
2462   workingBasis_.resize(maximumRows_, numberColumns);
2463   /*
2464       Set up an empty heap and associated data structures to hold the live set
2465       (problems which require further exploration).
2466     */
2467   CbcCompareDefault *compareActual
2468     = dynamic_cast< CbcCompareDefault * >(nodeCompare_);
2469   if (compareActual) {
2470     compareActual->setBestPossible(direction * solver_->getObjValue());
2471     compareActual->setCutoff(getCutoff());
2472 #ifdef JJF_ZERO
2473     if (false && !numberThreads_ && !parentModel_) {
2474       printf("CbcTreeArray ? threads ? parentArray\n");
2475       // Setup new style tree
2476       delete tree_;
2477       tree_ = new CbcTreeArray();
2478     }
2479 #endif
2480   }
2481   tree_->setComparison(*nodeCompare_);
2482   /*
2483       Used to record the path from a node to the root of the search tree, so that
2484       we can then traverse from the root to the node when restoring a subproblem.
2485     */
2486   maximumDepth_ = 10;
2487   delete[] walkback_;
2488   walkback_ = new CbcNodeInfo *[maximumDepth_];
2489   lastDepth_ = 0;
2490   delete[] lastNodeInfo_;
2491   lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_];
2492   delete[] lastNumberCuts_;
2493   lastNumberCuts_ = new int[maximumDepth_];
2494   maximumCuts_ = 100;
2495   lastNumberCuts2_ = 0;
2496   delete[] lastCut_;
2497   lastCut_ = new const OsiRowCut *[maximumCuts_];
2498   /*
2499       Used to generate bound edits for CbcPartialNodeInfo.
2500     */
2501   double *lowerBefore = new double[numberColumns];
2502   double *upperBefore = new double[numberColumns];
2503   /*
2504     Set up to run heuristics and generate cuts at the root node. The heavy
2505     lifting is hidden inside the calls to doHeuristicsAtRoot and solveWithCuts.
2506 
2507     To start, tell cut generators they can be a bit more aggressive at the
2508     root node.
2509 
2510     QUESTION: phase_ = 0 is documented as `initial solve', phase = 1 as `solve
2511         with cuts at root'. Is phase_ = 1 the correct indication when
2512         doHeurisiticsAtRoot is called to run heuristics outside of the main
2513         cut / heurisitc / reoptimise loop in solveWithCuts?
2514 
2515       Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
2516       lifting. It will iterate a generate/reoptimise loop (including reduced cost
2517       fixing) until no cuts are generated, the change in objective falls off,  or
2518       the limit on the number of rounds of cut generation is exceeded.
2519 
2520       At the end of all this, any cuts will be recorded in cuts and also
2521       installed in the solver's constraint system. We'll have reoptimised, and
2522       removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
2523       adjusted accordingly).
2524 
2525       Tell cut generators they can be a bit more aggressive at root node
2526 
2527       TODO: Why don't we make a copy of the solution after solveWithCuts?
2528       TODO: If numberUnsatisfied == 0, don't we have a solution?
2529     */
2530   phase_ = 1;
2531   int iCutGenerator;
2532   for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
2533     // If parallel switch off global cuts
2534     if (numberThreads_) {
2535       generator_[iCutGenerator]->setGlobalCuts(false);
2536       generator_[iCutGenerator]->setGlobalCutsAtRoot(false);
2537     }
2538     CglCutGenerator *generator = generator_[iCutGenerator]->generator();
2539     generator->setAggressiveness(generator->getAggressiveness() + 100);
2540     if (!generator->canDoGlobalCuts())
2541       generator->setGlobalCuts(false);
2542   }
2543   OsiCuts cuts;
2544   int anyAction = -1;
2545   numberOldActiveCuts_ = 0;
2546   numberNewCuts_ = 0;
2547   // Array to mark solution
2548   delete[] usedInSolution_;
2549   usedInSolution_ = new int[numberColumns];
2550   CoinZeroN(usedInSolution_, numberColumns);
2551   /*
2552       For printing totals and for CbcNode (numberNodes_)
2553     */
2554   numberIterations_ = 0;
2555   numberNodes_ = 0;
2556   numberNodes2_ = 0;
2557   maximumStatistics_ = 0;
2558   maximumDepthActual_ = 0;
2559   numberDJFixed_ = 0.0;
2560   if (!parentModel_) {
2561     if ((specialOptions_ & 262144) != 0) {
2562       // create empty stored cuts
2563       //storedRowCuts_ = new CglStored(solver_->getNumCols());
2564     } else if ((specialOptions_ & 524288) != 0 && storedRowCuts_) {
2565       // tighten and set best solution
2566       // A) tight bounds on integer variables
2567       /*
2568                 storedRowCuts_ are coming in from outside, probably for nonlinear.
2569               John was unsure about origin.
2570             */
2571       const double *lower = solver_->getColLower();
2572       const double *upper = solver_->getColUpper();
2573       const double *tightLower = storedRowCuts_->tightLower();
2574       const double *tightUpper = storedRowCuts_->tightUpper();
2575       int nTightened = 0;
2576       for (int i = 0; i < numberIntegers_; i++) {
2577         int iColumn = integerVariable_[i];
2578         if (tightLower[iColumn] > lower[iColumn]) {
2579           nTightened++;
2580           solver_->setColLower(iColumn, tightLower[iColumn]);
2581         }
2582         if (tightUpper[iColumn] < upper[iColumn]) {
2583           nTightened++;
2584           solver_->setColUpper(iColumn, tightUpper[iColumn]);
2585         }
2586       }
2587       if (nTightened)
2588         COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened));
2589       if (storedRowCuts_->bestObjective() < bestObjective_) {
2590         // B) best solution
2591         double objValue = storedRowCuts_->bestObjective();
2592         setBestSolution(CBC_SOLUTION, objValue,
2593           storedRowCuts_->bestSolution());
2594         // Do heuristics
2595         // Allow RINS
2596         for (int i = 0; i < numberHeuristics_; i++) {
2597           CbcHeuristicRINS *rins
2598             = dynamic_cast< CbcHeuristicRINS * >(heuristic_[i]);
2599           if (rins) {
2600             rins->setLastNode(-100);
2601           }
2602         }
2603       }
2604     }
2605   }
2606 #ifdef SWITCH_VARIABLES
2607   // see if any switching variables
2608   if (numberIntegers_ < solver_->getNumCols())
2609     findSwitching();
2610 #endif
2611   /*
2612       Run heuristics at the root. This is the only opportunity to run FPump; it
2613       will be removed from the heuristics list by doHeuristicsAtRoot.
2614     */
2615   // See if multiple runs wanted
2616   CbcModel **rootModels = NULL;
2617   if (!parentModel_ && multipleRootTries_ % 100) {
2618     double rootTimeCpu = CoinCpuTime();
2619     double startTimeRoot = CoinGetTimeOfDay();
2620     int numberRootThreads = 1;
2621     /* undocumented fine tuning
2622 	 aabbcc where cc is number of tries
2623 	 bb if nonzero is number of threads
2624 	 aa if nonzero just do heuristics
2625       */
2626     int numberModels = multipleRootTries_ % 100;
2627 #ifdef CBC_THREAD
2628     numberRootThreads = (multipleRootTries_ / 100) % 100;
2629     if (!numberRootThreads) {
2630       if (numberThreads_ < 2)
2631         numberRootThreads = numberModels;
2632       else
2633         numberRootThreads = CoinMin(numberThreads_, numberModels);
2634     }
2635 #endif
2636     int otherOptions = (multipleRootTries_ / 10000) % 100;
2637     rootModels = new CbcModel *[numberModels];
2638     int newSeed = randomSeed_;
2639     if (newSeed == 0) {
2640       double time = fabs(CoinGetTimeOfDay());
2641       while (time >= COIN_INT_MAX)
2642         time *= 0.5;
2643       newSeed = static_cast< unsigned int >(time);
2644     } else if (newSeed < 0) {
2645       newSeed = 123456789;
2646 #ifdef COIN_HAS_CLP
2647       OsiClpSolverInterface *clpSolver
2648         = dynamic_cast< OsiClpSolverInterface * >(solver_);
2649       if (clpSolver) {
2650         newSeed += clpSolver->getModelPtr()->randomNumberGenerator()->getSeed();
2651       }
2652 #endif
2653     }
2654     CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart());
2655     for (int i = 0; i < numberModels; i++) {
2656       rootModels[i] = new CbcModel(*this);
2657       rootModels[i]->setNumberThreads(0);
2658       rootModels[i]->setMaximumNodes(otherOptions ? -1 : 0);
2659       rootModels[i]->setRandomSeed(newSeed + 10000000 * i);
2660       rootModels[i]->randomNumberGenerator()->setSeed(newSeed + 50000000 * i);
2661       rootModels[i]->setMultipleRootTries(0);
2662 #ifdef COIN_HAS_NTY
2663       rootModels[i]->zapSymmetry();
2664       rootModels[i]->moreSpecialOptions2_ &= ~(128 | 256); // off nauty
2665 #endif
2666       // use seed
2667       rootModels[i]->setSpecialOptions(specialOptions_ | (4194304 | 8388608));
2668       rootModels[i]->setMoreSpecialOptions(moreSpecialOptions_ & (~(134217728 | 4194304)));
2669       rootModels[i]->setMoreSpecialOptions2(moreSpecialOptions2_ & (~(128 | 256)));
2670       rootModels[i]->solver_->setWarmStart(basis);
2671 #ifdef COIN_HAS_CLP
2672       OsiClpSolverInterface *clpSolver
2673         = dynamic_cast< OsiClpSolverInterface * >(rootModels[i]->solver_);
2674 #define NEW_RANDOM_BASIS
2675 #ifdef NEW_RANDOM_BASIS
2676       if (i == 0)
2677         continue;
2678 #endif
2679       if (clpSolver) {
2680         ClpSimplex *simplex = clpSolver->getModelPtr();
2681         if (defaultHandler_)
2682           simplex->setDefaultMessageHandler();
2683         simplex->setRandomSeed(newSeed + 20000000 * i);
2684         simplex->allSlackBasis();
2685         int logLevel = simplex->logLevel();
2686         if (logLevel == 1)
2687           simplex->setLogLevel(0);
2688         if (i != 0) {
2689 #ifdef NEW_RANDOM_BASIS
2690           int numberRows = simplex->numberRows();
2691           int throwOut = 20; //2+numberRows/100;
2692           for (int iThrow = 0; iThrow < throwOut; iThrow++) {
2693             double random = simplex->randomNumberGenerator()->randomDouble();
2694             int iStart = static_cast< int >(random * numberRows);
2695             for (int j = iStart; j < numberRows; j++) {
2696               if (simplex->getRowStatus(j) != ClpSimplex::basic) {
2697                 simplex->setRowStatus(j, ClpSimplex::basic);
2698                 break;
2699               }
2700             }
2701           }
2702           clpSolver->setWarmStart(NULL);
2703 #else
2704             double random = simplex->randomNumberGenerator()->randomDouble();
2705             int bias = static_cast< int >(random * (numberIterations / 4));
2706             simplex->setMaximumIterations(numberIterations / 2 + bias);
2707             simplex->primal();
2708             simplex->setMaximumIterations(COIN_INT_MAX);
2709             simplex->dual();
2710 #endif
2711         } else {
2712 #ifndef NEW_RANDOM_BASIS
2713           simplex->primal();
2714 #endif
2715 #endif
2716         }
2717 #ifdef NEW_RANDOM_BASIS
2718         simplex->setLogLevel(logLevel);
2719         clpSolver->setWarmStart(NULL);
2720 #endif
2721       }
2722       for (int j = 0; j < numberHeuristics_; j++)
2723         rootModels[i]->heuristic_[j]->setSeed(rootModels[i]->heuristic_[j]->getSeed() + 100000000 * i);
2724       for (int j = 0; j < numberCutGenerators_; j++)
2725         rootModels[i]->generator_[j]->generator()->refreshSolver(rootModels[i]->solver_);
2726     }
2727     delete basis;
2728 #ifdef CBC_THREAD
2729     if (numberRootThreads == 1) {
2730 #endif
2731       for (int iModel = 0; iModel < numberModels; iModel++) {
2732         doRootCbcThread(rootModels[iModel]);
2733         // see if solved at root node
2734         if (rootModels[iModel]->getMaximumNodes()) {
2735           feasible = false;
2736           break;
2737         }
2738       }
2739 #ifdef CBC_THREAD
2740     } else {
2741       Coin_pthread_t *threadId = new Coin_pthread_t[numberRootThreads];
2742       for (int kModel = 0; kModel < numberModels; kModel += numberRootThreads) {
2743         bool finished = false;
2744         for (int iModel = kModel; iModel < CoinMin(numberModels, kModel + numberRootThreads); iModel++) {
2745           pthread_create(&(threadId[iModel - kModel].thr), NULL,
2746             doRootCbcThread,
2747             rootModels[iModel]);
2748         }
2749         // wait
2750         for (int iModel = kModel; iModel < CoinMin(numberModels, kModel + numberRootThreads); iModel++) {
2751           pthread_join(threadId[iModel - kModel].thr, NULL);
2752         }
2753         // see if solved at root node
2754         for (int iModel = kModel; iModel < CoinMin(numberModels, kModel + numberRootThreads); iModel++) {
2755           if (rootModels[iModel]->getMaximumNodes())
2756             finished = true;
2757         }
2758         if (finished) {
2759           feasible = false;
2760           break;
2761         }
2762       }
2763       delete[] threadId;
2764     }
2765 #endif
2766     // sort solutions
2767     int *which = new int[numberModels];
2768     double *value = new double[numberModels];
2769     int numberSolutions = 0;
2770     for (int iModel = 0; iModel < numberModels; iModel++) {
2771       if (rootModels[iModel]->bestSolution()) {
2772         which[numberSolutions] = iModel;
2773         value[numberSolutions++] = -rootModels[iModel]->getMinimizationObjValue();
2774       }
2775     }
2776     char general[100];
2777     rootTimeCpu = CoinCpuTime() - rootTimeCpu;
2778     if (numberRootThreads == 1)
2779       sprintf(general, "Multiple root solvers took a total of %.2f seconds\n",
2780         rootTimeCpu);
2781     else
2782       sprintf(general, "Multiple root solvers took a total of %.2f seconds (%.2f elapsed)\n",
2783         rootTimeCpu, CoinGetTimeOfDay() - startTimeRoot);
2784     messageHandler()->message(CBC_GENERAL,
2785       messages())
2786       << general << CoinMessageEol;
2787     CoinSort_2(value, value + numberSolutions, which);
2788     // to get name
2789     CbcHeuristicRINS dummyHeuristic;
2790     dummyHeuristic.setHeuristicName("Multiple root solvers");
2791     lastHeuristic_ = &dummyHeuristic;
2792     for (int i = 0; i < numberSolutions; i++) {
2793       double objValue = -value[i];
2794       if (objValue < getCutoff()) {
2795         int iModel = which[i];
2796         setBestSolution(CBC_ROUNDING, objValue,
2797           rootModels[iModel]->bestSolution());
2798       }
2799     }
2800     lastHeuristic_ = NULL;
2801     delete[] which;
2802     delete[] value;
2803   }
2804   // Do heuristics
2805   if (numberObjects_ && !rootModels)
2806     doHeuristicsAtRoot();
2807   if (solverCharacteristics_->solutionAddsCuts()) {
2808     // With some heuristics solver needs a resolve here
2809     solver_->resolve();
2810     if (!isProvenOptimal()) {
2811       solver_->initialSolve();
2812     }
2813   }
2814   /*
2815       Grepping through the code, it would appear that this is a command line
2816       debugging hook.  There's no obvious place in the code where this is set to
2817       a negative value.
2818 
2819       User hook, says John.
2820     */
2821   if (intParam_[CbcMaxNumNode] < 0
2822     || numberSolutions_ >= getMaximumSolutions())
2823     eventHappened_ = true; // stop as fast as possible
2824   stoppedOnGap_ = false;
2825   // See if can stop on gap
2826   bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
2827   if (canStopOnGap()) {
2828     if (bestPossibleObjective_ < getCutoff())
2829       stoppedOnGap_ = true;
2830     feasible = false;
2831     //eventHappened_=true; // stop as fast as possible
2832   }
2833   /*
2834       Set up for statistics collection, if requested. Standard values are
2835       documented in CbcModel.hpp. The magic number 100 will trigger a dump of
2836       CbcSimpleIntegerDynamicPseudoCost objects (no others). Looks like another
2837       command line debugging hook.
2838     */
2839   statistics_ = NULL;
2840   // Do on switch
2841   if (doStatistics > 0 && doStatistics <= 100) {
2842     maximumStatistics_ = 10000;
2843     statistics_ = new CbcStatistics *[maximumStatistics_];
2844     memset(statistics_, 0, maximumStatistics_ * sizeof(CbcStatistics *));
2845   }
2846   // See if we can add integers
2847   if (noObjects && numberIntegers_ < solver_->getNumCols() && (specialOptions_ & 65536) != 0 && !parentModel_ && false) {
2848     int numberIntegers1 = 0;
2849     int numberColumns = solver_->getNumCols();
2850     for (int i = 0; i < numberColumns; i++) {
2851       if (solver_->isInteger(i))
2852         numberIntegers1++;
2853     }
2854     AddIntegers();
2855     // make sure in sync
2856     int numberIntegers2 = 0;
2857     for (int i = 0; i < numberColumns; i++) {
2858       if (solver_->isInteger(i))
2859         numberIntegers2++;
2860     }
2861     if (numberIntegers1 < numberIntegers2) {
2862       findIntegers(true, 2);
2863       convertToDynamic();
2864     }
2865   }
2866 
2867   /*
2868       Do an initial round of cut generation for the root node. Depending on the
2869       type of underlying solver, we may want to do this even if the initial query
2870       to the objects indicates they're satisfied.
2871 
2872       solveWithCuts does the heavy lifting. It will iterate a generate/reoptimise
2873       loop (including reduced cost fixing) until no cuts are generated, the
2874       change in objective falls off,  or the limit on the number of rounds of cut
2875       generation is exceeded.
2876 
2877       At the end of all this, any cuts will be recorded in cuts and also
2878       installed in the solver's constraint system. We'll have reoptimised, and
2879       removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
2880       adjusted accordingly).
2881     */
2882   int iObject;
2883   int numberUnsatisfied = 0;
2884   delete[] currentSolution_;
2885   currentSolution_ = new double[numberColumns];
2886   testSolution_ = currentSolution_;
2887   memcpy(currentSolution_, solver_->getColSolution(),
2888     numberColumns * sizeof(double));
2889   // point to useful information
2890   OsiBranchingInformation usefulInfo = usefulInformation();
2891 
2892   for (iObject = 0; iObject < numberObjects_; iObject++) {
2893     double infeasibility = object_[iObject]->checkInfeasibility(&usefulInfo);
2894     if (infeasibility)
2895       numberUnsatisfied++;
2896   }
2897   // replace solverType
2898   double *tightBounds = NULL;
2899   if (solverCharacteristics_->tryCuts()) {
2900 
2901     if (numberUnsatisfied) {
2902       // User event
2903       if (!eventHappened_ && feasible) {
2904         if (rootModels) {
2905           // for fixings
2906           int numberColumns = solver_->getNumCols();
2907           tightBounds = new double[2 * numberColumns];
2908           {
2909             const double *lower = solver_->getColLower();
2910             const double *upper = solver_->getColUpper();
2911             for (int i = 0; i < numberColumns; i++) {
2912               tightBounds[2 * i + 0] = lower[i];
2913               tightBounds[2 * i + 1] = upper[i];
2914             }
2915           }
2916           int numberModels = multipleRootTries_ % 100;
2917           const OsiSolverInterface **solvers = new const OsiSolverInterface *[numberModels];
2918           int numberRows = continuousSolver_->getNumRows();
2919           int maxCuts = 0;
2920           for (int i = 0; i < numberModels; i++) {
2921             solvers[i] = rootModels[i]->solver();
2922             const double *lower = solvers[i]->getColLower();
2923             const double *upper = solvers[i]->getColUpper();
2924             for (int j = 0; j < numberColumns; j++) {
2925               tightBounds[2 * j + 0] = CoinMax(lower[j], tightBounds[2 * j + 0]);
2926               tightBounds[2 * j + 1] = CoinMin(upper[j], tightBounds[2 * j + 1]);
2927             }
2928             int numberRows2 = solvers[i]->getNumRows();
2929             assert(numberRows2 >= numberRows);
2930             maxCuts += numberRows2 - numberRows;
2931             // accumulate statistics
2932             for (int j = 0; j < numberCutGenerators_; j++) {
2933               generator_[j]->addStatistics(rootModels[i]->cutGenerator(j));
2934             }
2935           }
2936           for (int j = 0; j < numberCutGenerators_; j++) {
2937             generator_[j]->scaleBackStatistics(numberModels);
2938           }
2939           //CbcRowCuts rowCut(maxCuts);
2940           const OsiRowCutDebugger *debugger = NULL;
2941           if ((specialOptions_ & 1) != 0)
2942             debugger = solver_->getRowCutDebugger();
2943           for (int iModel = 0; iModel < numberModels; iModel++) {
2944             int numberRows2 = solvers[iModel]->getNumRows();
2945             const CoinPackedMatrix *rowCopy = solvers[iModel]->getMatrixByRow();
2946             const int *rowLength = rowCopy->getVectorLengths();
2947             const double *elements = rowCopy->getElements();
2948             const int *column = rowCopy->getIndices();
2949             const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
2950             const double *rowLower = solvers[iModel]->getRowLower();
2951             const double *rowUpper = solvers[iModel]->getRowUpper();
2952             for (int iRow = numberRows; iRow < numberRows2; iRow++) {
2953               OsiRowCut rc;
2954               rc.setLb(rowLower[iRow]);
2955               rc.setUb(rowUpper[iRow]);
2956               CoinBigIndex start = rowStart[iRow];
2957               rc.setRow(rowLength[iRow], column + start, elements + start, false);
2958               if (debugger)
2959                 CoinAssert(!debugger->invalidCut(rc));
2960               globalCuts_.addCutIfNotDuplicate(rc);
2961             }
2962             //int cutsAdded=globalCuts_.numberCuts()-numberCuts;
2963             //numberCuts += cutsAdded;
2964             //printf("Model %d gave %d cuts (out of %d possible)\n",
2965             //	   iModel,cutsAdded,numberRows2-numberRows);
2966           }
2967           // normally replace global cuts
2968           //if (!globalCuts_.())
2969           //globalCuts_=rowCutrowCut.addCuts(globalCuts_);
2970           //rowCut.addCuts(globalCuts_);
2971           int nTightened = 0;
2972           assert(feasible);
2973           {
2974             double tolerance = 1.0e-5;
2975             const double *lower = solver_->getColLower();
2976             const double *upper = solver_->getColUpper();
2977             for (int i = 0; i < numberColumns; i++) {
2978               if (tightBounds[2 * i + 0] > tightBounds[2 * i + 1] + 1.0e-9) {
2979                 feasible = false;
2980                 char general[200];
2981                 sprintf(general, "Solvers give infeasible bounds on %d %g,%g was %g,%g - search finished\n",
2982                   i, tightBounds[2 * i + 0], tightBounds[2 * i + 1], lower[i], upper[i]);
2983                 messageHandler()->message(CBC_GENERAL, messages())
2984                   << general << CoinMessageEol;
2985                 break;
2986               }
2987               double oldLower = lower[i];
2988               double oldUpper = upper[i];
2989               if (tightBounds[2 * i + 0] > oldLower + tolerance) {
2990                 nTightened++;
2991                 solver_->setColLower(i, tightBounds[2 * i + 0]);
2992               }
2993               if (tightBounds[2 * i + 1] < oldUpper - tolerance) {
2994                 nTightened++;
2995                 solver_->setColUpper(i, tightBounds[2 * i + 1]);
2996               }
2997             }
2998           }
2999           delete[] tightBounds;
3000           tightBounds = NULL;
3001           char printBuffer[200];
3002           sprintf(printBuffer, "%d solvers added %d different cuts out of pool of %d",
3003             numberModels, globalCuts_.sizeRowCuts(), maxCuts);
3004           messageHandler()->message(CBC_GENERAL, messages())
3005             << printBuffer << CoinMessageEol;
3006           if (nTightened) {
3007             sprintf(printBuffer, "%d bounds were tightened",
3008               nTightened);
3009             messageHandler()->message(CBC_GENERAL, messages())
3010               << printBuffer << CoinMessageEol;
3011           }
3012           delete[] solvers;
3013         }
3014         if (!parentModel_ && (moreSpecialOptions_ & 67108864) != 0) {
3015           // load cuts from file
3016           FILE *fp = fopen("global.cuts", "rb");
3017           if (fp) {
3018             size_t nRead;
3019             int numberColumns = solver_->getNumCols();
3020             int numCols;
3021             nRead = fread(&numCols, sizeof(int), 1, fp);
3022             if (nRead != 1)
3023               throw("Error in fread");
3024             if (numberColumns != numCols) {
3025               printf("Mismatch on columns %d %d\n", numberColumns, numCols);
3026               fclose(fp);
3027             } else {
3028               // If rootModel just do some
3029               double threshold = -1.0;
3030               if (!multipleRootTries_)
3031                 threshold = 0.5;
3032               int initialCuts = 0;
3033               int initialGlobal = globalCuts_.sizeRowCuts();
3034               double *elements = new double[numberColumns + 2];
3035               int *indices = new int[numberColumns];
3036               int numberEntries = 1;
3037               while (numberEntries > 0) {
3038                 nRead = fread(&numberEntries, sizeof(int), 1, fp);
3039                 if (nRead != 1)
3040                   throw("Error in fread");
3041                 double randomNumber = randomNumberGenerator_.randomDouble();
3042                 if (numberEntries > 0) {
3043                   initialCuts++;
3044                   nRead = fread(elements, sizeof(double), numberEntries + 2, fp);
3045                   if (nRead != static_cast< size_t >(numberEntries + 2))
3046                     throw("Error in fread");
3047                   nRead = fread(indices, sizeof(int), numberEntries, fp);
3048                   if (nRead != static_cast< size_t >(numberEntries))
3049                     throw("Error in fread");
3050                   if (randomNumber > threshold) {
3051                     OsiRowCut rc;
3052                     rc.setLb(elements[numberEntries]);
3053                     rc.setUb(elements[numberEntries + 1]);
3054                     rc.setRow(numberEntries, indices, elements,
3055                       false);
3056                     rc.setGloballyValidAsInteger(2);
3057                     globalCuts_.addCutIfNotDuplicate(rc);
3058                   }
3059                 }
3060               }
3061               fclose(fp);
3062               // fixes
3063               int nTightened = 0;
3064               fp = fopen("global.fix", "rb");
3065               if (fp) {
3066                 nRead = fread(indices, sizeof(int), 2, fp);
3067                 if (nRead != 2)
3068                   throw("Error in fread");
3069                 if (numberColumns != indices[0]) {
3070                   printf("Mismatch on columns %d %d\n", numberColumns,
3071                     indices[0]);
3072                 } else {
3073                   indices[0] = 1;
3074                   while (indices[0] >= 0) {
3075                     nRead = fread(indices, sizeof(int), 2, fp);
3076                     if (nRead != 2)
3077                       throw("Error in fread");
3078                     int iColumn = indices[0];
3079                     if (iColumn >= 0) {
3080                       nTightened++;
3081                       nRead = fread(elements, sizeof(double), 4, fp);
3082                       if (nRead != 4)
3083                         throw("Error in fread");
3084                       solver_->setColLower(iColumn, elements[0]);
3085                       solver_->setColUpper(iColumn, elements[1]);
3086                     }
3087                   }
3088                 }
3089               }
3090               if (fp)
3091                 fclose(fp);
3092               char printBuffer[200];
3093               sprintf(printBuffer, "%d cuts read in of which %d were unique, %d bounds tightened",
3094                 initialCuts,
3095                 globalCuts_.sizeRowCuts() - initialGlobal, nTightened);
3096               messageHandler()->message(CBC_GENERAL, messages())
3097                 << printBuffer << CoinMessageEol;
3098               delete[] elements;
3099               delete[] indices;
3100             }
3101           }
3102         }
3103         if (feasible)
3104           feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
3105             NULL);
3106         if (multipleRootTries_ && (moreSpecialOptions_ & 134217728) != 0) {
3107           FILE *fp = NULL;
3108           size_t nRead;
3109           int numberColumns = solver_->getNumCols();
3110           int initialCuts = 0;
3111           if ((moreSpecialOptions_ & 134217728) != 0) {
3112             // append so go down to end
3113             fp = fopen("global.cuts", "r+b");
3114             if (fp) {
3115               int numCols;
3116               nRead = fread(&numCols, sizeof(int), 1, fp);
3117               if (nRead != 1)
3118                 throw("Error in fread");
3119               if (numberColumns != numCols) {
3120                 printf("Mismatch on columns %d %d\n", numberColumns, numCols);
3121                 fclose(fp);
3122                 fp = NULL;
3123               }
3124             }
3125           }
3126           double *elements = new double[numberColumns + 2];
3127           int *indices = new int[numberColumns];
3128           if (fp) {
3129             int numberEntries = 1;
3130             while (numberEntries > 0) {
3131               fpos_t position;
3132               fgetpos(fp, &position);
3133               nRead = fread(&numberEntries, sizeof(int), 1, fp);
3134               if (nRead != 1)
3135                 throw("Error in fread");
3136               if (numberEntries > 0) {
3137                 initialCuts++;
3138                 nRead = fread(elements, sizeof(double), numberEntries + 2, fp);
3139                 if (nRead != static_cast< size_t >(numberEntries + 2))
3140                   throw("Error in fread");
3141                 nRead = fread(indices, sizeof(int), numberEntries, fp);
3142                 if (nRead != static_cast< size_t >(numberEntries))
3143                   throw("Error in fread");
3144               } else {
3145                 // end
3146                 fsetpos(fp, &position);
3147               }
3148             }
3149           } else {
3150             fp = fopen("global.cuts", "wb");
3151             size_t nWrite;
3152             nWrite = fwrite(&numberColumns, sizeof(int), 1, fp);
3153             if (nWrite != 1)
3154               throw("Error in fwrite");
3155           }
3156           size_t nWrite;
3157           // now append binding cuts
3158           int numberC = continuousSolver_->getNumRows();
3159           int numberRows = solver_->getNumRows();
3160           printf("Saving %d cuts (up from %d)\n",
3161             initialCuts + numberRows - numberC, initialCuts);
3162           const double *rowLower = solver_->getRowLower();
3163           const double *rowUpper = solver_->getRowUpper();
3164           // Row copy
3165           CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow());
3166           const double *elementByRow = matrixByRow.getElements();
3167           const int *column = matrixByRow.getIndices();
3168           const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
3169           const int *rowLength = matrixByRow.getVectorLengths();
3170           for (int iRow = numberC; iRow < numberRows; iRow++) {
3171             int n = rowLength[iRow];
3172             assert(n);
3173             CoinBigIndex start = rowStart[iRow];
3174             memcpy(elements, elementByRow + start, n * sizeof(double));
3175             memcpy(indices, column + start, n * sizeof(int));
3176             elements[n] = rowLower[iRow];
3177             elements[n + 1] = rowUpper[iRow];
3178             nWrite = fwrite(&n, sizeof(int), 1, fp);
3179             if (nWrite != 1)
3180               throw("Error in fwrite");
3181             nWrite = fwrite(elements, sizeof(double), n + 2, fp);
3182             if (nWrite != static_cast< size_t >(n + 2))
3183               throw("Error in fwrite");
3184             nWrite = fwrite(indices, sizeof(int), n, fp);
3185             if (nWrite != static_cast< size_t >(n))
3186               throw("Error in fwrite");
3187           }
3188           // eof marker
3189           int eofMarker = -1;
3190           nWrite = fwrite(&eofMarker, sizeof(int), 1, fp);
3191           if (nWrite != 1)
3192             throw("Error in fwrite");
3193           fclose(fp);
3194           // do tighter bounds (? later extra to original columns)
3195           int nTightened = 0;
3196           const double *lower = solver_->getColLower();
3197           const double *upper = solver_->getColUpper();
3198           const double *originalLower = continuousSolver_->getColLower();
3199           const double *originalUpper = continuousSolver_->getColUpper();
3200           double tolerance = 1.0e-5;
3201           for (int i = 0; i < numberColumns; i++) {
3202             if (lower[i] > originalLower[i] + tolerance) {
3203               nTightened++;
3204             }
3205             if (upper[i] < originalUpper[i] - tolerance) {
3206               nTightened++;
3207             }
3208           }
3209           if (nTightened) {
3210             fp = fopen("global.fix", "wb");
3211             size_t nWrite;
3212             indices[0] = numberColumns;
3213             if (originalColumns_)
3214               indices[1] = COIN_INT_MAX;
3215             else
3216               indices[1] = -1;
3217             nWrite = fwrite(indices, sizeof(int), 2, fp);
3218             if (nWrite != 2)
3219               throw("Error in fwrite");
3220             for (int i = 0; i < numberColumns; i++) {
3221               int nTightened = 0;
3222               if (lower[i] > originalLower[i] + tolerance) {
3223                 nTightened++;
3224               }
3225               if (upper[i] < originalUpper[i] - tolerance) {
3226                 nTightened++;
3227               }
3228               if (nTightened) {
3229                 indices[0] = i;
3230                 if (originalColumns_)
3231                   indices[1] = originalColumns_[i];
3232                 elements[0] = lower[i];
3233                 elements[1] = upper[i];
3234                 elements[2] = originalLower[i];
3235                 elements[3] = originalUpper[i];
3236                 nWrite = fwrite(indices, sizeof(int), 2, fp);
3237                 if (nWrite != 2)
3238                   throw("Error in fwrite");
3239                 nWrite = fwrite(elements, sizeof(double), 4, fp);
3240                 if (nWrite != 4)
3241                   throw("Error in fwrite");
3242               }
3243             }
3244             // eof marker
3245             indices[0] = -1;
3246             nWrite = fwrite(indices, sizeof(int), 2, fp);
3247             if (nWrite != 2)
3248               throw("Error in fwrite");
3249             fclose(fp);
3250           }
3251           delete[] elements;
3252           delete[] indices;
3253         }
3254         if ((specialOptions_ & 524288) != 0 && !parentModel_
3255           && storedRowCuts_) {
3256           if (feasible) {
3257             /* pick up stuff and try again
3258                         add cuts, maybe keep around
3259                         do best solution and if so new heuristics
3260                         obviously tighten bounds
3261                         */
3262             // A and B probably done on entry
3263             // A) tight bounds on integer variables
3264             const double *lower = solver_->getColLower();
3265             const double *upper = solver_->getColUpper();
3266             const double *tightLower = storedRowCuts_->tightLower();
3267             const double *tightUpper = storedRowCuts_->tightUpper();
3268             int nTightened = 0;
3269             for (int i = 0; i < numberIntegers_; i++) {
3270               int iColumn = integerVariable_[i];
3271               if (tightLower[iColumn] > lower[iColumn]) {
3272                 nTightened++;
3273                 solver_->setColLower(iColumn, tightLower[iColumn]);
3274               }
3275               if (tightUpper[iColumn] < upper[iColumn]) {
3276                 nTightened++;
3277                 solver_->setColUpper(iColumn, tightUpper[iColumn]);
3278               }
3279             }
3280             if (nTightened)
3281               COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened));
3282             if (storedRowCuts_->bestObjective() < bestObjective_) {
3283               // B) best solution
3284               double objValue = storedRowCuts_->bestObjective();
3285               setBestSolution(CBC_SOLUTION, objValue,
3286                 storedRowCuts_->bestSolution());
3287               // Do heuristics
3288               // Allow RINS
3289               for (int i = 0; i < numberHeuristics_; i++) {
3290                 CbcHeuristicRINS *rins
3291                   = dynamic_cast< CbcHeuristicRINS * >(heuristic_[i]);
3292                 if (rins) {
3293                   rins->setLastNode(-100);
3294                 }
3295               }
3296               doHeuristicsAtRoot();
3297             }
3298 #ifdef JJF_ZERO
3299             int nCuts = storedRowCuts_->sizeRowCuts();
3300             // add to global list
3301             for (int i = 0; i < nCuts; i++) {
3302               OsiRowCut newCut(*storedRowCuts_->rowCutPointer(i));
3303               newCut.setGloballyValidAsInteger(2);
3304               newCut.mutableRow().setTestForDuplicateIndex(false);
3305               globalCuts_.insert(newCut);
3306             }
3307 #else
3308           addCutGenerator(storedRowCuts_, -99, "Stored from previous run",
3309             true, false, false, -200);
3310 #endif
3311             // Set cuts as active
3312             delete[] addedCuts_;
3313             maximumNumberCuts_ = cuts.sizeRowCuts();
3314             if (maximumNumberCuts_) {
3315               addedCuts_ = new CbcCountRowCut *[maximumNumberCuts_];
3316             } else {
3317               addedCuts_ = NULL;
3318             }
3319             for (int i = 0; i < maximumNumberCuts_; i++)
3320               addedCuts_[i] = new CbcCountRowCut(*cuts.rowCutPtr(i),
3321                 NULL, -1, -1, 2);
3322             COIN_DETAIL_PRINT(printf("size %d\n", cuts.sizeRowCuts()));
3323             cuts = OsiCuts();
3324             currentNumberCuts_ = maximumNumberCuts_;
3325             feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
3326               NULL);
3327             for (int i = 0; i < maximumNumberCuts_; i++)
3328               delete addedCuts_[i];
3329           }
3330           delete storedRowCuts_;
3331           storedRowCuts_ = NULL;
3332         }
3333       } else {
3334         feasible = false;
3335       }
3336     } else if (solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->alwaysTryCutsAtRootNode()) {
3337       // may generate cuts and turn the solution
3338       //to an infeasible one
3339       feasible = solveWithCuts(cuts, 2,
3340         NULL);
3341     }
3342   }
3343   if (rootModels) {
3344     int numberModels = multipleRootTries_ % 100;
3345     for (int i = 0; i < numberModels; i++)
3346       delete rootModels[i];
3347     delete[] rootModels;
3348   }
3349   // check extra info on feasibility
3350   if (!solverCharacteristics_->mipFeasible())
3351     feasible = false;
3352   // If max nodes==0 - don't do strong branching
3353   if (!getMaximumNodes()) {
3354     if (feasible)
3355       feasible = false;
3356     else
3357       setMaximumNodes(1); //allow to stop on success
3358   }
3359   topOfTree_ = NULL;
3360 #ifdef CLP_RESOLVE
3361   if ((moreSpecialOptions_ & 2097152) != 0 && !parentModel_ && feasible) {
3362     OsiClpSolverInterface *clpSolver
3363       = dynamic_cast< OsiClpSolverInterface * >(solver_);
3364     if (clpSolver)
3365       resolveClp(clpSolver, 0);
3366   }
3367 #endif
3368   // make cut generators less aggressive
3369   for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
3370     CglCutGenerator *generator = generator_[iCutGenerator]->generator();
3371     generator->setAggressiveness(generator->getAggressiveness() - 100);
3372   }
3373   currentNumberCuts_ = numberNewCuts_;
3374   if (solverCharacteristics_->solutionAddsCuts()) {
3375     // With some heuristics solver needs a resolve here (don't know if this is bug in heuristics)
3376     solver_->resolve();
3377     if (!isProvenOptimal()) {
3378       solver_->initialSolve();
3379     }
3380   }
3381   // See if can stop on gap
3382   bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense();
3383   if (canStopOnGap()) {
3384     if (bestPossibleObjective_ < getCutoff())
3385       stoppedOnGap_ = true;
3386     feasible = false;
3387   }
3388   // User event
3389   if (eventHappened_)
3390     feasible = false;
3391 #if defined(COIN_HAS_CLP) && defined(COIN_HAS_CPX)
3392   /*
3393       This is the notion of using Cbc stuff to get going, then calling cplex to
3394       finish off.
3395     */
3396   if (feasible && (specialOptions_ & 16384) != 0 && fastNodeDepth_ == -2 && !parentModel_) {
3397     // Use Cplex to do search!
3398     double time1 = CoinCpuTime();
3399     OsiClpSolverInterface *clpSolver
3400       = dynamic_cast< OsiClpSolverInterface * >(solver_);
3401     OsiCpxSolverInterface cpxSolver;
3402     double direction = clpSolver->getObjSense();
3403     cpxSolver.setObjSense(direction);
3404     // load up cplex
3405     const CoinPackedMatrix *matrix = continuousSolver_->getMatrixByCol();
3406     const double *rowLower = continuousSolver_->getRowLower();
3407     const double *rowUpper = continuousSolver_->getRowUpper();
3408     const double *columnLower = continuousSolver_->getColLower();
3409     const double *columnUpper = continuousSolver_->getColUpper();
3410     const double *objective = continuousSolver_->getObjCoefficients();
3411     cpxSolver.loadProblem(*matrix, columnLower, columnUpper,
3412       objective, rowLower, rowUpper);
3413     double *setSol = new double[numberIntegers_];
3414     int *setVar = new int[numberIntegers_];
3415     // cplex doesn't know about objective offset
3416     double offset = clpSolver->getModelPtr()->objectiveOffset();
3417     for (int i = 0; i < numberIntegers_; i++) {
3418       int iColumn = integerVariable_[i];
3419       cpxSolver.setInteger(iColumn);
3420       if (bestSolution_) {
3421         setSol[i] = bestSolution_[iColumn];
3422         setVar[i] = iColumn;
3423       }
3424     }
3425     CPXENVptr env = cpxSolver.getEnvironmentPtr();
3426     CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
3427     cpxSolver.switchToMIP();
3428     if (bestSolution_) {
3429 #if 0
3430             CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol);
3431 #else
3432         int zero = 0;
3433         CPXaddmipstarts(env, lpPtr, 1, numberIntegers_, &zero, setVar, setSol, NULL, NULL);
3434 #endif
3435     }
3436     if (clpSolver->getNumRows() > continuousSolver_->getNumRows() && false) {
3437       // add cuts
3438       const CoinPackedMatrix *matrix = clpSolver->getMatrixByRow();
3439       const double *rhs = clpSolver->getRightHandSide();
3440       const char *rowSense = clpSolver->getRowSense();
3441       const double *elementByRow = matrix->getElements();
3442       const int *column = matrix->getIndices();
3443       const CoinBigIndex *rowStart = matrix->getVectorStarts();
3444       const int *rowLength = matrix->getVectorLengths();
3445       int nStart = continuousSolver_->getNumRows();
3446       int nRows = clpSolver->getNumRows();
3447       int size = rowStart[nRows - 1] + rowLength[nRows - 1] - rowStart[nStart];
3448       int nAdd = 0;
3449       double *rmatval = new double[size];
3450       int *rmatind = new int[size];
3451       int *rmatbeg = new int[nRows - nStart + 1];
3452       size = 0;
3453       rmatbeg[0] = 0;
3454       for (int i = nStart; i < nRows; i++) {
3455         for (int k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) {
3456           rmatind[size] = column[k];
3457           rmatval[size++] = elementByRow[k];
3458         }
3459         nAdd++;
3460         rmatbeg[nAdd] = size;
3461       }
3462       CPXaddlazyconstraints(env, lpPtr, nAdd, size,
3463         rhs, rowSense, rmatbeg,
3464         rmatind, rmatval, NULL);
3465       CPXsetintparam(env, CPX_PARAM_REDUCE,
3466         // CPX_PREREDUCE_NOPRIMALORDUAL (0)
3467         CPX_PREREDUCE_PRIMALONLY);
3468     }
3469     if (getCutoff() < 1.0e50) {
3470       double useCutoff = getCutoff() + offset;
3471       if (bestObjective_ < 1.0e50)
3472         useCutoff = bestObjective_ + offset + 1.0e-7;
3473       cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff * direction);
3474       if (direction > 0.0)
3475         CPXsetdblparam(env, CPX_PARAM_CUTUP, useCutoff); // min
3476       else
3477         CPXsetdblparam(env, CPX_PARAM_CUTLO, useCutoff); // max
3478     }
3479     CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]);
3480     delete[] setSol;
3481     delete[] setVar;
3482     char printBuffer[200];
3483     if (offset) {
3484       sprintf(printBuffer, "Add %g to all Cplex messages for true objective",
3485         -offset);
3486       messageHandler()->message(CBC_GENERAL, messages())
3487         << printBuffer << CoinMessageEol;
3488       cpxSolver.setDblParam(OsiObjOffset, offset);
3489     }
3490     cpxSolver.branchAndBound();
3491     double timeTaken = CoinCpuTime() - time1;
3492     sprintf(printBuffer, "Cplex took %g seconds",
3493       timeTaken);
3494     messageHandler()->message(CBC_GENERAL, messages())
3495       << printBuffer << CoinMessageEol;
3496     numberExtraNodes_ = CPXgetnodecnt(env, lpPtr);
3497     numberExtraIterations_ = CPXgetmipitcnt(env, lpPtr);
3498     double value = cpxSolver.getObjValue() * direction;
3499     if (cpxSolver.isProvenOptimal() && value <= getCutoff()) {
3500       feasible = true;
3501       clpSolver->setWarmStart(NULL);
3502       // try and do solution
3503       double *newSolution = CoinCopyOfArray(cpxSolver.getColSolution(),
3504         getNumCols());
3505       setBestSolution(CBC_STRONGSOL, value, newSolution);
3506       delete[] newSolution;
3507     }
3508     feasible = false;
3509   }
3510 #endif
3511   if (!parentModel_ && (moreSpecialOptions_ & 268435456) != 0) {
3512     // try idiotic idea
3513     CbcObject *obj = new CbcIdiotBranch(this);
3514     obj->setPriority(1); // temp
3515     addObjects(1, &obj);
3516     delete obj;
3517   }
3518 
3519   /*
3520       A hook to use clp to quickly explore some part of the tree.
3521     */
3522   if (fastNodeDepth_ == 1000 && /*!parentModel_*/ (specialOptions_ & 2048) == 0) {
3523     fastNodeDepth_ = -1;
3524     CbcObject *obj = new CbcFollowOn(this);
3525     obj->setPriority(1);
3526     addObjects(1, &obj);
3527     delete obj;
3528   }
3529   int saveNumberSolves = numberSolves_;
3530   int saveNumberIterations = numberIterations_;
3531   if ((fastNodeDepth_ >= 0 || (moreSpecialOptions_ & 33554432) != 0)
3532     && /*!parentModel_*/ (specialOptions_ & 2048) == 0) {
3533     // add in a general depth object doClp
3534     int type = (fastNodeDepth_ <= 100) ? fastNodeDepth_ : -(fastNodeDepth_ - 100);
3535     if ((moreSpecialOptions_ & 33554432) != 0)
3536       type = 12;
3537     else
3538       fastNodeDepth_ += 1000000; // mark as done
3539     CbcObject *obj = new CbcGeneralDepth(this, type);
3540     addObjects(1, &obj);
3541     delete obj;
3542     // fake number of objects
3543     numberObjects_--;
3544     if (parallelMode() < -1) {
3545       // But make sure position is correct
3546       OsiObject *obj2 = object_[numberObjects_];
3547       obj = dynamic_cast< CbcObject * >(obj2);
3548       assert(obj);
3549       obj->setPosition(numberObjects_);
3550     }
3551   }
3552 #ifdef COIN_HAS_CLP
3553 #ifdef NO_CRUNCH
3554   if (true) {
3555     OsiClpSolverInterface *clpSolver
3556       = dynamic_cast< OsiClpSolverInterface * >(solver_);
3557     if (clpSolver && !parentModel_) {
3558       ClpSimplex *clpSimplex = clpSolver->getModelPtr();
3559       clpSimplex->setSpecialOptions(clpSimplex->specialOptions() | 131072);
3560       //clpSimplex->startPermanentArrays();
3561       clpSimplex->setPersistenceFlag(2);
3562     }
3563   }
3564 #endif
3565 #endif
3566   // Save copy of solver
3567   OsiSolverInterface *saveSolver = NULL;
3568   if (!parentModel_ && (specialOptions_ & (512 + 32768)) != 0)
3569     saveSolver = solver_->clone();
3570   double checkCutoffForRestart = 1.0e100;
3571   saveModel(saveSolver, &checkCutoffForRestart, &feasible);
3572   if ((specialOptions_ & 262144) != 0 && !parentModel_) {
3573     // Save stuff and return!
3574     storedRowCuts_->saveStuff(bestObjective_, bestSolution_,
3575       solver_->getColLower(),
3576       solver_->getColUpper());
3577     delete[] lowerBefore;
3578     delete[] upperBefore;
3579     delete saveSolver;
3580     if (flipObjective)
3581       flipModel();
3582     return;
3583   }
3584   /*
3585       We've taken the continuous relaxation as far as we can. Time to branch.
3586       The first order of business is to actually create a node. chooseBranch
3587       currently uses strong branching to evaluate branch object candidates,
3588       unless forced back to simple branching. If chooseBranch concludes that a
3589       branching candidate is monotone (anyAction == -1) or infeasible (anyAction
3590       == -2) when forced to integer values, it returns here immediately.
3591 
3592       Monotone variables trigger a call to resolve(). If the problem remains
3593       feasible, try again to choose a branching variable. At the end of the loop,
3594       resolved == true indicates that some variables were fixed.
3595 
3596       Loss of feasibility will result in the deletion of newNode.
3597     */
3598 
3599   bool resolved = false;
3600   CbcNode *newNode = NULL;
3601   numberFixedAtRoot_ = 0;
3602   numberFixedNow_ = 0;
3603   if (!parentModel_ && (moreSpecialOptions2_ & 2) != 0) {
3604 #ifdef COIN_HAS_CLP
3605     OsiClpSolverInterface *clpSolver
3606       = dynamic_cast< OsiClpSolverInterface * >(solver_);
3607     if (clpSolver) {
3608       if (getCutoff() > 1.0e20) {
3609         printf("Zapping costs\n");
3610         int numberColumns = solver_->getNumCols();
3611         double *zeroCost = new double[numberColumns];
3612         // could make small random
3613         memset(zeroCost, 0, numberColumns * sizeof(double));
3614         solver_->setObjective(zeroCost);
3615         double objValue = solver_->getObjValue();
3616         solver_->setDblParam(OsiObjOffset, -objValue);
3617         clpSolver->getModelPtr()->setObjectiveValue(objValue);
3618         delete[] zeroCost;
3619       } else {
3620         moreSpecialOptions2_ &= ~2;
3621       }
3622     } else {
3623 #endif
3624       moreSpecialOptions2_ &= ~2;
3625 #ifdef COIN_HAS_CLP
3626     }
3627 #endif
3628   }
3629   int numberIterationsAtContinuous = numberIterations_;
3630   //solverCharacteristics_->setSolver(solver_);
3631   if (feasible) {
3632     // mark all cuts as globally valid
3633     int numberCuts = cuts.sizeRowCuts();
3634     resizeWhichGenerator(0, numberCuts);
3635     for (int i = 0; i < numberCuts; i++) {
3636       cuts.rowCutPtr(i)->setGloballyValid();
3637       whichGenerator_[i] = 20000 + (whichGenerator_[i] % 10000);
3638     }
3639 #define HOTSTART -1
3640 #if HOTSTART < 0
3641     if (bestSolution_ && !parentModel_ && !hotstartSolution_ && (moreSpecialOptions_ & 1024) != 0 && (specialOptions_ & 2048) == 0) {
3642       // Set priorities so only branch on ones we need to
3643       // use djs and see if only few branches needed
3644 #ifndef NDEBUG
3645       double integerTolerance = getIntegerTolerance();
3646 #endif
3647       bool possible = true;
3648       const double *saveLower = continuousSolver_->getColLower();
3649       const double *saveUpper = continuousSolver_->getColUpper();
3650       for (int i = 0; i < numberObjects_; i++) {
3651         const CbcSimpleInteger *thisOne = dynamic_cast< const CbcSimpleInteger * >(object_[i]);
3652         if (thisOne) {
3653           int iColumn = thisOne->columnNumber();
3654           if (saveUpper[iColumn] > saveLower[iColumn] + 1.5) {
3655             possible = false;
3656             break;
3657           }
3658         } else {
3659           possible = false;
3660           break;
3661         }
3662       }
3663       if (possible) {
3664         OsiSolverInterface *solver = continuousSolver_->clone();
3665         int numberColumns = solver->getNumCols();
3666         for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
3667           double value = bestSolution_[iColumn];
3668           value = CoinMax(value, saveLower[iColumn]);
3669           value = CoinMin(value, saveUpper[iColumn]);
3670           value = floor(value + 0.5);
3671           if (solver->isInteger(iColumn)) {
3672             solver->setColLower(iColumn, value);
3673             solver->setColUpper(iColumn, value);
3674           }
3675         }
3676         solver->setHintParam(OsiDoDualInResolve, false, OsiHintTry);
3677         // objlim and all slack
3678         double direction = solver->getObjSense();
3679         solver->setDblParam(OsiDualObjectiveLimit, 1.0e50 * direction);
3680         CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver->getEmptyWarmStart());
3681         solver->setWarmStart(basis);
3682         delete basis;
3683         bool changed = true;
3684         hotstartPriorities_ = new int[numberColumns];
3685         for (int iColumn = 0; iColumn < numberColumns; iColumn++)
3686           hotstartPriorities_[iColumn] = 1;
3687         while (changed) {
3688           changed = false;
3689           solver->resolve();
3690           if (!solver->isProvenOptimal()) {
3691             possible = false;
3692             break;
3693           }
3694           const double *dj = solver->getReducedCost();
3695           const double *colLower = solver->getColLower();
3696           const double *colUpper = solver->getColUpper();
3697           const double *solution = solver->getColSolution();
3698           int nAtLbNatural = 0;
3699           int nAtUbNatural = 0;
3700           int nZeroDj = 0;
3701           int nForced = 0;
3702           for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
3703             double value = solution[iColumn];
3704             value = CoinMax(value, saveLower[iColumn]);
3705             value = CoinMin(value, saveUpper[iColumn]);
3706             if (solver->isInteger(iColumn)) {
3707               assert(fabs(value - solution[iColumn]) <= integerTolerance);
3708               if (hotstartPriorities_[iColumn] == 1) {
3709                 if (dj[iColumn] < -1.0e-6) {
3710                   // negative dj
3711                   if (saveUpper[iColumn] == colUpper[iColumn]) {
3712                     nAtUbNatural++;
3713                     hotstartPriorities_[iColumn] = 2;
3714                     solver->setColLower(iColumn, saveLower[iColumn]);
3715                     solver->setColUpper(iColumn, saveUpper[iColumn]);
3716                   } else {
3717                     nForced++;
3718                   }
3719                 } else if (dj[iColumn] > 1.0e-6) {
3720                   // positive dj
3721                   if (saveLower[iColumn] == colLower[iColumn]) {
3722                     nAtLbNatural++;
3723                     hotstartPriorities_[iColumn] = 2;
3724                     solver->setColLower(iColumn, saveLower[iColumn]);
3725                     solver->setColUpper(iColumn, saveUpper[iColumn]);
3726                   } else {
3727                     nForced++;
3728                   }
3729                 } else {
3730                   // zero dj
3731                   nZeroDj++;
3732                 }
3733               }
3734             }
3735           }
3736 #if CBC_USEFUL_PRINTING > 1
3737           printf("%d forced, %d naturally at lower, %d at upper - %d zero dj\n",
3738             nForced, nAtLbNatural, nAtUbNatural, nZeroDj);
3739 #endif
3740           if (nAtLbNatural || nAtUbNatural) {
3741             changed = true;
3742           } else {
3743             if (nForced + nZeroDj > 5000 || (nForced + nZeroDj) * 2 > numberIntegers_)
3744               possible = false;
3745           }
3746         }
3747         delete solver;
3748       }
3749       if (possible) {
3750         setHotstartSolution(bestSolution_);
3751         if (!saveCompare) {
3752           // create depth first comparison
3753           saveCompare = nodeCompare_;
3754           // depth first
3755           nodeCompare_ = new CbcCompareDepth();
3756           tree_->setComparison(*nodeCompare_);
3757         }
3758       } else {
3759         delete[] hotstartPriorities_;
3760         hotstartPriorities_ = NULL;
3761       }
3762     }
3763 #endif
3764 #if HOTSTART > 0
3765     if (hotstartSolution_ && !hotstartPriorities_) {
3766       // Set up hot start
3767       OsiSolverInterface *solver = solver_->clone();
3768       double direction = solver_->getObjSense();
3769       int numberColumns = solver->getNumCols();
3770       double *saveLower = CoinCopyOfArray(solver->getColLower(), numberColumns);
3771       double *saveUpper = CoinCopyOfArray(solver->getColUpper(), numberColumns);
3772       // move solution
3773       solver->setColSolution(hotstartSolution_);
3774       // point to useful information
3775       const double *saveSolution = testSolution_;
3776       testSolution_ = solver->getColSolution();
3777       OsiBranchingInformation usefulInfo = usefulInformation();
3778       testSolution_ = saveSolution;
3779       /*
3780             Run through the objects and use feasibleRegion() to set variable bounds
3781             so as to fix the variables specified in the objects at their value in this
3782             solution. Since the object list contains (at least) one object for every
3783             integer variable, this has the effect of fixing all integer variables.
3784             */
3785       for (int i = 0; i < numberObjects_; i++)
3786         object_[i]->feasibleRegion(solver, &usefulInfo);
3787       solver->resolve();
3788       assert(solver->isProvenOptimal());
3789       double gap = CoinMax((solver->getObjValue() - solver_->getObjValue()) * direction, 0.0);
3790       const double *dj = solver->getReducedCost();
3791       const double *colLower = solver->getColLower();
3792       const double *colUpper = solver->getColUpper();
3793       const double *solution = solver->getColSolution();
3794       int nAtLbNatural = 0;
3795       int nAtUbNatural = 0;
3796       int nAtLbNaturalZero = 0;
3797       int nAtUbNaturalZero = 0;
3798       int nAtLbFixed = 0;
3799       int nAtUbFixed = 0;
3800       int nAtOther = 0;
3801       int nAtOtherNatural = 0;
3802       int nNotNeeded = 0;
3803       delete[] hotstartSolution_;
3804       hotstartSolution_ = new double[numberColumns];
3805       delete[] hotstartPriorities_;
3806       hotstartPriorities_ = new int[numberColumns];
3807       int *order = (int *)saveUpper;
3808       int nFix = 0;
3809       double bestRatio = COIN_DBL_MAX;
3810       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
3811         double value = solution[iColumn];
3812         value = CoinMax(value, saveLower[iColumn]);
3813         value = CoinMin(value, saveUpper[iColumn]);
3814         double sortValue = COIN_DBL_MAX;
3815         if (solver->isInteger(iColumn)) {
3816           assert(fabs(value - solution[iColumn]) <= 1.0e-5);
3817           double value2 = floor(value + 0.5);
3818           if (dj[iColumn] < -1.0e-6) {
3819             // negative dj
3820             //assert (value2==colUpper[iColumn]);
3821             if (saveUpper[iColumn] == colUpper[iColumn]) {
3822               nAtUbNatural++;
3823               sortValue = 0.0;
3824               double value = -dj[iColumn];
3825               if (value > gap)
3826                 nFix++;
3827               else if (gap < value * bestRatio)
3828                 bestRatio = gap / value;
3829               if (saveLower[iColumn] != colLower[iColumn]) {
3830                 nNotNeeded++;
3831                 sortValue = 1.0e20;
3832               }
3833             } else if (saveLower[iColumn] == colUpper[iColumn]) {
3834               nAtLbFixed++;
3835               sortValue = dj[iColumn];
3836             } else {
3837               nAtOther++;
3838               sortValue = 0.0;
3839               if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) {
3840                 nNotNeeded++;
3841                 sortValue = 1.0e20;
3842               }
3843             }
3844           } else if (dj[iColumn] > 1.0e-6) {
3845             // positive dj
3846             //assert (value2==colLower[iColumn]);
3847             if (saveLower[iColumn] == colLower[iColumn]) {
3848               nAtLbNatural++;
3849               sortValue = 0.0;
3850               double value = dj[iColumn];
3851               if (value > gap)
3852                 nFix++;
3853               else if (gap < value * bestRatio)
3854                 bestRatio = gap / value;
3855               if (saveUpper[iColumn] != colUpper[iColumn]) {
3856                 nNotNeeded++;
3857                 sortValue = 1.0e20;
3858               }
3859             } else if (saveUpper[iColumn] == colLower[iColumn]) {
3860               nAtUbFixed++;
3861               sortValue = -dj[iColumn];
3862             } else {
3863               nAtOther++;
3864               sortValue = 0.0;
3865               if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) {
3866                 nNotNeeded++;
3867                 sortValue = 1.0e20;
3868               }
3869             }
3870           } else {
3871             // zero dj
3872             if (value2 == saveUpper[iColumn]) {
3873               nAtUbNaturalZero++;
3874               sortValue = 0.0;
3875               if (saveLower[iColumn] != colLower[iColumn]) {
3876                 nNotNeeded++;
3877                 sortValue = 1.0e20;
3878               }
3879             } else if (value2 == saveLower[iColumn]) {
3880               nAtLbNaturalZero++;
3881               sortValue = 0.0;
3882             } else {
3883               nAtOtherNatural++;
3884               sortValue = 0.0;
3885               if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) {
3886                 nNotNeeded++;
3887                 sortValue = 1.0e20;
3888               }
3889             }
3890           }
3891 #if HOTSTART == 3
3892           sortValue = -fabs(dj[iColumn]);
3893 #endif
3894         }
3895         hotstartSolution_[iColumn] = value;
3896         saveLower[iColumn] = sortValue;
3897         order[iColumn] = iColumn;
3898       }
3899       COIN_DETAIL_PRINT(printf("** can fix %d columns - best ratio for others is %g on gap of %g\n",
3900         nFix, bestRatio, gap));
3901       int nNeg = 0;
3902       CoinSort_2(saveLower, saveLower + numberColumns, order);
3903       for (int i = 0; i < numberColumns; i++) {
3904         if (saveLower[i] < 0.0) {
3905           nNeg++;
3906 #if HOTSTART == 2 || HOTSTART == 3
3907           // swap sign ?
3908           saveLower[i] = -saveLower[i];
3909 #endif
3910         }
3911       }
3912       CoinSort_2(saveLower, saveLower + nNeg, order);
3913       for (int i = 0; i < numberColumns; i++) {
3914 #if HOTSTART == 1
3915         hotstartPriorities_[order[i]] = 100;
3916 #else
3917           hotstartPriorities_[order[i]] = -(i + 1);
3918 #endif
3919       }
3920       COIN_DETAIL_PRINT(printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n",
3921         nAtLbNatural,
3922         nAtUbNatural,
3923         nAtLbNaturalZero,
3924         nAtUbNaturalZero,
3925         nAtLbFixed,
3926         nAtUbFixed,
3927         nAtOther,
3928         nAtOtherNatural, nNotNeeded, nNeg));
3929       delete[] saveLower;
3930       delete[] saveUpper;
3931       if (!saveCompare) {
3932         // create depth first comparison
3933         saveCompare = nodeCompare_;
3934         // depth first
3935         nodeCompare_ = new CbcCompareDepth();
3936         tree_->setComparison(*nodeCompare_);
3937       }
3938     }
3939 #endif
3940     newNode = new CbcNode;
3941     // Set objective value (not so obvious if NLP etc)
3942     setObjectiveValue(newNode, NULL);
3943     anyAction = -1;
3944     // To make depth available we may need a fake node
3945     CbcNode fakeNode;
3946     phase_ = 3;
3947     // only allow 1000 passes
3948     int numberPassesLeft = 1000;
3949     // This is first crude step
3950     if (numberAnalyzeIterations_ && !parentModel_) {
3951       delete[] analyzeResults_;
3952       //int numberColumns = solver_->getNumCols();
3953       analyzeResults_ = new double[5 * numberIntegers_];
3954       numberFixedAtRoot_ = newNode->analyze(this, analyzeResults_);
3955       if (numberFixedAtRoot_ > 0) {
3956         COIN_DETAIL_PRINT(printf("%d fixed by analysis\n", numberFixedAtRoot_));
3957         setPointers(solver_);
3958         numberFixedNow_ = numberFixedAtRoot_;
3959       } else if (numberFixedAtRoot_ < 0) {
3960         COIN_DETAIL_PRINT(printf("analysis found to be infeasible\n"));
3961         anyAction = -2;
3962         delete newNode;
3963         newNode = NULL;
3964         feasible = false;
3965       }
3966     }
3967     OsiSolverBranch *branches = NULL;
3968     if (feasible)
3969       anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts, resolved,
3970         NULL, NULL, NULL, branches);
3971     if (anyAction == -2 || newNode->objectiveValue() >= cutoff) {
3972       if (anyAction != -2) {
3973         // zap parent nodeInfo
3974 #ifdef COIN_DEVELOP
3975         printf("zapping CbcNodeInfo %x\n", newNode->nodeInfo()->parent());
3976 #endif
3977         if (newNode->nodeInfo())
3978           newNode->nodeInfo()->nullParent();
3979       }
3980       deleteNode(newNode);
3981       newNode = NULL;
3982       feasible = false;
3983     }
3984   }
3985   if (newNode && probingInfo_) {
3986     int number01 = probingInfo_->numberIntegers();
3987     //const fixEntry * entry = probingInfo_->fixEntries();
3988     const int *toZero = probingInfo_->toZero();
3989     //const int * toOne = probingInfo_->toOne();
3990     //const int * integerVariable = probingInfo_->integerVariable();
3991     if (toZero[number01]) {
3992       CglTreeProbingInfo info(*probingInfo_);
3993       if ((moreSpecialOptions2_ & 64) != 0 && !parentModel_) {
3994         /*
3995 		Marginal idea. Further exploration probably good. Build some extra
3996 		cliques from probing info. Not quite worth the effort?
3997 	      */
3998         CglProbing generator1;
3999         generator1.setUsingObjective(false);
4000         generator1.setMaxPass(1);
4001         generator1.setMaxPassRoot(1);
4002         generator1.setMaxLook(100);
4003         generator1.setRowCuts(3);
4004         generator1.setMaxElements(300);
4005         generator1.setMaxProbeRoot(solver_->getNumCols());
4006         CoinThreadRandom randomGenerator;
4007         //CglTreeProbingInfo info(solver_);
4008         info.level = 0;
4009         info.formulation_rows = solver_->getNumRows();
4010         info.inTree = false;
4011         if (parentModel_) {
4012           info.parentSolver = parentModel_->continuousSolver();
4013           // indicate if doing full search
4014           info.hasParent = ((specialOptions_ & 67108864) == 0) ? 1 : 2;
4015         } else {
4016           info.hasParent = 0;
4017           info.parentSolver = NULL;
4018         }
4019         info.originalColumns = originalColumns();
4020         info.randomNumberGenerator = &randomGenerator;
4021         info.pass = 4;
4022         generator1.setMode(8);
4023         OsiCuts cs;
4024         generator1.generateCutsAndModify(*solver_, cs, &info);
4025         // very clunky
4026         OsiSolverInterface *temp = generator1.cliqueModel(solver_, 2);
4027         CglPreProcess dummy;
4028         OsiSolverInterface *newSolver = dummy.cliqueIt(*temp, 0.0001);
4029         delete temp;
4030         OsiSolverInterface *fake = NULL;
4031         if (newSolver) {
4032 #if 0
4033 		int numberCliques = generator1.numberCliques();
4034 		cliqueEntry * entry = generator1.cliqueEntry();
4035 		cliqueType * type = new cliqueType [numberCliques];
4036 		int * start = new int [numberCliques+1];
4037 		start[numberCliques]=2*numberCliques;
4038 		int n=0;
4039 		for (int i=0;i<numberCliques;i++) {
4040 		  start[i]=2*i;
4041 		  setOneFixesInCliqueEntry(entry[2*i],true);
4042 		  setOneFixesInCliqueEntry(entry[2*i+1],true);
4043 		  type[i]=0;
4044 		}
4045 		fake = info.analyze(*solver_, 1,numberCliques,start,
4046 				    entry,type);
4047 		delete [] type;
4048 		delete [] entry;
4049 #else
4050         fake = info.analyze(*newSolver, 1, -1);
4051 #endif
4052           delete newSolver;
4053         } else {
4054           fake = info.analyze(*solver_, 1);
4055         }
4056         if (fake) {
4057           //fake->writeMps("fake");
4058           CglFakeClique cliqueGen(fake);
4059           cliqueGen.setStarCliqueReport(false);
4060           cliqueGen.setRowCliqueReport(false);
4061           cliqueGen.setMinViolation(0.1);
4062           addCutGenerator(&cliqueGen, 1, "Fake cliques", true, false, false, -200);
4063           generator_[numberCutGenerators_ - 1]->setTiming(true);
4064           for (int i = 0; i < numberCutGenerators_; i++) {
4065             CglKnapsackCover *cutGen = dynamic_cast< CglKnapsackCover * >(generator_[i]->generator());
4066             if (cutGen) {
4067               cutGen->createCliques(*fake, 2, 200, false);
4068             }
4069           }
4070         }
4071       }
4072       if (probingInfo_->packDown()) {
4073 #if CBC_USEFUL_PRINTING > 1
4074         printf("%d implications on %d 0-1\n", toZero[number01], number01);
4075 #endif
4076         // Create a cut generator that remembers implications discovered at root.
4077         CglImplication implication(probingInfo_);
4078         addCutGenerator(&implication, 1, "ImplicationCuts", true, false, false, -200);
4079         generator_[numberCutGenerators_ - 1]->setGlobalCuts(true);
4080         generator_[numberCutGenerators_ - 1]->setTiming(true);
4081       } else {
4082         delete probingInfo_;
4083         probingInfo_ = NULL;
4084       }
4085     } else {
4086       delete probingInfo_;
4087 
4088       probingInfo_ = NULL;
4089     }
4090   }
4091   /*
4092       At this point, the root subproblem is infeasible or fathomed by bound
4093       (newNode == NULL), or we're live with an objective value that satisfies the
4094       current objective cutoff.
4095     */
4096   assert(!newNode || newNode->objectiveValue() <= cutoff);
4097   // Save address of root node as we don't want to delete it
4098   /*
4099       The common case is that the lp relaxation is feasible but doesn't satisfy
4100       integrality (i.e., newNode->branchingObject(), indicating we've been able to
4101       select a branching variable). Remove any cuts that have gone slack due to
4102       forcing monotone variables. Then tack on an CbcFullNodeInfo object and full
4103       basis (via createInfo()) and stash the new cuts in the nodeInfo (via
4104       addCuts()). If, by some miracle, we have an integral solution at the root
4105       (newNode->branchingObject() is NULL), takeOffCuts() will ensure that the solver holds
4106       a valid solution for use by setBestSolution().
4107     */
4108   CoinWarmStartBasis *lastws = NULL;
4109   if (feasible && newNode->branchingObject()) {
4110     if (resolved) {
4111       takeOffCuts(cuts, false, NULL);
4112 #ifdef CHECK_CUT_COUNTS
4113       {
4114         printf("Number of rows after chooseBranch fix (root)"
4115                "(active only) %d\n",
4116           numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_);
4117         const CoinWarmStartBasis *debugws = dynamic_cast< const CoinWarmStartBasis * >(solver_->getWarmStart());
4118         debugws->print();
4119         delete debugws;
4120       }
4121 #endif
4122     }
4123     //newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
4124     //newNode->nodeInfo()->addCuts(cuts,
4125     //			 newNode->numberBranches(),whichGenerator_) ;
4126     if (lastws)
4127       delete lastws;
4128     lastws = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
4129   }
4130   /*
4131       Continuous data to be used later
4132     */
4133   continuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
4134   continuousInfeasibilities_ = 0;
4135   if (newNode) {
4136     continuousObjective_ = newNode->objectiveValue();
4137     delete[] continuousSolution_;
4138     continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
4139       numberColumns);
4140     continuousInfeasibilities_ = newNode->numberUnsatisfied();
4141   }
4142   /*
4143       Bound may have changed so reset in objects
4144     */
4145   {
4146     int i;
4147     for (i = 0; i < numberObjects_; i++)
4148       object_[i]->resetBounds(solver_);
4149   }
4150   /*
4151       Feasible? Then we should have either a live node prepped for future
4152       expansion (indicated by variable() >= 0), or (miracle of miracles) an
4153       integral solution at the root node.
4154 
4155       initializeInfo sets the reference counts in the nodeInfo object.  Since
4156       this node is still live, push it onto the heap that holds the live set.
4157     */
4158   if (newNode) {
4159     if (newNode->branchingObject()) {
4160       newNode->initializeInfo();
4161       tree_->push(newNode);
4162       // save pointer to root node - so can pick up bounds
4163       if (!topOfTree_)
4164         topOfTree_ = dynamic_cast< CbcFullNodeInfo * >(newNode->nodeInfo());
4165       if (statistics_) {
4166         if (numberNodes2_ == maximumStatistics_) {
4167           maximumStatistics_ = 2 * maximumStatistics_;
4168           CbcStatistics **temp = new CbcStatistics *[maximumStatistics_];
4169           memset(temp, 0, maximumStatistics_ * sizeof(CbcStatistics *));
4170           memcpy(temp, statistics_, numberNodes2_ * sizeof(CbcStatistics *));
4171           delete[] statistics_;
4172           statistics_ = temp;
4173         }
4174         assert(!statistics_[numberNodes2_]);
4175         statistics_[numberNodes2_] = new CbcStatistics(newNode, this);
4176       }
4177       numberNodes2_++;
4178 #ifdef CHECK_NODE
4179       printf("Node %x on tree\n", newNode);
4180 #endif
4181     } else {
4182       // continuous is integer
4183       double objectiveValue = newNode->objectiveValue();
4184       setBestSolution(CBC_SOLUTION, objectiveValue,
4185         solver_->getColSolution());
4186       if (eventHandler) {
4187         // we are stopping anyway so no need to test return code
4188         eventHandler->event(CbcEventHandler::solution);
4189       }
4190       delete newNode;
4191       newNode = NULL;
4192     }
4193   }
4194 
4195   if (printFrequency_ <= 0) {
4196     printFrequency_ = 1000;
4197     if (getNumCols() > 2000)
4198       printFrequency_ = 100;
4199   }
4200   /*
4201       It is possible that strong branching fixes one variable and then the code goes round
4202       again and again.  This can take too long.  So we need to warn user - just once.
4203     */
4204   numberLongStrong_ = 0;
4205   CbcNode *createdNode = NULL;
4206 #ifdef CBC_THREAD
4207   if ((specialOptions_ & 2048) != 0)
4208     numberThreads_ = 0;
4209   if (numberThreads_) {
4210     nodeCompare_->sayThreaded(); // need to use addresses
4211     master_ = new CbcBaseModel(*this,
4212       (parallelMode() < -1) ? 1 : 0);
4213     masterThread_ = master_->masterThread();
4214   }
4215 #endif
4216 #ifdef COIN_HAS_CLP
4217   {
4218     OsiClpSolverInterface *clpSolver
4219       = dynamic_cast< OsiClpSolverInterface * >(solver_);
4220     if (clpSolver && !parentModel_) {
4221       clpSolver->computeLargestAway();
4222     }
4223   }
4224 #endif
4225   /*
4226       At last, the actual branch-and-cut search loop, which will iterate until
4227       the live set is empty or we hit some limit (integrality gap, time, node
4228       count, etc.). The overall flow is to rebuild a subproblem, reoptimise using
4229       solveWithCuts(), choose a branching pattern with chooseBranch(), and finally
4230       add the node to the live set.
4231 
4232       The first action is to winnow the live set to remove nodes which are worse
4233       than the current objective cutoff.
4234     */
4235   if (solver_->getRowCutDebuggerAlways()) {
4236     OsiRowCutDebugger *debuggerX = const_cast< OsiRowCutDebugger * >(solver_->getRowCutDebuggerAlways());
4237     const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
4238     if (!debugger) {
4239       // infeasible!!
4240       printf("before search\n");
4241       const double *lower = solver_->getColLower();
4242       const double *upper = solver_->getColUpper();
4243       const double *solution = debuggerX->optimalSolution();
4244       int numberColumns = solver_->getNumCols();
4245       for (int i = 0; i < numberColumns; i++) {
4246         if (solver_->isInteger(i)) {
4247           if (solution[i] < lower[i] - 1.0e-6 || solution[i] > upper[i] + 1.0e-6)
4248             printf("**** ");
4249           printf("%d %g <= %g <= %g\n",
4250             i, lower[i], solution[i], upper[i]);
4251         }
4252       }
4253       //abort();
4254     }
4255   }
4256   {
4257     // may be able to change cutoff now
4258     double cutoff = getCutoff();
4259     double increment = getDblParam(CbcModel::CbcCutoffIncrement);
4260     if (cutoff > bestObjective_ - increment) {
4261       cutoff = bestObjective_ - increment;
4262       setCutoff(cutoff);
4263     }
4264   }
4265 #ifdef CBC_THREAD
4266   bool goneParallel = false;
4267 #endif
4268 #define MAX_DEL_NODE 1
4269   CbcNode *delNode[MAX_DEL_NODE + 1];
4270   int nDeleteNode = 0;
4271   // For Printing etc when parallel
4272   int lastEvery1000 = 0;
4273   int lastPrintEvery = 0;
4274   int numberConsecutiveInfeasible = 0;
4275 #define PERTURB_IN_FATHOM
4276 #ifdef PERTURB_IN_FATHOM
4277   // allow in fathom
4278   if ((moreSpecialOptions_ & 262144) != 0)
4279     specialOptions_ |= 131072;
4280 #endif
4281   while (true) {
4282     lockThread();
4283 #ifdef COIN_HAS_CLP
4284     // See if we want dantzig row choice
4285     goToDantzig(100, savePivotMethod);
4286 #endif
4287     //#define REPORT_DYNAMIC 2
4288 #if REPORT_DYNAMIC
4289     if (numberNodes_ && !parentModel_ && (tree_->empty() || (numberNodes_ % 10000) == 0)) {
4290       // Get average up and down costs
4291       double averageUp = 0.0;
4292       double averageDown = 0.0;
4293       int numberUp = 0;
4294       int numberDown = 0;
4295       int minTimesDown = COIN_INT_MAX;
4296       int maxTimesDown = 0;
4297       int neverBranchedDown = 0;
4298       int infeasibleTimesDown = 0;
4299       int minTimesUp = COIN_INT_MAX;
4300       int maxTimesUp = 0;
4301       int infeasibleTimesUp = 0;
4302       int neverBranchedUp = 0;
4303       int neverBranched = 0;
4304       int i;
4305       int numberInts = 0;
4306       bool endOfSearch = tree_->empty();
4307       int numberUp2 = 0;
4308       int numberDown2 = 0;
4309       for (i = 0; i < numberObjects_; i++) {
4310         OsiObject *object = object_[i];
4311         CbcSimpleIntegerDynamicPseudoCost *dynamicObject = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object);
4312         if (dynamicObject) {
4313           numberInts++;
4314           if (dynamicObject->numberTimesUp() || dynamicObject->numberTimesDown()) {
4315             int nUp = 0;
4316             int nDown = 0;
4317             double up = 0.0;
4318             double down = 0.0;
4319             if (dynamicObject->numberTimesUp()) {
4320               numberUp++;
4321               nUp = dynamicObject->numberTimesUp();
4322               minTimesUp = CoinMin(minTimesUp, nUp);
4323               maxTimesUp = CoinMax(maxTimesUp, nUp);
4324               up = dynamicObject->upDynamicPseudoCost();
4325               averageUp += up;
4326               numberUp2 += nUp;
4327               infeasibleTimesUp += dynamicObject->numberTimesUpInfeasible();
4328             } else {
4329               neverBranchedUp++;
4330             }
4331             if (dynamicObject->numberTimesDown()) {
4332               numberDown++;
4333               nDown = dynamicObject->numberTimesDown();
4334               minTimesDown = CoinMin(minTimesDown, nDown);
4335               maxTimesDown = CoinMax(maxTimesDown, nDown);
4336               down = dynamicObject->downDynamicPseudoCost();
4337               averageDown += down;
4338               numberDown2 += dynamicObject->numberTimesDown();
4339               infeasibleTimesDown += dynamicObject->numberTimesDownInfeasible();
4340             } else {
4341               neverBranchedDown++;
4342             }
4343 #if REPORT_DYNAMIC > 1
4344 #if REPORT_DYNAMIC == 2
4345             if (endOfSearch && numberIntegers_ < 400) {
4346 #elif REPORT_DYNAMIC == 3
4347             if (endOfSearch) {
4348 #else
4349             {
4350 #endif
4351               dynamicObject->print(0, 0.0);
4352             }
4353 #endif
4354           } else {
4355             neverBranched++;
4356 #if REPORT_DYNAMIC > 2
4357 #if REPORT_DYNAMIC == 3
4358             if (endOfSearch && numberIntegers_ < 400) {
4359 #elif REPORT_DYNAMIC == 4
4360             if (endOfSearch) {
4361 #else
4362             {
4363 #endif
4364               printf("col %d - never branched on\n", dynamicObject->columnNumber());
4365             }
4366 #endif
4367           }
4368         }
4369       }
4370       if (numberUp)
4371         averageUp /= static_cast< double >(numberUp);
4372       else
4373         averageUp = 0.0;
4374       if (numberDown)
4375         averageDown /= static_cast< double >(numberDown);
4376       else
4377         averageDown = 0.0;
4378       printf("Report for %d variables (%d never branched on) after %d nodes - total solves down %d up %d\n",
4379         numberInts, neverBranched, numberNodes_, numberDown2, numberUp2);
4380       if ((neverBranchedDown || neverBranchedUp) && endOfSearch)
4381         printf("odd %d never branched down and %d never branched up\n",
4382           neverBranchedDown, neverBranchedUp);
4383       printf("down average %g times (%d infeasible) average increase %g min/max times (%d,%d)\n",
4384         static_cast< double >(numberDown2) / numberDown, infeasibleTimesDown, averageDown,
4385         minTimesDown, maxTimesDown);
4386       printf("up average %g times (%d infeasible) average increase %g min/max times (%d,%d)\n",
4387         static_cast< double >(numberUp2) / numberUp, infeasibleTimesUp, averageUp,
4388         minTimesUp, maxTimesUp);
4389     }
4390 #endif
4391     if (tree_->empty()) {
4392 #ifdef CBC_THREAD
4393       if (parallelMode() > 0 && master_) {
4394         int anyLeft = master_->waitForThreadsInTree(0);
4395         if (!anyLeft) {
4396           master_->stopThreads(-1);
4397           break;
4398         }
4399       } else {
4400         break;
4401       }
4402 #else
4403     break;
4404 #endif
4405     } else {
4406       unlockThread();
4407     }
4408     // If done 50/100 nodes see if worth trying reduction
4409     if (numberNodes_ >= nextCheckRestart) {
4410       if (nextCheckRestart < 100)
4411         nextCheckRestart = 100;
4412       else
4413         nextCheckRestart = COIN_INT_MAX;
4414 #ifdef COIN_HAS_CLP
4415       OsiClpSolverInterface *clpSolver
4416         = dynamic_cast< OsiClpSolverInterface * >(solver_);
4417       if (clpSolver && ((specialOptions_ & 131072) == 0) && true) {
4418         ClpSimplex *simplex = clpSolver->getModelPtr();
4419         int perturbation = simplex->perturbation();
4420 #if CBC_USEFUL_PRINTING > 1
4421         printf("Testing its n,s %d %d solves n,s %d %d - pert %d\n",
4422           numberIterations_, saveNumberIterations,
4423           numberSolves_, saveNumberSolves, perturbation);
4424 #endif
4425         if (perturbation == 50 && (numberIterations_ - saveNumberIterations) < 8 * (numberSolves_ - saveNumberSolves)) {
4426           // switch off perturbation
4427           simplex->setPerturbation(100);
4428 #if CBC_USEFUL_PRINTING > 1
4429           printf("Perturbation switched off\n");
4430 #endif
4431         }
4432       }
4433 #endif
4434       /*
4435               Decide if we want to do a restart.
4436             */
4437       if (saveSolver && (specialOptions_ & (512 + 32768)) != 0) {
4438         bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() && (getCutoff() < 1.0e20 && getCutoff() < checkCutoffForRestart);
4439         int numberColumns = getNumCols();
4440         if (tryNewSearch) {
4441           // adding increment back allows current best - tiny bit weaker
4442           checkCutoffForRestart = getCutoff() + getCutoffIncrement();
4443 #if CBC_USEFUL_PRINTING > 1
4444           printf("after %d nodes, cutoff %g - looking\n",
4445             numberNodes_, getCutoff());
4446 #endif
4447           saveSolver->resolve();
4448           double direction = saveSolver->getObjSense();
4449           double gap = checkCutoffForRestart - saveSolver->getObjValue() * direction;
4450           double tolerance;
4451           saveSolver->getDblParam(OsiDualTolerance, tolerance);
4452           if (gap <= 0.0)
4453             gap = tolerance;
4454           gap += 100.0 * tolerance;
4455           double integerTolerance = getDblParam(CbcIntegerTolerance);
4456 
4457           const double *lower = saveSolver->getColLower();
4458           const double *upper = saveSolver->getColUpper();
4459           const double *solution = saveSolver->getColSolution();
4460           const double *reducedCost = saveSolver->getReducedCost();
4461 
4462           int numberFixed = 0;
4463           int numberFixed2 = 0;
4464 #ifdef COIN_DEVELOP
4465           printf("gap %g\n", gap);
4466 #endif
4467           for (int i = 0; i < numberIntegers_; i++) {
4468             int iColumn = integerVariable_[i];
4469             double djValue = direction * reducedCost[iColumn];
4470             if (upper[iColumn] - lower[iColumn] > integerTolerance) {
4471               if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
4472                 //printf("%d to lb on dj of %g - bounds %g %g\n",
4473                 //     iColumn,djValue,lower[iColumn],upper[iColumn]);
4474                 saveSolver->setColUpper(iColumn, lower[iColumn]);
4475                 numberFixed++;
4476               } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
4477                 //printf("%d to ub on dj of %g - bounds %g %g\n",
4478                 //     iColumn,djValue,lower[iColumn],upper[iColumn]);
4479                 saveSolver->setColLower(iColumn, upper[iColumn]);
4480                 numberFixed++;
4481               }
4482             } else {
4483               //printf("%d has dj of %g - already fixed to %g\n",
4484               //     iColumn,djValue,lower[iColumn]);
4485               numberFixed2++;
4486             }
4487           }
4488 #ifdef COIN_DEVELOP
4489           if ((specialOptions_ & 1) != 0) {
4490             const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger();
4491             if (debugger) {
4492               printf("Contains optimal\n");
4493               OsiSolverInterface *temp = saveSolver->clone();
4494               const double *solution = debugger->optimalSolution();
4495               const double *lower = temp->getColLower();
4496               const double *upper = temp->getColUpper();
4497               int n = temp->getNumCols();
4498               for (int i = 0; i < n; i++) {
4499                 if (temp->isInteger(i)) {
4500                   double value = floor(solution[i] + 0.5);
4501                   assert(value >= lower[i] && value <= upper[i]);
4502                   temp->setColLower(i, value);
4503                   temp->setColUpper(i, value);
4504                 }
4505               }
4506               temp->writeMps("reduced_fix");
4507               delete temp;
4508               saveSolver->writeMps("reduced");
4509             } else {
4510               abort();
4511             }
4512           }
4513           printf("Restart could fix %d integers (%d already fixed)\n",
4514             numberFixed + numberFixed2, numberFixed2);
4515 #endif
4516           numberFixed += numberFixed2;
4517           if (numberFixed * 10 < numberColumns && numberFixed * 4 < numberIntegers_)
4518             tryNewSearch = false;
4519         }
4520 #ifdef CONFLICT_CUTS
4521         // temporary
4522         //if ((moreSpecialOptions_&4194304)!=0)
4523         //tryNewSearch=false;
4524 #endif
4525         if (tryNewSearch) {
4526           // back to solver without cuts?
4527           OsiSolverInterface *solver2 = saveSolver->clone();
4528           const double *lower = saveSolver->getColLower();
4529           const double *upper = saveSolver->getColUpper();
4530           for (int i = 0; i < numberIntegers_; i++) {
4531             int iColumn = integerVariable_[i];
4532             solver2->setColLower(iColumn, lower[iColumn]);
4533             solver2->setColUpper(iColumn, upper[iColumn]);
4534           }
4535           // swap
4536           delete saveSolver;
4537           saveSolver = solver2;
4538           double *newSolution = new double[numberColumns];
4539           double objectiveValue = checkCutoffForRestart;
4540           // Save the best solution so far.
4541           CbcSerendipity heuristic(*this);
4542           if (bestSolution_)
4543             heuristic.setInputSolution(bestSolution_, bestObjective_);
4544           // Magic number
4545           heuristic.setFractionSmall(0.8);
4546           // `pumpTune' to stand-alone solver for explanations.
4547           heuristic.setFeasibilityPumpOptions(1008013);
4548           // Use numberNodes to say how many are original rows
4549           heuristic.setNumberNodes(continuousSolver_->getNumRows());
4550 #ifdef COIN_DEVELOP
4551           if (continuousSolver_->getNumRows() < solver_->getNumRows())
4552             printf("%d rows added ZZZZZ\n",
4553               solver_->getNumRows() - continuousSolver_->getNumRows());
4554 #endif
4555           int returnCode = heuristic.smallBranchAndBound(saveSolver,
4556             -1, newSolution,
4557             objectiveValue,
4558             checkCutoffForRestart, "Reduce");
4559           if (returnCode < 0) {
4560 #ifdef COIN_DEVELOP
4561             printf("Restart - not small enough to do search after fixing\n");
4562 #endif
4563             delete[] newSolution;
4564           } else {
4565             // 1 for sol'n, 2 for finished, 3 for both
4566             if ((returnCode & 1) != 0) {
4567               // increment number of solutions so other heuristics can test
4568               numberSolutions_++;
4569               numberHeuristicSolutions_++;
4570               lastHeuristic_ = NULL;
4571               setBestSolution(CBC_ROUNDING, objectiveValue, newSolution);
4572             }
4573             delete[] newSolution;
4574 #ifdef CBC_THREAD
4575             if (master_) {
4576               lockThread();
4577               if (parallelMode() > 0) {
4578                 while (master_->waitForThreadsInTree(0)) {
4579                   lockThread();
4580                   double dummyBest;
4581                   tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest);
4582                   //unlockThread();
4583                 }
4584               } else {
4585                 double dummyBest;
4586                 tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest);
4587               }
4588               master_->waitForThreadsInTree(2);
4589               delete master_;
4590               master_ = NULL;
4591               masterThread_ = NULL;
4592             }
4593 #endif
4594             if (tree_->size()) {
4595               double dummyBest;
4596               tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest);
4597             }
4598             break;
4599           }
4600         }
4601         delete saveSolver;
4602         saveSolver = NULL;
4603       }
4604     }
4605     /*
4606           Check for abort on limits: node count, solution count, time, integrality gap.
4607         */
4608     if (!(numberNodes_ < intParam_[CbcMaxNumNode] && numberSolutions_ < intParam_[CbcMaxNumSol] && !maximumSecondsReached() && !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 || numberIterations_ < maximumNumberIterations_))) {
4609       // out of loop
4610       break;
4611     }
4612 #ifdef BONMIN
4613     assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible());
4614 #endif
4615 // Sets percentage of time when we try diving. Diving requires a bit of heap reorganisation, because
4616 // we need to replace the comparison function to dive, and that requires reordering to retain the
4617 // heap property.
4618 #define DIVE_WHEN 1000
4619 #define DIVE_STOP 2000
4620     int kNode = numberNodes_ % 4000;
4621     if (numberNodes_ < 100000 && kNode > DIVE_WHEN && kNode <= DIVE_STOP) {
4622       if (!parallelMode()) {
4623         if (kNode == DIVE_WHEN + 1 || numberConsecutiveInfeasible > 1) {
4624           CbcCompareDefault *compare = dynamic_cast< CbcCompareDefault * >(nodeCompare_);
4625           // Don't interfere if user has replaced the compare function.
4626           if (compare) {
4627             //printf("Redoing tree\n");
4628             compare->startDive(this);
4629             numberConsecutiveInfeasible = 0;
4630           }
4631         }
4632       }
4633     }
4634     // replace current cutoff?
4635     if (cutoff > getCutoff()) {
4636       double newCutoff = getCutoff();
4637       if (analyzeResults_) {
4638         // see if we could fix any (more)
4639         int n = 0;
4640         double *newLower = analyzeResults_;
4641         double *objLower = newLower + numberIntegers_;
4642         double *newUpper = objLower + numberIntegers_;
4643         double *objUpper = newUpper + numberIntegers_;
4644         for (int i = 0; i < numberIntegers_; i++) {
4645           if (objLower[i] > newCutoff) {
4646             n++;
4647             if (objUpper[i] > newCutoff) {
4648               newCutoff = -COIN_DBL_MAX;
4649               break;
4650             }
4651             // add as global cut
4652             objLower[i] = -COIN_DBL_MAX;
4653             OsiRowCut rc;
4654             rc.setLb(newLower[i]);
4655             rc.setUb(COIN_DBL_MAX);
4656             double one = 1.0;
4657             rc.setRow(1, integerVariable_ + i, &one, false);
4658             rc.setGloballyValidAsInteger(2);
4659             globalCuts_.addCutIfNotDuplicate(rc);
4660           } else if (objUpper[i] > newCutoff) {
4661             n++;
4662             // add as global cut
4663             objUpper[i] = -COIN_DBL_MAX;
4664             OsiRowCut rc;
4665             rc.setLb(-COIN_DBL_MAX);
4666             rc.setUb(newUpper[i]);
4667             double one = 1.0;
4668             rc.setRow(1, integerVariable_ + i, &one, false);
4669             rc.setGloballyValidAsInteger(2);
4670             globalCuts_.addCutIfNotDuplicate(rc);
4671           }
4672         }
4673         if (newCutoff == -COIN_DBL_MAX) {
4674           COIN_DETAIL_PRINT(printf("Root analysis says finished\n"));
4675         } else if (n > numberFixedNow_) {
4676           COIN_DETAIL_PRINT(printf("%d more fixed by analysis - now %d\n", n - numberFixedNow_, n));
4677           numberFixedNow_ = n;
4678         }
4679       }
4680       if (eventHandler) {
4681         if (!eventHandler->event(CbcEventHandler::solution)) {
4682           eventHappened_ = true; // exit
4683         }
4684         newCutoff = getCutoff();
4685       }
4686       lockThread();
4687       /*
4688               Clean the tree to reflect the new solution, then see if the
4689               node comparison predicate wants to make any changes. If so,
4690               call setComparison for the side effect of rebuilding the heap.
4691             */
4692       tree_->cleanTree(this, newCutoff, bestPossibleObjective_);
4693       if (nodeCompare_->newSolution(this) || nodeCompare_->newSolution(this, continuousObjective_, continuousInfeasibilities_)) {
4694         tree_->setComparison(*nodeCompare_);
4695       }
4696       if (tree_->empty()) {
4697         continue;
4698       }
4699       unlockThread();
4700     }
4701     cutoff = getCutoff();
4702     /*
4703             Periodic activities: Opportunities to
4704             + tweak the nodeCompare criteria,
4705             + check if we've closed the integrality gap enough to quit,
4706             + print a summary line to let the user know we're working
4707         */
4708     if (numberNodes_ >= lastEvery1000) {
4709       lockThread();
4710 #ifdef COIN_HAS_CLP
4711       // See if we want dantzig row choice
4712       goToDantzig(1000, savePivotMethod);
4713 #endif
4714       lastEvery1000 = numberNodes_ + 1000;
4715       bool redoTree = nodeCompare_->every1000Nodes(this, numberNodes_);
4716 #ifdef CHECK_CUT_SIZE
4717       verifyCutSize(tree_, *this);
4718 #endif
4719       // redo tree if requested
4720       if (redoTree)
4721         tree_->setComparison(*nodeCompare_);
4722       unlockThread();
4723     }
4724     // Had hotstart before, now switched off
4725     if (saveCompare && !hotstartSolution_) {
4726       // hotstart switched off
4727       delete nodeCompare_; // off depth first
4728       nodeCompare_ = saveCompare;
4729       saveCompare = NULL;
4730       // redo tree
4731       lockThread();
4732       tree_->setComparison(*nodeCompare_);
4733       unlockThread();
4734     }
4735     if (numberNodes_ >= lastPrintEvery) {
4736       lastPrintEvery = numberNodes_ + printFrequency_;
4737       lockThread();
4738       int nNodes = tree_->size();
4739 
4740       //MODIF PIERRE
4741       bestPossibleObjective_ = tree_->getBestPossibleObjective();
4742 #ifdef CBC_THREAD
4743       if (parallelMode() > 0 && master_) {
4744         // need to adjust for ones not on tree
4745         int numberThreads = master_->numberThreads();
4746         for (int i = 0; i < numberThreads; i++) {
4747           CbcThread *child = master_->child(i);
4748           if (child->node()) {
4749             // adjust
4750             double value = child->node()->objectiveValue();
4751             bestPossibleObjective_ = CoinMin(bestPossibleObjective_, value);
4752           }
4753         }
4754       }
4755 #endif
4756       unlockThread();
4757 #if CBC_USEFUL_PRINTING > 1
4758       if (getCutoff() < 1.0e20) {
4759         if (fabs(getCutoff() - (bestObjective_ - getCutoffIncrement())) > 1.0e-6 && !parentModel_)
4760           printf("model cutoff in status %g, best %g, increment %g\n",
4761             getCutoff(), bestObjective_, getCutoffIncrement());
4762         assert(getCutoff() < bestObjective_ - getCutoffIncrement() + 1.0e-6 + 1.0e-10 * fabs(bestObjective_));
4763       }
4764 #endif
4765       if (!intParam_[CbcPrinting]) {
4766         // Parallel may not have any nodes
4767         if (!nNodes)
4768           bestPossibleObjective_ = lastBestPossibleObjective;
4769         else
4770           lastBestPossibleObjective = bestPossibleObjective_;
4771         messageHandler()->message(CBC_STATUS, messages())
4772           << numberNodes_ << CoinMax(nNodes, 1) << bestObjective_ << bestPossibleObjective_
4773           << getCurrentSeconds()
4774           << CoinMessageEol;
4775       } else if (intParam_[CbcPrinting] == 1) {
4776         messageHandler()->message(CBC_STATUS2, messages())
4777           << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
4778           << tree_->lastDepth() << tree_->lastUnsatisfied()
4779           << tree_->lastObjective() << numberIterations_
4780           << getCurrentSeconds()
4781           << CoinMessageEol;
4782       } else if (!numberExtraIterations_) {
4783         messageHandler()->message(CBC_STATUS2, messages())
4784           << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_
4785           << tree_->lastDepth() << tree_->lastUnsatisfied() << numberIterations_
4786           << getCurrentSeconds()
4787           << CoinMessageEol;
4788       } else {
4789         messageHandler()->message(CBC_STATUS3, messages())
4790           << numberNodes_ << numberFathoms_ << numberExtraNodes_ << nNodes
4791           << bestObjective_ << bestPossibleObjective_
4792           << tree_->lastDepth() << tree_->lastUnsatisfied() << numberIterations_ << numberExtraIterations_
4793           << getCurrentSeconds()
4794           << CoinMessageEol;
4795       }
4796 #ifdef COIN_HAS_NTY
4797       if (symmetryInfo_)
4798         symmetryInfo_->statsOrbits(this, 1);
4799 #endif
4800 #if PRINT_CONFLICT == 1
4801       if (numberConflictCuts > lastNumberConflictCuts) {
4802         double length = lengthConflictCuts / numberConflictCuts;
4803         printf("%d new conflict cuts - total %d - average length %g\n",
4804           numberConflictCuts - lastNumberConflictCuts,
4805           numberConflictCuts, length);
4806         lastNumberConflictCuts = numberConflictCuts;
4807       }
4808 #endif
4809       if (eventHandler && !eventHandler->event(CbcEventHandler::treeStatus)) {
4810         eventHappened_ = true; // exit
4811       }
4812     }
4813     // See if can stop on gap
4814     if (canStopOnGap()) {
4815       stoppedOnGap_ = true;
4816     }
4817 
4818 #ifdef CHECK_NODE_FULL
4819     verifyTreeNodes(tree_, *this);
4820 #endif
4821 #ifdef CHECK_CUT_COUNTS
4822     verifyCutCounts(tree_, *this);
4823 #endif
4824     /*
4825           Now we come to the meat of the loop. To create the active subproblem, we'll
4826           pop the most promising node in the live set, rebuild the subproblem it
4827           represents, and then execute the current arm of the branch to create the
4828           active subproblem.
4829         */
4830     CbcNode *node = NULL;
4831 #ifdef CBC_THREAD
4832     if (!parallelMode() || parallelMode() == -1) {
4833 #endif
4834       node = tree_->bestNode(cutoff);
4835       // Possible one on tree worse than cutoff
4836       // Weird comparison function can leave ineligible nodes on tree
4837       if (!node || node->objectiveValue() > cutoff)
4838         continue;
4839       // Do main work of solving node here
4840       doOneNode(this, node, createdNode);
4841 #ifdef JJF_ZERO
4842       if (node) {
4843         if (createdNode) {
4844           printf("Node %d depth %d, created %d depth %d\n",
4845             node->nodeNumber(), node->depth(),
4846             createdNode->nodeNumber(), createdNode->depth());
4847         } else {
4848           printf("Node %d depth %d,  no created node\n",
4849             node->nodeNumber(), node->depth());
4850         }
4851       } else if (createdNode) {
4852         printf("Node exhausted, created %d depth %d\n",
4853           createdNode->nodeNumber(), createdNode->depth());
4854       } else {
4855         printf("Node exhausted,  no created node\n");
4856         numberConsecutiveInfeasible = 2;
4857       }
4858 #endif
4859       //if (createdNode)
4860       //numberConsecutiveInfeasible=0;
4861       //else
4862       //numberConsecutiveInfeasible++;
4863 #ifdef CBC_THREAD
4864     } else if (parallelMode() > 0) {
4865       //lockThread();
4866       //node = tree_->bestNode(cutoff) ;
4867       // Possible one on tree worse than cutoff
4868       if (true || !node || node->objectiveValue() > cutoff) {
4869         assert(master_);
4870         if (master_) {
4871           int anyLeft = master_->waitForThreadsInTree(1);
4872           // may need to go round again
4873           if (anyLeft) {
4874             continue;
4875           } else {
4876             master_->stopThreads(-1);
4877           }
4878         }
4879       }
4880       //unlockThread();
4881     } else {
4882       // Deterministic parallel
4883       if ((tree_->size() < CoinMax(numberThreads_, 8) || hotstartSolution_) && !goneParallel) {
4884         node = tree_->bestNode(cutoff);
4885         // Possible one on tree worse than cutoff
4886         if (!node || node->objectiveValue() > cutoff)
4887           continue;
4888         // Do main work of solving node here
4889         doOneNode(this, node, createdNode);
4890         assert(createdNode);
4891         if (!createdNode->active()) {
4892           delete createdNode;
4893           createdNode = NULL;
4894         } else {
4895           // Say one more pointing to this
4896           node->nodeInfo()->increment();
4897           tree_->push(createdNode);
4898         }
4899         if (node->active()) {
4900           assert(node->nodeInfo());
4901           if (node->nodeInfo()->numberBranchesLeft()) {
4902             tree_->push(node);
4903           } else {
4904             node->setActive(false);
4905           }
4906         } else {
4907           if (node->nodeInfo()) {
4908             if (!node->nodeInfo()->numberBranchesLeft())
4909               node->nodeInfo()->allBranchesGone(); // can clean up
4910             // So will delete underlying stuff
4911             node->setActive(true);
4912           }
4913           delNode[nDeleteNode++] = node;
4914           node = NULL;
4915         }
4916         if (nDeleteNode >= MAX_DEL_NODE) {
4917           for (int i = 0; i < nDeleteNode; i++) {
4918             //printf("trying to del %d %x\n",i,delNode[i]);
4919             delete delNode[i];
4920             //printf("done to del %d %x\n",i,delNode[i]);
4921           }
4922           nDeleteNode = 0;
4923         }
4924       } else {
4925         // Split and solve
4926         master_->deterministicParallel();
4927         goneParallel = true;
4928       }
4929     }
4930 #endif
4931   }
4932   if (nDeleteNode) {
4933     for (int i = 0; i < nDeleteNode; i++) {
4934       delete delNode[i];
4935     }
4936     nDeleteNode = 0;
4937   }
4938 #ifdef CBC_THREAD
4939   if (master_) {
4940     master_->stopThreads(-1);
4941     master_->waitForThreadsInTree(2);
4942     // adjust time to allow for children on some systems
4943     //dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren();
4944   }
4945 #endif
4946   /*
4947       End of the non-abort actions. The next block of code is executed if we've
4948       aborted because we hit one of the limits. Clean up by deleting the live set
4949       and break out of the node processing loop. Note that on an abort, node may
4950       have been pushed back onto the tree for further processing, in which case
4951       it'll be deleted in cleanTree. We need to check.
4952     */
4953   if (!(numberNodes_ < intParam_[CbcMaxNumNode] && numberSolutions_ < intParam_[CbcMaxNumSol] && !maximumSecondsReached() && !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 || numberIterations_ < maximumNumberIterations_))) {
4954     if (tree_->size()) {
4955       double dummyBest;
4956       tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest);
4957 #if 0 // Does not seem to be needed def CBC_THREAD
4958 	    if (parallelMode() > 0 && master_) {
4959 	      // see if any dangling nodes
4960 	      int numberThreads = master_->numberThreads();
4961 	      for (int i=0;i<numberThreads;i++) {
4962 		CbcThread * child = master_->child(i);
4963 		//if (child->createdNode())
4964 		//printf("CHILD_NODE %p\n",child->createdNode());
4965 		delete child->createdNode();
4966 	      }
4967 	    }
4968 #endif
4969     }
4970     delete nextRowCut_;
4971     /* order is important here:
4972          * maximumSecondsReached() should be checked before eventHappened_ and
4973          * isNodeLimitReached() should be checked after eventHappened_
4974          * reason is, that at timelimit, eventHappened_ is set to true to make Cbc stop fast
4975          *   and if Ctrl+C is hit, then the nodelimit is set to -1 to make Cbc stop
4976          */
4977     if (stoppedOnGap_) {
4978       messageHandler()->message(CBC_GAP, messages())
4979         << bestObjective_ - bestPossibleObjective_
4980         << dblParam_[CbcAllowableGap]
4981         << dblParam_[CbcAllowableFractionGap] * 100.0
4982         << CoinMessageEol;
4983       secondaryStatus_ = 2;
4984       status_ = 0;
4985     } else if (maximumSecondsReached()) {
4986       handler_->message(CBC_MAXTIME, messages_) << CoinMessageEol;
4987       secondaryStatus_ = 4;
4988       status_ = 1;
4989     } else if (numberSolutions_ >= intParam_[CbcMaxNumSol]) {
4990       handler_->message(CBC_MAXSOLS, messages_) << CoinMessageEol;
4991       secondaryStatus_ = 6;
4992       status_ = 1;
4993     } else if (isNodeLimitReached()) {
4994       handler_->message(CBC_MAXNODES, messages_) << CoinMessageEol;
4995       secondaryStatus_ = 3;
4996       status_ = 1;
4997     } else if (maximumNumberIterations_ >= 0 && numberIterations_ >= maximumNumberIterations_) {
4998       handler_->message(CBC_MAXITERS, messages_) << CoinMessageEol;
4999       secondaryStatus_ = 8;
5000       status_ = 1;
5001     } else {
5002       handler_->message(CBC_EVENT, messages_) << CoinMessageEol;
5003       secondaryStatus_ = 5;
5004       status_ = 5;
5005     }
5006   }
5007 #ifdef CBC_THREAD
5008   if (master_) {
5009     delete master_;
5010     master_ = NULL;
5011     masterThread_ = NULL;
5012   }
5013 #endif
5014   /*
5015       That's it, we've exhausted the search tree, or broken out of the loop because
5016       we hit some limit on evaluation.
5017 
5018       We may have got an intelligent tree so give it one more chance
5019     */
5020   // Tell solver we are not in Branch and Cut
5021   solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL);
5022   tree_->endSearch();
5023   //  If we did any sub trees - did we give up on any?
5024   if (numberStoppedSubTrees_)
5025     status_ = 1;
5026   numberNodes_ += numberExtraNodes_;
5027   numberIterations_ += numberExtraIterations_;
5028   if (eventHandler) {
5029     eventHandler->event(CbcEventHandler::endSearch);
5030   }
5031   if (!status_) {
5032     // Set best possible unless stopped on gap
5033     if (secondaryStatus_ != 2)
5034       bestPossibleObjective_ = bestObjective_;
5035     handler_->message(CBC_END_GOOD, messages_)
5036       << bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds()
5037       << CoinMessageEol;
5038   } else {
5039     handler_->message(CBC_END, messages_)
5040       << bestObjective_ << bestPossibleObjective_
5041       << numberIterations_ << numberNodes_ << getCurrentSeconds()
5042       << CoinMessageEol;
5043   }
5044   if ((moreSpecialOptions_ & 4194304) != 0) {
5045     // Conflict cuts
5046     int numberCuts = globalCuts_.sizeRowCuts();
5047     int nConflict = 0;
5048     double sizeConflict = 0.0;
5049     for (int i = 0; i < numberCuts; i++) {
5050       OsiRowCut2 *cut = globalCuts_.cut(i);
5051       if (cut->whichRow() == 1) {
5052         nConflict++;
5053         sizeConflict += cut->row().getNumElements();
5054       }
5055     }
5056     if (nConflict) {
5057       sizeConflict /= nConflict;
5058       char general[200];
5059       sprintf(general, "%d conflict cuts generated - average length %g",
5060         nConflict, sizeConflict);
5061       messageHandler()->message(CBC_GENERAL,
5062         messages())
5063         << general << CoinMessageEol;
5064     }
5065   }
5066   if (numberStrongIterations_)
5067     handler_->message(CBC_STRONG_STATS, messages_)
5068       << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2]
5069       << strongInfo_[1] << CoinMessageEol;
5070   if (!numberExtraNodes_)
5071     handler_->message(CBC_OTHER_STATS, messages_)
5072       << maximumDepthActual_
5073       << numberDJFixed_ << CoinMessageEol;
5074   else
5075     handler_->message(CBC_OTHER_STATS2, messages_)
5076       << maximumDepthActual_
5077       << numberDJFixed_ << numberFathoms_ << numberExtraNodes_ << numberExtraIterations_
5078       << CoinMessageEol;
5079 #ifdef COIN_HAS_NTY
5080   if (symmetryInfo_)
5081     symmetryInfo_->statsOrbits(this, 1);
5082 #endif
5083   if (doStatistics == 100) {
5084     for (int i = 0; i < numberObjects_; i++) {
5085       CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
5086       if (obj)
5087         obj->print();
5088     }
5089   }
5090   if (statistics_) {
5091     // report in some way
5092     int *lookup = new int[numberObjects_];
5093     int i;
5094     for (i = 0; i < numberObjects_; i++)
5095       lookup[i] = -1;
5096     bool goodIds = false; //true;
5097     for (i = 0; i < numberObjects_; i++) {
5098       int iColumn = object_[i]->columnNumber();
5099       if (iColumn >= 0 && iColumn < numberColumns) {
5100         if (lookup[i] == -1) {
5101           lookup[i] = iColumn;
5102         } else {
5103           goodIds = false;
5104           break;
5105         }
5106       } else {
5107         goodIds = false;
5108         break;
5109       }
5110     }
5111     if (!goodIds) {
5112       delete[] lookup;
5113       lookup = NULL;
5114     }
5115     if (doStatistics >= 3) {
5116       printf("  node parent depth column   value                    obj      inf\n");
5117       for (i = 0; i < numberNodes2_; i++) {
5118         statistics_[i]->print(lookup);
5119       }
5120     }
5121     if (doStatistics > 1) {
5122       // Find last solution
5123       int k;
5124       for (k = numberNodes2_ - 1; k >= 0; k--) {
5125         if (statistics_[k]->endingObjective() != COIN_DBL_MAX && !statistics_[k]->endingInfeasibility())
5126           break;
5127       }
5128       if (k >= 0) {
5129         int depth = statistics_[k]->depth();
5130         int *which = new int[depth + 1];
5131         for (i = depth; i >= 0; i--) {
5132           which[i] = k;
5133           k = statistics_[k]->parentNode();
5134         }
5135         printf("  node parent depth column   value                    obj      inf\n");
5136         for (i = 0; i <= depth; i++) {
5137           statistics_[which[i]]->print(lookup);
5138         }
5139         delete[] which;
5140       }
5141     }
5142     // now summary
5143     int maxDepth = 0;
5144     double averageSolutionDepth = 0.0;
5145     int numberSolutions = 0;
5146     double averageCutoffDepth = 0.0;
5147     double averageSolvedDepth = 0.0;
5148     int numberCutoff = 0;
5149     int numberDown = 0;
5150     int numberFirstDown = 0;
5151     double averageInfDown = 0.0;
5152     double averageObjDown = 0.0;
5153     int numberCutoffDown = 0;
5154     int numberUp = 0;
5155     int numberFirstUp = 0;
5156     double averageInfUp = 0.0;
5157     double averageObjUp = 0.0;
5158     int numberCutoffUp = 0;
5159     double averageNumberIterations1 = 0.0;
5160     double averageValue = 0.0;
5161     for (i = 0; i < numberNodes2_; i++) {
5162       int depth = statistics_[i]->depth();
5163       int way = statistics_[i]->way();
5164       double value = statistics_[i]->value();
5165       double startingObjective = statistics_[i]->startingObjective();
5166       int startingInfeasibility = statistics_[i]->startingInfeasibility();
5167       double endingObjective = statistics_[i]->endingObjective();
5168       int endingInfeasibility = statistics_[i]->endingInfeasibility();
5169       maxDepth = CoinMax(depth, maxDepth);
5170       // Only for completed
5171       averageNumberIterations1 += statistics_[i]->numberIterations();
5172       averageValue += value;
5173       if (endingObjective != COIN_DBL_MAX && !endingInfeasibility) {
5174         numberSolutions++;
5175         averageSolutionDepth += depth;
5176       }
5177       if (endingObjective == COIN_DBL_MAX) {
5178         numberCutoff++;
5179         averageCutoffDepth += depth;
5180         if (way < 0) {
5181           numberDown++;
5182           numberCutoffDown++;
5183           if (way == -1)
5184             numberFirstDown++;
5185         } else {
5186           numberUp++;
5187           numberCutoffUp++;
5188           if (way == 1)
5189             numberFirstUp++;
5190         }
5191       } else {
5192         averageSolvedDepth += depth;
5193         if (way < 0) {
5194           numberDown++;
5195           averageInfDown += startingInfeasibility - endingInfeasibility;
5196           averageObjDown += endingObjective - startingObjective;
5197           if (way == -1)
5198             numberFirstDown++;
5199         } else {
5200           numberUp++;
5201           averageInfUp += startingInfeasibility - endingInfeasibility;
5202           averageObjUp += endingObjective - startingObjective;
5203           if (way == 1)
5204             numberFirstUp++;
5205         }
5206       }
5207     }
5208     // Now print
5209     if (numberSolutions)
5210       averageSolutionDepth /= static_cast< double >(numberSolutions);
5211     int numberSolved = numberNodes2_ - numberCutoff;
5212     double averageNumberIterations2 = numberIterations_ - averageNumberIterations1
5213       - numberIterationsAtContinuous;
5214     if (numberCutoff) {
5215       averageCutoffDepth /= static_cast< double >(numberCutoff);
5216       averageNumberIterations2 /= static_cast< double >(numberCutoff);
5217     }
5218     if (numberNodes2_)
5219       averageValue /= static_cast< double >(numberNodes2_);
5220     if (numberSolved) {
5221       averageNumberIterations1 /= static_cast< double >(numberSolved);
5222       averageSolvedDepth /= static_cast< double >(numberSolved);
5223     }
5224     printf("%d solution(s) were found (by branching) at an average depth of %g\n",
5225       numberSolutions, averageSolutionDepth);
5226     printf("average value of variable being branched on was %g\n",
5227       averageValue);
5228     printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n",
5229       numberCutoff, averageCutoffDepth, averageNumberIterations2);
5230     printf("%d nodes were solved at an average depth of %g with iteration count of %g\n",
5231       numberSolved, averageSolvedDepth, averageNumberIterations1);
5232     if (numberDown) {
5233       averageInfDown /= static_cast< double >(numberDown);
5234       averageObjDown /= static_cast< double >(numberDown);
5235     }
5236     printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
5237       numberDown, numberFirstDown, numberDown - numberFirstDown, numberCutoffDown,
5238       averageInfDown, averageObjDown);
5239     if (numberUp) {
5240       averageInfUp /= static_cast< double >(numberUp);
5241       averageObjUp /= static_cast< double >(numberUp);
5242     }
5243     printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
5244       numberUp, numberFirstUp, numberUp - numberFirstUp, numberCutoffUp,
5245       averageInfUp, averageObjUp);
5246     for (i = 0; i < numberNodes2_; i++)
5247       delete statistics_[i];
5248     delete[] statistics_;
5249     statistics_ = NULL;
5250     maximumStatistics_ = 0;
5251     delete[] lookup;
5252   }
5253   /*
5254       If we think we have a solution, restore and confirm it with a call to
5255       setBestSolution().  We need to reset the cutoff value so as not to fathom
5256       the solution on bounds.  Note that calling setBestSolution( ..., true)
5257       leaves the continuousSolver_ bounds vectors fixed at the solution value.
5258 
5259       Running resolve() here is a failsafe --- setBestSolution has already
5260       reoptimised using the continuousSolver_. If for some reason we fail to
5261       prove optimality, run the problem again after instructing the solver to
5262       tell us more.
5263 
5264       If all looks good, replace solver_ with continuousSolver_, so that the
5265       outside world will be able to obtain information about the solution using
5266       public methods.
5267 
5268       Don't replace if we are trying to save cuts
5269     */
5270   if (bestSolution_ && (solverCharacteristics_->solverType() < 2 || solverCharacteristics_->solverType() == 4) && ((specialOptions_ & 8388608) == 0 || (specialOptions_ & 2048) != 0)) {
5271     setCutoff(1.0e50); // As best solution should be worse than cutoff
5272     // change cutoff as constraint if wanted
5273     if (cutoffRowNumber_ >= 0) {
5274       if (solver_->getNumRows() > cutoffRowNumber_)
5275         solver_->setRowUpper(cutoffRowNumber_, 1.0e50);
5276     }
5277     // also in continuousSolver_
5278     if (continuousSolver_) {
5279       // Solvers know about direction
5280       double direction = solver_->getObjSense();
5281       continuousSolver_->setDblParam(OsiDualObjectiveLimit, 1.0e50 * direction);
5282     }
5283     phase_ = 5;
5284     double increment = getDblParam(CbcModel::CbcCutoffIncrement);
5285     if ((specialOptions_ & 4) == 0)
5286       bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve
5287     setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1);
5288     currentNode_ = NULL;
5289     continuousSolver_->resolve();
5290     // Deal with funny variables
5291     if ((moreSpecialOptions2_ & 32768) != 0)
5292       cleanBounds(continuousSolver_, NULL);
5293     if (!continuousSolver_->isProvenOptimal()) {
5294       continuousSolver_->messageHandler()->setLogLevel(2);
5295       continuousSolver_->initialSolve();
5296     }
5297     delete solver_;
5298     // above deletes solverCharacteristics_
5299     solverCharacteristics_ = NULL;
5300     solver_ = continuousSolver_;
5301     setPointers(solver_);
5302     continuousSolver_ = NULL;
5303   }
5304   /*
5305       Clean up dangling objects. continuousSolver_ may already be toast.
5306     */
5307   delete lastws;
5308   if (saveObjects) {
5309     for (int i = 0; i < numberObjects_; i++)
5310       delete saveObjects[i];
5311     delete[] saveObjects;
5312   }
5313   numberStrong_ = saveNumberStrong;
5314   numberBeforeTrust_ = saveNumberBeforeTrust;
5315   delete[] whichGenerator_;
5316   whichGenerator_ = NULL;
5317   delete[] lowerBefore;
5318   delete[] upperBefore;
5319   delete[] walkback_;
5320   walkback_ = NULL;
5321   delete[] lastNodeInfo_;
5322   lastNodeInfo_ = NULL;
5323   delete[] lastNumberCuts_;
5324   lastNumberCuts_ = NULL;
5325   delete[] lastCut_;
5326   lastCut_ = NULL;
5327   delete[] addedCuts_;
5328   addedCuts_ = NULL;
5329   //delete persistentInfo;
5330   // Get rid of characteristics
5331   solverCharacteristics_ = NULL;
5332   if (continuousSolver_) {
5333     delete continuousSolver_;
5334     continuousSolver_ = NULL;
5335   }
5336   /*
5337       Destroy global cuts by replacing with an empty OsiCuts object.
5338     */
5339   globalCuts_ = CbcRowCuts();
5340   delete globalConflictCuts_;
5341   globalConflictCuts_ = NULL;
5342   if (!bestSolution_ && (specialOptions_ & 8388608) == 0 && false) {
5343     // make sure lp solver is infeasible
5344     int numberColumns = solver_->getNumCols();
5345     const double *columnLower = solver_->getColLower();
5346     int iColumn;
5347     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5348       if (solver_->isInteger(iColumn))
5349         solver_->setColUpper(iColumn, columnLower[iColumn]);
5350     }
5351     solver_->initialSolve();
5352   }
5353 #ifdef COIN_HAS_CLP
5354   {
5355     OsiClpSolverInterface *clpSolver
5356       = dynamic_cast< OsiClpSolverInterface * >(solver_);
5357     if (clpSolver) {
5358       // Possible restore of pivot method
5359       if (savePivotMethod) {
5360         // model may have changed
5361         savePivotMethod->setModel(NULL);
5362         clpSolver->getModelPtr()->setDualRowPivotAlgorithm(*savePivotMethod);
5363         delete savePivotMethod;
5364       }
5365       clpSolver->setLargestAway(-1.0);
5366     }
5367   }
5368 #endif
5369   if ((fastNodeDepth_ >= 1000000 || (moreSpecialOptions_ & 33554432) != 0)
5370     && !parentModel_) {
5371     // delete object off end
5372     delete object_[numberObjects_];
5373     if ((moreSpecialOptions_ & 33554432) == 0)
5374       fastNodeDepth_ -= 1000000;
5375   }
5376   delete saveSolver;
5377   // Undo preprocessing performed during BaB.
5378   if (strategy_ && strategy_->preProcessState() > 0) {
5379     // undo preprocessing
5380     CglPreProcess *process = strategy_->process();
5381     assert(process);
5382     int n = originalSolver->getNumCols();
5383     if (bestSolution_) {
5384       delete[] bestSolution_;
5385       bestSolution_ = new double[n];
5386       process->postProcess(*solver_);
5387     }
5388     strategy_->deletePreProcess();
5389     // Solution now back in originalSolver
5390     delete solver_;
5391     solver_ = originalSolver;
5392     if (bestSolution_) {
5393       bestObjective_ = solver_->getObjValue() * solver_->getObjSense();
5394       memcpy(bestSolution_, solver_->getColSolution(), n * sizeof(double));
5395     }
5396     // put back original objects if there were any
5397     if (originalObject) {
5398       int iColumn;
5399       assert(ownObjects_);
5400       for (iColumn = 0; iColumn < numberObjects_; iColumn++)
5401         delete object_[iColumn];
5402       delete[] object_;
5403       numberObjects_ = numberOriginalObjects;
5404       object_ = originalObject;
5405       delete[] integerVariable_;
5406       numberIntegers_ = 0;
5407       for (iColumn = 0; iColumn < n; iColumn++) {
5408         if (solver_->isInteger(iColumn))
5409           numberIntegers_++;
5410       }
5411       integerVariable_ = new int[numberIntegers_];
5412       numberIntegers_ = 0;
5413       for (iColumn = 0; iColumn < n; iColumn++) {
5414         if (solver_->isInteger(iColumn))
5415           integerVariable_[numberIntegers_++] = iColumn;
5416       }
5417     }
5418   }
5419   if (flipObjective)
5420     flipModel();
5421 #ifdef COIN_HAS_CLP
5422   {
5423     OsiClpSolverInterface *clpSolver
5424       = dynamic_cast< OsiClpSolverInterface * >(solver_);
5425     if (clpSolver)
5426       clpSolver->setFakeObjective((double*)nullptr);
5427   }
5428 #endif
5429   moreSpecialOptions_ = saveMoreSpecialOptions;
5430   return;
5431 }
5432 
5433 // Solve the initial LP relaxation
5434 void CbcModel::initialSolve()
5435 {
5436   assert(solver_);
5437   // Double check optimization directions line up
5438   dblParam_[CbcOptimizationDirection] = solver_->getObjSense();
5439   // Check if bounds are all integral (as may get messed up later)
5440   checkModel();
5441   if (!solverCharacteristics_) {
5442     OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
5443     if (solverCharacteristics) {
5444       solverCharacteristics_ = solverCharacteristics;
5445     } else {
5446       // replace in solver
5447       OsiBabSolver defaultC;
5448       solver_->setAuxiliaryInfo(&defaultC);
5449       solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
5450     }
5451   }
5452   solverCharacteristics_->setSolver(solver_);
5453   solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL);
5454   solver_->initialSolve();
5455   solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL);
5456   if (!solver_->isProvenOptimal())
5457     solver_->resolve();
5458   // But set up so Jon Lee will be happy
5459   status_ = -1;
5460   secondaryStatus_ = -1;
5461   originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense();
5462   bestPossibleObjective_ = originalContinuousObjective_;
5463   if (solver_->isProvenDualInfeasible())
5464     originalContinuousObjective_ = -COIN_DBL_MAX;
5465   delete[] continuousSolution_;
5466   continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
5467     solver_->getNumCols());
5468   setPointers(solver_);
5469   solverCharacteristics_ = NULL;
5470 }
5471 
5472 /*! \brief Get an empty basis object
5473 
5474   Return an empty CoinWarmStartBasis object with the requested capacity,
5475   appropriate for the current solver. The object is cloned from the object
5476   cached as emptyWarmStart_. If there is no cached object, the routine
5477   queries the solver for a warm start object, empties it, and caches the
5478   result.
5479 */
5480 
5481 CoinWarmStartBasis *CbcModel::getEmptyBasis(int ns, int na) const
5482 
5483 {
5484   CoinWarmStartBasis *emptyBasis;
5485   /*
5486       Acquire an empty basis object, if we don't yet have one.
5487     */
5488   if (emptyWarmStart_ == 0) {
5489     if (solver_ == 0) {
5490       throw CoinError("Cannot construct basis without solver!",
5491         "getEmptyBasis", "CbcModel");
5492     }
5493     emptyBasis = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart());
5494     if (emptyBasis == 0) {
5495       throw CoinError(
5496         "Solver does not appear to use a basis-oriented warm start.",
5497         "getEmptyBasis", "CbcModel");
5498     }
5499     emptyBasis->setSize(0, 0);
5500     emptyWarmStart_ = dynamic_cast< CoinWarmStart * >(emptyBasis);
5501   }
5502   /*
5503       Clone the empty basis object, resize it as requested, and return.
5504     */
5505   emptyBasis = dynamic_cast< CoinWarmStartBasis * >(emptyWarmStart_->clone());
5506   assert(emptyBasis);
5507   if (ns != 0 || na != 0)
5508     emptyBasis->setSize(ns, na);
5509 
5510   return (emptyBasis);
5511 }
5512 
5513 /** Default Constructor
5514 
5515   Creates an empty model without an associated solver.
5516 */
5517 CbcModel::CbcModel()
5518 
5519   : solver_(NULL)
5520   , ownership_(0x80000000)
5521   , continuousSolver_(NULL)
5522   , referenceSolver_(NULL)
5523   , defaultHandler_(true)
5524   , emptyWarmStart_(NULL)
5525   , bestObjective_(COIN_DBL_MAX)
5526   , bestPossibleObjective_(COIN_DBL_MAX)
5527   , sumChangeObjective1_(0.0)
5528   , sumChangeObjective2_(0.0)
5529   , bestSolution_(NULL)
5530   , savedSolutions_(NULL)
5531   , currentSolution_(NULL)
5532   , testSolution_(NULL)
5533   , globalConflictCuts_(NULL)
5534   , minimumDrop_(1.0e-7)
5535   , numberSolutions_(0)
5536   , numberSavedSolutions_(0)
5537   , maximumSavedSolutions_(0)
5538   , stateOfSearch_(0)
5539   , whenCuts_(-1)
5540   , hotstartSolution_(NULL)
5541   , hotstartPriorities_(NULL)
5542   , numberHeuristicSolutions_(0)
5543   , numberNodes_(0)
5544   , numberNodes2_(0)
5545   , numberIterations_(0)
5546   , numberSolves_(0)
5547   , status_(-1)
5548   , secondaryStatus_(-1)
5549   , numberIntegers_(0)
5550   , numberRowsAtContinuous_(0)
5551   , cutoffRowNumber_(-1)
5552   , maximumNumberCuts_(0)
5553   , phase_(0)
5554   , currentNumberCuts_(0)
5555   , maximumDepth_(0)
5556   , walkback_(NULL)
5557   , preProcess_(NULL)
5558   , lastNodeInfo_(NULL)
5559   , lastCut_(NULL)
5560   , lastDepth_(0)
5561   , lastNumberCuts2_(0)
5562   , maximumCuts_(0)
5563   , lastNumberCuts_(NULL)
5564   , addedCuts_(NULL)
5565   , nextRowCut_(NULL)
5566   , currentNode_(NULL)
5567   , integerVariable_(NULL)
5568   , integerInfo_(NULL)
5569   , continuousSolution_(NULL)
5570   , usedInSolution_(NULL)
5571   , specialOptions_(0)
5572   , moreSpecialOptions_(0)
5573   , moreSpecialOptions2_(0)
5574   , topOfTree_(NULL)
5575   , subTreeModel_(NULL)
5576   , heuristicModel_(NULL)
5577   , numberStoppedSubTrees_(0)
5578   , presolve_(0)
5579   , numberStrong_(5)
5580   , numberBeforeTrust_(10)
5581   , numberPenalties_(20)
5582   , stopNumberIterations_(-1)
5583   , penaltyScaleFactor_(3.0)
5584   , numberAnalyzeIterations_(0)
5585   , analyzeResults_(NULL)
5586   , numberInfeasibleNodes_(0)
5587   , problemType_(0)
5588   , printFrequency_(0)
5589   , numberCutGenerators_(0)
5590   , generator_(NULL)
5591   , virginGenerator_(NULL)
5592   , numberHeuristics_(0)
5593   , heuristic_(NULL)
5594   , lastHeuristic_(NULL)
5595   , fastNodeDepth_(-1)
5596   , eventHandler_(NULL)
5597 #ifdef COIN_HAS_NTY
5598   , symmetryInfo_(NULL)
5599 #endif
5600   , numberObjects_(0)
5601   , object_(NULL)
5602   , ownObjects_(true)
5603   , originalColumns_(NULL)
5604   , howOftenGlobalScan_(3)
5605   , numberGlobalViolations_(0)
5606   , numberExtraIterations_(0)
5607   , numberExtraNodes_(0)
5608   , numberFathoms_(0)
5609   , continuousObjective_(COIN_DBL_MAX)
5610   , originalContinuousObjective_(COIN_DBL_MAX)
5611   , continuousInfeasibilities_(COIN_INT_MAX)
5612   , maximumCutPassesAtRoot_(20)
5613   , maximumCutPasses_(10)
5614   , preferredWay_(0)
5615   , currentPassNumber_(0)
5616   , maximumWhich_(INITIAL_MAXIMUM_WHICH)
5617   , maximumRows_(0)
5618   , randomSeed_(-1)
5619   , multipleRootTries_(0)
5620   , currentDepth_(0)
5621   , whichGenerator_(NULL)
5622   , maximumStatistics_(0)
5623   , statistics_(NULL)
5624   , maximumDepthActual_(0)
5625   , numberDJFixed_(0.0)
5626   , probingInfo_(NULL)
5627   , numberFixedAtRoot_(0)
5628   , numberFixedNow_(0)
5629   , stoppedOnGap_(false)
5630   , eventHappened_(false)
5631   , numberLongStrong_(0)
5632   , numberOldActiveCuts_(0)
5633   , numberNewCuts_(0)
5634   , searchStrategy_(-1)
5635   , strongStrategy_(0)
5636   , numberStrongIterations_(0)
5637   , resolveAfterTakeOffCuts_(true)
5638   , maximumNumberIterations_(-1)
5639   , continuousPriority_(COIN_INT_MAX)
5640   , numberUpdateItems_(0)
5641   , maximumNumberUpdateItems_(0)
5642   , updateItems_(NULL)
5643   , storedRowCuts_(NULL)
5644   , numberThreads_(0)
5645   , threadMode_(0)
5646   , numberGlobalCutsIn_(0)
5647   , master_(NULL)
5648   , masterThread_(NULL)
5649 {
5650   memset(intParam_, 0, sizeof(intParam_));
5651   intParam_[CbcMaxNumNode] = COIN_INT_MAX;
5652   intParam_[CbcMaxNumSol] = COIN_INT_MAX;
5653 
5654   memset(dblParam_, 0, sizeof(dblParam_));
5655   dblParam_[CbcIntegerTolerance] = 1e-7;
5656   dblParam_[CbcCutoffIncrement] = 1e-5;
5657   dblParam_[CbcAllowableGap] = 1.0e-10;
5658   dblParam_[CbcMaximumSeconds] = 1.0e100;
5659   dblParam_[CbcCurrentCutoff] = 1.0e100;
5660   dblParam_[CbcOptimizationDirection] = 1.0;
5661   dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
5662   dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
5663   strongInfo_[0] = 0;
5664   strongInfo_[1] = 0;
5665   strongInfo_[2] = 0;
5666   strongInfo_[3] = 0;
5667   strongInfo_[4] = 0;
5668   strongInfo_[5] = 0;
5669   strongInfo_[6] = 0;
5670   keepNamesPreproc = false;
5671   solverCharacteristics_ = NULL;
5672   nodeCompare_ = new CbcCompareDefault();
5673   problemFeasibility_ = new CbcFeasibilityBase();
5674   tree_ = new CbcTree();
5675   branchingMethod_ = NULL;
5676   cutModifier_ = NULL;
5677   strategy_ = NULL;
5678   parentModel_ = NULL;
5679   cbcColLower_ = NULL;
5680   cbcColUpper_ = NULL;
5681   cbcRowLower_ = NULL;
5682   cbcRowUpper_ = NULL;
5683   cbcColSolution_ = NULL;
5684   cbcRowPrice_ = NULL;
5685   cbcReducedCost_ = NULL;
5686   cbcRowActivity_ = NULL;
5687   appData_ = NULL;
5688   handler_ = new CoinMessageHandler();
5689   handler_->setLogLevel(2);
5690   messages_ = CbcMessage();
5691   //eventHandler_ = new CbcEventHandler() ;
5692 }
5693 
5694 /** Constructor from solver.
5695 
5696   Creates a model complete with a clone of the solver passed as a parameter.
5697 */
5698 
5699 CbcModel::CbcModel(const OsiSolverInterface &rhs)
5700   : ownership_(0x80000000)
5701   , continuousSolver_(NULL)
5702   , referenceSolver_(NULL)
5703   , defaultHandler_(true)
5704   , emptyWarmStart_(NULL)
5705   , bestObjective_(COIN_DBL_MAX)
5706   , bestPossibleObjective_(COIN_DBL_MAX)
5707   , sumChangeObjective1_(0.0)
5708   , sumChangeObjective2_(0.0)
5709   , globalConflictCuts_(NULL)
5710   , minimumDrop_(1.0e-7)
5711   , numberSolutions_(0)
5712   , numberSavedSolutions_(0)
5713   , maximumSavedSolutions_(0)
5714   , stateOfSearch_(0)
5715   , whenCuts_(-1)
5716   , hotstartSolution_(NULL)
5717   , hotstartPriorities_(NULL)
5718   , numberHeuristicSolutions_(0)
5719   , numberNodes_(0)
5720   , numberNodes2_(0)
5721   , numberIterations_(0)
5722   , numberSolves_(0)
5723   , status_(-1)
5724   , secondaryStatus_(-1)
5725   , numberRowsAtContinuous_(0)
5726   , cutoffRowNumber_(-1)
5727   , maximumNumberCuts_(0)
5728   , phase_(0)
5729   , currentNumberCuts_(0)
5730   , maximumDepth_(0)
5731   , walkback_(NULL)
5732   , preProcess_(NULL)
5733   , lastNodeInfo_(NULL)
5734   , lastCut_(NULL)
5735   , lastDepth_(0)
5736   , lastNumberCuts2_(0)
5737   , maximumCuts_(0)
5738   , lastNumberCuts_(NULL)
5739   , addedCuts_(NULL)
5740   , nextRowCut_(NULL)
5741   , currentNode_(NULL)
5742   , integerInfo_(NULL)
5743   , specialOptions_(0)
5744   , moreSpecialOptions_(0)
5745   , moreSpecialOptions2_(0)
5746   , topOfTree_(NULL)
5747   , subTreeModel_(NULL)
5748   , heuristicModel_(NULL)
5749   , numberStoppedSubTrees_(0)
5750   , presolve_(0)
5751   , numberStrong_(5)
5752   , numberBeforeTrust_(10)
5753   , numberPenalties_(20)
5754   , stopNumberIterations_(-1)
5755   , penaltyScaleFactor_(3.0)
5756   , numberAnalyzeIterations_(0)
5757   , analyzeResults_(NULL)
5758   , numberInfeasibleNodes_(0)
5759   , problemType_(0)
5760   , printFrequency_(0)
5761   , numberCutGenerators_(0)
5762   , generator_(NULL)
5763   , virginGenerator_(NULL)
5764   , numberHeuristics_(0)
5765   , heuristic_(NULL)
5766   , lastHeuristic_(NULL)
5767   , fastNodeDepth_(-1)
5768   , eventHandler_(NULL)
5769 #ifdef COIN_HAS_NTY
5770   , symmetryInfo_(NULL)
5771 #endif
5772   , numberObjects_(0)
5773   , object_(NULL)
5774   , ownObjects_(true)
5775   , originalColumns_(NULL)
5776   , howOftenGlobalScan_(3)
5777   , numberGlobalViolations_(0)
5778   , numberExtraIterations_(0)
5779   , numberExtraNodes_(0)
5780   , numberFathoms_(0)
5781   , continuousObjective_(COIN_DBL_MAX)
5782   , originalContinuousObjective_(COIN_DBL_MAX)
5783   , continuousInfeasibilities_(COIN_INT_MAX)
5784   , maximumCutPassesAtRoot_(20)
5785   , maximumCutPasses_(10)
5786   , preferredWay_(0)
5787   , currentPassNumber_(0)
5788   , maximumWhich_(INITIAL_MAXIMUM_WHICH)
5789   , maximumRows_(0)
5790   , randomSeed_(-1)
5791   , multipleRootTries_(0)
5792   , currentDepth_(0)
5793   , whichGenerator_(NULL)
5794   , maximumStatistics_(0)
5795   , statistics_(NULL)
5796   , maximumDepthActual_(0)
5797   , numberDJFixed_(0.0)
5798   , probingInfo_(NULL)
5799   , numberFixedAtRoot_(0)
5800   , numberFixedNow_(0)
5801   , stoppedOnGap_(false)
5802   , eventHappened_(false)
5803   , numberLongStrong_(0)
5804   , numberOldActiveCuts_(0)
5805   , numberNewCuts_(0)
5806   , searchStrategy_(-1)
5807   , strongStrategy_(0)
5808   , numberStrongIterations_(0)
5809   , resolveAfterTakeOffCuts_(true)
5810   , maximumNumberIterations_(-1)
5811   , continuousPriority_(COIN_INT_MAX)
5812   , numberUpdateItems_(0)
5813   , maximumNumberUpdateItems_(0)
5814   , updateItems_(NULL)
5815   , storedRowCuts_(NULL)
5816   , numberThreads_(0)
5817   , threadMode_(0)
5818   , numberGlobalCutsIn_(0)
5819   , master_(NULL)
5820   , masterThread_(NULL)
5821 {
5822   memset(intParam_, 0, sizeof(intParam_));
5823   intParam_[CbcMaxNumNode] = COIN_INT_MAX;
5824   intParam_[CbcMaxNumSol] = COIN_INT_MAX;
5825 
5826   memset(dblParam_, 0, sizeof(dblParam_));
5827   dblParam_[CbcIntegerTolerance] = 1e-7;
5828   dblParam_[CbcCutoffIncrement] = 1e-5;
5829   dblParam_[CbcAllowableGap] = 1.0e-10;
5830   dblParam_[CbcMaximumSeconds] = 1.0e100;
5831   dblParam_[CbcCurrentCutoff] = 1.0e100;
5832   dblParam_[CbcOptimizationDirection] = 1.0;
5833   dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
5834   dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
5835   strongInfo_[0] = 0;
5836   strongInfo_[1] = 0;
5837   strongInfo_[2] = 0;
5838   strongInfo_[3] = 0;
5839   strongInfo_[4] = 0;
5840   strongInfo_[5] = 0;
5841   strongInfo_[6] = 0;
5842   solverCharacteristics_ = NULL;
5843   keepNamesPreproc = false;
5844   nodeCompare_ = new CbcCompareDefault();
5845   problemFeasibility_ = new CbcFeasibilityBase();
5846   tree_ = new CbcTree();
5847   branchingMethod_ = NULL;
5848   cutModifier_ = NULL;
5849   strategy_ = NULL;
5850   parentModel_ = NULL;
5851   appData_ = NULL;
5852   solver_ = rhs.clone();
5853   ownership_ |= 0x80000000; // model now owns solver
5854   handler_ = new CoinMessageHandler();
5855   if (!solver_->defaultHandler() && solver_->messageHandler()->logLevel(0) != -1000)
5856     passInMessageHandler(solver_->messageHandler());
5857   handler_->setLogLevel(2);
5858   messages_ = CbcMessage();
5859   //eventHandler_ = new CbcEventHandler() ;
5860   referenceSolver_ = solver_->clone();
5861   ownership_ = 0x80000000;
5862   cbcColLower_ = NULL;
5863   cbcColUpper_ = NULL;
5864   cbcRowLower_ = NULL;
5865   cbcRowUpper_ = NULL;
5866   cbcColSolution_ = NULL;
5867   cbcRowPrice_ = NULL;
5868   cbcReducedCost_ = NULL;
5869   cbcRowActivity_ = NULL;
5870 
5871   // Initialize solution and integer variable vectors
5872   bestSolution_ = NULL; // to say no solution found
5873   savedSolutions_ = NULL;
5874   numberIntegers_ = 0;
5875   int numberColumns = solver_->getNumCols();
5876   int iColumn;
5877   if (numberColumns) {
5878     // Space for current solution
5879     currentSolution_ = new double[numberColumns];
5880     continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), numberColumns);
5881     usedInSolution_ = new int[numberColumns];
5882     CoinZeroN(usedInSolution_, numberColumns);
5883     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5884       if (solver_->isInteger(iColumn))
5885         numberIntegers_++;
5886     }
5887   } else {
5888     // empty model
5889     currentSolution_ = NULL;
5890     continuousSolution_ = NULL;
5891     usedInSolution_ = NULL;
5892   }
5893   testSolution_ = currentSolution_;
5894   if (numberIntegers_) {
5895     integerVariable_ = new int[numberIntegers_];
5896     numberIntegers_ = 0;
5897     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5898       if (solver_->isInteger(iColumn))
5899         integerVariable_[numberIntegers_++] = iColumn;
5900     }
5901   } else {
5902     integerVariable_ = NULL;
5903   }
5904 }
5905 
5906 static int *resizeInt(int *array, int oldLength, int newLength)
5907 {
5908   if (!array)
5909     return NULL;
5910   assert(newLength > oldLength);
5911   int *newArray = new int[newLength];
5912   memcpy(newArray, array, oldLength * sizeof(int));
5913   delete[] array;
5914   memset(newArray + oldLength, 0, (newLength - oldLength) * sizeof(int));
5915   return newArray;
5916 }
5917 static double *resizeDouble(double *array, int oldLength, int newLength)
5918 {
5919   if (!array)
5920     return NULL;
5921   assert(newLength > oldLength);
5922   double *newArray = new double[newLength];
5923   memcpy(newArray, array, oldLength * sizeof(double));
5924   delete[] array;
5925   memset(newArray + oldLength, 0, (newLength - oldLength) * sizeof(double));
5926   return newArray;
5927 }
5928 /*
5929   Assign a solver to the model (model assumes ownership)
5930 
5931   The integer variable vector is initialized if it's not already present.
5932   If deleteSolver then current solver deleted (if model owned)
5933 
5934   Assuming ownership matches usage in OsiSolverInterface
5935   (cf. assignProblem, loadProblem).
5936 
5937   TODO: What to do about solver parameters? A simple copy likely won't do it,
5938 	because the SI must push the settings into the underlying solver. In
5939 	the context of switching solvers in cbc, this means that command line
5940 	settings will get lost. Stash the command line somewhere and reread it
5941 	here, maybe?
5942 
5943   TODO: More generally, how much state should be transferred from the old
5944 	solver to the new solver? Best perhaps to see how usage develops.
5945 	What's done here mimics the CbcModel(OsiSolverInterface) constructor.
5946 */
5947 void CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver)
5948 
5949 {
5950   // resize stuff if exists
5951   if (solver && solver_) {
5952     int nOld = solver_->getNumCols();
5953     int nNew = solver->getNumCols();
5954     if (nNew > nOld) {
5955       originalColumns_ = resizeInt(originalColumns_, nOld, nNew);
5956       usedInSolution_ = resizeInt(usedInSolution_, nOld, nNew);
5957       continuousSolution_ = resizeDouble(continuousSolution_, nOld, nNew);
5958       hotstartSolution_ = resizeDouble(hotstartSolution_, nOld, nNew);
5959       bestSolution_ = resizeDouble(bestSolution_, nOld, nNew);
5960       currentSolution_ = resizeDouble(currentSolution_, nOld, nNew);
5961       if (savedSolutions_) {
5962         for (int i = 0; i < maximumSavedSolutions_; i++)
5963           savedSolutions_[i] = resizeDouble(savedSolutions_[i], nOld, nNew);
5964       }
5965     }
5966   }
5967   // Keep the current message level for solver (if solver exists)
5968   if (solver_)
5969     solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel());
5970 
5971   if (modelOwnsSolver() && deleteSolver) {
5972     solverCharacteristics_ = NULL;
5973     delete solver_;
5974   }
5975   solver_ = solver;
5976   solver = NULL;
5977   setModelOwnsSolver(true);
5978   /*
5979       Basis information is solver-specific.
5980     */
5981   if (emptyWarmStart_) {
5982     delete emptyWarmStart_;
5983     emptyWarmStart_ = 0;
5984   }
5985   bestSolutionBasis_ = CoinWarmStartBasis();
5986   /*
5987       Initialize integer variable vector.
5988     */
5989   numberIntegers_ = 0;
5990   int numberColumns = solver_->getNumCols();
5991   int iColumn;
5992   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5993     if (solver_->isInteger(iColumn))
5994       numberIntegers_++;
5995   }
5996   delete[] integerVariable_;
5997   if (numberIntegers_) {
5998     integerVariable_ = new int[numberIntegers_];
5999     numberIntegers_ = 0;
6000     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6001       if (solver_->isInteger(iColumn))
6002         integerVariable_[numberIntegers_++] = iColumn;
6003     }
6004   } else {
6005     integerVariable_ = NULL;
6006   }
6007 
6008   return;
6009 }
6010 
6011 // Cloning method
6012 
6013 CbcModel *CbcModel::clone(bool cloneHandler)
6014 {
6015   return new CbcModel(*this, cloneHandler);
6016 }
6017 
6018 // Copy constructor.
6019 
6020 CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler)
6021   : continuousSolver_(NULL)
6022   , referenceSolver_(NULL)
6023   , defaultHandler_(rhs.defaultHandler_)
6024   , emptyWarmStart_(NULL)
6025   , bestObjective_(rhs.bestObjective_)
6026   , bestPossibleObjective_(rhs.bestPossibleObjective_)
6027   , sumChangeObjective1_(rhs.sumChangeObjective1_)
6028   , sumChangeObjective2_(rhs.sumChangeObjective2_)
6029   , globalConflictCuts_(NULL)
6030   , minimumDrop_(rhs.minimumDrop_)
6031   , numberSolutions_(rhs.numberSolutions_)
6032   , numberSavedSolutions_(rhs.numberSavedSolutions_)
6033   , maximumSavedSolutions_(rhs.maximumSavedSolutions_)
6034   , stateOfSearch_(rhs.stateOfSearch_)
6035   , whenCuts_(rhs.whenCuts_)
6036   , numberHeuristicSolutions_(rhs.numberHeuristicSolutions_)
6037   , numberNodes_(rhs.numberNodes_)
6038   , numberNodes2_(rhs.numberNodes2_)
6039   , numberIterations_(rhs.numberIterations_)
6040   , numberSolves_(rhs.numberSolves_)
6041   , status_(rhs.status_)
6042   , secondaryStatus_(rhs.secondaryStatus_)
6043   , preProcess_(rhs.preProcess_)
6044   , specialOptions_(rhs.specialOptions_)
6045   , moreSpecialOptions_(rhs.moreSpecialOptions_)
6046   , moreSpecialOptions2_(rhs.moreSpecialOptions2_)
6047   , topOfTree_(NULL)
6048   , subTreeModel_(rhs.subTreeModel_)
6049   , heuristicModel_(NULL)
6050   , numberStoppedSubTrees_(rhs.numberStoppedSubTrees_)
6051   , presolve_(rhs.presolve_)
6052   , numberStrong_(rhs.numberStrong_)
6053   , numberBeforeTrust_(rhs.numberBeforeTrust_)
6054   , numberPenalties_(rhs.numberPenalties_)
6055   , stopNumberIterations_(rhs.stopNumberIterations_)
6056   , penaltyScaleFactor_(rhs.penaltyScaleFactor_)
6057   , numberAnalyzeIterations_(rhs.numberAnalyzeIterations_)
6058   , analyzeResults_(NULL)
6059   , numberInfeasibleNodes_(rhs.numberInfeasibleNodes_)
6060   , problemType_(rhs.problemType_)
6061   , printFrequency_(rhs.printFrequency_)
6062   , fastNodeDepth_(rhs.fastNodeDepth_)
6063   , howOftenGlobalScan_(rhs.howOftenGlobalScan_)
6064   , numberGlobalViolations_(rhs.numberGlobalViolations_)
6065   , numberExtraIterations_(rhs.numberExtraIterations_)
6066   , numberExtraNodes_(rhs.numberExtraNodes_)
6067   , numberFathoms_(rhs.numberFathoms_)
6068   , continuousObjective_(rhs.continuousObjective_)
6069   , originalContinuousObjective_(rhs.originalContinuousObjective_)
6070   , continuousInfeasibilities_(rhs.continuousInfeasibilities_)
6071   , maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_)
6072   , maximumCutPasses_(rhs.maximumCutPasses_)
6073   , preferredWay_(rhs.preferredWay_)
6074   , currentPassNumber_(rhs.currentPassNumber_)
6075   , maximumWhich_(rhs.maximumWhich_)
6076   , maximumRows_(0)
6077   , randomSeed_(rhs.randomSeed_)
6078   , multipleRootTries_(rhs.multipleRootTries_)
6079   , currentDepth_(0)
6080   , whichGenerator_(NULL)
6081   , maximumStatistics_(0)
6082   , statistics_(NULL)
6083   , maximumDepthActual_(0)
6084   , numberDJFixed_(0.0)
6085   , probingInfo_(NULL)
6086   , numberFixedAtRoot_(rhs.numberFixedAtRoot_)
6087   , numberFixedNow_(rhs.numberFixedNow_)
6088   , stoppedOnGap_(rhs.stoppedOnGap_)
6089   , eventHappened_(rhs.eventHappened_)
6090   , numberLongStrong_(rhs.numberLongStrong_)
6091   , numberOldActiveCuts_(rhs.numberOldActiveCuts_)
6092   , numberNewCuts_(rhs.numberNewCuts_)
6093   , searchStrategy_(rhs.searchStrategy_)
6094   , strongStrategy_(rhs.strongStrategy_)
6095   , numberStrongIterations_(rhs.numberStrongIterations_)
6096   , resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_)
6097   , maximumNumberIterations_(rhs.maximumNumberIterations_)
6098   , continuousPriority_(rhs.continuousPriority_)
6099   , numberUpdateItems_(rhs.numberUpdateItems_)
6100   , maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_)
6101   , updateItems_(NULL)
6102   , storedRowCuts_(NULL)
6103   , numberThreads_(rhs.numberThreads_)
6104   , threadMode_(rhs.threadMode_)
6105   , numberGlobalCutsIn_(rhs.numberGlobalCutsIn_)
6106   , master_(NULL)
6107   , masterThread_(NULL)
6108 {
6109   memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
6110   memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
6111   strongInfo_[0] = rhs.strongInfo_[0];
6112   strongInfo_[1] = rhs.strongInfo_[1];
6113   strongInfo_[2] = rhs.strongInfo_[2];
6114   strongInfo_[3] = rhs.strongInfo_[3];
6115   strongInfo_[4] = rhs.strongInfo_[4];
6116   strongInfo_[5] = rhs.strongInfo_[5];
6117   strongInfo_[6] = rhs.strongInfo_[6];
6118   keepNamesPreproc = rhs.keepNamesPreproc;
6119   solverCharacteristics_ = NULL;
6120   if (rhs.emptyWarmStart_)
6121     emptyWarmStart_ = rhs.emptyWarmStart_->clone();
6122   if (defaultHandler_ || cloneHandler) {
6123     handler_ = new CoinMessageHandler();
6124     handler_->setLogLevel(2);
6125   } else {
6126     handler_ = rhs.handler_;
6127   }
6128   messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
6129   numberCutGenerators_ = rhs.numberCutGenerators_;
6130   if (numberCutGenerators_) {
6131     generator_ = new CbcCutGenerator *[numberCutGenerators_];
6132     virginGenerator_ = new CbcCutGenerator *[numberCutGenerators_];
6133     int i;
6134     for (i = 0; i < numberCutGenerators_; i++) {
6135       generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
6136       virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
6137     }
6138   } else {
6139     generator_ = NULL;
6140     virginGenerator_ = NULL;
6141   }
6142   globalCuts_ = rhs.globalCuts_;
6143   numberHeuristics_ = rhs.numberHeuristics_;
6144   if (numberHeuristics_) {
6145     heuristic_ = new CbcHeuristic *[numberHeuristics_];
6146     int i;
6147     for (i = 0; i < numberHeuristics_; i++) {
6148       heuristic_[i] = rhs.heuristic_[i]->clone();
6149     }
6150   } else {
6151     heuristic_ = NULL;
6152   }
6153   lastHeuristic_ = NULL;
6154   if (rhs.eventHandler_) {
6155     eventHandler_ = rhs.eventHandler_->clone();
6156   } else {
6157     eventHandler_ = NULL;
6158   }
6159   ownObjects_ = rhs.ownObjects_;
6160   if (ownObjects_) {
6161     numberObjects_ = rhs.numberObjects_;
6162     if (numberObjects_) {
6163       object_ = new OsiObject *[numberObjects_];
6164       int i;
6165       for (i = 0; i < numberObjects_; i++) {
6166         object_[i] = (rhs.object_[i])->clone();
6167         CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]);
6168         // Could be OsiObjects
6169         if (obj)
6170           obj->setModel(this);
6171       }
6172     } else {
6173       object_ = NULL;
6174     }
6175   } else {
6176     // assume will be redone
6177     numberObjects_ = 0;
6178     object_ = NULL;
6179   }
6180   if (rhs.continuousSolver_) {
6181     continuousSolver_ = rhs.continuousSolver_->clone();
6182   } else {
6183     continuousSolver_ = NULL;
6184   }
6185   if (rhs.referenceSolver_)
6186     referenceSolver_ = rhs.referenceSolver_->clone();
6187   else
6188     referenceSolver_ = NULL;
6189   solver_ = rhs.solver_->clone();
6190   if (rhs.originalColumns_) {
6191     int numberColumns = solver_->getNumCols();
6192     originalColumns_ = new int[numberColumns];
6193     memcpy(originalColumns_, rhs.originalColumns_, numberColumns * sizeof(int));
6194   } else {
6195     originalColumns_ = NULL;
6196   }
6197   if (maximumNumberUpdateItems_) {
6198     updateItems_ = new CbcObjectUpdateData[maximumNumberUpdateItems_];
6199     for (int i = 0; i < maximumNumberUpdateItems_; i++)
6200       updateItems_[i] = rhs.updateItems_[i];
6201   }
6202   if (maximumWhich_ && rhs.whichGenerator_)
6203     whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_, maximumWhich_);
6204   nodeCompare_ = rhs.nodeCompare_->clone();
6205   problemFeasibility_ = rhs.problemFeasibility_->clone();
6206   tree_ = rhs.tree_->clone();
6207   if (rhs.branchingMethod_)
6208     branchingMethod_ = rhs.branchingMethod_->clone();
6209   else
6210     branchingMethod_ = NULL;
6211   if (rhs.cutModifier_)
6212     cutModifier_ = rhs.cutModifier_->clone();
6213   else
6214     cutModifier_ = NULL;
6215   cbcColLower_ = NULL;
6216   cbcColUpper_ = NULL;
6217   cbcRowLower_ = NULL;
6218   cbcRowUpper_ = NULL;
6219   cbcColSolution_ = NULL;
6220   cbcRowPrice_ = NULL;
6221   cbcReducedCost_ = NULL;
6222   cbcRowActivity_ = NULL;
6223   if (rhs.strategy_)
6224     strategy_ = rhs.strategy_->clone();
6225   else
6226     strategy_ = NULL;
6227   parentModel_ = rhs.parentModel_;
6228   appData_ = rhs.appData_;
6229   messages_ = rhs.messages_;
6230   ownership_ = rhs.ownership_ | 0x80000000;
6231   messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
6232   numberIntegers_ = rhs.numberIntegers_;
6233   randomNumberGenerator_ = rhs.randomNumberGenerator_;
6234   if (numberIntegers_) {
6235     integerVariable_ = new int[numberIntegers_];
6236     memcpy(integerVariable_, rhs.integerVariable_, numberIntegers_ * sizeof(int));
6237     integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, solver_->getNumCols());
6238   } else {
6239     integerVariable_ = NULL;
6240     integerInfo_ = NULL;
6241   }
6242   if (rhs.hotstartSolution_) {
6243     int numberColumns = solver_->getNumCols();
6244     hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns);
6245     hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns);
6246   } else {
6247     hotstartSolution_ = NULL;
6248     hotstartPriorities_ = NULL;
6249   }
6250   if (rhs.bestSolution_) {
6251     int numberColumns = solver_->getNumCols();
6252     bestSolution_ = new double[numberColumns];
6253     memcpy(bestSolution_, rhs.bestSolution_, numberColumns * sizeof(double));
6254   } else {
6255     bestSolution_ = NULL;
6256   }
6257   int numberColumns = solver_->getNumCols();
6258   if (maximumSavedSolutions_ && rhs.savedSolutions_) {
6259     savedSolutions_ = new double *[maximumSavedSolutions_];
6260     for (int i = 0; i < maximumSavedSolutions_; i++)
6261       savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2);
6262   } else {
6263     savedSolutions_ = NULL;
6264   }
6265   // Space for current solution
6266   if (numberColumns) {
6267     currentSolution_ = new double[numberColumns];
6268     continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), numberColumns);
6269     usedInSolution_ = new int[numberColumns];
6270     CoinZeroN(usedInSolution_, numberColumns);
6271   } else {
6272     currentSolution_ = NULL;
6273     continuousSolution_ = NULL;
6274     usedInSolution_ = NULL;
6275   }
6276   testSolution_ = currentSolution_;
6277   numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
6278   cutoffRowNumber_ = rhs.cutoffRowNumber_;
6279   maximumNumberCuts_ = rhs.maximumNumberCuts_;
6280   phase_ = rhs.phase_;
6281   currentNumberCuts_ = rhs.currentNumberCuts_;
6282   maximumDepth_ = rhs.maximumDepth_;
6283   // These are only used as temporary arrays so need not be filled
6284   if (maximumNumberCuts_) {
6285     addedCuts_ = new CbcCountRowCut *[maximumNumberCuts_];
6286   } else {
6287     addedCuts_ = NULL;
6288   }
6289   bestSolutionBasis_ = rhs.bestSolutionBasis_;
6290   nextRowCut_ = NULL;
6291   currentNode_ = NULL;
6292   if (maximumDepth_) {
6293     walkback_ = new CbcNodeInfo *[maximumDepth_];
6294     lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_];
6295     lastNumberCuts_ = new int[maximumDepth_];
6296   } else {
6297     walkback_ = NULL;
6298     lastNodeInfo_ = NULL;
6299     lastNumberCuts_ = NULL;
6300   }
6301   maximumCuts_ = rhs.maximumCuts_;
6302   if (maximumCuts_) {
6303     lastCut_ = new const OsiRowCut *[maximumCuts_];
6304   } else {
6305     lastCut_ = NULL;
6306   }
6307 #ifdef COIN_HAS_NTY
6308   if (rhs.symmetryInfo_)
6309     symmetryInfo_ = new CbcSymmetry(*rhs.symmetryInfo_);
6310   else
6311     symmetryInfo_ = NULL;
6312 #endif
6313   synchronizeModel();
6314   if (cloneHandler && !defaultHandler_) {
6315     delete handler_;
6316     /* We have to clone handlers - otherwise will all be
6317 	   writing to same buffer.  So if threads user will
6318 	   have to sychronize */
6319     CoinMessageHandler *handler = rhs.handler_->clone();
6320     passInMessageHandler(handler);
6321     defaultHandler_ = true;
6322   }
6323 }
6324 
6325 // Assignment operator
6326 CbcModel &
6327 CbcModel::operator=(const CbcModel &rhs)
6328 {
6329   if (this != &rhs) {
6330     if (modelOwnsSolver()) {
6331       solverCharacteristics_ = NULL;
6332       delete solver_;
6333       solver_ = NULL;
6334     }
6335     gutsOfDestructor();
6336     if (defaultHandler_) {
6337       delete handler_;
6338       handler_ = NULL;
6339     }
6340     defaultHandler_ = rhs.defaultHandler_;
6341     if (defaultHandler_) {
6342       handler_ = new CoinMessageHandler();
6343       handler_->setLogLevel(2);
6344     } else {
6345       handler_ = rhs.handler_;
6346     }
6347     messages_ = rhs.messages_;
6348     messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
6349     if (rhs.solver_) {
6350       solver_ = rhs.solver_->clone();
6351     } else {
6352       solver_ = 0;
6353     }
6354     ownership_ = 0x80000000;
6355     delete continuousSolver_;
6356     if (rhs.continuousSolver_) {
6357       continuousSolver_ = rhs.continuousSolver_->clone();
6358     } else {
6359       continuousSolver_ = 0;
6360     }
6361     delete referenceSolver_;
6362     if (rhs.referenceSolver_) {
6363       referenceSolver_ = rhs.referenceSolver_->clone();
6364     } else {
6365       referenceSolver_ = NULL;
6366     }
6367 
6368     delete emptyWarmStart_;
6369     if (rhs.emptyWarmStart_) {
6370       emptyWarmStart_ = rhs.emptyWarmStart_->clone();
6371     } else {
6372       emptyWarmStart_ = 0;
6373     }
6374 
6375     bestObjective_ = rhs.bestObjective_;
6376     bestPossibleObjective_ = rhs.bestPossibleObjective_;
6377     sumChangeObjective1_ = rhs.sumChangeObjective1_;
6378     sumChangeObjective2_ = rhs.sumChangeObjective2_;
6379     delete[] bestSolution_;
6380     if (rhs.bestSolution_) {
6381       int numberColumns = rhs.getNumCols();
6382       bestSolution_ = new double[numberColumns];
6383       memcpy(bestSolution_, rhs.bestSolution_, numberColumns * sizeof(double));
6384     } else {
6385       bestSolution_ = NULL;
6386     }
6387     for (int i = 0; i < maximumSavedSolutions_; i++)
6388       delete[] savedSolutions_[i];
6389     delete[] savedSolutions_;
6390     savedSolutions_ = NULL;
6391     int numberColumns = rhs.getNumCols();
6392     if (numberColumns) {
6393       // Space for current solution
6394       currentSolution_ = new double[numberColumns];
6395       continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), numberColumns);
6396       usedInSolution_ = new int[numberColumns];
6397       CoinZeroN(usedInSolution_, numberColumns);
6398     } else {
6399       currentSolution_ = NULL;
6400       continuousSolution_ = NULL;
6401       usedInSolution_ = NULL;
6402     }
6403     if (maximumSavedSolutions_) {
6404       savedSolutions_ = new double *[maximumSavedSolutions_];
6405       for (int i = 0; i < maximumSavedSolutions_; i++)
6406         savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2);
6407     } else {
6408       savedSolutions_ = NULL;
6409     }
6410     testSolution_ = currentSolution_;
6411     minimumDrop_ = rhs.minimumDrop_;
6412     numberSolutions_ = rhs.numberSolutions_;
6413     numberSavedSolutions_ = rhs.numberSavedSolutions_;
6414     maximumSavedSolutions_ = rhs.maximumSavedSolutions_;
6415     stateOfSearch_ = rhs.stateOfSearch_;
6416     whenCuts_ = rhs.whenCuts_;
6417     numberHeuristicSolutions_ = rhs.numberHeuristicSolutions_;
6418     numberNodes_ = rhs.numberNodes_;
6419     numberNodes2_ = rhs.numberNodes2_;
6420     numberIterations_ = rhs.numberIterations_;
6421     numberSolves_ = rhs.numberSolves_;
6422     status_ = rhs.status_;
6423     secondaryStatus_ = rhs.secondaryStatus_;
6424     specialOptions_ = rhs.specialOptions_;
6425     moreSpecialOptions_ = rhs.moreSpecialOptions_;
6426     moreSpecialOptions2_ = rhs.moreSpecialOptions2_;
6427     subTreeModel_ = rhs.subTreeModel_;
6428     heuristicModel_ = NULL;
6429     numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
6430     presolve_ = rhs.presolve_;
6431     numberStrong_ = rhs.numberStrong_;
6432     numberBeforeTrust_ = rhs.numberBeforeTrust_;
6433     numberPenalties_ = rhs.numberPenalties_;
6434     stopNumberIterations_ = rhs.stopNumberIterations_;
6435     penaltyScaleFactor_ = rhs.penaltyScaleFactor_;
6436     numberAnalyzeIterations_ = rhs.numberAnalyzeIterations_;
6437     delete[] analyzeResults_;
6438     analyzeResults_ = NULL;
6439     numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_;
6440     problemType_ = rhs.problemType_;
6441     printFrequency_ = rhs.printFrequency_;
6442     howOftenGlobalScan_ = rhs.howOftenGlobalScan_;
6443     numberGlobalViolations_ = rhs.numberGlobalViolations_;
6444     numberExtraIterations_ = rhs.numberExtraIterations_;
6445     numberExtraNodes_ = rhs.numberExtraNodes_;
6446     preProcess_ = rhs.preProcess_;
6447     numberFathoms_ = rhs.numberFathoms_;
6448     continuousObjective_ = rhs.continuousObjective_;
6449     originalContinuousObjective_ = rhs.originalContinuousObjective_;
6450     continuousInfeasibilities_ = rhs.continuousInfeasibilities_;
6451     maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_;
6452     maximumCutPasses_ = rhs.maximumCutPasses_;
6453     randomSeed_ = rhs.randomSeed_;
6454     multipleRootTries_ = rhs.multipleRootTries_;
6455     preferredWay_ = rhs.preferredWay_;
6456     currentPassNumber_ = rhs.currentPassNumber_;
6457     memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
6458     memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
6459     globalCuts_ = rhs.globalCuts_;
6460     delete globalConflictCuts_;
6461     globalConflictCuts_ = NULL;
6462     int i;
6463     for (i = 0; i < numberCutGenerators_; i++) {
6464       delete generator_[i];
6465       delete virginGenerator_[i];
6466     }
6467     delete[] generator_;
6468     delete[] virginGenerator_;
6469     delete[] heuristic_;
6470     maximumWhich_ = rhs.maximumWhich_;
6471     delete[] whichGenerator_;
6472     whichGenerator_ = NULL;
6473     if (maximumWhich_ && rhs.whichGenerator_)
6474       whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_, maximumWhich_);
6475     maximumRows_ = 0;
6476     currentDepth_ = 0;
6477     randomNumberGenerator_ = rhs.randomNumberGenerator_;
6478     workingBasis_ = CoinWarmStartBasis();
6479     for (i = 0; i < maximumStatistics_; i++)
6480       delete statistics_[i];
6481     delete[] statistics_;
6482     maximumStatistics_ = 0;
6483     statistics_ = NULL;
6484     delete probingInfo_;
6485     probingInfo_ = NULL;
6486     numberFixedAtRoot_ = rhs.numberFixedAtRoot_;
6487     numberFixedNow_ = rhs.numberFixedNow_;
6488     stoppedOnGap_ = rhs.stoppedOnGap_;
6489     eventHappened_ = rhs.eventHappened_;
6490     numberLongStrong_ = rhs.numberLongStrong_;
6491     numberOldActiveCuts_ = rhs.numberOldActiveCuts_;
6492     numberNewCuts_ = rhs.numberNewCuts_;
6493     resolveAfterTakeOffCuts_ = rhs.resolveAfterTakeOffCuts_;
6494     maximumNumberIterations_ = rhs.maximumNumberIterations_;
6495     continuousPriority_ = rhs.continuousPriority_;
6496     numberUpdateItems_ = rhs.numberUpdateItems_;
6497     maximumNumberUpdateItems_ = rhs.maximumNumberUpdateItems_;
6498     delete[] updateItems_;
6499     if (maximumNumberUpdateItems_) {
6500       updateItems_ = new CbcObjectUpdateData[maximumNumberUpdateItems_];
6501       for (i = 0; i < maximumNumberUpdateItems_; i++)
6502         updateItems_[i] = rhs.updateItems_[i];
6503     } else {
6504       updateItems_ = NULL;
6505     }
6506     numberThreads_ = rhs.numberThreads_;
6507     threadMode_ = rhs.threadMode_;
6508     numberGlobalCutsIn_ = rhs.numberGlobalCutsIn_;
6509     delete master_;
6510     master_ = NULL;
6511     masterThread_ = NULL;
6512     searchStrategy_ = rhs.searchStrategy_;
6513     strongStrategy_ = rhs.strongStrategy_;
6514     numberStrongIterations_ = rhs.numberStrongIterations_;
6515     strongInfo_[0] = rhs.strongInfo_[0];
6516     strongInfo_[1] = rhs.strongInfo_[1];
6517     strongInfo_[2] = rhs.strongInfo_[2];
6518     strongInfo_[3] = rhs.strongInfo_[3];
6519     strongInfo_[4] = rhs.strongInfo_[4];
6520     strongInfo_[5] = rhs.strongInfo_[5];
6521     strongInfo_[6] = rhs.strongInfo_[6];
6522     solverCharacteristics_ = NULL;
6523     lastHeuristic_ = NULL;
6524     numberCutGenerators_ = rhs.numberCutGenerators_;
6525     if (numberCutGenerators_) {
6526       generator_ = new CbcCutGenerator *[numberCutGenerators_];
6527       virginGenerator_ = new CbcCutGenerator *[numberCutGenerators_];
6528       int i;
6529       for (i = 0; i < numberCutGenerators_; i++) {
6530         generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
6531         virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
6532       }
6533     } else {
6534       generator_ = NULL;
6535       virginGenerator_ = NULL;
6536     }
6537     numberHeuristics_ = rhs.numberHeuristics_;
6538     if (numberHeuristics_) {
6539       heuristic_ = new CbcHeuristic *[numberHeuristics_];
6540       memcpy(heuristic_, rhs.heuristic_,
6541         numberHeuristics_ * sizeof(CbcHeuristic *));
6542     } else {
6543       heuristic_ = NULL;
6544     }
6545     lastHeuristic_ = NULL;
6546     if (eventHandler_)
6547       delete eventHandler_;
6548     if (rhs.eventHandler_) {
6549       eventHandler_ = rhs.eventHandler_->clone();
6550     } else {
6551       eventHandler_ = NULL;
6552     }
6553     fastNodeDepth_ = rhs.fastNodeDepth_;
6554     if (ownObjects_) {
6555       for (i = 0; i < numberObjects_; i++)
6556         delete object_[i];
6557       delete[] object_;
6558       numberObjects_ = rhs.numberObjects_;
6559       if (numberObjects_) {
6560         object_ = new OsiObject *[numberObjects_];
6561         int i;
6562         for (i = 0; i < numberObjects_; i++)
6563           object_[i] = (rhs.object_[i])->clone();
6564       } else {
6565         object_ = NULL;
6566       }
6567     } else {
6568       // assume will be redone
6569       numberObjects_ = 0;
6570       object_ = NULL;
6571     }
6572     delete[] originalColumns_;
6573     if (rhs.originalColumns_) {
6574       int numberColumns = rhs.getNumCols();
6575       originalColumns_ = new int[numberColumns];
6576       memcpy(originalColumns_, rhs.originalColumns_, numberColumns * sizeof(int));
6577     } else {
6578       originalColumns_ = NULL;
6579     }
6580     nodeCompare_ = rhs.nodeCompare_->clone();
6581     problemFeasibility_ = rhs.problemFeasibility_->clone();
6582     delete tree_;
6583     tree_ = rhs.tree_->clone();
6584     if (rhs.branchingMethod_)
6585       branchingMethod_ = rhs.branchingMethod_->clone();
6586     else
6587       branchingMethod_ = NULL;
6588     if (rhs.cutModifier_)
6589       cutModifier_ = rhs.cutModifier_->clone();
6590     else
6591       cutModifier_ = NULL;
6592 
6593     if (strategy_)
6594         delete strategy_;
6595     if (rhs.strategy_)
6596       strategy_ = rhs.strategy_->clone();
6597     else
6598       strategy_ = NULL;
6599     parentModel_ = rhs.parentModel_;
6600     appData_ = rhs.appData_;
6601 
6602     delete[] integerVariable_;
6603     numberIntegers_ = rhs.numberIntegers_;
6604     if (numberIntegers_) {
6605       integerVariable_ = new int[numberIntegers_];
6606       memcpy(integerVariable_, rhs.integerVariable_,
6607         numberIntegers_ * sizeof(int));
6608       integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, rhs.getNumCols());
6609     } else {
6610       integerVariable_ = NULL;
6611       integerInfo_ = NULL;
6612     }
6613     if (rhs.hotstartSolution_) {
6614       int numberColumns = solver_->getNumCols();
6615       hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns);
6616       hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns);
6617     } else {
6618       hotstartSolution_ = NULL;
6619       hotstartPriorities_ = NULL;
6620     }
6621     numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
6622     cutoffRowNumber_ = rhs.cutoffRowNumber_;
6623     maximumNumberCuts_ = rhs.maximumNumberCuts_;
6624     phase_ = rhs.phase_;
6625     currentNumberCuts_ = rhs.currentNumberCuts_;
6626     maximumDepth_ = rhs.maximumDepth_;
6627     keepNamesPreproc = rhs.keepNamesPreproc;
6628     mipStart_ = rhs.mipStart_;
6629     delete[] addedCuts_;
6630     delete[] walkback_;
6631     // These are only used as temporary arrays so need not be filled
6632     if (maximumNumberCuts_) {
6633       addedCuts_ = new CbcCountRowCut *[maximumNumberCuts_];
6634     } else {
6635       addedCuts_ = NULL;
6636     }
6637     delete[] lastNodeInfo_;
6638     delete[] lastNumberCuts_;
6639     delete[] lastCut_;
6640     bestSolutionBasis_ = rhs.bestSolutionBasis_;
6641     nextRowCut_ = NULL;
6642     currentNode_ = NULL;
6643     if (maximumDepth_) {
6644       walkback_ = new CbcNodeInfo *[maximumDepth_];
6645       lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_];
6646       lastNumberCuts_ = new int[maximumDepth_];
6647     } else {
6648       walkback_ = NULL;
6649       lastNodeInfo_ = NULL;
6650       lastNumberCuts_ = NULL;
6651     }
6652     maximumCuts_ = rhs.maximumCuts_;
6653     if (maximumCuts_) {
6654       lastCut_ = new const OsiRowCut *[maximumCuts_];
6655     } else {
6656       lastCut_ = NULL;
6657     }
6658 #ifdef COIN_HAS_NTY
6659     if (rhs.symmetryInfo_)
6660       symmetryInfo_ = new CbcSymmetry(*rhs.symmetryInfo_);
6661     else
6662       symmetryInfo_ = NULL;
6663 #endif
6664     synchronizeModel();
6665     cbcColLower_ = NULL;
6666     cbcColUpper_ = NULL;
6667     cbcRowLower_ = NULL;
6668     cbcRowUpper_ = NULL;
6669     cbcColSolution_ = NULL;
6670     cbcRowPrice_ = NULL;
6671     cbcReducedCost_ = NULL;
6672     cbcRowActivity_ = NULL;
6673   }
6674   return *this;
6675 }
6676 // Destructor
6677 CbcModel::~CbcModel()
6678 {
6679   if (defaultHandler_) {
6680     delete handler_;
6681     handler_ = NULL;
6682   }
6683   delete tree_;
6684   tree_ = NULL;
6685   if (modelOwnsSolver()) {
6686     delete solver_;
6687     solver_ = NULL;
6688   }
6689   gutsOfDestructor();
6690   delete eventHandler_;
6691   eventHandler_ = NULL;
6692 #ifdef CBC_THREAD
6693   // Get rid of all threaded stuff
6694   delete master_;
6695 #endif
6696 }
6697 // Clears out as much as possible (except solver)
6698 void CbcModel::gutsOfDestructor()
6699 {
6700   delete referenceSolver_;
6701   referenceSolver_ = NULL;
6702   int i;
6703   for (i = 0; i < numberCutGenerators_; i++) {
6704     delete generator_[i];
6705     delete virginGenerator_[i];
6706   }
6707   delete[] generator_;
6708   delete[] virginGenerator_;
6709   generator_ = NULL;
6710   virginGenerator_ = NULL;
6711   for (i = 0; i < numberHeuristics_; i++)
6712     delete heuristic_[i];
6713   delete[] heuristic_;
6714   heuristic_ = NULL;
6715   delete nodeCompare_;
6716   nodeCompare_ = NULL;
6717   delete problemFeasibility_;
6718   problemFeasibility_ = NULL;
6719   delete[] originalColumns_;
6720   originalColumns_ = NULL;
6721   delete strategy_;
6722   delete[] updateItems_;
6723   updateItems_ = NULL;
6724   numberUpdateItems_ = 0;
6725   maximumNumberUpdateItems_ = 0;
6726   gutsOfDestructor2();
6727 }
6728 // Clears out enough to reset CbcModel
6729 void CbcModel::gutsOfDestructor2()
6730 {
6731   delete[] integerInfo_;
6732   integerInfo_ = NULL;
6733   delete[] integerVariable_;
6734   integerVariable_ = NULL;
6735   int i;
6736   if (ownObjects_) {
6737     for (i = 0; i < numberObjects_; i++)
6738       delete object_[i];
6739     delete[] object_;
6740   }
6741   ownObjects_ = true;
6742   object_ = NULL;
6743   numberIntegers_ = 0;
6744   numberObjects_ = 0;
6745   // Below here is whatever consensus is
6746   ownership_ = 0x80000000;
6747   delete branchingMethod_;
6748   branchingMethod_ = NULL;
6749   delete cutModifier_;
6750   cutModifier_ = NULL;
6751   topOfTree_ = NULL;
6752   resetModel();
6753 #ifdef COIN_HAS_NTY
6754   delete symmetryInfo_;
6755   symmetryInfo_ = NULL;
6756 #endif
6757 }
6758 // Clears out enough to reset CbcModel
6759 void CbcModel::resetModel()
6760 {
6761   delete emptyWarmStart_;
6762   emptyWarmStart_ = NULL;
6763   delete continuousSolver_;
6764   continuousSolver_ = NULL;
6765   numberSavedSolutions_ = 0;
6766   delete[] bestSolution_;
6767   bestSolution_ = NULL;
6768   if (savedSolutions_) {
6769     for (int i = 0; i < maximumSavedSolutions_; i++)
6770       delete[] savedSolutions_[i];
6771     delete[] savedSolutions_;
6772     savedSolutions_ = NULL;
6773   }
6774   delete[] currentSolution_;
6775   currentSolution_ = NULL;
6776   delete[] continuousSolution_;
6777   continuousSolution_ = NULL;
6778   solverCharacteristics_ = NULL;
6779   delete[] usedInSolution_;
6780   usedInSolution_ = NULL;
6781   testSolution_ = NULL;
6782   lastHeuristic_ = NULL;
6783   delete[] addedCuts_;
6784   addedCuts_ = NULL;
6785   nextRowCut_ = NULL;
6786   currentNode_ = NULL;
6787   delete[] walkback_;
6788   walkback_ = NULL;
6789   delete[] lastNodeInfo_;
6790   lastNodeInfo_ = NULL;
6791   delete[] lastNumberCuts_;
6792   lastNumberCuts_ = NULL;
6793   delete[] lastCut_;
6794   lastCut_ = NULL;
6795   delete[] whichGenerator_;
6796   whichGenerator_ = NULL;
6797   for (int i = 0; i < maximumStatistics_; i++)
6798     delete statistics_[i];
6799   delete[] statistics_;
6800   statistics_ = NULL;
6801   maximumDepthActual_ = 0;
6802   numberDJFixed_ = 0.0;
6803   if (probingInfo_) {
6804     delete probingInfo_;
6805     probingInfo_ = NULL;
6806     if (!generator_)
6807       numberCutGenerators_ = 0;
6808     // also get rid of cut generator
6809     int n = 0;
6810     for (int i = 0; i < numberCutGenerators_; i++) {
6811       CglImplication *cutGen;
6812       cutGen = dynamic_cast< CglImplication * >(generator_[i]->generator());
6813       if (!cutGen) {
6814         generator_[n] = generator_[i];
6815         virginGenerator_[n] = virginGenerator_[i];
6816         n++;
6817       } else {
6818         cutGen->setProbingInfo(NULL);
6819         delete generator_[i];
6820         cutGen = dynamic_cast< CglImplication * >(virginGenerator_[i]->generator());
6821         assert(cutGen);
6822         cutGen->setProbingInfo(NULL);
6823         delete virginGenerator_[i];
6824       }
6825     }
6826     numberCutGenerators_ = n;
6827   }
6828   maximumStatistics_ = 0;
6829   delete[] analyzeResults_;
6830   analyzeResults_ = NULL;
6831   bestObjective_ = COIN_DBL_MAX;
6832   bestPossibleObjective_ = COIN_DBL_MAX;
6833   sumChangeObjective1_ = 0.0;
6834   sumChangeObjective2_ = 0.0;
6835   numberSolutions_ = 0;
6836   stateOfSearch_ = 0;
6837   delete[] hotstartSolution_;
6838   hotstartSolution_ = NULL;
6839   delete[] hotstartPriorities_;
6840   hotstartPriorities_ = NULL;
6841   numberHeuristicSolutions_ = 0;
6842   numberNodes_ = 0;
6843   numberNodes2_ = 0;
6844   numberIterations_ = 0;
6845   numberSolves_ = 0;
6846   status_ = -1;
6847   secondaryStatus_ = -1;
6848   maximumNumberCuts_ = 0;
6849   phase_ = 0;
6850   currentNumberCuts_ = 0;
6851   maximumDepth_ = 0;
6852   nextRowCut_ = NULL;
6853   currentNode_ = NULL;
6854   // clear out tree
6855   if (tree_ && tree_->size())
6856     tree_->cleanTree(this, -1.0e100, bestPossibleObjective_);
6857   subTreeModel_ = NULL;
6858   heuristicModel_ = NULL;
6859   numberStoppedSubTrees_ = 0;
6860   numberInfeasibleNodes_ = 0;
6861   numberGlobalViolations_ = 0;
6862   numberExtraIterations_ = 0;
6863   numberExtraNodes_ = 0;
6864   numberFathoms_ = 0;
6865   continuousObjective_ = 0.0;
6866   originalContinuousObjective_ = 0.0;
6867   continuousInfeasibilities_ = 0;
6868   numberFixedAtRoot_ = 0;
6869   numberFixedNow_ = 0;
6870   stoppedOnGap_ = false;
6871   eventHappened_ = false;
6872   numberLongStrong_ = 0;
6873   numberOldActiveCuts_ = 0;
6874   numberNewCuts_ = 0;
6875   searchStrategy_ = -1;
6876   strongStrategy_ = 0;
6877   numberStrongIterations_ = 0;
6878   // Parameters which need to be reset
6879   setCutoff(COIN_DBL_MAX);
6880   dblParam_[CbcCutoffIncrement] = 1e-5;
6881   dblParam_[CbcCurrentCutoff] = 1.0e100;
6882   dblParam_[CbcCurrentObjectiveValue] = 1.0e100;
6883   dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100;
6884   delete globalConflictCuts_;
6885   globalConflictCuts_ = NULL;
6886 }
6887 /* Most of copy constructor
6888       mode - 0 copy but don't delete before
6889              1 copy and delete before
6890 	     2 copy and delete before (but use virgin generators)
6891 */
6892 void CbcModel::gutsOfCopy(const CbcModel &rhs, int mode)
6893 {
6894   minimumDrop_ = rhs.minimumDrop_;
6895   specialOptions_ = rhs.specialOptions_;
6896   moreSpecialOptions_ = rhs.moreSpecialOptions_;
6897   moreSpecialOptions2_ = rhs.moreSpecialOptions2_;
6898   numberStrong_ = rhs.numberStrong_;
6899   numberBeforeTrust_ = rhs.numberBeforeTrust_;
6900   numberPenalties_ = rhs.numberPenalties_;
6901   printFrequency_ = rhs.printFrequency_;
6902   fastNodeDepth_ = rhs.fastNodeDepth_;
6903   howOftenGlobalScan_ = rhs.howOftenGlobalScan_;
6904   maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_;
6905   maximumCutPasses_ = rhs.maximumCutPasses_;
6906   randomSeed_ = rhs.randomSeed_;
6907   multipleRootTries_ = rhs.multipleRootTries_;
6908   preferredWay_ = rhs.preferredWay_;
6909   resolveAfterTakeOffCuts_ = rhs.resolveAfterTakeOffCuts_;
6910   maximumNumberIterations_ = rhs.maximumNumberIterations_;
6911   numberSavedSolutions_ = rhs.numberSavedSolutions_;
6912   maximumSavedSolutions_ = rhs.maximumSavedSolutions_;
6913   if (maximumSavedSolutions_) {
6914     int n = solver_->getNumCols();
6915     savedSolutions_ = new double *[maximumSavedSolutions_];
6916     for (int i = 0; i < maximumSavedSolutions_; i++)
6917       savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], n + 2);
6918   }
6919   continuousPriority_ = rhs.continuousPriority_;
6920   numberThreads_ = rhs.numberThreads_;
6921   threadMode_ = rhs.threadMode_;
6922   numberGlobalCutsIn_ = rhs.numberGlobalCutsIn_;
6923   delete master_;
6924   master_ = NULL;
6925   masterThread_ = NULL;
6926   memcpy(intParam_, rhs.intParam_, sizeof(intParam_));
6927   memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_));
6928   int i;
6929   if (mode) {
6930     for (i = 0; i < numberCutGenerators_; i++) {
6931       delete generator_[i];
6932       delete virginGenerator_[i];
6933     }
6934     delete[] generator_;
6935     delete[] virginGenerator_;
6936     for (i = 0; i < numberHeuristics_; i++) {
6937       delete heuristic_[i];
6938     }
6939     delete[] heuristic_;
6940     delete eventHandler_;
6941     delete branchingMethod_;
6942   }
6943   numberCutGenerators_ = rhs.numberCutGenerators_;
6944   if (numberCutGenerators_) {
6945     generator_ = new CbcCutGenerator *[numberCutGenerators_];
6946     virginGenerator_ = new CbcCutGenerator *[numberCutGenerators_];
6947     int i;
6948     for (i = 0; i < numberCutGenerators_; i++) {
6949       if (mode < 2) {
6950         generator_[i] = new CbcCutGenerator(*rhs.generator_[i]);
6951       } else {
6952         generator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
6953         // But copy across maximumTries and switches
6954         generator_[i]->setMaximumTries(rhs.generator_[i]->maximumTries());
6955         generator_[i]->setSwitches(rhs.generator_[i]->switches());
6956       }
6957       virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]);
6958     }
6959   } else {
6960     generator_ = NULL;
6961     virginGenerator_ = NULL;
6962   }
6963   numberHeuristics_ = rhs.numberHeuristics_;
6964   if (numberHeuristics_) {
6965     heuristic_ = new CbcHeuristic *[numberHeuristics_];
6966     int i;
6967     for (i = 0; i < numberHeuristics_; i++) {
6968       heuristic_[i] = rhs.heuristic_[i]->clone();
6969     }
6970   } else {
6971     heuristic_ = NULL;
6972   }
6973   if (rhs.eventHandler_)
6974     eventHandler_ = rhs.eventHandler_->clone();
6975   else
6976     eventHandler_ = NULL;
6977   if (rhs.branchingMethod_)
6978     branchingMethod_ = rhs.branchingMethod_->clone();
6979   else
6980     branchingMethod_ = NULL;
6981   messageHandler()->setLogLevel(rhs.messageHandler()->logLevel());
6982   whenCuts_ = rhs.whenCuts_;
6983 #ifdef COIN_HAS_NTY
6984   if (rhs.symmetryInfo_)
6985     symmetryInfo_ = new CbcSymmetry(*rhs.symmetryInfo_);
6986   else
6987     symmetryInfo_ = NULL;
6988 #endif
6989   synchronizeModel();
6990 }
6991 // Move status, nodes etc etc across
6992 void CbcModel::moveInfo(const CbcModel &rhs)
6993 {
6994   bestObjective_ = rhs.bestObjective_;
6995   bestPossibleObjective_ = rhs.bestPossibleObjective_;
6996   numberSolutions_ = rhs.numberSolutions_;
6997   numberHeuristicSolutions_ = rhs.numberHeuristicSolutions_;
6998   numberNodes_ = rhs.numberNodes_;
6999   numberNodes2_ = rhs.numberNodes2_;
7000   numberIterations_ = rhs.numberIterations_;
7001   numberSolves_ = rhs.numberSolves_;
7002   status_ = rhs.status_;
7003   secondaryStatus_ = rhs.secondaryStatus_;
7004   numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
7005   numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_;
7006   continuousObjective_ = rhs.continuousObjective_;
7007   originalContinuousObjective_ = rhs.originalContinuousObjective_;
7008   continuousInfeasibilities_ = rhs.continuousInfeasibilities_;
7009   numberFixedAtRoot_ = rhs.numberFixedAtRoot_;
7010   numberFixedNow_ = rhs.numberFixedNow_;
7011   stoppedOnGap_ = rhs.stoppedOnGap_;
7012   eventHappened_ = rhs.eventHappened_;
7013   numberLongStrong_ = rhs.numberLongStrong_;
7014   numberStrongIterations_ = rhs.numberStrongIterations_;
7015   strongInfo_[0] = rhs.strongInfo_[0];
7016   strongInfo_[1] = rhs.strongInfo_[1];
7017   strongInfo_[2] = rhs.strongInfo_[2];
7018   strongInfo_[3] = rhs.strongInfo_[3];
7019   strongInfo_[4] = rhs.strongInfo_[4];
7020   strongInfo_[5] = rhs.strongInfo_[5];
7021   strongInfo_[6] = rhs.strongInfo_[6];
7022   numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_;
7023   cutoffRowNumber_ = rhs.cutoffRowNumber_;
7024   maximumDepth_ = rhs.maximumDepth_;
7025 }
7026 // Save a copy of the current solver so can be reset to
7027 void CbcModel::saveReferenceSolver()
7028 {
7029   delete referenceSolver_;
7030   referenceSolver_ = solver_->clone();
7031 }
7032 
7033 // Uses a copy of reference solver to be current solver
7034 void CbcModel::resetToReferenceSolver()
7035 {
7036   delete solver_;
7037   solver_ = referenceSolver_->clone();
7038   // clear many things
7039   gutsOfDestructor2();
7040   // Reset cutoff
7041   // Solvers know about direction
7042   double direction = solver_->getObjSense();
7043   double value;
7044   solver_->getDblParam(OsiDualObjectiveLimit, value);
7045   setCutoff(value * direction);
7046 }
7047 
7048 // Are there a numerical difficulties?
7049 bool CbcModel::isAbandoned() const
7050 {
7051   return status_ == 2;
7052 }
7053 // Is optimality proven?
7054 bool CbcModel::isProvenOptimal() const
7055 {
7056   if (!status_ && bestObjective_ < 1.0e30)
7057     return true;
7058   else
7059     return false;
7060 }
7061 // Is  infeasiblity proven (or none better than cutoff)?
7062 bool CbcModel::isProvenInfeasible() const
7063 {
7064   if (!status_ && (bestObjective_ >= 1.0e30 && (secondaryStatus_ == 0 || secondaryStatus_ == 1)))
7065     return true;
7066   else
7067     return false;
7068 }
7069 // Was continuous solution unbounded
7070 bool CbcModel::isContinuousUnbounded() const
7071 {
7072   if (!status_ && secondaryStatus_ == 7)
7073     return true;
7074   else
7075     return false;
7076 }
7077 // Was continuous solution unbounded
7078 bool CbcModel::isProvenDualInfeasible() const
7079 {
7080   if (!status_ && secondaryStatus_ == 7)
7081     return true;
7082   else
7083     return false;
7084 }
7085 // Node limit reached?
7086 bool CbcModel::isNodeLimitReached() const
7087 {
7088   return numberNodes_ >= intParam_[CbcMaxNumNode];
7089 }
7090 // Time limit reached?
7091 bool CbcModel::isSecondsLimitReached() const
7092 {
7093   if (status_ == 1 && secondaryStatus_ == 4)
7094     return true;
7095   else
7096     return false;
7097 }
7098 // Solution limit reached?
7099 bool CbcModel::isSolutionLimitReached() const
7100 {
7101   return numberSolutions_ >= intParam_[CbcMaxNumSol];
7102 }
7103 // Set language
7104 void CbcModel::newLanguage(CoinMessages::Language language)
7105 {
7106   messages_ = CbcMessage(language);
7107 }
7108 void CbcModel::setNumberStrong(int number)
7109 {
7110   if (number < 0)
7111     numberStrong_ = 0;
7112   else
7113     numberStrong_ = number;
7114 }
7115 void CbcModel::setNumberBeforeTrust(int number)
7116 {
7117   if (number < -3) {
7118     numberBeforeTrust_ = 0;
7119   } else {
7120     numberBeforeTrust_ = number;
7121     //numberStrong_ = CoinMax(numberStrong_,1);
7122   }
7123 }
7124 void CbcModel::setNumberPenalties(int number)
7125 {
7126   if (number <= 0) {
7127     numberPenalties_ = 0;
7128   } else {
7129     numberPenalties_ = number;
7130   }
7131 }
7132 void CbcModel::setPenaltyScaleFactor(double value)
7133 {
7134   if (value <= 0) {
7135     penaltyScaleFactor_ = 3.0;
7136   } else {
7137     penaltyScaleFactor_ = value;
7138   }
7139 }
7140 void CbcModel::setHowOftenGlobalScan(int number)
7141 {
7142   if (number < -1)
7143     howOftenGlobalScan_ = 0;
7144   else
7145     howOftenGlobalScan_ = number;
7146 }
7147 
7148 // Add one generator
7149 void CbcModel::addCutGenerator(CglCutGenerator *generator,
7150   int howOften, const char *name,
7151   bool normal, bool atSolution,
7152   bool whenInfeasible, int howOftenInSub,
7153   int whatDepth, int whatDepthInSub)
7154 {
7155   CbcCutGenerator **temp = generator_;
7156   generator_ = new CbcCutGenerator *[numberCutGenerators_ + 1];
7157   if (temp != NULL) {
7158     memcpy(generator_, temp, numberCutGenerators_ * sizeof(CbcCutGenerator *));
7159     delete[] temp;
7160   }
7161   generator_[numberCutGenerators_] = new CbcCutGenerator(this, generator, howOften, name,
7162     normal, atSolution, whenInfeasible, howOftenInSub,
7163     whatDepth, whatDepthInSub);
7164   // and before any changes
7165   temp = virginGenerator_;
7166   virginGenerator_ = new CbcCutGenerator *[numberCutGenerators_ + 1];
7167   memcpy(virginGenerator_, temp, numberCutGenerators_ * sizeof(CbcCutGenerator *));
7168   delete[] temp;
7169   virginGenerator_[numberCutGenerators_++] = new CbcCutGenerator(this, generator, howOften, name,
7170     normal, atSolution, whenInfeasible, howOftenInSub,
7171     whatDepth, whatDepthInSub);
7172 }
7173 // Add one heuristic
7174 void CbcModel::addHeuristic(CbcHeuristic *generator, const char *name,
7175   int before)
7176 {
7177   CbcHeuristic **temp = heuristic_;
7178   heuristic_ = new CbcHeuristic *[numberHeuristics_ + 1];
7179   if (temp!= NULL) {
7180     memcpy(heuristic_, temp, numberHeuristics_ * sizeof(CbcHeuristic *));
7181     delete[] temp;
7182   }
7183   int where;
7184   if (before < 0 || before >= numberHeuristics_) {
7185     where = numberHeuristics_;
7186   } else {
7187     // move up
7188     for (int i = numberHeuristics_; i > before; i--)
7189       heuristic_[i] = heuristic_[i - 1];
7190     where = before;
7191   }
7192   heuristic_[where] = generator->clone();
7193   if (name)
7194     heuristic_[where]->setHeuristicName(name);
7195 #ifndef SAME_HEURISTIC_SEED
7196   heuristic_[where]->setSeed(987654321 + where);
7197 #else
7198   heuristic_[where]->setSeed(987654321);
7199 #endif
7200   numberHeuristics_++;
7201 }
7202 
7203 /*
7204   The last subproblem handled by the solver is not necessarily related to the
7205   one being recreated, so the first action is to remove all cuts from the
7206   constraint system.  Next, traverse the tree from node to the root to
7207   determine the basis size required for this subproblem and create an empty
7208   basis with the right capacity.  Finally, traverse the tree from root to
7209   node, adjusting bounds in the constraint system, adjusting the basis, and
7210   collecting the cuts that must be added to the constraint system.
7211   applyToModel does the heavy lifting.
7212 
7213   addCuts1 is used in contexts where all that's desired is the list of cuts:
7214   the node is already fathomed, and we're collecting cuts so that we can
7215   adjust reference counts as we prune nodes. Arguably the two functions
7216   should be separated. The culprit is applyToModel, which performs cut
7217   collection and model adjustment.
7218 
7219   Certainly in the contexts where all we need is a list of cuts, there's no
7220   point in passing in a valid basis --- an empty basis will do just fine.
7221 */
7222 bool CbcModel::addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws)
7223 {
7224   int nNode = 0;
7225   CbcNodeInfo *nodeInfo = node->nodeInfo();
7226   int numberColumns = getNumCols();
7227 
7228   /*
7229       Accumulate the path from node to the root in walkback_, and accumulate a
7230       cut count in currentNumberCuts.
7231 
7232       original comment: when working then just unwind until where new node joins
7233       old node (for cuts?)
7234     */
7235   int currentNumberCuts = 0;
7236   while (nodeInfo) {
7237     //printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo);
7238     walkback_[nNode++] = nodeInfo;
7239     currentNumberCuts += nodeInfo->numberCuts();
7240     nodeInfo = nodeInfo->parent();
7241     if (nNode == maximumDepth_) {
7242       redoWalkBack();
7243     }
7244   }
7245   resizeWhichGenerator(currentNumberCuts_, currentNumberCuts);
7246   currentNumberCuts_ = currentNumberCuts;
7247   if (currentNumberCuts > maximumNumberCuts_) {
7248     maximumNumberCuts_ = currentNumberCuts;
7249     delete[] addedCuts_;
7250     addedCuts_ = new CbcCountRowCut *[maximumNumberCuts_];
7251   }
7252   /*
7253       This last bit of code traverses the path collected in walkback_ from the
7254       root back to node. At the end of the loop,
7255        * lastws will be an appropriate basis for node;
7256        * variable bounds in the constraint system will be set to be correct for
7257          node; and
7258        * addedCuts_ will be set to a list of cuts that need to be added to the
7259          constraint system at node.
7260       applyToModel does all the heavy lifting.
7261     */
7262   bool sameProblem = false;
7263   if ((specialOptions_ & 4096) == 0) {
7264 #if 0
7265         {
7266             int n1 = numberRowsAtContinuous_;
7267             for (int i = 0; i < lastDepth_; i++)
7268                 n1 += lastNumberCuts_[i];
7269             int n2 = numberRowsAtContinuous_;
7270             for (int i = 0; i < nNode; i++)
7271                 n2 += walkback_[i]->numberCuts();
7272             //printf("ROWS a %d - old thinks %d new %d\n",solver_->getNumRows(),n1,n2);
7273         }
7274 #endif
7275     int nDel = 0;
7276     int nAdd = 0;
7277     int n = CoinMin(lastDepth_, nNode);
7278     int i;
7279     int difference = lastDepth_ - nNode;
7280     int iZ = lastDepth_;
7281     int iN = 0;
7282     // Last is reversed to minimize copying
7283     if (difference > 0) {
7284       for (i = 0; i < difference; i++) {
7285         // delete rows
7286         nDel += lastNumberCuts_[--iZ];
7287       }
7288     } else if (difference < 0) {
7289       for (i = 0; i < -difference; i++) {
7290         // add rows
7291         nAdd += walkback_[i]->numberCuts();
7292       }
7293       iN = -difference;
7294     }
7295     for (i = 0; i < n; i++) {
7296       iZ--;
7297       if (lastNodeInfo_[iZ] == walkback_[iN]) {
7298         break;
7299       } else {
7300         // delete rows
7301         nDel += lastNumberCuts_[iZ];
7302         // add rows
7303         nAdd += walkback_[iN++]->numberCuts();
7304       }
7305     }
7306     assert(i < n || lastDepth_ == 0);
7307     //printf("lastDepth %d thisDepth %d match at %d, rows+-= %d %d\n",
7308     //   lastDepth_,nNode,n-i,nAdd,nDel);
7309     sameProblem = (!nAdd) && (!nDel);
7310     if (lastDepth_) {
7311       while (iN >= 0) {
7312         lastNumberCuts_[iZ] = walkback_[iN]->numberCuts();
7313         lastNodeInfo_[iZ++] = walkback_[iN--];
7314       }
7315     } else {
7316       lastNumberCuts_[0] = walkback_[0]->numberCuts();
7317       lastNodeInfo_[0] = walkback_[0];
7318     }
7319     lastDepth_ = nNode;
7320   }
7321   currentDepth_ = nNode;
7322   /*
7323       Remove all cuts from the constraint system.
7324       (original comment includes ``see note below for later efficiency'', but
7325       the reference isn't clear to me).
7326     */
7327   /*
7328       Create an empty basis with sufficient capacity for the constraint system
7329       we'll construct: original system plus cuts. Make sure we have capacity to
7330       record those cuts in addedCuts_.
7331 
7332       The method of adjusting the basis at a FullNodeInfo object (the root, for
7333       example) is to use a copy constructor to duplicate the basis held in the
7334       nodeInfo, then resize it and return the new basis object. Guaranteed,
7335       lastws will point to a different basis when it returns. We pass in a basis
7336       because we need the parameter to return the allocated basis, and it's an
7337       easy way to pass in the size. But we take a hit for memory allocation.
7338     */
7339   if (lastws)
7340     lastws->setSize(numberColumns, numberRowsAtContinuous_ + currentNumberCuts);
7341   currentNumberCuts = 0;
7342   while (nNode) {
7343     --nNode;
7344     walkback_[nNode]->applyToModel(this, lastws,
7345       addedCuts_, currentNumberCuts);
7346   }
7347 #ifndef NDEBUG
7348   if (lastws && !lastws->fullBasis()) {
7349 #ifdef COIN_DEVELOP
7350     printf("******* bad basis\n");
7351 #endif
7352     int numberRows = lastws->getNumArtificial();
7353     int i;
7354     for (i = 0; i < numberRows; i++)
7355       lastws->setArtifStatus(i, CoinWarmStartBasis::basic);
7356     int numberColumns = lastws->getNumStructural();
7357     for (i = 0; i < numberColumns; i++) {
7358       if (lastws->getStructStatus(i) == CoinWarmStartBasis::basic)
7359         lastws->setStructStatus(i, CoinWarmStartBasis::atLowerBound);
7360     }
7361   }
7362 #endif
7363   return sameProblem;
7364 }
7365 
7366 /*
7367   adjustCuts might be a better name: If the node is feasible, we sift through
7368   the cuts collected by addCuts1, add the ones that are tight and omit the
7369   ones that are loose. If the node is infeasible, we just adjust the
7370   reference counts to reflect that we're about to prune this node and its
7371   descendants.
7372 */
7373 int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws)
7374 {
7375   /*
7376       addCuts1 performs step 1 of restoring the subproblem at this node; see the
7377       comments there.
7378     */
7379   bool sameProblem = addCuts1(node, lastws);
7380   int i;
7381   int numberColumns = getNumCols();
7382   if (solver_->getNumRows() > maximumRows_) {
7383     maximumRows_ = solver_->getNumRows();
7384     workingBasis_.resize(maximumRows_, numberColumns);
7385   }
7386   CbcNodeInfo *nodeInfo = node->nodeInfo();
7387   double cutoff = getCutoff();
7388   int currentNumberCuts = currentNumberCuts_;
7389   /*
7390       If the node can't be fathomed by bound, reinstall tight cuts in the
7391       constraint system. Even if there are no cuts, we'll want to set the
7392       reconstructed basis in the solver.
7393     */
7394   if (node->objectiveValue() < cutoff || numberThreads_) {
7395     //#   define CBC_CHECK_BASIS
7396 #ifdef CBC_CHECK_BASIS
7397     printf("addCuts: expanded basis; rows %d+%d\n",
7398       numberRowsAtContinuous_, currentNumberCuts);
7399     lastws->print();
7400 #endif
7401     /*
7402           Adjust the basis and constraint system so that we retain only active cuts.
7403           There are three steps:
7404             1) Scan the basis. Sort the cuts into effective cuts to be kept and
7405                loose cuts to be dropped.
7406             2) Drop the loose cuts and resize the basis to fit.
7407             3) Install the tight cuts in the constraint system (applyRowCuts) and
7408                and install the basis (setWarmStart).
7409           Use of compressRows conveys we're compressing the basis and not just
7410           tweaking the artificialStatus_ array.
7411         */
7412     if (currentNumberCuts > 0) {
7413       int numberToAdd = 0;
7414       const OsiRowCut **addCuts;
7415       int numberToDrop = 0;
7416       int *cutsToDrop;
7417       addCuts = new const OsiRowCut *[currentNumberCuts];
7418       cutsToDrop = new int[currentNumberCuts];
7419       assert(currentNumberCuts + numberRowsAtContinuous_ <= lastws->getNumArtificial());
7420       assert(currentNumberCuts <= maximumWhich_); // we will read from whichGenerator_[0..currentNumberCuts-1] below, so should have all these entries
7421       for (i = 0; i < currentNumberCuts; i++) {
7422         CoinWarmStartBasis::Status status = lastws->getArtifStatus(i + numberRowsAtContinuous_);
7423         if (addedCuts_[i] && (status != CoinWarmStartBasis::basic || (addedCuts_[i]->effectiveness() > 1.0e10 && !addedCuts_[i]->canDropCut(solver_, i + numberRowsAtContinuous_)))) {
7424 #ifdef CHECK_CUT_COUNTS
7425           printf("Using cut %d %x as row %d\n", i, addedCuts_[i],
7426             numberRowsAtContinuous_ + numberToAdd);
7427 #endif
7428           assert(i < maximumWhich_);
7429           whichGenerator_[numberToAdd] = whichGenerator_[i];
7430           addCuts[numberToAdd++] = addedCuts_[i];
7431 #if 1
7432           if ((specialOptions_ & 1) != 0) {
7433             const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
7434             if (debugger)
7435               CoinAssert(!debugger->invalidCut(*addedCuts_[i]));
7436           }
7437 #endif
7438         } else {
7439 #ifdef CHECK_CUT_COUNTS
7440           printf("Dropping cut %d %x\n", i, addedCuts_[i]);
7441 #endif
7442           addedCuts_[i] = NULL;
7443           cutsToDrop[numberToDrop++] = numberRowsAtContinuous_ + i;
7444         }
7445       }
7446       assert(lastws->fullBasis());
7447       int numberRowsNow = numberRowsAtContinuous_ + numberToAdd;
7448       lastws->compressRows(numberToDrop, cutsToDrop);
7449       lastws->resize(numberRowsNow, numberColumns);
7450       // Take out as local search can give bad basisassert (lastws->fullBasis());
7451       bool canMissStuff = false;
7452       if ((specialOptions_ & 4096) == 0) {
7453         bool redoCuts = true;
7454         if (CoinAbs(lastNumberCuts2_ - numberToAdd) < 5) {
7455           int numberToCheck = CoinMin(lastNumberCuts2_, numberToAdd);
7456           int i1 = 0;
7457           int i2 = 0;
7458           int nDiff = 0;
7459           int nSame = 0;
7460           if (lastNumberCuts2_ == numberToAdd) {
7461             for (int i = 0; i < numberToCheck; i++) {
7462               if (lastCut_[i1++] != addCuts[i2++]) {
7463                 nDiff++;
7464               } else {
7465                 nSame++;
7466               }
7467             }
7468           } else if (lastNumberCuts2_ > numberToAdd) {
7469             int nDiff2 = lastNumberCuts2_ - numberToAdd;
7470             for (int i = 0; i < numberToCheck; i++) {
7471               if (lastCut_[i1] != addCuts[i2]) {
7472                 nDiff++;
7473                 while (nDiff2) {
7474                   i1++;
7475                   nDiff2--;
7476                   if (lastCut_[i1] == addCuts[i2]) {
7477                     nSame++;
7478                     break;
7479                   } else {
7480                     nDiff++;
7481                   }
7482                 }
7483               } else {
7484                 nSame++;
7485               }
7486             }
7487             nDiff += nDiff2;
7488           } else {
7489             int nDiff2 = numberToAdd - lastNumberCuts2_;
7490             for (int i = 0; i < numberToCheck; i++) {
7491               if (lastCut_[i1] != addCuts[i2]) {
7492                 nDiff++;
7493                 while (nDiff2) {
7494                   i2++;
7495                   nDiff2--;
7496                   if (lastCut_[i1] == addCuts[i2]) {
7497                     nSame++;
7498                     break;
7499                   } else {
7500                     nDiff++;
7501                   }
7502                 }
7503               } else {
7504                 nSame++;
7505               }
7506             }
7507             nDiff += nDiff2;
7508           }
7509           canMissStuff = !nDiff && sameProblem;
7510           // But only if number of rows looks OK
7511           if (numberRowsAtContinuous_ + numberToAdd != solver_->getNumRows())
7512             canMissStuff = false;
7513         } else {
7514           //printf("add now %d add last %d NO2\n",numberToAdd,lastNumberCuts2_);
7515         }
7516         assert(lastws->fullBasis() && numberRowsAtContinuous_ + numberToAdd == numberRowsNow);
7517         if (redoCuts) {
7518           if (numberToAdd > maximumCuts_) {
7519             delete[] lastCut_;
7520             maximumCuts_ = 2 * numberToAdd + 10;
7521             lastCut_ = new const OsiRowCut *[maximumCuts_];
7522           }
7523           lastNumberCuts2_ = numberToAdd;
7524           for (int i = 0; i < numberToAdd; i++)
7525             lastCut_[i] = addCuts[i];
7526         }
7527       }
7528       if (!canMissStuff) {
7529         //if (canMissStuff)
7530         //solver_->writeMps("before");
7531         //printf("Not Skipped\n");
7532         //int n1=solver_->getNumRows();
7533         if ((specialOptions_ & 4096) == 0) {
7534           solver_->restoreBaseModel(numberRowsAtContinuous_);
7535         } else {
7536           // *** Fix later
7537           int numberCuts = solver_->getNumRows() - numberRowsAtContinuous_;
7538           int *which = new int[numberCuts];
7539           for (i = 0; i < numberCuts; i++)
7540             which[i] = i + numberRowsAtContinuous_;
7541           solver_->deleteRows(numberCuts, which);
7542           delete[] which;
7543         }
7544         //#define CHECK_DEBUGGER
7545 #ifdef CHECK_DEBUGGER
7546         if ((specialOptions_ & 1) != 0) {
7547           const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
7548           if (debugger) {
7549             for (int j = 0; j < numberToAdd; j++)
7550               CoinAssert(!debugger->invalidCut(*addCuts[j]));
7551             //addCuts[j]->print();
7552           }
7553         }
7554 #endif
7555         solver_->applyRowCuts(numberToAdd, addCuts);
7556       }
7557 #ifdef CBC_CHECK_BASIS
7558       printf("addCuts: stripped basis; rows %d + %d\n",
7559         numberRowsAtContinuous_, numberToAdd);
7560       lastws->print();
7561 #endif
7562       delete[] addCuts;
7563       delete[] cutsToDrop;
7564     }
7565     /*
7566           Set the basis in the solver.
7567         */
7568     solver_->setWarmStart(lastws);
7569     /*
7570           Clean up and we're out of here.
7571         */
7572     numberNodes_++;
7573     return 0;
7574   }
7575   /*
7576       This node has been fathomed by bound as we try to revive it out of the live
7577       set. Adjust the cut reference counts to reflect that we no longer need to
7578       explore the remaining branch arms, hence they will no longer reference any
7579       cuts. Cuts whose reference count falls to zero are deleted.
7580     */
7581   else {
7582     int i;
7583     if (currentNumberCuts) {
7584       lockThread();
7585       int numberLeft = nodeInfo->numberBranchesLeft();
7586       for (i = 0; i < currentNumberCuts; i++) {
7587         if (addedCuts_[i]) {
7588           if (!addedCuts_[i]->decrement(numberLeft)) {
7589             delete addedCuts_[i];
7590             addedCuts_[i] = NULL;
7591           }
7592         }
7593       }
7594       unlockThread();
7595     }
7596     return 1;
7597   }
7598 }
7599 /* Makes all handlers same.  If makeDefault 1 then makes top level
7600    default and rest point to that.  If 2 then each is copy
7601 */
7602 void CbcModel::synchronizeHandlers(int /*makeDefault*/)
7603 {
7604   bool defaultHandler = defaultHandler_;
7605   if (!defaultHandler_) {
7606     // Must have clone
7607     handler_ = handler_->clone();  // Not sure - worst is small memory leak
7608     defaultHandler_ = true;
7609   }
7610 #ifdef COIN_HAS_CLP
7611   if (!defaultHandler) {
7612     OsiClpSolverInterface *solver;
7613     solver = dynamic_cast< OsiClpSolverInterface * >(solver_);
7614     if (solver) {
7615       solver->passInMessageHandler(handler_);
7616       solver->getModelPtr()->passInMessageHandler(handler_);
7617     }
7618     solver = dynamic_cast< OsiClpSolverInterface * >(continuousSolver_);
7619     if (solver) {
7620       solver->passInMessageHandler(handler_);
7621       solver->getModelPtr()->passInMessageHandler(handler_);
7622     }
7623   }
7624 #endif
7625 }
7626 
7627 /*
7628   Perform reduced cost fixing on integer variables.
7629 
7630   The variables in question are already nonbasic at bound. We're just nailing
7631   down the current situation.
7632 */
7633 int CbcModel::reducedCostFix()
7634 
7635 {
7636   if (!solverCharacteristics_->reducedCostsAccurate())
7637     return 0; //NLP
7638   double cutoff = getCutoff();
7639   double direction = solver_->getObjSense();
7640   double gap = cutoff - solver_->getObjValue() * direction;
7641   double tolerance;
7642   solver_->getDblParam(OsiDualTolerance, tolerance);
7643   if (gap <= 0.0)
7644     gap = tolerance; //return 0;
7645   gap += 100.0 * tolerance;
7646   double integerTolerance = getDblParam(CbcIntegerTolerance);
7647 
7648   const double *lower = solver_->getColLower();
7649   const double *upper = solver_->getColUpper();
7650   const double *solution = solver_->getColSolution();
7651   const double *reducedCost = solver_->getReducedCost();
7652 
7653   int numberFixed = 0;
7654   int numberTightened = 0;
7655 
7656 #ifdef COIN_HAS_CLP
7657   OsiClpSolverInterface *clpSolver
7658     = dynamic_cast< OsiClpSolverInterface * >(solver_);
7659   ClpSimplex *clpSimplex = NULL;
7660   if (clpSolver)
7661     clpSimplex = clpSolver->getModelPtr();
7662 #endif
7663   for (int i = 0; i < numberIntegers_; i++) {
7664     int iColumn = integerVariable_[i];
7665     double djValue = direction * reducedCost[iColumn];
7666     double boundGap = upper[iColumn] - lower[iColumn];
7667     if (boundGap > integerTolerance) {
7668       if (solution[iColumn] < lower[iColumn] + integerTolerance
7669         && djValue * boundGap > gap) {
7670 #ifdef COIN_HAS_CLP
7671         // may just have been fixed before
7672         if (clpSimplex) {
7673           if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) {
7674 #ifdef COIN_DEVELOP
7675             printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n",
7676               iColumn, clpSimplex->getColumnStatus(iColumn),
7677               djValue, gap, lower[iColumn], upper[iColumn]);
7678 #endif
7679           } else {
7680             assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atLowerBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed);
7681           }
7682         }
7683 #endif
7684         double newBound = lower[iColumn];
7685         if (boundGap > 1.99) {
7686           boundGap = gap / djValue + 1.0e-4 * boundGap;
7687           newBound = lower[iColumn] + floor(boundGap);
7688           numberTightened++;
7689           //if (newBound)
7690           //printf("tighter - gap %g dj %g newBound %g\n",
7691           //   gap,djValue,newBound);
7692         }
7693         solver_->setColUpper(iColumn, newBound);
7694         numberFixed++;
7695       } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > boundGap * gap) {
7696 #ifdef COIN_HAS_CLP
7697         // may just have been fixed before
7698         if (clpSimplex) {
7699           if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) {
7700 #ifdef COIN_DEVELOP
7701             printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n",
7702               iColumn, clpSimplex->getColumnStatus(iColumn),
7703               djValue, gap, lower[iColumn], upper[iColumn]);
7704 #endif
7705           } else {
7706             assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atUpperBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed);
7707           }
7708         }
7709 #endif
7710         double newBound = upper[iColumn];
7711         if (boundGap > 1.99) {
7712           boundGap = -gap / djValue + 1.0e-4 * boundGap;
7713           newBound = upper[iColumn] - floor(boundGap);
7714           //if (newBound)
7715           //printf("tighter - gap %g dj %g newBound %g\n",
7716           //   gap,djValue,newBound);
7717           numberTightened++;
7718         }
7719         solver_->setColLower(iColumn, newBound);
7720         numberFixed++;
7721       }
7722     }
7723   }
7724   numberDJFixed_ += numberFixed - numberTightened;
7725 #ifdef SWITCH_VARIABLES
7726   if (numberFixed)
7727     fixAssociated(NULL, 0);
7728 #endif
7729   return numberFixed;
7730 }
7731 // Collect coding to replace whichGenerator
7732 void CbcModel::resizeWhichGenerator(int numberNow, int numberAfter)
7733 {
7734   if (numberAfter > maximumWhich_) {
7735 #define MAXIMUM_WHICH_INCREMENT 100
7736 #define MAXIMUM_WHICH_MULTIPLIER 2
7737     //printf("maximumWhich from %d to %d (%d needed)\n",maximumWhich_,
7738     //   CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + MAXIMUM_WHICH_INCREMENT, numberAfter),
7739     //   numberAfter);
7740     maximumWhich_ = CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + MAXIMUM_WHICH_INCREMENT, numberAfter);
7741     //maximumWhich_ = numberAfter ;
7742     int *temp = new int[2 * maximumWhich_];
7743     memcpy(temp, whichGenerator_, numberNow * sizeof(int));
7744     delete[] whichGenerator_;
7745     whichGenerator_ = temp;
7746     memset(whichGenerator_ + numberNow, 0, (maximumWhich_ - numberNow) * sizeof(int));
7747   }
7748 }
7749 
7750 /** Solve the model using cuts
7751 
7752   This version takes off redundant cuts from node.
7753   Returns true if feasible.
7754 
7755   \todo
7756   Why do I need to resolve the problem? What has been done between the last
7757   relaxation and calling solveWithCuts?
7758 
7759   If numberTries == 0 then user did not want any cuts.
7760 */
7761 
7762 bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node)
7763 /*
7764   Parameters:
7765     numberTries: (i) the maximum number of iterations for this round of cut
7766 		     generation; if negative then we don't mind if drop is tiny.
7767 
7768     cuts:	(o) all cuts generated in this round of cut generation
7769 
7770     node: (i)     So we can update dynamic pseudo costs
7771 */
7772 
7773 {
7774 #ifdef JJF_ZERO
7775   if (node && numberTries > 1) {
7776     if (currentDepth_ < 5)
7777       numberTries *= 4; // boost
7778     else if (currentDepth_ < 10)
7779       numberTries *= 2; // boost
7780   }
7781 #endif
7782 #define CUT_HISTORY 7
7783   double cut_obj[CUT_HISTORY];
7784   for (int j = 0; j < CUT_HISTORY; j++)
7785     cut_obj[j] = -COIN_DBL_MAX;
7786 #ifdef COIN_HAS_CLP
7787   OsiClpSolverInterface *clpSolver
7788     = dynamic_cast< OsiClpSolverInterface * >(solver_);
7789   int saveClpOptions = 0;
7790   if (clpSolver)
7791     saveClpOptions = clpSolver->specialOptions();
7792 #endif
7793     //solver_->writeMps("saved");
7794 #ifdef CBC_THREAD
7795   /*
7796       Thread mode makes a difference here only when it specifies using separate
7797       threads to generate cuts at the root (bit 2^1 set in threadMode_). In which
7798       case we'll create an array of empty CbcModels (!). Solvers will be cloned
7799       later.
7800 
7801       Don't start up threads here if we're already threaded.
7802     */
7803   CbcBaseModel *master = NULL;
7804   if (numberThreads_ && (threadMode_ & 2) != 0 && !numberNodes_) {
7805     master = new CbcBaseModel(*this, -1);
7806   }
7807 #endif
7808   bool feasible = true;
7809   int violated = 0;
7810   int numberRowsAtStart = solver_->getNumRows();
7811   //printf("solver had %d rows\n",numberRowsAtStart);
7812   int numberColumns = solver_->getNumCols();
7813   CoinBigIndex numberElementsAtStart = solver_->getNumElements();
7814 
7815   numberOldActiveCuts_ = numberRowsAtStart - numberRowsAtContinuous_;
7816 #ifndef NDEBUG
7817   {
7818     int n = 0;
7819     for (int i = 0; i < currentNumberCuts_; i++) {
7820       if (addedCuts_[i])
7821         n++;
7822     }
7823     assert(n == numberOldActiveCuts_);
7824   }
7825 #endif
7826   numberNewCuts_ = cuts.sizeRowCuts();
7827   int lastNumberCuts = numberNewCuts_;
7828   if (numberNewCuts_) {
7829     // from multiple root passes
7830     const OsiRowCut **addCuts = new const OsiRowCut *[numberNewCuts_];
7831     for (int i = 0; i < numberNewCuts_; i++) {
7832       addCuts[i] = cuts.rowCutPtr(i);
7833     }
7834     solver_->applyRowCuts(numberNewCuts_, addCuts);
7835     delete[] addCuts;
7836   }
7837 
7838   bool onOptimalPath = false;
7839   const OsiRowCutDebugger *debugger = NULL;
7840   if ((specialOptions_ & 1) != 0) {
7841     /*
7842           See OsiRowCutDebugger for details. In a nutshell, make sure that current
7843           variable values do not conflict with a known optimal solution. (Obviously
7844           this can be fooled when there are multiple solutions.)
7845         */
7846     debugger = solver_->getRowCutDebugger();
7847     if (debugger)
7848       onOptimalPath = (debugger->onOptimalPath(*solver_));
7849   }
7850   /*
7851       As the final action in each round of cut generation (the numberTries loop),
7852       we'll call takeOffCuts to remove slack cuts. These are saved into slackCuts
7853       and rechecked immediately after the cut generation phase of the loop.
7854     */
7855   OsiCuts slackCuts;
7856   /*
7857     lh:
7858       Resolve the problem
7859 
7860     The resolve will also refresh cached copies of the solver solution
7861     (cbcColLower_, ...) held by CbcModel.
7862     This resolve looks like the best point to capture a warm start for use in
7863     the case where cut generation proves ineffective and we need to back out
7864     a few tight cuts.
7865     I've always maintained that this resolve is unnecessary. Let's put in a hook
7866     to report if it's every nontrivial. -lh
7867 
7868     Resolve the problem. If we've lost feasibility, might as well bail out right
7869       after the debug stuff. The resolve will also refresh cached copies of the
7870       solver solution (cbcColLower_, ...) held by CbcModel.
7871     */
7872   double objectiveValue = solver_->getObjValue() * solver_->getObjSense();
7873   if (node) {
7874     objectiveValue = node->objectiveValue();
7875   }
7876   int save = moreSpecialOptions_;
7877   if ((moreSpecialOptions_ & 4194304) != 0)
7878     moreSpecialOptions_ |= 8388608;
7879   int returnCode = resolve(node ? node->nodeInfo() : NULL, 1);
7880   moreSpecialOptions_ = save;
7881 #ifdef CONFLICT_CUTS
7882 #ifdef COIN_HAS_CLP
7883   // if infeasible conflict analysis
7884   if (solver_->isProvenPrimalInfeasible() && !parentModel_ && (moreSpecialOptions_ & 4194304) != 0 && clpSolver) {
7885     if (!topOfTree_ && masterThread_)
7886       topOfTree_ = masterThread_->master_->baseModel_->topOfTree_;
7887     assert(topOfTree_);
7888     int iType = 0;
7889     OsiRowCut *cut = clpSolver->modelCut(topOfTree_->lower(),
7890       topOfTree_->upper(),
7891       numberRowsAtContinuous_, whichGenerator_, iType);
7892     if (cut) {
7893       //cut->print();
7894       if (!iType) {
7895         int badCut = makeGlobalCut(cut);
7896         if (!badCut) {
7897 #if PRINT_CONFLICT == 1
7898           numberConflictCuts++;
7899           lengthConflictCuts += cut->row().getNumElements();
7900 #endif
7901 #if PRINT_CONFLICT < 2
7902           if (handler_->logLevel() > 1) {
7903 #endif
7904             printf("Conflict cut at depth %d (%d elements)\n",
7905               currentDepth_, cut->row().getNumElements());
7906             if (cut->row().getNumElements() < 3)
7907               cut->print();
7908 #if PRINT_CONFLICT < 2
7909           }
7910 #endif
7911         }
7912         if ((specialOptions_ & 1) != 0) {
7913           debugger = continuousSolver_->getRowCutDebugger();
7914           if (debugger) {
7915             if (debugger->invalidCut(*cut)) {
7916               continuousSolver_->applyRowCuts(1, cut);
7917               continuousSolver_->writeMps("bad");
7918             }
7919             CoinAssert(!debugger->invalidCut(*cut));
7920           }
7921         }
7922       } else {
7923         makePartialCut(cut);
7924       }
7925       delete cut;
7926     }
7927   }
7928   if ((moreSpecialOptions_ & 4194304) != 0 && solver_->isProvenPrimalInfeasible()
7929     && clpSolver && clpSolver->lastAlgorithm() == 2 && clpSolver->getModelPtr()->infeasibilityRay() && !parentModel_) {
7930     printf("ray exists\n");
7931   }
7932 #endif
7933 #endif
7934   double lastObjective = solver_->getObjValue() * solver_->getObjSense();
7935   cut_obj[CUT_HISTORY - 1] = lastObjective;
7936   //double firstObjective = lastObjective+1.0e-8+1.0e-12*fabs(lastObjective);
7937   /*
7938       Contemplate the result of the resolve.
7939         - CbcModel::resolve() has a hook that calls CbcStrategy::status to look
7940           over the solution. The net result is that resolve can return
7941           0 (infeasible), 1 (feasible), or -1 (feasible, but do no further work).
7942         - CbcFeasbililityBase::feasible() can return 0 (no comment),
7943           1 (pretend this is an integer solution), or -1 (pretend this is
7944           infeasible). As of 080104, this seems to be a stub to allow overrides,
7945           with a default implementation that always returns 0.
7946 
7947       Setting numberTries = 0 for `do no more work' is problematic. The main cut
7948       generation loop will still execute once, so we do not observe the `no
7949       further work' semantics.
7950 
7951       As best I can see, allBranchesGone is a null function as of 071220.
7952     */
7953   if (node && node->nodeInfo() && !node->nodeInfo()->numberBranchesLeft())
7954     node->nodeInfo()->allBranchesGone(); // can clean up
7955   feasible = returnCode != 0;
7956   if (returnCode < 0)
7957     numberTries = 0;
7958   if (problemFeasibility_->feasible(this, 0) < 0) {
7959     feasible = false; // pretend infeasible
7960   }
7961   //#define CHECK_KNOWN_SOLUTION
7962 #ifdef CHECK_KNOWN_SOLUTION
7963   if (onOptimalPath && (solver_->isDualObjectiveLimitReached() || !feasible)) {
7964     printf("help 1\n");
7965   }
7966 #endif
7967   /*
7968       NEW_UPDATE_OBJECT is defined to 0 when unthreaded (CBC_THREAD undefined), 2
7969       when threaded. No sign of 1 as of 071220.
7970 
7971       At present, there are two sets of hierarchies for branching classes. Call
7972       them CbcHier and OsiHier. For example, we have OsiBranchingObject, with
7973       children CbcBranchingObject and OsiTwoWayBranchingObject. All
7974       specialisations descend from one of these two children. Similarly, there is
7975       OsiObject, with children CbcObject and OsiObject2.
7976 
7977       In the original setup, there's a single CbcBranchDecision object attached
7978       to CbcModel (branchingMethod_). It has a field to hold the current CbcHier
7979       branching object, and the updateInformation routine reaches through the
7980       branching object to update the underlying CbcHier object.
7981 
7982       NEW_UPDATE_OBJECT = 0 would seem to assume the original setup. But,
7983       if we're using the OSI hierarchy for objects and branching, a call to a
7984       nontrivial branchingMethod_->updateInformation would have no effect (it
7985       would expect a CbcObject to work on) or perhaps crash.  For the
7986       default CbcBranchDefaultDecision, updateInformation is a noop (actually
7987       defined in the base CbcBranchDecision class).
7988 
7989       NEW_UPDATE_OBJECT = 2 looks like it's prepared to cope with either CbcHier or
7990       OsiHier, but it'll be executed only when threads are activated. See the
7991       comments below. The setup is scary.
7992 
7993       But ... if the OsiHier update actually reaches right through to the object
7994       list in the solver, it should work just fine in unthreaded mode. It would
7995       seem that the appropriate thing to do in unthreaded mode would be to choose
7996       between the existing code for NEW_UPDATE_OBJECT = 0 and the OsiHier code for
7997       NEW_UPDATE_OBJECT = 2. But I'm going to let John hash that out. The worst
7998       that can happen is inefficiency because I'm not properly updating an object.
7999     */
8000 
8001   // Update branching information if wanted
8002   if (node && branchingMethod_) {
8003     OsiBranchingObject *bobj = node->modifiableBranchingObject();
8004     CbcBranchingObject *cbcobj = dynamic_cast< CbcBranchingObject * >(bobj);
8005     if (cbcobj && cbcobj->object()) {
8006       CbcObject *object = cbcobj->object();
8007       CbcObjectUpdateData update = object->createUpdateInformation(solver_, node, cbcobj);
8008       // have to compute object number as not saved
8009       CbcSimpleInteger *simpleObject = static_cast< CbcSimpleInteger * >(object);
8010       int iObject = simpleObject->position();
8011 #ifndef NDEBUG
8012       int iColumn = simpleObject->columnNumber();
8013       int jObject;
8014       for (jObject = 0; jObject < numberObjects_; jObject++) {
8015         simpleObject = static_cast< CbcSimpleInteger * >(object_[jObject]);
8016         if (simpleObject->columnNumber() == iColumn)
8017           break;
8018       }
8019       assert(jObject < numberObjects_ && iObject == jObject);
8020 #else
8021 #ifdef CBCMODEL_TIGHTEN_BOUNDS
8022       int iColumn = simpleObject->columnNumber();
8023 #endif
8024 #endif
8025       update.objectNumber_ = iObject;
8026       // Care! We must be careful not to update the same variable in parallel threads.
8027       addUpdateInformation(update);
8028       // update here
8029       {
8030         CbcObject *object = dynamic_cast< CbcObject * >(update.object_);
8031         if (object)
8032           object->updateInformation(update);
8033       }
8034       //#define CBCMODEL_TIGHTEN_BOUNDS
8035 #ifdef CBCMODEL_TIGHTEN_BOUNDS
8036       double cutoff = getCutoff();
8037       if (feasible && cutoff < 1.0e20) {
8038         int way = cbcobj->way();
8039         // way is what will be taken next
8040         way = -way;
8041         double value = cbcobj->value();
8042         //const double * lower = solver_->getColLower();
8043         //const double * upper = solver_->getColUpper();
8044         double objectiveChange = lastObjective - objectiveValue;
8045         if (objectiveChange > 1.0e-5) {
8046           CbcIntegerBranchingObject *branch = dynamic_cast< CbcIntegerBranchingObject * >(cbcobj);
8047           assert(branch);
8048           if (way < 0) {
8049             double down = value - floor(value);
8050             double changePer = objectiveChange / (down + 1.0e-7);
8051             double distance = (cutoff - objectiveValue) / changePer;
8052             distance += 1.0e-3;
8053             if (distance < 5.0) {
8054               double newLower = ceil(value - distance);
8055               const double *downBounds = branch->downBounds();
8056               if (newLower > downBounds[0]) {
8057                 //printf("%d way %d bounds %g %g value %g\n",
8058                 //     iColumn,way,lower[iColumn],upper[iColumn],value);
8059                 //printf("B Could increase lower bound on %d from %g to %g\n",
8060                 //     iColumn,downBounds[0],newLower);
8061                 solver_->setColLower(iColumn, newLower);
8062               }
8063             }
8064           } else {
8065             double up = ceil(value) - value;
8066             double changePer = objectiveChange / (up + 1.0e-7);
8067             double distance = (cutoff - objectiveValue) / changePer;
8068             distance += 1.0e-3;
8069             if (distance < 5.0) {
8070               double newUpper = floor(value + distance);
8071               const double *upBounds = branch->upBounds();
8072               if (newUpper < upBounds[1]) {
8073                 //printf("%d way %d bounds %g %g value %g\n",
8074                 //     iColumn,way,lower[iColumn],upper[iColumn],value);
8075                 //printf("B Could decrease upper bound on %d from %g to %g\n",
8076                 //     iColumn,upBounds[1],newUpper);
8077                 solver_->setColUpper(iColumn, newUpper);
8078               }
8079             }
8080           }
8081         }
8082       }
8083 #endif
8084     } else {
8085       OsiIntegerBranchingObject *obj = dynamic_cast< OsiIntegerBranchingObject * >(bobj);
8086       if (obj) {
8087         const OsiObject *object = obj->originalObject();
8088         // have to compute object number as not saved
8089         int iObject;
8090         int iColumn = object->columnNumber();
8091         for (iObject = 0; iObject < numberObjects_; iObject++) {
8092           if (object_[iObject]->columnNumber() == iColumn)
8093             break;
8094         }
8095         assert(iObject < numberObjects_);
8096         int branch = obj->firstBranch();
8097         if (obj->branchIndex() == 2)
8098           branch = 1 - branch;
8099         assert(branch == 0 || branch == 1);
8100         double originalValue = node->objectiveValue();
8101         double objectiveValue = solver_->getObjValue() * solver_->getObjSense();
8102         double changeInObjective = CoinMax(0.0, objectiveValue - originalValue);
8103         double value = obj->value();
8104         double movement;
8105         if (branch)
8106           movement = ceil(value) - value;
8107         else
8108           movement = value - floor(value);
8109         branchingMethod_->chooseMethod()->updateInformation(iObject, branch, changeInObjective,
8110           movement, 0 /*(feasible) ? 0 : 1; */);
8111       }
8112     }
8113   }
8114 
8115 #ifdef CBC_DEBUG
8116   if (feasible) {
8117     printf("Obj value %g (%s) %d rows\n", solver_->getObjValue(),
8118       (solver_->isProvenOptimal()) ? "proven" : "unproven",
8119       solver_->getNumRows());
8120   }
8121 
8122   else {
8123     printf("Infeasible %d rows\n", solver_->getNumRows());
8124   }
8125 #endif
8126   if ((specialOptions_ & 1) != 0) {
8127     /*
8128           If the RowCutDebugger said we were compatible with the optimal solution,
8129           and now we're suddenly infeasible, we might be confused. Then again, we
8130           may have fathomed by bound, heading for a rediscovery of an optimal solution.
8131         */
8132     if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) {
8133       if (!feasible) {
8134         solver_->writeMpsNative("infeas.mps", NULL, NULL, 2);
8135         solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
8136         CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart());
8137         solver_->setWarmStart(slack);
8138         delete slack;
8139         solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0);
8140         solver_->initialSolve();
8141       }
8142       assert(feasible);
8143     }
8144   }
8145 
8146   if (!feasible) {
8147     numberInfeasibleNodes_++;
8148 #ifdef COIN_HAS_CLP
8149     if (clpSolver)
8150       clpSolver->setSpecialOptions(saveClpOptions);
8151 #endif
8152     return (false);
8153   }
8154   double change = lastObjective - objectiveValue;
8155   if (change > 1.0e-10) {
8156     dblParam_[CbcSmallestChange] = CoinMin(dblParam_[CbcSmallestChange], change);
8157     dblParam_[CbcSumChange] += change;
8158     dblParam_[CbcLargestChange] = CoinMax(dblParam_[CbcLargestChange], change);
8159     intParam_[CbcNumberBranches]++;
8160   }
8161   sumChangeObjective1_ += solver_->getObjValue() * solver_->getObjSense()
8162     - objectiveValue;
8163   if (maximumSecondsReached())
8164     numberTries = 0; // exit
8165   if ((moreSpecialOptions2_ & (2048 | 4096)) != 0 && currentDepth_ > 5) {
8166     // howOftenGlobalScan_ = 10;
8167     int type = (moreSpecialOptions2_ & (2048 | 4096)) >> 11;
8168     if (type == 1) {
8169       int n = 0;
8170       int k = currentDepth_;
8171       while (k) {
8172         if ((k & 1) != 0)
8173           n++;
8174         k = k >> 1;
8175       }
8176       if (n > 1)
8177         numberTries = 0;
8178     } else if (type == 2) {
8179       if ((currentDepth_ % 4) != 0)
8180         numberTries = 0;
8181     } else {
8182       if ((currentDepth_ % 8) != 0)
8183         numberTries = 0;
8184     }
8185   }
8186   //if ((numberNodes_%100)==0)
8187   //printf("XXa sum obj changed by %g\n",sumChangeObjective1_);
8188   objectiveValue = solver_->getObjValue() * solver_->getObjSense();
8189   // Return at once if numberTries zero
8190   if (!numberTries) {
8191     cuts = OsiCuts();
8192     numberNewCuts_ = 0;
8193 #ifdef COIN_HAS_CLP
8194     if (clpSolver)
8195       clpSolver->setSpecialOptions(saveClpOptions);
8196 #endif
8197     setPointers(solver_);
8198     return true;
8199   }
8200   /*
8201       Do reduced cost fixing.
8202     */
8203   int xxxxxx = 0;
8204   if (xxxxxx)
8205     solver_->resolve();
8206   reducedCostFix();
8207   /*
8208       Set up for at most numberTries rounds of cut generation. If numberTries is
8209       negative, we'll ignore the minimumDrop_ cutoff and keep generating cuts for
8210       the specified number of rounds.
8211     */
8212   double minimumDrop = minimumDrop_;
8213   bool allowZeroIterations = false;
8214   int maximumBadPasses = 0;
8215   if (numberTries < 0) {
8216     numberTries = -numberTries;
8217     // minimumDrop *= 1.0e-5 ;
8218     // if (numberTries >= -1000000) {
8219     //numberTries=100;
8220     minimumDrop = -1.0;
8221     // }
8222     //numberTries=CoinMax(numberTries,100);
8223     allowZeroIterations = true;
8224   }
8225   int saveNumberTries = numberTries;
8226   /*
8227       Is it time to scan the cuts in order to remove redundant cuts? If so, set
8228       up to do it.
8229     */
8230   int fullScan = 0;
8231   if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_ & 256) != 0) {
8232     fullScan = 1;
8233     if (!numberNodes_ || (specialOptions_ & 256) != 0)
8234       fullScan = 2;
8235     specialOptions_ &= ~256; // mark as full scan done
8236   }
8237 
8238   double direction = solver_->getObjSense();
8239   double startObjective = solver_->getObjValue() * direction;
8240 
8241   currentPassNumber_ = 0;
8242   // Really primalIntegerTolerance; relates to an illposed problem with various
8243   // integer solutions depending on integer tolerance.
8244   //double primalTolerance = 1.0e-7 ;
8245   // We may need to keep going on
8246   bool keepGoing = false;
8247   // Say we have not tried one last time
8248   int numberLastAttempts = 0;
8249   /* Get experimental option as to when to stop adding cuts
8250        0 - old style
8251        1 - new style
8252        2 - new style plus don't break if zero cuts first time
8253        3 - as 2 but last drop has to be >0.1*min to say OK
8254     */
8255   int experimentBreak = (moreSpecialOptions_ >> 11) & 3;
8256   // Whether to increase minimum drop
8257   bool increaseDrop = (moreSpecialOptions_ & 8192) != 0;
8258   for (int i = 0; i < numberCutGenerators_; i++)
8259     generator_[i]->setWhetherInMustCallAgainMode(false);
8260   /*
8261       Begin cut generation loop. Cuts generated during each iteration are
8262       collected in theseCuts. The loop can be divided into four phases:
8263        1) Prep: Fix variables using reduced cost. In the first iteration only,
8264           consider scanning globalCuts_ and activating any applicable cuts.
8265        2) Cut Generation: Call each generator and heuristic registered in the
8266           generator_ and heuristic_ arrays. Newly generated global cuts are
8267           copied to globalCuts_ at this time.
8268        3) Cut Installation and Reoptimisation: Install column and row cuts in
8269           the solver. Copy row cuts to cuts (parameter). Reoptimise.
8270        4) Cut Purging: takeOffCuts() removes inactive cuts from the solver, and
8271           does the necessary bookkeeping in the model.
8272     */
8273   do {
8274     currentPassNumber_++;
8275     numberTries--;
8276     if (numberTries < 0 && keepGoing) {
8277       // switch off all normal generators (by the generator's opinion of normal)
8278       // Intended for situations where the primal problem really isn't complete,
8279       // and there are `not normal' cut generators that will augment.
8280       for (int i = 0; i < numberCutGenerators_; i++) {
8281         if (!generator_[i]->mustCallAgain())
8282           generator_[i]->setSwitchedOff(true);
8283         else
8284           generator_[i]->setWhetherInMustCallAgainMode(true);
8285       }
8286     }
8287     keepGoing = false;
8288     OsiCuts theseCuts;
8289     /*
8290           Scan previously generated global column and row cuts to see if any are
8291           useful.
8292         */
8293     int numberViolated = 0;
8294     if ((currentPassNumber_ == 1 || !numberNodes_) && howOftenGlobalScan_ > 0 && (numberNodes_ % howOftenGlobalScan_) == 0 && (doCutsNow(1) || true)) {
8295       // global column cuts now done in node at top of tree
8296       int numberCuts = numberCutGenerators_ ? globalCuts_.sizeRowCuts() : 0;
8297       if (numberCuts) {
8298         // possibly extend whichGenerator
8299         resizeWhichGenerator(numberViolated, numberViolated + numberCuts);
8300         // only add new cuts up to 10% of current elements
8301         CoinBigIndex numberElements = solver_->getNumElements();
8302         int numberColumns = solver_->getNumCols();
8303         CoinBigIndex maximumAdd = CoinMax(numberElements / 10,
8304                                     static_cast< CoinBigIndex >(2 * numberColumns))
8305           + 100;
8306         double *violations = new double[numberCuts];
8307         int *which = new int[numberCuts];
8308         int numberPossible = 0;
8309         for (int i = 0; i < numberCuts; i++) {
8310           OsiRowCut *thisCut = globalCuts_.rowCutPtr(i);
8311           double violation = thisCut->violated(cbcColSolution_);
8312           if (thisCut->effectiveness() == COIN_DBL_MAX) {
8313             // see if already there
8314             int j;
8315             for (j = 0; j < currentNumberCuts_; j++) {
8316               if (addedCuts_[j] == thisCut)
8317                 break;
8318             }
8319             if (j == currentNumberCuts_)
8320               violation = COIN_DBL_MAX;
8321             //else
8322             //printf("already done??\n");
8323           }
8324           if (violation > 0.005) {
8325             violations[numberPossible] = -violation;
8326             which[numberPossible++] = i;
8327           }
8328         }
8329         CoinSort_2(violations, violations + numberPossible, which);
8330         for (int i = 0; i < numberPossible; i++) {
8331           int k = which[i];
8332           OsiRowCut *thisCut = globalCuts_.rowCutPtr(k);
8333           assert(thisCut->violated(cbcColSolution_) > 0.005 /*primalTolerance*/ || thisCut->effectiveness() == COIN_DBL_MAX);
8334 #define CHECK_DEBUGGER
8335 #ifdef CHECK_DEBUGGER
8336           if ((specialOptions_ & 1) != 0 && !parentModel_) {
8337             CoinAssert(!solver_->getRowCutDebuggerAlways()->invalidCut(*thisCut));
8338           }
8339 #endif
8340 #if 0 //ndef NDEBUG
8341 		printf("Global cut added - violation %g\n",
8342 		       thisCut->violated(cbcColSolution_)) ;
8343 #endif
8344           whichGenerator_[numberViolated++] = 20099;
8345 #ifndef GLOBAL_CUTS_JUST_POINTERS
8346           theseCuts.insert(*thisCut);
8347 #else
8348           theseCuts.insert(thisCut);
8349 #endif
8350           if (violations[i] != -COIN_DBL_MAX)
8351             maximumAdd -= thisCut->row().getNumElements();
8352           if (maximumAdd < 0)
8353             break;
8354         }
8355         delete[] which;
8356         delete[] violations;
8357         numberGlobalViolations_ += numberViolated;
8358       }
8359     }
8360     /*
8361           Generate new cuts (global and/or local) and/or apply heuristics.  If
8362           CglProbing is used, then it should be first as it can fix continuous
8363           variables.
8364 
8365           At present, CglProbing is the only case where generateCuts will return
8366           true. generateCuts actually modifies variable bounds in the solver when
8367           CglProbing indicates that it can fix a variable. Reoptimisation is required
8368           to take full advantage.
8369 
8370           The need to resolve here should only happen after a heuristic solution.
8371         optimalBasisIsAvailable resolves to basisIsAvailable, which seems to be part
8372         of the old OsiSimplex API. Doc'n says `Returns true if a basis is available
8373         and the problem is optimal. Should be used to see if the BinvARow type
8374         operations are possible and meaningful.' Which means any solver other the clp
8375         is probably doing a lot of unnecessary resolves right here.
8376           (Note default OSI implementation of optimalBasisIsAvailable always returns
8377           false.)
8378         */
8379     if (solverCharacteristics_->warmStart() && !solver_->optimalBasisIsAvailable()) {
8380       //printf("XXXXYY no opt basis\n");
8381 #ifdef JJF_ZERO //def COIN_HAS_CLP
8382       //OsiClpSolverInterface * clpSolver
8383       //= dynamic_cast<OsiClpSolverInterface *> (solver_);
8384       int save = 0;
8385       if (clpSolver) {
8386         save = clpSolver->specialOptions();
8387         clpSolver->setSpecialOptions(save | 2048 /*4096*/); // Bonmin <something>
8388       }
8389 #endif
8390       resolve(node ? node->nodeInfo() : NULL, 3);
8391 #ifdef JJF_ZERO //def COIN_HAS_CLP
8392       if (clpSolver)
8393         clpSolver->setSpecialOptions(save);
8394 #if CBC_USEFUL_PRINTING > 1
8395       if (clpSolver->getModelPtr()->numberIterations())
8396         printf("ITS %d pass %d\n",
8397           clpSolver->getModelPtr()->numberIterations(),
8398           currentPassNumber_);
8399 #endif
8400 #endif
8401     }
8402     if (nextRowCut_) {
8403       // branch was a cut - add it
8404       theseCuts.insert(*nextRowCut_);
8405       if (handler_->logLevel() > 1)
8406         nextRowCut_->print();
8407       const OsiRowCut *cut = nextRowCut_;
8408       double lb = cut->lb();
8409       double ub = cut->ub();
8410       int n = cut->row().getNumElements();
8411       const int *column = cut->row().getIndices();
8412       const double *element = cut->row().getElements();
8413       double sum = 0.0;
8414       for (int i = 0; i < n; i++) {
8415         int iColumn = column[i];
8416         double value = element[i];
8417         //if (cbcColSolution_[iColumn]>1.0e-7)
8418         //printf("value of %d is %g\n",iColumn,cbcColSolution_[iColumn]);
8419         sum += value * cbcColSolution_[iColumn];
8420       }
8421       delete nextRowCut_;
8422       nextRowCut_ = NULL;
8423       if (handler_->logLevel() > 1)
8424         printf("applying branch cut, sum is %g, bounds %g %g\n", sum, lb, ub);
8425       // possibly extend whichGenerator
8426       resizeWhichGenerator(numberViolated, numberViolated + 1);
8427       // set whichgenerator (also serves as marker to say don't delete0
8428       whichGenerator_[numberViolated++] = 20098;
8429     }
8430 
8431     // reset probing info
8432     //if (probingInfo_)
8433     //probingInfo_->initializeFixing();
8434     int i;
8435     // If necessary make cut generators work harder
8436     bool strongCuts = (!node && cut_obj[CUT_HISTORY - 1] != -COIN_DBL_MAX && fabs(cut_obj[CUT_HISTORY - 1] - cut_obj[CUT_HISTORY - 2]) < 1.0e-7 + 1.0e-6 * fabs(cut_obj[CUT_HISTORY - 1]));
8437     for (i = 0; i < numberCutGenerators_; i++)
8438       generator_[i]->setIneffectualCuts(strongCuts);
8439     // Print details
8440     if (!node) {
8441       handler_->message(CBC_ROOT_DETAIL, messages_)
8442         << currentPassNumber_
8443         << solver_->getNumRows()
8444         << solver_->getNumRows() - numberRowsAtContinuous_
8445         << solver_->getObjValue()
8446         << CoinMessageEol;
8447     }
8448     //Is Necessary for Bonmin? Always keepGoing if cuts have been generated in last iteration (taken from similar code in Cbc-2.4)
8449     if (solverCharacteristics_->solutionAddsCuts() && numberViolated) {
8450       for (i = 0; i < numberCutGenerators_; i++) {
8451         if (generator_[i]->mustCallAgain()) {
8452           keepGoing = true; // say must go round
8453           break;
8454         }
8455       }
8456     }
8457     if (!keepGoing) {
8458       // Status for single pass of cut generation
8459       int status = 0;
8460       /*
8461           threadMode with bit 2^1 set indicates we should use threads for root cut
8462           generation.
8463         */
8464       if ((threadMode_ & 2) == 0 || numberNodes_) {
8465         status = serialCuts(theseCuts, node, slackCuts, lastNumberCuts);
8466       } else {
8467         // do cuts independently
8468 #ifdef CBC_THREAD
8469         status = parallelCuts(master, theseCuts, node, slackCuts, lastNumberCuts);
8470 #endif
8471       }
8472       // Do we need feasible and violated?
8473       feasible = (status >= 0);
8474       if (status == 1)
8475         keepGoing = true;
8476       else if (status == 2)
8477         numberTries = 0;
8478       if (!feasible)
8479         violated = -2;
8480     }
8481     //if (!feasible)
8482     //break;
8483     /*
8484           End of the loop to exercise each generator - try heuristics
8485           - unless at root node and first pass
8486         */
8487     if ((numberNodes_ || currentPassNumber_ != 1) && (!this->maximumSecondsReached())) {
8488       double *newSolution = new double[numberColumns];
8489       double heuristicValue = getCutoff();
8490       int found = -1; // no solution found
8491       int whereFrom = numberNodes_ ? 4 : 1;
8492       for (i = 0; i < numberHeuristics_; i++) {
8493         // skip if can't run here
8494         if (!heuristic_[i]->shouldHeurRun(whereFrom))
8495           continue;
8496         // see if heuristic will do anything
8497         double saveValue = heuristicValue;
8498         int ifSol = heuristic_[i]->solution(heuristicValue,
8499           newSolution);
8500         //theseCuts) ;
8501         if (ifSol > 0) {
8502           // better solution found
8503           heuristic_[i]->incrementNumberSolutionsFound();
8504           found = i;
8505           incrementUsed(newSolution);
8506           lastHeuristic_ = heuristic_[found];
8507 #ifdef HEURISTIC_INFORM
8508           printf("HEUR %s where %d A\n",
8509             lastHeuristic_->heuristicName(), whereFrom);
8510 #endif
8511           // CBC_ROUNDING is symbolic; just says found by heuristic
8512           setBestSolution(CBC_ROUNDING, heuristicValue, newSolution);
8513           whereFrom |= 8; // say solution found
8514         } else if (ifSol < 0) {
8515           heuristicValue = saveValue;
8516         }
8517       }
8518       /*
8519               Did any of the heuristics turn up a new solution? Record it before we free
8520               the vector.
8521             */
8522       if (found >= 0) {
8523         phase_ = 4;
8524         CbcTreeLocal *tree
8525           = dynamic_cast< CbcTreeLocal * >(tree_);
8526         if (tree)
8527           tree->passInSolution(bestSolution_, heuristicValue);
8528       }
8529       delete[] newSolution;
8530     }
8531     CbcEventHandler *eventHandler = getEventHandler();
8532     if (eventHandler) {
8533       // Massage cuts??
8534       // save appData
8535       void *saveAppData = getApplicationData();
8536       // point to cuts
8537       setApplicationData(&theseCuts);
8538       eventHandler->event(CbcEventHandler::generatedCuts);
8539       setApplicationData(saveAppData);
8540     }
8541 #ifdef JJF_ZERO
8542     // switch on to get all cuts printed
8543     theseCuts.printCuts();
8544 #endif
8545     int numberColumnCuts = theseCuts.sizeColCuts();
8546     int numberRowCuts = theseCuts.sizeRowCuts();
8547     if (violated >= 0)
8548       violated = numberRowCuts + numberColumnCuts;
8549     /*
8550           Apply column cuts (aka bound tightening). This may be partially redundant
8551           for column cuts returned by CglProbing, as generateCuts installs bounds
8552           from CglProbing when it determines it can fix a variable.
8553 
8554           TODO: Looks like the use of violated has evolved. The value set above is
8555         	completely ignored. All that's left is violated == -1 indicates some
8556         	cut is violated, violated == -2 indicates infeasibility. Only
8557         	infeasibility warrants exceptional action.
8558 
8559           TODO: Strikes me that this code will fail to detect infeasibility, because
8560         	the breaks escape the inner loops but the outer loop keeps going.
8561         	Infeasibility in an early cut will be overwritten if a later cut is
8562         	merely violated.
8563         */
8564     if (numberColumnCuts) {
8565 
8566 #ifdef CBC_DEBUG
8567       double *oldLower = new double[numberColumns];
8568       double *oldUpper = new double[numberColumns];
8569       memcpy(oldLower, cbcColLower_, numberColumns * sizeof(double));
8570       memcpy(oldUpper, cbcColUpper_, numberColumns * sizeof(double));
8571 #endif
8572 
8573       double integerTolerance = getDblParam(CbcIntegerTolerance);
8574       for (int i = 0; i < numberColumnCuts; i++) {
8575         const OsiColCut *thisCut = theseCuts.colCutPtr(i);
8576         const CoinPackedVector &lbs = thisCut->lbs();
8577         const CoinPackedVector &ubs = thisCut->ubs();
8578         int j;
8579         int n;
8580         const int *which;
8581         const double *values;
8582         n = lbs.getNumElements();
8583         which = lbs.getIndices();
8584         values = lbs.getElements();
8585         for (j = 0; j < n; j++) {
8586           int iColumn = which[j];
8587           double value = cbcColSolution_[iColumn];
8588 #if CBC_DEBUG > 1
8589           printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn],
8590             cbcColSolution_[iColumn], oldUpper[iColumn], values[j]);
8591 #endif
8592           solver_->setColLower(iColumn, values[j]);
8593           if (value < values[j] - integerTolerance)
8594             violated = -1;
8595           if (values[j] > cbcColUpper_[iColumn] + integerTolerance) {
8596             // infeasible
8597             violated = -2;
8598             break;
8599           }
8600         }
8601         n = ubs.getNumElements();
8602         which = ubs.getIndices();
8603         values = ubs.getElements();
8604         for (j = 0; j < n; j++) {
8605           int iColumn = which[j];
8606           double value = cbcColSolution_[iColumn];
8607 #if CBC_DEBUG > 1
8608           printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn],
8609             cbcColSolution_[iColumn], oldUpper[iColumn], values[j]);
8610 #endif
8611           solver_->setColUpper(iColumn, values[j]);
8612           if (value > values[j] + integerTolerance)
8613             violated = -1;
8614           if (values[j] < cbcColLower_[iColumn] - integerTolerance) {
8615             // infeasible
8616             violated = -2;
8617             break;
8618           }
8619         }
8620       }
8621 #ifdef CBC_DEBUG
8622       delete[] oldLower;
8623       delete[] oldUpper;
8624 #endif
8625     }
8626     /*
8627           End installation of column cuts. The break here escapes the numberTries
8628           loop.
8629         */
8630     if (violated == -2 || !feasible) {
8631       // infeasible
8632       feasible = false;
8633       violated = -2;
8634       if (!numberNodes_)
8635         messageHandler()->message(CBC_INFEAS,
8636           messages())
8637           << CoinMessageEol;
8638       break;
8639     }
8640     /*
8641           Now apply the row (constraint) cuts. This is a bit more work because we need
8642           to obtain and augment the current basis.
8643 
8644           TODO: Why do this work, if there are no row cuts? The current basis will do
8645         	just fine.
8646         */
8647     int numberRowsNow = solver_->getNumRows();
8648 #ifndef NDEBUG
8649     assert(numberRowsNow == numberRowsAtStart + lastNumberCuts);
8650 #else
8651     // ? maybe clue to threaded problems
8652     if (numberRowsNow != numberRowsAtStart + lastNumberCuts) {
8653       fprintf(stderr, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n",
8654         numberRowsNow, numberRowsAtStart, lastNumberCuts);
8655       fprintf(stdout, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n",
8656         numberRowsNow, numberRowsAtStart, lastNumberCuts);
8657       abort();
8658     }
8659 #endif
8660     int numberToAdd = theseCuts.sizeRowCuts();
8661     numberNewCuts_ = lastNumberCuts + numberToAdd;
8662     // resize whichGenerator
8663     resizeWhichGenerator(lastNumberCuts, numberNewCuts_);
8664     /*
8665           Now actually add the row cuts and reoptimise.
8666 
8667           Install the cuts in the solver using applyRowCuts and
8668           augment the basis with the corresponding slack. We also add each row cut to
8669           the set of row cuts (cuts.insert()) supplied as a parameter. The new basis
8670           must be set with setWarmStart().
8671 
8672           TODO: Seems to me the original code could allocate addCuts with size 0, if
8673         	numberRowCuts was 0 and numberColumnCuts was nonzero. That might
8674         	explain the memory fault noted in the comment by AJK.  Unfortunately,
8675         	just commenting out the delete[] results in massive memory leaks. Try
8676         	a revision to separate the row cut case. Why do we need addCuts at
8677         	all? A typing issue, apparently: OsiCut vs. OsiRowCut.
8678 
8679           TODO: It looks to me as if numberToAdd and numberRowCuts are identical at
8680         	this point. Confirm & get rid of one of them.
8681 
8682           TODO: Any reason why the three loops can't be consolidated?
8683         */
8684     const OsiRowCut **addCuts = NULL;
8685     if (numberRowCuts > 0 || numberColumnCuts > 0) {
8686       if (numberToAdd > 0) {
8687         int i;
8688         int *whichGenerator = whichGenerator_ + lastNumberCuts;
8689         // Faster to add all at once
8690         addCuts = new const OsiRowCut *[numberToAdd];
8691         for (i = 0; i < numberToAdd; i++) {
8692           addCuts[i] = &theseCuts.rowCut(i);
8693           whichGenerator[i] = 90;
8694         }
8695         if ((specialOptions_ & 262144) != 0 && !parentModel_) {
8696           //save
8697           for (i = 0; i < numberToAdd; i++)
8698             storedRowCuts_->addCut(*addCuts[i]);
8699         }
8700         solver_->applyRowCuts(numberToAdd, addCuts);
8701         CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
8702         assert(basis != NULL); // make sure not volume
8703         /* dylp bug
8704 
8705                   Consistent size used by OsiDylp as sanity check. Implicit resize seen
8706                   as an error. Hence this call to resize is necessary.
8707                 */
8708         basis->resize(numberRowsAtStart + numberNewCuts_, numberColumns);
8709         for (i = 0; i < numberToAdd; i++) {
8710           basis->setArtifStatus(numberRowsNow + i,
8711             CoinWarmStartBasis::basic);
8712         }
8713         if (solver_->setWarmStart(basis) == false) {
8714           throw CoinError("Fail setWarmStart() after cut installation.",
8715             "solveWithCuts", "CbcModel");
8716         }
8717         delete basis;
8718       }
8719       //solver_->setHintParam(OsiDoDualInResolve,false,OsiHintTry);
8720       feasible = (resolve(node ? node->nodeInfo() : NULL, 2) != 0);
8721       //solver_->setHintParam(OsiDoDualInResolve,true,OsiHintTry);
8722       if (maximumSecondsReached()) {
8723         numberTries = -1000; // exit
8724         feasible = false;
8725         delete[] addCuts;
8726         break;
8727       }
8728 #ifdef CBC_DEBUG
8729       printf("Obj value after cuts %g %d rows\n", solver_->getObjValue(),
8730         solver_->getNumRows());
8731       if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
8732         assert(feasible);
8733 #endif
8734     }
8735     /*
8736           No cuts. Cut short the cut generation (numberTries) loop.
8737         */
8738     else if (numberLastAttempts > 2 || experimentBreak < 2) {
8739       numberTries = 0;
8740     }
8741     /*
8742           If the problem is still feasible, first, call takeOffCuts() to remove cuts
8743           that are now slack. takeOffCuts() will call the solver to reoptimise if
8744           that's needed to restore a valid solution.
8745 
8746           Next, see if we should quit due to diminishing returns:
8747             * we've tried three rounds of cut generation and we're getting
8748               insufficient improvement in the objective; or
8749             * we generated no cuts; or
8750             * the solver declared optimality with 0 iterations after we added the
8751               cuts generated in this round.
8752           If we decide to keep going, prep for the next iteration.
8753 
8754           It just seems more safe to tell takeOffCuts() to call resolve(), even if
8755           we're not continuing cut generation. Otherwise code executed between here
8756           and final disposition of the node will need to be careful not to access the
8757           lp solution. It can happen that we lose feasibility in takeOffCuts ---
8758           numerical jitters when the cutoff bound is epsilon less than the current
8759           best, and we're evaluating an alternative optimum.
8760 
8761           TODO: After successive rounds of code motion, there seems no need to
8762         	distinguish between the two checks for aborting the cut generation
8763         	loop. Confirm and clean up.
8764         */
8765     if (feasible) {
8766       int cutIterations = solver_->getIterationCount();
8767       if (numberOldActiveCuts_ + numberNewCuts_
8768         && (numberNewCuts_ || doCutsNow(1))) {
8769         OsiCuts *saveCuts = node ? NULL : &slackCuts;
8770         int nDel = takeOffCuts(cuts, resolveAfterTakeOffCuts_, saveCuts, numberToAdd, addCuts);
8771         if (nDel)
8772           lastNumberCuts2_ = 0;
8773         if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) {
8774           feasible = false;
8775 #ifdef CBC_DEBUG
8776           double z = solver_->getObjValue();
8777           double cut = getCutoff();
8778           printf("Lost feasibility by %g in takeOffCuts; z = %g, cutoff = %g\n",
8779             z - cut, z, cut);
8780 #endif
8781         }
8782       }
8783       delete[] addCuts;
8784       if (feasible) {
8785         numberRowsAtStart = numberOldActiveCuts_ + numberRowsAtContinuous_;
8786         lastNumberCuts = numberNewCuts_;
8787         double thisObj = direction * solver_->getObjValue();
8788         bool badObj = (allowZeroIterations) ? thisObj < cut_obj[0] + minimumDrop
8789                                             : thisObj < cut_obj[CUT_HISTORY - 1] + minimumDrop;
8790 #ifdef JJF_ZERO // probably not a good idea
8791         if (!badObj)
8792           numberLastAttempts = CoinMax(0, numberLastAttempts - 1);
8793 #endif
8794         // Compute maximum number of bad passes
8795         if (minimumDrop > 0.0) {
8796           if (increaseDrop) {
8797             // slowly increase minimumDrop; breakpoints are rule-of-thumb
8798             if (currentPassNumber_ == 13)
8799               minimumDrop = CoinMax(1.5 * minimumDrop, 1.0e-5 * fabs(thisObj));
8800             else if (currentPassNumber_ > 20 && (currentPassNumber_ % 5) == 0)
8801               minimumDrop = CoinMax(1.1 * minimumDrop, 1.0e-5 * fabs(thisObj));
8802             else if (currentPassNumber_ > 50)
8803               minimumDrop = CoinMax(1.1 * minimumDrop, 1.0e-5 * fabs(thisObj));
8804           }
8805           int nBadPasses = 0;
8806           // The standard way of determining escape
8807           if (!experimentBreak) {
8808             double test = 0.01 * minimumDrop;
8809             double goodDrop = COIN_DBL_MAX;
8810             for (int j = CUT_HISTORY - 1; j >= 0; j--) {
8811               if (thisObj - cut_obj[j] < test) {
8812                 nBadPasses++;
8813               } else {
8814                 goodDrop = (thisObj - cut_obj[j]) / static_cast< double >(nBadPasses + 1);
8815                 break;
8816               }
8817             }
8818             maximumBadPasses = CoinMax(maximumBadPasses, nBadPasses);
8819             if (nBadPasses < maximumBadPasses && goodDrop > minimumDrop)
8820               badObj = false; // carry on
8821           } else {
8822             // Experimental escape calculations
8823             //if (currentPassNumber_==13||currentPassNumber_>50)
8824             //minimumDrop = CoinMax(1.5*minimumDrop,1.0e-5*fabs(thisObj));
8825             double test = 0.1 * minimumDrop;
8826             double goodDrop = (thisObj - cut_obj[0]) / static_cast< double >(CUT_HISTORY);
8827             double objValue = thisObj;
8828             for (int j = CUT_HISTORY - 1; j >= 0; j--) {
8829               if (objValue - cut_obj[j] < test) {
8830                 nBadPasses++;
8831                 objValue = cut_obj[j];
8832               } else {
8833                 break;
8834               }
8835             }
8836 #if CBC_USEFUL_PRINTING > 12
8837             if (!parentModel_ && !numberNodes_)
8838               printf("badObj %s nBad %d maxBad %d goodDrop %g minDrop %g thisDrop %g obj %g\n",
8839                 badObj ? "true" : "false",
8840                 nBadPasses, maximumBadPasses, goodDrop, minimumDrop,
8841                 thisObj - cut_obj[CUT_HISTORY - 1],
8842                 solver_->getObjValue());
8843 #endif
8844             maximumBadPasses = CoinMax(maximumBadPasses, nBadPasses);
8845             if (nBadPasses < 2 || goodDrop > 2.0 * minimumDrop) {
8846               if (experimentBreak <= 2 || goodDrop > 0.1 * minimumDrop)
8847                 badObj = false; // carry on
8848             }
8849             if (experimentBreak > 1 && goodDrop < minimumDrop)
8850               numberLastAttempts++;
8851           }
8852         }
8853         // magic numbers, they seemed reasonable; there's a possibility here of going more than
8854         // nominal number of passes if we're doing really well.
8855         if (numberTries == 1 && currentDepth_ < 12 && currentPassNumber_ < 10) {
8856           double drop[12] = { 1.0, 2.0, 3.0, 10.0, 10.0, 10.0, 10.0, 20.0, 100.0, 100.0, 1000.0, 1000.0 };
8857           if (thisObj - lastObjective > drop[currentDepth_] * minimumDrop) {
8858             numberTries++;
8859 #if CBC_USEFUL_PRINTING > 1
8860             //printf("drop %g %g %d\n",thisObj,lastObjective,currentPassNumber_);
8861 #endif
8862           }
8863         }
8864         for (int j = 0; j < CUT_HISTORY - 1; j++)
8865           cut_obj[j] = cut_obj[j + 1];
8866         cut_obj[CUT_HISTORY - 1] = thisObj;
8867         bool allowEarlyTermination = currentPassNumber_ >= 10;
8868         if (currentDepth_ > 10 || (currentDepth_ > 5 && numberColumns > 200))
8869           allowEarlyTermination = true;
8870         //if (badObj && (currentPassNumber_ >= 10 || (currentDepth_>10))
8871         if (badObj && allowEarlyTermination
8872           //&&(currentPassNumber_>=10||lastObjective>firstObjective)
8873           && !keepGoing) {
8874           numberTries = 0;
8875         }
8876         if (numberRowCuts + numberColumnCuts == 0 || (cutIterations == 0 && !allowZeroIterations)) {
8877           // maybe give it one more try
8878           if (numberLastAttempts > 2 || currentDepth_ || experimentBreak < 2)
8879             numberTries = 0;
8880           else
8881             numberLastAttempts++;
8882         }
8883         if (numberTries > 0) {
8884           reducedCostFix();
8885           lastObjective = direction * solver_->getObjValue();
8886         }
8887       }
8888     } else {
8889       // not feasible
8890       delete[] addCuts;
8891     }
8892     /*
8893           We've lost feasibility --- this node won't be referencing the cuts we've
8894           been collecting, so decrement the reference counts.
8895         */
8896     if (!feasible) {
8897       int i;
8898       if (currentNumberCuts_) {
8899         lockThread();
8900         for (i = 0; i < currentNumberCuts_; i++) {
8901           // take off node
8902           if (addedCuts_[i]) {
8903             if (!addedCuts_[i]->decrement())
8904               delete addedCuts_[i];
8905             addedCuts_[i] = NULL;
8906           }
8907         }
8908         unlockThread();
8909       }
8910       numberTries = 0;
8911       keepGoing = false;
8912     }
8913     if (numberTries == 0 && feasible && !keepGoing && !parentModel_ && !numberNodes_) {
8914       for (int i = 0; i < numberCutGenerators_; i++) {
8915         if (generator_[i]->whetherCallAtEnd()
8916           && !generator_[i]->whetherInMustCallAgainMode()) {
8917           // give it some goes and switch off
8918           numberTries = (saveNumberTries + 4) / 5;
8919           generator_[i]->setWhetherCallAtEnd(false);
8920         }
8921       }
8922     }
8923   } while ( (numberTries > 0 || keepGoing) && (!this->maximumSecondsReached()) );
8924   /*
8925       End cut generation loop.
8926     */
8927   {
8928     // switch on
8929     for (int i = 0; i < numberCutGenerators_; i++)
8930       generator_[i]->setSwitchedOff(false);
8931   }
8932   //check feasibility.
8933   //If solution seems to be integer feasible calling setBestSolution
8934   //will eventually add extra global cuts which we need to install at
8935   //the nodes
8936 
8937   if (feasible && solverCharacteristics_->solutionAddsCuts()) { //check integer feasibility
8938     bool integerFeasible = true;
8939     const double *save = testSolution_;
8940     testSolution_ = solver_->getColSolution();
8941     // point to useful information
8942     OsiBranchingInformation usefulInfo = usefulInformation();
8943     for (int i = 0; i < numberObjects_ && integerFeasible; i++) {
8944       double infeasibility = object_[i]->checkInfeasibility(&usefulInfo);
8945       if (infeasibility)
8946         integerFeasible = false;
8947     }
8948     testSolution_ = save;
8949     // Consider the possibility that some alternatives here only make sense in context
8950     // of bonmin.
8951     if (integerFeasible) { //update
8952       double objValue = solver_->getObjValue();
8953       int numberGlobalBefore = globalCuts_.sizeRowCuts();
8954       // SOLUTION2 so won't up cutoff or print message
8955       setBestSolution(CBC_SOLUTION2, objValue,
8956         solver_->getColSolution(), 0);
8957       int numberGlobalAfter = globalCuts_.sizeRowCuts();
8958       int numberToAdd = numberGlobalAfter - numberGlobalBefore;
8959       if (numberToAdd > 0)
8960       //We have added some cuts say they are tight at that node
8961       //Basis and lp should already have been updated
8962       {
8963         feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached());
8964         if (feasible) {
8965           int numberCuts = numberNewCuts_ = cuts.sizeRowCuts();
8966           // possibly extend whichGenerator
8967           resizeWhichGenerator(numberCuts, numberToAdd + numberCuts);
8968 
8969           for (int i = numberGlobalBefore; i < numberGlobalAfter; i++) {
8970             whichGenerator_[numberNewCuts_++] = 20099;
8971 #ifndef GLOBAL_CUTS_JUST_POINTERS
8972             cuts.insert(*globalCuts_.rowCutPtr(i));
8973 #else
8974             OsiRowCut *rowCutPointer = globalCuts_.rowCutPtr(i);
8975             cuts.insert(rowCutPointer);
8976 #endif
8977           }
8978           numberNewCuts_ = lastNumberCuts + numberToAdd;
8979           //now take off the cuts which are not tight anymore
8980           takeOffCuts(cuts, resolveAfterTakeOffCuts_, NULL);
8981           if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) {
8982             feasible = false;
8983           }
8984         }
8985         if (!feasible) { //node will be fathomed
8986           lockThread();
8987           for (int i = 0; i < currentNumberCuts_; i++) {
8988             // take off node
8989             if (addedCuts_[i]) {
8990               if (!addedCuts_[i]->decrement())
8991                 delete addedCuts_[i];
8992               addedCuts_[i] = NULL;
8993             }
8994           }
8995           unlockThread();
8996         }
8997       }
8998     }
8999   }
9000   /*
9001     End of code block to check for a solution, when cuts may be added as a result
9002     of a feasible solution.
9003 
9004       Reduced cost fix at end. Must also check feasible, in case we've popped out
9005       because a generator indicated we're infeasible.
9006     */
9007   if (feasible && solver_->isProvenOptimal())
9008     reducedCostFix();
9009   // If at root node do heuristics
9010   if (!numberNodes_ && !maximumSecondsReached()) {
9011     // First see if any cuts are slack
9012     int numberRows = solver_->getNumRows();
9013     int numberAdded = numberRows - numberRowsAtContinuous_;
9014     if (numberAdded) {
9015       CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
9016       assert(basis != NULL);
9017       int *added = new int[numberAdded];
9018       int nDelete = 0;
9019       for (int j = numberRowsAtContinuous_; j < numberRows; j++) {
9020         if (basis->getArtifStatus(j) == CoinWarmStartBasis::basic) {
9021           //printf("%d slack!\n",j);
9022           added[nDelete++] = j;
9023         }
9024       }
9025       if (nDelete) {
9026         solver_->deleteRows(nDelete, added);
9027       }
9028       delete[] added;
9029       delete basis;
9030     }
9031     // mark so heuristics can tell
9032     int savePass = currentPassNumber_;
9033     currentPassNumber_ = 999999;
9034     double *newSolution = new double[numberColumns];
9035     double heuristicValue = getCutoff();
9036     int found = -1; // no solution found
9037     if (feasible) {
9038       int whereFrom = node ? 3 : 2;
9039       for (int i = 0; i < numberHeuristics_; i++) {
9040         // skip if can't run here
9041         if (!heuristic_[i]->shouldHeurRun(whereFrom))
9042           continue;
9043         // see if heuristic will do anything
9044         double saveValue = heuristicValue;
9045         int ifSol = heuristic_[i]->solution(heuristicValue,
9046           newSolution);
9047         if (ifSol > 0) {
9048           // better solution found
9049           heuristic_[i]->incrementNumberSolutionsFound();
9050           found = i;
9051           incrementUsed(newSolution);
9052           lastHeuristic_ = heuristic_[found];
9053 #ifdef HEURISTIC_INFORM
9054           printf("HEUR %s where %d B\n",
9055             lastHeuristic_->heuristicName(), whereFrom);
9056 #endif
9057           setBestSolution(CBC_ROUNDING, heuristicValue, newSolution);
9058           whereFrom |= 8; // say solution found
9059         } else {
9060           heuristicValue = saveValue;
9061         }
9062       }
9063     }
9064     currentPassNumber_ = savePass;
9065     if (found >= 0) {
9066       phase_ = 4;
9067     }
9068     delete[] newSolution;
9069   }
9070   // Up change due to cuts
9071   if (feasible)
9072     sumChangeObjective2_ += solver_->getObjValue() * solver_->getObjSense()
9073       - objectiveValue;
9074     //if ((numberNodes_%100)==0)
9075     //printf("XXb sum obj changed by %g\n",sumChangeObjective2_);
9076     /*
9077       End of cut generation loop.
9078 
9079       Now, consider if we want to disable or adjust the frequency of use for any
9080       of the cut generators. If the client specified a positive number for
9081       howOften, it will never change. If the original value was negative, it'll
9082       be converted to 1000000+|howOften|, and this value will be adjusted each
9083       time fullScan is true. Actual cut generation is performed every
9084       howOften%1000000 nodes; the 1000000 offset is just a convenient way to
9085       specify that the frequency is adjustable.
9086 
9087       During cut generation, we recorded the number of cuts produced by each
9088       generator for this node. For all cuts, whichGenerator records the generator
9089       that produced a cut.
9090 
9091       TODO: All this should probably be hidden in a method of the CbcCutGenerator
9092       class.
9093     lh:
9094     TODO: Can the loop that scans over whichGenerator to accumulate per
9095     generator counts be replaced by values in countRowCuts and
9096     countColumnCuts?
9097 
9098     << I think the answer is yes, but not the other way 'round. Row and
9099        column cuts are block interleaved in whichGenerator. >>
9100 
9101     The root is automatically a full scan interval. At the root, decide if
9102     we're going to do cuts in the tree, and whether we should keep the cuts we
9103     have.
9104 
9105     Codes for willBeCutsInTree:
9106     -1: no cuts in tree and currently active cuts seem ineffective; delete
9107     them
9108      0: no cuts in tree but currently active cuts seem effective; make them
9109     into architecturals (faster than treating them as cuts)
9110      1: cuts will be generated in the tree; currently active cuts remain as
9111     cuts
9112     -lh
9113     */
9114 #ifdef NODE_LOG
9115   int fatherNum = (node == NULL) ? -1 : node->nodeNumber();
9116   double value = (node == NULL) ? -1 : node->branchingObject()->value();
9117   string bigOne = (solver_->getIterationCount() > 30) ? "*******" : "";
9118   string way = (node == NULL) ? "" : (node->branchingObject()->way()) == 1 ? "Down" : "Up";
9119   std::cout << "Node " << numberNodes_ << ", father " << fatherNum << ", #iterations " << solver_->getIterationCount() << ", sol value : " << solver_->getObjValue() << std::endl;
9120 #endif
9121   if (fullScan && numberCutGenerators_) {
9122     /* If cuts just at root node then it will probably be faster to
9123            update matrix and leave all in */
9124     int willBeCutsInTree = 0;
9125     double thisObjective = solver_->getObjValue() * direction;
9126     // get sizes
9127     int numberRowsAdded = solver_->getNumRows() - numberRowsAtStart;
9128     CoinBigIndex numberElementsAdded = solver_->getNumElements() - numberElementsAtStart;
9129     double densityOld = static_cast< double >(numberElementsAtStart) / static_cast< double >(numberRowsAtStart);
9130     double densityNew = numberRowsAdded ? (static_cast< double >(numberElementsAdded)) / static_cast< double >(numberRowsAdded)
9131                                         : 0.0;
9132     /*
9133           If we're at the root, and we added cuts, and the cuts haven't changed the
9134           objective, and the cuts resulted in a significant increase (> 20%) in nonzero
9135           coefficients, do no cuts in the tree and ditch the current cuts. They're not
9136           cost-effective.
9137         */
9138     if (!numberNodes_) {
9139       if (!parentModel_) {
9140         //printf("%d global cuts\n",globalCuts_.sizeRowCuts()) ;
9141         if ((specialOptions_ & 1) != 0) {
9142           //specialOptions_ &= ~1;
9143           int numberCuts = globalCuts_.sizeRowCuts();
9144           const OsiRowCutDebugger *debugger = continuousSolver_->getRowCutDebugger();
9145           if (debugger) {
9146             for (int i = 0; i < numberCuts; i++) {
9147               OsiRowCut *cut = globalCuts_.rowCutPtr(i);
9148               if (debugger->invalidCut(*cut)) {
9149                 continuousSolver_->applyRowCuts(1, cut);
9150                 continuousSolver_->writeMps("bad");
9151                 printf("BAD cut\n");
9152               }
9153               //CoinAssert (!debugger->invalidCut(*cut));
9154             }
9155           }
9156         }
9157       }
9158       //solver_->writeMps("second");
9159       if (numberRowsAdded)
9160         handler_->message(CBC_CUTS_STATS, messages_)
9161           << numberRowsAdded
9162           << densityNew
9163           << CoinMessageEol;
9164       if (thisObjective - startObjective < 1.0e-5 && numberElementsAdded > 0.2 * numberElementsAtStart)
9165         willBeCutsInTree = -1;
9166       int whenC = whenCuts_;
9167       if (whenC == 999999 || whenC == 999998) {
9168         int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols();
9169         bool smallProblem = size <= 550;
9170         smallProblem = false;
9171 #if CBC_USEFUL_PRINTING > 1
9172         int maxPass = maximumCutPasses_;
9173 #endif
9174         if (thisObjective - startObjective < 1.0e-5) {
9175           // No change in objective function
9176           if (numberElementsAdded > 0.2 * numberElementsAtStart) {
9177             if (whenCuts_ == 999999) {
9178               whenCuts_ = 5000010;
9179               if (!smallProblem)
9180                 maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
9181             } else if (whenCuts_ == 999998) {
9182               whenCuts_ = 5000010;
9183               if (!smallProblem)
9184                 maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
9185             }
9186 #ifdef JJF_ZERO
9187           } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) {
9188             if (whenCuts_ == 999999) {
9189               whenCuts_ = 8000008;
9190               maximumCutPasses_ = 1;
9191             } else if (whenCuts_ == 999998) {
9192               whenCuts_ = 10000008;
9193               maximumCutPasses_ = 1;
9194             }
9195           } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) {
9196             if (whenCuts_ == 999999) {
9197               whenCuts_ = 8000008;
9198               maximumCutPasses_ = 1;
9199             } else if (whenCuts_ == 999998) {
9200               whenCuts_ = 10000006;
9201               maximumCutPasses_ = 1;
9202             }
9203           } else if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) {
9204             if (whenCuts_ == 999999) {
9205               whenCuts_ = 8000008;
9206               maximumCutPasses_ = 1;
9207             } else if (whenCuts_ == 999998) {
9208               whenCuts_ = 10000004;
9209               maximumCutPasses_ = 1;
9210             }
9211 #endif
9212           } else {
9213             if (whenCuts_ == 999999) {
9214               whenCuts_ = 8000008;
9215               if (!smallProblem)
9216                 maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
9217             } else if (whenCuts_ == 999998) {
9218               whenCuts_ = 10000004;
9219               if (!smallProblem)
9220                 maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
9221             }
9222           }
9223         } else {
9224           // Objective changed
9225 #ifdef JJF_ZERO
9226           if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) {
9227             if (whenCuts_ == 999999) {
9228               whenCuts_ = 8000008;
9229               maximumCutPasses_ = 1;
9230             } else if (whenCuts_ == 999998) {
9231               whenCuts_ = 10000008;
9232               maximumCutPasses_ = 1;
9233             }
9234           } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) {
9235             if (whenCuts_ == 999999) {
9236               whenCuts_ = 8000008;
9237               maximumCutPasses_ = 1;
9238             } else if (whenCuts_ == 999998) {
9239               whenCuts_ = 10000004;
9240               maximumCutPasses_ = 1;
9241             }
9242           } else
9243 #endif
9244             if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) {
9245             if (whenCuts_ == 999999) {
9246               whenCuts_ = 8000008;
9247               if (!smallProblem)
9248                 maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
9249             } else if (whenCuts_ == 999998) {
9250               whenCuts_ = 10000004;
9251               if (!smallProblem)
9252                 maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1);
9253             }
9254           } else {
9255             if (whenCuts_ == 999999) {
9256               whenCuts_ = 10000004;
9257               maximumCutPasses_ = CoinMax(maximumCutPasses_, 2);
9258             } else if (whenCuts_ == 999998) {
9259               whenCuts_ = 11000002;
9260               maximumCutPasses_ = CoinMax(maximumCutPasses_, 2);
9261             }
9262           }
9263         }
9264         // Set bit to say don't try too hard if seems reasonable
9265         if (maximumCutPasses_ <= 5)
9266           whenCuts_ += 100000;
9267           //// end
9268 #if CBC_USEFUL_PRINTING > 1
9269         printf("changing whenCuts from %d to %d and cutPasses from %d to %d objchange %g\n",
9270           whenC, whenCuts_, maxPass, maximumCutPasses_, thisObjective - startObjective);
9271 #endif
9272       }
9273     }
9274     /*
9275           Noop block 071219.
9276         */
9277     if ((numberRowsAdded > 100 + 0.5 * numberRowsAtStart
9278           || numberElementsAdded > 0.5 * numberElementsAtStart)
9279       && (densityNew > 200.0 && numberRowsAdded > 100 && densityNew > 2.0 * densityOld)) {
9280       // much bigger
9281       //if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5)
9282       //willBeCutsInTree=-1;
9283       //printf("Cuts will be taken off , %d rows added with density %g\n",
9284       //     numberRowsAdded,densityNew);
9285     }
9286     /*
9287           Noop block 071219.
9288         */
9289     if (densityNew > 100.0 && numberRowsAdded > 2 && densityNew > 2.0 * densityOld) {
9290       //if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5)
9291       //willBeCutsInTree=-2;
9292       //printf("Density says no cuts ? , %d rows added with density %g\n",
9293       //     numberRowsAdded,densityNew);
9294     }
9295     // Root node or every so often - see what to turn off
9296     /*
9297           Hmmm ... > -90 for any generator will overrule previous decision to do no
9298           cuts in tree and delete existing cuts.
9299         */
9300     int i;
9301     for (i = 0; i < numberCutGenerators_; i++) {
9302       int howOften = generator_[i]->howOften();
9303       if (howOften > -90)
9304         willBeCutsInTree = 0;
9305     }
9306     if (!numberNodes_) {
9307       handler_->message(CBC_ROOT, messages_)
9308         << numberNewCuts_
9309         << startObjective << thisObjective
9310         << currentPassNumber_
9311         << CoinMessageEol;
9312       // do heuristics again! if feasibility pump still exists
9313       if ((specialOptions_ & 33554432) != 0 && !parentModel_) {
9314         specialOptions_ &= ~33554432;
9315         doHeuristicsAtRoot();
9316       }
9317     }
9318     /*
9319           Count the number of cuts produced by each cut generator on this call. Not
9320           clear to me that the accounting is equivalent here. whichGenerator_ records
9321           the generator for column and row cuts. So unless numberNewCuts is row cuts
9322           only, we're double counting for JUST_ACTIVE. Note too the multiplier applied
9323           to column cuts.
9324         */
9325     if (!numberNodes_) {
9326       double value = CoinMax(minimumDrop_, 0.005 * (thisObjective - startObjective) / static_cast< double >(currentPassNumber_));
9327       if (numberColumns < 200)
9328         value = CoinMax(minimumDrop_, 0.1 * value);
9329 #if CBC_USEFUL_PRINTING > 1
9330       printf("Minimum drop for cuts was %g, now is %g\n", minimumDrop_, value);
9331 #endif
9332       minimumDrop_ = value;
9333     }
9334     int *count = new int[numberCutGenerators_];
9335     memset(count, 0, numberCutGenerators_ * sizeof(int));
9336     int numberActiveGenerators = 0;
9337     for (i = 0; i < numberNewCuts_; i++) {
9338       int iGenerator = whichGenerator_[i];
9339       //assert (iGenerator>=0);
9340       if (iGenerator >= 0)
9341         iGenerator = iGenerator % 10000;
9342       if (iGenerator >= 0 && iGenerator < numberCutGenerators_)
9343         count[iGenerator]++;
9344     }
9345     // add in any active cuts if at root node (for multiple solvers)
9346 #ifdef CHECK_KNOWN_SOLUTION
9347     if (onOptimalPath && (solver_->isDualObjectiveLimitReached() || !feasible)) {
9348       printf("help 2\n");
9349     }
9350 #endif
9351     if (!numberNodes_) {
9352       for (i = 0; i < numberCutGenerators_; i++)
9353         count[i] += generator_[i]->numberCutsActive();
9354     }
9355     double totalCuts = 0.0;
9356     //#define JUST_ACTIVE
9357     for (i = 0; i < numberCutGenerators_; i++) {
9358       if (generator_[i]->numberCutsInTotal() || generator_[i]->numberColumnCuts())
9359         numberActiveGenerators++;
9360 #ifdef JUST_ACTIVE
9361       double value = count[i];
9362 #else
9363       double value = generator_[i]->numberCutsInTotal();
9364 #endif
9365       totalCuts += value;
9366     }
9367     /*
9368           Open up a loop to step through the cut generators and decide what (if any)
9369           adjustment should be made for calling frequency.
9370         */
9371     int iProbing = -1;
9372     double smallProblem = (0.2 * totalCuts) / static_cast< double >(numberActiveGenerators + 1.0e-100);
9373     for (i = 0; i < numberCutGenerators_; i++) {
9374       int howOften = generator_[i]->howOften();
9375       /*  Probing can be set to just do column cuts in treee.
9376             But if doing good then leave as on
9377             Ok, let me try to explain this. rowCuts = 3 says do disaggregation (1<<0) and
9378             coefficient (1<<1) cuts. But if the value is negative, there's code at the
9379             entry to generateCuts, and generateCutsAndModify, that temporarily changes
9380             the value to 4 (1<<2) if we're in a search tree.
9381 
9382             Which does nothing to explain this next bit. We set a boolean, convert
9383             howOften to the code for `generate while objective is improving', and change
9384             over to `do everywhere'. Hmmm ... now I write it out, this makes sense in the
9385             context of the original comment. If we're doing well (objective improving)
9386             we'll keep probing fully active.
9387 
9388             */
9389       bool probingWasOnBut = false;
9390       CglProbing *probing = dynamic_cast< CglProbing * >(generator_[i]->generator());
9391       if (probing && !numberNodes_) {
9392         if (generator_[i]->numberCutsInTotal()) {
9393           // If large number of probing - can be biased
9394           smallProblem = (0.2 * (totalCuts - generator_[i]->numberCutsInTotal())) / static_cast< double >(numberActiveGenerators - 1 + 1.0e-100);
9395         }
9396         iProbing = i;
9397         if (probing->rowCuts() == -3) {
9398           probingWasOnBut = true;
9399           howOften = -98;
9400           probing->setRowCuts(3);
9401         }
9402       }
9403       /*
9404               Convert `as long as objective is improving' into `only at root' if we've
9405               decided cuts just aren't worth it.
9406             */
9407       if (willBeCutsInTree < 0 && howOften == -98)
9408         howOften = -99;
9409       /*
9410               And check to see if the objective is improving. But don't do the check if
9411               the user has specified some minimum number of cuts.
9412 
9413               This exclusion seems bogus, or at least counterintuitive. Why would a user
9414               suspect that setting a minimum cut limit would invalidate the objective
9415               check? Nor do I see the point in comparing the number of rows and columns
9416               in the second test.
9417             */
9418       if (!probing && howOften == -98 && !generator_[i]->numberShortCutsAtRoot() && generator_[i]->numberCutsInTotal()) {
9419         // switch off as no short cuts generated
9420         //printf("Switch off %s?\n",generator_[i]->cutGeneratorName());
9421         howOften = -99;
9422       }
9423       if (howOften == -98 && generator_[i]->switchOffIfLessThan() > 0) {
9424         if (thisObjective - startObjective < 0.005 * fabs(startObjective) + 1.0e-5)
9425           howOften = -99; // switch off
9426         if (thisObjective - startObjective < 0.1 * fabs(startObjective) + 1.0e-5
9427           && 5 * solver_->getNumRows() < solver_->getNumCols())
9428           howOften = -99; // switch off
9429       }
9430       if (generator_[i]->maximumTries() != -1)
9431         howOften = CoinMin(howOften, -99); // switch off
9432       /*
9433               Below -99, this generator is switched off. There's no need to consider
9434               further. Then again, there was no point in persisting this far!
9435             */
9436       if (howOften < -99) {
9437         // may have been switched off - report
9438         if (!numberNodes_) {
9439           int n = generator_[i]->numberCutsInTotal();
9440           if (n) {
9441             double average = 0.0;
9442             average = generator_[i]->numberElementsInTotal();
9443             average /= n;
9444             handler_->message(CBC_GENERATOR, messages_)
9445               << i
9446               << generator_[i]->cutGeneratorName()
9447               << n
9448               << average
9449               << generator_[i]->numberColumnCuts()
9450               << generator_[i]->numberCutsActive()
9451                 + generator_[i]->numberColumnCuts();
9452             handler_->printing(generator_[i]->timing())
9453               << generator_[i]->timeInCutGenerator();
9454             handler_->message()
9455               << -100
9456               << CoinMessageEol;
9457           }
9458         }
9459         continue;
9460       }
9461       /*
9462               Adjust, if howOften is adjustable.
9463             */
9464       if (howOften < 0 || howOften >= 1000000) {
9465         if (!numberNodes_) {
9466           /*
9467                       If root only, or objective improvement but no cuts generated, switch off. If
9468                       it's just that the generator found no cuts at the root, give it one more
9469                       chance.
9470                     */
9471           // If small number switch mostly off
9472 #ifdef JUST_ACTIVE
9473           double thisCuts = count[i] + 5.0 * generator_[i]->numberColumnCuts();
9474 #else
9475           double thisCuts = generator_[i]->numberCutsInTotal() + 5.0 * generator_[i]->numberColumnCuts();
9476 #endif
9477           // Allow on smaller number if <-1
9478           if (generator_[i]->switchOffIfLessThan() < 0) {
9479             double multiplier[] = { 2.0, 5.0 };
9480             int iSwitch = -generator_[i]->switchOffIfLessThan() - 1;
9481             assert(iSwitch >= 0 && iSwitch < 2);
9482             thisCuts *= multiplier[iSwitch];
9483           }
9484           if (!thisCuts || howOften == -99) {
9485             if (howOften == -99 || howOften == -98) {
9486               howOften = -100;
9487             } else {
9488               howOften = 1000000 + SCANCUTS; // wait until next time
9489               if (probing) {
9490                 // not quite so drastic
9491                 howOften = 1000000 + 1;
9492                 probing->setMaxLook(1);
9493                 probing->setMaxProbe(123);
9494               }
9495             }
9496             /*
9497                           Not productive, but not zero either.
9498                         */
9499           } else if ((thisCuts + generator_[i]->numberColumnCuts() < smallProblem)
9500             && !generator_[i]->whetherToUse()) {
9501             /*
9502                           Not unadjustable every node, and not strong probing.
9503                         */
9504             if (howOften != 1 && !probingWasOnBut) {
9505               /*
9506                               No depth spec, or not adjustable every node.
9507                             */
9508               if (generator_[i]->whatDepth() < 0 || howOften != -1) {
9509                 int k = static_cast< int >(sqrt(smallProblem / thisCuts));
9510                 /*
9511                                   Not objective improvement, set to new frequency, otherwise turn off.
9512                                 */
9513                 if (howOften != -98)
9514                   howOften = k + 1000000;
9515                 else
9516                   howOften = -100;
9517                 /*
9518                                   Depth spec, or adjustable every node. Force to unadjustable every node.
9519                                 */
9520               } else {
9521                 howOften = 1;
9522               }
9523               /*
9524                               Unadjustable every node, or strong probing. Force unadjustable every node and
9525                               force not strong probing? I don't understand.
9526                             */
9527             } else {
9528               howOften = 1;
9529               // allow cuts
9530               probingWasOnBut = false;
9531             }
9532             /*
9533                           Productive cut generator. Say we'll do it every node, adjustable. But if the
9534                           objective isn't improving, restrict that to every fifth depth level
9535                           (whatDepth overrides howOften in generateCuts).
9536                         */
9537           } else {
9538             if (thisObjective - startObjective < 0.1 * fabs(startObjective) + 1.0e-5 && generator_[i]->whatDepth() < 0)
9539               generator_[i]->setWhatDepth(5);
9540             howOften = 1 + 1000000;
9541           }
9542         }
9543         /*
9544                   End root actions.
9545 
9546                   sumChangeObjective2_ is the objective change due to cuts. If we're getting
9547                   much better results from branching over a large number of nodes, switch off
9548                   cuts.
9549 
9550                   Except it doesn't, really --- it just puts off the decision 'til the
9551                   next full scan, when it'll put it off again unless cuts look better.
9552                 */
9553         // If cuts useless switch off
9554         if (numberNodes_ >= 100000 && sumChangeObjective1_ > 2.0e2 * (sumChangeObjective2_ + 1.0e-12)) {
9555           howOften = 1000000 + SCANCUTS; // wait until next time
9556           //printf("switch off cut %d due to lack of use\n",i);
9557         }
9558       }
9559       /*
9560               Ok, that's the frequency adjustment bit.
9561 
9562               Now, if we're at the root, force probing back on at every node, for column
9563               cuts at least, even if it looks useless for row cuts. Notice that if it
9564               looked useful, the values set above mean we'll be doing strong probing in
9565               the tree subject to objective improvement.
9566             */
9567       if (!numberNodes_) {
9568         if (probingWasOnBut && howOften == -100) {
9569           probing->setRowCuts(-3);
9570           howOften = 1;
9571         }
9572         if (howOften == 1)
9573           generator_[i]->setWhatDepth(1);
9574 
9575         if (howOften >= 0 && generator_[i]->generator()->mayGenerateRowCutsInTree())
9576           willBeCutsInTree = 1;
9577       }
9578       /*
9579               Set the new frequency in the generator. If this is an adjustable frequency,
9580               use the value to set whatDepth.
9581 
9582               Hey! Seems like this could override the user's depth setting.
9583             */
9584       generator_[i]->setHowOften(howOften);
9585       if (howOften >= 1000000 && howOften < 2000000 && 0) {
9586         // Go to depth
9587         int bias = 1;
9588         if (howOften == 1 + 1000000)
9589           generator_[i]->setWhatDepth(bias + 1);
9590         else if (howOften <= 10 + 1000000)
9591           generator_[i]->setWhatDepth(bias + 2);
9592         else
9593           generator_[i]->setWhatDepth(bias + 1000);
9594       }
9595       int newFrequency = generator_[i]->howOften() % 1000000;
9596       // increment cut counts
9597       generator_[i]->incrementNumberCutsActive(count[i]);
9598       CglStored *stored = dynamic_cast< CglStored * >(generator_[i]->generator());
9599       if (stored && !generator_[i]->numberCutsInTotal())
9600         continue;
9601       double average = 0.0;
9602       int n = generator_[i]->numberCutsInTotal();
9603       if (n) {
9604         average = generator_[i]->numberElementsInTotal();
9605         average /= n;
9606       }
9607       if (handler_->logLevel() > 1 || !numberNodes_) {
9608         handler_->message(CBC_GENERATOR, messages_)
9609           << i
9610           << generator_[i]->cutGeneratorName()
9611           //<<generator_[i]->numberCutsInTotal()<<count[i]
9612           << n
9613           << average
9614           << generator_[i]->numberColumnCuts()
9615           << generator_[i]->numberCutsActive()
9616             + generator_[i]->numberColumnCuts();
9617         handler_->printing(!numberNodes_ && generator_[i]->timing())
9618           << generator_[i]->timeInCutGenerator();
9619         handler_->message()
9620           << newFrequency
9621           << CoinMessageEol;
9622       }
9623     }
9624     /*
9625           End loop to adjust cut generator frequency of use.
9626         */
9627     delete[] count;
9628     if (!numberNodes_) {
9629       // save statistics
9630       for (i = 0; i < numberCutGenerators_; i++) {
9631         generator_[i]->setNumberCutsAtRoot(generator_[i]->numberCutsInTotal());
9632         generator_[i]->setNumberActiveCutsAtRoot(generator_[i]->numberCutsActive());
9633       }
9634       /*
9635               Garbage code 071219
9636             */
9637       // decide on pseudo cost strategy
9638       int howOften = iProbing >= 0 ? generator_[iProbing]->howOften() : 0;
9639       if ((howOften % 1000000) != 1)
9640         howOften = 0;
9641       //if (howOften) {
9642       //CglProbing * probing = dynamic_cast<CglProbing*>(generator_[iProbing]->generator());
9643       //}
9644       howOften = 0;
9645       if (howOften) {
9646         COIN_DETAIL_PRINT(printf("** method 1\n"));
9647         //CglProbing * probing = dynamic_cast<CglProbing*>(generator_[iProbing]->generator());
9648         generator_[iProbing]->setWhatDepth(1);
9649         // could set no row cuts
9650         //if (thisObjective-startObjective<0.001*fabs(startObjective)+1.0e-5)
9651         // probing->setRowCuts(0);
9652         for (int i = 0; i < numberObjects_; i++) {
9653           CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
9654           if (obj)
9655             obj->setMethod(1);
9656         }
9657       }
9658       if (willBeCutsInTree == -2)
9659         willBeCutsInTree = 0;
9660       /*
9661               End garbage code.
9662 
9663               Now I've reached the problem area. This is a problem only at the root node,
9664               so that should simplify the issue of finding a workable basis? Or maybe not.
9665             */
9666       if (willBeCutsInTree <= 0) {
9667         // Take off cuts
9668         cuts = OsiCuts();
9669         numberNewCuts_ = 0;
9670         if (!willBeCutsInTree) {
9671           // update size of problem
9672           numberRowsAtContinuous_ = solver_->getNumRows();
9673         } else {
9674           // take off cuts
9675           int numberRows = solver_->getNumRows();
9676           int numberAdded = numberRows - numberRowsAtContinuous_;
9677           if (numberAdded) {
9678             int *added = new int[numberAdded];
9679             for (int i = 0; i < numberAdded; i++)
9680               added[i] = i + numberRowsAtContinuous_;
9681             solver_->deleteRows(numberAdded, added);
9682             delete[] added;
9683             // resolve so optimal
9684             resolve(solver_);
9685           }
9686         }
9687 #ifdef COIN_HAS_CLP
9688         OsiClpSolverInterface *clpSolver
9689           = dynamic_cast< OsiClpSolverInterface * >(solver_);
9690         if (clpSolver) {
9691           // Maybe solver might like to know only column bounds will change
9692           //int options = clpSolver->specialOptions();
9693           //clpSolver->setSpecialOptions(options|128);
9694           clpSolver->synchronizeModel();
9695         }
9696 #endif
9697       } else {
9698 #ifdef COIN_HAS_CLP
9699         OsiClpSolverInterface *clpSolver
9700           = dynamic_cast< OsiClpSolverInterface * >(solver_);
9701         if (clpSolver) {
9702           // make sure factorization can't carry over
9703           int options = clpSolver->specialOptions();
9704           clpSolver->setSpecialOptions(options & (~8));
9705         }
9706 #endif
9707       }
9708     }
9709   } else {
9710 #ifdef COIN_HAS_CLP
9711     OsiClpSolverInterface *clpSolver
9712       = dynamic_cast< OsiClpSolverInterface * >(solver_);
9713     if (clpSolver) {
9714       // Maybe solver might like to know only column bounds will change
9715       //int options = clpSolver->specialOptions();
9716       //clpSolver->setSpecialOptions(options|128);
9717       clpSolver->synchronizeModel();
9718     }
9719 #endif
9720     if (numberCutGenerators_) {
9721       int i;
9722       // What if not feasible as cuts may have helped
9723       if (feasible) {
9724         for (i = 0; i < numberNewCuts_; i++) {
9725           int iGenerator = whichGenerator_[i];
9726 #ifdef CONFLICT_CUTS
9727           assert(iGenerator >= 0);
9728 #endif
9729           if (iGenerator >= 0)
9730             iGenerator = iGenerator % 10000;
9731           if (iGenerator >= 0 && iGenerator < numberCutGenerators_)
9732             generator_[iGenerator]->incrementNumberCutsActive();
9733         }
9734       }
9735     }
9736   }
9737 
9738 #ifdef CHECK_CUT_COUNTS
9739   if (feasible) {
9740     CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
9741     printf("solveWithCuts: Number of rows at end (only active cuts) %d\n",
9742       numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_);
9743     basis->print();
9744     delete basis;
9745   }
9746 #endif
9747 #ifdef CHECK_KNOWN_SOLUTION
9748   if (onOptimalPath && (solver_->isDualObjectiveLimitReached() || !feasible)) {
9749     printf("help\n");
9750   }
9751 #endif
9752 #ifdef CBC_DEBUG
9753   if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
9754     assert(feasible);
9755 #endif
9756 #ifdef COIN_HAS_CLP
9757   if (clpSolver)
9758     clpSolver->setSpecialOptions(saveClpOptions);
9759 #endif
9760 #ifdef CBC_THREAD
9761   // Get rid of all threaded stuff
9762   if (master) {
9763     master->stopThreads(0);
9764     delete master;
9765   }
9766 #endif
9767   // make sure pointers are up to date
9768   setPointers(solver_);
9769 
9770   return feasible;
9771 }
9772 
9773 // Generate one round of cuts - serial mode
9774 int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, int lastNumberCuts)
9775 {
9776   /*
9777       Is it time to scan the cuts in order to remove redundant cuts? If so, set
9778       up to do it.
9779     */
9780   int fullScan = 0;
9781   if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_ & 256) != 0) {
9782     fullScan = 1;
9783     if (!numberNodes_ || (specialOptions_ & 256) != 0)
9784       fullScan = 2;
9785     specialOptions_ &= ~256; // mark as full scan done
9786   }
9787 #if 0 //def COIN_HAS_CLP
9788     // check basis
9789     OsiClpSolverInterface * clpSolver
9790       = dynamic_cast<OsiClpSolverInterface *> (solver_);
9791     if (clpSolver) {
9792       ClpSimplex * simplex = clpSolver->getModelPtr();
9793       int numberTotal=simplex->numberRows()+simplex->numberColumns();
9794       int superbasic=0;
9795       for (int i=0;i<numberTotal;i++) {
9796 	if (simplex->getStatus(i)==ClpSimplex::superBasic)
9797 	  superbasic++;
9798       }
9799       if (superbasic) {
9800 	printf("%d superbasic!\n",superbasic);
9801 	clpSolver->resolve();
9802 	superbasic=0;
9803 	for (int i=0;i<numberTotal;i++) {
9804 	  if (simplex->getStatus(i)==ClpSimplex::superBasic)
9805 	    superbasic++;
9806 	}
9807 	assert (!superbasic);
9808       }
9809     }
9810 #endif
9811   int switchOff = (!doCutsNow(1) && !fullScan) ? 1 : 0;
9812   int status = 0;
9813   int i;
9814   for (i = 0; i < numberCutGenerators_ && (!this->maximumSecondsReached()) ; i++) {
9815     int numberRowCutsBefore = theseCuts.sizeRowCuts();
9816     int numberColumnCutsBefore = theseCuts.sizeColCuts();
9817     int numberRowCutsAfter = numberRowCutsBefore;
9818     int numberColumnCutsAfter = numberColumnCutsBefore;
9819     /*printf("GEN %d %s switches %d\n",
9820 	       i,generator_[i]->cutGeneratorName(),
9821 	       generator_[i]->switches());*/
9822     bool generate = generator_[i]->normal();
9823     // skip if not optimal and should be (maybe a cut generator has fixed variables)
9824     if (generator_[i]->howOften() == -100 || (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
9825       || generator_[i]->switchedOff())
9826       generate = false;
9827     if (switchOff && !generator_[i]->mustCallAgain()) {
9828       // switch off if default
9829       if (generator_[i]->howOften() == 1 && generator_[i]->whatDepth() < 0) {
9830         generate = false;
9831       } else if (currentDepth_ > -10 && switchOff == 2) {
9832         generate = false;
9833       }
9834     }
9835     if (generator_[i]->whetherCallAtEnd())
9836       generate = false;
9837     const OsiRowCutDebugger *debugger = NULL;
9838     bool onOptimalPath = false;
9839     if (generate) {
9840       bool mustResolve = generator_[i]->generateCuts(theseCuts, fullScan, solver_, node);
9841       numberRowCutsAfter = theseCuts.sizeRowCuts();
9842       if (fullScan && generator_[i]->howOften() == 1000000 + SCANCUTS_PROBING) {
9843         CglProbing *probing = dynamic_cast< CglProbing * >(generator_[i]->generator());
9844         if (probing && (numberRowCutsBefore < numberRowCutsAfter || numberColumnCutsBefore < theseCuts.sizeColCuts())) {
9845           // switch on
9846           generator_[i]->setHowOften(1);
9847         }
9848       }
9849       if (numberRowCutsBefore < numberRowCutsAfter && generator_[i]->mustCallAgain() && status >= 0)
9850         /*printf("%s before %d after %d must %c atend %c off %c endmode %c\n",
9851 		   generator_[i]->cutGeneratorName(),
9852 		   numberRowCutsBefore,numberRowCutsAfter,
9853 		   generator_[i]->mustCallAgain() ? 'Y': 'N',
9854 		   generator_[i]->whetherCallAtEnd() ? 'Y': 'N',
9855 		   generator_[i]->switchedOff() ? 'Y': 'N',
9856 		   generator_[i]->whetherInMustCallAgainMode() ? 'Y': 'N');*/
9857         if (numberRowCutsBefore < numberRowCutsAfter && generator_[i]->mustCallAgain() && status >= 0)
9858           status = 1; // say must go round
9859       // Check last cut to see if infeasible
9860       /*
9861             The convention is that if the generator proves infeasibility, it should
9862             return as its last cut something with lb > ub.
9863             */
9864       if (numberRowCutsBefore < numberRowCutsAfter) {
9865         const OsiRowCut *thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1);
9866         if (thisCut->lb() > thisCut->ub()) {
9867           status = -1; // sub-problem is infeasible
9868           break;
9869         }
9870       }
9871 #ifdef CBC_DEBUG
9872       {
9873         int k;
9874         for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
9875           OsiRowCut thisCut = theseCuts.rowCut(k);
9876           /* check size of elements.
9877                        We can allow smaller but this helps debug generators as it
9878                        is unsafe to have small elements */
9879           int n = thisCut.row().getNumElements();
9880           const int *column = thisCut.row().getIndices();
9881           const double *element = thisCut.row().getElements();
9882           //assert (n);
9883           for (int i = 0; i < n; i++) {
9884             double value = element[i];
9885             assert(fabs(value) > 1.0e-12 && fabs(value) < 1.0e20);
9886           }
9887         }
9888       }
9889 #endif
9890       if (mustResolve /*|| (specialOptions_&1) != 0*/) {
9891         int returnCode = resolve(node ? node->nodeInfo() : NULL, 2);
9892         if (returnCode == 0)
9893           status = -1;
9894         if (returnCode < 0 && !status)
9895           status = 2;
9896         if ((specialOptions_ & 1) != 0) {
9897           debugger = solver_->getRowCutDebugger();
9898           if (debugger)
9899             onOptimalPath = (debugger->onOptimalPath(*solver_));
9900           else
9901             onOptimalPath = false;
9902           if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
9903             assert(status >= 0);
9904         }
9905         if (status < 0)
9906           break;
9907       }
9908     }
9909     numberRowCutsAfter = theseCuts.sizeRowCuts();
9910     numberColumnCutsAfter = theseCuts.sizeColCuts();
9911     if ((specialOptions_ & 1) != 0) {
9912       if (onOptimalPath) {
9913         int k;
9914         for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
9915           OsiRowCut thisCut = theseCuts.rowCut(k);
9916           if (debugger->invalidCut(thisCut)) {
9917             solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
9918             solver_->writeMpsNative("badCut.mps", NULL, NULL, 2);
9919             printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
9920               i, generator_[i]->cutGeneratorName(), k - numberRowCutsBefore);
9921             const double *lower = getColLower();
9922             const double *upper = getColUpper();
9923             int numberColumns = solver_->getNumCols();
9924             if (numberColumns < 200) {
9925               for (int i = 0; i < numberColumns; i++)
9926                 printf("%d bounds %g,%g\n", i, lower[i], upper[i]);
9927             }
9928             abort();
9929           }
9930           assert(!debugger->invalidCut(thisCut));
9931         }
9932       }
9933     }
9934     /*
9935           The cut generator has done its thing, and maybe it generated some
9936           cuts.  Do a bit of bookkeeping: load
9937           whichGenerator[i] with the index of the generator responsible for a cut,
9938           and place cuts flagged as global in the global cut pool for the model.
9939 
9940           lastNumberCuts is the sum of cuts added in previous iterations; it's the
9941           offset to the proper starting position in whichGenerator.
9942         */
9943     int numberBefore = numberRowCutsBefore + lastNumberCuts;
9944     int numberAfter = numberRowCutsAfter + lastNumberCuts;
9945     // possibly extend whichGenerator
9946     resizeWhichGenerator(numberBefore, numberAfter);
9947     int j;
9948 
9949     /*
9950           Look for numerically unacceptable cuts.
9951         */
9952     bool dodgyCuts = false;
9953     for (j = numberRowCutsBefore; j < numberRowCutsAfter; j++) {
9954       const OsiRowCut *thisCut = theseCuts.rowCutPtr(j);
9955       if (thisCut->lb() > 1.0e10 || thisCut->ub() < -1.0e10) {
9956         dodgyCuts = true;
9957         break;
9958       }
9959       whichGenerator_[numberBefore++] = i + 20000;
9960       if (!numberNodes_ || generator_[i]->globalCuts())
9961         whichGenerator_[numberBefore - 1] = i + 10000;
9962       if (thisCut->lb() > thisCut->ub())
9963         status = -1; // sub-problem is infeasible
9964       if (thisCut->globallyValid() || !numberNodes_) {
9965         // add to global list
9966         OsiRowCut newCut(*thisCut);
9967         newCut.setGloballyValid(true);
9968         newCut.mutableRow().setTestForDuplicateIndex(false);
9969         globalCuts_.addCutIfNotDuplicate(newCut);
9970         whichGenerator_[numberBefore - 1] = i + 10000;
9971       }
9972     }
9973     if (dodgyCuts) {
9974       for (int k = numberRowCutsAfter - 1; k >= j; k--) {
9975         const OsiRowCut *thisCut = theseCuts.rowCutPtr(k);
9976         if (thisCut->lb() > thisCut->ub())
9977           status = -1; // sub-problem is infeasible
9978         if (thisCut->lb() > 1.0e10 || thisCut->ub() < -1.0e10)
9979           theseCuts.eraseRowCut(k);
9980       }
9981       numberRowCutsAfter = theseCuts.sizeRowCuts();
9982       for (; j < numberRowCutsAfter; j++) {
9983         const OsiRowCut *thisCut = theseCuts.rowCutPtr(j);
9984         whichGenerator_[numberBefore++] = i + 20000;
9985         if (!numberNodes_ || generator_[i]->globalCuts())
9986           whichGenerator_[numberBefore - 1] = i + 10000;
9987         if (thisCut->globallyValid()) {
9988           // add to global list
9989           OsiRowCut newCut(*thisCut);
9990           newCut.setGloballyValid(true);
9991           newCut.mutableRow().setTestForDuplicateIndex(false);
9992           globalCuts_.addCutIfNotDuplicate(newCut);
9993           whichGenerator_[numberBefore - 1] = i + 10000;
9994         }
9995       }
9996     }
9997     for (j = numberColumnCutsBefore; j < numberColumnCutsAfter; j++) {
9998       //whichGenerator_[numberBefore++] = i ;
9999       const OsiColCut *thisCut = theseCuts.colCutPtr(j);
10000       if (thisCut->globallyValid()) {
10001         // fix
10002         makeGlobalCut(thisCut);
10003       }
10004     }
10005   }
10006   /*
10007       End of loop to run each cut generator.
10008     */
10009   if (status >= 0) {
10010     // delete null cuts
10011     int nCuts = theseCuts.sizeRowCuts();
10012     int k;
10013     for (k = nCuts - 1; k >= 0; k--) {
10014       const OsiRowCut *thisCut = theseCuts.rowCutPtr(k);
10015       int n = thisCut->row().getNumElements();
10016       if (!n)
10017         theseCuts.eraseRowCut(k);
10018     }
10019   }
10020   // Add in any violated saved cuts
10021   if (!theseCuts.sizeRowCuts() && !theseCuts.sizeColCuts()) {
10022     int numberOld = theseCuts.sizeRowCuts() + lastNumberCuts;
10023     int numberCuts = slackCuts.sizeRowCuts();
10024     int i;
10025     // possibly extend whichGenerator
10026     resizeWhichGenerator(numberOld, numberOld + numberCuts);
10027     double primalTolerance;
10028     solver_->getDblParam(OsiPrimalTolerance, primalTolerance);
10029     for (i = 0; i < numberCuts; i++) {
10030       const OsiRowCut *thisCut = slackCuts.rowCutPtr(i);
10031       if (thisCut->violated(cbcColSolution_) > 100.0 * primalTolerance) {
10032         if (messageHandler()->logLevel() > 2)
10033           printf("Old cut added - violation %g\n",
10034             thisCut->violated(cbcColSolution_));
10035         whichGenerator_[numberOld++] = 20097;
10036         theseCuts.insert(*thisCut);
10037       }
10038     }
10039   }
10040   return status;
10041 }
10042 
10043 /*
10044   Remove slack cuts. We obtain a basis and scan it. Cuts with basic slacks
10045   are purged. If any cuts are purged, resolve() is called to restore the
10046   solution held in the solver.	If resolve() pivots, there's the possibility
10047   that a slack may be pivoted in (trust me :-), so the process iterates.
10048   Setting allowResolve to false will suppress reoptimisation (but see note
10049   below).
10050 
10051   At the level of the solver's constraint system, loose cuts are really
10052   deleted.  There's an implicit assumption that deleteRows will also update
10053   the active basis in the solver.
10054 
10055   At the level of nodes and models, it's more complicated.
10056 
10057   New cuts exist only in the collection of cuts passed as a parameter. They
10058   are deleted from the collection and that's the end of them.
10059 
10060   Older cuts have made it into addedCuts_. Two separate actions are needed.
10061   The reference count for the CbcCountRowCut object is decremented. If this
10062   count falls to 0, the node which owns the cut is located, the reference to
10063   the cut is removed, and then the cut object is destroyed (courtesy of the
10064   CbcCountRowCut destructor). We also need to set the addedCuts_ entry to
10065   NULL. This is important so that when it comes time to generate basis edits
10066   we can tell this cut was dropped from the basis during processing of the
10067   node.
10068 
10069   NOTE: In general, it's necessary to call resolve() after purging slack
10070 	cuts.  Deleting constraints constitutes a change in the problem, and
10071 	an OSI is not required to maintain a valid solution when the problem
10072 	is changed. But ... it's really useful to maintain the active basis,
10073 	and the OSI is supposed to do that. (Yes, it's splitting hairs.) In
10074 	some places, it's possible to know that the solution will never be
10075 	consulted after this call, only the basis.  (E.g., this routine is
10076 	called as a last act before generating info to place the node in the
10077 	live set.) For such use, set allowResolve to false.
10078 
10079   TODO: No real harm would be done if we just ignored the rare occasion when
10080 	the call to resolve() pivoted a slack back into the basis. It's a
10081 	minor inefficiency, at worst. But it does break assertions which
10082 	check that there are no loose cuts in the basis. It might be better
10083 	to remove the assertions.
10084 */
10085 
10086 int CbcModel::takeOffCuts(OsiCuts &newCuts,
10087   bool allowResolve, OsiCuts *saveCuts,
10088   int numberNewCuts, const OsiRowCut **addedCuts)
10089 
10090 { // int resolveIterations = 0 ;
10091   int numberDropped = 0;
10092   int firstOldCut = numberRowsAtContinuous_;
10093   int totalNumberCuts = numberNewCuts_ + numberOldActiveCuts_;
10094   assert(numberRowsAtContinuous_ + totalNumberCuts == solver_->getNumRows());
10095   int *solverCutIndices = new int[totalNumberCuts];
10096   int *newCutIndices = new int[numberNewCuts_];
10097   const CoinWarmStartBasis *ws;
10098   CoinWarmStartBasis::Status status;
10099   //#define COIN_HAS_CLP_KEEP_STATUS
10100 #ifdef COIN_HAS_CLP_KEEP_STATUS
10101   int problemStatus = -1;
10102   OsiClpSolverInterface *clpSolver
10103     = dynamic_cast< OsiClpSolverInterface * >(solver_);
10104   if (clpSolver)
10105     problemStatus = clpSolver->getModelPtr()->status();
10106 #endif
10107   bool needPurge = true;
10108   /*
10109       The outer loop allows repetition of purge in the event that reoptimisation
10110       changes the basis. To start an iteration, clear the deletion counts and grab
10111       the current basis.
10112     */
10113   while (needPurge) {
10114     int numberNewToDelete = 0;
10115     int numberOldToDelete = 0;
10116     int i;
10117     int kCut = 0;
10118     ws = dynamic_cast< const CoinWarmStartBasis * >(solver_->getWarmStart());
10119     /*
10120           Scan the basis entries of the old cuts generated prior to this round of cut
10121           generation.  Loose cuts are `removed' by decrementing their reference count
10122           and setting the addedCuts_ entry to NULL. (If the reference count falls to
10123           0, they're really deleted.  See CbcModel and CbcCountRowCut doc'n for
10124           principles of cut handling.)
10125         */
10126     int oldCutIndex = 0;
10127     if (numberOldActiveCuts_) {
10128       lockThread();
10129       for (i = 0; i < numberOldActiveCuts_; i++) {
10130         status = ws->getArtifStatus(i + firstOldCut);
10131         while (!addedCuts_[oldCutIndex])
10132           oldCutIndex++;
10133         assert(oldCutIndex < currentNumberCuts_);
10134         // always leave if from nextRowCut_
10135         if (status == CoinWarmStartBasis::basic && (addedCuts_[oldCutIndex]->effectiveness() <= 1.0e10 || addedCuts_[oldCutIndex]->canDropCut(solver_, i + firstOldCut))) {
10136           solverCutIndices[numberOldToDelete++] = i + firstOldCut;
10137           if (saveCuts) {
10138             // send to cut pool
10139             OsiRowCut *slackCut = addedCuts_[oldCutIndex];
10140             if (slackCut->effectiveness() != -1.234) {
10141               slackCut->setEffectiveness(-1.234);
10142               slackCut->setGloballyValid();
10143               saveCuts->insert(*slackCut);
10144             }
10145           }
10146           if (addedCuts_[oldCutIndex]->decrement() == 0)
10147             delete addedCuts_[oldCutIndex];
10148           addedCuts_[oldCutIndex] = NULL;
10149           oldCutIndex++;
10150         } else {
10151           int iGenerator = addedCuts_[oldCutIndex]->whichCutGenerator();
10152           if (iGenerator == -1)
10153             iGenerator = 100;
10154           whichGenerator_[kCut++] = iGenerator;
10155           oldCutIndex++;
10156         }
10157       }
10158       unlockThread();
10159     }
10160     /*
10161           Scan the basis entries of the new cuts generated with this round of cut
10162           generation.  At this point, newCuts is the only record of the new cuts, so
10163           when we delete loose cuts from newCuts, they're really gone. newCuts is a
10164           vector, so it's most efficient to compress it (eraseRowCut) from back to
10165           front.
10166         */
10167     int firstNewCut = firstOldCut + numberOldActiveCuts_;
10168     int nCuts = newCuts.sizeRowCuts();
10169     for (i = 0; i < nCuts; i++) {
10170       status = ws->getArtifStatus(i + firstNewCut);
10171       if (status == CoinWarmStartBasis::basic &&
10172         /*whichGenerator_[i]!=-2*/ newCuts.rowCutPtr(i)->effectiveness() < 1.0e20) {
10173         solverCutIndices[numberNewToDelete + numberOldToDelete] = i + firstNewCut;
10174         newCutIndices[numberNewToDelete++] = i;
10175       } else { // save which generator did it
10176         // 20098 means branch cut! assert (whichGenerator_[i]!=20098); // ?? what if it is - memory leak?
10177         whichGenerator_[kCut++] = whichGenerator_[i];
10178       }
10179     }
10180     int baseRow = firstNewCut + nCuts;
10181     //OsiRowCut ** mutableAdded = const_cast<OsiRowCut **>(addedCuts);
10182     int numberTotalToDelete = numberNewToDelete + numberOldToDelete;
10183     for (i = 0; i < numberNewCuts; i++) {
10184       status = ws->getArtifStatus(i + baseRow);
10185       if (status != CoinWarmStartBasis::basic ||
10186         /*whichGenerator_[i+nCuts]==-2*/ addedCuts[i]->effectiveness() >= 1.0e20) {
10187         newCuts.insert(*addedCuts[i]);
10188         //newCuts.insert(mutableAdded[i]) ;
10189         //mutableAdded[i]=NULL;
10190         //if (status == CoinWarmStartBasis::basic&&whichGenerator_[i]!=-2) {
10191         // save which generator did it
10192         //whichGenerator_[k++] = whichGenerator_[i+nCuts] ;
10193         //}
10194       } else {
10195         solverCutIndices[numberTotalToDelete++] = i + baseRow;
10196       }
10197     }
10198     numberNewCuts = 0;
10199     numberNewCuts_ = newCuts.sizeRowCuts();
10200     delete ws;
10201     for (i = numberNewToDelete - 1; i >= 0; i--) {
10202       int iCut = newCutIndices[i];
10203       if (saveCuts) {
10204         // send to cut pool
10205         OsiRowCut *slackCut = newCuts.rowCutPtrAndZap(iCut);
10206         if (slackCut->effectiveness() != -1.234) {
10207           slackCut->setEffectiveness(-1.234);
10208           slackCut->setGloballyValid();
10209           saveCuts->insert(slackCut);
10210         } else {
10211           delete slackCut;
10212         }
10213       } else {
10214         newCuts.eraseRowCut(iCut);
10215       }
10216     }
10217     /*
10218           Did we delete anything? If so, delete the cuts from the constraint system
10219           held in the solver and reoptimise unless we're forbidden to do so. If the
10220           call to resolve() results in pivots, there's the possibility we again have
10221           basic slacks. Repeat the purging loop.
10222         */
10223     if (numberTotalToDelete > 0) {
10224       solver_->deleteRows(numberTotalToDelete,
10225         solverCutIndices);
10226       numberDropped += numberTotalToDelete;
10227       numberNewCuts_ -= numberNewToDelete;
10228       assert(numberNewCuts_ == newCuts.sizeRowCuts());
10229       numberOldActiveCuts_ -= numberOldToDelete;
10230 #ifdef CBC_DEBUG
10231       printf("takeOffCuts: purged %d+%d cuts\n", numberOldToDelete,
10232         numberNewToDelete);
10233 #endif
10234       if (allowResolve) {
10235         phase_ = 3;
10236         // can do quick optimality check
10237         int easy = 2;
10238         solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy);
10239         resolve(solver_);
10240         setPointers(solver_);
10241         solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL);
10242         if (solver_->getIterationCount() == 0) {
10243           needPurge = false;
10244         }
10245 #ifdef CBC_DEBUG
10246         else {
10247           printf("Repeating purging loop. %d iters.\n",
10248             solver_->getIterationCount());
10249         }
10250 #endif
10251       } else {
10252         needPurge = false;
10253       }
10254     } else {
10255       needPurge = false;
10256     }
10257   }
10258 
10259 #ifdef COIN_HAS_CLP_KEEP_STATUS
10260   // need to check further that only zero duals dropped
10261   if (clpSolver) // status may have got to -1
10262     clpSolver->getModelPtr()->setProblemStatus(problemStatus);
10263 #endif
10264   /*
10265       Clean up and return.
10266     */
10267   delete[] solverCutIndices;
10268   delete[] newCutIndices;
10269   return numberDropped;
10270 }
10271 /*
10272   Return values:
10273     1:	feasible
10274     0:	infeasible
10275    -1:	feasible and finished (do no more work on this subproblem)
10276 */
10277 int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom,
10278   double *saveSolution,
10279   double *saveLower,
10280   double *saveUpper)
10281 {
10282 #ifdef CBC_STATISTICS
10283   void cbc_resolve_check(const OsiSolverInterface *solver);
10284   cbc_resolve_check(solver_);
10285 #endif
10286   bool onOptimalPath = false;
10287   if ((specialOptions_ & 1) != 0) {
10288     const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
10289     if (debugger) {
10290       onOptimalPath = true;
10291       printf("On optimal path d\n");
10292     }
10293   }
10294   // We may have deliberately added in violated cuts - check to avoid message
10295   int iRow;
10296   int numberRows = solver_->getNumRows();
10297   const double *rowLower = solver_->getRowLower();
10298   const double *rowUpper = solver_->getRowUpper();
10299   bool feasible = true;
10300   for (iRow = numberRowsAtContinuous_; iRow < numberRows; iRow++) {
10301     if (rowLower[iRow] > rowUpper[iRow] + 1.0e-8)
10302       feasible = false;
10303   }
10304   // Can't happen if strong branching as would have been found before
10305   if ((!numberStrong_ || (moreSpecialOptions_ & 1073741824) != 0)
10306     && numberObjects_ > numberIntegers_) {
10307     int iColumn;
10308     int numberColumns = solver_->getNumCols();
10309     const double *columnLower = solver_->getColLower();
10310     const double *columnUpper = solver_->getColUpper();
10311     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
10312       if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5)
10313         feasible = false;
10314     }
10315   }
10316 #ifdef COIN_HAS_CLP
10317   OsiClpSolverInterface *clpSolver
10318     = dynamic_cast< OsiClpSolverInterface * >(solver_);
10319 #endif
10320   /*
10321       Reoptimize. Consider the possibility that we should fathom on bounds. But be
10322       careful --- where the objective takes on integral values, we may want to keep
10323       a solution where the objective is right on the cutoff.
10324     */
10325   if (feasible) {
10326     int nTightened = 0;
10327 #ifdef COIN_HAS_CLP
10328     // Pierre pointed out that this is not valid for all solvers
10329     // so just do if Clp
10330     if ((specialOptions_ & 1) != 0 && onOptimalPath) {
10331       solver_->writeMpsNative("before-tighten.mps", NULL, NULL, 2);
10332     }
10333     if (clpSolver && (!currentNode_ || (currentNode_->depth() & 2) != 0) && !solverCharacteristics_->solutionAddsCuts() && (moreSpecialOptions_ & 1073741824) == 0)
10334       nTightened = clpSolver->tightenBounds();
10335     if (nTightened) {
10336       //printf("%d bounds tightened\n",nTightened);
10337       if ((specialOptions_ & 1) != 0 && onOptimalPath) {
10338         const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
10339         if (!debugger) {
10340           // tighten did something???
10341           solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
10342           solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2);
10343           printf("Not on optimalpath aaaa\n");
10344           //abort();
10345           onOptimalPath = false;
10346         }
10347       }
10348     }
10349 #endif
10350     if (nTightened >= 0) {
10351       resolve(solver_);
10352       numberIterations_ += solver_->getIterationCount();
10353       feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached());
10354       if (feasible) {
10355         // double check
10356         double testValue = solver_->getObjSense() * solver_->getObjValue();
10357         //double cutoff = getCutoff();
10358         if (bestObjective_ - getCutoffIncrement() < testValue) {
10359 #if CBC_USEFUL_PRINTING > 1
10360           double value;
10361           solver_->getDblParam(OsiDualObjectiveLimit, value);
10362           printf("Should cutoff as obj %.18g, best %.18g, inc %.18g - solver cutoff %.18g model cutoff %.18g\n",
10363             testValue, bestObjective_, getCutoffIncrement(),
10364             value, getCutoff());
10365 #endif
10366           feasible = false;
10367         }
10368       } else if (solver_->isAbandoned()) {
10369         setMaximumSeconds(-COIN_DBL_MAX);
10370       }
10371 #ifdef COIN_HAS_CLP
10372       if (clpSolver && feasible && !numberNodes_ && false) {
10373         double direction = solver_->getObjSense();
10374         double tolerance;
10375         solver_->getDblParam(OsiDualTolerance, tolerance);
10376         double primalTolerance;
10377         solver_->getDblParam(OsiPrimalTolerance, primalTolerance);
10378 
10379         const double *lower = solver_->getColLower();
10380         const double *upper = solver_->getColUpper();
10381         const double *solution = solver_->getColSolution();
10382         const double *reducedCost = solver_->getReducedCost();
10383         ClpSimplex *clpSimplex = clpSolver->getModelPtr();
10384         double *rowLower = clpSimplex->rowLower();
10385         double *rowUpper = clpSimplex->rowUpper();
10386         int numberRows = clpSimplex->numberRows();
10387         double *saveRowLower = CoinCopyOfArray(rowLower, numberRows);
10388         double *saveRowUpper = CoinCopyOfArray(rowUpper, numberRows);
10389         {
10390           const double *dual = clpSimplex->dualRowSolution();
10391           const double *rowActivity = clpSimplex->primalRowSolution();
10392           for (int iRow = 0; iRow < numberRows; iRow++) {
10393             double djValue = direction * dual[iRow];
10394             double lowerValue = rowLower[iRow];
10395             double upperValue = rowUpper[iRow];
10396             if (rowActivity[iRow] < lowerValue + primalTolerance && djValue > tolerance) {
10397               rowUpper[iRow] = lowerValue;
10398               assert(clpSimplex->getRowStatus(iRow) != ClpSimplex::basic);
10399             } else if (rowActivity[iRow] > upperValue - primalTolerance && djValue < -tolerance) {
10400               rowLower[iRow] = upperValue;
10401               assert(clpSimplex->getRowStatus(iRow) != ClpSimplex::basic);
10402             }
10403           }
10404         }
10405         int numberColumns = solver_->getNumCols();
10406         double *objective = clpSimplex->objective();
10407         double *saveObj = CoinCopyOfArray(objective, numberColumns);
10408         double objValue = 0.01;
10409         bool someFree = false;
10410         for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
10411           double djValue = direction * reducedCost[iColumn];
10412           double lowerValue = lower[iColumn];
10413           double upperValue = upper[iColumn];
10414           if (solution[iColumn] < lowerValue + primalTolerance && djValue > tolerance) {
10415             objective[iColumn] = 1.0e8 * direction;
10416             assert(clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic);
10417           } else if (solution[iColumn] > upperValue - primalTolerance && djValue < -tolerance) {
10418             objective[iColumn] = -1.0e8 * direction;
10419             assert(clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic);
10420           } else if (lowerValue > -1.0e20 || upperValue < 1.0e20) {
10421             assert(fabs(djValue) <= tolerance);
10422             if (fabs(lowerValue) < fabs(upperValue))
10423               objective[iColumn] = objValue * direction;
10424             else
10425               objective[iColumn] = -objValue * direction;
10426             objValue += 0.01;
10427           } else {
10428             objective[iColumn] = 0.0;
10429             someFree = true;
10430           }
10431         }
10432         if (!someFree)
10433           clpSimplex->primal(1);
10434         memcpy(objective, saveObj, numberColumns * sizeof(double));
10435         delete[] saveObj;
10436         memcpy(rowLower, saveRowLower, numberRows * sizeof(double));
10437         delete[] saveRowLower;
10438         memcpy(rowUpper, saveRowUpper, numberRows * sizeof(double));
10439         delete[] saveRowUpper;
10440         if (!someFree) {
10441           clpSimplex->primal(1);
10442           //assert (clpSimplex->numberIterations()<10);
10443         }
10444         //clpSimplex->writeMps("xx");
10445         //clpSimplex->primal(1);
10446         clpSolver->setWarmStart(NULL);
10447       }
10448 #endif
10449       if ((specialOptions_ & 1) != 0 && onOptimalPath) {
10450         if (!solver_->getRowCutDebugger()) {
10451           // tighten did something???
10452           solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
10453           solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2);
10454           //assert (solver_->getRowCutDebugger()) ;
10455           printf("Not on optimalpath e\n");
10456           //abort();
10457         }
10458       }
10459     } else {
10460       feasible = false;
10461     }
10462   }
10463   if (0 && feasible) {
10464     const double *lb = solver_->getColLower();
10465     const double *ub = solver_->getColUpper();
10466     const double *x = solver_->getColSolution();
10467     const double *dj = solver_->getReducedCost();
10468     int numberColumns = solver_->getNumCols();
10469     for (int i = 0; i < numberColumns; i++) {
10470       if (dj[i] > 1.0e-4 && ub[i] - lb[i] > 1.0e-4 && x[i] > lb[i] + 1.0e-4)
10471         printf("error %d %g %g %g %g\n", i, dj[i], lb[i], x[i], ub[i]);
10472       if (dj[i] < -1.0e-4 && ub[i] - lb[i] > 1.0e-4 && x[i] < ub[i] - 1.0e-4)
10473         printf("error %d %g %g %g %g\n", i, dj[i], lb[i], x[i], ub[i]);
10474     }
10475   }
10476   if (false && !feasible && continuousObjective_ < -1.0e30) {
10477     // at root node - double double check
10478     bool saveTakeHint;
10479     OsiHintStrength saveStrength;
10480     solver_->getHintParam(OsiDoDualInResolve, saveTakeHint, saveStrength);
10481     if (saveTakeHint || saveStrength == OsiHintIgnore) {
10482       solver_->setHintParam(OsiDoDualInResolve, false, OsiHintDo);
10483       resolve(solver_);
10484       solver_->setHintParam(OsiDoDualInResolve, saveTakeHint, saveStrength);
10485       numberIterations_ += solver_->getIterationCount();
10486       feasible = solver_->isProvenOptimal();
10487       //      solver_->writeMps("infeas");
10488     }
10489   }
10490 #ifdef JJF_ZERO
10491   if (cutModifier_ && feasible && !solverCharacteristics_->solutionAddsCuts()) {
10492     //double increment = getDblParam(CbcModel::CbcCutoffIncrement) ;
10493     double cutoff;
10494     solver_->getDblParam(OsiDualObjectiveLimit, cutoff);
10495     double distance = fabs(cutoff - solver_->getObjValue());
10496     if (distance < 10.0 * trueIncrement) {
10497       double offset;
10498       solver_->getDblParam(OsiObjOffset, offset);
10499       double objFixedValue = -offset;
10500       double objValue = 0.0;
10501       double direction = solver_->getObjSense();
10502       const double *solution = solver_->getColSolution();
10503       const double *objective = solver_->getObjCoefficients();
10504       const double *columnLower = solver_->getColLower();
10505       const double *columnUpper = solver_->getColUpper();
10506       int numberColumns = solver_->getNumCols();
10507       int increment = 0;
10508       double multiplier = 1.0 / trueIncrement;
10509       int bigIntegers = 0; // Count of large costs which are integer
10510       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
10511         double value = solution[iColumn];
10512         // make sure clean
10513         value = CoinMin(value, columnUpper[iColumn]);
10514         value = CoinMax(value, columnLower[iColumn]);
10515         double cost = direction * objective[iColumn];
10516         if (cost) {
10517           if (columnLower[iColumn] < columnUpper[iColumn]) {
10518             objValue += value * cost;
10519             value = fabs(cost) * multiplier;
10520             if (value < 2.1e9) {
10521               int nearest = static_cast< int >(floor(value + 0.5));
10522               assert(fabs(value - floor(value + 0.5)) < 1.0e-8);
10523               if (!increment)
10524                 increment = nearest;
10525               else
10526                 increment = gcd(increment, nearest);
10527             } else {
10528               // large value - may still be multiple of 1.0
10529               value = fabs(objective[iColumn]);
10530               assert(fabs(value - floor(value + 0.5)) < 1.0e-8);
10531               bigIntegers++;
10532             }
10533           } else {
10534             // fixed
10535             objFixedValue += value * cost;
10536           }
10537         }
10538       }
10539       if (increment) {
10540         double value = increment;
10541         value /= multiplier;
10542         if (value > trueIncrement) {
10543           double x = objValue / value;
10544           x = ceil(x - 1.0e-5);
10545           x *= value;
10546           //printf("fixed %g, variable %g -> %g, sum %g - cutoff %g\n",
10547           // objFixedValue,objValue,x,x+objFixedValue,cutoff);
10548           x += objFixedValue;
10549           if (x > cutoff + 1.0e-5 * fabs(cutoff) + 1.0e-5) {
10550             //printf("Node cutoff\n");
10551             feasible = false;
10552           }
10553         } else {
10554           value = trueIncrement;
10555           double x = objValue / value;
10556           x = ceil(x - 1.0e-5);
10557           x *= value;
10558           x += objFixedValue;
10559           if (x > cutoff + 1.0e-5 * fabs(cutoff) + 1.0e-5) {
10560             //printf("Node cutoff\n");
10561             feasible = false;
10562           }
10563         }
10564       }
10565     }
10566   }
10567 #endif
10568 
10569   setPointers(solver_);
10570   if (feasible && saveSolution) {
10571     // called from CbcNode
10572     assert(saveLower);
10573     assert(saveUpper);
10574     int numberColumns = solver_->getNumCols();
10575     memcpy(saveSolution, solver_->getColSolution(), numberColumns * sizeof(double));
10576     reserveCurrentSolution(saveSolution);
10577     memcpy(saveLower, solver_->getColLower(), numberColumns * sizeof(double));
10578     memcpy(saveUpper, solver_->getColUpper(), numberColumns * sizeof(double));
10579   }
10580 #ifdef COIN_HAS_CLP
10581   if (clpSolver && !feasible) {
10582     // make sure marked infeasible
10583     if (!clpSolver->isProvenDualInfeasible())
10584       clpSolver->getModelPtr()->setProblemStatus(1);
10585   }
10586 #endif
10587   int returnStatus = feasible ? 1 : 0;
10588   if (strategy_) {
10589     /*
10590           Possible returns from status:
10591             -1:	no recommendation
10592              0: treat as optimal
10593              1: treat as optimal and finished (no more resolves, cuts, etc.)
10594              2: treat as infeasible.
10595         */
10596     // user can play clever tricks here
10597     int status = strategy_->status(this, parent, whereFrom);
10598     if (status >= 0) {
10599       if (status == 0)
10600         returnStatus = 1;
10601       else if (status == 1)
10602         returnStatus = -1;
10603       else
10604         returnStatus = 0;
10605     }
10606   }
10607 #if 0
10608     if ((specialOptions_&1) != 0 && onOptimalPath) {
10609       const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
10610       if (!debugger) {
10611 	// tighten did something???
10612 	solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
10613 	solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2);
10614 	printf("Not on optimalpath aaaa\n");
10615 	//abort();
10616       } else {
10617 	printf("Still on optimal path\n");
10618       }
10619     }
10620 #endif
10621   return returnStatus;
10622 }
10623 
10624 /* Set up objects.  Only do ones whose length is in range.
10625    If makeEquality true then a new model may be returned if
10626    modifications had to be made, otherwise "this" is returned.
10627 
10628    Could use Probing at continuous to extend objects
10629 */
10630 CbcModel *
10631 CbcModel::findCliques(bool makeEquality,
10632   int atLeastThisMany, int lessThanThis,
10633   int /*defaultValue*/)
10634 {
10635   // No objects are allowed to exist
10636   assert(numberObjects_ == numberIntegers_ || !numberObjects_);
10637   CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow());
10638   int numberRows = solver_->getNumRows();
10639   int numberColumns = solver_->getNumCols();
10640 
10641   // We may want to add columns
10642   int numberSlacks = 0;
10643   int *rows = new int[numberRows];
10644   double *element = new double[numberRows];
10645 
10646   int iRow;
10647 
10648   findIntegers(true);
10649   numberObjects_ = numberIntegers_;
10650 
10651   int numberCliques = 0;
10652   OsiObject **object = new OsiObject *[numberRows];
10653   int *which = new int[numberIntegers_];
10654   char *type = new char[numberIntegers_];
10655   int *lookup = new int[numberColumns];
10656   int i;
10657   for (i = 0; i < numberColumns; i++)
10658     lookup[i] = -1;
10659   for (i = 0; i < numberIntegers_; i++)
10660     lookup[integerVariable_[i]] = i;
10661 
10662   // Statistics
10663   int totalP1 = 0, totalM1 = 0;
10664   int numberBig = 0, totalBig = 0;
10665   int numberFixed = 0;
10666 
10667   // Row copy
10668   const double *elementByRow = matrixByRow.getElements();
10669   const int *column = matrixByRow.getIndices();
10670   const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
10671   const int *rowLength = matrixByRow.getVectorLengths();
10672 
10673   // Column lengths for slacks
10674   const int *columnLength = solver_->getMatrixByCol()->getVectorLengths();
10675 
10676   const double *lower = getColLower();
10677   const double *upper = getColUpper();
10678   const double *rowLower = getRowLower();
10679   const double *rowUpper = getRowUpper();
10680   /*
10681       Scan the rows, looking for individual rows that are clique constraints.
10682     */
10683 
10684   for (iRow = 0; iRow < numberRows; iRow++) {
10685     int numberP1 = 0, numberM1 = 0;
10686     CoinBigIndex j;
10687     double upperValue = rowUpper[iRow];
10688     double lowerValue = rowLower[iRow];
10689     bool good = true;
10690     int slack = -1;
10691     /*
10692           Does this row qualify? All variables must be binary and all coefficients
10693           +/- 1.0. Variables with positive coefficients are recorded at the low end of
10694           which, variables with negative coefficients the high end.
10695         */
10696     for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
10697       int iColumn = column[j];
10698       int iInteger = lookup[iColumn];
10699       if (upper[iColumn] - lower[iColumn] < 1.0e-8) {
10700         // fixed
10701         upperValue -= lower[iColumn] * elementByRow[j];
10702         lowerValue -= lower[iColumn] * elementByRow[j];
10703         continue;
10704       } else if (upper[iColumn] != 1.0 || lower[iColumn] != 0.0) {
10705         good = false;
10706         break;
10707       } else if (iInteger < 0) {
10708         good = false;
10709         break;
10710       } else {
10711         if (columnLength[iColumn] == 1)
10712           slack = iInteger;
10713       }
10714       if (fabs(elementByRow[j]) != 1.0) {
10715         good = false;
10716         break;
10717       } else if (elementByRow[j] > 0.0) {
10718         which[numberP1++] = iInteger;
10719       } else {
10720         numberM1++;
10721         which[numberIntegers_ - numberM1] = iInteger;
10722       }
10723     }
10724     int iUpper = static_cast< int >(floor(upperValue + 1.0e-5));
10725     int iLower = static_cast< int >(ceil(lowerValue - 1.0e-5));
10726     /*
10727           What do we have? If the row upper bound is greater than 1-numberM1, this
10728           isn't a clique. If the row upper bound is 1-numberM1, we have the classic
10729           clique (an SOS1 on binary variables, if numberM1 = 0). If the upper bound
10730           equals numberM1, we can fix all variables. If the upper bound is less than
10731           numberM1, we're infeasible.
10732 
10733           A similar analysis applies using numberP1 against the lower bound.
10734         */
10735     int state = 0;
10736     if (upperValue < 1.0e6) {
10737       if (iUpper == 1 - numberM1)
10738         state = 1;
10739       else if (iUpper == -numberM1)
10740         state = 2;
10741       else if (iUpper < -numberM1)
10742         state = 3;
10743     }
10744     if (!state && lowerValue > -1.0e6) {
10745       if (-iLower == 1 - numberP1)
10746         state = -1;
10747       else if (-iLower == -numberP1)
10748         state = -2;
10749       else if (-iLower < -numberP1)
10750         state = -3;
10751     }
10752     /*
10753         What to do? If we learned nothing, move on to the next iteration. If we're
10754         infeasible, we're outta here. If we decided we can fix variables, do it.
10755         */
10756     if (good && state) {
10757       if (abs(state) == 3) {
10758         // infeasible
10759         numberObjects_ = -1;
10760         break;
10761       } else if (abs(state) == 2) {
10762         // we can fix all
10763         numberFixed += numberP1 + numberM1;
10764         if (state > 0) {
10765           // fix all +1 at 0, -1 at 1
10766           for (i = 0; i < numberP1; i++)
10767             solver_->setColUpper(integerVariable_[which[i]], 0.0);
10768           for (i = 0; i < numberM1; i++)
10769             solver_->setColLower(integerVariable_[which[numberIntegers_ - i - 1]],
10770               1.0);
10771         } else {
10772           // fix all +1 at 1, -1 at 0
10773           for (i = 0; i < numberP1; i++)
10774             solver_->setColLower(integerVariable_[which[i]], 1.0);
10775           for (i = 0; i < numberM1; i++)
10776             solver_->setColUpper(integerVariable_[which[numberIntegers_ - i - 1]],
10777               0.0);
10778         }
10779       } else {
10780         /*
10781                   And the final case: we have a clique constraint. If it's within the allowed
10782                   size range, make a clique object.
10783                 */
10784         int length = numberP1 + numberM1;
10785         if (length >= atLeastThisMany && length < lessThanThis) {
10786           // create object
10787           bool addOne = false;
10788           int objectType;
10789           /*
10790                       Choose equality (type 1) or inequality (type 0). If we're forcing equalities,
10791                       add a slack.
10792                     */
10793           if (iLower == iUpper) {
10794             objectType = 1;
10795           } else {
10796             if (makeEquality) {
10797               objectType = 1;
10798               element[numberSlacks] = state;
10799               rows[numberSlacks++] = iRow;
10800               addOne = true;
10801             } else {
10802               objectType = 0;
10803             }
10804           }
10805           /*
10806                       Record the strong values for the variables. Variables with positive
10807                       coefficients force all others when set to 1; variables with negative
10808                       coefficients force when set to 0. If the clique is formed against the row
10809                       lower bound, convert to the canonical form of a clique against the row
10810                       upper bound.
10811                     */
10812           if (state > 0) {
10813             totalP1 += numberP1;
10814             totalM1 += numberM1;
10815             for (i = 0; i < numberP1; i++)
10816               type[i] = 1;
10817             for (i = 0; i < numberM1; i++) {
10818               which[numberP1] = which[numberIntegers_ - i - 1];
10819               type[numberP1++] = 0;
10820             }
10821           } else {
10822             totalP1 += numberM1;
10823             totalM1 += numberP1;
10824             for (i = 0; i < numberP1; i++)
10825               type[i] = 0;
10826             for (i = 0; i < numberM1; i++) {
10827               which[numberP1] = which[numberIntegers_ - i - 1];
10828               type[numberP1++] = 1;
10829             }
10830           }
10831           if (addOne) {
10832             // add in slack
10833             which[numberP1] = numberIntegers_ + numberSlacks - 1;
10834             slack = numberP1;
10835             type[numberP1++] = 1;
10836           } else if (slack >= 0) {
10837             for (i = 0; i < numberP1; i++) {
10838               if (which[i] == slack) {
10839                 slack = i;
10840               }
10841             }
10842           }
10843           object[numberCliques] = new CbcClique(this, objectType, numberP1,
10844             which, type,
10845             1000000 + numberCliques, slack);
10846           numberCliques++;
10847         } else if (numberP1 + numberM1 >= lessThanThis) {
10848           // too big
10849           numberBig++;
10850           totalBig += numberP1 + numberM1;
10851         }
10852       }
10853     }
10854   }
10855   delete[] which;
10856   delete[] type;
10857   delete[] lookup;
10858 #if COIN_DEVELOP > 1
10859   if (numberCliques < 0) {
10860     printf("*** Problem infeasible\n");
10861   } else {
10862     if (numberCliques)
10863       printf("%d cliques of average size %g found, %d P1, %d M1\n",
10864         numberCliques,
10865         (static_cast< double >(totalP1 + totalM1)) / (static_cast< double >(numberCliques)),
10866         totalP1, totalM1);
10867     else
10868       printf("No cliques found\n");
10869     if (numberBig)
10870       printf("%d large cliques ( >= %d) found, total %d\n",
10871         numberBig, lessThanThis, totalBig);
10872     if (numberFixed)
10873       printf("%d variables fixed\n", numberFixed);
10874   }
10875 #endif
10876   /*
10877       If required, augment the constraint matrix with clique slacks. Seems like we
10878       should be able to add the necessary integer objects without a complete
10879       rebuild of existing integer objects, but I'd need to look further to confirm
10880       that (lh, 071219). Finally, add the clique objects.
10881     */
10882   if (numberCliques > 0 && numberSlacks && makeEquality) {
10883     COIN_DETAIL_PRINT(printf("adding %d integer slacks\n", numberSlacks));
10884     // add variables to make equality rows
10885     int *temp = new int[numberIntegers_ + numberSlacks];
10886     memcpy(temp, integerVariable_, numberIntegers_ * sizeof(int));
10887     // Get new model
10888     CbcModel *newModel = new CbcModel(*this);
10889     OsiSolverInterface *newSolver = newModel->solver();
10890     for (i = 0; i < numberSlacks; i++) {
10891       temp[i + numberIntegers_] = i + numberColumns;
10892       int iRow = rows[i];
10893       double value = element[i];
10894       double lowerValue = 0.0;
10895       double upperValue = 1.0;
10896       double objValue = 0.0;
10897       CoinPackedVector column(1, &iRow, &value);
10898       newSolver->addCol(column, lowerValue, upperValue, objValue);
10899       // set integer
10900       newSolver->setInteger(numberColumns + i);
10901       if (value > 0)
10902         newSolver->setRowLower(iRow, rowUpper[iRow]);
10903       else
10904         newSolver->setRowUpper(iRow, rowLower[iRow]);
10905     }
10906     // replace list of integers
10907     for (i = 0; i < newModel->numberObjects_; i++)
10908       delete newModel->object_[i];
10909     newModel->numberObjects_ = 0;
10910     delete[] newModel->object_;
10911     newModel->object_ = NULL;
10912     newModel->findIntegers(true); //Set up all integer objects
10913     for (i = 0; i < numberIntegers_; i++) {
10914       newModel->modifiableObject(i)->setPriority(object_[i]->priority());
10915     }
10916     if (originalColumns_) {
10917       // old model had originalColumns
10918       delete[] newModel->originalColumns_;
10919       newModel->originalColumns_ = new int[numberColumns + numberSlacks];
10920       memcpy(newModel->originalColumns_, originalColumns_, numberColumns * sizeof(int));
10921       // mark as not in previous model
10922       for (i = numberColumns; i < numberColumns + numberSlacks; i++)
10923         newModel->originalColumns_[i] = -1;
10924     }
10925     delete[] rows;
10926     delete[] element;
10927     newModel->addObjects(numberCliques, object);
10928     assert(ownObjects_);
10929     for (; i < numberCliques; i++)
10930       delete object[i];
10931     delete[] object;
10932     newModel->synchronizeModel();
10933     return newModel;
10934   } else {
10935     assert(ownObjects_);
10936     if (numberCliques > 0) {
10937       addObjects(numberCliques, object);
10938       for (; i < numberCliques; i++)
10939         delete object[i];
10940       synchronizeModel();
10941     }
10942     delete[] object;
10943     delete[] rows;
10944     delete[] element;
10945     return this;
10946   }
10947 }
10948 // Fill in useful estimates
10949 void CbcModel::pseudoShadow(int iActive)
10950 {
10951   assert(iActive < 2 * 8 * 32 && iActive > -3);
10952   if (iActive == -1) {
10953     if (numberNodes_) {
10954       // zero out
10955       for (int i = 0; i < numberObjects_; i++) {
10956         CbcSimpleIntegerDynamicPseudoCost *obj1 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
10957         if (obj1) {
10958           //assert (obj1->downShadowPrice()>0.0);
10959 #define P_FACTOR 1.0
10960 #ifndef JJF_ONE
10961           obj1->setDownShadowPrice(-P_FACTOR * obj1->downShadowPrice());
10962           obj1->setUpShadowPrice(-P_FACTOR * obj1->upShadowPrice());
10963 #else
10964           double pCost;
10965           double sCost;
10966           pCost = obj1->downDynamicPseudoCost();
10967           sCost = P_FACTOR * obj1->downShadowPrice();
10968           if (!obj1->numberTimesDown() || sCost > pCost)
10969             obj1->updateDownDynamicPseudoCost(sCost);
10970           obj1->setDownShadowPrice(0.0);
10971           pCost = obj1->upDynamicPseudoCost();
10972           sCost = P_FACTOR * obj1->upShadowPrice();
10973           if (!obj1->numberTimesUp() || sCost > pCost)
10974             obj1->updateUpDynamicPseudoCost(sCost);
10975           obj1->setUpShadowPrice(0.0);
10976 #endif
10977         }
10978       }
10979     }
10980     return;
10981   }
10982   bool doShadow = false;
10983   if (!iActive || iActive >= 32) {
10984     doShadow = true;
10985     if (iActive >= 32)
10986       iActive -= 32;
10987   }
10988   double *rowWeight = NULL;
10989   double *columnWeight = NULL;
10990   int numberColumns = solver_->getNumCols();
10991   int numberRows = solver_->getNumRows();
10992   // Column copy of matrix
10993   const double *element = solver_->getMatrixByCol()->getElements();
10994   const int *row = solver_->getMatrixByCol()->getIndices();
10995   const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts();
10996   const int *columnLength = solver_->getMatrixByCol()->getVectorLengths();
10997   const double *dual = solver_->getRowPrice();
10998   const double *solution = solver_->getColSolution();
10999   const double *dj = solver_->getReducedCost();
11000   bool useMax = false;
11001   bool useAlpha = false;
11002   if (iActive) {
11003     // Use Patel and Chinneck ideas
11004     rowWeight = new double[numberRows];
11005     columnWeight = new double[numberColumns];
11006     // add in active constraints
11007     double tolerance = 1.0e-5;
11008     const double *rowLower = getRowLower();
11009     const double *rowUpper = getRowUpper();
11010     const double *rowActivity = solver_->getRowActivity();
11011     const double *lower = getColLower();
11012     const double *upper = getColUpper();
11013     CoinZeroN(rowWeight, numberRows);
11014     /* 1 A weight 1
11015            2 B weight 1/sum alpha
11016            3 L weight 1/number integer
11017            4 M weight 1/number active integer
11018            7 O weight 1/number integer and use alpha
11019            8 P weight 1/number active integer and use alpha
11020            9 up subtract 8 and use maximum
11021         */
11022     if (iActive > 8) {
11023       iActive -= 8;
11024       useMax = true;
11025     }
11026     if (iActive > 4) {
11027       iActive -= 4;
11028       useAlpha = true;
11029     }
11030     switch (iActive) {
11031       // A
11032     case 1:
11033       for (int iRow = 0; iRow < numberRows; iRow++) {
11034         if (rowActivity[iRow] > rowUpper[iRow] - tolerance || rowActivity[iRow] < rowLower[iRow] + tolerance) {
11035           rowWeight[iRow] = 1.0;
11036         }
11037       }
11038       break;
11039       // B
11040     case 2:
11041       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
11042         if (upper[iColumn] > lower[iColumn]) {
11043           CoinBigIndex start = columnStart[iColumn];
11044           CoinBigIndex end = start + columnLength[iColumn];
11045           for (CoinBigIndex j = start; j < end; j++) {
11046             int iRow = row[j];
11047             rowWeight[iRow] += fabs(element[j]);
11048           }
11049         }
11050       }
11051       for (int iRow = 0; iRow < numberRows; iRow++) {
11052         if (rowWeight[iRow])
11053           rowWeight[iRow] = 1.0 / rowWeight[iRow];
11054       }
11055       break;
11056       // L
11057     case 3:
11058       for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
11059         int iColumn = integerVariable_[jColumn];
11060         if (upper[iColumn] > lower[iColumn]) {
11061           CoinBigIndex start = columnStart[iColumn];
11062           CoinBigIndex end = start + columnLength[iColumn];
11063           for (CoinBigIndex j = start; j < end; j++) {
11064             int iRow = row[j];
11065             rowWeight[iRow]++;
11066           }
11067         }
11068       }
11069       for (int iRow = 0; iRow < numberRows; iRow++) {
11070         if (rowWeight[iRow])
11071           rowWeight[iRow] = 1.0 / rowWeight[iRow];
11072       }
11073       break;
11074       // M
11075     case 4:
11076       for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
11077         int iColumn = integerVariable_[jColumn];
11078         double value = solution[iColumn];
11079         if (fabs(value - floor(value + 0.5)) > 1.0e-5) {
11080           CoinBigIndex start = columnStart[iColumn];
11081           CoinBigIndex end = start + columnLength[iColumn];
11082           for (CoinBigIndex j = start; j < end; j++) {
11083             int iRow = row[j];
11084             rowWeight[iRow]++;
11085           }
11086         }
11087       }
11088       for (int iRow = 0; iRow < numberRows; iRow++) {
11089         if (rowWeight[iRow])
11090           rowWeight[iRow] = 1.0 / rowWeight[iRow];
11091       }
11092       break;
11093     }
11094     if (doShadow) {
11095       for (int iRow = 0; iRow < numberRows; iRow++) {
11096         rowWeight[iRow] *= dual[iRow];
11097       }
11098     }
11099     dual = rowWeight;
11100   }
11101   const double *objective = solver_->getObjCoefficients();
11102   double direction = solver_->getObjSense();
11103   double *down = new double[numberColumns];
11104   double *up = new double[numberColumns];
11105   double upSum = 1.0e-20;
11106   double downSum = 1.0e-20;
11107   int numberIntegers = 0;
11108   if (doShadow) {
11109     // shadow prices
11110     if (!useMax) {
11111       for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
11112         int iColumn = integerVariable_[jColumn];
11113         CoinBigIndex start = columnStart[iColumn];
11114         CoinBigIndex end = start + columnLength[iColumn];
11115         double upValue = 0.0;
11116         double downValue = 0.0;
11117         double value = direction * objective[iColumn];
11118         if (value) {
11119           if (value > 0.0)
11120             upValue += value;
11121           else
11122             downValue -= value;
11123         }
11124         for (CoinBigIndex j = start; j < end; j++) {
11125           int iRow = row[j];
11126           value = -dual[iRow];
11127           assert(fabs(dual[iRow]) < 1.0e50);
11128           if (value) {
11129             value *= element[j];
11130             if (value > 0.0)
11131               upValue += value;
11132             else
11133               downValue -= value;
11134           }
11135         }
11136         up[iColumn] = upValue;
11137         down[iColumn] = downValue;
11138         if (solver_->isInteger(iColumn)) {
11139           if (!numberNodes_ && handler_->logLevel() > 1)
11140             printf("%d - up %g down %g cost %g\n",
11141               iColumn, upValue, downValue, objective[iColumn]);
11142           upSum += upValue;
11143           downSum += downValue;
11144           numberIntegers++;
11145         }
11146       }
11147     } else {
11148       for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
11149         int iColumn = integerVariable_[jColumn];
11150         CoinBigIndex start = columnStart[iColumn];
11151         CoinBigIndex end = start + columnLength[iColumn];
11152         double upValue = 0.0;
11153         double downValue = 0.0;
11154         double value = direction * objective[iColumn];
11155         if (value) {
11156           if (value > 0.0)
11157             upValue += value;
11158           else
11159             downValue -= value;
11160         }
11161         for (CoinBigIndex j = start; j < end; j++) {
11162           int iRow = row[j];
11163           value = -dual[iRow];
11164           if (value) {
11165             value *= element[j];
11166             if (value > 0.0)
11167               upValue = CoinMax(upValue, value);
11168             else
11169               downValue = CoinMax(downValue, -value);
11170           }
11171         }
11172         up[iColumn] = upValue;
11173         down[iColumn] = downValue;
11174         if (solver_->isInteger(iColumn)) {
11175           if (!numberNodes_ && handler_->logLevel() > 1)
11176             printf("%d - up %g down %g cost %g\n",
11177               iColumn, upValue, downValue, objective[iColumn]);
11178           upSum += upValue;
11179           downSum += downValue;
11180           numberIntegers++;
11181         }
11182       }
11183     }
11184   } else {
11185     for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) {
11186       int iColumn = integerVariable_[jColumn];
11187       CoinBigIndex start = columnStart[iColumn];
11188       CoinBigIndex end = start + columnLength[iColumn];
11189       double upValue = 0.0;
11190       double downValue = 0.0;
11191       double value = direction * objective[iColumn];
11192       if (value) {
11193         if (value > 0.0)
11194           upValue += value;
11195         else
11196           downValue -= value;
11197       }
11198       double weight = 0.0;
11199       for (CoinBigIndex j = start; j < end; j++) {
11200         int iRow = row[j];
11201         value = -dual[iRow];
11202         double thisWeight = rowWeight[iRow];
11203         if (useAlpha)
11204           thisWeight *= fabs(element[j]);
11205         if (!useMax)
11206           weight += thisWeight;
11207         else
11208           weight = CoinMax(weight, thisWeight);
11209         if (value) {
11210           value *= element[j];
11211           if (value > 0.0)
11212             upValue += value;
11213           else
11214             downValue -= value;
11215         }
11216       }
11217       columnWeight[iColumn] = weight;
11218       // use dj if bigger
11219       double djValue = dj[iColumn];
11220       upValue = CoinMax(upValue, djValue);
11221       downValue = CoinMax(downValue, -djValue);
11222       up[iColumn] = upValue;
11223       down[iColumn] = downValue;
11224       if (solver_->isInteger(iColumn)) {
11225         if (!numberNodes_ && handler_->logLevel() > 1)
11226           printf("%d - dj %g up %g down %g cost %g\n",
11227             iColumn, djValue, upValue, downValue, objective[iColumn]);
11228         upSum += upValue;
11229         downSum += downValue;
11230         numberIntegers++;
11231       }
11232     }
11233     if (numberIntegers) {
11234       double averagePrice = (0.5 * (upSum + downSum)) / static_cast< double >(numberIntegers);
11235       //averagePrice *= 0.1;
11236       averagePrice *= 100.0;
11237       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
11238         double weight = columnWeight[iColumn];
11239         up[iColumn] += averagePrice * weight;
11240         down[iColumn] += averagePrice * weight;
11241       }
11242     }
11243   }
11244   delete[] rowWeight;
11245   delete[] columnWeight;
11246   if (numberIntegers) {
11247     double smallDown = 0.0001 * (downSum / static_cast< double >(numberIntegers));
11248     double smallUp = 0.0001 * (upSum / static_cast< double >(numberIntegers));
11249 #define PSEUDO_FACTOR 5.0e-1
11250     double pseudoFactor = PSEUDO_FACTOR;
11251     //if (!numberNodes_)
11252     //pseudoFactor=0.0;
11253     for (int i = 0; i < numberObjects_; i++) {
11254       CbcSimpleIntegerDynamicPseudoCost *obj1 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
11255       if (obj1 && obj1->upShadowPrice() >= 0.0) {
11256         int iColumn = obj1->columnNumber();
11257         double upPseudoCost = obj1->upDynamicPseudoCost();
11258         double saveUp = upPseudoCost;
11259         upPseudoCost = CoinMax(pseudoFactor * upPseudoCost, smallUp);
11260         upPseudoCost = CoinMax(upPseudoCost, up[iColumn]);
11261         upPseudoCost = CoinMax(upPseudoCost, 0.001 * down[iColumn]);
11262         obj1->setUpShadowPrice(upPseudoCost);
11263         if (upPseudoCost > saveUp && !numberNodes_ && handler_->logLevel() > 1)
11264           printf("For %d up went from %g to %g\n",
11265             iColumn, saveUp, upPseudoCost);
11266         double downPseudoCost = obj1->downDynamicPseudoCost();
11267         double saveDown = downPseudoCost;
11268         downPseudoCost = CoinMax(pseudoFactor * downPseudoCost, smallDown);
11269         downPseudoCost = CoinMax(downPseudoCost, down[iColumn]);
11270         downPseudoCost = CoinMax(downPseudoCost, 0.001 * up[iColumn]);
11271         obj1->setDownShadowPrice(downPseudoCost);
11272         if (downPseudoCost > saveDown && !numberNodes_ && handler_->logLevel() > 1)
11273           printf("For %d down went from %g to %g\n",
11274             iColumn, saveDown, downPseudoCost);
11275       }
11276     }
11277   }
11278   delete[] down;
11279   delete[] up;
11280 }
11281 
11282 /*
11283   Set branching priorities.
11284 
11285   Setting integer priorities looks pretty robust; the call to findIntegers
11286   makes sure that SimpleInteger objects are in place. Setting priorities for
11287   other objects is entirely dependent on their existence, and the routine may
11288   quietly fail in several directions.
11289 */
11290 
11291 void CbcModel::passInPriorities(const int *priorities,
11292   bool ifObject)
11293 {
11294   findIntegers(false);
11295   int i;
11296   if (priorities) {
11297     int i0 = 0;
11298     int i1 = numberObjects_ - 1;
11299     if (ifObject) {
11300       for (i = numberIntegers_; i < numberObjects_; i++) {
11301         object_[i]->setPriority(priorities[i - numberIntegers_]);
11302       }
11303       i0 = numberIntegers_;
11304     } else {
11305       for (i = 0; i < numberIntegers_; i++) {
11306         object_[i]->setPriority(priorities[i]);
11307       }
11308       i1 = numberIntegers_ - 1;
11309     }
11310     messageHandler()->message(CBC_PRIORITY,
11311       messages())
11312       << i0 << i1 << numberObjects_ << CoinMessageEol;
11313   }
11314 }
11315 
11316 // Delete all object information
11317 void CbcModel::deleteObjects(bool getIntegers)
11318 {
11319   if (ownObjects_) {
11320     int i;
11321     for (i = 0; i < numberObjects_; i++)
11322       delete object_[i];
11323     delete[] object_;
11324   }
11325   object_ = NULL;
11326   numberObjects_ = 0;
11327   if (getIntegers && ownObjects_)
11328     findIntegers(true);
11329 }
11330 
11331 /*!
11332   Ensure all attached objects (OsiObjects, heuristics, and cut
11333   generators) point to this model.
11334 */
11335 void CbcModel::synchronizeModel()
11336 {
11337   if (!numberObjects_)
11338     return;
11339   int i;
11340   for (i = 0; i < numberHeuristics_; i++)
11341     heuristic_[i]->setModel(this);
11342   for (i = 0; i < numberObjects_; i++) {
11343     CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]);
11344     if (obj) {
11345       obj->setModel(this);
11346       obj->setPosition(i);
11347     }
11348   }
11349   for (i = 0; i < numberCutGenerators_; i++)
11350     generator_[i]->refreshModel(this);
11351 
11352   if (!solverCharacteristics_) {
11353     OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
11354     if (solverCharacteristics) {
11355       solverCharacteristics_ = solverCharacteristics;
11356     } else {
11357       // replace in solver
11358       OsiBabSolver defaultC;
11359       solver_->setAuxiliaryInfo(&defaultC);
11360       solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
11361     }
11362   }
11363 
11364   solverCharacteristics_->setSolver(solver_);
11365 }
11366 
11367 // Fill in integers and create objects
11368 
11369 /**
11370   The routine first does a scan to count the number of integer variables.
11371   It then creates an array, integerVariable_, to store the indices of the
11372   integer variables, and an array of `objects', one for each variable.
11373 
11374   The scan is repeated, this time recording the index of each integer
11375   variable in integerVariable_, and creating an CbcSimpleInteger object that
11376   contains information about the integer variable. Initially, this is just
11377   the index and upper & lower bounds.
11378 
11379   \todo
11380   Note the assumption in cbc that the first numberIntegers_ objects are
11381   CbcSimpleInteger. In particular, the code which handles the startAgain
11382   case assumes that if the object_ array exists it can simply replace the first
11383   numberInteger_ objects. This is arguably unsafe.
11384 
11385   I am going to re-order if necessary
11386 */
11387 
11388 void CbcModel::findIntegers(bool startAgain, int type)
11389 {
11390   assert(solver_);
11391   /*
11392       No need to do this if we have previous information, unless forced to start
11393       over.
11394     */
11395   if (numberIntegers_ && !startAgain && object_)
11396     return;
11397   /*
11398       Clear out the old integer variable list, then count the number of integer
11399       variables.
11400     */
11401   delete[] integerVariable_;
11402   integerVariable_ = NULL;
11403   numberIntegers_ = 0;
11404   int numberColumns = getNumCols();
11405   int iColumn;
11406   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11407     if (isInteger(iColumn))
11408       numberIntegers_++;
11409   }
11410   // Find out how many old non-integer objects there are
11411   int nObjects = 0;
11412   OsiObject **oldObject = object_;
11413   int iObject;
11414   // also see where old ones were
11415   char *mark = new char[numberColumns];
11416   CoinZeroN(mark, numberColumns);
11417   int iPriority = -100000;
11418   for (iObject = 0; iObject < numberObjects_; iObject++) {
11419     iPriority = CoinMax(iPriority, object_[iObject]->priority());
11420     CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(oldObject[iObject]);
11421     if (obj) {
11422       int iColumn = obj->columnNumber();
11423       if (iColumn >= 0 && iColumn < numberColumns)
11424         mark[iColumn] = 1;
11425       delete oldObject[iObject];
11426     } else {
11427       oldObject[nObjects++] = oldObject[iObject];
11428     }
11429   }
11430   // See if there any SOS
11431 #ifdef COIN_HAS_CLP
11432   if (!nObjects) {
11433     OsiClpSolverInterface *clpSolver
11434       = dynamic_cast< OsiClpSolverInterface * >(solver_);
11435     if (clpSolver && (clpSolver->numberSOS() || clpSolver->numberObjects())) {
11436       // deal with sos
11437       const CoinSet *setInfo = clpSolver->setInfo();
11438       int numberSOS = clpSolver->numberSOS();
11439       if (numberSOS) {
11440         nObjects = 0;
11441         delete[] oldObject;
11442         oldObject = new OsiObject *[numberSOS];
11443         for (int i = 0; i < numberSOS; i++) {
11444           int type = setInfo[i].setType();
11445           int n = setInfo[i].numberEntries();
11446           const int *which = setInfo[i].which();
11447           const double *weights = setInfo[i].weights();
11448           oldObject[nObjects++] = new CbcSOS(this, n, which, weights, i, type);
11449         }
11450       } else {
11451         // objects - only works with SOS at present
11452         int numberObjects = clpSolver->numberObjects();
11453         nObjects = 0;
11454         delete[] oldObject;
11455         oldObject = new OsiObject *[numberObjects];
11456         OsiObject **osiObjects = clpSolver->objects();
11457         for (int i = 0; i < numberObjects; i++) {
11458           OsiSOS *obj = dynamic_cast< OsiSOS * >(osiObjects[i]);
11459           if (obj) {
11460             int type = obj->setType();
11461             int n = obj->numberMembers();
11462             const int *which = obj->members();
11463             const double *weights = obj->weights();
11464             oldObject[nObjects++] = new CbcSOS(this, n, which, weights, i, type);
11465           }
11466         }
11467       }
11468     }
11469   }
11470 #endif
11471 
11472   /*
11473       Found any? Allocate an array to hold the indices of the integer variables.
11474       Make a large enough array for all objects
11475     */
11476   delete[] integerVariable_;
11477   object_ = new OsiObject *[numberIntegers_ + nObjects];
11478   numberObjects_ = numberIntegers_ + nObjects;
11479   integerVariable_ = new int[numberIntegers_];
11480   /*
11481       Walk the variables again, filling in the indices and creating objects for
11482       the integer variables. Initially, the objects hold the index and upper &
11483       lower bounds.
11484     */
11485   numberIntegers_ = 0;
11486   if (type == 2)
11487     continuousPriority_ = iPriority + 1;
11488   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11489     if (isInteger(iColumn)) {
11490       if (!type) {
11491         object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn);
11492       } else if (type == 1) {
11493         object_[numberIntegers_] = new CbcSimpleIntegerPseudoCost(this, iColumn, 0.3);
11494       } else if (type == 2) {
11495         object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn);
11496         if (mark[iColumn]) {
11497           // could up priority on costs if all costs same??
11498         } else {
11499           object_[numberIntegers_]->setPriority(iPriority + 1);
11500         }
11501       }
11502       integerVariable_[numberIntegers_++] = iColumn;
11503     }
11504   }
11505   delete[] mark;
11506   // Now append other objects
11507   memcpy(object_ + numberIntegers_, oldObject, nObjects * sizeof(OsiObject *));
11508   // Delete old array (just array)
11509   delete[] oldObject;
11510 
11511   if (!numberObjects_)
11512     handler_->message(CBC_NOINT, messages_) << CoinMessageEol;
11513 }
11514 /* If numberBeforeTrust >0 then we are going to use CbcBranchDynamic.
11515    Scan and convert CbcSimpleInteger objects
11516 */
11517 void CbcModel::convertToDynamic()
11518 {
11519   int iObject;
11520   const double *cost = solver_->getObjCoefficients();
11521   bool allDynamic = true;
11522   for (iObject = 0; iObject < numberObjects_; iObject++) {
11523     CbcSimpleInteger *obj1 = dynamic_cast< CbcSimpleInteger * >(object_[iObject]);
11524     CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(object_[iObject]);
11525     CbcSimpleIntegerDynamicPseudoCost *obj2 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[iObject]);
11526     if (obj1 && !obj2) {
11527       // replace
11528       int iColumn = obj1->columnNumber();
11529       int priority = obj1->priority();
11530       int preferredWay = obj1->preferredWay();
11531       double costValue = CoinMax(1.0e-5, fabs(cost[iColumn]));
11532       // treat as if will cost what it says up
11533       double upCost = costValue;
11534 #ifndef BRANCH_BREAKEVEN
11535 #define BRANCH_BREAKEVEN 0.3
11536 #else
11537       preferredWay = 1;
11538 #endif
11539       // and balance at breakeven of 0.3
11540       double downCost = ((1.0 - BRANCH_BREAKEVEN) * upCost) / BRANCH_BREAKEVEN;
11541       if (obj1a) {
11542         upCost = obj1a->upPseudoCost();
11543         downCost = obj1a->downPseudoCost();
11544       }
11545       delete object_[iObject];
11546       CbcSimpleIntegerDynamicPseudoCost *newObject = new CbcSimpleIntegerDynamicPseudoCost(this, iColumn, 1.0e0 * downCost, 1.0e0 * upCost);
11547       //newObject->setNumberBeforeTrust(numberBeforeTrust_);
11548       newObject->setPriority(priority);
11549       newObject->setPosition(iObject);
11550       newObject->setPreferredWay(preferredWay);
11551       object_[iObject] = newObject;
11552     } else if (!obj2) {
11553       CbcObject *obj3 = dynamic_cast< CbcObject * >(object_[iObject]);
11554       if (!obj3 || !obj3->optionalObject())
11555         allDynamic = false;
11556     } else {
11557       // synchronize trust
11558       //obj2->setNumberBeforeTrust(numberBeforeTrust_);
11559     }
11560   }
11561   if (branchingMethod_) {
11562     if ((branchingMethod_->whichMethod() & 1) == 0 && !branchingMethod_->chooseMethod()) {
11563       // Need a method which can do better
11564       delete branchingMethod_;
11565       branchingMethod_ = NULL;
11566     }
11567   }
11568   if (allDynamic)
11569     ownership_ |= 0x40000000;
11570   if (!branchingMethod_ && allDynamic) {
11571     // create one
11572     branchingMethod_ = new CbcBranchDynamicDecision();
11573   }
11574 #ifdef SWITCH_VARIABLES
11575   // see if any switching variables
11576   if (numberIntegers_ < solver_->getNumCols())
11577     findSwitching();
11578 #endif
11579   synchronizeNumberBeforeTrust();
11580 }
11581 #ifdef SWITCH_VARIABLES
11582 // Convert Dynamic to Switching
11583 int CbcModel::findSwitching()
11584 {
11585   if ((moreSpecialOptions2_ & 1) == 0)
11586     return 0;
11587   const CoinPackedMatrix *rowCopy = solver_->getMatrixByRow();
11588   const int *column = rowCopy->getIndices();
11589   const int *rowLength = rowCopy->getVectorLengths();
11590   const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
11591   const double *rowLower = solver_->getRowLower();
11592   const double *rowUpper = solver_->getRowUpper();
11593   const double *columnLower = solver_->getColLower();
11594   const double *columnUpper = solver_->getColUpper();
11595   const double *element = rowCopy->getElements();
11596   //const double * element = solver_->getMatrixByCol()->getElements();
11597   const int *row = solver_->getMatrixByCol()->getIndices();
11598   const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts();
11599   const int *columnLength = solver_->getMatrixByCol()->getVectorLengths();
11600   int numberRows = solver_->getNumRows();
11601   int numberColumns = solver_->getNumCols();
11602   int *sort = new int[2 * numberRows + 2 + numberColumns];
11603   int *whichRow = sort + numberRows + 1;
11604   int *marked = whichRow + numberRows + 1;
11605   memset(marked, 0, numberColumns * sizeof(int));
11606   int nnSwitch = 0;
11607   int nnSwitchTotal = 0;
11608   int n2Switch = 0;
11609   double largeRatio1 = 1000.0;
11610   double largeRatio2 = 100.0;
11611   for (int i = 0; i < numberIntegers_; i++) {
11612     int iColumn = integerVariable_[i];
11613     if (columnLower[iColumn] || columnUpper[iColumn] != 1.0)
11614       continue;
11615     if (!dynamic_cast< CbcSimpleInteger * >(object_[i]))
11616       continue;
11617     int nAdd = 0;
11618     bool takeThis = false;
11619     CoinBigIndex start = columnStart[iColumn];
11620     CoinBigIndex end = start + columnLength[iColumn];
11621     for (CoinBigIndex j = start; j < end; j++) {
11622       int iRow = row[j];
11623       if (rowLength[iRow] != 2) {
11624         continue;
11625       }
11626       // for now just 0.0 in rhs
11627       if (!rowLower[iRow]) {
11628         if (rowUpper[iRow] != COIN_DBL_MAX)
11629           continue;
11630       } else if (rowLower[iRow] != -COIN_DBL_MAX) {
11631         continue;
11632       } else if (rowUpper[iRow]) {
11633         continue;
11634       }
11635       CoinBigIndex k = rowStart[iRow];
11636       double bValue, cValue;
11637       int cColumn;
11638       if (column[k] == iColumn) {
11639         bValue = element[k];
11640         cValue = element[k + 1];
11641         cColumn = column[k + 1];
11642       } else {
11643         bValue = element[k + 1];
11644         cValue = element[k];
11645         cColumn = column[k];
11646       }
11647       if (solver_->isInteger(cColumn))
11648         continue;
11649       if (columnLower[cColumn] < 0.0)
11650         continue;
11651       if (bValue * cValue > 0.0)
11652         continue;
11653       if (fabs(bValue) > largeRatio1 * fabs(cValue))
11654         takeThis = true;
11655       // add to list
11656       whichRow[nAdd] = iRow;
11657       sort[nAdd++] = cColumn;
11658     }
11659     if (nAdd) {
11660       n2Switch++;
11661       CoinSort_2(sort, sort + nAdd, whichRow);
11662       int last = sort[0];
11663       for (int k = 1; k < nAdd; k++) {
11664         if (sort[k] == last)
11665           takeThis = true;
11666         else
11667           last = sort[k];
11668       }
11669       if (takeThis) {
11670         int last = sort[0];
11671         marked[last]++;
11672         for (int k = 1; k < nAdd; k++) {
11673           if (sort[k] != last) {
11674             last = sort[k];
11675             marked[last]++;
11676           }
11677         }
11678         //printf("Column %d has %d other columns\n",iColumn,nAdd);
11679         sort[nAdd] = COIN_INT_MAX;
11680         whichRow[nAdd] = COIN_INT_MAX;
11681         CbcSimpleIntegerDynamicPseudoCost *thisOne = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
11682         if (thisOne) {
11683           assert(iColumn == thisOne->columnNumber());
11684           object_[i] = new CbcSwitchingBinary(thisOne, nAdd, sort, whichRow);
11685           delete thisOne;
11686         } else {
11687           CbcSimpleInteger *thisOne = dynamic_cast< CbcSimpleInteger * >(object_[i]);
11688           assert(thisOne);
11689           assert(iColumn == thisOne->columnNumber());
11690           CbcSimpleIntegerDynamicPseudoCost tempObj(this, iColumn, 0.1);
11691           object_[i] = new CbcSwitchingBinary(&tempObj, nAdd, sort, whichRow);
11692           delete thisOne;
11693         }
11694       }
11695     }
11696     // see if there is an interesting row
11697     for (CoinBigIndex j = start; j < end; j++) {
11698       int iRow = row[j];
11699       // for now just 0.0 in rhs
11700       if (!rowLower[iRow]) {
11701         if (rowUpper[iRow] != COIN_DBL_MAX)
11702           continue;
11703       } else if (rowLower[iRow] != -COIN_DBL_MAX) {
11704         continue;
11705       } else if (rowUpper[iRow]) {
11706         continue;
11707       }
11708       int nOther = 0;
11709       double bEl = 0.0;
11710       double cMax = -COIN_DBL_MAX;
11711       double cMin = COIN_DBL_MAX;
11712       for (CoinBigIndex k = rowStart[iRow];
11713            k < rowStart[iRow] + rowLength[iRow]; k++) {
11714         int jColumn = column[k];
11715         if (jColumn == iColumn) {
11716           bEl = element[k];
11717         } else {
11718           sort[nOther++] = jColumn;
11719           if (solver_->isInteger(jColumn)) {
11720             cMin = -1.0;
11721             cMax = 1.0;
11722             break;
11723           } else {
11724             cMax = CoinMax(cMax, element[k]);
11725             cMin = CoinMin(cMin, element[k]);
11726             if (columnLower[jColumn] < 0.0) {
11727               cMin = -1.0;
11728               cMax = 1.0;
11729               break;
11730             }
11731           }
11732         }
11733       }
11734       double largestC = CoinMax(fabs(cMin), fabs(cMax));
11735       if (((cMin > 0.0 && bEl < 0.0 && !rowUpper[iRow]) || (cMin < 0.0 && bEl > 0.0 && !rowLower[iRow])) && cMin * cMax > 0.0 && fabs(bEl) > largeRatio2 * largestC) {
11736         // forces to zero
11737         CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]);
11738         if (!object) {
11739           // create empty one
11740           CbcSimpleIntegerDynamicPseudoCost *thisOne = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
11741           if (thisOne) {
11742             assert(iColumn == thisOne->columnNumber());
11743             object = new CbcSwitchingBinary(thisOne, 0, sort, whichRow);
11744             delete thisOne;
11745           } else {
11746             CbcSimpleInteger *thisOne = dynamic_cast< CbcSimpleInteger * >(object_[i]);
11747             assert(thisOne);
11748             assert(iColumn == thisOne->columnNumber());
11749             CbcSimpleIntegerDynamicPseudoCost tempObj(this, iColumn, 0.1);
11750             object = new CbcSwitchingBinary(&tempObj, 0, sort, whichRow);
11751             delete thisOne;
11752           }
11753           object_[i] = object;
11754         }
11755         object->addZeroSwitches(nOther, sort);
11756         nnSwitch++;
11757         nnSwitchTotal += nOther;
11758       }
11759     }
11760   }
11761   if (n2Switch + nnSwitch) {
11762     if (handler_->logLevel() > 2)
11763       printf("%d two switch variables - %d multi (total multi %d)\n",
11764         n2Switch, nnSwitch, nnSwitchTotal);
11765     memset(whichRow, 0, (numberRows + 1) * sizeof(int));
11766     for (int i = 0; i < numberColumns; i++) {
11767       whichRow[marked[i]]++;
11768     }
11769     if (handler_->logLevel() > 2) {
11770       for (int i = 0; i < numberRows + 1; i++) {
11771         if (whichRow[i])
11772           printf("%d variables have %d switches\n", whichRow[i], i);
11773       }
11774     }
11775   }
11776   delete[] sort;
11777   // say switches exist
11778   if (n2Switch + nnSwitch)
11779     moreSpecialOptions2_ |= 4;
11780   return n2Switch + nnSwitch;
11781 }
11782 // Fix associated variables
11783 int CbcModel::fixAssociated(OsiSolverInterface *solver, int cleanBasis)
11784 {
11785   int nChanged = 0;
11786   if ((moreSpecialOptions2_ & 4) != 0) {
11787     int n = -1;
11788     while (n) {
11789       n = 0;
11790       for (int i = 0; i < numberObjects_; i++) {
11791         CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]);
11792         if (object) {
11793           n += object->setAssociatedBounds(solver, cleanBasis);
11794         }
11795       }
11796       nChanged += n;
11797     }
11798   }
11799   return nChanged;
11800 }
11801 /* Debug associated variables
11802    printLevel - 1 summary if bad on fixed
11803                 2 summary if bad on satisfied
11804                 3 for individuals
11805  */
11806 int CbcModel::checkAssociated(const OsiSolverInterface *solver,
11807   const double *solution, int printLevel)
11808 {
11809   int nBad = 0;
11810   int nBadFixed = 0;
11811   if ((moreSpecialOptions2_ & 4) != 0) {
11812     int nAt0 = 0;
11813     int nAt1 = 0;
11814     int nBetween = 0;
11815     for (int i = 0; i < numberObjects_; i++) {
11816       CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]);
11817       if (object) {
11818         int state[3];
11819         nBad += object->checkAssociatedBounds(solver, solution, printLevel, state,
11820           nBadFixed);
11821         if (state[0] == 0)
11822           nBetween++;
11823         else if (state[0] == -1)
11824           nAt0++;
11825         else
11826           nAt1++;
11827       }
11828     }
11829     if (handler_->logLevel() > 2) {
11830       if (printLevel > 1 || (printLevel == 1 && nBadFixed)) {
11831         printf("%d switches, %d at 0, %d at 1, %d between - %d bad values (%d when fixed)\n",
11832           nBetween + nAt0 + nAt1, nAt0, nAt1, nBetween, nBad, nBadFixed);
11833         if (nBadFixed && printLevel != 3)
11834           checkAssociated(solver, solution, 3);
11835       }
11836     }
11837   }
11838   return nBad;
11839 }
11840 #endif
11841 // Set numberBeforeTrust in all objects
11842 void CbcModel::synchronizeNumberBeforeTrust(int type)
11843 {
11844   int iObject;
11845   for (iObject = 0; iObject < numberObjects_; iObject++) {
11846     CbcSimpleIntegerDynamicPseudoCost *obj2 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[iObject]);
11847     if (obj2) {
11848       // synchronize trust
11849       if (!type) {
11850         obj2->setNumberBeforeTrust(numberBeforeTrust_);
11851       } else if (type == 1) {
11852         int value = obj2->numberBeforeTrust();
11853         value = (value * 11) / 10 + 1;
11854         value = CoinMax(numberBeforeTrust_, value);
11855         obj2->setNumberBeforeTrust(value);
11856       } else {
11857         assert(type == 2);
11858         int value = obj2->numberBeforeTrust();
11859         int n = CoinMax(obj2->numberTimesDown(),
11860           obj2->numberTimesUp());
11861         if (n >= value) {
11862           value = CoinMin(CoinMin(n + 1, 3 * (value + 1) / 2), 5 * numberBeforeTrust_);
11863           obj2->setNumberBeforeTrust(value);
11864         }
11865       }
11866     }
11867   }
11868 }
11869 
11870 /* Add in any object information (objects are cloned - owner can delete
11871    originals */
11872 void CbcModel::addObjects(int numberObjects, CbcObject **objects)
11873 {
11874   // If integers but not enough objects fudge
11875   if (numberIntegers_ > numberObjects_ || !numberObjects_)
11876     findIntegers(true);
11877   /* But if incoming objects inherit from simple integer we just want
11878        to replace */
11879   int numberColumns = solver_->getNumCols();
11880   /** mark is -1 if not integer, >=0 if using existing simple integer and
11881         >=numberColumns if using new integer */
11882   int *mark = new int[numberColumns];
11883   int i;
11884   for (i = 0; i < numberColumns; i++)
11885     mark[i] = -1;
11886   int newNumberObjects = numberObjects;
11887   int newIntegers = 0;
11888   for (i = 0; i < numberObjects; i++) {
11889     CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]);
11890     if (obj) {
11891       int iColumn = obj->columnNumber();
11892       assert(iColumn >= 0);
11893       mark[iColumn] = i + numberColumns;
11894       newIntegers++;
11895     }
11896   }
11897   // and existing
11898   for (i = 0; i < numberObjects_; i++) {
11899     CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
11900     if (obj) {
11901       int iColumn = obj->columnNumber();
11902       if (mark[iColumn] < 0) {
11903         newIntegers++;
11904         newNumberObjects++;
11905         mark[iColumn] = i;
11906       }
11907     } else {
11908       // some other object - keep
11909       newNumberObjects++;
11910     }
11911   }
11912   delete[] integerVariable_;
11913   integerVariable_ = NULL;
11914 #if COIN_DEVELOP > 1
11915   if (newIntegers != numberIntegers_)
11916     printf("changing number of integers from %d to %d\n",
11917       numberIntegers_, newIntegers);
11918 #endif
11919   numberIntegers_ = newIntegers;
11920   integerVariable_ = new int[numberIntegers_];
11921   OsiObject **temp = new OsiObject *[newNumberObjects];
11922   // Put integers first
11923   newIntegers = 0;
11924   numberIntegers_ = 0;
11925   for (i = 0; i < numberColumns; i++) {
11926     int which = mark[i];
11927     if (which >= 0) {
11928       if (!isInteger(i)) {
11929         newIntegers++;
11930         solver_->setInteger(i);
11931       }
11932       if (which < numberColumns) {
11933         temp[numberIntegers_] = object_[which];
11934         object_[which] = NULL;
11935       } else {
11936         temp[numberIntegers_] = objects[which - numberColumns]->clone();
11937       }
11938       integerVariable_[numberIntegers_++] = i;
11939     }
11940   }
11941 #if COIN_DEVELOP > 1
11942   if (newIntegers)
11943     printf("%d variables were declared integer\n", newIntegers);
11944 #endif
11945   int n = numberIntegers_;
11946   // Now rest of old
11947   for (i = 0; i < numberObjects_; i++) {
11948     if (object_[i]) {
11949       CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
11950       if (obj) {
11951         delete object_[i];
11952       } else {
11953         temp[n++] = object_[i];
11954       }
11955     }
11956   }
11957   // and rest of new
11958   for (i = 0; i < numberObjects; i++) {
11959     CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]);
11960     if (!obj) {
11961       temp[n] = objects[i]->clone();
11962       CbcObject *obj = dynamic_cast< CbcObject * >(temp[n]);
11963       if (obj)
11964         obj->setModel(this);
11965       n++;
11966     }
11967   }
11968   delete[] mark;
11969   assert(ownObjects_);
11970   delete[] object_;
11971   object_ = temp;
11972   assert(n == newNumberObjects);
11973   numberObjects_ = newNumberObjects;
11974 }
11975 /* Add in any object information (objects are cloned - owner can delete
11976    originals */
11977 void CbcModel::addObjects(int numberObjects, OsiObject **objects)
11978 {
11979   // If integers but not enough objects fudge
11980   if (numberIntegers_ > numberObjects_)
11981     findIntegers(true);
11982   /* But if incoming objects inherit from simple integer we just want
11983        to replace */
11984   int numberColumns = solver_->getNumCols();
11985   /** mark is -1 if not integer, >=0 if using existing simple integer and
11986         >=numberColumns if using new integer */
11987   int *mark = new int[numberColumns];
11988   int i;
11989   for (i = 0; i < numberColumns; i++)
11990     mark[i] = -1;
11991   int newNumberObjects = numberObjects;
11992   int newIntegers = 0;
11993   for (i = 0; i < numberObjects; i++) {
11994     CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]);
11995     if (obj) {
11996       int iColumn = obj->columnNumber();
11997       mark[iColumn] = i + numberColumns;
11998       newIntegers++;
11999     } else {
12000       OsiSimpleInteger *obj2 = dynamic_cast< OsiSimpleInteger * >(objects[i]);
12001       if (obj2) {
12002         // Osi takes precedence
12003         int iColumn = obj2->columnNumber();
12004         mark[iColumn] = i + numberColumns;
12005         newIntegers++;
12006       }
12007     }
12008   }
12009   // and existing
12010   for (i = 0; i < numberObjects_; i++) {
12011     CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
12012     if (obj) {
12013       int iColumn = obj->columnNumber();
12014       if (mark[iColumn] < 0) {
12015         newIntegers++;
12016         newNumberObjects++;
12017         mark[iColumn] = i;
12018       }
12019     } else {
12020       newNumberObjects++;
12021     }
12022   }
12023   delete[] integerVariable_;
12024   integerVariable_ = NULL;
12025 #if COIN_DEVELOP > 1
12026   if (newIntegers != numberIntegers_)
12027     printf("changing number of integers from %d to %d\n",
12028       numberIntegers_, newIntegers);
12029 #endif
12030   numberIntegers_ = newIntegers;
12031   integerVariable_ = new int[numberIntegers_];
12032   OsiObject **temp = new OsiObject *[newNumberObjects];
12033   // Put integers first
12034   newIntegers = 0;
12035   numberIntegers_ = 0;
12036   for (i = 0; i < numberColumns; i++) {
12037     int which = mark[i];
12038     if (which >= 0) {
12039       if (!isInteger(i)) {
12040         newIntegers++;
12041         solver_->setInteger(i);
12042       }
12043       if (which < numberColumns) {
12044         temp[numberIntegers_] = object_[which];
12045         object_[which] = NULL;
12046       } else {
12047         temp[numberIntegers_] = objects[which - numberColumns]->clone();
12048       }
12049       integerVariable_[numberIntegers_++] = i;
12050     }
12051   }
12052 #if COIN_DEVELOP > 1
12053   if (newIntegers)
12054     printf("%d variables were declared integer\n", newIntegers);
12055 #endif
12056   int n = numberIntegers_;
12057   // Now rest of old
12058   for (i = 0; i < numberObjects_; i++) {
12059     if (object_[i]) {
12060       CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
12061       if (obj) {
12062         delete object_[i];
12063       } else {
12064         temp[n++] = object_[i];
12065       }
12066     }
12067   }
12068   // and rest of new
12069   for (i = 0; i < numberObjects; i++) {
12070     CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]);
12071     OsiSimpleInteger *obj2 = dynamic_cast< OsiSimpleInteger * >(objects[i]);
12072     if (!obj && !obj2) {
12073       temp[n] = objects[i]->clone();
12074       CbcObject *obj = dynamic_cast< CbcObject * >(temp[n]);
12075       if (obj)
12076         obj->setModel(this);
12077       n++;
12078     }
12079   }
12080   delete[] mark;
12081   assert(ownObjects_);
12082   delete[] object_;
12083   object_ = temp;
12084   assert(n == newNumberObjects);
12085   numberObjects_ = newNumberObjects;
12086 }
12087 
12088 /**
12089   This routine sets the objective cutoff value used for fathoming and
12090   determining monotonic variables.
12091 
12092   If the fathoming discipline is strict, a small tolerance is added to the
12093   new cutoff. This avoids problems due to roundoff when the target value
12094   is exact. The common example would be an IP with only integer variables in
12095   the objective. If the target is set to the exact value z of the optimum,
12096   it's possible to end up fathoming an ancestor of the solution because the
12097   solver returns z+epsilon.
12098 
12099   Determining if strict fathoming is needed is best done by analysis.
12100   In cbc, that's analyseObjective. The default is false.
12101 
12102   In cbc we always minimize so add epsilon
12103 */
12104 
12105 void CbcModel::setCutoff(double value)
12106 
12107 {
12108 #ifdef JJF_ZERO
12109   double tol = 0;
12110   int fathomStrict = getIntParam(CbcFathomDiscipline);
12111   if (fathomStrict == 1) {
12112     solver_->getDblParam(OsiDualTolerance, tol);
12113     tol = tol * (1 + fabs(value));
12114 
12115     value += tol;
12116   }
12117 #endif
12118   dblParam_[CbcCurrentCutoff] = value;
12119   if (solver_) {
12120     // Solvers know about direction
12121     // but Clp tries to be too clever and flips twice!
12122 #ifndef COIN_HAS_CLP
12123     double direction = solver_->getObjSense();
12124 #else
12125     double direction = 1.0;
12126     if (!dynamic_cast< OsiClpSolverInterface * >(solver_))
12127       direction = solver_->getObjSense();
12128 #endif
12129     solver_->setDblParam(OsiDualObjectiveLimit, value * direction);
12130   }
12131 }
12132 
12133 /*
12134   Call this to really test if a valid solution can be feasible. The cutoff is
12135   passed in as a parameter so that we don't need to worry here after swapping
12136   solvers.  The solution is assumed to be numberColumns in size.  If
12137   fixVariables is true then the bounds of the continuous solver are updated.
12138   The routine returns the objective value determined by reoptimizing from
12139   scratch. If the solution is rejected, this will be worse than the cutoff.
12140 
12141   TODO: There's an issue with getting the correct cutoff value: We update the
12142 	cutoff in the regular solver, but not in continuousSolver_. But our only
12143 	use for continuousSolver_ is verifying candidate solutions. Would it
12144 	make sense to update the cutoff? Then we wouldn't need to step around
12145 	isDualObjectiveLimitReached().
12146 */
12147 double
12148 CbcModel::checkSolution(double cutoff, double *solution,
12149   int fixVariables, double objectiveValue)
12150 
12151 {
12152   int numberContinuousColumns = continuousSolver_->getNumCols();
12153   if (!solverCharacteristics_->solutionAddsCuts()) {
12154     // Can trust solution
12155     int numberColumns = solver_->getNumCols();
12156 #ifdef COIN_HAS_CLP
12157     OsiClpSolverInterface *clpContinuousSolver
12158       = dynamic_cast< OsiClpSolverInterface * >(continuousSolver_);
12159     int modifiedTolerances = 0;
12160 #ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
12161     int savePerturbation = -1;
12162 #endif
12163 #ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
12164     double savePrimalTolerance = 0.0;
12165 #endif
12166 #ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
12167     int saveScaling = -1;
12168 #endif
12169 #define CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION // for now
12170 #ifndef CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION
12171     int saveSpecialOptions=0;
12172 #endif
12173     if (clpContinuousSolver) {
12174       // be more accurate if possible
12175       ClpSimplex *clp = clpContinuousSolver->getModelPtr();
12176 #ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
12177       savePerturbation = clp->perturbation();
12178 #endif
12179 #ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
12180       savePrimalTolerance = clp->primalTolerance();
12181 #endif
12182 #ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
12183       saveScaling = clp->scalingFlag();
12184 #endif
12185 #ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
12186       if (savePrimalTolerance > 0.9999999e-7) {
12187         modifiedTolerances |= 1;
12188         clp->setPrimalTolerance(1.0e-8);
12189       }
12190 #endif
12191 #ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
12192       if (savePerturbation < 100) {
12193         modifiedTolerances |= 2;
12194         clp->setPerturbation(100);
12195       }
12196 #endif
12197 #ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
12198       if (saveScaling) {
12199         modifiedTolerances |= 4;
12200         clp->scaling(0);
12201         clpContinuousSolver->setHintParam(OsiDoScale, false, OsiHintTry);
12202       }
12203 #endif
12204 #ifndef CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION
12205       modifiedTolerances |= 8;
12206       saveSpecialOptions = clpContinuousSolver->specialOptions();
12207       clpContinuousSolver->setSpecialOptions(saveSpecialOptions&(~1)); // switch off crunch
12208 #endif
12209     }
12210 #endif
12211 
12212     /*
12213           Grab the continuous solver (the pristine copy of the problem, made before
12214           starting to work on the root node). Save the bounds on the variables.
12215           Install the solution passed as a parameter, and copy it to the model's
12216           currentSolution_.
12217 
12218           TODO: This is a belt-and-suspenders approach. Once the code has settled
12219           a bit, we can cast a critical eye here.
12220         */
12221     OsiSolverInterface *saveSolver = solver_;
12222     if (continuousSolver_)
12223       solver_ = continuousSolver_;
12224     // save basis and solution
12225     CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
12226     assert(basis != NULL);
12227     double *saveSolution = CoinCopyOfArray(solver_->getColSolution(),
12228       solver_->getNumCols());
12229     // move solution to continuous copy
12230     solver_->setColSolution(solution);
12231     // Put current solution in safe place
12232     // Point to current solution
12233     const double *save = testSolution_;
12234     // Safe as will be const inside infeasibility()
12235     testSolution_ = solver_->getColSolution();
12236     //memcpy(currentSolution_,solver_->getColSolution(),
12237     // numberColumns*sizeof(double));
12238     //solver_->messageHandler()->setLogLevel(4);
12239 
12240     // save original bounds
12241     double *saveUpper = new double[numberColumns];
12242     double *saveLower = new double[numberColumns];
12243     memcpy(saveUpper, getColUpper(), numberColumns * sizeof(double));
12244     memcpy(saveLower, getColLower(), numberColumns * sizeof(double));
12245     //#define CLP_INVESTIGATE4
12246 #if CBC_USEFUL_PRINTING > 14
12247     {
12248       int nBad = checkAssociated(solver_, solver_->getColSolution(), 1);
12249       if (nBad)
12250         checkAssociated(solver_, solver_->getColSolution(), 3);
12251       double largestInfeasibility = 0.0;
12252       double primalTolerance;
12253       double offset;
12254       solver_->getDblParam(OsiObjOffset, offset);
12255       solver_->getDblParam(OsiPrimalTolerance, primalTolerance);
12256       const double *objective = getObjCoefficients();
12257       const double *rowLower = solver_->getRowLower();
12258       const double *rowUpper = solver_->getRowUpper();
12259       const double *columnLower = solver_->getColLower();
12260       const double *columnUpper = solver_->getColUpper();
12261       int numberRows = solver_->getNumRows();
12262       double *rowActivity = new double[numberRows];
12263       memset(rowActivity, 0, numberRows * sizeof(double));
12264       double *rowSum = new double[numberRows];
12265       memset(rowSum, 0, numberRows * sizeof(double));
12266       int *marked = new int[numberColumns];
12267       for (int i = 0; i < numberColumns; i++)
12268         marked[i] = -1;
12269       for (int i = 0; i < numberIntegers_; i++)
12270         marked[integerVariable_[i]] = -2;
12271       if ((moreSpecialOptions2_ & 4) != 0) {
12272         for (int i = 0; i < numberObjects_; i++) {
12273           CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]);
12274           if (object) {
12275             int iColumn = object->columnNumber();
12276             const int *other = object->otherVariable();
12277             marked[iColumn] = -3 - other[0];
12278             int n = object->numberOther();
12279             for (int k = 0; k < n; k++)
12280               marked[other[k]] = iColumn;
12281           }
12282         }
12283       }
12284       const double *element = solver_->getMatrixByCol()->getElements();
12285       const int *row = solver_->getMatrixByCol()->getIndices();
12286       const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts();
12287       const int *columnLength = solver_->getMatrixByCol()->getVectorLengths();
12288       const CoinPackedMatrix *rowCopy = solver_->getMatrixByRow();
12289       const int *column = rowCopy->getIndices();
12290       const int *rowLength = rowCopy->getVectorLengths();
12291       const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
12292       const double *elementByRow = rowCopy->getElements();
12293       double objValue = -offset;
12294       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
12295         double value = solution[iColumn];
12296         objValue += value * objective[iColumn];
12297         if (value > columnUpper[iColumn]) {
12298           if (value - columnUpper[iColumn] > 1.0e-8)
12299             printf("column %d has value %.12g above %.12g\n", iColumn, value, columnUpper[iColumn]);
12300           value = columnUpper[iColumn];
12301         } else if (value < columnLower[iColumn]) {
12302           if (value - columnLower[iColumn] < -1.0e-8)
12303             printf("column %d has value %.12g below %.12g\n", iColumn, value, columnLower[iColumn]);
12304           value = columnLower[iColumn];
12305         }
12306         if (value) {
12307           CoinBigIndex start = columnStart[iColumn];
12308           CoinBigIndex end = start + columnLength[iColumn];
12309           for (CoinBigIndex j = start; j < end; j++) {
12310             int iRow = row[j];
12311             rowActivity[iRow] += value * element[j];
12312             rowSum[iRow] += fabs(value * element[j]);
12313           }
12314         }
12315       }
12316       for (int i = 0; i < numberRows; i++) {
12317 #if 0 //def CLP_INVESTIGATE
12318 	    double inf;
12319 	    inf = rowLower[i] - rowActivity[i];
12320 	    if (inf > primalTolerance)
12321 	      printf("Row %d inf %g sum %g %g <= %g <= %g\n",
12322 		     i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
12323 	    inf = rowActivity[i] - rowUpper[i];
12324 	    if (inf > primalTolerance)
12325 	      printf("Row %d inf %g sum %g %g <= %g <= %g\n",
12326 		     i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
12327 #endif
12328         double infeasibility = CoinMax(rowActivity[i] - rowUpper[i],
12329           rowLower[i] - rowActivity[i]);
12330         // but allow for errors
12331         double factor = CoinMax(1.0, rowSum[i] * 1.0e-3);
12332         if (infeasibility > largestInfeasibility * factor) {
12333           largestInfeasibility = infeasibility / factor;
12334           printf("Ainf of %g on row %d sum %g scaled %g\n",
12335             infeasibility, i, rowSum[i], largestInfeasibility);
12336           if (infeasibility > 1.0e10) {
12337             for (CoinBigIndex j = rowStart[i];
12338                  j < rowStart[i] + rowLength[i]; j++) {
12339               printf("col %d element %g marked %d\n",
12340                 column[j], elementByRow[j], marked[column[j]]);
12341             }
12342           }
12343         }
12344       }
12345       delete[] rowActivity;
12346       delete[] rowSum;
12347       delete[] marked;
12348       if (largestInfeasibility > 10.0 * primalTolerance)
12349         printf("Alargest infeasibility is %g - obj %g\n", largestInfeasibility, objValue);
12350       else
12351         printf("Afeasible (%g) - obj %g\n", largestInfeasibility, objValue);
12352     }
12353 #endif
12354     // point to useful information
12355     OsiBranchingInformation usefulInfo = usefulInformation();
12356 
12357     /*
12358           Run through the objects and use feasibleRegion() to set variable bounds
12359           so as to fix the variables specified in the objects at their value in this
12360           solution. Since the object list contains (at least) one object for every
12361           integer variable, this has the effect of fixing all integer variables.
12362         */
12363     int i;
12364     for (i = 0; i < numberObjects_; i++)
12365       object_[i]->feasibleRegion(solver_, &usefulInfo);
12366     // If SOS then might have been declared infeasible (bad heuristic)
12367     {
12368       int numberColumns = solver_->getNumCols();
12369       const double *columnLower = solver_->getColLower();
12370       const double *columnUpper = solver_->getColUpper();
12371       bool looksGood = true;
12372       for (int i = 0; i < numberColumns; i++) {
12373         if (columnUpper[i] < columnLower[i])
12374           looksGood = false;
12375       }
12376       if (!looksGood) {
12377         // not good
12378         messageHandler()->message(CBC_FPUMP2, messages())
12379           << "On closer inspection - solution discarded"
12380           << CoinMessageEol;
12381         objectiveValue = 1.0e50;
12382         for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
12383           solver_->setColLower(iColumn, saveLower[iColumn]);
12384           solver_->setColUpper(iColumn, saveUpper[iColumn]);
12385         }
12386         delete[] saveLower;
12387         delete[] saveUpper;
12388 
12389         solver_->setColSolution(saveSolution);
12390         delete[] saveSolution;
12391         solver_->setWarmStart(basis);
12392         delete basis;
12393         /*
12394 	      Restore the usual solver.
12395 	    */
12396         solver_ = saveSolver;
12397         testSolution_ = save;
12398 #ifdef COIN_HAS_CLP
12399         if (modifiedTolerances) {
12400           // Restore
12401           ClpSimplex *clp = clpContinuousSolver->getModelPtr();
12402 #ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
12403           clp->setPrimalTolerance(savePrimalTolerance);
12404 #endif
12405 #ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
12406           clp->setPerturbation(savePerturbation);
12407 #endif
12408 #ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
12409           if (saveScaling) {
12410             clp->scaling(saveScaling);
12411             clpContinuousSolver->setHintParam(OsiDoScale, true, OsiHintTry);
12412           }
12413 #endif
12414 #ifndef CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION
12415 	  // Restore
12416 	  clpContinuousSolver->setSpecialOptions(saveSpecialOptions);
12417 #endif
12418         }
12419 #endif
12420         return 1.0e50;
12421       }
12422     }
12423 #if CBC_USEFUL_PRINTING > 14
12424     {
12425       int nBad = checkAssociated(solver_, solver_->getColSolution(), 1);
12426       if (nBad)
12427         checkAssociated(solver_, solver_->getColSolution(), 3);
12428       double largestInfeasibility = 0.0;
12429       double primalTolerance;
12430       double offset;
12431       solver_->getDblParam(OsiObjOffset, offset);
12432       solver_->getDblParam(OsiPrimalTolerance, primalTolerance);
12433       const double *objective = getObjCoefficients();
12434       const double *rowLower = solver_->getRowLower();
12435       const double *rowUpper = solver_->getRowUpper();
12436       const double *columnLower = solver_->getColLower();
12437       const double *columnUpper = solver_->getColUpper();
12438       int numberRows = solver_->getNumRows();
12439       double *rowActivity = new double[numberRows];
12440       memset(rowActivity, 0, numberRows * sizeof(double));
12441       double *rowSum = new double[numberRows];
12442       memset(rowSum, 0, numberRows * sizeof(double));
12443       int *marked = new int[numberColumns];
12444       for (int i = 0; i < numberColumns; i++)
12445         marked[i] = -1;
12446       for (int i = 0; i < numberIntegers_; i++)
12447         marked[integerVariable_[i]] = -2;
12448       if ((moreSpecialOptions2_ & 4) != 0) {
12449         for (int i = 0; i < numberObjects_; i++) {
12450           CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]);
12451           if (object) {
12452             int iColumn = object->columnNumber();
12453             const int *other = object->otherVariable();
12454             marked[iColumn] = -3 - other[0];
12455             int n = object->numberOther();
12456             for (int k = 0; k < n; k++)
12457               marked[other[k]] = iColumn;
12458           }
12459         }
12460       }
12461       const double *element = solver_->getMatrixByCol()->getElements();
12462       const int *row = solver_->getMatrixByCol()->getIndices();
12463       const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts();
12464       const int *columnLength = solver_->getMatrixByCol()->getVectorLengths();
12465       const CoinPackedMatrix *rowCopy = solver_->getMatrixByRow();
12466       const int *column = rowCopy->getIndices();
12467       const int *rowLength = rowCopy->getVectorLengths();
12468       const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
12469       const double *elementByRow = rowCopy->getElements();
12470       double objValue = -offset;
12471       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
12472         double value = solution[iColumn];
12473         objValue += value * objective[iColumn];
12474         if (value > columnUpper[iColumn]) {
12475           if (value - columnUpper[iColumn] > 1.0e-8)
12476             printf("column %d has value %.12g above %.12g\n", iColumn, value, columnUpper[iColumn]);
12477           value = columnUpper[iColumn];
12478         } else if (value < columnLower[iColumn]) {
12479           if (value - columnLower[iColumn] < -1.0e-8)
12480             printf("column %d has value %.12g below %.12g\n", iColumn, value, columnLower[iColumn]);
12481           value = columnLower[iColumn];
12482         }
12483         if (value) {
12484           CoinBigIndex start = columnStart[iColumn];
12485           CoinBigIndex end = start + columnLength[iColumn];
12486           for (CoinBigIndex j = start; j < end; j++) {
12487             int iRow = row[j];
12488             rowActivity[iRow] += value * element[j];
12489             rowSum[iRow] += fabs(value * element[j]);
12490           }
12491         }
12492       }
12493       for (int i = 0; i < numberRows; i++) {
12494 #if 0 //def CLP_INVESTIGATE
12495 	    double inf;
12496 	    inf = rowLower[i] - rowActivity[i];
12497 	    if (inf > primalTolerance)
12498 	      printf("Row %d inf %g sum %g %g <= %g <= %g\n",
12499 		     i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
12500 	    inf = rowActivity[i] - rowUpper[i];
12501 	    if (inf > primalTolerance)
12502 	      printf("Row %d inf %g sum %g %g <= %g <= %g\n",
12503 		     i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
12504 #endif
12505         double infeasibility = CoinMax(rowActivity[i] - rowUpper[i],
12506           rowLower[i] - rowActivity[i]);
12507         // but allow for errors
12508         double factor = CoinMax(1.0, rowSum[i] * 1.0e-3);
12509         if (infeasibility > largestInfeasibility * factor) {
12510           largestInfeasibility = infeasibility / factor;
12511           printf("inf of %g on row %d sum %g scaled %g\n",
12512             infeasibility, i, rowSum[i], largestInfeasibility);
12513           if (infeasibility > 1.0e10) {
12514             for (CoinBigIndex j = rowStart[i];
12515                  j < rowStart[i] + rowLength[i]; j++) {
12516               printf("col %d element %g marked %d\n",
12517                 column[j], elementByRow[j], marked[column[j]]);
12518             }
12519           }
12520         }
12521       }
12522       delete[] rowActivity;
12523       delete[] rowSum;
12524       delete[] marked;
12525       if (largestInfeasibility > 10.0 * primalTolerance)
12526         printf("Largest infeasibility is %g - obj %g\n", largestInfeasibility, objValue);
12527       else
12528         printf("Feasible (%g) - obj %g\n", largestInfeasibility, objValue);
12529     }
12530 #endif
12531     // If relaxed then leave bounds on basic variables
12532     if (fixVariables == -1 && (specialOptions_ & 16) == 0) {
12533       CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(saveSolver->getWarmStart());
12534       assert(basis != NULL);
12535 #ifdef JJF_ZERO //ndef CBC_OTHER_SOLVER
12536       for (i = 0; i < numberObjects_; i++) {
12537         CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
12538         if (obj) {
12539           int iColumn = obj->columnNumber();
12540           if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::basic) {
12541             solver_->setColLower(iColumn, saveLower[iColumn]);
12542             solver_->setColUpper(iColumn, saveUpper[iColumn]);
12543           }
12544         }
12545       }
12546 #endif
12547       delete basis;
12548     }
12549     // We can switch off check
12550     if ((specialOptions_ & 4) == 0 && (moreSpecialOptions2_ & 10) != 8) {
12551       // Be on safe side - unless very few integers and large
12552       bool allSlack = (specialOptions_ & 2) == 0 && solverCharacteristics_->warmStart();
12553       if (numberIntegers_ * 4 > solver_->getNumCols() || solver_->getNumCols() < 10000)
12554         allSlack = true;
12555       if (allSlack) {
12556         /*
12557                   Remove any existing warm start information to be sure there is no
12558                   residual influence on initialSolve().
12559                 */
12560         CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart());
12561         solver_->setWarmStart(slack);
12562         delete slack;
12563       } else {
12564         if (bestSolutionBasis_.getNumStructural() == solver_->getNumCols() && bestSolutionBasis_.getNumArtificial() == solver_->getNumRows())
12565           solver_->setWarmStart(&bestSolutionBasis_);
12566       }
12567       // Give a hint to do dual
12568       bool saveTakeHint;
12569       OsiHintStrength saveStrength;
12570 #ifndef NDEBUG
12571       bool gotHint = (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength));
12572       assert(gotHint);
12573 #else
12574       (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength));
12575 #endif
12576       solver_->setHintParam(OsiDoDualInInitial, true, OsiHintTry);
12577       solver_->initialSolve();
12578 #ifdef SWITCH_VARIABLES
12579       if (solver_->isProvenOptimal()) {
12580         int nBad = checkAssociated(solver_, solver_->getColSolution(), 1);
12581         if (nBad)
12582           checkAssociated(solver_, solver_->getColSolution(), 3);
12583       }
12584 #endif
12585 #ifdef JJF_ZERO
12586       if (solver_->isProvenOptimal()) {
12587         solver_->writeMpsNative("feasible.mps", NULL, NULL, 2);
12588 #ifdef COIN_HAS_CLP
12589         OsiClpSolverInterface *clpSolver
12590           = dynamic_cast< OsiClpSolverInterface * >(solver_);
12591         if (clpSolver) {
12592           clpSolver->getModelPtr()->writeBasis("feasible.bas", true);
12593         }
12594 #endif
12595         printf("XXXXXXXXXXXX - saving feasible\n");
12596       }
12597 #endif
12598       if (!solver_->isProvenOptimal()) {
12599 #if CBC_FEASIBILITY_INVESTIGATE
12600         printf("checkSolution infeas! Retrying with primal.\n");
12601 #endif
12602         //bool saveTakeHint;
12603         //OsiHintStrength saveStrength;
12604         //bool savePrintHint;
12605         //solver_->writeMpsNative("infeas.mps", NULL, NULL, 2);
12606         //bool gotHint = (solver_->getHintParam(OsiDoReducePrint,savePrintHint,saveStrength));
12607         //gotHint = (solver_->getHintParam(OsiDoScale,saveTakeHint,saveStrength));
12608         //solver_->setHintParam(OsiDoScale,false,OsiHintTry);
12609         //solver_->setHintParam(OsiDoReducePrint,false,OsiHintTry) ;
12610         solver_->setHintParam(OsiDoDualInInitial, false, OsiHintTry);
12611         solver_->initialSolve();
12612         //solver_->setHintParam(OsiDoScale,saveTakeHint,saveStrength);
12613         //solver_->setHintParam(OsiDoReducePrint,savePrintHint,OsiHintTry) ;
12614         // go from all slack now
12615         specialOptions_ &= ~2;
12616         if (!solver_->isProvenOptimal()) {
12617           CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart());
12618           solver_->setWarmStart(slack);
12619           delete slack;
12620 #if CBC_FEASIBILITY_INVESTIGATE
12621           printf("checkSolution infeas! Retrying wihout basis and with primal.\n");
12622 #endif
12623           solver_->initialSolve();
12624           //solver_->writeMps("bad");
12625 #ifdef COIN_HAS_CLP
12626           if (!solver_->isProvenOptimal() && modifiedTolerances) {
12627             // Restore
12628             ClpSimplex *clp = clpContinuousSolver->getModelPtr();
12629 #ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
12630             clp->setPrimalTolerance(savePrimalTolerance);
12631 #endif
12632 #ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
12633             clp->setPerturbation(savePerturbation);
12634 #endif
12635 #ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
12636             if (saveScaling) {
12637               clp->scaling(saveScaling);
12638               clpContinuousSolver->setHintParam(OsiDoScale, true, OsiHintTry);
12639             }
12640 #endif
12641             solver_->resolve();
12642           }
12643 #endif
12644 #if CBC_FEASIBILITY_INVESTIGATE
12645           if (!solver_->isProvenOptimal()) {
12646             printf("checkSolution still infeas!\n");
12647           }
12648 #endif
12649         }
12650       }
12651       //assert(solver_->isProvenOptimal());
12652       solver_->setHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength);
12653       objectiveValue = solver_->isProvenOptimal() ? solver_->getObjValue() * solver_->getObjSense() : 1.0e50;
12654     }
12655     bestSolutionBasis_ = CoinWarmStartBasis();
12656 
12657     /*
12658           Check that the solution still beats the objective cutoff.
12659 
12660           If it passes, make a copy of the primal variable values and do some
12661           cleanup and checks:
12662           + Values of all variables are are within original bounds and values of
12663           all integer variables are within tolerance of integral.
12664           + There are no constraint violations.
12665           There really should be no need for the check against original bounds.
12666           Perhaps an opportunity for a sanity check?
12667         */
12668     if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8 * fabs(cutoff))
12669       cutoff = objectiveValue; // relax
12670     if ((solver_->isProvenOptimal() || (specialOptions_ & 4) != 0) && objectiveValue <= cutoff) {
12671       memcpy(solution, solver_->getColSolution(), numberColumns * sizeof(double));
12672       int iColumn;
12673 #ifndef NDEBUG
12674       double integerTolerance = getIntegerTolerance();
12675 #endif
12676 #if CBC_FEASIBILITY_INVESTIGATE
12677       const double *dj = solver_->getReducedCost();
12678       const double *colLower = saveSolver->getColLower();
12679       const double *colUpper = saveSolver->getColUpper();
12680       int nAtLbNatural = 0;
12681       int nAtUbNatural = 0;
12682       int nAtLbNaturalZero = 0;
12683       int nAtUbNaturalZero = 0;
12684       int nAtLbFixed = 0;
12685       int nAtUbFixed = 0;
12686       int nAtOther = 0;
12687       int nAtOtherNatural = 0;
12688       int nNotNeeded = 0;
12689 #endif
12690       for (iColumn = 0; iColumn < numberContinuousColumns; iColumn++) {
12691         double value = solution[iColumn];
12692         value = CoinMax(value, saveLower[iColumn]);
12693         value = CoinMin(value, saveUpper[iColumn]);
12694         if (solver_->isInteger(iColumn)) {
12695           assert(fabs(value - solution[iColumn]) <= 100.0 * integerTolerance);
12696 #if CBC_FEASIBILITY_INVESTIGATE
12697           double value2 = floor(value + 0.5);
12698           if (dj[iColumn] < -1.0e-6) {
12699             // negative dj
12700             //assert (value2==colUpper[iColumn]);
12701             if (saveUpper[iColumn] == colUpper[iColumn]) {
12702               nAtUbNatural++;
12703               if (saveLower[iColumn] != colLower[iColumn])
12704                 nNotNeeded++;
12705             } else if (saveLower[iColumn] == colUpper[iColumn]) {
12706               nAtLbFixed++;
12707             } else {
12708               nAtOther++;
12709               if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn])
12710                 nNotNeeded++;
12711             }
12712           } else if (dj[iColumn] > 1.0e-6) {
12713             // positive dj
12714             //assert (value2==colLower[iColumn]);
12715             if (saveLower[iColumn] == colLower[iColumn]) {
12716               nAtLbNatural++;
12717               if (saveUpper[iColumn] != colUpper[iColumn])
12718                 nNotNeeded++;
12719             } else if (saveUpper[iColumn] == colLower[iColumn]) {
12720               nAtUbFixed++;
12721             } else {
12722               nAtOther++;
12723               if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn])
12724                 nNotNeeded++;
12725             }
12726           } else {
12727             // zero dj
12728             if (value2 == saveUpper[iColumn]) {
12729               nAtUbNaturalZero++;
12730               if (saveLower[iColumn] != colLower[iColumn])
12731                 nNotNeeded++;
12732             } else if (value2 == saveLower[iColumn]) {
12733               nAtLbNaturalZero++;
12734             } else {
12735               nAtOtherNatural++;
12736               if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn])
12737                 nNotNeeded++;
12738             }
12739           }
12740 #endif
12741         }
12742         solution[iColumn] = value;
12743       }
12744 #if CBC_FEASIBILITY_INVESTIGATE
12745       printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d\n",
12746         nAtLbNatural,
12747         nAtUbNatural,
12748         nAtLbNaturalZero,
12749         nAtUbNaturalZero,
12750         nAtLbFixed,
12751         nAtUbFixed,
12752         nAtOther,
12753         nAtOtherNatural, nNotNeeded);
12754       //if (currentNode_)
12755       //printf(" SOL at depth %d\n",currentNode_->depth());
12756       //else
12757       //printf(" SOL at unknown depth\n");
12758 #endif
12759       if ((specialOptions_ & 16) == 0) {
12760 #ifdef JJF_ZERO
12761         // check without scaling
12762         bool saveTakeHint;
12763         OsiHintStrength saveStrength;
12764         solver_->getHintParam(OsiDoScale, saveTakeHint, saveStrength);
12765         solver_->setHintParam(OsiDoScale, false, OsiHintTry);
12766         solver_->resolve();
12767         solver_->setHintParam(OsiDoScale, saveTakeHint, saveStrength);
12768 #endif
12769         double largestInfeasibility = 0.0;
12770 #ifdef COIN_HAS_CLP
12771         if (clpContinuousSolver) {
12772           ClpSimplex *clp = clpContinuousSolver->getModelPtr();
12773           if ((modifiedTolerances & 1) != 0)
12774             clp->setPrimalTolerance(savePrimalTolerance);
12775           assert(savePrimalTolerance);
12776         }
12777 #endif
12778         double primalTolerance;
12779         solver_->getDblParam(OsiPrimalTolerance, primalTolerance);
12780         const double *rowLower = solver_->getRowLower();
12781         const double *rowUpper = solver_->getRowUpper();
12782         int numberRows = solver_->getNumRows();
12783         double *rowActivity = new double[numberRows];
12784         memset(rowActivity, 0, numberRows * sizeof(double));
12785         double *rowSum = new double[numberRows];
12786         memset(rowSum, 0, numberRows * sizeof(double));
12787         const double *element = solver_->getMatrixByCol()->getElements();
12788         const int *row = solver_->getMatrixByCol()->getIndices();
12789         const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts();
12790         const int *columnLength = solver_->getMatrixByCol()->getVectorLengths();
12791         double offset;
12792         solver_->getDblParam(OsiObjOffset, offset);
12793         double objValue = -offset;
12794         const double *objective = getObjCoefficients();
12795         for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
12796           double value = solution[iColumn];
12797           objValue += value * objective[iColumn];
12798           if (value) {
12799             CoinBigIndex start = columnStart[iColumn];
12800             CoinBigIndex end = start + columnLength[iColumn];
12801             for (CoinBigIndex j = start; j < end; j++) {
12802               int iRow = row[j];
12803               rowActivity[iRow] += value * element[j];
12804               rowSum[iRow] += fabs(value * element[j]);
12805             }
12806           }
12807         }
12808         for (i = 0; i < numberRows; i++) {
12809 #if CBC_FEASIBILITY_INVESTIGATE > 1
12810           double inf;
12811           inf = rowLower[i] - rowActivity[i];
12812           if (inf > primalTolerance)
12813             printf("Row %d inf %g sum %g %g <= %g <= %g\n",
12814               i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
12815           inf = rowActivity[i] - rowUpper[i];
12816           if (inf > primalTolerance)
12817             printf("Row %d inf %g sum %g %g <= %g <= %g\n",
12818               i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
12819 #endif
12820           double infeasibility = CoinMax(rowActivity[i] - rowUpper[i],
12821             rowLower[i] - rowActivity[i]);
12822           // but allow for errors
12823           double factor = CoinMax(1.0, rowSum[i] * 1.0e-3);
12824           if (infeasibility > largestInfeasibility * factor) {
12825             largestInfeasibility = infeasibility / factor;
12826             //printf("inf of %g on row %d sum %g scaled %g\n",
12827             //     infeasibility,i,rowSum[i],largestInfeasibility);
12828           }
12829         }
12830         delete[] rowActivity;
12831         delete[] rowSum;
12832 #if CBC_FEASIBILITY_INVESTIGATE == 0
12833         if (handler_->logLevel() > 2) {
12834 #endif
12835           if (largestInfeasibility > 10.0 * primalTolerance)
12836             printf("BLargest infeasibility is %g - obj %g (%g)\n", largestInfeasibility, objValue, objectiveValue);
12837           else
12838             printf("BFeasible (%g) - obj %g %g\n", largestInfeasibility, objValue, objectiveValue);
12839 #if CBC_FEASIBILITY_INVESTIGATE == 0
12840         }
12841 #else
12842         solver_->writeMpsNative("BFeasible.mps", NULL, NULL, 2);
12843 #endif
12844         //if (fabs(objValue-objectiveValue)>1.0e-7*fabs(objectiveValue)) {
12845         //printf("Bad obj values\n");
12846         objectiveValue = objValue;
12847         //}
12848 #if CBC_FEASIBILITY_INVESTIGATE
12849         if (largestInfeasibility > 10.0 * primalTolerance)
12850           printf("XX largest infeasibility is %g\n", largestInfeasibility);
12851 #endif
12852         if (largestInfeasibility > 200.0 * primalTolerance) {
12853           handler_->message(CBC_NOTFEAS3, messages_)
12854             << largestInfeasibility << CoinMessageEol;
12855           objectiveValue = 1.0e50;
12856         }
12857       }
12858     } else {
12859       objectiveValue = 1.0e50;
12860     }
12861     /*
12862           Regardless of what we think of the solution, we may need to restore the
12863           original bounds of the continuous solver. Unfortunately, const'ness
12864           prevents us from simply reversing the memcpy used to make these snapshots.
12865         */
12866     if (fixVariables <= 0) {
12867       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
12868         solver_->setColLower(iColumn, saveLower[iColumn]);
12869         solver_->setColUpper(iColumn, saveUpper[iColumn]);
12870       }
12871     }
12872     delete[] saveLower;
12873     delete[] saveUpper;
12874 
12875     solver_->setColSolution(saveSolution);
12876     delete[] saveSolution;
12877     solver_->setWarmStart(basis);
12878     delete basis;
12879     /*
12880           Restore the usual solver.
12881         */
12882     solver_ = saveSolver;
12883     testSolution_ = save;
12884 #ifdef COIN_HAS_CLP
12885     if (modifiedTolerances) {
12886       // Restore
12887       ClpSimplex *clp = clpContinuousSolver->getModelPtr();
12888 #ifndef CBC_LEAVE_TOLERANCE_ON_CHECK_SOLUTION
12889       clp->setPrimalTolerance(savePrimalTolerance);
12890 #endif
12891 #ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION
12892       clp->setPerturbation(savePerturbation);
12893 #endif
12894 #ifndef CBC_LEAVE_SCALING_ON_CHECK_SOLUTION
12895       if (saveScaling) {
12896         clp->scaling(saveScaling);
12897         clpContinuousSolver->setHintParam(OsiDoScale, true, OsiHintTry);
12898       }
12899 #endif
12900 #ifndef CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION
12901       clpContinuousSolver->setSpecialOptions(saveSpecialOptions);
12902 #endif
12903     }
12904 #endif
12905     return objectiveValue;
12906   } else {
12907     // Outer approximation or similar
12908     //If this is true then the solution comes from the nlp we don't need to resolve the same nlp with ipopt
12909     //solverCharacteristics_->setSolver(solver_);
12910     bool solutionComesFromNlp = solverCharacteristics_->bestObjectiveValue() < cutoff;
12911     double objectiveValue;
12912     int numberColumns = solver_->getNumCols();
12913     double *saveLower = NULL;
12914     double *saveUpper = NULL;
12915 
12916     if (!solutionComesFromNlp) { //Otherwise solution already comes from ipopt and cuts are known
12917       if (fixVariables > 0) { //Will temporarily fix all integer valued var
12918         // save original bounds
12919         saveUpper = new double[numberColumns];
12920         saveLower = new double[numberColumns];
12921         memcpy(saveUpper, solver_->getColUpper(), numberColumns * sizeof(double));
12922         memcpy(saveLower, solver_->getColLower(), numberColumns * sizeof(double));
12923         //in any case solution should be already loaded into solver_
12924         /*
12925                   Run through the objects and use feasibleRegion() to set variable bounds
12926                   so as to fix the variables specified in the objects at their value in this
12927                   solution. Since the object list contains (at least) one object for every
12928                   integer variable, this has the effect of fixing all integer variables.
12929                 */
12930         const double *save = testSolution_;
12931         testSolution_ = solution;
12932         // point to useful information
12933         OsiBranchingInformation usefulInfo = usefulInformation();
12934         for (int i = 0; i < numberObjects_; i++)
12935           object_[i]->feasibleRegion(solver_, &usefulInfo);
12936         testSolution_ = save;
12937         resolve(solver_);
12938       }
12939 
12940       /*
12941               Now step through the cut generators and see if any of them are flagged to
12942               run when a new solution is discovered. Only global cuts are useful.
12943               (The solution being evaluated may not correspond to the current location in the
12944               search tree --- discovered by heuristic, for example.)
12945             */
12946       OsiCuts theseCuts;
12947       int i;
12948       int lastNumberCuts = 0;
12949       // reset probing info
12950       //if (probingInfo_)
12951       //probingInfo_->initializeFixing();
12952       for (i = 0; i < numberCutGenerators_; i++) {
12953         if (generator_[i]->atSolution()) {
12954           generator_[i]->generateCuts(theseCuts, 1, solver_, NULL);
12955           int numberCuts = theseCuts.sizeRowCuts();
12956           for (int j = lastNumberCuts; j < numberCuts; j++) {
12957             const OsiRowCut *thisCut = theseCuts.rowCutPtr(j);
12958             if (thisCut->globallyValid()) {
12959               //           if ((specialOptions_&1)!=0)
12960               //           {
12961               //             /* As these are global cuts -
12962               //             a) Always get debugger object
12963               // b) Not fatal error to cutoff optimal (if we have just got optimal)
12964               // */
12965               //             const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways() ;
12966               //             if (debugger)
12967               //             {
12968               //               if(debugger->invalidCut(*thisCut))
12969               //                 printf("ZZZZ Global cut - cuts off optimal solution!\n");
12970               //             }
12971               //           }
12972               // add to global list
12973               OsiRowCut newCut(*thisCut);
12974               newCut.setGloballyValid(true);
12975               newCut.mutableRow().setTestForDuplicateIndex(false);
12976               globalCuts_.addCutIfNotDuplicate(newCut);
12977             } else {
12978               // obviously wrong
12979               if (handler_->logLevel() > 1)
12980                 printf("Cut generator %s set to run on new solution but NOT globally valid!!\n",
12981                   generator_[i]->cutGeneratorName());
12982             }
12983           }
12984         }
12985       }
12986       //   int numberCuts = theseCuts.sizeColCuts();
12987       //   for (i=0;i<numberCuts;i++) {
12988       //     const OsiColCut * thisCut = theseCuts.colCutPtr(i);
12989       //     if (thisCut->globallyValid()) {
12990       //       // add to global list
12991       //       globalCuts_.insert(*thisCut);
12992       //     }
12993       //   }
12994       //have to retrieve the solution and its value from the nlp
12995     }
12996     double newObjectiveValue = cutoff;
12997     if (solverCharacteristics_->solution(newObjectiveValue,
12998           const_cast< double * >(solution),
12999           numberColumns)) {
13000       objectiveValue = newObjectiveValue;
13001     } else {
13002       objectiveValue = 2e50;
13003     }
13004     if (!solutionComesFromNlp && fixVariables > 0) {
13005       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
13006         solver_->setColLower(iColumn, saveLower[iColumn]);
13007         solver_->setColUpper(iColumn, saveUpper[iColumn]);
13008       }
13009       delete[] saveLower;
13010       delete[] saveUpper;
13011       solver_->resolve();
13012     }
13013     //If the variables were fixed the cutting plane procedure may have believed that the node could be fathomed
13014     //re-establish truth.- should do no harm for non nlp
13015     if (!solutionComesFromNlp && fixVariables > 0)
13016       solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
13017     return objectiveValue;
13018   }
13019 }
13020 
13021 /*
13022   Call this routine from anywhere when a solution is found. The solution
13023   vector is assumed to contain one value for each structural variable.
13024 
13025   The first action is to run checkSolution() to confirm the objective and
13026   feasibility. If this check causes the solution to be rejected, we're done.
13027   If fixVariables = true, the variable bounds held by the continuous solver
13028   will be left fixed to the values in the solution; otherwise they are
13029   restored to the original values.
13030 
13031   If the solution is accepted, install it as the best solution.
13032 
13033   The routine also contains a hook to run any cut generators that are flagged
13034   to run when a new solution is discovered. There's a potential hazard because
13035   the cut generators see the continuous solver >after< possible restoration of
13036   original bounds (which may well invalidate the solution).
13037 */
13038 
13039 void CbcModel::setBestSolution(CBC_Message how,
13040   double &objectiveValue, const double *solutionIn,
13041   int fixVariables)
13042 
13043 {
13044 
13045   double *solution = CoinCopyOfArray(solutionIn, solver_->getNumCols());
13046 #ifdef JJF_ZERO
13047   {
13048     double saveOffset;
13049     solver_->getDblParam(OsiObjOffset, saveOffset);
13050     const double *obj = solver_->getObjCoefficients();
13051     double newTrueSolutionValue = -saveOffset;
13052     double newSumInfeas = 0.0;
13053     int numberColumns = solver_->getNumCols();
13054     for (int i = 0; i < numberColumns; i++) {
13055       if (solver_->isInteger(i)) {
13056         double value = solution[i];
13057         double nearest = floor(value + 0.5);
13058         newSumInfeas += fabs(value - nearest);
13059       }
13060       if (solution[i])
13061         printf("%d obj %g val %g - total %g true\n", i, obj[i], solution[i],
13062           newTrueSolutionValue);
13063       newTrueSolutionValue += obj[i] * solution[i];
13064     }
13065     printf("obj %g\n", newTrueSolutionValue);
13066   }
13067 #endif
13068   if (!solverCharacteristics_->solutionAddsCuts()) {
13069     // Can trust solution
13070     double cutoff = getCutoff();
13071     if (cutoff < 1.0e30)
13072       cutoff = CoinMin(cutoff, bestObjective_);
13073 
13074     /*
13075           Double check the solution to catch pretenders.
13076         */
13077     double saveObjectiveValue = objectiveValue;
13078     // save basis
13079     CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
13080     assert(basis != NULL);
13081     objectiveValue = checkSolution(cutoff, solution, fixVariables, objectiveValue);
13082     if (cutoff > 1.0e40 && objectiveValue < 1.0e10)
13083       saveObjectiveValue = objectiveValue; // take anyway
13084     if (saveObjectiveValue + 1.0e-3 + 1.0e-7 * fabs(saveObjectiveValue)
13085       < objectiveValue) {
13086 #if CBC_FEASIBILITY_INVESTIGATE
13087       printf("First try at solution had objective %.16g, rechecked as %.16g\n",
13088         saveObjectiveValue, objectiveValue);
13089 #endif
13090       // try again with basic variables with original bounds
13091       // save basis
13092       CoinWarmStartBasis *basis2 = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
13093       assert(basis2 != NULL);
13094       solver_->setWarmStart(basis);
13095       int numberColumns = solver_->getNumCols();
13096       double *solution2 = CoinCopyOfArray(solutionIn, numberColumns);
13097       double objectiveValue2 = saveObjectiveValue;
13098       objectiveValue2 = checkSolution(cutoff, solution2, -1, objectiveValue2);
13099 #if CBC_FEASIBILITY_INVESTIGATE
13100       printf("Relaxed second try had objective of %.16g\n",
13101         objectiveValue2);
13102 #endif
13103       if (objectiveValue2 + 1.0e-7 < objectiveValue) {
13104         // Now check tolerances
13105         double integerTolerance = dblParam_[CbcIntegerTolerance];
13106         double tolerance;
13107         solver_->getDblParam(OsiPrimalTolerance, tolerance);
13108         double largestAway = 0.0;
13109         int iAway = -1;
13110         double largestInfeasibility = tolerance;
13111 #if CBC_FEASIBILITY_INVESTIGATE
13112         int iInfeas = -1;
13113 #endif
13114         const double *columnLower = continuousSolver_->getColLower();
13115         const double *columnUpper = continuousSolver_->getColUpper();
13116         int i;
13117         for (i = 0; i < numberColumns; i++) {
13118           double value = solution2[i];
13119           if (value > columnUpper[i] + largestInfeasibility) {
13120 #if CBC_FEASIBILITY_INVESTIGATE
13121             iInfeas = i;
13122 #endif
13123             largestInfeasibility = value - columnUpper[i];
13124           } else if (value < columnLower[i] - largestInfeasibility) {
13125 #if CBC_FEASIBILITY_INVESTIGATE
13126             iInfeas = i;
13127 #endif
13128             largestInfeasibility = columnLower[i] - value;
13129           }
13130         }
13131         for (i = 0; i < numberObjects_; i++) {
13132           CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]);
13133           if (obj) {
13134             int iColumn = obj->columnNumber();
13135             double value = solution2[iColumn];
13136             value = fabs(floor(value + 0.5) - value);
13137             if (value > largestAway) {
13138               iAway = iColumn;
13139               largestAway = value;
13140             }
13141           }
13142         }
13143 #if CBC_FEASIBILITY_INVESTIGATE
13144         if (iInfeas >= 0)
13145           printf("Largest infeasibility of %g on column %d - tolerance %g\n",
13146             largestInfeasibility, iInfeas, tolerance);
13147 #endif
13148         if (largestAway > integerTolerance) {
13149           handler_->message(CBC_RELAXED1, messages_)
13150             << objectiveValue2
13151             << iAway
13152             << largestAway
13153             << integerTolerance
13154             << CoinMessageEol;
13155         } else {
13156           handler_->message(CBC_RELAXED2, messages_)
13157             << objectiveValue2
13158             << integerTolerance
13159             << CoinMessageEol;
13160           // take
13161           CoinCopyN(solution2, numberColumns, solution);
13162           objectiveValue = objectiveValue2;
13163         }
13164       } else if (!parentModel_) {
13165         // not good
13166         messageHandler()->message(CBC_FPUMP2, messages())
13167           << "On closer inspection - solution discarded"
13168           << CoinMessageEol;
13169       }
13170       delete[] solution2;
13171       solver_->setWarmStart(basis2);
13172       delete basis2;
13173     }
13174     delete basis;
13175     if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8 * fabs(cutoff))
13176       cutoff = objectiveValue; // relax
13177     CbcEventHandler::CbcAction action = dealWithEventHandler(CbcEventHandler::beforeSolution2,
13178       objectiveValue, solution);
13179     if (action == CbcEventHandler::killSolution) {
13180       // Pretend solution never happened
13181       objectiveValue = cutoff + 1.0e30;
13182     }
13183     if (objectiveValue > cutoff || objectiveValue > 1.0e30) {
13184       if (objectiveValue > 1.0e30)
13185         handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol;
13186       else
13187         handler_->message(CBC_NOTFEAS2, messages_)
13188           << objectiveValue << cutoff << CoinMessageEol;
13189     } else if (objectiveValue < bestObjective_) {
13190       /*
13191               We have a winner. Install it as the new incumbent.
13192               Bump the objective cutoff value and solution counts. Give the user the
13193               good news.
13194             */
13195       specialOptions_ |= 256; // mark as full cut scan should be done
13196       saveBestSolution(solution, objectiveValue);
13197       //bestObjective_ = objectiveValue;
13198       //int numberColumns = solver_->getNumCols();
13199       //if (!bestSolution_)
13200       //bestSolution_ = new double[numberColumns];
13201       //CoinCopyN(solution,numberColumns,bestSolution_);
13202 
13203       cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement];
13204       // But allow for rounding errors
13205       if (dblParam_[CbcCutoffIncrement] == 1e-5) {
13206 #if CBC_FEASIBILITY_INVESTIGATE
13207         if (saveObjectiveValue + 1.0e-7 < bestObjective_)
13208           printf("First try at solution had objective %.16g, rechecked as %.16g\n",
13209             saveObjectiveValue, bestObjective_);
13210 #endif
13211         saveObjectiveValue = CoinMax(saveObjectiveValue, bestObjective_ - 0.0000001 * fabs(bestObjective_));
13212         cutoff = CoinMin(bestObjective_, saveObjectiveValue) - 1.0e-5;
13213         if (fabs(cutoff + 1.0e-5 - floor(cutoff + 0.5)) < 1.0e-8)
13214           cutoff -= 2.0e-5;
13215       }
13216       if (!parentModel_ && (moreSpecialOptions2_ & 2) != 0) {
13217         // put back objective
13218         solver_->setObjective(continuousSolver_->getObjCoefficients());
13219         double offset;
13220         continuousSolver_->getDblParam(OsiObjOffset, offset);
13221         solver_->setDblParam(OsiObjOffset, offset);
13222         moreSpecialOptions2_ &= ~2;
13223       }
13224       // This is not correct - that way cutoff can go up if maximization
13225       //double direction = solver_->getObjSense();
13226       //setCutoff(cutoff*direction);
13227       setCutoff(cutoff);
13228       // change cutoff as constraint if wanted
13229       if (cutoffRowNumber_ >= 0) {
13230         if (solver_->getNumRows() > cutoffRowNumber_) {
13231           double offset;
13232           solver_->getDblParam(OsiObjOffset, offset);
13233           solver_->setRowUpper(cutoffRowNumber_, cutoff + offset);
13234         }
13235       }
13236 
13237       if (how == CBC_ROUNDING)
13238         numberHeuristicSolutions_++;
13239       numberSolutions_++;
13240 
13241       if (how != CBC_ROUNDING) {
13242         handler_->message(how, messages_)
13243           << bestObjective_ << numberIterations_
13244           << numberNodes_ << getCurrentSeconds()
13245           << CoinMessageEol;
13246         dealWithEventHandler(CbcEventHandler::solution,
13247           objectiveValue, solution);
13248       } else {
13249         const char *name;
13250         if (lastHeuristic_)
13251           name = lastHeuristic_->heuristicName();
13252         else
13253           name = "Reduced search";
13254         handler_->message(CBC_ROUNDING, messages_)
13255           << bestObjective_
13256           << name
13257           << numberIterations_
13258           << numberNodes_ << getCurrentSeconds()
13259           << CoinMessageEol;
13260         dealWithEventHandler(CbcEventHandler::heuristicSolution,
13261           objectiveValue, solution);
13262       }
13263       /*
13264               Now step through the cut generators and see if any of them are flagged to
13265               run when a new solution is discovered. Only global cuts are useful. (The
13266               solution being evaluated may not correspond to the current location in the
13267               search tree --- discovered by heuristic, for example.)
13268             */
13269       OsiCuts theseCuts;
13270       int i;
13271       int lastNumberCuts = 0;
13272       // reset probing info
13273       //if (probingInfo_)
13274       //probingInfo_->initializeFixing();
13275       for (i = 0; i < numberCutGenerators_; i++) {
13276         bool generate = generator_[i]->atSolution();
13277         // skip if not optimal and should be (maybe a cut generator has fixed variables)
13278         if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
13279           generate = false;
13280         if (generate) {
13281           generator_[i]->generateCuts(theseCuts, 1, solver_, NULL);
13282           int numberCuts = theseCuts.sizeRowCuts();
13283           for (int j = lastNumberCuts; j < numberCuts; j++) {
13284             const OsiRowCut *thisCut = theseCuts.rowCutPtr(j);
13285             if (thisCut->globallyValid()) {
13286               if ((specialOptions_ & 1) != 0) {
13287                 /* As these are global cuts -
13288                                    a) Always get debugger object
13289                                    b) Not fatal error to cutoff optimal (if we have just got optimal)
13290                                 */
13291                 const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways();
13292                 if (debugger) {
13293                   if (debugger->invalidCut(*thisCut))
13294                     printf("ZZZZ Global cut - cuts off optimal solution!\n");
13295                 }
13296               }
13297               // add to global list
13298               OsiRowCut newCut(*thisCut);
13299               newCut.setGloballyValid(true);
13300               newCut.mutableRow().setTestForDuplicateIndex(false);
13301               globalCuts_.addCutIfNotDuplicate(newCut);
13302               generator_[i]->incrementNumberCutsInTotal();
13303             }
13304           }
13305         }
13306       }
13307       int numberCuts = theseCuts.sizeColCuts();
13308       for (i = 0; i < numberCuts; i++) {
13309         const OsiColCut *thisCut = theseCuts.colCutPtr(i);
13310         if (thisCut->globallyValid()) {
13311           // fix
13312           makeGlobalCut(thisCut);
13313         }
13314       }
13315     }
13316   } else {
13317     // Outer approximation or similar
13318     double cutoff = getCutoff();
13319 
13320     /*
13321           Double check the solution to catch pretenders.
13322         */
13323 
13324     int numberRowBefore = solver_->getNumRows();
13325     int numberColBefore = solver_->getNumCols();
13326     double *saveColSol = NULL;
13327 
13328     CoinWarmStart *saveWs = NULL;
13329     // if(how!=CBC_SOLUTION) return;
13330     if (how == CBC_ROUNDING) //We don't want to make any change to solver_
13331     //take a snapshot of current state
13332     {
13333       //save solution
13334       saveColSol = new double[numberColBefore];
13335       CoinCopyN(solver_->getColSolution(), numberColBefore, saveColSol);
13336       //save warm start
13337       saveWs = solver_->getWarmStart();
13338     }
13339 
13340     //run check solution this will eventually generate cuts
13341     //if in strongBranching or heuristic will do only one cut generation iteration
13342     // by fixing variables.
13343     if (!fixVariables && ((how == CBC_ROUNDING) || (how == CBC_STRONGSOL)))
13344       fixVariables = 1;
13345     double *candidate = new double[numberColBefore];
13346     CoinCopyN(solution, numberColBefore, candidate);
13347     objectiveValue = checkSolution(cutoff, candidate, fixVariables, objectiveValue);
13348 
13349     //If it was an heuristic solution we have to clean up the solver
13350     if (how == CBC_ROUNDING) {
13351       //delete the cuts
13352       int currentNumberRowCuts = solver_->getNumRows() - numberRowBefore;
13353       int currentNumberColCuts = solver_->getNumCols() - numberColBefore;
13354       if (CoinMax(currentNumberColCuts, currentNumberRowCuts) > 0) {
13355         int *which = new int[CoinMax(currentNumberColCuts, currentNumberRowCuts)];
13356         if (currentNumberRowCuts) {
13357           for (int i = 0; i < currentNumberRowCuts; i++)
13358             which[i] = i + numberRowBefore;
13359 
13360           solver_->deleteRows(currentNumberRowCuts, which);
13361         }
13362         if (currentNumberColCuts) {
13363           for (int i = 0; i < currentNumberColCuts; i++)
13364             which[i] = i + numberColBefore;
13365           solver_->deleteCols(currentNumberColCuts, which);
13366         }
13367         delete[] which;
13368       }
13369       // Reset solution and warm start info
13370       solver_->setColSolution(saveColSol);
13371       solver_->setWarmStart(saveWs);
13372       delete[] saveColSol;
13373       delete saveWs;
13374     }
13375 
13376     if (objectiveValue > cutoff) {
13377       // message only for solution
13378       if (how == CBC_SOLUTION) {
13379         if (!solverCharacteristics_->solutionAddsCuts()) {
13380           if (objectiveValue > 1.0e30)
13381             handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol;
13382           else
13383             handler_->message(CBC_NOTFEAS2, messages_)
13384               << objectiveValue << cutoff << CoinMessageEol;
13385         }
13386       }
13387     } else {
13388       /*
13389               We have a winner. Install it as the new incumbent.
13390               Bump the objective cutoff value and solution counts. Give the user the
13391               good news.
13392               NB - Not all of this if from solve with cuts
13393             */
13394       saveBestSolution(candidate, objectiveValue);
13395       //bestObjective_ = objectiveValue;
13396       //int numberColumns = solver_->getNumCols();
13397       //if (!bestSolution_)
13398       //bestSolution_ = new double[numberColumns];
13399       //CoinCopyN(candidate,numberColumns,bestSolution_);
13400 
13401       // don't update if from solveWithCuts
13402       if (how != CBC_SOLUTION2) {
13403         if (how == CBC_ROUNDING)
13404           numberHeuristicSolutions_++;
13405         cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement];
13406         // This is not correct - that way cutoff can go up if maximization
13407         //double direction = solver_->getObjSense();
13408         //setCutoff(cutoff*direction);
13409         setCutoff(cutoff);
13410         // change cutoff as constraint if wanted
13411         if (cutoffRowNumber_ >= 0) {
13412           if (solver_->getNumRows() > cutoffRowNumber_) {
13413             double offset;
13414             solver_->getDblParam(OsiObjOffset, offset);
13415             solver_->setRowUpper(cutoffRowNumber_, cutoff + offset);
13416           }
13417         }
13418 
13419         numberSolutions_++;
13420 
13421         if (how != CBC_ROUNDING) {
13422           handler_->message(how, messages_)
13423             << bestObjective_ << numberIterations_
13424             << numberNodes_ << getCurrentSeconds()
13425             << CoinMessageEol;
13426         } else {
13427           assert(lastHeuristic_);
13428           const char *name = lastHeuristic_->heuristicName();
13429           handler_->message(CBC_ROUNDING, messages_)
13430             << bestObjective_
13431             << name
13432             << numberIterations_
13433             << numberNodes_ << getCurrentSeconds()
13434             << CoinMessageEol;
13435         }
13436       }
13437     }
13438     delete[] candidate;
13439   }
13440   delete[] solution;
13441   return;
13442 }
13443 // Deals with event handler and solution
13444 CbcEventHandler::CbcAction
13445 CbcModel::dealWithEventHandler(CbcEventHandler::CbcEvent event,
13446   double objValue,
13447   const double *solution)
13448 {
13449   CbcEventHandler *eventHandler = getEventHandler();
13450   if (eventHandler) {
13451     // Temporarily put in best
13452     double saveObj = bestObjective_;
13453     int numberColumns = solver_->getNumCols();
13454     double *saveSol = CoinCopyOfArray(bestSolution_, numberColumns);
13455     if (!saveSol)
13456       bestSolution_ = new double[numberColumns];
13457     bestObjective_ = objValue;
13458     memcpy(bestSolution_, solution, numberColumns * sizeof(double));
13459     CbcEventHandler::CbcAction action = eventHandler->event(event);
13460     bestObjective_ = saveObj;
13461     if (saveSol) {
13462       memcpy(bestSolution_, saveSol, numberColumns * sizeof(double));
13463       delete[] saveSol;
13464     } else {
13465       delete[] bestSolution_;
13466       bestSolution_ = NULL;
13467     }
13468     return action;
13469   } else {
13470     return CbcEventHandler::noAction;
13471   }
13472 }
13473 
13474 /* Test the current solution for feasibility.
13475 
13476    Calculate the number of standard integer infeasibilities, then scan the
13477    remaining objects to see if any of them report infeasibilities.
13478 
13479    Currently (2003.08) the only object besides SimpleInteger is Clique, hence
13480    the comments about `odd ones' infeasibilities.
13481 */
13482 bool CbcModel::feasibleSolution(int &numberIntegerInfeasibilities,
13483   int &numberObjectInfeasibilities) const
13484 {
13485   int numberUnsatisfied = 0;
13486   //double sumUnsatisfied=0.0;
13487   int j;
13488   // Point to current solution
13489   const double *save = testSolution_;
13490   // Safe as will be const inside infeasibility()
13491   testSolution_ = solver_->getColSolution();
13492   // Put current solution in safe place
13493   //memcpy(currentSolution_,solver_->getColSolution(),
13494   // solver_->getNumCols()*sizeof(double));
13495   // point to useful information
13496   OsiBranchingInformation usefulInfo = usefulInformation();
13497 #define SIMPLE_INTEGER
13498 #ifdef SIMPLE_INTEGER
13499   const double *solution = usefulInfo.solution_;
13500   const double *lower = usefulInfo.lower_;
13501   const double *upper = usefulInfo.upper_;
13502   double tolerance = usefulInfo.integerTolerance_;
13503 #endif
13504   for (j = 0; j < numberIntegers_; j++) {
13505 #ifndef SIMPLE_INTEGER
13506     const OsiObject *object = object_[j];
13507     double infeasibility = object->checkInfeasibility(&usefulInfo);
13508     if (infeasibility) {
13509       assert(infeasibility > 0);
13510       numberUnsatisfied++;
13511       //sumUnsatisfied += infeasibility;
13512     }
13513 #else
13514     int iColumn = integerVariable_[j];
13515     double value = solution[iColumn];
13516     value = CoinMax(value, lower[iColumn]);
13517     value = CoinMin(value, upper[iColumn]);
13518     double nearest = floor(value + 0.5);
13519     if (fabs(value - nearest) > tolerance) {
13520       numberUnsatisfied++;
13521     }
13522 #endif
13523   }
13524   numberIntegerInfeasibilities = numberUnsatisfied;
13525   for (; j < numberObjects_; j++) {
13526     const OsiObject *object = object_[j];
13527     double infeasibility = object->checkInfeasibility(&usefulInfo);
13528     if (infeasibility) {
13529       assert(infeasibility > 0);
13530       numberUnsatisfied++;
13531       //sumUnsatisfied += infeasibility;
13532     }
13533   }
13534   // and restore
13535   testSolution_ = save;
13536   numberObjectInfeasibilities = numberUnsatisfied - numberIntegerInfeasibilities;
13537   return (!numberUnsatisfied);
13538 }
13539 
13540 /* For all vubs see if we can tighten bounds by solving Lp's
13541    type - 0 just vubs
13542    1 all (could be very slow)
13543    -1 just vubs where variable away from bound
13544    Returns false if not feasible
13545 */
13546 bool CbcModel::tightenVubs(int type, bool allowMultipleBinary, double useCutoff)
13547 {
13548 
13549   CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow());
13550   int numberRows = solver_->getNumRows();
13551   int numberColumns = solver_->getNumCols();
13552 
13553   int iRow, iColumn;
13554 
13555   // Row copy
13556   //const double * elementByRow = matrixByRow.getElements();
13557   const int *column = matrixByRow.getIndices();
13558   const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
13559   const int *rowLength = matrixByRow.getVectorLengths();
13560 
13561   const double *colUpper = solver_->getColUpper();
13562   const double *colLower = solver_->getColLower();
13563   //const double * rowUpper = solver_->getRowUpper();
13564   //const double * rowLower = solver_->getRowLower();
13565 
13566   const double *objective = solver_->getObjCoefficients();
13567   //double direction = solver_->getObjSense();
13568   const double *colsol = solver_->getColSolution();
13569 
13570   int numberVub = 0;
13571   int *continuous = new int[numberColumns];
13572   if (type >= 0) {
13573     double *sort = new double[numberColumns];
13574     for (iRow = 0; iRow < numberRows; iRow++) {
13575       CoinBigIndex j;
13576       int numberBinary = 0;
13577       int numberUnsatisfiedBinary = 0;
13578       int numberContinuous = 0;
13579       int iCont = -1;
13580       double weight = 1.0e30;
13581       for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
13582         int iColumn = column[j];
13583         if (colUpper[iColumn] - colLower[iColumn] > 1.0e-8) {
13584           if (solver_->isFreeBinary(iColumn)) {
13585             numberBinary++;
13586             /* For sort I make naive assumption:
13587                            x - a * delta <=0 or
13588                            -x + a * delta >= 0
13589                         */
13590             if (colsol[iColumn] > colLower[iColumn] + 1.0e-6 && colsol[iColumn] < colUpper[iColumn] - 1.0e-6) {
13591               numberUnsatisfiedBinary++;
13592               weight = CoinMin(weight, fabs(objective[iColumn]));
13593             }
13594           } else {
13595             numberContinuous++;
13596             iCont = iColumn;
13597           }
13598         }
13599       }
13600       if (numberContinuous == 1 && numberBinary) {
13601         if (numberBinary == 1 || allowMultipleBinary) {
13602           // treat as vub
13603           if (!numberUnsatisfiedBinary)
13604             weight = -1.0; // at end
13605           sort[numberVub] = -weight;
13606           continuous[numberVub++] = iCont;
13607         }
13608       }
13609     }
13610     if (type > 0) {
13611       // take so many
13612       CoinSort_2(sort, sort + numberVub, continuous);
13613       numberVub = CoinMin(numberVub, type);
13614     }
13615     delete[] sort;
13616   } else {
13617     for (iColumn = 0; iColumn < numberColumns; iColumn++)
13618       continuous[iColumn] = iColumn;
13619     numberVub = numberColumns;
13620   }
13621   bool feasible = tightenVubs(numberVub, continuous, useCutoff);
13622   delete[] continuous;
13623 
13624   return feasible;
13625 }
13626 // This version is just handed a list of variables
13627 bool CbcModel::tightenVubs(int numberSolves, const int *which,
13628   double useCutoff)
13629 {
13630 
13631   int numberColumns = solver_->getNumCols();
13632 
13633   int iColumn;
13634 
13635   OsiSolverInterface *solver = solver_;
13636   double saveCutoff = getCutoff();
13637 
13638   double *objective = new double[numberColumns];
13639   memcpy(objective, solver_->getObjCoefficients(), numberColumns * sizeof(double));
13640   double direction = solver_->getObjSense();
13641 
13642   // add in objective if there is a cutoff
13643   if (useCutoff < 1.0e30) {
13644     // get new version of model
13645     solver = solver_->clone();
13646     CoinPackedVector newRow;
13647     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
13648       solver->setObjCoeff(iColumn, 0.0); // zero out in new model
13649       if (objective[iColumn])
13650         newRow.insert(iColumn, direction * objective[iColumn]);
13651     }
13652     solver->addRow(newRow, -COIN_DBL_MAX, useCutoff);
13653     // signal no objective
13654     delete[] objective;
13655     objective = NULL;
13656   }
13657   setCutoff(COIN_DBL_MAX);
13658 
13659   bool *vub = new bool[numberColumns];
13660   int iVub;
13661 
13662   // mark vub columns
13663   for (iColumn = 0; iColumn < numberColumns; iColumn++)
13664     vub[iColumn] = false;
13665   for (iVub = 0; iVub < numberSolves; iVub++)
13666     vub[which[iVub]] = true;
13667   OsiCuts cuts;
13668   // First tighten bounds anyway if CglProbing there
13669   CglProbing *generator = NULL;
13670   int iGen;
13671   // reset probing info
13672   //if (probingInfo_)
13673   //probingInfo_->initializeFixing();
13674   for (iGen = 0; iGen < numberCutGenerators_; iGen++) {
13675     generator = dynamic_cast< CglProbing * >(generator_[iGen]->generator());
13676     if (generator)
13677       break;
13678   }
13679   int numberFixed = 0;
13680   int numberTightened = 0;
13681   int numberFixedByProbing = 0;
13682   int numberTightenedByProbing = 0;
13683   int printFrequency = (numberSolves + 19) / 20; // up to 20 messages
13684   int save[4] = { 0, 0, 0, 0 };
13685   if (generator) {
13686     // set to cheaper and then restore at end
13687     save[0] = generator->getMaxPass();
13688     save[1] = generator->getMaxProbe();
13689     save[2] = generator->getMaxLook();
13690     save[3] = generator->rowCuts();
13691     generator->setMaxPass(1);
13692     generator->setMaxProbe(10);
13693     generator->setMaxLook(50);
13694     generator->setRowCuts(0);
13695 
13696     // Probing - return tight column bounds
13697     CglTreeInfo info;
13698     generator->generateCutsAndModify(*solver, cuts, &info);
13699     const double *tightLower = generator->tightLower();
13700     const double *lower = solver->getColLower();
13701     const double *tightUpper = generator->tightUpper();
13702     const double *upper = solver->getColUpper();
13703     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
13704       double newUpper = tightUpper[iColumn];
13705       double newLower = tightLower[iColumn];
13706       if (newUpper < upper[iColumn] - 1.0e-8 * (fabs(upper[iColumn]) + 1) || newLower > lower[iColumn] + 1.0e-8 * (fabs(lower[iColumn]) + 1)) {
13707         if (newUpper < newLower) {
13708           fprintf(stderr, "Problem is infeasible\n");
13709           return false;
13710         }
13711         if (newUpper == newLower) {
13712           numberFixed++;
13713           numberFixedByProbing++;
13714           solver->setColLower(iColumn, newLower);
13715           solver->setColUpper(iColumn, newUpper);
13716           COIN_DETAIL_PRINT(printf("Column %d, new bounds %g %g\n", iColumn,
13717             newLower, newUpper));
13718         } else if (vub[iColumn]) {
13719           numberTightened++;
13720           numberTightenedByProbing++;
13721           if (!solver->isInteger(iColumn)) {
13722             // relax
13723             newLower = CoinMax(lower[iColumn],
13724               newLower
13725                 - 1.0e-5 * (fabs(lower[iColumn]) + 1));
13726             newUpper = CoinMin(upper[iColumn],
13727               newUpper
13728                 + 1.0e-5 * (fabs(upper[iColumn]) + 1));
13729           }
13730           solver->setColLower(iColumn, newLower);
13731           solver->setColUpper(iColumn, newUpper);
13732         }
13733       }
13734     }
13735   }
13736   CoinWarmStart *ws = solver->getWarmStart();
13737   double *solution = new double[numberColumns];
13738   memcpy(solution, solver->getColSolution(), numberColumns * sizeof(double));
13739   for (iColumn = 0; iColumn < numberColumns; iColumn++)
13740     solver->setObjCoeff(iColumn, 0.0);
13741   //solver->messageHandler()->setLogLevel(2);
13742   for (iVub = 0; iVub < numberSolves; iVub++) {
13743     iColumn = which[iVub];
13744     int iTry;
13745     for (iTry = 0; iTry < 2; iTry++) {
13746       double saveUpper = solver->getColUpper()[iColumn];
13747       double saveLower = solver->getColLower()[iColumn];
13748       double value;
13749       if (iTry == 1) {
13750         // try all way up
13751         solver->setObjCoeff(iColumn, -1.0);
13752       } else {
13753         // try all way down
13754         solver->setObjCoeff(iColumn, 1.0);
13755       }
13756       solver->initialSolve();
13757       setPointers(continuousSolver_);
13758       value = solver->getColSolution()[iColumn];
13759       bool change = false;
13760       if (iTry == 1) {
13761         if (value < saveUpper - 1.0e-4) {
13762           if (solver->isInteger(iColumn)) {
13763             value = floor(value + 0.00001);
13764           } else {
13765             // relax a bit
13766             value = CoinMin(saveUpper, value + 1.0e-8 * (fabs(saveUpper) + 1));
13767           }
13768           if (value - saveLower < 1.0e-7)
13769             value = saveLower; // make sure exactly same
13770           solver->setColUpper(iColumn, value);
13771           saveUpper = value;
13772           change = true;
13773         }
13774       } else {
13775         if (value > saveLower + 1.0e-4) {
13776           if (solver->isInteger(iColumn)) {
13777             value = ceil(value - 0.00001);
13778           } else {
13779             // relax a bit
13780             value = CoinMax(saveLower, value - 1.0e-8 * (fabs(saveLower) + 1));
13781           }
13782           if (saveUpper - value < 1.0e-7)
13783             value = saveUpper; // make sure exactly same
13784           solver->setColLower(iColumn, value);
13785           saveLower = value;
13786           change = true;
13787         }
13788       }
13789       solver->setObjCoeff(iColumn, 0.0);
13790       if (change) {
13791         if (saveUpper == saveLower)
13792           numberFixed++;
13793         else
13794           numberTightened++;
13795         int saveFixed = numberFixed;
13796 
13797         int jColumn;
13798         if (generator) {
13799           // Probing - return tight column bounds
13800           cuts = OsiCuts();
13801           CglTreeInfo info;
13802           generator->generateCutsAndModify(*solver, cuts, &info);
13803           const double *tightLower = generator->tightLower();
13804           const double *lower = solver->getColLower();
13805           const double *tightUpper = generator->tightUpper();
13806           const double *upper = solver->getColUpper();
13807           for (jColumn = 0; jColumn < numberColumns; jColumn++) {
13808             double newUpper = tightUpper[jColumn];
13809             double newLower = tightLower[jColumn];
13810             if (newUpper < upper[jColumn] - 1.0e-8 * (fabs(upper[jColumn]) + 1) || newLower > lower[jColumn] + 1.0e-8 * (fabs(lower[jColumn]) + 1)) {
13811               if (newUpper < newLower) {
13812                 fprintf(stderr, "Problem is infeasible\n");
13813                 delete[] solution;
13814                 return false;
13815               }
13816               if (newUpper == newLower) {
13817                 numberFixed++;
13818                 numberFixedByProbing++;
13819                 solver->setColLower(jColumn, newLower);
13820                 solver->setColUpper(jColumn, newUpper);
13821               } else if (vub[jColumn]) {
13822                 numberTightened++;
13823                 numberTightenedByProbing++;
13824                 if (!solver->isInteger(jColumn)) {
13825                   // relax
13826                   newLower = CoinMax(lower[jColumn],
13827                     newLower
13828                       - 1.0e-8 * (fabs(lower[jColumn]) + 1));
13829                   newUpper = CoinMin(upper[jColumn],
13830                     newUpper
13831                       + 1.0e-8 * (fabs(upper[jColumn]) + 1));
13832                 }
13833                 solver->setColLower(jColumn, newLower);
13834                 solver->setColUpper(jColumn, newUpper);
13835               }
13836             }
13837           }
13838         }
13839         if (numberFixed > saveFixed) {
13840           // original solution may not be feasible
13841           // go back to true costs to solve if exists
13842           if (objective) {
13843             for (jColumn = 0; jColumn < numberColumns; jColumn++)
13844               solver->setObjCoeff(jColumn, objective[jColumn]);
13845           }
13846           solver->setColSolution(solution);
13847           solver->setWarmStart(ws);
13848           solver->resolve();
13849           if (!solver->isProvenOptimal()) {
13850             fprintf(stderr, "Problem is infeasible\n");
13851             if (vub)
13852                 delete[] vub;
13853             return false;
13854           }
13855           delete ws;
13856           ws = solver->getWarmStart();
13857           memcpy(solution, solver->getColSolution(),
13858             numberColumns * sizeof(double));
13859           for (jColumn = 0; jColumn < numberColumns; jColumn++)
13860             solver->setObjCoeff(jColumn, 0.0);
13861         }
13862       }
13863       solver->setColSolution(solution);
13864       solver->setWarmStart(ws);
13865     }
13866     if (iVub % printFrequency == 0)
13867       handler_->message(CBC_VUB_PASS, messages_)
13868         << iVub + 1 << numberFixed << numberTightened
13869         << CoinMessageEol;
13870   }
13871   handler_->message(CBC_VUB_END, messages_)
13872     << numberFixed << numberTightened
13873     << CoinMessageEol;
13874   delete ws;
13875   delete[] solution;
13876   // go back to true costs to solve if exists
13877   if (objective) {
13878     for (iColumn = 0; iColumn < numberColumns; iColumn++)
13879       solver_->setObjCoeff(iColumn, objective[iColumn]);
13880     delete[] objective;
13881   }
13882   delete[] vub;
13883   if (generator) {
13884     /*printf("Probing fixed %d and tightened %d\n",
13885            numberFixedByProbing,
13886            numberTightenedByProbing);*/
13887     if (generator_[iGen]->howOften() == -1 && (numberFixedByProbing + numberTightenedByProbing) * 5 > (numberFixed + numberTightened))
13888       generator_[iGen]->setHowOften(1000000 + 1);
13889     generator->setMaxPass(save[0]);
13890     generator->setMaxProbe(save[1]);
13891     generator->setMaxLook(save[2]);
13892     generator->setRowCuts(save[3]);
13893   }
13894 
13895   if (solver != solver_) {
13896     // move bounds across
13897     const double *lower = solver->getColLower();
13898     const double *upper = solver->getColUpper();
13899     const double *lowerOrig = solver_->getColLower();
13900     const double *upperOrig = solver_->getColUpper();
13901     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
13902       solver_->setColLower(iColumn, CoinMax(lower[iColumn], lowerOrig[iColumn]));
13903       solver_->setColUpper(iColumn, CoinMin(upper[iColumn], upperOrig[iColumn]));
13904     }
13905     delete solver;
13906   }
13907   setCutoff(saveCutoff);
13908   return true;
13909 }
13910 // Pass in Message handler (not deleted at end)
13911 void CbcModel::passInMessageHandler(CoinMessageHandler *handler)
13912 {
13913   if (defaultHandler_) {
13914     delete handler_;
13915     handler_ = NULL;
13916   }
13917   defaultHandler_ = false;
13918   handler_ = handler;
13919   if (solver_)
13920     solver_->passInMessageHandler(handler);
13921   if (continuousSolver_)
13922     continuousSolver_->passInMessageHandler(handler);
13923   if (referenceSolver_)
13924     referenceSolver_->passInMessageHandler(handler);
13925 }
13926 void CbcModel::passInTreeHandler(CbcTree &tree)
13927 {
13928   delete tree_;
13929   tree_ = tree.clone();
13930 }
13931 // Make sure region there
13932 void CbcModel::reserveCurrentSolution(const double *solution)
13933 {
13934   int numberColumns = getNumCols();
13935   if (!currentSolution_)
13936     currentSolution_ = new double[numberColumns];
13937   testSolution_ = currentSolution_;
13938   if (solution)
13939     memcpy(currentSolution_, solution, numberColumns * sizeof(double));
13940 }
13941 /* For passing in an CbcModel to do a sub Tree (with derived tree handlers).
13942    Passed in model must exist for duration of branch and bound
13943 */
13944 void CbcModel::passInSubTreeModel(CbcModel &model)
13945 {
13946   subTreeModel_ = &model;
13947 }
13948 // For retrieving a copy of subtree model with given OsiSolver or NULL
13949 CbcModel *
13950 CbcModel::subTreeModel(OsiSolverInterface *solver) const
13951 {
13952   const CbcModel *subModel = subTreeModel_;
13953   if (!subModel)
13954     subModel = this;
13955   // Get new copy
13956   CbcModel *newModel = new CbcModel(*subModel);
13957   if (solver)
13958     newModel->assignSolver(solver);
13959   return newModel;
13960 }
13961 //#############################################################################
13962 // Set/Get Application Data
13963 // This is a pointer that the application can store into and retrieve
13964 // from the solverInterface.
13965 // This field is the application to optionally define and use.
13966 //#############################################################################
13967 
13968 void CbcModel::setApplicationData(void *appData)
13969 {
13970   appData_ = appData;
13971 }
13972 //-----------------------------------------------------------------------------
13973 void *CbcModel::getApplicationData() const
13974 {
13975   return appData_;
13976 }
13977 // Set a pointer to a row cut which will be added instead of normal branching.
13978 void CbcModel::setNextRowCut(const OsiRowCut &cut)
13979 {
13980   nextRowCut_ = new OsiRowCut(cut);
13981   nextRowCut_->setEffectiveness(COIN_DBL_MAX); // mark so will always stay
13982 }
13983 // Just update objectiveValue
13984 void CbcModel::setBestObjectiveValue(double objectiveValue)
13985 {
13986   bestObjective_ = objectiveValue;
13987 }
13988 double
13989 CbcModel::getBestPossibleObjValue() const
13990 {
13991   return CoinMin(bestPossibleObjective_, bestObjective_) * solver_->getObjSense();
13992 }
13993 // Make given rows (L or G) into global cuts and remove from lp
13994 void CbcModel::makeGlobalCuts(int number, const int *which)
13995 {
13996   const double *rowLower = solver_->getRowLower();
13997   const double *rowUpper = solver_->getRowUpper();
13998 
13999   int numberRows = solver_->getNumRows();
14000 
14001   // Row copy
14002   const double *elementByRow = solver_->getMatrixByRow()->getElements();
14003   const int *column = solver_->getMatrixByRow()->getIndices();
14004   const CoinBigIndex *rowStart = solver_->getMatrixByRow()->getVectorStarts();
14005   const int *rowLength = solver_->getMatrixByRow()->getVectorLengths();
14006 
14007   // Not all rows may be good so we need new array
14008   int *whichDelete = new int[numberRows];
14009   int nDelete = 0;
14010   for (int i = 0; i < number; i++) {
14011     int iRow = which[i];
14012     if (iRow >= 0 && iRow < numberRows) {
14013       if (rowLower[iRow] < -1.0e20 || rowUpper[iRow] > 1.0e20) {
14014         whichDelete[nDelete++] = iRow;
14015         OsiRowCut thisCut;
14016         thisCut.setLb(rowLower[iRow]);
14017         thisCut.setUb(rowUpper[iRow]);
14018         CoinBigIndex start = rowStart[iRow];
14019         thisCut.setRow(rowLength[iRow], column + start, elementByRow + start, false);
14020         thisCut.setGloballyValid(true);
14021         globalCuts_.addCutIfNotDuplicate(thisCut);
14022       }
14023     }
14024   }
14025   if (nDelete)
14026     solver_->deleteRows(nDelete, whichDelete);
14027   delete[] whichDelete;
14028 }
14029 // Make given cut into a global cut
14030 int CbcModel::makeGlobalCut(const OsiRowCut *cut)
14031 {
14032   if (cut->row().getNumElements() > 1 - 1) {
14033     OsiRowCut newCut(*cut);
14034     newCut.setGloballyValidAsInteger(2);
14035     newCut.mutableRow().setTestForDuplicateIndex(false);
14036     return globalCuts_.addCutIfNotDuplicate(newCut, 1);
14037   } else {
14038     assert(cut->row().getNumElements() == 1);
14039     int iColumn = cut->row().getIndices()[0];
14040     double value = cut->row().getElements()[0];
14041     double lb = cut->lb();
14042     double ub = cut->ub();
14043     if (value > 0) {
14044       if (lb > -COIN_DBL_MAX)
14045         lb /= value;
14046       if (ub < COIN_DBL_MAX)
14047         ub /= value;
14048     } else {
14049       double saveUb = ub;
14050       if (lb > -COIN_DBL_MAX)
14051         ub = lb / value;
14052       else
14053         ub = COIN_DBL_MAX;
14054       if (saveUb < COIN_DBL_MAX)
14055         lb = saveUb / value;
14056       else
14057         lb = -COIN_DBL_MAX;
14058     }
14059 #if PRINT_CONFLICT == 0
14060     if (handler_->logLevel() > 1) {
14061 #endif
14062       printf("Conflict cut at depth %d (%d elements)\n",
14063         currentDepth_, cut->row().getNumElements());
14064       cut->print();
14065 #if PRINT_CONFLICT == 0
14066     }
14067 #endif
14068     const double *lower;
14069     const double *upper;
14070     if (topOfTree_) {
14071       lower = topOfTree_->lower();
14072       upper = topOfTree_->upper();
14073       lb = CoinMax(lb, lower[iColumn]);
14074       topOfTree_->setColLower(iColumn, lb);
14075       ub = CoinMin(ub, upper[iColumn]);
14076       topOfTree_->setColUpper(iColumn, ub);
14077     } else {
14078       lower = solver_->getColLower();
14079       upper = solver_->getColUpper();
14080       lb = CoinMax(lb, lower[iColumn]);
14081       solver_->setColLower(iColumn, lb);
14082       ub = CoinMin(ub, upper[iColumn]);
14083       solver_->setColUpper(iColumn, ub);
14084     }
14085     return 1;
14086   }
14087 }
14088 // Make given cut into a global cut
14089 int CbcModel::makeGlobalCut(const OsiRowCut &cut)
14090 {
14091   OsiRowCut newCut(cut);
14092   newCut.setGloballyValid(true);
14093   newCut.mutableRow().setTestForDuplicateIndex(false);
14094   return globalCuts_.addCutIfNotDuplicate(newCut);
14095 }
14096 // Make given column cut into a global cut
14097 void CbcModel::makeGlobalCut(const OsiColCut *cut)
14098 {
14099   const double *lower;
14100   const double *upper;
14101   if (topOfTree_) {
14102     lower = topOfTree_->lower();
14103     upper = topOfTree_->upper();
14104   } else {
14105     lower = solver_->getColLower();
14106     upper = solver_->getColUpper();
14107   }
14108   int nLower = cut->lbs().getNumElements();
14109   const int *indexLower = cut->lbs().getIndices();
14110   const double *boundLower = cut->lbs().getElements();
14111   for (int i = 0; i < nLower; i++) {
14112     int iColumn = indexLower[i];
14113     double newValue = CoinMax(lower[iColumn], boundLower[iColumn]);
14114     if (topOfTree_)
14115       topOfTree_->setColLower(iColumn, newValue);
14116     else
14117       solver_->setColLower(iColumn, newValue);
14118   }
14119   int nUpper = cut->ubs().getNumElements();
14120   const int *indexUpper = cut->ubs().getIndices();
14121   const double *boundUpper = cut->ubs().getElements();
14122   for (int i = 0; i < nUpper; i++) {
14123     int iColumn = indexUpper[i];
14124     double newValue = CoinMin(upper[iColumn], boundUpper[iColumn]);
14125     if (topOfTree_)
14126       topOfTree_->setColUpper(iColumn, newValue);
14127     else
14128       solver_->setColUpper(iColumn, newValue);
14129   }
14130 }
14131 // Make given column cut into a global cut
14132 void CbcModel::makeGlobalCut(const OsiColCut &cut)
14133 {
14134   const double *lower;
14135   const double *upper;
14136   if (topOfTree_) {
14137     lower = topOfTree_->lower();
14138     upper = topOfTree_->upper();
14139   } else {
14140     lower = solver_->getColLower();
14141     upper = solver_->getColUpper();
14142   }
14143   int nLower = cut.lbs().getNumElements();
14144   const int *indexLower = cut.lbs().getIndices();
14145   const double *boundLower = cut.lbs().getElements();
14146   for (int i = 0; i < nLower; i++) {
14147     int iColumn = indexLower[i];
14148     double newValue = CoinMax(lower[iColumn], boundLower[iColumn]);
14149     if (topOfTree_)
14150       topOfTree_->setColLower(iColumn, newValue);
14151     else
14152       solver_->setColLower(iColumn, newValue);
14153   }
14154   int nUpper = cut.ubs().getNumElements();
14155   const int *indexUpper = cut.ubs().getIndices();
14156   const double *boundUpper = cut.ubs().getElements();
14157   for (int i = 0; i < nUpper; i++) {
14158     int iColumn = indexUpper[i];
14159     double newValue = CoinMin(upper[iColumn], boundUpper[iColumn]);
14160     if (topOfTree_)
14161       topOfTree_->setColUpper(iColumn, newValue);
14162     else
14163       solver_->setColUpper(iColumn, newValue);
14164   }
14165 }
14166 // Make partial cut into a global cut and save
14167 void CbcModel::makePartialCut(const OsiRowCut *partialCut,
14168   const OsiSolverInterface *solver)
14169 {
14170   // get greedy cut
14171   double bSum = partialCut->lb();
14172   assert(bSum < 0.0);
14173   if (!solver)
14174     solver = solver_;
14175   int nConflict = partialCut->row().getNumElements();
14176   const int *column = partialCut->row().getIndices();
14177   const double *element = partialCut->row().getElements();
14178   double *originalLower = topOfTree_->mutableLower();
14179   const double *columnLower = solver->getColLower();
14180   double *originalUpper = topOfTree_->mutableUpper();
14181   const double *columnUpper = solver->getColUpper();
14182   int nC = nConflict;
14183   while (nConflict) {
14184     int iColumn = column[nConflict - 1];
14185     double farkasValue = element[nConflict - 1];
14186     double change;
14187     if (farkasValue > 0.0) {
14188       change = farkasValue * (originalUpper[iColumn] - columnUpper[iColumn]);
14189     } else {
14190       change = farkasValue * (originalLower[iColumn] - columnLower[iColumn]);
14191     }
14192     if (bSum + change > -1.0e-4)
14193       break;
14194     nConflict--;
14195     bSum += change;
14196   }
14197   OsiRowCut newCut;
14198   newCut.setUb(COIN_DBL_MAX);
14199   double lo = 1.0;
14200   double *values = new double[nConflict];
14201   for (int i = 0; i < nConflict; i++) {
14202     int iColumn = column[i];
14203     if (originalLower[iColumn] == columnLower[iColumn]) {
14204       // must be at least one higher
14205       values[i] = 1.0;
14206       lo += originalLower[iColumn];
14207     } else {
14208       // must be at least one lower
14209       values[i] = -1.0;
14210       lo -= originalUpper[iColumn];
14211     }
14212   }
14213   newCut.setLb(lo);
14214   newCut.setRow(nConflict, column, values);
14215   printf("CUTa has %d (started at %d) - final bSum %g - depth %d\n", nConflict, nC, bSum, currentDepth_);
14216   if (nConflict > 1) {
14217     if ((specialOptions_ & 1) != 0) {
14218       const OsiRowCutDebugger *debugger = continuousSolver_->getRowCutDebugger();
14219       if (debugger) {
14220         if (debugger->invalidCut(newCut)) {
14221           continuousSolver_->applyRowCuts(1, &newCut);
14222           continuousSolver_->writeMps("bad");
14223         }
14224         CoinAssert(!debugger->invalidCut(newCut));
14225       }
14226     }
14227     newCut.setGloballyValidAsInteger(2);
14228     newCut.mutableRow().setTestForDuplicateIndex(false);
14229     globalCuts_.addCutIfNotDuplicate(newCut);
14230   } else {
14231     // change bounds
14232     int iColumn = column[0];
14233     if (values[0] < 0.0) {
14234       // change upper bound
14235       double newUpper = -lo;
14236       assert(newUpper < originalUpper[iColumn]);
14237       printf("Changing upper bound on %d from %g to %g\n",
14238         iColumn, originalUpper[iColumn], newUpper);
14239       originalUpper[iColumn] = newUpper;
14240     } else {
14241       // change lower bound
14242       double newLower = lo;
14243       assert(newLower > originalLower[iColumn]);
14244       printf("Changing lower bound on %d from %g to %g\n",
14245         iColumn, originalLower[iColumn], newLower);
14246       originalLower[iColumn] = newLower;
14247     }
14248   }
14249   // add to partial cuts
14250   if (globalConflictCuts_) {
14251     globalConflictCuts_->addCutIfNotDuplicateWhenGreedy(*partialCut, 2);
14252   }
14253   delete[] values;
14254 }
14255 // Make partial cuts into global cuts
14256 void CbcModel::makeGlobalCuts()
14257 {
14258 }
14259 void CbcModel::setNodeComparison(CbcCompareBase *compare)
14260 {
14261   delete nodeCompare_;
14262   nodeCompare_ = compare->clone();
14263 }
14264 void CbcModel::setNodeComparison(CbcCompareBase &compare)
14265 {
14266   delete nodeCompare_;
14267   nodeCompare_ = compare.clone();
14268 }
14269 void CbcModel::setProblemFeasibility(CbcFeasibilityBase *feasibility)
14270 {
14271   delete problemFeasibility_;
14272   problemFeasibility_ = feasibility->clone();
14273 }
14274 void CbcModel::setProblemFeasibility(CbcFeasibilityBase &feasibility)
14275 {
14276   delete problemFeasibility_;
14277   problemFeasibility_ = feasibility.clone();
14278 }
14279 // Set the strategy. Clones
14280 void CbcModel::setStrategy(CbcStrategy &strategy)
14281 {
14282   delete strategy_;
14283   strategy_ = strategy.clone();
14284 }
14285 // Increases usedInSolution for nonzeros
14286 void CbcModel::incrementUsed(const double *solution)
14287 {
14288   if (usedInSolution_) {
14289     // might as well mark all including continuous
14290     int numberColumns = solver_->getNumCols();
14291     for (int i = 0; i < numberColumns; i++) {
14292       if (solution[i])
14293         usedInSolution_[i]++;
14294     }
14295   }
14296 }
14297 // Are there numerical difficulties (for initialSolve) ?
14298 bool CbcModel::isInitialSolveAbandoned() const
14299 {
14300   if (status_ != -1) {
14301     return false;
14302   } else {
14303     return solver_->isAbandoned();
14304   }
14305 }
14306 // Is optimality proven (for initialSolve) ?
14307 bool CbcModel::isInitialSolveProvenOptimal() const
14308 {
14309   if (status_ != -1) {
14310     return fabs(originalContinuousObjective_) < 1.0e50;
14311   } else {
14312     return solver_->isProvenOptimal();
14313   }
14314 }
14315 // Is primal infeasiblity proven (for initialSolve) ?
14316 bool CbcModel::isInitialSolveProvenPrimalInfeasible() const
14317 {
14318   if (status_ != -1) {
14319     if (status_ == 0 && secondaryStatus_ == 7)
14320       return false;
14321     else
14322       return originalContinuousObjective_ >= 1.0e50;
14323   } else {
14324     return solver_->isProvenPrimalInfeasible();
14325   }
14326 }
14327 // Is dual infeasiblity proven (for initialSolve) ?
14328 bool CbcModel::isInitialSolveProvenDualInfeasible() const
14329 {
14330   if (status_ != -1) {
14331     if (status_ == 0 && secondaryStatus_ == 7)
14332       return true;
14333     else
14334       return false;
14335   } else {
14336     return solver_->isProvenDualInfeasible();
14337   }
14338 }
14339 // Set pointers for speed
14340 void CbcModel::setPointers(const OsiSolverInterface *solver)
14341 {
14342   /// Pointer to array[getNumCols()] (for speed) of column lower bounds
14343   cbcColLower_ = solver_->getColLower();
14344   /// Pointer to array[getNumCols()] (for speed) of column upper bounds
14345   cbcColUpper_ = solver_->getColUpper();
14346   /// Pointer to array[getNumRows()] (for speed) of row lower bounds
14347   cbcRowLower_ = solver_->getRowLower();
14348   /// Pointer to array[getNumRows()] (for speed) of row upper bounds
14349   cbcRowUpper_ = solver_->getRowUpper();
14350   /// Pointer to array[getNumCols()] (for speed) of primal solution vector
14351   cbcColSolution_ = solver_->getColSolution();
14352   /// Pointer to array[getNumRows()] (for speed) of dual prices
14353   cbcRowPrice_ = solver_->getRowPrice();
14354   /// Get a pointer to array[getNumCols()] (for speed) of reduced costs
14355   if (solverCharacteristics_ && solverCharacteristics_->reducedCostsAccurate())
14356     cbcReducedCost_ = solver_->getReducedCost();
14357   else
14358     cbcReducedCost_ = NULL;
14359   /// Pointer to array[getNumRows()] (for speed) of row activity levels.
14360   cbcRowActivity_ = solver_->getRowActivity();
14361   dblParam_[CbcCurrentObjectiveValue] = solver->getObjValue();
14362   dblParam_[CbcCurrentMinimizationObjectiveValue] = dblParam_[CbcCurrentObjectiveValue] * dblParam_[CbcOptimizationDirection];
14363 }
14364 
14365 /*
14366   Delete any existing handler and create a clone of the one supplied.
14367 */
14368 void CbcModel::passInEventHandler(const CbcEventHandler *eventHandler)
14369 {
14370   delete eventHandler_;
14371   eventHandler_ = NULL;
14372   if (eventHandler) {
14373     eventHandler_ = eventHandler->clone();
14374     eventHandler_->setModel(this);
14375   }
14376 }
14377 
14378 /*
14379   CbcEventHandler* CbcModel::eventHandler is inlined in CbcModel.hpp.
14380 */
14381 
14382 // Encapsulates solver resolve
14383 int CbcModel::resolve(OsiSolverInterface *solver)
14384 {
14385   numberSolves_++;
14386 #ifdef COIN_HAS_CLP
14387   OsiClpSolverInterface *clpSolver
14388     = dynamic_cast< OsiClpSolverInterface * >(solver);
14389 #endif
14390 #ifdef CLIQUE_ANALYSIS
14391   if (probingInfo_ && currentDepth_ > 0) {
14392     int nFix = probingInfo_->fixColumns(*solver);
14393 #ifdef SWITCH_VARIABLES
14394     if (nFix > 0)
14395       fixAssociated(solver_, 0);
14396 #endif
14397     if (nFix < 0) {
14398 #ifdef COIN_HAS_CLP
14399       if (clpSolver)
14400         clpSolver->getModelPtr()->setProblemStatus(1);
14401 #endif
14402       return 0;
14403     }
14404   }
14405 #endif
14406 #ifdef COIN_HAS_CLP
14407   if (clpSolver) {
14408     /*bool takeHint;
14409         OsiHintStrength strength;
14410         bool gotHint = (clpSolver->getHintParam(OsiDoDualInResolve,takeHint,strength));
14411         assert (gotHint);
14412         int algorithm=-1;
14413         if (strength!=OsiHintIgnore)
14414           algorithm = takeHint ? -1 : 1;
14415           assert (algorithm==-1);*/
14416     //clpSolver->setHintParam(OsiDoDualInResolve,true,OsiHintTry);
14417     ClpSimplex *clpSimplex = clpSolver->getModelPtr();
14418     int save = clpSimplex->specialOptions();
14419     if ((moreSpecialOptions_ & 8388608) == 0)
14420       clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound)
14421     else
14422       clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray)
14423     int save2 = clpSolver->specialOptions();
14424     if (false && (save2 & 2048) == 0) {
14425       // see if worthwhile crunching
14426       int nFixed = 0;
14427       const double *columnLower = clpSimplex->columnLower();
14428       const double *columnUpper = clpSimplex->columnUpper();
14429       for (int i = 0; i < numberIntegers_; i++) {
14430         int iColumn = integerVariable_[i];
14431         if (columnLower[iColumn] == columnUpper[iColumn])
14432           nFixed++;
14433       }
14434       if (nFixed * 20 < clpSimplex->numberColumns()) {
14435         double d = nFixed;
14436         printf("%d fixed out of %d - ratio %g\n",
14437           nFixed,
14438           clpSimplex->numberColumns(),
14439           d / clpSimplex->numberColumns());
14440         clpSolver->setSpecialOptions(save2 | 2048);
14441       }
14442     }
14443 #ifdef CHECK_KNOWN_SOLUTION
14444     bool onOptimalPath = false;
14445     if ((specialOptions_ & 1) != 0) {
14446       const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
14447       if (debugger) {
14448         onOptimalPath = true;
14449         printf("On optimal path before resolve\n");
14450       }
14451     }
14452 #endif
14453     clpSolver->resolve();
14454 #ifdef CHECK_RAY
14455     static int nSolves = 0;
14456     static int nInfSolves = 0;
14457     static int nRays = 0;
14458     nSolves++;
14459     if (!parentModel_ && clpSolver->getModelPtr()->problemStatus() == 1
14460       && (clpSolver->getModelPtr()->specialOptions() & 32) != 0) {
14461       nInfSolves++;
14462       if (clpSolver->getModelPtr()->infeasibilityRay())
14463         nRays++;
14464     }
14465     if ((nSolves % 1000) == 0)
14466       printf("ZZ %d solves, %d infeasible %d rays\n",
14467         nSolves, nInfSolves, nRays);
14468 #endif
14469 #ifdef CHECK_KNOWN_SOLUTION
14470     if ((specialOptions_ & 1) != 0 && onOptimalPath) {
14471       const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
14472       if (debugger) {
14473         printf("On optimal path after resolve\n");
14474       } else {
14475         solver_->writeMpsNative("badSolve.mps", NULL, NULL, 2);
14476         printf("NOT on optimal path after resolve\n");
14477       }
14478     }
14479 #endif
14480     if (!numberNodes_) {
14481 #if 0
14482 	  // make sure really feasible when not scaled
14483 	  if (clpSimplex->secondaryStatus()==2) {
14484 	    messageHandler()->message(CBC_FPUMP1, messages())
14485 	      << "Continuous solution cleaned for scaling"
14486 	      << CoinMessageEol ;
14487 	    // overkill but stop odd things happeneing
14488 	    bool takeHint1,takeHint2;
14489 	    OsiHintStrength strength;
14490 	    clpSolver->getHintParam(OsiDoScale,takeHint1,strength);
14491 	    clpSolver->getHintParam(OsiDoPresolveInInitial,takeHint2,strength);
14492 	    //assert (takeHint);
14493 	    clpSolver->setHintParam(OsiDoScale,false,OsiHintTry);
14494 	    clpSolver->setHintParam(OsiDoPresolveInInitial,false,OsiHintTry);
14495 	    int saveFlag=clpSimplex->scalingFlag();
14496 	    clpSimplex->scaling(0);
14497 	    clpSolver->initialSolve();
14498 	    clpSolver->setHintParam(OsiDoScale,takeHint1,OsiHintTry);
14499 	    clpSolver->setHintParam(OsiDoPresolveInInitial,takeHint2,OsiHintTry);
14500 	    clpSimplex->scaling(saveFlag);
14501 	  }
14502 #endif
14503       double error = CoinMax(clpSimplex->largestDualError(),
14504         clpSimplex->largestPrimalError());
14505       if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) {
14506 #if CBC_USEFUL_PRINTING > 1
14507         printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n",
14508           clpSolver->isProvenOptimal() ? "optimal" : "!infeasible",
14509           clpSimplex->largestDualError(),
14510           clpSimplex->largestPrimalError());
14511 #endif
14512         if (!clpSolver->isProvenOptimal()) {
14513           // check if proven infeasible i.e. bad bounds
14514           int numberColumns = clpSolver->getNumCols();
14515           const double *columnLower = clpSolver->getColLower();
14516           const double *columnUpper = clpSolver->getColUpper();
14517           bool provenInfeasible = false;
14518           for (int i = 0; i < numberColumns; i++) {
14519             if (columnLower[i] > columnUpper[i]) {
14520               provenInfeasible = true;
14521             }
14522           }
14523           if (!provenInfeasible) {
14524             clpSolver->setSpecialOptions(save2 | 2048);
14525             clpSimplex->allSlackBasis(true);
14526             clpSolver->resolve();
14527             if (!clpSolver->isProvenOptimal()) {
14528               bool takeHint;
14529               OsiHintStrength strength;
14530               clpSolver->getHintParam(OsiDoDualInResolve, takeHint, strength);
14531               clpSolver->setHintParam(OsiDoDualInResolve, false, OsiHintDo);
14532               clpSolver->resolve();
14533               clpSolver->setHintParam(OsiDoDualInResolve, takeHint, strength);
14534             }
14535           }
14536         }
14537         // make cuts safer
14538         for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
14539           CglCutGenerator *generator = generator_[iCutGenerator]->generator();
14540           CglGomory *cgl1 = dynamic_cast< CglGomory * >(generator);
14541           if (cgl1) {
14542             cgl1->setLimitAtRoot(cgl1->getLimit());
14543           }
14544           CglTwomir *cgl2 = dynamic_cast< CglTwomir * >(generator);
14545           if (cgl2) {
14546             generator_[iCutGenerator]->setHowOften(-100);
14547           }
14548         }
14549       }
14550     }
14551     clpSolver->setSpecialOptions(save2);
14552 #if CBC_USEFUL_PRINTING > 1
14553     if (clpSimplex->numberIterations() > 1000)
14554       printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations());
14555 #endif
14556     clpSimplex->setSpecialOptions(save);
14557     if (clpSimplex->status() == 4)
14558       clpSimplex->setProblemStatus(1);
14559   } else {
14560     solver->resolve();
14561   }
14562 #else
14563   solver->resolve();
14564 #endif
14565 #ifdef SWITCH_VARIABLES
14566   if (solver_->isProvenOptimal()) {
14567     int nBad = checkAssociated(solver_, solver_->getColSolution(), 0);
14568     if (nBad)
14569       checkAssociated(solver_, solver_->getColSolution(), 1);
14570   }
14571 #endif
14572   return solver->isProvenOptimal() ? 1 : 0;
14573 }
14574 #ifdef CLP_RESOLVE
14575 // Special purpose resolve
14576 int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type)
14577 {
14578   numberSolves_++;
14579   ClpSimplex *clpSimplex = clpSolver->getModelPtr();
14580   int save = clpSimplex->specialOptions();
14581   clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound)
14582   int save2 = clpSolver->specialOptions();
14583   clpSolver->resolve();
14584   if (!numberNodes_) {
14585     double error = CoinMax(clpSimplex->largestDualError(),
14586       clpSimplex->largestPrimalError());
14587     if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) {
14588 #if CBC_USEFUL_PRINTING > 1
14589       printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n",
14590         clpSolver->isProvenOptimal() ? "optimal" : "!infeasible",
14591         clpSimplex->largestDualError(),
14592         clpSimplex->largestPrimalError());
14593 #endif
14594       if (!clpSolver->isProvenOptimal()) {
14595         clpSolver->setSpecialOptions(save2 | 2048);
14596         clpSimplex->allSlackBasis(true);
14597         clpSolver->resolve();
14598         if (!clpSolver->isProvenOptimal()) {
14599           bool takeHint;
14600           OsiHintStrength strength;
14601           clpSolver->getHintParam(OsiDoDualInResolve, takeHint, strength);
14602           clpSolver->setHintParam(OsiDoDualInResolve, false, OsiHintDo);
14603           clpSolver->resolve();
14604           clpSolver->setHintParam(OsiDoDualInResolve, takeHint, strength);
14605         }
14606       }
14607       // make cuts safer
14608       for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
14609         CglCutGenerator *generator = generator_[iCutGenerator]->generator();
14610         CglGomory *cgl1 = dynamic_cast< CglGomory * >(generator);
14611         if (cgl1) {
14612           cgl1->setLimitAtRoot(cgl1->getLimit());
14613         }
14614         CglTwomir *cgl2 = dynamic_cast< CglTwomir * >(generator);
14615         if (cgl2) {
14616           generator_[iCutGenerator]->setHowOften(-100);
14617         }
14618       }
14619     }
14620   }
14621   clpSolver->setSpecialOptions(save2);
14622 #if CBC_USEFUL_PRINTING > 1
14623   if (clpSimplex->numberIterations() > 1000)
14624     printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations());
14625 #endif
14626   if (type == 0 && clpSolver->isProvenOptimal()) {
14627     ClpSimplex newModel(*clpSimplex);
14628     newModel.primal();
14629     int numberColumns = newModel.numberColumns();
14630     int numberRows = newModel.numberRows();
14631     double *obj = new double[numberColumns];
14632     int *which = new int[numberColumns];
14633     const double *solution = clpSimplex->primalColumnSolution();
14634     double rhs = 1.0e-8;
14635     int numberObj = 0;
14636     double integerTolerance = getDblParam(CbcIntegerTolerance);
14637     double *objective = newModel.objective();
14638     for (int i = 0; i < numberColumns; i++) {
14639       if (objective[i]) {
14640         rhs += objective[i] * solution[i];
14641         obj[numberObj] = objective[i];
14642         which[numberObj++] = i;
14643         objective[i] = 0.0;
14644       }
14645     }
14646     if (numberObj) {
14647       newModel.addRow(numberObj, which, obj, -COIN_DBL_MAX, rhs);
14648     }
14649     delete[] obj;
14650     delete[] which;
14651     double *lower = newModel.columnLower();
14652     double *upper = newModel.columnUpper();
14653     int numberInf = 0;
14654     int numberLb = 0;
14655     int numberUb = 0;
14656     int numberInt = 0;
14657     double sumInf = 0.0;
14658     for (int i = 0; i < numberIntegers_; i++) {
14659       int iSequence = integerVariable_[i];
14660       double value = solution[iSequence];
14661       value = CoinMax(value, lower[iSequence]);
14662       value = CoinMin(value, upper[iSequence]);
14663       double nearest = floor(value + 0.5);
14664       if (value < lower[iSequence] + integerTolerance) {
14665         objective[iSequence] = 1.0;
14666         numberLb++;
14667       } else if (value > upper[iSequence] - integerTolerance) {
14668         objective[iSequence] = -1.0;
14669         numberUb++;
14670       } else if (fabs(value - nearest) <= integerTolerance) {
14671         // fix??
14672         lower[iSequence] = nearest;
14673         upper[iSequence] = nearest;
14674         numberInt++;
14675       } else {
14676         lower[iSequence] = floor(value);
14677         upper[iSequence] = ceil(value);
14678         if (value > nearest) {
14679           objective[iSequence] = 1.0;
14680           sumInf += value - nearest;
14681         } else {
14682           objective[iSequence] = -1.0;
14683           sumInf -= value - nearest;
14684         }
14685         numberInf++;
14686       }
14687     }
14688     printf("XX %d inf (sum %g), %d at lb %d at ub %d other integer\n",
14689       numberInf, sumInf, numberLb, numberUb, numberInt);
14690     if (numberInf) {
14691       newModel.primal(1);
14692       if (!newModel.isProvenOptimal()) {
14693         printf("not optimal - scaling issue - switch off\n");
14694         clpSimplex->setSpecialOptions(save);
14695         if (clpSimplex->status() == 4)
14696           clpSimplex->setProblemStatus(1);
14697         return clpSolver->isProvenOptimal() ? 1 : 0;
14698       }
14699       //newModel.writeMps("bad.mps");
14700       //assert (newModel.isProvenOptimal());
14701       printf("%d iterations\n", newModel.numberIterations());
14702       int numberInf2 = 0;
14703       int numberLb2 = 0;
14704       int numberUb2 = 0;
14705       int numberInt2 = 0;
14706       double sumInf2 = 0.0;
14707       const double *solution = newModel.primalColumnSolution();
14708       const double *lower = clpSimplex->columnLower();
14709       const double *upper = clpSimplex->columnUpper();
14710       for (int i = 0; i < numberIntegers_; i++) {
14711         int iSequence = integerVariable_[i];
14712         double value = solution[iSequence];
14713         value = CoinMax(value, lower[iSequence]);
14714         value = CoinMin(value, upper[iSequence]);
14715         double nearest = floor(value + 0.5);
14716         if (value < lower[iSequence] + integerTolerance) {
14717           numberLb2++;
14718         } else if (value > upper[iSequence] - integerTolerance) {
14719           numberUb2++;
14720         } else if (fabs(value - nearest) <= integerTolerance) {
14721           numberInt2++;
14722         } else {
14723           if (value > nearest) {
14724             sumInf2 += value - nearest;
14725           } else {
14726             sumInf2 -= value - nearest;
14727           }
14728           numberInf2++;
14729         }
14730       }
14731       printf("XXX %d inf (sum %g), %d at lb %d at ub %d other integer\n",
14732         numberInf2, sumInf2, numberLb2, numberUb2, numberInt2);
14733       if (sumInf2 < sumInf * 0.95) {
14734         printf("XXXX suminf reduced from %g (%d) to %g (%d)\n",
14735           sumInf, numberInf, sumInf2, numberInf2);
14736         if (numberObj) {
14737           newModel.deleteRows(1, &numberRows);
14738         }
14739         memcpy(newModel.objective(),
14740           clpSimplex->objective(),
14741           numberColumns * sizeof(double));
14742         memcpy(newModel.columnLower(),
14743           clpSimplex->columnLower(),
14744           numberColumns * sizeof(double));
14745         memcpy(newModel.columnUpper(),
14746           clpSimplex->columnUpper(),
14747           numberColumns * sizeof(double));
14748         newModel.setClpScaledMatrix(NULL);
14749         newModel.primal(1);
14750         printf("%d iterations\n", newModel.numberIterations());
14751         int numberInf3 = 0;
14752         int numberLb3 = 0;
14753         int numberUb3 = 0;
14754         int numberInt3 = 0;
14755         double sumInf3 = 0.0;
14756         const double *solution = newModel.primalColumnSolution();
14757         const double *lower = clpSimplex->columnLower();
14758         const double *upper = clpSimplex->columnUpper();
14759         for (int i = 0; i < numberIntegers_; i++) {
14760           int iSequence = integerVariable_[i];
14761           double value = solution[iSequence];
14762           value = CoinMax(value, lower[iSequence]);
14763           value = CoinMin(value, upper[iSequence]);
14764           double nearest = floor(value + 0.5);
14765           if (value < lower[iSequence] + integerTolerance) {
14766             numberLb3++;
14767           } else if (value > upper[iSequence] - integerTolerance) {
14768             numberUb3++;
14769           } else if (fabs(value - nearest) <= integerTolerance) {
14770             numberInt3++;
14771           } else {
14772             if (value > nearest) {
14773               sumInf3 += value - nearest;
14774             } else {
14775               sumInf3 -= value - nearest;
14776             }
14777             numberInf3++;
14778           }
14779         }
14780         printf("XXXXX %d inf (sum %g), %d at lb %d at ub %d other integer\n",
14781           numberInf3, sumInf3, numberLb3, numberUb3, numberInt3);
14782         if (sumInf3 < sumInf * 0.95) {
14783           memcpy(clpSimplex->primalColumnSolution(),
14784             newModel.primalColumnSolution(),
14785             numberColumns * sizeof(double));
14786           memcpy(clpSimplex->dualColumnSolution(),
14787             newModel.dualColumnSolution(),
14788             numberColumns * sizeof(double));
14789           memcpy(clpSimplex->primalRowSolution(),
14790             newModel.primalRowSolution(),
14791             numberRows * sizeof(double));
14792           memcpy(clpSimplex->dualRowSolution(),
14793             newModel.dualRowSolution(),
14794             numberRows * sizeof(double));
14795           memcpy(clpSimplex->statusArray(),
14796             newModel.statusArray(),
14797             (numberColumns + numberRows) * sizeof(unsigned char));
14798           clpSolver->setWarmStart(NULL);
14799         }
14800       }
14801     }
14802   }
14803   clpSimplex->setSpecialOptions(save);
14804   if (clpSimplex->status() == 4)
14805     clpSimplex->setProblemStatus(1);
14806   return clpSolver->isProvenOptimal() ? 1 : 0;
14807 }
14808 #endif
14809 /*!
14810     \todo It'd be really nice if there were an overload for this method that
14811 	  allowed a separate value for the underlying solver's log level. The
14812 	  overload could be coded to allow an increase in the log level of the
14813 	  underlying solver.
14814 
14815 	  It's worth contemplating whether OSI should have a setLogLevel method
14816 	  that's more specific than the hint mechanism.
14817 */
14818 
14819 // Set log level
14820 void CbcModel::setLogLevel(int value)
14821 {
14822   handler_->setLogLevel(value);
14823   // Reduce print out in Osi
14824   if (solver_) {
14825     int oldLevel = solver_->messageHandler()->logLevel();
14826     if (value < oldLevel)
14827       solver_->messageHandler()->setLogLevel(value);
14828 #ifdef COIN_HAS_CLP
14829     OsiClpSolverInterface *clpSolver
14830       = dynamic_cast< OsiClpSolverInterface * >(solver_);
14831     if (clpSolver) {
14832       ClpSimplex *clpSimplex = clpSolver->getModelPtr();
14833       oldLevel = clpSimplex->logLevel();
14834       if (value < oldLevel)
14835         clpSimplex->setLogLevel(value);
14836     }
14837 #else // COIN_HAS_CLP
14838     /*
14839           For generic OSI solvers, if the new log level is 0, try the
14840           DoReducePrint hint for emphasis.
14841         */
14842     if (value == 0) {
14843       solver_->setHintParam(OsiDoReducePrint, true, OsiHintDo);
14844     }
14845 #endif // COIN_HAS_CLP
14846   }
14847 }
14848 
14849 /* Pass in target solution and optional priorities.
14850    If priorities then >0 means only branch if incorrect
14851    while <0 means branch even if correct. +1 or -1 are
14852    highest priority */
14853 void CbcModel::setHotstartSolution(const double *solution, const int *priorities)
14854 {
14855   if (solution == NULL) {
14856     delete[] hotstartSolution_;
14857     hotstartSolution_ = NULL;
14858     delete[] hotstartPriorities_;
14859     hotstartPriorities_ = NULL;
14860   } else {
14861     int numberColumns = solver_->getNumCols();
14862     hotstartSolution_ = CoinCopyOfArray(solution, numberColumns);
14863     hotstartPriorities_ = CoinCopyOfArray(priorities, numberColumns);
14864     for (int i = 0; i < numberColumns; i++) {
14865       if (hotstartSolution_[i] == -COIN_DBL_MAX) {
14866         hotstartSolution_[i] = 0.0;
14867         hotstartPriorities_[i] += 10000;
14868       }
14869       if (solver_->isInteger(i))
14870         hotstartSolution_[i] = floor(hotstartSolution_[i] + 0.5);
14871     }
14872   }
14873 }
14874 // Increment strong info
14875 void CbcModel::incrementStrongInfo(int numberTimes, int numberIterations,
14876   int numberFixed, bool ifInfeasible)
14877 {
14878   strongInfo_[0] += numberTimes;
14879   numberStrongIterations_ += numberIterations;
14880   strongInfo_[1] += numberFixed;
14881   if (ifInfeasible)
14882     strongInfo_[2]++;
14883 }
14884 /* Set objective value in a node.  This is separated out so that
14885    odd solvers can use.  It may look at extra information in
14886    solverCharacteriscs_ and will also use bound from parent node
14887 */
14888 void CbcModel::setObjectiveValue(CbcNode *thisNode, const CbcNode *parentNode) const
14889 {
14890   double newObjValue = solver_->getObjSense() * solver_->getObjValue();
14891   // If odd solver take its bound
14892   if (solverCharacteristics_) {
14893     newObjValue = CoinMax(newObjValue, solverCharacteristics_->mipBound());
14894     // Reset bound anyway (no harm if not odd)
14895     solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
14896   }
14897   // If not root then use max of this and parent
14898   if (parentNode)
14899     newObjValue = CoinMax(newObjValue, parentNode->objectiveValue());
14900   thisNode->setObjectiveValue(newObjValue);
14901 }
14902 // Current time since start of branchAndbound
14903 double
14904 CbcModel::getCurrentSeconds() const
14905 {
14906   if (!useElapsedTime())
14907     return CoinCpuTime() - getDblParam(CbcStartSeconds);
14908   else
14909     return CoinGetTimeOfDay() - getDblParam(CbcStartSeconds);
14910 }
14911 /* Encapsulates choosing a variable -
14912    anyAction: -2 infeasible
14913 	      -1 round again
14914 	       0 done
14915 
14916    At the point where chooseBranch is called, we've decided that this problem
14917    will need to be placed in the live set and we need to choose a branching
14918    variable.
14919 
14920    Parameters:
14921      newNode:	the node just created for the active subproblem.
14922      oldNode:	newNode's parent.
14923      lastws:	oldNode's basis
14924      lowerBefore, upperBefore: column bound arrays for oldNode
14925      cuts:	list of cuts added to newNode.
14926 
14927      resolved:	(o)  set to true if newNode is resolved during processing
14928      branches:	(o) will be filled in with ... ? Null on entry
14929 */
14930 int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft,
14931   CbcNode *oldNode, OsiCuts &cuts,
14932   bool &resolved, CoinWarmStartBasis *lastws,
14933   const double *lowerBefore, const double *upperBefore,
14934   OsiSolverBranch *&branches)
14935 {
14936   // Set state of search
14937   /*
14938       0 - outside CbcNode
14939       1 - no solutions
14940       2 - all heuristic solutions
14941       3 - a solution reached by branching (could be strong)
14942       4 - no solution but many nodes
14943          add 10 if depth >= K
14944     K is currently hardcoded to 8, a few lines below.
14945 
14946     CBCMODEL_DEBUG: Seems like stateOfSearch_ should be 2 if
14947            numberHeuristicSolutions_ == numberSolutions_.
14948 
14949     */
14950   stateOfSearch_ = 1;
14951   if (numberSolutions_ > 0) {
14952     if (numberHeuristicSolutions_ == numberSolutions_)
14953       stateOfSearch_ = 3;
14954     else
14955       stateOfSearch_ = 3;
14956   }
14957   if (numberNodes_ > 2 * numberObjects_ + 1000) {
14958     stateOfSearch_ = 4;
14959   }
14960   //stateOfSearch_=3;
14961   if (currentNode_ && currentNode_->depth() >= 8)
14962     stateOfSearch_ += 10;
14963   //printf("STate %d, %d nodes - parent %c - sol %d %d\n",
14964   // stateOfSearch_,numberNodes_,parentModel_ ? 'Y' :'N',
14965   // numberSolutions_,numberHeuristicSolutions_);
14966   int anyAction = -1;
14967   resolved = false;
14968   if (newNode->objectiveValue() >= getCutoff())
14969     anyAction = -2;
14970   branches = NULL;
14971   bool feasible = true;
14972   int branchingState = -1;
14973   // Compute "small" change in branch
14974   int nBranches = intParam_[CbcNumberBranches];
14975   if (nBranches) {
14976     double average = dblParam_[CbcSumChange] / static_cast< double >(nBranches);
14977     dblParam_[CbcSmallChange] = CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]);
14978     dblParam_[CbcSmallChange] = CoinMax(dblParam_[CbcSmallChange], 1.0e-8);
14979   } else {
14980     dblParam_[CbcSmallChange] = 1.0e-8;
14981   }
14982 #ifdef JJF_ZERO
14983   // Say not on optimal path
14984   bool onOptimalPath = false;
14985   if ((specialOptions_ & 1) != 0) {
14986     /*
14987           This doesn't work as intended --- getRowCutDebugger will return null
14988           unless the current feasible solution region includes the optimal solution
14989           that RowCutDebugger knows. There's no way to tell inactive from off the
14990           optimal path.
14991         */
14992     const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
14993     if (debugger) {
14994       onOptimalPath = true;
14995       printf("On optimal path - choose\n");
14996     }
14997   }
14998 #endif
14999   currentNode_ = newNode; // so can be used elsewhere
15000   // Remember number of rows to restore at the end of the loop
15001   int saveNumberRows = solver_->getNumRows();
15002   /*
15003       Enough preparation. Get down to the business of choosing a branching
15004       variable.
15005     */
15006   while (anyAction == -1) {
15007     // Set objective value (not so obvious if NLP etc)
15008     setObjectiveValue(newNode, oldNode);
15009     //if (numberPassesLeft<=0)
15010     //branchingState=1;
15011     /*
15012           Is there a CbcBranchDecision object installed? Does it specify a
15013           chooseVariable method? If not, we're using the old (Cbc) side of the branch
15014           decision hierarchy.  In quick summary, CbcNode::chooseBranch uses strong
15015           branching on any objects, while CbcNode::chooseDynamicBranch uses dynamic
15016           branching, but only on simple integers (-3 is the code for punt due to
15017           complex objects). Serious bugs remain on the Cbc side, particularly in
15018           chooseDynamicBranch.
15019         */
15020     if (!branchingMethod_ || !branchingMethod_->chooseMethod()) {
15021 #ifdef COIN_HAS_CLP
15022       bool doClp = oldNode && (oldNode->depth() % 2) == 1;
15023       if (!doCutsNow(1))
15024         doClp = true;
15025       //doClp = true;
15026       int testDepth = 5;
15027       // Don't do if many iterations per node
15028       int totalNodes = numberNodes_ + numberExtraNodes_;
15029       int totalIterations = numberIterations_ + numberExtraIterations_;
15030       bool diving = false;
15031       if ((moreSpecialOptions_ & 33554432) != 0) {
15032         testDepth = COIN_INT_MAX;
15033         if (oldNode && (oldNode->depth() == -2 || oldNode->depth() == 4))
15034           diving = true;
15035       }
15036       if (totalNodes * 40 < totalIterations || numberNodes_ < 1000) {
15037         doClp = false;
15038         //} else if (oldNode&&fastNodeDepth_>=0&&oldNode->depth()>=testDepth&&(specialOptions_&2048)==0) {
15039         //printf("size %d %d - cuts %d - nodes %d its %d %c\n",solver_->getNumRows(),
15040         //     solver_->getNumCols(),cuts.sizeRowCuts(),
15041         //     totalNodes,totalIterations,doClp ? 'Y' : 'N');
15042       }
15043       if (oldNode && ((fastNodeDepth_ >= 0 && oldNode->depth() >= testDepth && doClp) || diving) && /*!parentModel_*/ (specialOptions_ & 2048) == 0
15044         && !cuts.sizeRowCuts()) {
15045         OsiClpSolverInterface *clpSolver
15046           = dynamic_cast< OsiClpSolverInterface * >(solver_);
15047         if (clpSolver) {
15048           anyAction = newNode->chooseClpBranch(this, oldNode);
15049 	  currentNode_ = NULL;
15050           if (anyAction != -1)
15051             break;
15052         }
15053       }
15054 #endif
15055 #ifdef COIN_HAS_CLP
15056       // Deal with funny variables
15057       if ((moreSpecialOptions2_ & 32768) != 0)
15058         cleanBounds(solver_, NULL);
15059       int save = 0;
15060       OsiClpSolverInterface *clpSolver
15061         = dynamic_cast< OsiClpSolverInterface * >(solver_);
15062       if (clpSolver && (moreSpecialOptions_ & 4194304) != 0) {
15063         ClpSimplex *clpSimplex = clpSolver->getModelPtr();
15064         save = clpSimplex->specialOptions();
15065         clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray)
15066       }
15067 #endif
15068 #ifdef COIN_HAS_NTY
15069       if (symmetryInfo_) {
15070         CbcNodeInfo *infoX = oldNode ? oldNode->nodeInfo() : NULL;
15071         bool worthTrying = false;
15072         if (infoX) {
15073           CbcNodeInfo *info = infoX;
15074           for (int i = 0; i < NTY_BAD_DEPTH; i++) {
15075             if (!info->parent()) {
15076               worthTrying = true;
15077               break;
15078             }
15079             info = info->parent();
15080             if (info->symmetryWorked()) {
15081               worthTrying = true;
15082               break;
15083             }
15084           }
15085         } else {
15086           worthTrying = true;
15087         }
15088         if ((moreSpecialOptions2_ & (128 | 256)) == (128 | 256) && currentDepth_ > 5)
15089           worthTrying = false;
15090         if (worthTrying) {
15091           int n = symmetryInfo_->orbitalFixing(solver_);
15092           if (n) {
15093 #if PRINT_MORE == 0
15094             if (logLevel() > 1)
15095               printf("%d orbital fixes\n", n);
15096 #endif
15097             solver_->resolve();
15098             if (!isProvenOptimal()) {
15099               if (logLevel() > 1)
15100                 printf("infeasible after orbital fixing\n");
15101             }
15102           }
15103         }
15104       }
15105 #endif
15106       if (numberBeforeTrust_ == 0) {
15107         anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft);
15108       } else {
15109         anyAction = newNode->chooseDynamicBranch(this, oldNode, branches, numberPassesLeft);
15110         if (anyAction == -3)
15111           anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft); // dynamic did nothing
15112       }
15113       currentNode_ = NULL;
15114 #ifdef COIN_HAS_CLP
15115       if (clpSolver && (moreSpecialOptions_ & 4194304) != 0) {
15116         ClpSimplex *clpSimplex = clpSolver->getModelPtr();
15117         clpSimplex->setSpecialOptions(save);
15118       }
15119 #endif
15120       /*
15121               We're on the new (Osi) side of the branching hierarchy.
15122             */
15123     } else {
15124       OsiBranchingInformation usefulInfo = usefulInformation();
15125       anyAction = newNode->chooseOsiBranch(this, oldNode, &usefulInfo, branchingState);
15126       currentNode_ = NULL;
15127       //branchingState=0;
15128     }
15129     if (!oldNode) {
15130       if (numberUpdateItems_) {
15131         for (int i = 0; i < numberUpdateItems_; i++) {
15132           CbcObjectUpdateData *update = updateItems_ + i;
15133           CbcObject *object = dynamic_cast< CbcObject * >(update->object_);
15134 #ifndef NDEBUG
15135           bool found = false;
15136           for (int j = 0; j < numberObjects_; j++) {
15137             if (update->object_ == object_[j]) {
15138               found = true;
15139               break;
15140             }
15141           }
15142           assert(found);
15143 #endif
15144           if (object)
15145             object->updateInformation(*update);
15146         }
15147         numberUpdateItems_ = 0;
15148       }
15149     }
15150     if (solverCharacteristics_ && solverCharacteristics_->solutionAddsCuts() && // we are in some OA based bab
15151       feasible && (newNode->numberUnsatisfied() == 0) //solution has become integer feasible during strong branching
15152     ) {
15153       //in the present case we need to check here integer infeasibility if the node is not fathomed we will have to do the loop
15154       // again
15155       //std::cout<<solver_<<std::endl;
15156 
15157       OsiCuts feasCuts;
15158 
15159       for (int i = 0; i < numberCutGenerators_ && (feasCuts.sizeRowCuts() == 0); i++) {
15160         if (generator_[i]->normal() && (!generator_[i]->needsOptimalBasis() || solver_->basisIsAvailable()))
15161           generator_[i]->generateCuts(feasCuts, 1 /* = fullscan */, solver_, NULL);
15162       }
15163       solver_->applyCuts(feasCuts);
15164 
15165       resolve(solver_);
15166       double objval = solver_->getObjValue();
15167       lastHeuristic_ = NULL;
15168       setBestSolution(CBC_SOLUTION, objval,
15169         solver_->getColSolution());
15170       int easy = 2;
15171       if (!solverCharacteristics_->mipFeasible()) //did we prove that the node could be pruned?
15172         feasible = false;
15173       // Reset the bound now
15174       solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
15175 
15176       solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy);
15177       feasible &= resolve(oldNode ? oldNode->nodeInfo() : NULL, 11) != 0;
15178       solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL);
15179       resolved = true;
15180       if (problemFeasibility_->feasible(this, 0) < 0) {
15181         feasible = false; // pretend infeasible
15182       }
15183       if (feasible)
15184         anyAction = -1;
15185       else
15186         anyAction = -2;
15187     }
15188     /*
15189           Yep, false positives for sure. And no easy way to distinguish honest
15190           infeasibility from `found a solution and tightened objective target.'
15191 
15192           if (onOptimalPath)
15193           assert (anyAction!=-2); // can be useful but gives false positives on strong
15194           */
15195     numberPassesLeft--;
15196     if (numberPassesLeft <= -1) {
15197       if (!numberLongStrong_ && !numberThreads_)
15198         messageHandler()->message(CBC_WARNING_STRONG,
15199           messages())
15200           << CoinMessageEol;
15201       numberLongStrong_++;
15202     }
15203     if (anyAction == -1) {
15204       // can do quick optimality check
15205       int easy = 2;
15206       solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy);
15207       feasible = resolve(oldNode ? oldNode->nodeInfo() : NULL, 11) != 0;
15208       solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL);
15209       resolved = true;
15210       if (problemFeasibility_->feasible(this, 0) < 0) {
15211         feasible = false; // pretend infeasible
15212       }
15213       if (feasible) {
15214         // Set objective value (not so obvious if NLP etc)
15215         setObjectiveValue(newNode, oldNode);
15216         reducedCostFix();
15217         if (newNode->objectiveValue() >= getCutoff())
15218           anyAction = -2;
15219       } else {
15220         anyAction = -2;
15221       }
15222     }
15223   }
15224   //A candidate has been found; restore the subproblem.
15225   if (saveNumberRows < solver_->getNumRows()) {
15226     // delete rows - but leave solution
15227     int n = solver_->getNumRows();
15228     int *del = new int[n - saveNumberRows];
15229     for (int i = saveNumberRows; i < n; i++)
15230       del[i - saveNumberRows] = i;
15231     solver_->deleteRows(n - saveNumberRows, del);
15232     delete[] del;
15233   }
15234   /*
15235       End main loop to choose a branching variable.
15236     */
15237   if (anyAction >= 0) {
15238     if (resolved) {
15239       /*
15240               Used to be that when the node was not fathomed (branching object present)
15241               the solution was not needed. But that's no longer the case --- heuristics
15242               are applied, and they may want the solution.
15243             */
15244       // bool needValidSolution = (newNode->branchingObject() == NULL) ;
15245       bool needValidSolution = true;
15246       takeOffCuts(cuts, needValidSolution, NULL);
15247 #ifdef CHECK_CUT_COUNTS
15248       {
15249         printf("Number of rows after chooseBranch fix (node)"
15250                "(active only) %d\n",
15251           numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_);
15252         const CoinWarmStartBasis *debugws = dynamic_cast< const CoinWarmStartBasis * >(solver_->getWarmStart());
15253         debugws->print();
15254         delete debugws;
15255       }
15256 #endif
15257     }
15258     {
15259       OsiBranchingObject *branchingObject = newNode->modifiableBranchingObject();
15260       CbcGeneralBranchingObject *generalBranch = dynamic_cast< CbcGeneralBranchingObject * >(branchingObject);
15261       if (generalBranch && false) {
15262         int numberProblems = generalBranch->numberSubProblems();
15263         for (int i = 0; i < numberProblems; i++) {
15264           double objectiveValue;
15265           double sumInfeasibilities;
15266           int numberUnsatisfied;
15267           generalBranch->state(objectiveValue, sumInfeasibilities,
15268             numberUnsatisfied, i);
15269           printf("node %d obj %g sumI %g numI %i rel depth %d\n",
15270             i, objectiveValue, sumInfeasibilities, numberUnsatisfied,
15271             generalBranch->subProblem(i)->depth_);
15272         }
15273       }
15274       if (generalBranch) {
15275         int numberProblems = generalBranch->numberSubProblems();
15276         newNode->setBranchingObject(NULL);
15277         CbcNode *newNode2 = NULL;
15278         assert(numberProblems);
15279         int nProbMinus1 = numberProblems - 1;
15280         lockThread();
15281         for (int i = 0; i < currentNumberCuts_; i++) {
15282           if (addedCuts_[i])
15283             addedCuts_[i]->increment(nProbMinus1);
15284         }
15285         unlockThread();
15286         for (int i = 0; i < numberProblems; i++) {
15287           double objectiveValue;
15288           double sumInfeasibilities;
15289           int numberUnsatisfied;
15290           generalBranch->state(objectiveValue, sumInfeasibilities,
15291             numberUnsatisfied, i);
15292           //printf("node %d obj %g sumI %g numI %i rel depth %d\n",
15293           // i,objectiveValue,sumInfeasibilities,numberUnsatisfied,
15294           // generalBranch->subProblem(i)->depth_);
15295           newNode2 = new CbcNode();
15296           newNode2->setDepth(generalBranch->subProblem(i)->depth_ + currentDepth_);
15297           generalBranch->subProblem(i)->apply(solver_, 8); // basis
15298           newNode2->setNumberUnsatisfied(numberUnsatisfied);
15299           newNode2->setSumInfeasibilities(sumInfeasibilities);
15300           newNode2->setGuessedObjectiveValue(objectiveValue);
15301           newNode2->setObjectiveValue(objectiveValue);
15302           CbcOneGeneralBranchingObject *object = new CbcOneGeneralBranchingObject(this, generalBranch, i);
15303           newNode2->setBranchingObject(object);
15304           assert(lastws->fullBasis());
15305           newNode2->createInfo(this, oldNode, lastws,
15306             lowerBefore, upperBefore,
15307             numberOldActiveCuts_, numberNewCuts_);
15308           newNode2->nodeInfo()->setNumberBranchesLeft(1);
15309           //newNode2->nodeInfo()->unsetParentBasedData();
15310           if (i < nProbMinus1) {
15311             //OsiBranchingObject * object = oldNode->modifiableBranchingObject();
15312             CbcNodeInfo *nodeInfo = oldNode->nodeInfo();
15313             //object->incrementNumberBranchesLeft();
15314             nodeInfo->incrementNumberPointingToThis();
15315             newNode2->nodeInfo()->setNodeNumber(numberNodes2_);
15316             //newNode2->nodeInfo()->setNumberBranchesLeft(1);
15317             newNode2->initializeInfo();
15318             numberNodes2_++;
15319             tree_->push(newNode2);
15320           }
15321         }
15322         delete newNode;
15323         newNode = newNode2;
15324       } else {
15325         if (lastws) {
15326           if (parallelMode() < -1) {
15327             lastws->fixFullBasis();
15328           } else {
15329             if ((specialOptions_ & 8192) == 0)
15330               assert(lastws->fullBasis());
15331             else
15332               lastws->fixFullBasis();
15333           }
15334         }
15335         newNode->createInfo(this, oldNode, lastws, lowerBefore, upperBefore,
15336           numberOldActiveCuts_, numberNewCuts_);
15337       }
15338     }
15339     if (newNode->numberUnsatisfied()) {
15340       maximumDepthActual_ = CoinMax(maximumDepthActual_, newNode->depth());
15341       // Number of branches is in oldNode!
15342       newNode->initializeInfo();
15343       if (cuts.sizeRowCuts()) {
15344         int initialNumber = ((threadMode_ & 1) == 0) ? 0 : 1000000000;
15345         lockThread();
15346         newNode->nodeInfo()->addCuts(cuts, newNode->numberBranches(),
15347           //whichGenerator_,
15348           initialNumber);
15349         unlockThread();
15350       }
15351     }
15352   } else {
15353     anyAction = -2;
15354     // Reset bound anyway (no harm if not odd)
15355     solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
15356   }
15357   // May have slipped through i.e. anyAction == 0 and objective above cutoff
15358   // I think this will screw up cut reference counts if executed.
15359   // We executed addCuts just above. (lh)
15360   if (anyAction >= 0) {
15361     assert(newNode);
15362     if (newNode->objectiveValue() >= getCutoff()) {
15363       anyAction = -2; // say bad after all
15364       // zap parent nodeInfo
15365 #ifdef COIN_DEVELOP
15366       printf("zapping3 CbcNodeInfo %x\n", newNode->nodeInfo()->parent());
15367 #endif
15368       if (newNode->nodeInfo())
15369         newNode->nodeInfo()->nullParent();
15370     }
15371   }
15372   stateOfSearch_ = 0; // outside chooseBranch
15373 #ifdef JJF_ZERO
15374   if (onOptimalPath) {
15375     const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
15376     if (!debugger) {
15377       printf("NOT On optimal path - choose\n");
15378       abort();
15379     } else {
15380       printf("Still On optimal path - choose\n");
15381       if (anyAction == -2) {
15382         printf("anyAction 2!!\n");
15383         abort();
15384       }
15385     }
15386   }
15387 #endif
15388   return anyAction;
15389 }
15390 
15391 /*
15392    For advanced applications you may wish to modify the behavior of Cbc
15393    e.g. if the solver is a NLP solver then you may not have an exact
15394    optimum solution at each step.  Information could be built into
15395    OsiSolverInterface but this is an alternative so that that interface
15396    does not have to be changed.  If something similar is useful to
15397    enough solvers then it could be migrated.
15398    You can also pass in by using solver->setAuxiliaryInfo.
15399    You should do that if solver is odd - if solver is normal simplex
15400    then use this
15401 */
15402 void CbcModel::passInSolverCharacteristics(OsiBabSolver *solverCharacteristics)
15403 {
15404   solverCharacteristics_ = solverCharacteristics;
15405 }
15406 // Generate an OsiBranchingInformation object
15407 OsiBranchingInformation
15408 CbcModel::usefulInformation() const
15409 {
15410   OsiBranchingInformation usefulInfo(solver_, normalSolver(), false);
15411   // and modify
15412   usefulInfo.solution_ = testSolution_;
15413   usefulInfo.integerTolerance_ = dblParam_[CbcIntegerTolerance];
15414   usefulInfo.hotstartSolution_ = hotstartSolution_;
15415   usefulInfo.numberSolutions_ = numberSolutions_;
15416   usefulInfo.numberBranchingSolutions_ = numberSolutions_ - numberHeuristicSolutions_;
15417   usefulInfo.depth_ = -1;
15418   return usefulInfo;
15419 }
15420 void CbcModel::setBestSolution(const double *solution, int numberColumns,
15421   double objectiveValue, bool checkSolution)
15422 {
15423   // May be odd discontinuities - so only check if asked
15424   if (checkSolution) {
15425     assert(numberColumns == solver_->getNumCols());
15426     double *saveLower = CoinCopyOfArray(solver_->getColLower(), numberColumns);
15427     double *saveUpper = CoinCopyOfArray(solver_->getColUpper(), numberColumns);
15428     // Fix integers
15429     int numberAway = 0;
15430     for (int i = 0; i < numberColumns; i++) {
15431       if (solver_->isInteger(i)) {
15432         double value = solution[i];
15433         double intValue = floor(value + 0.5);
15434         if (fabs(value - intValue) > 1.0e-4)
15435           numberAway++;
15436         solver_->setColLower(i, intValue);
15437         solver_->setColUpper(i, intValue);
15438       }
15439     }
15440     // Save basis
15441     CoinWarmStart *saveBasis = solver_->getWarmStart();
15442     // Solve
15443     solver_->initialSolve();
15444     char printBuffer[200];
15445     if (numberAway) {
15446       sprintf(printBuffer, "Warning %d integer variables were more than 1.0e-4 away from integer", numberAway);
15447       messageHandler()->message(CBC_GENERAL, messages())
15448         << printBuffer << CoinMessageEol;
15449     }
15450     bool looksGood = solver_->isProvenOptimal();
15451     if (looksGood) {
15452       double direction = solver_->getObjSense();
15453       double objValue = direction * solver_->getObjValue();
15454       if (objValue > objectiveValue + 1.0e-8 * (1.0 + fabs(objectiveValue))) {
15455         sprintf(printBuffer, "Given objective value %g, computed %g",
15456           objectiveValue, objValue);
15457         messageHandler()->message(CBC_GENERAL, messages())
15458           << printBuffer << CoinMessageEol;
15459       }
15460       // Use this as objective value and solution
15461       objectiveValue = objValue;
15462       solution = solver_->getColSolution();
15463       // Save current basis
15464       CoinWarmStartBasis *ws = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart());
15465       assert(ws);
15466       setBestSolutionBasis(*ws);
15467       delete ws;
15468     }
15469     // Restore basis
15470     solver_->setWarmStart(saveBasis);
15471     delete saveBasis;
15472     // Restore bounds
15473     solver_->setColLower(saveLower);
15474     delete[] saveLower;
15475     solver_->setColUpper(saveUpper);
15476     delete[] saveUpper;
15477     // Return if no good
15478     if (!looksGood) {
15479       messageHandler()->message(CBC_GENERAL, messages())
15480         << "Error solution not saved as not feasible" << CoinMessageEol;
15481       return;
15482     } else {
15483       // message
15484       sprintf(printBuffer, "Solution with objective value %g saved",
15485         objectiveValue);
15486       messageHandler()->message(CBC_GENERAL, messages())
15487         << printBuffer << CoinMessageEol;
15488     }
15489   }
15490   if (bestSolution_)
15491     saveExtraSolution(bestSolution_, bestObjective_);
15492   bestObjective_ = objectiveValue;
15493   // may be able to change cutoff now
15494   double cutoff = getCutoff();
15495   double increment = getDblParam(CbcModel::CbcCutoffIncrement);
15496   if (cutoff > objectiveValue - increment) {
15497     cutoff = objectiveValue - increment;
15498     setCutoff(cutoff);
15499     // change cutoff as constraint if wanted
15500     if (cutoffRowNumber_ >= 0) {
15501       if (solver_->getNumRows() > cutoffRowNumber_) {
15502         double offset;
15503         solver_->getDblParam(OsiObjOffset, offset);
15504         solver_->setRowUpper(cutoffRowNumber_, cutoff + offset);
15505         if (continuousSolver_ && solver_->getNumCols() > continuousSolver_->getNumCols()) {
15506           solver_->setRowUpper(cutoffRowNumber_, floor(cutoff) + offset);
15507           solver_->setRowLower(cutoffRowNumber_, floor(cutoff) + offset);
15508         }
15509       }
15510     }
15511   }
15512   int n = CoinMax(numberColumns, solver_->getNumCols());
15513   delete[] bestSolution_;
15514   bestSolution_ = new double[n];
15515   memset(bestSolution_, 0, n * sizeof(double));
15516   memcpy(bestSolution_, solution, numberColumns * sizeof(double));
15517 }
15518 /* Do heuristics at root.
15519    0 - don't delete
15520    1 - delete
15521       2 - just delete - don't even use
15522   Parameter of 2 means what it says --- the routine will do nothing except
15523   delete the existing heuristics. A feasibility pump is always deleted,
15524   independent of the parameter value, as it's only useful at the root.
15525 
15526   The routine is called from branchAndBound to process the root node. But it
15527   will also be called when we've recursed into branchAndBound via smallBaB.
15528 */
15529 void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards)
15530 {
15531 
15532   int numberColumns = getNumCols();
15533   double *newSolution = new double[numberColumns];
15534   int i;
15535   if (deleteHeuristicsAfterwards != 2) {
15536     /*
15537           If mode == 1, we delete and recreate here, then delete at the bottom. The
15538           create/delete part makes sense, but why delete the existing array? Seems like
15539           it should be preserved and restored.
15540         */
15541     if (deleteHeuristicsAfterwards) {
15542       delete[] usedInSolution_;
15543       usedInSolution_ = new int[numberColumns];
15544       CoinZeroN(usedInSolution_, numberColumns);
15545     }
15546     double heuristicValue = getCutoff();
15547     int found = -1; // no solution found
15548     CbcEventHandler *eventHandler = getEventHandler();
15549     if (eventHandler)
15550       eventHandler->setModel(this);
15551     /*
15552           currentPassNumber_ is described as `cut pass number'. Again, seems a bit
15553           cavalier to just change it.
15554 
15555           Whether this has any effect is determined by individual heuristics. Typically
15556           there will be a check at the front of the solution() routine that determines
15557           whether it will run or simply return. Root heuristics are characterised by
15558           node count of 0. In addition, currentPassNumber_ can be checked to to limit
15559           execution in terms of passes through cut generation / heuristic execution in
15560           solveWithCuts.
15561         */
15562 
15563     currentPassNumber_ = 1; // so root heuristics will run
15564     /*
15565           A loop to run the heuristics. incrementUsed will mark entries in
15566           usedInSolution corresponding to variables that are nonzero in the solution.
15567           CBC_ROUNDING just identifies a message template, not the heuristic.
15568         */
15569     // Modify based on size etc
15570     adjustHeuristics();
15571     // See if already within allowable gap
15572     bool exitNow = false;
15573     for (i = 0; i < numberHeuristics_; i++) {
15574       if (heuristic_[i]->exitNow(bestObjective_))
15575         exitNow = true;
15576     }
15577     if (!exitNow) {
15578       /** -1 first time otherwise number of solutions last time */
15579       int lastSolutionCount = -1;
15580       while (lastSolutionCount) {
15581         int thisSolutionCount = 0;
15582 #ifdef CBC_THREAD
15583         if ((threadMode_ & 4) != 0) {
15584           typedef struct {
15585             double solutionValue;
15586             CbcModel *model;
15587             double *solution;
15588             int foundSol;
15589           } argBundle;
15590           int chunk;
15591           if (!numberThreads_)
15592             chunk = numberHeuristics_;
15593           else
15594             chunk = numberThreads_;
15595           for (int iChunk = 0; iChunk < numberHeuristics_; iChunk += chunk) {
15596             argBundle *parameters = new argBundle[chunk];
15597             for (int i = 0; i < chunk; i++)
15598               parameters[i].model = NULL;
15599             int nThisTime = CoinMin(numberHeuristics_ - iChunk, chunk);
15600             for (int i = iChunk; i < iChunk + nThisTime; i++) {
15601               // skip if can't run here
15602               if (!heuristic_[i]->shouldHeurRun(0))
15603                 continue;
15604               if (lastSolutionCount > 0 && (heuristic_[i]->switches() & 16) == 0)
15605                 continue; // no point
15606               parameters[i - iChunk].solutionValue = heuristicValue;
15607               // Don't want a strategy object
15608               CbcStrategy *saveStrategy = strategy_;
15609               strategy_ = NULL;
15610               CbcModel *newModel = new CbcModel(*this);
15611               strategy_ = saveStrategy;
15612               assert(!newModel->continuousSolver_);
15613               if (continuousSolver_)
15614                 newModel->continuousSolver_ = continuousSolver_->clone();
15615               else
15616                 newModel->continuousSolver_ = solver_->clone();
15617               parameters[i - iChunk].model = newModel;
15618               parameters[i - iChunk].solution = new double[numberColumns];
15619               ;
15620               parameters[i - iChunk].foundSol = 0;
15621               //newModel->gutsOfCopy(*this,-1);
15622               for (int j = 0; j < numberHeuristics_; j++)
15623                 delete newModel->heuristic_[j];
15624               //newModel->heuristic_ = new CbcHeuristic * [1];
15625               newModel->heuristic_[0] = heuristic_[i]->clone();
15626               newModel->heuristic_[0]->setModel(newModel);
15627               newModel->heuristic_[0]->resetModel(newModel);
15628               newModel->numberHeuristics_ = 1;
15629             }
15630             void
15631             parallelHeuristics(int numberThreads,
15632               int sizeOfData,
15633               void *argBundle);
15634             parallelHeuristics(nThisTime,
15635               static_cast< int >(sizeof(argBundle)),
15636               parameters);
15637             double cutoff = heuristicValue;
15638             for (int i = 0; i < chunk; i++) {
15639               if (parameters[i].model) {
15640                 if (parameters[i].foundSol > 0 && parameters[i].solutionValue < heuristicValue) {
15641                   memcpy(newSolution, parameters[i].solution,
15642                     numberColumns * sizeof(double));
15643                   lastHeuristic_ = heuristic_[i + iChunk];
15644                   double value = parameters[i].solutionValue;
15645                   setBestSolution(CBC_ROUNDING, value, newSolution);
15646                   // Double check valid
15647                   if (getCutoff() < cutoff) {
15648                     cutoff = getCutoff();
15649                     heuristicValue = value;
15650                     heuristic_[i + iChunk]->incrementNumberSolutionsFound();
15651                     incrementUsed(newSolution);
15652                     // increment number of solutions so other heuristics can test
15653                     thisSolutionCount++;
15654                     numberHeuristicSolutions_++;
15655                     found = i + iChunk;
15656                   }
15657                 }
15658                 if (heuristic_[i + iChunk]->exitNow(bestObjective_) || (parameters[i].model->heuristic(0)->switches() & (1024 + 2048)) == (1024 + 2048))
15659                   exitNow = true;
15660                 delete[] parameters[i].solution;
15661                 delete parameters[i].model;
15662               }
15663             }
15664             delete[] parameters;
15665             if (exitNow)
15666               break;
15667           }
15668         } else {
15669 #endif
15670           int whereFrom = 0;
15671           for (i = 0; i < numberHeuristics_; i++) {
15672             // skip if can't run here
15673             if (!heuristic_[i]->shouldHeurRun(whereFrom))
15674               continue;
15675             if (lastSolutionCount > 0 && (heuristic_[i]->switches() & 16) == 0)
15676               continue; // no point
15677             if (maximumSecondsReached()) {
15678               thisSolutionCount = -1000000;
15679               break;
15680             }
15681             // see if heuristic will do anything
15682             double saveValue = heuristicValue;
15683             double before = getCurrentSeconds();
15684             int ifSol = heuristic_[i]->solution(heuristicValue,
15685               newSolution);
15686             if (handler_->logLevel() > 1) {
15687               char line[100];
15688               sprintf(line, "Heuristic %s took %g seconds (%s)",
15689                 heuristic_[i]->heuristicName(),
15690                 getCurrentSeconds() - before,
15691                 ifSol ? "good" : "no good");
15692               handler_->message(CBC_GENERAL, messages_) << line << CoinMessageEol;
15693             }
15694             //#define DEBUG_BEST
15695 #ifdef DEBUG_BEST
15696             FILE *fp = fopen("solution.data", "rb");
15697             if (!fp && ifSol > 0) {
15698               int numberColumns = getNumCols();
15699               fp = fopen("solution.data", "wb");
15700               printf("Solution data on file solution.data\n");
15701               size_t numberWritten;
15702               numberWritten = fwrite(&numberColumns, sizeof(int), 1, fp);
15703               assert(numberWritten == 1);
15704               numberWritten = fwrite(&heuristicValue, sizeof(double), 1, fp);
15705               assert(numberWritten == 1);
15706               numberWritten = fwrite(newSolution, sizeof(double), numberColumns, fp);
15707               assert(numberWritten == numberColumns);
15708               fclose(fp);
15709             } else if (fp) {
15710               int numberColumns = getNumCols();
15711               int numberColumnsX;
15712               size_t numberRead;
15713               numberRead = fread(&numberColumnsX, sizeof(int), 1, fp);
15714               assert(numberRead == 1);
15715               if (numberColumns == numberColumnsX) {
15716                 numberRead = fread(&heuristicValue, sizeof(double), 1, fp);
15717                 assert(numberRead == 1);
15718                 numberRead = fread(newSolution, sizeof(double), numberColumns, fp);
15719                 assert(numberRead == numberColumns);
15720                 ifSol = 1;
15721               }
15722               fclose(fp);
15723             }
15724 #endif
15725             if (ifSol > 0) {
15726               // better solution found
15727               double currentObjective = bestObjective_;
15728               CbcHeuristic *saveHeuristic = lastHeuristic_;
15729               lastHeuristic_ = heuristic_[i];
15730               setBestSolution(CBC_ROUNDING, heuristicValue, newSolution);
15731               if (bestObjective_ < currentObjective) {
15732                 thisSolutionCount++;
15733                 heuristic_[i]->incrementNumberSolutionsFound();
15734                 found = i;
15735                 incrementUsed(newSolution);
15736                 // increment number of solutions so other heuristics can test
15737                 //                            numberSolutions_++;
15738                 numberHeuristicSolutions_++;
15739 #ifdef HEURISTIC_INFORM
15740                 printf("HEUR %s where %d C\n",
15741                   lastHeuristic_->heuristicName(), whereFrom);
15742 #endif
15743                 whereFrom |= 8; // say solution found
15744                 if (heuristic_[i]->exitNow(bestObjective_)
15745                   || numberSolutions_ >= getMaximumSolutions()) {
15746                   thisSolutionCount = -1000000;
15747                   break;
15748                 }
15749                 if (eventHandler) {
15750                   if (!eventHandler->event(CbcEventHandler::heuristicSolution)) {
15751                     eventHappened_ = true; // exit
15752                     thisSolutionCount = -1000000;
15753                     break;
15754                   }
15755                 }
15756                 double testGap = CoinMax(dblParam_[CbcAllowableGap],
15757                   CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
15758                     * dblParam_[CbcAllowableFractionGap]);
15759                 if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0 && bestPossibleObjective_ < 1.0e30) {
15760                   if (bestPossibleObjective_ < getCutoff())
15761                     stoppedOnGap_ = true;
15762                   //eventHappened_=true; // stop as fast as possible
15763                   thisSolutionCount = -1000000;
15764                   break;
15765                 }
15766                 reducedCostFix();
15767               } else {
15768                 // NOT better solution
15769 #if CBC_USEFUL_PRINTING > 1
15770                 printf("HEUR %s where %d REJECTED i==%d\n",
15771                   heuristic_[i]->heuristicName(), whereFrom, i);
15772 #endif
15773                 lastHeuristic_ = saveHeuristic;
15774                 heuristicValue = saveValue;
15775               }
15776             } else {
15777               heuristicValue = saveValue;
15778             }
15779             if (eventHandler) {
15780               if (!eventHandler->event(CbcEventHandler::afterHeuristic)) {
15781                 eventHappened_ = true; // exit
15782                 thisSolutionCount = -1000000;
15783                 break;
15784               }
15785             }
15786           }
15787 #ifdef CBC_THREAD
15788         }
15789 #endif
15790         if (thisSolutionCount <= 0)
15791           break;
15792         lastSolutionCount = thisSolutionCount;
15793       }
15794     }
15795     currentPassNumber_ = 0;
15796     /*
15797           Did any of the heuristics turn up a new solution? Record it before we free
15798         the vector. tree_ will not necessarily be a CbcTreeLocal; the main model gets
15799         a CbcTree by default. CbcTreeLocal actually implements a k-neighbourhood
15800         search heuristic. This initialises it with a solution and creates the
15801         k-neighbourhood cut.
15802         */
15803     if (found >= 0) {
15804       CbcTreeLocal *tree
15805         = dynamic_cast< CbcTreeLocal * >(tree_);
15806       if (tree)
15807         tree->passInSolution(bestSolution_, heuristicValue);
15808       if (eventHandler) {
15809         if (!eventHandler->event(CbcEventHandler::solution)) {
15810           eventHappened_ = true; // exit
15811         }
15812       }
15813     }
15814   }
15815   /*
15816       Cleanup. The feasibility pump heuristic is a root heuristic to look for an
15817       initial feasible solution. It's had its chance; remove it.
15818 
15819       For modes 1 and 2, all the heuristics are deleted.
15820     */
15821   if (!deleteHeuristicsAfterwards) {
15822     for (i = 0; i < numberHeuristics_; i++) {
15823       // delete FPump
15824       CbcHeuristicFPump *pump
15825         = dynamic_cast< CbcHeuristicFPump * >(heuristic_[i]);
15826       if (pump && pump->feasibilityPumpOptions() < 1000000
15827         && (specialOptions_ & 33554432) == 0) {
15828         delete pump;
15829         numberHeuristics_--;
15830         for (int j = i; j < numberHeuristics_; j++)
15831           heuristic_[j] = heuristic_[j + 1];
15832       }
15833     }
15834   } else {
15835     // delete all
15836     for (i = 0; i < numberHeuristics_; i++)
15837       delete heuristic_[i];
15838     numberHeuristics_ = 0;
15839     delete[] heuristic_;
15840     heuristic_ = NULL;
15841     delete[] usedInSolution_;
15842     usedInSolution_ = NULL;
15843   }
15844   delete[] newSolution;
15845 }
15846 // Zap integer information in problem (may leave object info)
15847 void CbcModel::zapIntegerInformation(bool leaveObjects)
15848 {
15849   numberIntegers_ = 0;
15850   delete[] integerVariable_;
15851   integerVariable_ = NULL;
15852   if (!leaveObjects && ownObjects_) {
15853     int i;
15854     for (i = 0; i < numberObjects_; i++)
15855       delete object_[i];
15856     delete[] object_;
15857     numberObjects_ = 0;
15858     object_ = NULL;
15859   }
15860 }
15861 // Create C++ lines to get to current state
15862 void CbcModel::generateCpp(FILE *fp, int /*options*/)
15863 {
15864   // Do cut generators
15865   int i;
15866   for (i = 0; i < numberCutGenerators_; i++) {
15867     CglCutGenerator *generator = generator_[i]->generator();
15868     std::string name = generator->generateCpp(fp);
15869     int howOften = generator_[i]->howOften();
15870     int howOftenInSub = generator_[i]->howOftenInSub();
15871     int whatDepth = generator_[i]->whatDepth();
15872     int whatDepthInSub = generator_[i]->whatDepthInSub();
15873     bool normal = generator_[i]->normal();
15874     bool atSolution = generator_[i]->atSolution();
15875     bool whenInfeasible = generator_[i]->whenInfeasible();
15876     bool timing = generator_[i]->timing();
15877     fprintf(fp, "3  cbcModel->addCutGenerator(&%s,%d,",
15878       name.c_str(), howOften);
15879     // change name
15880     name[0] = static_cast< char >(toupper(name[0]));
15881     fprintf(fp, "\"%s\",%s,%s,%s,%d,%d,%d);\n",
15882       name.c_str(), normal ? "true" : "false",
15883       atSolution ? "true" : "false",
15884       whenInfeasible ? "true" : "false",
15885       howOftenInSub, whatDepth, whatDepthInSub);
15886     fprintf(fp, "3  cbcModel->cutGenerator(%d)->setTiming(%s);\n",
15887       i, timing ? "true" : "false");
15888     fprintf(fp, "3  \n");
15889   }
15890   for (i = 0; i < numberHeuristics_; i++) {
15891     CbcHeuristic *heuristic = heuristic_[i];
15892     heuristic->generateCpp(fp);
15893     fprintf(fp, "3  \n");
15894   }
15895   if (nodeCompare_)
15896     nodeCompare_->generateCpp(fp);
15897   tree_->generateCpp(fp);
15898   CbcModel defaultModel;
15899   CbcModel *other = &defaultModel;
15900   int iValue1, iValue2;
15901   double dValue1, dValue2;
15902   iValue1 = this->getMaximumNodes();
15903   iValue2 = other->getMaximumNodes();
15904   fprintf(fp, "%d  int save_getMaximumNodes = cbcModel->getMaximumNodes();\n", iValue1 == iValue2 ? 2 : 1);
15905   fprintf(fp, "%d  cbcModel->setMaximumNodes(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15906   fprintf(fp, "%d  cbcModel->setMaximumNodes(save_getMaximumNodes);\n", iValue1 == iValue2 ? 7 : 6);
15907   iValue1 = this->getMaximumSolutions();
15908   iValue2 = other->getMaximumSolutions();
15909   fprintf(fp, "%d  int save_getMaximumSolutions = cbcModel->getMaximumSolutions();\n", iValue1 == iValue2 ? 2 : 1);
15910   fprintf(fp, "%d  cbcModel->setMaximumSolutions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15911   fprintf(fp, "%d  cbcModel->setMaximumSolutions(save_getMaximumSolutions);\n", iValue1 == iValue2 ? 7 : 6);
15912   iValue1 = this->numberStrong();
15913   iValue2 = other->numberStrong();
15914   fprintf(fp, "%d  int save_numberStrong = cbcModel->numberStrong();\n", iValue1 == iValue2 ? 2 : 1);
15915   fprintf(fp, "%d  cbcModel->setNumberStrong(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15916   fprintf(fp, "%d  cbcModel->setNumberStrong(save_numberStrong);\n", iValue1 == iValue2 ? 7 : 6);
15917   iValue1 = this->numberBeforeTrust();
15918   iValue2 = other->numberBeforeTrust();
15919   fprintf(fp, "%d  int save_numberBeforeTrust = cbcModel->numberBeforeTrust();\n", iValue1 == iValue2 ? 2 : 1);
15920   fprintf(fp, "%d  cbcModel->setNumberBeforeTrust(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15921   fprintf(fp, "%d  cbcModel->setNumberBeforeTrust(save_numberBeforeTrust);\n", iValue1 == iValue2 ? 7 : 6);
15922   iValue1 = this->numberPenalties();
15923   iValue2 = other->numberPenalties();
15924   fprintf(fp, "%d  int save_numberPenalties = cbcModel->numberPenalties();\n", iValue1 == iValue2 ? 2 : 1);
15925   fprintf(fp, "%d  cbcModel->setNumberPenalties(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15926   fprintf(fp, "%d  cbcModel->setNumberPenalties(save_numberPenalties);\n", iValue1 == iValue2 ? 7 : 6);
15927   iValue1 = this->howOftenGlobalScan();
15928   iValue2 = other->howOftenGlobalScan();
15929   fprintf(fp, "%d  int save_howOftenGlobalScan = cbcModel->howOftenGlobalScan();\n", iValue1 == iValue2 ? 2 : 1);
15930   fprintf(fp, "%d  cbcModel->setHowOftenGlobalScan(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15931   fprintf(fp, "%d  cbcModel->setHowOftenGlobalScan(save_howOftenGlobalScan);\n", iValue1 == iValue2 ? 7 : 6);
15932   iValue1 = this->printFrequency();
15933   iValue2 = other->printFrequency();
15934   fprintf(fp, "%d  int save_printFrequency = cbcModel->printFrequency();\n", iValue1 == iValue2 ? 2 : 1);
15935   fprintf(fp, "%d  cbcModel->setPrintFrequency(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15936   fprintf(fp, "%d  cbcModel->setPrintFrequency(save_printFrequency);\n", iValue1 == iValue2 ? 7 : 6);
15937   iValue1 = this->getPrintingMode();
15938   iValue2 = other->getPrintingMode();
15939   fprintf(fp, "%d  int save_printingMode = cbcModel->getPrintingMode();\n", iValue1 == iValue2 ? 2 : 1);
15940   fprintf(fp, "%d  cbcModel->setPrintingMode(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15941   fprintf(fp, "%d  cbcModel->setPrintingMode(save_printingMode);\n", iValue1 == iValue2 ? 7 : 6);
15942   iValue1 = this->searchStrategy();
15943   iValue2 = other->searchStrategy();
15944   fprintf(fp, "%d  int save_searchStrategy = cbcModel->searchStrategy();\n", iValue1 == iValue2 ? 2 : 1);
15945   fprintf(fp, "%d  cbcModel->setSearchStrategy(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15946   fprintf(fp, "%d  cbcModel->setSearchStrategy(save_searchStrategy);\n", iValue1 == iValue2 ? 7 : 6);
15947   iValue1 = this->specialOptions();
15948   iValue2 = other->specialOptions();
15949   fprintf(fp, "%d  int save_cbcSpecialOptions = cbcModel->specialOptions();\n", iValue1 == iValue2 ? 2 : 1);
15950   fprintf(fp, "%d  cbcModel->setSpecialOptions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15951   fprintf(fp, "%d  cbcModel->setSpecialOptions(save_cbcSpecialOptions);\n", iValue1 == iValue2 ? 7 : 6);
15952   iValue1 = this->messageHandler()->logLevel();
15953   iValue2 = other->messageHandler()->logLevel();
15954   fprintf(fp, "%d  int save_cbcMessageLevel = cbcModel->messageHandler()->logLevel();\n", iValue1 == iValue2 ? 2 : 1);
15955   fprintf(fp, "%d  cbcModel->messageHandler()->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15956   fprintf(fp, "%d  cbcModel->messageHandler()->setLogLevel(save_cbcMessageLevel);\n", iValue1 == iValue2 ? 7 : 6);
15957   iValue1 = this->getMaximumCutPassesAtRoot();
15958   iValue2 = other->getMaximumCutPassesAtRoot();
15959   fprintf(fp, "%d  int save_getMaximumCutPassesAtRoot = cbcModel->getMaximumCutPassesAtRoot();\n", iValue1 == iValue2 ? 2 : 1);
15960   fprintf(fp, "%d  cbcModel->setMaximumCutPassesAtRoot(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15961   fprintf(fp, "%d  cbcModel->setMaximumCutPassesAtRoot(save_getMaximumCutPassesAtRoot);\n", iValue1 == iValue2 ? 7 : 6);
15962   iValue1 = this->getMaximumCutPasses();
15963   iValue2 = other->getMaximumCutPasses();
15964   fprintf(fp, "%d  int save_getMaximumCutPasses = cbcModel->getMaximumCutPasses();\n", iValue1 == iValue2 ? 2 : 1);
15965   fprintf(fp, "%d  cbcModel->setMaximumCutPasses(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15966   fprintf(fp, "%d  cbcModel->setMaximumCutPasses(save_getMaximumCutPasses);\n", iValue1 == iValue2 ? 7 : 6);
15967   iValue1 = this->getPreferredWay();
15968   iValue2 = other->getPreferredWay();
15969   fprintf(fp, "%d  int save_getPreferredWay = cbcModel->getPreferredWay();\n", iValue1 == iValue2 ? 2 : 1);
15970   fprintf(fp, "%d  cbcModel->setPreferredWay(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
15971   fprintf(fp, "%d  cbcModel->setPreferredWay(save_getPreferredWay);\n", iValue1 == iValue2 ? 7 : 6);
15972   dValue1 = this->getMinimumDrop();
15973   dValue2 = other->getMinimumDrop();
15974   fprintf(fp, "%d  double save_getMinimumDrop = cbcModel->getMinimumDrop();\n", dValue1 == dValue2 ? 2 : 1);
15975   fprintf(fp, "%d  cbcModel->setMinimumDrop(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
15976   fprintf(fp, "%d  cbcModel->setMinimumDrop(save_getMinimumDrop);\n", dValue1 == dValue2 ? 7 : 6);
15977   dValue1 = this->getIntegerTolerance();
15978   dValue2 = other->getIntegerTolerance();
15979   fprintf(fp, "%d  double save_getIntegerTolerance = cbcModel->getIntegerTolerance();\n", dValue1 == dValue2 ? 2 : 1);
15980   fprintf(fp, "%d  cbcModel->setIntegerTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
15981   fprintf(fp, "%d  cbcModel->setIntegerTolerance(save_getIntegerTolerance);\n", dValue1 == dValue2 ? 7 : 6);
15982   dValue1 = this->getInfeasibilityWeight();
15983   dValue2 = other->getInfeasibilityWeight();
15984   fprintf(fp, "%d  double save_getInfeasibilityWeight = cbcModel->getInfeasibilityWeight();\n", dValue1 == dValue2 ? 2 : 1);
15985   fprintf(fp, "%d  cbcModel->setInfeasibilityWeight(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
15986   fprintf(fp, "%d  cbcModel->setInfeasibilityWeight(save_getInfeasibilityWeight);\n", dValue1 == dValue2 ? 7 : 6);
15987   dValue1 = this->getCutoffIncrement();
15988   dValue2 = other->getCutoffIncrement();
15989   fprintf(fp, "%d  double save_getCutoffIncrement = cbcModel->getCutoffIncrement();\n", dValue1 == dValue2 ? 2 : 1);
15990   fprintf(fp, "%d  cbcModel->setCutoffIncrement(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
15991   fprintf(fp, "%d  cbcModel->setCutoffIncrement(save_getCutoffIncrement);\n", dValue1 == dValue2 ? 7 : 6);
15992   dValue1 = this->getAllowableGap();
15993   dValue2 = other->getAllowableGap();
15994   fprintf(fp, "%d  double save_getAllowableGap = cbcModel->getAllowableGap();\n", dValue1 == dValue2 ? 2 : 1);
15995   fprintf(fp, "%d  cbcModel->setAllowableGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
15996   fprintf(fp, "%d  cbcModel->setAllowableGap(save_getAllowableGap);\n", dValue1 == dValue2 ? 7 : 6);
15997   dValue1 = this->getAllowableFractionGap();
15998   dValue2 = other->getAllowableFractionGap();
15999   fprintf(fp, "%d  double save_getAllowableFractionGap = cbcModel->getAllowableFractionGap();\n", dValue1 == dValue2 ? 2 : 1);
16000   fprintf(fp, "%d  cbcModel->setAllowableFractionGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
16001   fprintf(fp, "%d  cbcModel->setAllowableFractionGap(save_getAllowableFractionGap);\n", dValue1 == dValue2 ? 7 : 6);
16002   dValue1 = this->getMaximumSeconds();
16003   dValue2 = other->getMaximumSeconds();
16004   fprintf(fp, "%d  double save_cbcMaximumSeconds = cbcModel->getMaximumSeconds();\n", dValue1 == dValue2 ? 2 : 1);
16005   fprintf(fp, "%d  cbcModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
16006   fprintf(fp, "%d  cbcModel->setMaximumSeconds(save_cbcMaximumSeconds);\n", dValue1 == dValue2 ? 7 : 6);
16007 }
16008 // So we can use osiObject or CbcObject during transition
16009 void getIntegerInformation(const OsiObject *object, double &originalLower,
16010   double &originalUpper)
16011 {
16012   const CbcSimpleInteger *integerObject = dynamic_cast< const CbcSimpleInteger * >(object);
16013   if (integerObject) {
16014     // get original bounds
16015     originalLower = integerObject->originalLowerBound();
16016     originalUpper = integerObject->originalUpperBound();
16017   } else {
16018     const OsiSimpleInteger *integerObject = dynamic_cast< const OsiSimpleInteger * >(object);
16019     assert(integerObject);
16020     // get original bounds
16021     originalLower = integerObject->originalLowerBound();
16022     originalUpper = integerObject->originalUpperBound();
16023   }
16024 }
16025 // Set original columns as created by preprocessing
16026 void CbcModel::setOriginalColumns(const int *originalColumns, int numberGood)
16027 {
16028   int numberColumns = getNumCols();
16029   delete[] originalColumns_;
16030   originalColumns_ = new int[numberColumns];
16031   int numberCopy = CoinMin(numberColumns, numberGood);
16032   memcpy(originalColumns_, originalColumns, numberCopy * sizeof(int));
16033   for (int i = numberCopy; i < numberColumns; i++)
16034     originalColumns_[i] = -1;
16035 }
16036 // Set the cut modifier method
16037 void CbcModel::setCutModifier(CbcCutModifier *modifier)
16038 {
16039   delete cutModifier_;
16040   cutModifier_ = modifier->clone();
16041 }
16042 /* Set the cut modifier method
16043  */
16044 void CbcModel::setCutModifier(CbcCutModifier &modifier)
16045 {
16046   delete cutModifier_;
16047   cutModifier_ = modifier.clone();
16048 }
16049 /* Do one node - broken out for clarity?
16050    also for parallel (when baseModel!=this)
16051    Returns 1 if solution found
16052    node NULL on return if no branches left
16053    newNode NULL if no new node created
16054 */
16055 int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode)
16056 {
16057   int foundSolution = 0;
16058   int saveNumberCutGenerators = numberCutGenerators_;
16059   if ((moreSpecialOptions_ & 33554432) != 0 && (specialOptions_ & 2048) == 0) {
16060     if (node && (node->depth() == -2 || node->depth() == 4))
16061       numberCutGenerators_ = 0; // so can dive and branch
16062   }
16063   currentNode_ = node; // so can be accessed elsewhere
16064   double bestObjective = bestObjective_;
16065   numberUpdateItems_ = 0;
16066   // Say not on optimal path
16067   bool onOptimalPath = false;
16068 #ifdef CHECK_NODE
16069   printf("Node %x popped from tree - %d left, %d count\n", node,
16070     node->nodeInfo()->numberBranchesLeft(),
16071     node->nodeInfo()->numberPointingToThis());
16072   printf("\tdepth = %d, z =  %g, unsat = %d\n", //var = %d.\n",
16073     node->depth(), node->objectiveValue(),
16074     node->numberUnsatisfied());
16075   //node->columnNumber()) ;
16076 #endif
16077 
16078   /*
16079       Rebuild the subproblem for this node:	 Call addCuts() to adjust the model
16080       to recreate the subproblem for this node (set proper variable bounds, add
16081       cuts, create a basis).  This may result in the problem being fathomed by
16082       bound or infeasibility. Returns 1 if node is fathomed.
16083       Execute the current arm of the branch: If the problem survives, save the
16084       resulting variable bounds and call branch() to modify variable bounds
16085       according to the current arm of the branching object. If we're processing
16086       the final arm of the branching object, flag the node for removal from the
16087       live set.
16088     */
16089   /*
16090       Used to generate bound edits for CbcPartialNodeInfo.
16091     */
16092   int numberColumns = getNumCols();
16093   double *lowerBefore = new double[numberColumns];
16094   double *upperBefore = new double[numberColumns];
16095   if (parallelMode() >= 0)
16096     newNode = NULL;
16097   else
16098     newNode = new CbcNode();
16099   bool feasible = true;
16100   CoinWarmStartBasis *lastws = new CoinWarmStartBasis();
16101   lockThread();
16102   // point to genuine ones
16103   //int save1 = maximumNumberCuts_;
16104   //maximumNumberCuts_ = baseModel->maximumNumberCuts_;
16105   //addedCuts_ = baseModel->addedCuts_;
16106   if (parallelMode() >= 0) {
16107     maximumDepth_ = baseModel->maximumDepth_;
16108     walkback_ = baseModel->walkback_;
16109     lastNodeInfo_ = baseModel->lastNodeInfo_;
16110     lastNumberCuts_ = baseModel->lastNumberCuts_;
16111     lastCut_ = baseModel->lastCut_;
16112     lastNumberCuts2_ = baseModel->lastNumberCuts2_;
16113   }
16114   int save2 = maximumDepth_;
16115   int retCode = addCuts(node, lastws);
16116 #ifdef SWITCH_VARIABLES
16117   fixAssociated(solver_, 0);
16118 #endif
16119   //if (save1<maximumNumberCuts_) {
16120   // increased
16121   //baseModel->maximumNumberCuts_ = maximumNumberCuts_;
16122   //baseModel->addedCuts_ = addedCuts_;
16123   //}
16124   if (parallelMode() >= 0 && save2 < maximumDepth_) {
16125     // increased
16126     baseModel->maximumDepth_ = maximumDepth_;
16127     baseModel->walkback_ = walkback_;
16128     baseModel->lastNodeInfo_ = lastNodeInfo_;
16129     baseModel->lastNumberCuts_ = lastNumberCuts_;
16130     baseModel->lastCut_ = lastCut_;
16131     baseModel->lastNumberCuts2_ = lastNumberCuts2_;
16132   }
16133   int branchesLeft = 0;
16134   if (!retCode) {
16135     unlockThread();
16136     int i;
16137     const double *lower = getColLower();
16138     const double *upper = getColUpper();
16139     for (i = 0; i < numberColumns; i++) {
16140       lowerBefore[i] = lower[i];
16141       upperBefore[i] = upper[i];
16142     }
16143     if ((solverCharacteristics_->extraCharacteristics() & 2) != 0) {
16144       solverCharacteristics_->setBeforeLower(lowerBefore);
16145       solverCharacteristics_->setBeforeUpper(upperBefore);
16146     }
16147     lockThread();
16148     assert(node->objectiveValue() < 1.0e200);
16149     if (messageHandler()->logLevel() > 2)
16150       node->modifiableBranchingObject()->print();
16151     if (branchingMethod_ && branchingMethod_->chooseMethod()) {
16152       branchesLeft = node->branch(solver_); // new way
16153     } else {
16154       // old way so need to cheat
16155       OsiBranchingObject *branch2 = node->modifiableBranchingObject();
16156 #ifndef NDEBUG
16157       CbcBranchingObject *branch = dynamic_cast< CbcBranchingObject * >(branch2);
16158       assert(branch);
16159 #else
16160       CbcBranchingObject *branch = static_cast< CbcBranchingObject * >(branch2);
16161 #endif
16162 #if 1
16163       branch->setModel(this);
16164       branchesLeft = node->branch(NULL); // old way
16165 #else
16166       branchesLeft = node->branch(solver_);
16167 #endif
16168       if (parallelMode() >= 0)
16169         branch->setModel(baseModel);
16170     }
16171     assert(branchesLeft == node->nodeInfo()->numberBranchesLeft());
16172     if (parallelMode() > 0) {
16173       assert(masterThread_);
16174       assert(node->nodeInfo());
16175       node->nodeInfo()->increment();
16176       unlockThread();
16177     }
16178     if ((specialOptions_ & 1) != 0) {
16179       /*
16180             This doesn't work as intended --- getRowCutDebugger will return null
16181             unless the current feasible solution region includes the optimal solution
16182             that RowCutDebugger knows. There's no way to tell inactive from off the
16183             optimal path.
16184             */
16185       const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
16186       if (debugger) {
16187         onOptimalPath = true;
16188         printf("On optimal path\n");
16189       }
16190     }
16191 
16192     /*
16193           Reoptimize, possibly generating cuts and/or using heuristics to find
16194           solutions.  Cut reference counts are unaffected unless we lose feasibility,
16195           in which case solveWithCuts() will make the adjustment.
16196         */
16197     phase_ = 2;
16198     OsiCuts cuts;
16199     int saveNumber = numberIterations_;
16200     if (solverCharacteristics_->solutionAddsCuts()) {
16201       int returnCode = resolve(node ? node->nodeInfo() : NULL, 1);
16202       feasible = returnCode != 0;
16203       if (feasible) {
16204         int iObject;
16205         int numberUnsatisfied = 0;
16206         memcpy(currentSolution_, solver_->getColSolution(),
16207           numberColumns * sizeof(double));
16208         // point to useful information
16209         OsiBranchingInformation usefulInfo = usefulInformation();
16210 
16211         for (iObject = 0; iObject < numberObjects_; iObject++) {
16212           double infeasibility = object_[iObject]->checkInfeasibility(&usefulInfo);
16213           if (infeasibility)
16214             numberUnsatisfied++;
16215         }
16216         if (returnCode > 0) {
16217           if (numberUnsatisfied) {
16218             feasible = solveWithCuts(cuts, maximumCutPasses_, node);
16219           } else {
16220             // may generate cuts and turn the solution
16221             //to an infeasible one
16222             feasible = solveWithCuts(cuts, 1,
16223               node);
16224           }
16225         }
16226         // check extra info on feasibility
16227         if (!solverCharacteristics_->mipFeasible()) {
16228           feasible = false;
16229           solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
16230         }
16231       }
16232     } else {
16233       // normal
16234       if (false) {
16235         const double *lower = solver_->getColLower();
16236         const double *upper = solver_->getColUpper();
16237         printf("STATE before solve\n");
16238         for (int i = 0; i < 100; i++)
16239           if (lower[i] || !upper[i])
16240             printf("%d fixed to %g\n", i, lower[i]);
16241       }
16242 #ifdef COIN_HAS_CLP
16243       OsiClpSolverInterface *clpSolver
16244         = dynamic_cast< OsiClpSolverInterface * >(solver_);
16245       if ((clpSolver || (specialOptions_ & 16384) != 0) && fastNodeDepth_ < -1
16246         && (specialOptions_ & 2048) == 0) {
16247 #define FATHOM_BIAS -2
16248         if (numberNodes_ == 1) {
16249           int numberNodesBeforeFathom = 500;
16250           if (fastNodeDepth_ < -1000001) {
16251             numberNodesBeforeFathom = (-fastNodeDepth_) / 1000000;
16252             numberNodesBeforeFathom = 250 * numberNodesBeforeFathom;
16253           }
16254 #ifdef COIN_DEVELOP
16255           int fastNodeDepth1 = -fastNodeDepth_ % 1000000;
16256           printf("initial depth %d after %d nodes\n",
16257             FATHOM_BIAS + fastNodeDepth1, numberNodesBeforeFathom);
16258 #endif
16259         }
16260         //#endif
16261         ClpNodeStuff stuff;
16262         ClpNodeStuff *info = &stuff;
16263         /*
16264                   Used to generate bound edits for CbcPartialNodeInfo.
16265                 */
16266         //double * lowerBefore = NULL;
16267         //double * upperBefore = NULL;
16268         int fastNodeDepth1 = -fastNodeDepth_ % 1000000;
16269         int numberNodesBeforeFathom = 500;
16270         if (fastNodeDepth_ < -1000001) {
16271           numberNodesBeforeFathom = (-fastNodeDepth_) / 1000000;
16272           numberNodesBeforeFathom = 100 * numberNodesBeforeFathom;
16273         }
16274         int go_fathom = FATHOM_BIAS + fastNodeDepth1;
16275         if ((specialOptions_ & 16384) != 0)
16276           numberNodesBeforeFathom = 0;
16277         if (node->depth() >= go_fathom && (specialOptions_ & 2048) == 0
16278           //if (node->depth()>=FATHOM_BIAS-fastNodeDepth_&&!parentModel_
16279           && numberNodes_ >= numberNodesBeforeFathom && !hotstartSolution_) {
16280 #ifndef COIN_HAS_CPX
16281           specialOptions_ &= ~16384;
16282 #endif
16283           if ((specialOptions_ & 16384) == 0) {
16284             info->integerTolerance_ = getIntegerTolerance();
16285             info->integerIncrement_ = getCutoffIncrement();
16286             info->numberBeforeTrust_ = numberBeforeTrust_;
16287             info->stateOfSearch_ = 1;
16288             if (numberSolutions_ > 0) {
16289               info->stateOfSearch_ = 3;
16290             }
16291             if (numberNodes_ > 2 * numberObjects_ + 1000) {
16292               info->stateOfSearch_ = 4;
16293             }
16294             // Compute "small" change in branch
16295             int nBranches = intParam_[CbcNumberBranches];
16296             if (nBranches) {
16297               double average = dblParam_[CbcSumChange] / static_cast< double >(nBranches);
16298               info->smallChange_ = CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]);
16299               info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8);
16300             } else {
16301               info->smallChange_ = 1.0e-8;
16302             }
16303             double *down = new double[numberIntegers_];
16304             double *up = new double[numberIntegers_];
16305             int *priority = new int[numberIntegers_];
16306             int *numberDown = new int[numberIntegers_];
16307             int *numberUp = new int[numberIntegers_];
16308             int *numberDownInfeasible = new int[numberIntegers_];
16309             int *numberUpInfeasible = new int[numberIntegers_];
16310             fillPseudoCosts(down, up, priority, numberDown, numberUp,
16311               numberDownInfeasible, numberUpInfeasible);
16312             // See if all priorities same
16313             bool allSame = true;
16314             int kPriority = priority[0];
16315             for (int i = 1; i < numberIntegers_; i++) {
16316               if (kPriority != priority[i]) {
16317                 allSame = false;
16318                 break;
16319               }
16320             }
16321             ClpSimplex *simplex = clpSolver->getModelPtr();
16322             double *saveLower = CoinCopyOfArray(solver_->getColLower(), numberColumns);
16323             double *saveUpper = CoinCopyOfArray(solver_->getColUpper(), numberColumns);
16324             if (allSame && false) {
16325               // change priorities on general
16326               const double *lower = simplex->columnLower();
16327               const double *upper = simplex->columnUpper();
16328               for (int i = 0; i < numberIntegers_; i++) {
16329                 int iColumn = integerVariable_[i];
16330                 if (upper[iColumn] > lower[iColumn] + 1.1)
16331                   priority[i] = kPriority + 1;
16332               }
16333             }
16334             info->fillPseudoCosts(down, up, priority, numberDown, numberUp,
16335               numberDownInfeasible,
16336               numberUpInfeasible, numberIntegers_);
16337             info->presolveType_ = 1;
16338             // for reduced costs and duals
16339             info->solverOptions_ |= 7;
16340             delete[] down;
16341             delete[] up;
16342             delete[] numberDown;
16343             delete[] priority;
16344             delete[] numberUp;
16345             delete[] numberDownInfeasible;
16346             delete[] numberUpInfeasible;
16347             bool takeHint;
16348             OsiHintStrength strength;
16349             solver_->getHintParam(OsiDoReducePrint, takeHint, strength);
16350             //printf("mod cutoff %g solver %g offset %g\n",
16351             //   getCutoff(),simplex->dualObjectiveLimit(),simplex->objectiveOffset());
16352             int saveLevel = simplex->logLevel();
16353             if (strength != OsiHintIgnore && takeHint && saveLevel == 1)
16354               simplex->setLogLevel(0);
16355             clpSolver->setBasis();
16356             int perturbation = simplex->perturbation();
16357             if ((specialOptions_ & 131072) != 0) {
16358               //assert (perturbation == 100);
16359               simplex->setPerturbation(50);
16360             }
16361             int saveMoreOptions = simplex->moreSpecialOptions();
16362             int flags = (moreSpecialOptions_ >> 18) & 3;
16363             simplex->setMoreSpecialOptions(saveMoreOptions | flags << 11);
16364 #ifndef NO_FATHOM_PRINT
16365             info->startingDepth_ = node->depth();
16366             info->nodeCalled_ = numberNodes_;
16367             info->handler_ = handler_;
16368 #endif
16369             feasible = simplex->fathom(info) != 0;
16370             simplex->setMoreSpecialOptions(saveMoreOptions);
16371             simplex->setPerturbation(perturbation);
16372             incrementExtra(info->numberNodesExplored_,
16373               info->numberIterations_);
16374             if (feasible && false) { // can mess up cuts
16375               double objValue = simplex->objectiveValue();
16376               feasible = solveWithCuts(cuts, 1, node);
16377               if (!feasible) {
16378                 if ((specialOptions_ & 1) != 0)
16379                   printf("small was feasible %g now infeasible! - depths %d %d\n",
16380                     objValue, node->depth(), fastNodeDepth_);
16381                 // switch off
16382                 info->nNodes_ = -99;
16383                 solver_->setColLower(saveLower);
16384                 solver_->setColUpper(saveUpper);
16385               }
16386             }
16387             char general[200];
16388             int fathomStatus = info->nNodes_;
16389             if (feasible)
16390               fathomStatus = 1;
16391             sprintf(general, "fathom took %d nodes, %d iterations - status %d",
16392               info->numberNodesExplored_,
16393               info->numberIterations_, fathomStatus);
16394             messageHandler()->message(CBC_FPUMP2,
16395               messages())
16396               << general << CoinMessageEol;
16397             if (info->numberNodesExplored_ > 10000 /* && !feasible */
16398               && (moreSpecialOptions_ & 524288) == 0 && info->nNodes_ >= 0) {
16399               fastNodeDepth_--;
16400 #ifndef NO_FATHOM_PRINT
16401               if ((moreSpecialOptions_ & 262144) != 0)
16402                 handler_->message(CBC_FATHOM_CHANGE, messages_) << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol;
16403 #endif
16404 #if CBC_USEFUL_PRINTING > 0
16405               printf(">10000 - depth now %d so at depth >= %d\n",
16406                 fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_);
16407 #endif
16408             }
16409             if (info->nNodes_ < 0) {
16410               // we gave up
16411               //abort();
16412               fastNodeDepth_ -= (info->nNodes_ == -10) ? 5 : 2;
16413               if (info->nNodes_ == -99)
16414                 fastNodeDepth_ = -1; // switch off
16415 #ifndef NO_FATHOM_PRINT
16416               if ((moreSpecialOptions_ & 262144) != 0)
16417                 handler_->message(CBC_FATHOM_CHANGE, messages_) << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol;
16418 #endif
16419 #if CBC_USEFUL_PRINTING > 0
16420               printf("gave up fastNodeDepth now %d - so at depth >= %d\n",
16421                 fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_);
16422 #endif
16423               if (feasible) {
16424                 // Save bounds round bestSolution
16425                 //double * saveLower = CoinCopyOfArray(solver_->getColLower(),
16426                 //			     numberColumns);
16427                 //double * saveUpper = CoinCopyOfArray(solver_->getColUpper(),
16428                 //			     numberColumns);
16429                 clpSolver->setWarmStart(NULL);
16430                 // try and do solution
16431                 double value = simplex->objectiveValue();
16432                 double *newSolution = CoinCopyOfArray(simplex->primalColumnSolution(),
16433                   numberColumns);
16434                 double saveBest = bestObjective_;
16435                 setBestSolution(CBC_STRONGSOL, value, newSolution);
16436                 delete[] newSolution;
16437                 if (bestObjective_ == saveBest) {
16438                   if ((specialOptions_ & 1) != 0)
16439                     printf("small was feasible now just infeasible! - depths %d %d\n",
16440                       node->depth(), fastNodeDepth_);
16441                   fastNodeDepth_ = -1; // switch off
16442                   solver_->setColLower(saveLower);
16443                   solver_->setColUpper(saveUpper);
16444                 }
16445               }
16446               // say feasible so will redo node
16447               feasible = true;
16448             } else {
16449               if (feasible) {
16450                 clpSolver->setWarmStart(NULL);
16451                 // try and do solution
16452                 double value = simplex->objectiveValue();
16453                 double *newSolution = CoinCopyOfArray(simplex->primalColumnSolution(),
16454                   numberColumns);
16455                 double saveBest = bestObjective_;
16456                 setBestSolution(CBC_STRONGSOL, value, newSolution);
16457                 // in case of inaccuracy
16458                 simplex->setObjectiveValue(CoinMax(bestObjective_,
16459                   simplex->objectiveValue()));
16460                 delete[] newSolution;
16461                 if (bestObjective_ == saveBest) {
16462                   if ((specialOptions_ & 1) != 0)
16463                     printf("small was feasible now just infeasible! - depths %d %d\n",
16464                       node->depth(), fastNodeDepth_);
16465                   fastNodeDepth_ = -1; // switch off
16466                   solver_->setColLower(saveLower);
16467                   solver_->setColUpper(saveUpper);
16468                 }
16469               }
16470               // update pseudo costs
16471               double smallest = 1.0e50;
16472               double largest = -1.0;
16473               for (int i = 0; i < numberIntegers_; i++) {
16474                 CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
16475                 if (!obj)
16476                   continue;
16477                 assert(obj->columnNumber() == integerVariable_[i]);
16478                 if (info->numberUp_[i] > 0) {
16479                   if (info->downPseudo_[i] > largest)
16480                     largest = info->downPseudo_[i];
16481                   if (info->downPseudo_[i] < smallest)
16482                     smallest = info->downPseudo_[i];
16483                   if (info->upPseudo_[i] > largest)
16484                     largest = info->upPseudo_[i];
16485                   if (info->upPseudo_[i] < smallest)
16486                     smallest = info->upPseudo_[i];
16487                   obj->updateAfterMini(info->numberDown_[i],
16488                     info->numberDownInfeasible_[i],
16489                     info->downPseudo_[i],
16490                     info->numberUp_[i],
16491                     info->numberUpInfeasible_[i],
16492                     info->upPseudo_[i]);
16493                 }
16494               }
16495               //printf("range of costs %g to %g\n",smallest,largest);
16496             }
16497             delete[] saveLower;
16498             delete[] saveUpper;
16499             simplex->setLogLevel(saveLevel);
16500 #ifdef COIN_HAS_CPX
16501           } else {
16502             // try cplex
16503             OsiCpxSolverInterface cpxSolver;
16504             double direction = clpSolver->getObjSense();
16505             cpxSolver.setObjSense(direction);
16506             // load up cplex
16507             const CoinPackedMatrix *matrix = clpSolver->getMatrixByCol();
16508             const double *rowLower = clpSolver->getRowLower();
16509             const double *rowUpper = clpSolver->getRowUpper();
16510             const double *columnLower = clpSolver->getColLower();
16511             const double *columnUpper = clpSolver->getColUpper();
16512             const double *objective = clpSolver->getObjCoefficients();
16513             cpxSolver.loadProblem(*matrix, columnLower, columnUpper,
16514               objective, rowLower, rowUpper);
16515             double *setSol = new double[numberIntegers_];
16516             int *setVar = new int[numberIntegers_];
16517             // cplex doesn't know about objective offset
16518             double offset = clpSolver->getModelPtr()->objectiveOffset();
16519             for (int i = 0; i < numberIntegers_; i++) {
16520               int iColumn = integerVariable_[i];
16521               cpxSolver.setInteger(iColumn);
16522               if (bestSolution_) {
16523                 setSol[i] = bestSolution_[iColumn];
16524                 setVar[i] = iColumn;
16525               }
16526             }
16527             CPXENVptr env = cpxSolver.getEnvironmentPtr();
16528             CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
16529             cpxSolver.switchToMIP();
16530             if (bestSolution_) {
16531 #if 0
16532                             CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol);
16533 #else
16534               int zero = 0;
16535               CPXaddmipstarts(env, lpPtr, 1, numberIntegers_, &zero, setVar, setSol, NULL, NULL);
16536 #endif
16537             }
16538             if (getCutoff() < 1.0e50) {
16539               double useCutoff = getCutoff() + offset;
16540               if (bestObjective_ < 1.0e50)
16541                 useCutoff = bestObjective_ + offset + 1.0e-7;
16542               cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff * direction);
16543               if (direction > 0.0)
16544                 CPXsetdblparam(env, CPX_PARAM_CUTUP, useCutoff); // min
16545               else
16546                 CPXsetdblparam(env, CPX_PARAM_CUTLO, useCutoff); // max
16547             }
16548             CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]);
16549             delete[] setSol;
16550             delete[] setVar;
16551             if (offset) {
16552               char printBuffer[200];
16553               sprintf(printBuffer, "Add %g to all Cplex messages for true objective",
16554                 -offset);
16555               messageHandler()->message(CBC_GENERAL, messages())
16556                 << printBuffer << CoinMessageEol;
16557               cpxSolver.setDblParam(OsiObjOffset, offset);
16558             }
16559             cpxSolver.branchAndBound();
16560             numberExtraNodes_ += CPXgetnodecnt(env, lpPtr);
16561             numberExtraIterations_ += CPXgetmipitcnt(env, lpPtr);
16562             double value = cpxSolver.getObjValue() * direction;
16563             if (cpxSolver.isProvenOptimal() && value <= getCutoff()) {
16564               feasible = true;
16565               clpSolver->setWarmStart(NULL);
16566               // try and do solution
16567               double *newSolution = CoinCopyOfArray(cpxSolver.getColSolution(),
16568                 getNumCols());
16569               setBestSolution(CBC_STRONGSOL, value, newSolution);
16570               delete[] newSolution;
16571             }
16572 #endif
16573           }
16574         }
16575       }
16576       if (feasible) {
16577         //int numberPasses = doCutsNow(1) ? maximumCutPasses_ : 0;
16578         int numberPasses = /*doCutsNow(1) ?*/ maximumCutPasses_ /*: 0*/;
16579         feasible = solveWithCuts(cuts, numberPasses, node);
16580       }
16581 #else
16582       feasible = solveWithCuts(cuts, maximumCutPasses_, node);
16583 #endif
16584     }
16585     if ((specialOptions_ & 1) != 0 && onOptimalPath) {
16586       if (solver_->getRowCutDebuggerAlways()->optimalValue() < getCutoff()) {
16587         if (!solver_->getRowCutDebugger() || !feasible) {
16588           // dj fix did something???
16589           solver_->writeMpsNative("infeas2.mps", NULL, NULL, 2);
16590           solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
16591 #ifndef NDEBUG
16592           const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger();
16593 #endif
16594           assert(debugger);
16595           int numberRows0 = continuousSolver_->getNumRows();
16596           int numberRows = solver_->getNumRows();
16597           const CoinPackedMatrix *rowCopy = solver_->getMatrixByRow();
16598           const int *rowLength = rowCopy->getVectorLengths();
16599           const double *elements = rowCopy->getElements();
16600           const int *column = rowCopy->getIndices();
16601           const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
16602           const double *rowLower = solver_->getRowLower();
16603           const double *rowUpper = solver_->getRowUpper();
16604           for (int iRow = numberRows0; iRow < numberRows; iRow++) {
16605             OsiRowCut rc;
16606             rc.setLb(rowLower[iRow]);
16607             rc.setUb(rowUpper[iRow]);
16608             CoinBigIndex start = rowStart[iRow];
16609             rc.setRow(rowLength[iRow], column + start, elements + start, false);
16610             CoinAssert(!debugger->invalidCut(rc));
16611           }
16612           assert(feasible);
16613         }
16614       }
16615     }
16616     if (statistics_) {
16617       assert(numberNodes2_);
16618       assert(statistics_[numberNodes2_ - 1]);
16619       assert(statistics_[numberNodes2_ - 1]->node() == numberNodes2_ - 1);
16620       statistics_[numberNodes2_ - 1]->endOfBranch(numberIterations_ - saveNumber,
16621         feasible ? solver_->getObjValue()
16622                  : COIN_DBL_MAX);
16623     }
16624     /*
16625           Are we still feasible? If so, create a node and do the work to attach a
16626           branching object, reoptimising as needed if chooseBranch() identifies
16627           monotone objects.
16628 
16629           Finally, attach a partial nodeInfo object and store away any cuts that we
16630           created back in solveWithCuts. addCuts() will initialise the reference
16631           counts for these new cuts.
16632 
16633           This next test can be problematic if we've discovered an
16634           alternate equivalent answer and subsequently fathom the solution
16635           known to the row cut debugger due to bounds.
16636         */
16637     if (onOptimalPath) {
16638       bool objLim = solver_->isDualObjectiveLimitReached();
16639       if (!feasible && !objLim) {
16640         if (solver_->getRowCutDebuggerAlways()->optimalValue() < getCutoff()) {
16641           printf("infeas2\n");
16642           solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
16643           solver_->writeMpsNative("infeas.mps", NULL, NULL, 2);
16644           CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart());
16645           solver_->setWarmStart(slack);
16646           delete slack;
16647           solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0);
16648           solver_->initialSolve();
16649           assert(!solver_->isProvenOptimal());
16650           assert(feasible || objLim);
16651         }
16652       }
16653     }
16654     bool checkingNode = false;
16655     if (feasible) {
16656 #ifdef FUNNY_BRANCHING2
16657       // Far too clever
16658       if ((numberThreads_ == -10 || true) && node->numberBranches() == 2) {
16659         // see if any parent branches redundant
16660         // Look at state of "node"
16661         CbcNodeInfo *nodeInfo = node->nodeInfo();
16662         if (nodeInfo) {
16663           // See if any branched variables off bounds
16664           const double *dj = solver_->getReducedCost();
16665           const double *lower = solver_->getColLower();
16666           const double *upper = solver_->getColUpper();
16667           const double *solution = solver_->getColSolution();
16668           int numberColumns = solver_->getNumCols();
16669           double *currentLower = CoinCopyOfArray(lower, numberColumns);
16670           double *currentUpper = CoinCopyOfArray(upper, numberColumns);
16671           char *touched = new char[numberColumns];
16672           memset(touched, 0, numberColumns);
16673           double direction = solver_->getObjSense();
16674           bool canDelete = nodeInfo->numberBranchesLeft() > 0;
16675           //int numberBounds = nodeInfo->numberChangedBounds();
16676           //const int * which = nodeInfo->variables();
16677           //const double * bounds = nodeInfo->newBounds();
16678           const OsiBranchingObject *obj = node->branchingObject();
16679           const CbcIntegerBranchingObject *objectI = dynamic_cast< const CbcIntegerBranchingObject * >(obj);
16680           if (objectI) {
16681             const CbcSimpleInteger *object1 = dynamic_cast< const CbcSimpleInteger * >(objectI->object());
16682             int iColumn1 = -1;
16683             int way1 = 0;
16684             const double *bounds1 = NULL;
16685             bool zeroOne1 = false;
16686             if (object1) {
16687               iColumn1 = object1->columnNumber();
16688               double originalLower1 = object1->originalLowerBound();
16689               double originalUpper1 = object1->originalUpperBound();
16690               // Unset all bounds from parents
16691               CbcPartialNodeInfo *partial = dynamic_cast< CbcPartialNodeInfo * >(nodeInfo);
16692               touched[iColumn1] = 1;
16693               if (partial) {
16694                 /* maybe don't do if obj hasn't changed
16695                                 as then you might get loop
16696                                 at present just 0-1
16697                                 as need to know original bound
16698                                 */
16699                 int n = partial->numberChangedBounds();
16700                 const int *which = partial->variables();
16701                 const double *values = partial->newBounds();
16702                 for (int i = 0; i < n; i++) {
16703                   int variable = which[i];
16704                   int k = variable & 0x3fffffff;
16705                   assert(k != iColumn1);
16706                   if (!touched[k]) {
16707                     if ((variable & 0x80000000) == 0) {
16708                       // lower bound changing
16709                       assert(currentLower[k] == 1.0);
16710                       currentLower[k] = 0.0;
16711                     } else {
16712                       // upper bound changing
16713                       assert(currentUpper[k] == 0.0);
16714                       currentUpper[k] = 1.0;
16715                     }
16716                   }
16717                 }
16718               }
16719               zeroOne1 = originalLower1 == 0.0 && originalUpper1 == 1.0;
16720               way1 = objectI->way();
16721               assert(way1 == -1 || way1 == 1);
16722               int kWay = way1;
16723               //way1 = -way1; // what last branch did
16724               // work out using bounds
16725               if (objectI->downBounds()[1] >= upper[iColumn1] && objectI->downBounds()[0] <= lower[iColumn1])
16726                 way1 = -1;
16727               else
16728                 way1 = 1;
16729               assert(kWay == -way1);
16730               if (way1 < 0) {
16731                 // must have been down branch
16732                 bounds1 = objectI->downBounds();
16733               } else {
16734                 // must have been up branch
16735                 bounds1 = objectI->upBounds();
16736               }
16737               // double check bounds
16738               assert(bounds1[0] <= lower[iColumn1] && bounds1[1] >= upper[iColumn1]);
16739             }
16740             bool inBetween = false;
16741 #ifdef CBC_PRINT2
16742             printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n",
16743               iColumn1, way1, objectI->downBounds()[0], objectI->downBounds()[1],
16744               objectI->upBounds()[0], objectI->upBounds()[1],
16745               lower[iColumn1], upper[iColumn1], solution[iColumn1],
16746               dj[iColumn1], nodeInfo->numberBranchesLeft());
16747 #endif
16748             while (nodeInfo->parent()) {
16749               nodeInfo = nodeInfo->parent();
16750               CbcNode *nodeLook = nodeInfo->mutableOwner();
16751               if (!nodeLook || nodeLook->objectiveValue() == 0.5 * COIN_DBL_MAX)
16752                 continue;
16753               OsiBranchingObject *obj = nodeLook->modifiableBranchingObject();
16754               CbcIntegerBranchingObject *objectI = dynamic_cast< CbcIntegerBranchingObject * >(obj);
16755               //const OsiObject * object2a = obj->originalObject();
16756               //assert (object2a);
16757               const CbcSimpleInteger *object2 = dynamic_cast< const CbcSimpleInteger * >(objectI->object());
16758               if (nodeInfo->numberBranchesLeft() && object2) {
16759                 int iColumn2 = object2->columnNumber();
16760                 double originalLower = object2->originalLowerBound();
16761                 double originalUpper = object2->originalUpperBound();
16762                 bool zeroOne2 = originalLower == 0.0 && originalUpper == 1.0;
16763                 zeroOne1 = true; // temp
16764                 double newUpper = originalUpper;
16765                 double newLower = originalLower;
16766                 //double value = solution[iColumn2];
16767                 double djValue = dj[iColumn2] * direction;
16768                 int way = objectI->way();
16769                 assert(way == -1 || way == 1);
16770                 way = -way; // what last branch did
16771 #ifdef CBC_PRINT2
16772                 printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n",
16773                   iColumn2, way, objectI->downBounds()[0], objectI->downBounds()[1],
16774                   objectI->upBounds()[0], objectI->upBounds()[1],
16775                   lower[iColumn2], upper[iColumn2], solution[iColumn2],
16776                   djValue, nodeInfo->numberBranchesLeft());
16777 #endif
16778                 /*if (objectI->downBounds()[0]==0&&objectI->downBounds()[1]==1&&
16779                                     objectI->upBounds()[0]==0&&objectI->upBounds()[1]==1)
16780                                     assert(lower[iColumn2]<upper[iColumn2]);*/
16781                 if (way < 0) {
16782                   // must have been down branch
16783                   const double *bounds = objectI->downBounds();
16784                   if (djValue > 1.0e-3 || solution[iColumn2] < upper[iColumn2] - 1.0e-5) {
16785                     if (canDelete) {
16786                       //nRedundantDown++;
16787 #ifndef JJF_ONE
16788                       COIN_DETAIL_PRINT(printf("%d redundant branch down with bounds %g, %g current upper %g solution %g dj %g\n",
16789                         iColumn2, bounds[0], bounds[1], upper[iColumn2], solution[iColumn2], djValue));
16790 #endif
16791                       if (bounds[0] == bounds[1] || zeroOne2 || (bounds[0] == lower[iColumn2] && false)) {
16792                         {
16793                           // get rid of node as far as branching
16794                           nodeLook->setObjectiveValue(0.5 * COIN_DBL_MAX);
16795                           objectI->deactivate();
16796                         }
16797                         previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 2);
16798                         solver_->setColUpper(iColumn2, newUpper);
16799                         assert(newLower == lower[iColumn2]);
16800                       } else {
16801                         COIN_DETAIL_PRINT(printf("SKipping\n"));
16802                       }
16803                     } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) {
16804 #ifndef JJF_ONE
16805                       if (true) {
16806                         // add in bounds
16807                         newLower = bounds1[0];
16808                         newUpper = bounds1[1];
16809                         COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n",
16810                           newLower, newUpper, iColumn1, iColumn2));
16811                         int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way());
16812                         if (infeasible) {
16813                           COIN_DETAIL_PRINT(printf("infeasa!\n"));
16814                           // get rid of node as far as branching
16815                           nodeLook->setObjectiveValue(0.5 * COIN_DBL_MAX);
16816                         }
16817                       }
16818 #endif
16819                     }
16820                     //break;
16821                   } else {
16822                     inBetween = true;
16823                   }
16824                 } else {
16825                   // must have been up branch
16826                   const double *bounds = objectI->upBounds();
16827                   if (djValue < -1.0e-3 || solution[iColumn2] > lower[iColumn2] + 1.0e-5) {
16828                     if (canDelete) {
16829                       //nRedundantUp++;
16830 #ifndef JJF_ONE
16831                       COIN_DETAIL_PRINT(printf("%d redundant branch up with bounds %g, %g current lower %g solution %g dj %g\n",
16832                         iColumn2, bounds[0], bounds[1], lower[iColumn2], solution[iColumn2], djValue));
16833 #endif
16834                       if (bounds[0] == bounds[1] || zeroOne2 || (bounds[1] == upper[iColumn2] && false)) {
16835                         {
16836                           // get rid of node as far as branching
16837                           nodeLook->setObjectiveValue(0.5 * COIN_DBL_MAX);
16838                           objectI->deactivate();
16839                         }
16840                         previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 1);
16841                         solver_->setColLower(iColumn2, newLower);
16842                         assert(newUpper == upper[iColumn2]);
16843                       } else {
16844                         COIN_DETAIL_PRINT(printf("SKipping\n"));
16845                       }
16846                     } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) {
16847 #ifndef JJF_ONE
16848                       // add in bounds
16849                       newLower = bounds1[0];
16850                       newUpper = bounds1[1];
16851                       COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n",
16852                         newLower, newUpper, iColumn1, iColumn2));
16853                       int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way());
16854                       if (infeasible) {
16855                         COIN_DETAIL_PRINT(printf("infeasb!\n"));
16856                         // get rid of node as far as branching
16857                         nodeLook->setObjectiveValue(0.5 * COIN_DBL_MAX);
16858                       }
16859 #endif
16860                     }
16861                     // break;
16862                   } else {
16863                     inBetween = true;
16864                   }
16865                 }
16866               } else {
16867                 // odd
16868                 break;
16869               }
16870             }
16871           }
16872           delete[] currentLower;
16873           delete[] currentUpper;
16874         }
16875       }
16876 #endif
16877       if (parallelMode() >= 0)
16878         newNode = new CbcNode();
16879 #if 0
16880 	    // Try diving
16881             if (parallelMode() >= 0 && (specialOptions_&2048) == 0) {
16882 	      // See if any diving heuristics set to do dive+save
16883 	      CbcHeuristicDive * dive=NULL;
16884 	      for (int i = 0; i < numberHeuristics_; i++) {
16885 		CbcHeuristicDive * possible = dynamic_cast<CbcHeuristicDive *>(heuristic_[i]);
16886 		if (possible&&possible->maxSimplexIterations()==COIN_INT_MAX) {
16887 		  // if more than one then rotate later?
16888 		  //if (possible->canHeuristicRun()) {
16889 		  if (node->depth()==0||node->depth()==5) {
16890 		    dive=possible;
16891 		    break;
16892 		  }
16893 		}
16894 	      }
16895 	      if (dive) {
16896 		int numberNodes;
16897 		CbcSubProblem ** nodes=NULL;
16898 		int branchState=dive->fathom(this,numberNodes,nodes);
16899 		if (branchState) {
16900 		  printf("new solution\n");
16901 		}
16902 		if (0) {
16903 		  for (int iNode=0;iNode<numberNodes;iNode++) {
16904 		    //tree_->push(nodes[iNode]) ;
16905 		  }
16906 		  assert (node->nodeInfo());
16907 		  if (node->nodeInfo()->numberBranchesLeft()) {
16908 		    tree_->push(node) ;
16909 		  } else {
16910 		    node->setActive(false);
16911 		  }
16912 		}
16913 		delete [] nodes;
16914 	      }
16915 	    }
16916 	    // end try diving
16917 #endif
16918       // Set objective value (not so obvious if NLP etc)
16919       setObjectiveValue(newNode, node);
16920       int anyAction = -1;
16921       bool resolved = false;
16922       if (newNode->objectiveValue() >= getCutoff()) {
16923         anyAction = -2;
16924       } else { // only allow at most a few passes
16925         int numberPassesLeft = 5;
16926         checkingNode = true;
16927         OsiSolverBranch *branches = NULL;
16928         // point to useful information
16929         anyAction = chooseBranch(newNode, numberPassesLeft, node, cuts, resolved,
16930           lastws, lowerBefore, upperBefore, branches);
16931       }
16932       /*
16933             If we end up infeasible, we can delete the new node immediately. Since this
16934             node won't be needing the cuts we collected, decrement the reference counts.
16935             If we are feasible, then we'll be placing this node into the live set, so
16936             increment the reference count in the current (parent) nodeInfo.
16937             */
16938       lockThread();
16939       if (anyAction == -2) {
16940         if (parallelMode() > 0) {
16941           assert(masterThread_);
16942           assert(node->nodeInfo());
16943           node->nodeInfo()->decrement();
16944           delete newNode;
16945           assert(node->nodeInfo());
16946           node->nodeInfo()->increment();
16947           newNode = NULL;
16948         } else if (parallelMode() == 0) {
16949           delete newNode;
16950           newNode = NULL;
16951         } else {
16952           //assert (newNode->active());
16953           newNode->setActive(false);
16954         }
16955         // say strong doing well
16956         if (checkingNode)
16957           setSpecialOptions(specialOptions_ | 8);
16958         for (i = 0; i < currentNumberCuts_; i++) {
16959           if (addedCuts_[i]) {
16960             if (!addedCuts_[i]->decrement(1)) {
16961               delete addedCuts_[i];
16962             }
16963             addedCuts_[i] = NULL;
16964             //}
16965           }
16966         }
16967       } else {
16968         assert(node->nodeInfo());
16969         if (parallelMode() >= 0)
16970           node->nodeInfo()->increment();
16971         if ((numberNodes_ % 20) == 0) {
16972           // say strong not doing as well
16973           setSpecialOptions(specialOptions_ & ~8);
16974         }
16975       }
16976       unlockThread();
16977     }
16978     /*
16979           At this point, there are three possibilities:
16980           * newNode is live and will require further branching to resolve
16981           (variable() >= 0). Increment the cut reference counts by
16982           numberBranches() to allow for use by children of this node, and
16983           decrement by 1 because we've executed one arm of the branch of our
16984           parent (consuming one reference). Before we push newNode onto the
16985           search tree, try for a heuristic solution.
16986           * We have a solution, in which case newNode is non-null but we have no
16987           branching variable. Decrement the cut counts and save the solution.
16988           * The node was found to be infeasible, in which case it's already been
16989           deleted, and newNode is null.
16990         */
16991     // Set currentNode_ so can be used in handler
16992     currentNode_ = newNode;
16993     if (eventHandler_ && !eventHandler_->event(CbcEventHandler::node)) {
16994       eventHappened_ = true; // exit
16995     }
16996     if (parallelMode() >= 0)
16997       assert(!newNode || newNode->objectiveValue() <= getCutoff());
16998     else
16999       assert(!newNode->active() || newNode->objectiveValue() <= getCutoff());
17000     if (statistics_) {
17001       assert(numberNodes2_);
17002       assert(statistics_[numberNodes2_ - 1]);
17003       assert(statistics_[numberNodes2_ - 1]->node() == numberNodes2_ - 1);
17004       if (newNode && newNode->active())
17005         statistics_[numberNodes2_ - 1]->updateInfeasibility(newNode->numberUnsatisfied());
17006       else
17007         statistics_[numberNodes2_ - 1]->sayInfeasible();
17008     }
17009     lockThread();
17010     bool locked = true;
17011     if (parallelMode() <= 0) {
17012       if (numberUpdateItems_) {
17013         for (i = 0; i < numberUpdateItems_; i++) {
17014           CbcObjectUpdateData *update = updateItems_ + i;
17015           CbcObject *object = dynamic_cast< CbcObject * >(update->object_);
17016 #ifndef NDEBUG
17017           bool found = false;
17018           for (int j = 0; j < numberObjects_; j++) {
17019             if (update->object_ == object_[j]) {
17020               found = true;
17021               break;
17022             }
17023           }
17024           assert(found);
17025 #endif
17026           if (object)
17027             object->updateInformation(*update);
17028         }
17029         numberUpdateItems_ = 0;
17030       }
17031     }
17032     if (newNode)
17033       if (newNode && newNode->active()) {
17034         if (newNode->branchingObject() == NULL) {
17035           const double *solution = solver_->getColSolution();
17036           CbcEventHandler::CbcAction action = dealWithEventHandler(CbcEventHandler::beforeSolution1,
17037             getSolverObjValue(), solution);
17038           if (action == CbcEventHandler::addCuts || solverCharacteristics_->solverType() == 4) {
17039             // need to check if any cuts would do anything
17040             OsiCuts theseCuts;
17041             // reset probing info
17042             //if (probingInfo_)
17043             //probingInfo_->initializeFixing(solver_);
17044             for (int i = 0; i < numberCutGenerators_; i++) {
17045               bool generate = generator_[i]->normal();
17046               // skip if not optimal and should be (maybe a cut generator has fixed variables)
17047               if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
17048                 generate = false;
17049               if (!generator_[i]->mustCallAgain())
17050                 generate = false; // only special cuts
17051               if (generate) {
17052                 generator_[i]->generateCuts(theseCuts, -1, solver_, NULL);
17053                 int numberRowCutsAfter = theseCuts.sizeRowCuts();
17054                 if (numberRowCutsAfter)
17055                   break;
17056               }
17057             }
17058             int numberRowCutsAfter = theseCuts.sizeRowCuts();
17059             if (numberRowCutsAfter || action == CbcEventHandler::addCuts) {
17060               // need dummy branch
17061               newNode->setBranchingObject(new CbcDummyBranchingObject(this));
17062               newNode->nodeInfo()->initializeInfo(1);
17063             }
17064           }
17065         }
17066         if (newNode->branchingObject()) {
17067           handler_->message(CBC_BRANCH, messages_)
17068             << numberNodes_ << newNode->objectiveValue()
17069             << newNode->numberUnsatisfied() << newNode->depth()
17070             << CoinMessageEol;
17071           // Increment cut counts (taking off current)
17072           int numberLeft = newNode->numberBranches();
17073           for (i = 0; i < currentNumberCuts_; i++) {
17074             if (addedCuts_[i]) {
17075 #ifdef CHECK_CUT_COUNTS
17076               printf("Count on cut %x increased by %d\n", addedCuts_[i],
17077                 numberLeft - 1);
17078 #endif
17079               addedCuts_[i]->increment(numberLeft - 1);
17080             }
17081           }
17082           unlockThread();
17083           locked = false;
17084           double estValue = newNode->guessedObjectiveValue();
17085           int found = -1;
17086           double *newSolution = new double[numberColumns];
17087           double heurValue = getCutoff();
17088           int iHeur;
17089           int whereFrom = 3;
17090           // allow more heuristics
17091           currentPassNumber_ = 0;
17092           for (iHeur = 0; iHeur < numberHeuristics_; iHeur++) {
17093             // skip if can't run here
17094             if (!heuristic_[iHeur]->shouldHeurRun(whereFrom))
17095               continue;
17096             double saveValue = heurValue;
17097             int ifSol = heuristic_[iHeur]->solution(heurValue, newSolution);
17098             if (ifSol > 0) {
17099               // new solution found
17100               heuristic_[iHeur]->incrementNumberSolutionsFound();
17101               found = iHeur;
17102               if (parallelMode() > 0) {
17103                 lockThread();
17104                 baseModel->incrementUsed(newSolution);
17105                 unlockThread();
17106               } else {
17107                 lastHeuristic_ = heuristic_[found];
17108 #ifdef HEURISTIC_INFORM
17109                 printf("HEUR %s where %d D\n",
17110                   lastHeuristic_->heuristicName(), whereFrom);
17111 #endif
17112                 setBestSolution(CBC_ROUNDING, heurValue, newSolution);
17113                 foundSolution = 1;
17114                 whereFrom |= 8; // say solution found
17115               }
17116             } else if (ifSol < 0) { // just returning an estimate
17117               estValue = heurValue; //CoinMin(heurValue, estValue) ;
17118               heurValue = saveValue;
17119             }
17120           }
17121           if (found >= 0 && parallelMode() > 0) {
17122             lastHeuristic_ = heuristic_[found];
17123 #if CBC_USEFUL_PRINTING > 1
17124             printf("HEUR %s where %d D\n",
17125               lastHeuristic_->heuristicName(), whereFrom);
17126 #endif
17127             setBestSolution(CBC_ROUNDING, heurValue, newSolution);
17128             foundSolution = 1;
17129           }
17130           delete[] newSolution;
17131           newNode->setGuessedObjectiveValue(estValue);
17132           if (parallelMode() >= 0) {
17133             if (!masterThread_) // only if serial
17134               tree_->push(newNode);
17135           }
17136           if (statistics_) {
17137             if (numberNodes2_ == maximumStatistics_) {
17138               maximumStatistics_ = 2 * maximumStatistics_;
17139               CbcStatistics **temp = new CbcStatistics *[maximumStatistics_];
17140               memset(temp, 0, maximumStatistics_ * sizeof(CbcStatistics *));
17141               memcpy(temp, statistics_, numberNodes2_ * sizeof(CbcStatistics *));
17142               delete[] statistics_;
17143               statistics_ = temp;
17144             }
17145             assert(!statistics_[numberNodes2_]);
17146             statistics_[numberNodes2_] = new CbcStatistics(newNode, this);
17147           }
17148           numberNodes2_++;
17149 #ifdef CHECK_NODE
17150           printf("Node %x pushed on tree c\n", newNode);
17151 #endif
17152         } else {
17153           if (solverCharacteristics_ && //we may be in a non standard bab
17154             solverCharacteristics_->solutionAddsCuts() // we are in some kind of OA based bab.
17155           ) {
17156 
17157             std::cerr << "You should never get here" << std::endl;
17158             throw CoinError("Nodes should not be fathomed on integer infeasibility in this setting",
17159               "branchAndBound", "CbcModel");
17160           }
17161           for (i = 0; i < currentNumberCuts_; i++) {
17162             if (addedCuts_[i]) {
17163               if (!addedCuts_[i]->decrement(1)) {
17164                 delete addedCuts_[i];
17165                 addedCuts_[i] = NULL;
17166               }
17167             }
17168           }
17169           double objectiveValue = newNode->objectiveValue();
17170           lastHeuristic_ = NULL;
17171           // Just possible solver did not know about a solution from another thread!
17172           if (objectiveValue < getCutoff()) {
17173             incrementUsed(solver_->getColSolution());
17174             setBestSolution(CBC_SOLUTION, objectiveValue,
17175               solver_->getColSolution());
17176             // Check if was found
17177             if (bestObjective_ < getCutoff())
17178               foundSolution = 1;
17179           }
17180           //assert(nodeInfo->numberPointingToThis() <= 2) ;
17181           if (parallelMode() >= 0) {
17182             // avoid accidental pruning, if newNode was final branch arm
17183             node->nodeInfo()->increment();
17184             delete newNode;
17185             newNode = NULL;
17186             node->nodeInfo()->decrement();
17187           } else {
17188             newNode->setActive(false);
17189           }
17190         }
17191       }
17192     if (branchesLeft) {
17193       // set nodenumber correctly
17194       if (node->nodeInfo())
17195         node->nodeInfo()->setNodeNumber(numberNodes2_);
17196       if (parallelMode() >= 0) {
17197         if (!masterThread_) // only if serial
17198           tree_->push(node);
17199       }
17200       if (statistics_) {
17201         if (numberNodes2_ == maximumStatistics_) {
17202           maximumStatistics_ = 2 * maximumStatistics_;
17203           CbcStatistics **temp = new CbcStatistics *[maximumStatistics_];
17204           memset(temp, 0, maximumStatistics_ * sizeof(CbcStatistics *));
17205           memcpy(temp, statistics_, numberNodes2_ * sizeof(CbcStatistics *));
17206           delete[] statistics_;
17207           statistics_ = temp;
17208         }
17209         assert(!statistics_[numberNodes2_]);
17210         statistics_[numberNodes2_] = new CbcStatistics(node, this);
17211       }
17212       numberNodes2_++;
17213       //nodeOnTree=true; // back on tree
17214       //deleteNode = false ;
17215 #ifdef CHECK_NODE
17216       printf("Node %x pushed back on tree - %d left, %d count\n", node,
17217         node->nodeInfo()->numberBranchesLeft(),
17218         node->nodeInfo()->numberPointingToThis());
17219 #endif
17220       if (parallelMode() > 0) {
17221         assert(node->nodeInfo());
17222         node->nodeInfo()->decrement();
17223       }
17224     } else {
17225       /*
17226               This node has been completely expanded and can be removed from the live
17227               set.
17228             */
17229       if (parallelMode() > 0) {
17230         assert(masterThread_);
17231         assert(node->nodeInfo());
17232         node->nodeInfo()->decrement();
17233       }
17234       assert(node->nodeInfo());
17235       if (parallelMode() >= 0) {
17236         if (!node->nodeInfo()->numberBranchesLeft())
17237           node->nodeInfo()->allBranchesGone(); // can clean up
17238         deleteNode(node);
17239         node = NULL;
17240       } else {
17241         node->setActive(false);
17242       }
17243     }
17244     if (locked)
17245       unlockThread();
17246   } else {
17247     // add cuts found to be infeasible (on bound)!
17248     COIN_DETAIL_PRINT(printf("found to be infeas! - branches left %d - cutoff %g\n", node->nodeInfo()->numberBranchesLeft(),
17249       getCutoff()));
17250 #ifdef COIN_DETAIL
17251     node->print();
17252 #endif
17253     //abort();
17254     assert(node->nodeInfo());
17255     if (parallelMode() >= 0) {
17256       if (!node->nodeInfo()->numberBranchesLeft())
17257         node->nodeInfo()->allBranchesGone(); // can clean up
17258       delete node;
17259       node = NULL;
17260     } else {
17261       node->setActive(false);
17262     }
17263   }
17264   /*
17265       Delete cuts to get back to the original system.
17266 
17267       I'm thinking this is redundant --- the call to addCuts that conditions entry
17268       to this code block also performs this action.
17269     */
17270 #ifndef JJF_ONE
17271   //if (numberThreads_)
17272   {
17273     int numberToDelete = getNumRows() - numberRowsAtContinuous_;
17274     if (numberToDelete) {
17275       int *delRows = new int[numberToDelete];
17276       int i;
17277       for (i = 0; i < numberToDelete; i++)
17278         delRows[i] = i + numberRowsAtContinuous_;
17279       solver_->deleteRows(numberToDelete, delRows);
17280       delete[] delRows;
17281     }
17282     numberNewCuts_ = 0;
17283   }
17284 #endif
17285   delete lastws;
17286   delete[] lowerBefore;
17287   delete[] upperBefore;
17288   if (bestObjective > bestObjective_)
17289     foundSolution = 2;
17290   if (parallelMode() > 0 && foundSolution) {
17291     lockThread();
17292     // might as well mark all including continuous
17293     int numberColumns = solver_->getNumCols();
17294     for (int i = 0; i < numberColumns; i++) {
17295       baseModel->usedInSolution_[i] += usedInSolution_[i];
17296       usedInSolution_[i] = 0;
17297     }
17298     if (bestObjective_ < baseModel->bestObjective_ && bestObjective_ < baseModel->getCutoff()) {
17299       baseModel->bestObjective_ = bestObjective_;
17300       int numberColumns = solver_->getNumCols();
17301       if (!baseModel->bestSolution_)
17302         baseModel->bestSolution_ = new double[numberColumns];
17303       CoinCopyN(bestSolution_, numberColumns, baseModel->bestSolution_);
17304       baseModel->setCutoff(getCutoff());
17305       baseModel->handler_->message(CBC_ROUNDING, messages_)
17306         << bestObjective_
17307         << "heuristic"
17308         << baseModel->numberIterations_
17309         << baseModel->numberNodes_ << getCurrentSeconds()
17310         << CoinMessageEol;
17311     }
17312     baseModel->numberSolutions_++;
17313     unlockThread();
17314   }
17315   numberCutGenerators_ = saveNumberCutGenerators;
17316   return foundSolution;
17317 }
17318 // Adds an update information object
17319 void CbcModel::addUpdateInformation(const CbcObjectUpdateData &data)
17320 {
17321   if (numberUpdateItems_ == maximumNumberUpdateItems_) {
17322     maximumNumberUpdateItems_ += 10;
17323     CbcObjectUpdateData *temp = new CbcObjectUpdateData[maximumNumberUpdateItems_];
17324     for (int i = 0; i < maximumNumberUpdateItems_ - 10; i++)
17325       temp[i] = updateItems_[i];
17326     delete[] updateItems_;
17327     updateItems_ = temp;
17328   }
17329   updateItems_[numberUpdateItems_++] = data;
17330 }
17331 // Returns bounds just before where - initially original bounds - also sets bounds
17332 void CbcModel::previousBounds(CbcNode *node, CbcNodeInfo *where, int iColumn,
17333   double &lower, double &upper, int force)
17334 {
17335   int i;
17336   int nNode = 0;
17337   CbcNodeInfo *nodeInfo = node->nodeInfo();
17338   int nWhere = -1;
17339 
17340   /*
17341       Accumulate the path from node to the root in walkback_
17342     */
17343   while (nodeInfo) {
17344     //printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo);
17345     walkback_[nNode++] = nodeInfo;
17346     nodeInfo = nodeInfo->parent();
17347     if (nNode == maximumDepth_) {
17348       redoWalkBack();
17349     }
17350     if (nodeInfo == where)
17351       nWhere = nNode;
17352   }
17353   assert(nWhere >= 0);
17354   nWhere = nNode - nWhere;
17355   for (i = 0; i < nWhere; i++) {
17356     --nNode;
17357     walkback_[nNode]->applyBounds(iColumn, lower, upper, 0);
17358   }
17359   // correct bounds
17360   walkback_[nNode]->applyBounds(iColumn, lower, upper, 3);
17361   CbcNode *nodeLook = walkback_[nNode]->mutableOwner();
17362   if (nodeLook) {
17363     OsiBranchingObject *obj = nodeLook->modifiableBranchingObject();
17364     CbcIntegerBranchingObject *objectI = dynamic_cast< CbcIntegerBranchingObject * >(obj);
17365     //const OsiObject * object2 = obj->orig
17366 #ifndef NDEBUG
17367     const CbcSimpleInteger *object2 = dynamic_cast< const CbcSimpleInteger * >(objectI->object());
17368     assert(object2);
17369     assert(iColumn == object2->columnNumber());
17370 #endif
17371     double bounds[2];
17372     bounds[0] = lower;
17373     bounds[1] = upper;
17374     objectI->setDownBounds(bounds);
17375     objectI->setUpBounds(bounds);
17376   }
17377   while (nNode) {
17378     --nNode;
17379     walkback_[nNode]->applyBounds(iColumn, lower, upper, force);
17380 #ifdef JJF_ZERO
17381     CbcNode *nodeLook = walkback_[nNode]->mutableOwner();
17382     if (nodeLook) {
17383       const OsiBranchingObject *obj = nodeLook->branchingObject();
17384       const CbcIntegerBranchingObject *objectI = dynamic_cast< const CbcIntegerBranchingObject * >(obj);
17385       //const OsiObject * object2 = obj->orig
17386       const CbcSimpleInteger *object2 = dynamic_cast< const CbcSimpleInteger * >(objectI->object());
17387       assert(object2);
17388       int iColumn2 = object2->columnNumber();
17389       assert(iColumn != iColumn2);
17390     }
17391 #endif
17392   }
17393 }
17394 /* Return pseudo costs
17395    If not all integers or not pseudo costs - returns all zero
17396    Length of arrays are numberIntegers() and entries
17397       correspond to integerVariable()[i]
17398       User must allocate arrays before call
17399 */
17400 void CbcModel::fillPseudoCosts(double *downCosts, double *upCosts,
17401   int *priority,
17402   int *numberDown, int *numberUp,
17403   int *numberDownInfeasible,
17404   int *numberUpInfeasible) const
17405 {
17406   CoinFillN(downCosts, numberIntegers_, 1.0);
17407   CoinFillN(upCosts, numberIntegers_, 1.0);
17408   if (priority) {
17409     CoinFillN(priority, numberIntegers_, 1000000);
17410   }
17411   if (numberDown) {
17412     CoinFillN(numberDown, numberIntegers_, 1);
17413     CoinFillN(numberUp, numberIntegers_, 1);
17414   }
17415   if (numberDownInfeasible) {
17416     CoinZeroN(numberDownInfeasible, numberIntegers_);
17417     CoinZeroN(numberUpInfeasible, numberIntegers_);
17418   }
17419   int numberColumns = getNumCols();
17420   int *back = new int[numberColumns];
17421   int i;
17422   for (i = 0; i < numberColumns; i++)
17423     back[i] = -1;
17424   for (i = 0; i < numberIntegers_; i++)
17425     back[integerVariable_[i]] = i;
17426 #if CBC_USEFUL_PRINTING > 1
17427   int numberNot = 0;
17428 #endif
17429   for (i = 0; i < numberObjects_; i++) {
17430     CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]);
17431     if (!obj)
17432       continue;
17433 #if CBC_USEFUL_PRINTING > 1
17434     if (obj->numberTimesDown() < numberBeforeTrust_ || obj->numberTimesUp() < numberBeforeTrust_)
17435       numberNot++;
17436 #endif
17437     int iColumn = obj->columnNumber();
17438     iColumn = back[iColumn];
17439     assert(iColumn >= 0);
17440     if (priority)
17441       priority[iColumn] = obj->priority();
17442     downCosts[iColumn] = obj->downDynamicPseudoCost();
17443     upCosts[iColumn] = obj->upDynamicPseudoCost();
17444     if (numberDown) {
17445       numberDown[iColumn] = obj->numberTimesDown();
17446       numberUp[iColumn] = obj->numberTimesUp();
17447     }
17448     if (numberDownInfeasible) {
17449       numberDownInfeasible[iColumn] = obj->numberTimesDownInfeasible();
17450       numberUpInfeasible[iColumn] = obj->numberTimesUpInfeasible();
17451     }
17452   }
17453 #if CBC_USEFUL_PRINTING > 5
17454   if (priority)
17455     printf("Before fathom %d not trusted out of %d\n",
17456       numberNot, numberIntegers_);
17457 #endif
17458   delete[] back;
17459 }
17460 // Redo walkback arrays
17461 void CbcModel::redoWalkBack()
17462 {
17463   int nNode = maximumDepth_;
17464   maximumDepth_ *= 2;
17465   CbcNodeInfo **temp = new CbcNodeInfo *[maximumDepth_];
17466   CbcNodeInfo **temp2 = new CbcNodeInfo *[maximumDepth_];
17467   int *temp3 = new int[maximumDepth_];
17468   for (int i = 0; i < nNode; i++) {
17469     temp[i] = walkback_[i];
17470     temp2[i] = lastNodeInfo_[i];
17471     temp3[i] = lastNumberCuts_[i];
17472   }
17473   delete[] walkback_;
17474   walkback_ = temp;
17475   delete[] lastNodeInfo_;
17476   lastNodeInfo_ = temp2;
17477   delete[] lastNumberCuts_;
17478   lastNumberCuts_ = temp3;
17479 }
17480 /* Return true if we want to do cuts
17481    If allowForTopOfTree zero then just does on multiples of depth
17482    if 1 then allows for doing at top of tree
17483    if 2 then says if cuts allowed anywhere apart from root
17484    if 3 then gives smallest valid depth >shallow
17485 */
17486 bool CbcModel::doCutsNow(int allowForTopOfTree) const
17487 {
17488   int whenCutsUse = whenCuts_;
17489   int alwaysReturnAt10 = whenCutsUse % 100000;
17490   if (whenCutsUse > 0 && alwaysReturnAt10) {
17491     whenCutsUse -= alwaysReturnAt10;
17492     if (currentDepth_ > 10)
17493       return false;
17494   }
17495   //if (currentDepth_>10)
17496   //return false;
17497 #define TRY_IDEA1 2
17498   int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols();
17499 
17500   if (true && (whenCutsUse < 0 || (size <= 500 - 500 * TRY_IDEA1 && allowForTopOfTree != 3))) {
17501     int whenCuts = (size <= 500) ? -1 : 1;
17502     //whenCuts = (size<=500) ? 1 :1;
17503     if (parentModel_)
17504       whenCuts = 1;
17505     //int nodeDepth = currentDepth_-1;
17506     bool doCuts2 = !(currentDepth_ > 11 && (currentDepth_ & 1) == whenCuts);
17507     if (fastNodeDepth_ > 0 && currentDepth_ > 10)
17508       doCuts2 = false;
17509     //printf("when %d node %d depth %d size %d doing cuts %s\n",whenCutsUse,
17510     //   numberNodes_,currentDepth_,size,doCuts2 ? "yes" : "no");
17511     return doCuts2;
17512   }
17513   //if (!parentModel_&&currentDepth_==7)
17514   //printf("q\n");
17515   int top = whenCutsUse / 1000000;
17516   int shallow = top ? (top - 1) : 9;
17517   int when = whenCutsUse - 1000000 * top;
17518 #if TRY_IDEA1
17519   if (when < 15 && when > 1 && size <= 500)
17520     when /= 2;
17521 #endif
17522   if ((when > 15 || (top && top < 5)) && currentDepth_ > when)
17523     when = 100000; // off
17524   bool doCuts = when ? ((currentDepth_ % when) == 0) || (when == 1) : false;
17525   if (allowForTopOfTree == 1 && currentDepth_ <= shallow) {
17526     doCuts = true;
17527   } else if (allowForTopOfTree == 2 && shallow >= 1) {
17528     doCuts = true;
17529 #if TRY_IDEA1 < 2
17530   } else if (allowForTopOfTree == 3 && doCuts) {
17531     // only if first
17532     if (currentDepth_ <= shallow || currentDepth_ - when > shallow)
17533       doCuts = false;
17534 #else
17535   } else if (allowForTopOfTree == 3) {
17536     // only exactly at 10
17537     doCuts = (currentDepth_ == 10);
17538 #endif
17539   }
17540   //if (!doCuts&&currentDepth_&&!parentModel_)
17541   //printf("zzz\n");
17542   return doCuts;
17543 }
17544 // See if can stop on gap
17545 bool CbcModel::canStopOnGap() const
17546 {
17547   bool returnCode = false;
17548   if (bestObjective_ < 1.0e50) {
17549     double testGap = CoinMax(dblParam_[CbcAllowableGap],
17550       CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_))
17551         * dblParam_[CbcAllowableFractionGap]);
17552     returnCode = (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0);
17553   }
17554 #if 0
17555   if (returnCode) {
17556     if (fabs(bestObjective_+1469650.0)<1.0) {
17557       fprintf(stderr,"BAD - cr to continue\n");
17558       fflush(stdout);
17559       char xx;
17560       xx=getc(stdin);
17561     }
17562   }
17563 #endif
17564   return returnCode;
17565 }
17566 // Adjust heuristics based on model
17567 void CbcModel::adjustHeuristics()
17568 {
17569   int numberRows = solver_->getNumRows();
17570   int numberColumns = solver_->getNumCols();
17571   int nTree = CoinMax(10000, 2 * numberRows + numberColumns);
17572   int nRoot = CoinMax(40000, 8 * numberRows + 4 * numberColumns);
17573   for (int i = 0; i < numberHeuristics_; i++) {
17574     CbcHeuristicDive *heuristic = dynamic_cast< CbcHeuristicDive * >(heuristic_[i]);
17575     if (heuristic && heuristic->maxSimplexIterations() != COIN_INT_MAX) {
17576       heuristic->setMaxSimplexIterations(nTree);
17577       heuristic->setMaxSimplexIterationsAtRoot(nRoot);
17578     }
17579   }
17580 }
17581 // Number of saved solutions (including best)
17582 int CbcModel::numberSavedSolutions() const
17583 {
17584   if (!bestSolution_)
17585     return 0;
17586   else
17587     return numberSavedSolutions_ + 1;
17588 }
17589 // Set maximum number of extra saved solutions
17590 void CbcModel::setMaximumSavedSolutions(int value)
17591 {
17592   if (value < maximumSavedSolutions_) {
17593     for (int i = value; i < maximumSavedSolutions_; i++)
17594       delete[] savedSolutions_[i];
17595     maximumSavedSolutions_ = value;
17596     numberSavedSolutions_ = CoinMin(numberSavedSolutions_,
17597       maximumSavedSolutions_);
17598     if (!maximumSavedSolutions_)
17599       delete[] savedSolutions_;
17600   } else if (value > maximumSavedSolutions_) {
17601     double **temp = new double *[value];
17602     int i;
17603     for (i = 0; i < maximumSavedSolutions_; i++)
17604       temp[i] = savedSolutions_[i];
17605     for (; i < value; i++)
17606       temp[i] = NULL;
17607     delete[] savedSolutions_;
17608     maximumSavedSolutions_ = value;
17609     savedSolutions_ = temp;
17610   }
17611 }
17612 // Return a saved solution objective (0==best) - COIN_DBL_MAX if off end
17613 double
17614 CbcModel::savedSolutionObjective(int which) const
17615 {
17616   if (which == 0) {
17617     return bestObjective_;
17618   } else if (which <= numberSavedSolutions_) {
17619     double *sol = savedSolutions_[which - 1];
17620     assert(static_cast< int >(sol[0]) == solver_->getNumCols());
17621     return sol[1];
17622   } else {
17623     return COIN_DBL_MAX;
17624   }
17625 }
17626 // Return a saved solution (0==best) - NULL if off end
17627 const double *
17628 CbcModel::savedSolution(int which) const
17629 {
17630   if (which == 0) {
17631     return bestSolution_;
17632   } else if (which <= numberSavedSolutions_) {
17633     double *sol = savedSolutions_[which - 1];
17634     assert(static_cast< int >(sol[0]) == solver_->getNumCols());
17635     return sol + 2;
17636   } else {
17637     return NULL;
17638   }
17639 }
17640 // Save a solution
17641 void CbcModel::saveExtraSolution(const double *solution, double objectiveValue)
17642 {
17643   double *save = NULL;
17644   if (maximumSavedSolutions_) {
17645     if (!savedSolutions_) {
17646       savedSolutions_ = new double *[maximumSavedSolutions_];
17647       for (int i = 0; i < maximumSavedSolutions_; i++)
17648         savedSolutions_[i] = NULL;
17649     }
17650     int n = solver_->getNumCols();
17651     int k;
17652     for (k = numberSavedSolutions_ - 1; k >= 0; k--) {
17653       double *sol = savedSolutions_[k];
17654       assert(static_cast< int >(sol[0]) == n);
17655       if (objectiveValue > sol[1])
17656         break;
17657     }
17658     k++; // where to put
17659     if (k < maximumSavedSolutions_) {
17660       if (numberSavedSolutions_ == maximumSavedSolutions_) {
17661         save = savedSolutions_[numberSavedSolutions_ - 1];
17662       } else {
17663         save = new double[n + 2];
17664         numberSavedSolutions_++;
17665       }
17666       // move up
17667       for (int j = maximumSavedSolutions_ - 1; j > k; j--)
17668         savedSolutions_[j] = savedSolutions_[j - 1];
17669       savedSolutions_[k] = save;
17670       save[0] = n;
17671       save[1] = objectiveValue;
17672       memcpy(save + 2, solution, n * sizeof(double));
17673     }
17674   }
17675 }
17676 // Save a solution to best and move current to saved
17677 void CbcModel::saveBestSolution(const double *solution, double objectiveValue)
17678 {
17679   int n = solver_->getNumCols();
17680   if (bestSolution_)
17681     saveExtraSolution(bestSolution_, bestObjective_);
17682   else
17683     bestSolution_ = new double[n];
17684   bestObjective_ = objectiveValue;
17685   memcpy(bestSolution_, solution, n * sizeof(double));
17686 }
17687 // Delete best and saved solutions
17688 void CbcModel::deleteSolutions()
17689 {
17690   delete[] bestSolution_;
17691   bestSolution_ = NULL;
17692   for (int i = 0; i < maximumSavedSolutions_; i++) {
17693     delete[] savedSolutions_[i];
17694     savedSolutions_[i] = NULL;
17695   }
17696   numberSavedSolutions_ = 0;
17697 }
17698 // Delete a saved solution and move others up
17699 void CbcModel::deleteSavedSolution(int which)
17700 {
17701   if (which > 0 && which <= numberSavedSolutions_) {
17702     delete[] savedSolutions_[which - 1];
17703     // move up
17704     numberSavedSolutions_--;
17705     for (int j = which - 1; j < numberSavedSolutions_; j++) {
17706       savedSolutions_[j] = savedSolutions_[j + 1];
17707     }
17708     savedSolutions_[numberSavedSolutions_] = NULL;
17709   }
17710 }
17711 #ifdef COIN_HAS_CLP
17712 void CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod)
17713 {
17714   // Possible change of pivot method
17715   if (!savePivotMethod && !parentModel_) {
17716     OsiClpSolverInterface *clpSolver
17717       = dynamic_cast< OsiClpSolverInterface * >(solver_);
17718     if (clpSolver && numberNodes_ >= numberNodes && numberNodes_ < 2 * numberNodes && clpSolver->getNumRows() < 10000) {
17719       if (numberIterations_ < (numberSolves_ + numberNodes_) * 10) {
17720         //if (numberIterations_<numberNodes_*20) {
17721         ClpSimplex *simplex = clpSolver->getModelPtr();
17722         ClpDualRowPivot *pivotMethod = simplex->dualRowPivot();
17723         ClpDualRowDantzig *pivot = dynamic_cast< ClpDualRowDantzig * >(pivotMethod);
17724         if (!pivot) {
17725           savePivotMethod = pivotMethod->clone(true);
17726           ClpDualRowDantzig dantzig;
17727           simplex->setDualRowPivotAlgorithm(dantzig);
17728 #ifdef COIN_DEVELOP
17729           printf("%d node, %d iterations ->Dantzig\n", numberNodes_,
17730             numberIterations_);
17731 #endif
17732 #ifdef CBC_THREAD
17733           if (master_)
17734             master_->setDantzigState();
17735 #endif
17736         }
17737       }
17738     }
17739   }
17740 }
17741 #else
17742 CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod)
17743 {
17744   printf("Need Clp to go to Dantzig\n");
17745   abort();
17746 }
17747 #endif
17748 // Below this is deprecated or at least fairly deprecated
17749 /*
17750    Do Integer Presolve. Returns new model.
17751    I have to work out cleanest way of getting solution to
17752    original problem at end.  So this is very preliminary.
17753 */
17754 CbcModel *
17755 CbcModel::integerPresolve(bool weak)
17756 {
17757   status_ = 0;
17758   // solve LP
17759   //solver_->writeMps("bad");
17760   bool feasible = (resolve(NULL, 3) != 0);
17761 
17762   CbcModel *newModel = NULL;
17763   if (feasible) {
17764 
17765     // get a new model
17766     newModel = new CbcModel(*this);
17767     newModel->messageHandler()->setLogLevel(messageHandler()->logLevel());
17768 
17769     feasible = newModel->integerPresolveThisModel(solver_, weak);
17770   }
17771   if (!feasible) {
17772     handler_->message(CBC_INFEAS, messages_)
17773       << CoinMessageEol;
17774     status_ = 0;
17775     secondaryStatus_ = 1;
17776     delete newModel;
17777     return NULL;
17778   } else {
17779     newModel->synchronizeModel(); // make sure everything that needs solver has it
17780     return newModel;
17781   }
17782 }
17783 /*
17784    Do Integer Presolve - destroying current model
17785 */
17786 bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver,
17787   bool weak)
17788 {
17789   printf("DEPRECATED\n");
17790   status_ = 0;
17791   // solve LP
17792   bool feasible = (resolve(NULL, 3) != 0);
17793 
17794   bestObjective_ = 1.0e50;
17795   numberSolutions_ = 0;
17796   numberHeuristicSolutions_ = 0;
17797   double cutoff = getCutoff();
17798   double direction = solver_->getObjSense();
17799   if (cutoff < 1.0e20 && direction < 0.0)
17800     messageHandler()->message(CBC_CUTOFF_WARNING1,
17801       messages())
17802       << cutoff << -cutoff << CoinMessageEol;
17803   if (cutoff > bestObjective_)
17804     cutoff = bestObjective_;
17805   setCutoff(cutoff);
17806   int iColumn;
17807   int numberColumns = getNumCols();
17808   int originalNumberColumns = numberColumns;
17809   currentPassNumber_ = 0;
17810   synchronizeModel(); // make sure everything that needs solver has it
17811   if (!solverCharacteristics_) {
17812     OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
17813     if (solverCharacteristics) {
17814       solverCharacteristics_ = solverCharacteristics;
17815     } else {
17816       // replace in solver
17817       OsiBabSolver defaultC;
17818       solver_->setAuxiliaryInfo(&defaultC);
17819       solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo());
17820     }
17821   }
17822   solverCharacteristics_->setSolver(solver_);
17823   // just point to solver_
17824   delete continuousSolver_;
17825   continuousSolver_ = solver_;
17826   // get a copy of original so we can fix bounds
17827   OsiSolverInterface *cleanModel = originalSolver->clone();
17828 #ifdef CBC_DEBUG
17829   std::string problemName;
17830   cleanModel->getStrParam(OsiProbName, problemName);
17831   printf("Problem name - %s\n", problemName.c_str());
17832   cleanModel->activateRowCutDebugger(problemName.c_str());
17833   const OsiRowCutDebugger *debugger = cleanModel->getRowCutDebugger();
17834 #endif
17835 
17836   // array which points from original columns to presolved
17837   int *original = new int[numberColumns];
17838   // arrays giving bounds - only ones found by probing
17839   // rest will be found by presolve
17840   double *originalLower = new double[numberColumns];
17841   double *originalUpper = new double[numberColumns];
17842   {
17843     const double *lower = getColLower();
17844     const double *upper = getColUpper();
17845     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
17846       original[iColumn] = iColumn;
17847       originalLower[iColumn] = lower[iColumn];
17848       originalUpper[iColumn] = upper[iColumn];
17849     }
17850   }
17851   findIntegers(true);
17852   // save original integers
17853   int *originalIntegers = new int[numberIntegers_];
17854   int originalNumberIntegers = numberIntegers_;
17855   memcpy(originalIntegers, integerVariable_, numberIntegers_ * sizeof(int));
17856 
17857   int todo = 20;
17858   if (weak)
17859     todo = 1;
17860   while (currentPassNumber_ < todo) {
17861 
17862     currentPassNumber_++;
17863     numberSolutions_ = 0;
17864     // this will be set false to break out of loop with presolved problem
17865     bool doIntegerPresolve = (currentPassNumber_ != 20);
17866 
17867     // Current number of free integer variables
17868     // Get increment in solutions
17869     {
17870       const double *objective = cleanModel->getObjCoefficients();
17871       const double *lower = cleanModel->getColLower();
17872       const double *upper = cleanModel->getColUpper();
17873       double maximumCost = 0.0;
17874       bool possibleMultiple = true;
17875       int numberChanged = 0;
17876       for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
17877         if (originalUpper[iColumn] > originalLower[iColumn]) {
17878           if (cleanModel->isInteger(iColumn)) {
17879             maximumCost = CoinMax(maximumCost, fabs(objective[iColumn]));
17880           } else if (objective[iColumn]) {
17881             possibleMultiple = false;
17882           }
17883         }
17884         if (originalUpper[iColumn] < upper[iColumn]) {
17885 #ifdef CBC_DEBUG
17886           printf("Changing upper bound on %d from %g to %g\n",
17887             iColumn, upper[iColumn], originalUpper[iColumn]);
17888 #endif
17889           cleanModel->setColUpper(iColumn, originalUpper[iColumn]);
17890           numberChanged++;
17891         }
17892         if (originalLower[iColumn] > lower[iColumn]) {
17893 #ifdef CBC_DEBUG
17894           printf("Changing lower bound on %d from %g to %g\n",
17895             iColumn, lower[iColumn], originalLower[iColumn]);
17896 #endif
17897           cleanModel->setColLower(iColumn, originalLower[iColumn]);
17898           numberChanged++;
17899         }
17900       }
17901       // if first pass - always try
17902       if (currentPassNumber_ == 1)
17903         numberChanged += 1;
17904       if (possibleMultiple && maximumCost) {
17905         int increment = 0;
17906         double multiplier = 2520.0;
17907         while (10.0 * multiplier * maximumCost < 1.0e8)
17908           multiplier *= 10.0;
17909         for (int j = 0; j < originalNumberIntegers; j++) {
17910           iColumn = originalIntegers[j];
17911           if (originalUpper[iColumn] > originalLower[iColumn]) {
17912             if (objective[iColumn]) {
17913               double value = fabs(objective[iColumn]) * multiplier;
17914               int nearest = static_cast< int >(floor(value + 0.5));
17915               if (fabs(value - floor(value + 0.5)) > 1.0e-8 || value > 2.1e9) {
17916                 increment = 0;
17917                 break; // no good
17918               } else if (!increment) {
17919                 // first
17920                 increment = nearest;
17921               } else {
17922                 increment = gcd(increment, nearest);
17923               }
17924             }
17925           }
17926         }
17927         if (increment) {
17928           double value = increment;
17929           value /= multiplier;
17930           if (value * 0.999 > dblParam_[CbcCutoffIncrement]) {
17931             messageHandler()->message(CBC_INTEGERINCREMENT, messages())
17932               << value
17933               << CoinMessageEol;
17934             dblParam_[CbcCutoffIncrement] = value * 0.999;
17935           }
17936         }
17937       }
17938       if (!numberChanged) {
17939         doIntegerPresolve = false; // not doing any better
17940       }
17941     }
17942 #ifdef CBC_DEBUG
17943     if (debugger)
17944       assert(debugger->onOptimalPath(*cleanModel));
17945 #endif
17946 #ifdef COIN_HAS_CLP
17947     // do presolve - for now just clp but easy to get osi interface
17948     OsiClpSolverInterface *clpSolver
17949       = dynamic_cast< OsiClpSolverInterface * >(cleanModel);
17950     if (clpSolver) {
17951       ClpSimplex *clp = clpSolver->getModelPtr();
17952       clp->messageHandler()->setLogLevel(cleanModel->messageHandler()->logLevel());
17953       ClpPresolve pinfo;
17954       //printf("integerPresolve - temp switch off doubletons\n");
17955       //pinfo.setPresolveActions(4);
17956       ClpSimplex *model2 = pinfo.presolvedModel(*clp, 1.0e-8);
17957       if (!model2) {
17958         // presolve found to be infeasible
17959         feasible = false;
17960       } else {
17961         // update original array
17962         const int *originalColumns = pinfo.originalColumns();
17963         // just slot in new solver
17964         OsiClpSolverInterface *temp = new OsiClpSolverInterface(model2, true);
17965         numberColumns = temp->getNumCols();
17966         for (iColumn = 0; iColumn < originalNumberColumns; iColumn++)
17967           original[iColumn] = -1;
17968         for (iColumn = 0; iColumn < numberColumns; iColumn++)
17969           original[originalColumns[iColumn]] = iColumn;
17970         // copy parameters
17971         temp->copyParameters(*solver_);
17972         // and specialized ones
17973         temp->setSpecialOptions(clpSolver->specialOptions());
17974         delete solver_;
17975         solver_ = temp;
17976         setCutoff(cutoff);
17977         deleteObjects();
17978         if (!numberObjects_) {
17979           // Nothing left
17980           doIntegerPresolve = false;
17981           weak = true;
17982           break;
17983         }
17984         synchronizeModel(); // make sure everything that needs solver has it
17985         // just point to solver_
17986         continuousSolver_ = solver_;
17987         feasible = (resolve(NULL, 3) != 0);
17988         if (!feasible || !doIntegerPresolve || weak)
17989           break;
17990         // see if we can get solution by heuristics
17991         int found = -1;
17992         int iHeuristic;
17993         double *newSolution = new double[numberColumns];
17994         double heuristicValue = getCutoff();
17995         int whereFrom = 0;
17996         for (iHeuristic = 0; iHeuristic < numberHeuristics_; iHeuristic++) {
17997           // skip if can't run here
17998           if (!heuristic_[iHeuristic]->shouldHeurRun(whereFrom))
17999             continue;
18000           double saveValue = heuristicValue;
18001           int ifSol = heuristic_[iHeuristic]->solution(heuristicValue,
18002             newSolution);
18003           if (ifSol > 0) {
18004             // better solution found
18005             heuristic_[iHeuristic]->incrementNumberSolutionsFound();
18006             found = iHeuristic;
18007             incrementUsed(newSolution);
18008             whereFrom |= 8; // say solution found
18009           } else if (ifSol < 0) {
18010             heuristicValue = saveValue;
18011           }
18012         }
18013         if (found >= 0) {
18014           // We probably already have a current solution, but just in case ...
18015           int numberColumns = getNumCols();
18016           if (!currentSolution_)
18017             currentSolution_ = new double[numberColumns];
18018           testSolution_ = currentSolution_;
18019           // better solution save
18020           lastHeuristic_ = heuristic_[found];
18021 #ifdef HEURISTIC_INFORM
18022           printf("HEUR %s where %d oddE\n",
18023             lastHeuristic_->heuristicName(), whereFrom);
18024 #endif
18025           setBestSolution(CBC_ROUNDING, heuristicValue,
18026             newSolution);
18027           // update cutoff
18028           cutoff = getCutoff();
18029         }
18030         delete[] newSolution;
18031         // Space for type of cuts
18032         maximumWhich_ = INITIAL_MAXIMUM_WHICH;
18033         delete[] whichGenerator_;
18034         whichGenerator_ = new int[maximumWhich_];
18035         // save number of rows
18036         numberRowsAtContinuous_ = getNumRows();
18037         maximumNumberCuts_ = 0;
18038         currentNumberCuts_ = 0;
18039         delete[] addedCuts_;
18040         addedCuts_ = NULL;
18041 
18042         // maximum depth for tree walkback
18043         maximumDepth_ = 10;
18044         delete[] walkback_;
18045         walkback_ = new CbcNodeInfo *[maximumDepth_];
18046         lastDepth_ = 0;
18047         delete[] lastNodeInfo_;
18048         lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_];
18049         delete[] lastNumberCuts_;
18050         lastNumberCuts_ = new int[maximumDepth_];
18051         maximumCuts_ = 100;
18052         delete[] lastCut_;
18053         lastCut_ = new const OsiRowCut *[maximumCuts_];
18054 
18055         OsiCuts cuts;
18056         numberOldActiveCuts_ = 0;
18057         numberNewCuts_ = 0;
18058         feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL);
18059         currentNumberCuts_ = numberNewCuts_;
18060         delete[] whichGenerator_;
18061         whichGenerator_ = NULL;
18062         delete[] walkback_;
18063         walkback_ = NULL;
18064         delete[] addedCuts_;
18065         addedCuts_ = NULL;
18066         if (feasible) {
18067           // fix anything in original which integer presolve fixed
18068           // for now just integers
18069           const double *lower = solver_->getColLower();
18070           const double *upper = solver_->getColUpper();
18071           int i;
18072           for (i = 0; i < originalNumberIntegers; i++) {
18073             iColumn = originalIntegers[i];
18074             int jColumn = original[iColumn];
18075             if (jColumn >= 0) {
18076               if (upper[jColumn] < originalUpper[iColumn])
18077                 originalUpper[iColumn] = upper[jColumn];
18078               if (lower[jColumn] > originalLower[iColumn])
18079                 originalLower[iColumn] = lower[jColumn];
18080             }
18081           }
18082         }
18083       }
18084     }
18085 #endif
18086     if (!feasible || !doIntegerPresolve) {
18087       break;
18088     }
18089   }
18090   //solver_->writeMps("xx");
18091   delete cleanModel;
18092   delete[] originalIntegers;
18093   numberColumns = getNumCols();
18094   delete[] originalColumns_;
18095   originalColumns_ = new int[numberColumns];
18096   numberColumns = 0;
18097   for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
18098     int jColumn = original[iColumn];
18099     if (jColumn >= 0)
18100       originalColumns_[numberColumns++] = iColumn;
18101   }
18102   delete[] original;
18103   delete[] originalLower;
18104   delete[] originalUpper;
18105 
18106   deleteObjects();
18107   synchronizeModel(); // make sure everything that needs solver has it
18108   continuousSolver_ = NULL;
18109   currentNumberCuts_ = 0;
18110   return feasible;
18111 }
18112 // Put back information into original model - after integerpresolve
18113 void CbcModel::originalModel(CbcModel *presolvedModel, bool weak)
18114 {
18115   solver_->copyParameters(*(presolvedModel->solver_));
18116   bestObjective_ = presolvedModel->bestObjective_;
18117   delete[] bestSolution_;
18118   findIntegers(true);
18119   if (presolvedModel->bestSolution_) {
18120     int numberColumns = getNumCols();
18121     int numberOtherColumns = presolvedModel->getNumCols();
18122     //bestSolution_ = new double[numberColumns];
18123     // set up map
18124     int *back = new int[numberColumns];
18125     int i;
18126     for (i = 0; i < numberColumns; i++)
18127       back[i] = -1;
18128     for (i = 0; i < numberOtherColumns; i++)
18129       back[presolvedModel->originalColumns_[i]] = i;
18130     int iColumn;
18131     // set ones in presolved model to values
18132     double *otherSolution = presolvedModel->bestSolution_;
18133     //const double * lower = getColLower();
18134     for (i = 0; i < numberIntegers_; i++) {
18135       iColumn = integerVariable_[i];
18136       int jColumn = back[iColumn];
18137       //bestSolution_[iColumn]=lower[iColumn];
18138       if (jColumn >= 0) {
18139         double value = floor(otherSolution[jColumn] + 0.5);
18140         solver_->setColLower(iColumn, value);
18141         solver_->setColUpper(iColumn, value);
18142         //bestSolution_[iColumn]=value;
18143       }
18144     }
18145     delete[] back;
18146 #ifdef JJF_ZERO
18147     // ** looks as if presolve needs more intelligence
18148     // do presolve - for now just clp but easy to get osi interface
18149     OsiClpSolverInterface *clpSolver
18150       = dynamic_cast< OsiClpSolverInterface * >(solver_);
18151     assert(clpSolver);
18152     ClpSimplex *clp = clpSolver->getModelPtr();
18153     Presolve pinfo;
18154     ClpSimplex *model2 = pinfo.presolvedModel(*clp, 1.0e-8);
18155     model2->primal(1);
18156     pinfo.postsolve(true);
18157     const double *solution = solver_->getColSolution();
18158     for (i = 0; i < numberIntegers_; i++) {
18159       iColumn = integerVariable_[i];
18160       double value = floor(solution[iColumn] + 0.5);
18161       solver_->setColLower(iColumn, value);
18162       solver_->setColUpper(iColumn, value);
18163     }
18164 #else
18165     if (!weak) {
18166       // for now give up
18167       int save = numberCutGenerators_;
18168       numberCutGenerators_ = 0;
18169       bestObjective_ = 1.0e100;
18170       branchAndBound();
18171       numberCutGenerators_ = save;
18172     }
18173 #endif
18174     if (bestSolution_) {
18175       // solve problem
18176       resolve(NULL, 3);
18177       // should be feasible
18178       if (!currentSolution_)
18179         currentSolution_ = new double[numberColumns];
18180       testSolution_ = currentSolution_;
18181 #ifndef NDEBUG
18182       int numberIntegerInfeasibilities;
18183       int numberObjectInfeasibilities;
18184       assert(feasibleSolution(numberIntegerInfeasibilities,
18185         numberObjectInfeasibilities));
18186 #endif
18187     }
18188   } else {
18189     bestSolution_ = NULL;
18190   }
18191   numberSolutions_ = presolvedModel->numberSolutions_;
18192   numberHeuristicSolutions_ = presolvedModel->numberHeuristicSolutions_;
18193   numberNodes_ = presolvedModel->numberNodes_;
18194   numberIterations_ = presolvedModel->numberIterations_;
18195   status_ = presolvedModel->status_;
18196   secondaryStatus_ = presolvedModel->secondaryStatus_;
18197   synchronizeModel();
18198 }
18199 void CbcModel::setOptionalInteger(int index)
18200 {
18201 #ifdef COIN_HAS_CLP
18202   OsiClpSolverInterface *clpSolver
18203     = dynamic_cast< OsiClpSolverInterface * >(solver_);
18204   if (clpSolver)
18205     clpSolver->setOptionalInteger(index);
18206   else
18207 #endif
18208     solver_->setInteger(index);
18209 }
18210 // Return true if maximum time reached
18211 bool CbcModel::maximumSecondsReached() const
18212 {
18213   double totalTime = getCurrentSeconds();
18214   double maxSeconds = getMaximumSeconds();
18215   bool hitMaxTime = (totalTime >= maxSeconds);
18216   if (parentModel_ && !hitMaxTime) {
18217     // In a sub tree
18218     assert(parentModel_);
18219     maxSeconds = parentModel_->getMaximumSeconds();
18220     hitMaxTime = (totalTime >= maxSeconds);
18221   }
18222   if (hitMaxTime) {
18223     // Set eventHappened_ so will by-pass as much stuff as possible
18224     eventHappened_ = true;
18225   }
18226   return hitMaxTime;
18227 }
18228 // Check original model before it gets messed up
18229 void CbcModel::checkModel()
18230 {
18231   int iColumn;
18232   int numberColumns = getNumCols();
18233   const double *lower = getColLower();
18234   const double *upper = getColUpper();
18235   int setFlag = 65536;
18236   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
18237     if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
18238       double value;
18239       value = fabs(lower[iColumn]);
18240       if (floor(value + 0.5) != value) {
18241         setFlag = 0;
18242         break;
18243       }
18244       value = fabs(upper[iColumn]);
18245       if (floor(value + 0.5) != value) {
18246         setFlag = 0;
18247         break;
18248       }
18249     }
18250   }
18251   specialOptions_ |= setFlag;
18252 }
18253 static void flipSolver(OsiSolverInterface *solver, double newCutoff)
18254 {
18255   if (solver) {
18256     double objValue = solver->getObjValue();
18257     double objectiveOffset;
18258     solver->setObjSense(-solver->getObjSense());
18259     solver->getDblParam(OsiObjOffset, objectiveOffset);
18260     solver->setDblParam(OsiObjOffset, -objectiveOffset);
18261     int numberColumns = solver->getNumCols();
18262     double *array = CoinCopyOfArray(solver->getObjCoefficients(), numberColumns);
18263     for (int i = 0; i < numberColumns; i++)
18264       array[i] = -array[i];
18265     solver->setObjective(array);
18266     delete[] array;
18267     solver->setDblParam(OsiDualObjectiveLimit, newCutoff);
18268 #ifdef COIN_HAS_CLP
18269     OsiClpSolverInterface *clpSolver
18270       = dynamic_cast< OsiClpSolverInterface * >(solver);
18271     if (clpSolver) {
18272       double *dj = clpSolver->getModelPtr()->dualColumnSolution();
18273       for (int i = 0; i < numberColumns; i++)
18274         dj[i] = -dj[i];
18275       int numberRows = clpSolver->getNumRows();
18276       double *pi = clpSolver->getModelPtr()->dualRowSolution();
18277       for (int i = 0; i < numberRows; i++)
18278         pi[i] = -pi[i];
18279       clpSolver->getModelPtr()->setObjectiveValue(-objValue);
18280     } else {
18281 #endif
18282       // update values
18283       solver->resolve();
18284 #ifdef COIN_HAS_CLP
18285     }
18286 #endif
18287   }
18288 }
18289 /*
18290   Flip direction of optimization on all models
18291 */
18292 void CbcModel::flipModel()
18293 {
18294   if (parentModel_)
18295     return;
18296   // I think cutoff is always minimization
18297   double cutoff = getCutoff();
18298   flipSolver(referenceSolver_, cutoff);
18299   flipSolver(continuousSolver_, cutoff);
18300   flipSolver(solver_, cutoff);
18301 }
18302 #ifdef CBC_KEEP_DEPRECATED
18303 /* preProcess problem - replacing solver
18304    If makeEquality true then <= cliques converted to ==.
18305    Presolve will be done numberPasses times.
18306 
18307    Returns NULL if infeasible
18308 
18309    If makeEquality is 1 add slacks to get cliques,
18310    if 2 add slacks to get sos (but only if looks plausible) and keep sos info
18311 */
18312 CglPreProcess *
18313 CbcModel::preProcess(int makeEquality, int numberPasses, int tuning)
18314 {
18315   CglPreProcess *process = new CglPreProcess();
18316   // Default set of cut generators
18317   CglProbing generator1;
18318   generator1.setUsingObjective(true);
18319   generator1.setMaxPass(3);
18320   generator1.setMaxProbeRoot(solver_->getNumCols());
18321   generator1.setMaxElements(100);
18322   generator1.setMaxLookRoot(50);
18323   generator1.setRowCuts(3);
18324   // Add in generators
18325   process->addCutGenerator(&generator1);
18326   process->messageHandler()->setLogLevel(this->logLevel());
18327   /* model may not have created objects
18328        If none then create
18329     */
18330   if (!numberIntegers_ || !numberObjects_) {
18331     this->findIntegers(true, 1);
18332   }
18333   // Do SOS
18334   int i;
18335   int numberSOS2 = 0;
18336   for (i = 0; i < numberObjects_; i++) {
18337     CbcSOS *objSOS = dynamic_cast< CbcSOS * >(object_[i]);
18338     if (objSOS) {
18339       int type = objSOS->sosType();
18340       if (type == 2)
18341         numberSOS2++;
18342     }
18343   }
18344   if (numberSOS2) {
18345     // SOS
18346     int numberColumns = solver_->getNumCols();
18347     char *prohibited = new char[numberColumns];
18348     memset(prohibited, 0, numberColumns);
18349     for (i = 0; i < numberObjects_; i++) {
18350       CbcSOS *objSOS = dynamic_cast< CbcSOS * >(object_[i]);
18351       if (objSOS) {
18352         int type = objSOS->sosType();
18353         if (type == 2) {
18354           int n = objSOS->numberMembers();
18355           const int *which = objSOS->members();
18356           for (int j = 0; j < n; j++) {
18357             int iColumn = which[j];
18358             prohibited[iColumn] = 1;
18359           }
18360         }
18361       }
18362     }
18363     process->passInProhibited(prohibited, numberColumns);
18364     delete[] prohibited;
18365   }
18366   // Tell solver we are not in Branch and Cut
18367   solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo);
18368   OsiSolverInterface *newSolver = process->preProcessNonDefault(*solver_, makeEquality,
18369     numberPasses, tuning);
18370   // Tell solver we are not in Branch and Cut
18371   solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
18372   if (newSolver) {
18373     int numberOriginalObjects = numberObjects_;
18374     OsiSolverInterface *originalSolver = solver_;
18375     solver_ = newSolver->clone(); // clone as process owns solver
18376     // redo sequence
18377     numberIntegers_ = 0;
18378     int numberColumns = solver_->getNumCols();
18379     int nOrig = originalSolver->getNumCols();
18380     const int *originalColumns = process->originalColumns();
18381     // allow for cliques etc
18382     nOrig = CoinMax(nOrig, originalColumns[numberColumns - 1] + 1);
18383     OsiObject **originalObject = object_;
18384     // object number or -1
18385     int *temp = new int[nOrig];
18386     int iColumn;
18387     for (iColumn = 0; iColumn < nOrig; iColumn++)
18388       temp[iColumn] = -1;
18389     int iObject;
18390     numberObjects_ = 0;
18391     int nNonInt = 0;
18392     for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
18393       iColumn = originalObject[iObject]->columnNumber();
18394       if (iColumn < 0) {
18395         nNonInt++;
18396       } else {
18397         temp[iColumn] = iObject;
18398       }
18399     }
18400     int numberNewIntegers = 0;
18401     int numberOldIntegers = 0;
18402     int numberOldOther = 0;
18403     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
18404       int jColumn = originalColumns[iColumn];
18405       if (temp[jColumn] >= 0) {
18406         int iObject = temp[jColumn];
18407         CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]);
18408         if (obj)
18409           numberOldIntegers++;
18410         else
18411           numberOldOther++;
18412       } else if (isInteger(iColumn)) {
18413         numberNewIntegers++;
18414       }
18415     }
18416     /*
18417           Allocate an array to hold the indices of the integer variables.
18418           Make a large enough array for all objects
18419         */
18420     numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt;
18421     object_ = new OsiObject *[numberObjects_];
18422     delete[] integerVariable_;
18423     integerVariable_ = new int[numberNewIntegers + numberOldIntegers];
18424     /*
18425           Walk the variables again, filling in the indices and creating objects for
18426           the integer variables. Initially, the objects hold the index and upper &
18427           lower bounds.
18428         */
18429     numberIntegers_ = 0;
18430     int n = originalColumns[numberColumns - 1] + 1;
18431     int *backward = new int[n];
18432     int i;
18433     for (i = 0; i < n; i++)
18434       backward[i] = -1;
18435     for (i = 0; i < numberColumns; i++)
18436       backward[originalColumns[i]] = i;
18437     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
18438       int jColumn = originalColumns[iColumn];
18439       if (temp[jColumn] >= 0) {
18440         int iObject = temp[jColumn];
18441         CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]);
18442         if (obj) {
18443           object_[numberIntegers_] = originalObject[iObject]->clone();
18444           // redo ids etc
18445           //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns);
18446           object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward);
18447           integerVariable_[numberIntegers_++] = iColumn;
18448         }
18449       } else if (isInteger(iColumn)) {
18450         object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn);
18451         integerVariable_[numberIntegers_++] = iColumn;
18452       }
18453     }
18454     delete[] backward;
18455     numberObjects_ = numberIntegers_;
18456     // Now append other column stuff
18457     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
18458       int jColumn = originalColumns[iColumn];
18459       if (temp[jColumn] >= 0) {
18460         int iObject = temp[jColumn];
18461         CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]);
18462         if (!obj) {
18463           object_[numberObjects_] = originalObject[iObject]->clone();
18464           // redo ids etc
18465           CbcObject *obj = dynamic_cast< CbcObject * >(object_[numberObjects_]);
18466           assert(obj);
18467           obj->redoSequenceEtc(this, numberColumns, originalColumns);
18468           numberObjects_++;
18469         }
18470       }
18471     }
18472     // now append non column stuff
18473     for (iObject = 0; iObject < numberOriginalObjects; iObject++) {
18474       iColumn = originalObject[iObject]->columnNumber();
18475       if (iColumn < 0) {
18476         object_[numberObjects_] = originalObject[iObject]->clone();
18477         // redo ids etc
18478         CbcObject *obj = static_cast< CbcObject * >(object_[numberObjects_]);
18479         assert(obj);
18480         obj->redoSequenceEtc(this, numberColumns, originalColumns);
18481         numberObjects_++;
18482       }
18483       delete originalObject[iObject];
18484     }
18485     delete[] originalObject;
18486     delete[] temp;
18487     if (!numberObjects_)
18488       handler_->message(CBC_NOINT, messages_) << CoinMessageEol;
18489     return process;
18490   } else {
18491     // infeasible
18492     delete process;
18493     return NULL;
18494   }
18495 }
18496 /* Does postprocessing - original solver back.
18497    User has to delete process */
18498 void CbcModel::postProcess(CglPreProcess *process)
18499 {
18500   process->postProcess(*solver_);
18501   delete solver_;
18502   solver_ = process->originalModel();
18503 }
18504 
18505 /* Process root node and return a strengthened model
18506 
18507 The method assumes that initialSolve() has been called to solve the
18508 LP relaxation. It processes the root node and then returns a pointer
18509 to the strengthened model (or NULL if infeasible)
18510 */
18511 OsiSolverInterface *
18512 CbcModel::strengthenedModel()
18513 {
18514   /*
18515       Switch off heuristics
18516     */
18517   int saveNumberHeuristics = numberHeuristics_;
18518   numberHeuristics_ = 0;
18519   /*
18520       Scan the variables, noting the integer variables. Create an
18521       CbcSimpleInteger object for each integer variable.
18522     */
18523   findIntegers(false);
18524   /*
18525       Ensure that objects on the lists of OsiObjects, heuristics, and cut
18526       generators attached to this model all refer to this model.
18527     */
18528   synchronizeModel();
18529 
18530   // Set so we can tell we are in initial phase in resolve
18531   continuousObjective_ = -COIN_DBL_MAX;
18532   /*
18533       Solve the relaxation.
18534 
18535       Apparently there are circumstances where this will be non-trivial --- i.e.,
18536       we've done something since initialSolve that's trashed the solution to the
18537       continuous relaxation.
18538     */
18539   bool feasible = resolve(NULL, 0) != 0;
18540   /*
18541       If the linear relaxation of the root is infeasible, bail out now. Otherwise,
18542       continue with processing the root node.
18543     */
18544   if (!feasible) {
18545     handler_->message(CBC_INFEAS, messages_) << CoinMessageEol;
18546     return NULL;
18547   }
18548   // Save objective (just so user can access it)
18549   originalContinuousObjective_ = solver_->getObjValue();
18550 
18551   /*
18552       Begin setup to process a feasible root node.
18553     */
18554   bestObjective_ = CoinMin(bestObjective_, 1.0e50);
18555   numberSolutions_ = 0;
18556   numberHeuristicSolutions_ = 0;
18557   // Everything is minimization
18558   double cutoff = getCutoff();
18559   double direction = solver_->getObjSense();
18560   if (cutoff < 1.0e20 && direction < 0.0)
18561     messageHandler()->message(CBC_CUTOFF_WARNING1,
18562       messages())
18563       << cutoff << -cutoff << CoinMessageEol;
18564   if (cutoff > bestObjective_)
18565     cutoff = bestObjective_;
18566   setCutoff(cutoff);
18567   /*
18568       We probably already have a current solution, but just in case ...
18569     */
18570   int numberColumns = getNumCols();
18571   if (!currentSolution_)
18572     currentSolution_ = new double[numberColumns];
18573   testSolution_ = currentSolution_;
18574   /*
18575       Create a copy of the solver, thus capturing the original (root node)
18576       constraint system (aka the continuous system).
18577     */
18578   continuousSolver_ = solver_->clone();
18579   numberRowsAtContinuous_ = getNumRows();
18580   /*
18581       Check the objective to see if we can deduce a nontrivial increment. If
18582       it's better than the current value for CbcCutoffIncrement, it'll be
18583       installed.
18584     */
18585   analyzeObjective();
18586   /*
18587       Set up for cut generation. addedCuts_ holds the cuts which are relevant for
18588       the active subproblem. whichGenerator will be used to record the generator
18589       that produced a given cut.
18590     */
18591   maximumWhich_ = INITIAL_MAXIMUM_WHICH;
18592   delete[] whichGenerator_;
18593   whichGenerator_ = new int[maximumWhich_];
18594   maximumNumberCuts_ = 0;
18595   currentNumberCuts_ = 0;
18596   delete[] addedCuts_;
18597   addedCuts_ = NULL;
18598   /*
18599     Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
18600     lifting. It will iterate a generate/reoptimise loop (including reduced cost
18601     fixing) until no cuts are generated, the change in objective falls off,  or
18602     the limit on the number of rounds of cut generation is exceeded.
18603 
18604     At the end of all this, any cuts will be recorded in cuts and also
18605     installed in the solver's constraint system. We'll have reoptimised, and
18606     removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
18607     adjusted accordingly).
18608 
18609     Tell cut generators they can be a bit more aggressive at root node
18610 
18611     */
18612   int iCutGenerator;
18613   for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) {
18614     CglCutGenerator *generator = generator_[iCutGenerator]->generator();
18615     generator->setAggressiveness(generator->getAggressiveness() + 100);
18616   }
18617   OsiCuts cuts;
18618   numberOldActiveCuts_ = 0;
18619   numberNewCuts_ = 0;
18620   {
18621     int iObject;
18622     int numberUnsatisfied = 0;
18623     memcpy(currentSolution_, solver_->getColSolution(),
18624       numberColumns * sizeof(double));
18625 
18626     // point to useful information
18627     OsiBranchingInformation usefulInfo = usefulInformation();
18628     for (iObject = 0; iObject < numberObjects_; iObject++) {
18629       double infeasibility = object_[iObject]->checkInfeasibility(&usefulInfo);
18630       if (infeasibility)
18631         numberUnsatisfied++;
18632     }
18633     if (numberUnsatisfied) {
18634       feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_,
18635         NULL);
18636     }
18637   }
18638   /*
18639       We've taken the continuous relaxation as far as we can.
18640     */
18641 
18642   OsiSolverInterface *newSolver = NULL;
18643   if (feasible) {
18644     // make copy of current solver
18645     newSolver = solver_->clone();
18646   }
18647   /*
18648       Clean up dangling objects. continuousSolver_ may already be toast.
18649     */
18650   delete[] whichGenerator_;
18651   whichGenerator_ = NULL;
18652   delete[] walkback_;
18653   walkback_ = NULL;
18654   delete[] lastNodeInfo_;
18655   lastNodeInfo_ = NULL;
18656   delete[] lastNumberCuts_;
18657   lastNumberCuts_ = NULL;
18658   delete[] lastCut_;
18659   lastCut_ = NULL;
18660   delete[] addedCuts_;
18661   addedCuts_ = NULL;
18662   if (continuousSolver_) {
18663     delete continuousSolver_;
18664     continuousSolver_ = NULL;
18665   }
18666   /*
18667       Destroy global cuts by replacing with an empty OsiCuts object.
18668     */
18669   globalCuts_ = OsiCuts();
18670   delete globalConflictCuts_;
18671   globalConflictCuts_ = NULL;
18672   numberHeuristics_ = saveNumberHeuristics;
18673 
18674   return newSolver;
18675 }
18676 /*  create a submodel from partially fixed problem
18677 
18678 The method creates a new clean model with given bounds.
18679 */
18680 CbcModel *
18681 CbcModel::cleanModel(const double *lower, const double *upper)
18682 {
18683   OsiSolverInterface *solver = continuousSolver_->clone();
18684 
18685   int numberIntegers = numberIntegers_;
18686   const int *integerVariable = integerVariable_;
18687 
18688   int i;
18689   for (i = 0; i < numberIntegers; i++) {
18690     int iColumn = integerVariable[i];
18691     const OsiObject *object = object_[i];
18692 #ifndef NDEBUG
18693     const CbcSimpleInteger *integerObject = dynamic_cast< const CbcSimpleInteger * >(object);
18694     assert(integerObject);
18695 #else
18696       const CbcSimpleInteger *integerObject = static_cast< const CbcSimpleInteger * >(object);
18697 #endif
18698     // get original bounds
18699     double originalLower = integerObject->originalLowerBound();
18700     double originalUpper = integerObject->originalUpperBound();
18701     solver->setColLower(iColumn, CoinMax(lower[iColumn], originalLower));
18702     solver->setColUpper(iColumn, CoinMin(upper[iColumn], originalUpper));
18703   }
18704   CbcModel *model = new CbcModel(*solver);
18705   // off some messages
18706   if (handler_->logLevel() <= 1) {
18707     model->messagesPointer()->setDetailMessage(3, 9);
18708     model->messagesPointer()->setDetailMessage(3, 6);
18709     model->messagesPointer()->setDetailMessage(3, 4);
18710     model->messagesPointer()->setDetailMessage(3, 1);
18711     model->messagesPointer()->setDetailMessage(3, 13);
18712     model->messagesPointer()->setDetailMessage(3, 14);
18713     model->messagesPointer()->setDetailMessage(3, 3007);
18714   }
18715   // Cuts
18716   for (i = 0; i < numberCutGenerators_; i++) {
18717     int howOften = generator_[i]->howOftenInSub();
18718     if (howOften > -100) {
18719       CbcCutGenerator *generator = virginGenerator_[i];
18720       CglCutGenerator *cglGenerator = generator->generator();
18721       model->addCutGenerator(cglGenerator, howOften,
18722         generator->cutGeneratorName(),
18723         generator->normal(),
18724         generator->atSolution(),
18725         generator->whenInfeasible(),
18726         -100, generator->whatDepthInSub(), -1);
18727     }
18728   }
18729   double cutoff = getCutoff();
18730   model->setCutoff(cutoff);
18731   return model;
18732 }
18733 /* Invoke the branch & cut algorithm on partially fixed problem
18734 
18735    The method uses a subModel created by cleanModel. The search
18736    ends when the tree is exhausted or maximum nodes is reached.
18737 
18738    If better solution found then it is saved.
18739 
18740    Returns 0 if search completed and solution, 1 if not completed and solution,
18741    2 if completed and no solution, 3 if not completed and no solution.
18742 
18743    Normally okay to do subModel immediately followed by subBranchandBound
18744    (== other form of subBranchAndBound)
18745    but may need to get at model for advanced features.
18746 
18747    Deletes model
18748 
18749 */
18750 
18751 int CbcModel::subBranchAndBound(CbcModel *model,
18752   CbcModel *presolvedModel,
18753   int maximumNodes)
18754 {
18755   int i;
18756   double cutoff = model->getCutoff();
18757   CbcModel *model2;
18758   if (presolvedModel)
18759     model2 = presolvedModel;
18760   else
18761     model2 = model;
18762   // Do complete search
18763 
18764   for (i = 0; i < numberHeuristics_; i++) {
18765     model2->addHeuristic(heuristic_[i]);
18766     model2->heuristic(i)->resetModel(model2);
18767   }
18768   // Definition of node choice
18769   model2->setNodeComparison(nodeCompare_->clone());
18770   //model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
18771   model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1));
18772   //model2->solver()->messageHandler()->setLogLevel(2);
18773   model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_);
18774   model2->setPrintFrequency(50);
18775   model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes);
18776   model2->branchAndBound();
18777   delete model2->nodeComparison();
18778   if (model2->getMinimizationObjValue() > cutoff) {
18779     // no good
18780     if (model != model2)
18781       delete model2;
18782     delete model;
18783     return 2;
18784   }
18785   if (model != model2) {
18786     // get back solution
18787     model->originalModel(model2, false);
18788     delete model2;
18789   }
18790   int status;
18791   if (model->getMinimizationObjValue() < cutoff && model->bestSolution()) {
18792     double objValue = model->getObjValue();
18793     const double *solution = model->bestSolution();
18794     setBestSolution(CBC_TREE_SOL, objValue, solution);
18795     status = 0;
18796   } else {
18797     status = 2;
18798   }
18799   if (model->status())
18800     status++; // not finished search
18801   delete model;
18802   return status;
18803 }
18804 /* Invoke the branch & cut algorithm on partially fixed problem
18805 
18806 The method creates a new model with given bounds, presolves it
18807 then proceeds to explore the branch & cut search tree. The search
18808 ends when the tree is exhausted or maximum nodes is reached.
18809 Returns 0 if search completed and solution, 1 if not completed and solution,
18810 2 if completed and no solution, 3 if not completed and no solution.
18811 */
18812 int CbcModel::subBranchAndBound(const double *lower, const double *upper,
18813   int maximumNodes)
18814 {
18815   OsiSolverInterface *solver = continuousSolver_->clone();
18816 
18817   int numberIntegers = numberIntegers_;
18818   const int *integerVariable = integerVariable_;
18819 
18820   int i;
18821   for (i = 0; i < numberIntegers; i++) {
18822     int iColumn = integerVariable[i];
18823     const OsiObject *object = object_[i];
18824 #ifndef NDEBUG
18825     const CbcSimpleInteger *integerObject = dynamic_cast< const CbcSimpleInteger * >(object);
18826     assert(integerObject);
18827 #else
18828       const CbcSimpleInteger *integerObject = static_cast< const CbcSimpleInteger * >(object);
18829 #endif
18830     // get original bounds
18831     double originalLower = integerObject->originalLowerBound();
18832     double originalUpper = integerObject->originalUpperBound();
18833     solver->setColLower(iColumn, CoinMax(lower[iColumn], originalLower));
18834     solver->setColUpper(iColumn, CoinMin(upper[iColumn], originalUpper));
18835   }
18836   CbcModel model(*solver);
18837   // off some messages
18838   if (handler_->logLevel() <= 1) {
18839     model.messagesPointer()->setDetailMessage(3, 9);
18840     model.messagesPointer()->setDetailMessage(3, 6);
18841     model.messagesPointer()->setDetailMessage(3, 4);
18842     model.messagesPointer()->setDetailMessage(3, 1);
18843     model.messagesPointer()->setDetailMessage(3, 3007);
18844   }
18845   double cutoff = getCutoff();
18846   model.setCutoff(cutoff);
18847   // integer presolve
18848   CbcModel *model2 = model.integerPresolve(false);
18849   if (!model2 || !model2->getNumRows()) {
18850     delete model2;
18851     delete solver;
18852     return 2;
18853   }
18854   if (handler_->logLevel() > 1)
18855     printf("Reduced model has %d rows and %d columns\n",
18856       model2->getNumRows(), model2->getNumCols());
18857   // Do complete search
18858 
18859   // Cuts
18860   for (i = 0; i < numberCutGenerators_; i++) {
18861     int howOften = generator_[i]->howOftenInSub();
18862     if (howOften > -100) {
18863       CbcCutGenerator *generator = virginGenerator_[i];
18864       CglCutGenerator *cglGenerator = generator->generator();
18865       model2->addCutGenerator(cglGenerator, howOften,
18866         generator->cutGeneratorName(),
18867         generator->normal(),
18868         generator->atSolution(),
18869         generator->whenInfeasible(),
18870         -100, generator->whatDepthInSub(), -1);
18871     }
18872   }
18873   for (i = 0; i < numberHeuristics_; i++) {
18874     model2->addHeuristic(heuristic_[i]);
18875     model2->heuristic(i)->resetModel(model2);
18876   }
18877   // Definition of node choice
18878   model2->setNodeComparison(nodeCompare_->clone());
18879   //model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
18880   model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1));
18881   //model2->solver()->messageHandler()->setLogLevel(2);
18882   model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_);
18883   model2->setPrintFrequency(50);
18884   model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes);
18885   model2->branchAndBound();
18886   delete model2->nodeComparison();
18887   if (model2->getMinimizationObjValue() > cutoff) {
18888     // no good
18889     delete model2;
18890     delete solver;
18891     return 2;
18892   }
18893   // get back solution
18894   model.originalModel(model2, false);
18895   delete model2;
18896   int status;
18897   if (model.getMinimizationObjValue() < cutoff && model.bestSolution()) {
18898     double objValue = model.getObjValue();
18899     const double *solution = model.bestSolution();
18900     setBestSolution(CBC_TREE_SOL, objValue, solution);
18901     status = 0;
18902   } else {
18903     status = 2;
18904   }
18905   if (model.status())
18906     status++; // not finished search
18907   delete solver;
18908   return status;
18909 }
18910 #endif
18911 
18912 static void *doRootCbcThread(void *voidInfo)
18913 {
18914   CbcModel *model = reinterpret_cast< CbcModel * >(voidInfo);
18915 #ifdef COIN_HAS_CLP
18916   OsiClpSolverInterface *clpSolver
18917     = dynamic_cast< OsiClpSolverInterface * >(model->solver());
18918   char general[200];
18919   if (clpSolver) {
18920     sprintf(general, "Starting multiple root solver");
18921     model->messageHandler()->message(CBC_GENERAL,
18922       model->messages())
18923       << general << CoinMessageEol;
18924     clpSolver->setHintParam(OsiDoReducePrint, true, OsiHintTry);
18925     ClpSimplex *simplex = clpSolver->getModelPtr();
18926     int logLevel = simplex->logLevel();
18927     if (logLevel <= 1)
18928       simplex->setLogLevel(0);
18929     simplex->dual();
18930     simplex->setLogLevel(logLevel);
18931     clpSolver->setWarmStart(NULL);
18932   } else {
18933     model->initialSolve();
18934     sprintf(general, "Solver did %d iterations in initialSolve\n",
18935       model->solver()->getIterationCount());
18936     model->messageHandler()->message(CBC_GENERAL,
18937       model->messages())
18938       << general << CoinMessageEol;
18939   }
18940 #endif
18941   model->branchAndBound();
18942   sprintf(general, "Ending multiple root solver");
18943   model->messageHandler()->message(CBC_GENERAL,
18944     model->messages())
18945     << general << CoinMessageEol;
18946   return NULL;
18947 }
18948 OsiRowCut *
18949 CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts)
18950 {
18951   OsiRowCut *cut = NULL;
18952   localCuts = false;
18953 #ifdef COIN_HAS_CLP
18954   const OsiClpSolverInterface *clpSolver
18955     = dynamic_cast< const OsiClpSolverInterface * >(solver);
18956   if (clpSolver && topOfTree_) {
18957     int debugMode = 0;
18958     const double *originalLower = topOfTree_->lower();
18959     const double *originalUpper = topOfTree_->upper();
18960     int typeCut = 1;
18961     ClpSimplex *simplex = clpSolver->getModelPtr();
18962     assert(simplex->status() == 1);
18963     if (simplex->ray()) {
18964       {
18965         int numberRows = simplex->numberRows();
18966         double *saveRay = CoinCopyOfArray(simplex->ray(), numberRows);
18967 #define SAFE_RAY
18968 #ifdef SAFE_RAY
18969         ClpSimplex &tempSimplex = *simplex;
18970 #else
18971           ClpSimplex tempSimplex = *simplex;
18972 #endif
18973         int logLevel = simplex->logLevel();
18974         tempSimplex.setLogLevel(63);
18975         tempSimplex.scaling(0);
18976         tempSimplex.dual();
18977         tempSimplex.setLogLevel(logLevel);
18978         if (!tempSimplex.numberIterations()) {
18979           double *ray = tempSimplex.ray();
18980           int nBad = 0;
18981           for (int i = 0; i < numberRows; i++) {
18982             if (fabs(ray[i] - saveRay[i]) > 1.0e-3) {
18983               if (debugMode)
18984                 printf("row %d true %g bad %g - diff %g\n",
18985                   i, ray[i], saveRay[i], ray[i] - saveRay[i]);
18986               nBad++;
18987             }
18988           }
18989           if (nBad)
18990             printf("%d mismatch crunch ray values\n", nBad);
18991         }
18992         delete[] saveRay;
18993       }
18994       // make sure we use non-scaled versions
18995       ClpPackedMatrix *saveMatrix = simplex->swapScaledMatrix(NULL);
18996       double *saveScale = simplex->swapRowScale(NULL);
18997       //printf("Could do normal cut\n");
18998       // could use existing arrays
18999       int numberRows = simplex->numberRows();
19000       int numberColumns = simplex->numberColumns();
19001       double *farkas = new double[2 * numberColumns + numberRows];
19002       double *bound = farkas + numberColumns;
19003       double *effectiveRhs = bound + numberColumns;
19004       // sign as internally for dual - so swap if primal
19005       /*const*/ double *ray = simplex->ray();
19006       // have to get rid of local cut rows
19007       if (whichGenerator_) {
19008         const int *whichGenerator = whichGenerator_ - numberRowsAtContinuous_;
19009         int badRows = 0;
19010         for (int iRow = numberRowsAtContinuous_; iRow < numberRows; iRow++) {
19011           int iType = whichGenerator[iRow];
19012           if ((iType >= 0 && iType < 20000)) {
19013             if (fabs(ray[iRow]) > 1.0e-10) {
19014               badRows++;
19015             } else {
19016               ray[iRow] = 0.0;
19017             }
19018           }
19019         }
19020         if (badRows) {
19021           if ((debugMode & 1) != 0)
19022             printf("%d rows from local cuts\n", badRows);
19023           localCuts = true;
19024         }
19025       }
19026       // get farkas row
19027       memset(farkas, 0, (2 * numberColumns + numberRows) * sizeof(double));
19028       simplex->transposeTimes(-1.0, ray, farkas);
19029       //const char * integerInformation = simplex->integerType_;
19030       //assert (integerInformation);
19031 
19032       int sequenceOut = simplex->sequenceOut();
19033       // Put nonzero bounds in bound
19034       const double *columnLower = simplex->columnLower();
19035       const double *columnUpper = simplex->columnUpper();
19036       int numberBad = 0;
19037       for (int i = 0; i < numberColumns; i++) {
19038         double value = farkas[i];
19039         double boundValue = 0.0;
19040         if (simplex->getStatus(i) == ClpSimplex::basic) {
19041           // treat as zero if small
19042           if (fabs(value) < 1.0e-8) {
19043             value = 0.0;
19044             farkas[i] = 0.0;
19045           }
19046           if (value) {
19047             //printf("basic %d direction %d farkas %g\n",
19048             //	   i,simplex->directionOut(),value);
19049             if (value < 0.0)
19050               boundValue = columnLower[i];
19051             else
19052               boundValue = columnUpper[i];
19053           }
19054         } else if (fabs(value) > 1.0e-10) {
19055           if (value < 0.0)
19056             boundValue = columnLower[i];
19057           else
19058             boundValue = columnUpper[i];
19059         }
19060         bound[i] = boundValue;
19061         if (fabs(boundValue) > 1.0e10)
19062           numberBad++;
19063       }
19064       const double *rowLower = simplex->rowLower();
19065       const double *rowUpper = simplex->rowUpper();
19066       //int pivotRow = simplex->spareIntArray_[3];
19067       //bool badPivot=pivotRow<0;
19068       for (int i = 0; i < numberRows; i++) {
19069         double value = ray[i];
19070         double rhsValue = 0.0;
19071         if (simplex->getRowStatus(i) == ClpSimplex::basic) {
19072           // treat as zero if small
19073           if (fabs(value) < 1.0e-8) {
19074             value = 0.0;
19075             ray[i] = 0.0;
19076           }
19077           if (value) {
19078             //printf("row basic %d direction %d ray %g\n",
19079             //	   i,simplex->directionOut(),value);
19080             if (value < 0.0)
19081               rhsValue = rowLower[i];
19082             else
19083               rhsValue = rowUpper[i];
19084           }
19085         } else if (fabs(value) > 1.0e-10) {
19086           if (value < 0.0)
19087             rhsValue = rowLower[i];
19088           else
19089             rhsValue = rowUpper[i];
19090         }
19091         effectiveRhs[i] = rhsValue;
19092       }
19093       simplex->times(-1.0, bound, effectiveRhs);
19094       simplex->swapRowScale(saveScale);
19095       simplex->swapScaledMatrix(saveMatrix);
19096       double bSum = 0.0;
19097       for (int i = 0; i < numberRows; i++) {
19098         bSum += effectiveRhs[i] * ray[i];
19099       }
19100       if (numberBad || bSum > -1.0e-4) {
19101 #ifndef NDEBUG
19102         printf("bad BOUND bSum %g  - %d bad\n",
19103           bSum, numberBad);
19104 #endif
19105       } else {
19106         const char *integerInformation = simplex->integerInformation();
19107         assert(integerInformation);
19108         int *conflict = new int[numberColumns];
19109         double *sort = new double[numberColumns];
19110         double relax = 0.0;
19111         int nConflict = 0;
19112         int nOriginal = 0;
19113         int nFixed = 0;
19114         for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
19115           if (integerInformation[iColumn]) {
19116             if ((debugMode & 1) != 0)
19117               printf("%d status %d %g <= %g <=%g (orig %g, %g) farkas %g\n",
19118                 iColumn, simplex->getStatus(iColumn), columnLower[iColumn],
19119                 simplex->primalColumnSolution()[iColumn], columnUpper[iColumn],
19120                 originalLower[iColumn], originalUpper[iColumn],
19121                 farkas[iColumn]);
19122             double gap = originalUpper[iColumn] - originalLower[iColumn];
19123             if (!gap)
19124               continue;
19125             if (gap == columnUpper[iColumn] - columnLower[iColumn])
19126               nOriginal++;
19127             if (columnUpper[iColumn] == columnLower[iColumn])
19128               nFixed++;
19129             if (fabs(farkas[iColumn]) < 1.0e-15) {
19130               farkas[iColumn] = 0.0;
19131               continue;
19132             }
19133             // temp
19134             if (gap >= 20000.0 && false) {
19135               // can't use
19136               if (farkas[iColumn] < 0.0) {
19137                 assert(originalLower[iColumn] - columnLower[iColumn] <= 0.0);
19138                 // farkas is negative - relax lower bound all way
19139                 relax += farkas[iColumn] * (originalLower[iColumn] - columnLower[iColumn]);
19140               } else {
19141                 assert(originalUpper[iColumn] - columnUpper[iColumn] >= 0.0);
19142                 // farkas is positive - relax upper bound all way
19143                 relax += farkas[iColumn] * (originalUpper[iColumn] - columnUpper[iColumn]);
19144               }
19145               continue;
19146             }
19147             if (originalLower[iColumn] == columnLower[iColumn]) {
19148               if (farkas[iColumn] > 0.0 && (simplex->getStatus(iColumn) == ClpSimplex::atUpperBound || simplex->getStatus(iColumn) == ClpSimplex::isFixed || iColumn == sequenceOut)) {
19149                 // farkas is positive - add to list
19150                 gap = originalUpper[iColumn] - columnUpper[iColumn];
19151                 if (gap) {
19152                   sort[nConflict] = -farkas[iColumn] * gap;
19153                   conflict[nConflict++] = iColumn;
19154                 }
19155                 //assert (gap>columnUpper[iColumn]-columnLower[iColumn]);
19156               }
19157             } else if (originalUpper[iColumn] == columnUpper[iColumn]) {
19158               if (farkas[iColumn] < 0.0 && (simplex->getStatus(iColumn) == ClpSimplex::atLowerBound || simplex->getStatus(iColumn) == ClpSimplex::isFixed || iColumn == sequenceOut)) {
19159                 // farkas is negative - add to list
19160                 gap = columnLower[iColumn] - originalLower[iColumn];
19161                 if (gap) {
19162                   sort[nConflict] = farkas[iColumn] * gap;
19163                   conflict[nConflict++] = iColumn;
19164                 }
19165                 //assert (gap>columnUpper[iColumn]-columnLower[iColumn]);
19166               }
19167             } else {
19168               // can't use
19169               if (farkas[iColumn] < 0.0) {
19170                 assert(originalLower[iColumn] - columnLower[iColumn] <= 0.0);
19171                 // farkas is negative - relax lower bound all way
19172                 relax += farkas[iColumn] * (originalLower[iColumn] - columnLower[iColumn]);
19173               } else {
19174                 assert(originalUpper[iColumn] - columnUpper[iColumn] >= 0.0);
19175                 // farkas is positive - relax upper bound all way
19176                 relax += farkas[iColumn] * (originalUpper[iColumn] - columnUpper[iColumn]);
19177               }
19178             }
19179             assert(relax >= 0.0);
19180           } else {
19181             // not integer - but may have been got at
19182             double gap = originalUpper[iColumn] - originalLower[iColumn];
19183             if (gap > columnUpper[iColumn] - columnLower[iColumn]) {
19184               // can't use
19185               if (farkas[iColumn] < 0.0) {
19186                 assert(originalLower[iColumn] - columnLower[iColumn] <= 0.0);
19187                 // farkas is negative - relax lower bound all way
19188                 relax += farkas[iColumn] * (originalLower[iColumn] - columnLower[iColumn]);
19189               } else {
19190                 assert(originalUpper[iColumn] - columnUpper[iColumn] >= 0.0);
19191                 // farkas is positive - relax upper bound all way
19192                 relax += farkas[iColumn] * (originalUpper[iColumn] - columnUpper[iColumn]);
19193               }
19194             }
19195           }
19196         }
19197         if (relax + bSum > -1.0e-4 || !nConflict) {
19198           if (relax + bSum > -1.0e-4) {
19199 #ifndef NDEBUG
19200             printf("General integers relax bSum to %g\n", relax + bSum);
19201 #endif
19202           } else {
19203             printf("All variables relaxed and still infeasible - what does this mean?\n");
19204             int nR = 0;
19205             for (int i = 0; i < numberRows; i++) {
19206               if (fabs(ray[i]) > 1.0e-10)
19207                 nR++;
19208               else
19209                 ray[i] = 0.0;
19210             }
19211             int nC = 0;
19212             for (int i = 0; i < numberColumns; i++) {
19213               if (fabs(farkas[i]) > 1.0e-10)
19214                 nC++;
19215               else
19216                 farkas[i] = 0.0;
19217             }
19218             if (nR < 3 && nC < 5) {
19219               printf("BAD %d nonzero rows, %d nonzero columns\n", nR, nC);
19220             }
19221           }
19222         } else {
19223           printf("BOUNDS violation bSum %g (relaxed %g) - %d at original bounds, %d fixed - %d in conflict\n", bSum,
19224             relax + bSum, nOriginal, nFixed, nConflict);
19225           CoinSort_2(sort, sort + nConflict, conflict);
19226           int nC = nConflict;
19227           bSum += relax;
19228           double saveBsum = bSum;
19229           while (nConflict) {
19230             //int iColumn=conflict[nConflict-1];
19231             double change = -sort[nConflict - 1];
19232             if (bSum + change > -1.0e-4)
19233               break;
19234             nConflict--;
19235             bSum += change;
19236           }
19237           if (!nConflict) {
19238             int nR = 0;
19239             for (int i = 0; i < numberRows; i++) {
19240               if (fabs(ray[i]) > 1.0e-10)
19241                 nR++;
19242               else
19243                 ray[i] = 0.0;
19244             }
19245             int nC = 0;
19246             for (int i = 0; i < numberColumns; i++) {
19247               if (fabs(farkas[i]) > 1.0e-10)
19248                 nC++;
19249               else
19250                 farkas[i] = 0.0;
19251             }
19252             if (nR < 3 && nC < 5) {
19253               printf("BAD2 %d nonzero rows, %d nonzero columns\n", nR, nC);
19254             }
19255           }
19256           // no point doing if no reduction (or big?) ?
19257           if (nConflict < nC + 1 && nConflict < 500) {
19258             cut = new OsiRowCut();
19259             cut->setUb(COIN_DBL_MAX);
19260             if (!typeCut) {
19261               double lo = 1.0;
19262               for (int i = 0; i < nConflict; i++) {
19263                 int iColumn = conflict[i];
19264                 if (originalLower[iColumn] == columnLower[iColumn]) {
19265                   // must be at least one higher
19266                   sort[i] = 1.0;
19267                   lo += originalLower[iColumn];
19268                 } else {
19269                   // must be at least one lower
19270                   sort[i] = -1.0;
19271                   lo -= originalUpper[iColumn];
19272                 }
19273               }
19274               cut->setLb(lo);
19275               cut->setRow(nConflict, conflict, sort);
19276               printf("CUT has %d (started at %d) - final bSum %g\n", nConflict, nC, bSum);
19277             } else {
19278               // just save for use later
19279               // first take off small
19280               int nC2 = nC;
19281               while (nC2) {
19282                 //int iColumn=conflict[nConflict-1];
19283                 double change = -sort[nC2 - 1];
19284                 if (saveBsum + change > -1.0e-4 || change > 1.0e-4)
19285                   break;
19286                 nC2--;
19287                 saveBsum += change;
19288               }
19289               cut->setLb(saveBsum);
19290               for (int i = 0; i < nC2; i++) {
19291                 int iColumn = conflict[i];
19292                 sort[i] = farkas[iColumn];
19293               }
19294               cut->setRow(nC2, conflict, sort);
19295               printf("Stem CUT has %d (greedy %d - with small %d) - saved bSum %g final greedy bSum %g\n",
19296                 nC2, nConflict, nC, saveBsum, bSum);
19297             }
19298           }
19299         }
19300         delete[] conflict;
19301         delete[] sort;
19302       }
19303       delete[] farkas;
19304     } else {
19305       printf("No dual ray\n");
19306     }
19307   }
19308 #endif
19309   return cut;
19310 }
19311 
19312 void CbcModel::setMIPStart(int count, const char **colNames, const double colValues[])
19313 {
19314   mipStart_.clear();
19315   for (int i = 0; (i < count); ++i)
19316     mipStart_.push_back(std::pair< std::string, double >(std::string(colNames[i]), colValues[i]));
19317 }
19318 #ifdef COIN_HAS_NTY
19319 // get rid of all
19320 void CbcModel::zapSymmetry()
19321 {
19322   delete symmetryInfo_;
19323   symmetryInfo_ = NULL;
19324 }
19325 #endif
19326 /* Add SOS info to solver -
19327    Overwrites SOS information in solver with information
19328    in CbcModel.  Has no effect with some solvers.
19329    Also updates integer info. */
19330 void CbcModel::addSOSEtcToSolver()
19331 {
19332   // at present just for OsiClp
19333 #ifdef COIN_HAS_CLP
19334   OsiClpSolverInterface *clpSolver
19335     = dynamic_cast< OsiClpSolverInterface * >(solver_);
19336   if (clpSolver) {
19337     int numberColumns = clpSolver->getNumCols();
19338     for (int i = 0; i < numberColumns; i++)
19339       clpSolver->setContinuous(i);
19340     int nOdd = 0;
19341     int numberSOS = 0;
19342     for (int i = 0; i < numberObjects_; i++) {
19343       CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]);
19344       CbcSimpleInteger *thisInt = dynamic_cast< CbcSimpleInteger * >(obj);
19345       OsiSOS *objSOS1 = dynamic_cast< OsiSOS * >(obj);
19346       CbcSOS *objSOS2 = dynamic_cast< CbcSOS * >(obj);
19347       if (thisInt) {
19348         clpSolver->setInteger(thisInt->columnNumber());
19349       } else if (objSOS1) {
19350         numberSOS++;
19351       } else if (objSOS2) {
19352         numberSOS++;
19353       } else {
19354         nOdd++;
19355       }
19356     }
19357     if (nOdd) {
19358       char general[200];
19359       sprintf(general, "%d objects not SOS or Integer - can't move to Osi",
19360         nOdd);
19361       messageHandler()->message(CBC_GENERAL,
19362         messages())
19363         << general << CoinMessageEol;
19364     }
19365     if (numberSOS) {
19366       CoinSet *setInfo = new CoinSet[numberSOS];
19367       numberSOS = 0;
19368       for (int i = 0; i < numberObjects_; i++) {
19369         CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]);
19370         OsiSOS *objSOS1 = dynamic_cast< OsiSOS * >(obj);
19371         CbcSOS *objSOS2 = dynamic_cast< CbcSOS * >(obj);
19372         if (objSOS1 || objSOS2) {
19373           int numberMembers;
19374           const int *members;
19375           int type;
19376           const double *weights;
19377           if (objSOS1) {
19378             numberMembers = objSOS1->numberMembers();
19379             members = objSOS1->members();
19380             type = objSOS1->sosType();
19381             weights = objSOS1->weights();
19382           } else {
19383             numberMembers = objSOS2->numberMembers();
19384             members = objSOS2->members();
19385             type = objSOS2->sosType();
19386             weights = objSOS2->weights();
19387           }
19388           CoinSosSet info(numberMembers, members,
19389             weights, type);
19390           //info.setSetType(type);
19391           //memcpy(info.modifiableWeights(),weights,
19392           //	 numberMembers*sizeof(double));
19393           setInfo[numberSOS++] = info;
19394         }
19395       }
19396       clpSolver->replaceSetInfo(numberSOS, setInfo);
19397     }
19398   }
19399 #endif
19400 }
19401 /*
19402   Clean model i.e. make SOS/integer variables exactly at bound if needed
19403   Only if moreSpecialOptions2_ 32768
19404   Returns number of variables forced out
19405   cleanVariables array will be used if exists
19406 */
19407 int CbcModel::cleanBounds(OsiSolverInterface *solver, char *cleanIn)
19408 {
19409   int numberBad = 0;
19410 #ifdef COIN_HAS_CLP
19411 #ifndef ZERO_ODD_TOLERANCE
19412 #define ZERO_ODD_TOLERANCE 1.0e-14
19413 #endif
19414   OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(solver);
19415   if (osiclp && osiclp->isProvenOptimal()) {
19416     int numberColumns = osiclp->getNumCols();
19417     char *cleanVariables;
19418     if (!cleanIn) {
19419       cleanVariables = setupCleanVariables();
19420     } else {
19421       cleanVariables = cleanIn;
19422     }
19423     // If any small values re-do
19424     ClpSimplex *clp = osiclp->getModelPtr();
19425     double *solution = clp->primalColumnSolution();
19426     const double *columnLower = clp->columnLower();
19427     const double *columnUpper = clp->columnUpper();
19428     //#define SHOW_BAD
19429 #ifdef SHOW_BAD
19430     double sumBadLow = 0.0;
19431     double sumBadHigh = 0.0;
19432     double maxBadLow = 0.0;
19433     double maxBadHigh = 0.0;
19434 #endif
19435     for (int i = 0; i < numberColumns; i++) {
19436       if (cleanVariables[i]) {
19437         if (solution[i] > columnUpper[i] + ZERO_ODD_TOLERANCE) {
19438           numberBad++;
19439 #ifdef SHOW_BAD
19440           sumBadHigh += solution[i] - columnUpper[i];
19441           maxBadHigh = CoinMax(maxBadHigh, solution[i] - columnUpper[i]);
19442 #endif
19443         } else if (solution[i] < columnLower[i] - ZERO_ODD_TOLERANCE) {
19444           numberBad++;
19445 #ifdef SHOW_BAD
19446           sumBadLow += columnLower[i] - solution[i];
19447           maxBadLow = CoinMax(maxBadLow, columnLower[i] - solution[i]);
19448 #endif
19449         }
19450       }
19451     }
19452     if (numberBad) {
19453 #ifdef SHOW_BAD
19454       printf("%d small variables low (%g max %g), high (%g max %g)\n", numberBad, sumBadLow, maxBadLow, sumBadHigh, maxBadHigh);
19455 #endif
19456       for (int i = 0; i < numberColumns; i++) {
19457         if (cleanVariables[i]) {
19458           if (solution[i] > columnUpper[i] + ZERO_ODD_TOLERANCE) {
19459             solution[i] = columnUpper[i];
19460             clp->setColumnStatus(i, ClpSimplex::atUpperBound);
19461           } else if (solution[i] < columnLower[i] - ZERO_ODD_TOLERANCE) {
19462             solution[i] = columnLower[i];
19463             clp->setColumnStatus(i, ClpSimplex::atLowerBound);
19464           }
19465         }
19466       }
19467       int saveLevel = clp->logLevel();
19468       clp->setLogLevel(0);
19469       clp->dual();
19470       clp->setLogLevel(saveLevel);
19471     }
19472     if (!cleanIn)
19473       delete[] cleanVariables;
19474   }
19475 #endif
19476   return numberBad;
19477 }
19478 // Sets up cleanVariables array (i.e. ones to be careful about)
19479 char *
19480 CbcModel::setupCleanVariables()
19481 {
19482   OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(solver_);
19483   int numberColumns = osiclp->getNumCols();
19484   char *cleanVariables = NULL;
19485   if (osiclp) {
19486     cleanVariables = new char[numberColumns];
19487     memset(cleanVariables, 0, numberColumns);
19488     for (int i = 0; i < numberObjects_; i++) {
19489       const CbcSimpleInteger *intvar = dynamic_cast< const CbcSimpleInteger * >(object_[i]);
19490       const CbcSOS *sos = dynamic_cast< const CbcSOS * >(object_[i]);
19491       if (intvar) {
19492 #ifdef CLEAN_INTEGER_VARIABLES
19493         cleanVariables[intvar->columnNumber()] = 1;
19494 #endif
19495       } else if (sos) {
19496         int n = sos->numberMembers();
19497         const int *members = sos->members();
19498         for (int j = 0; j < n; j++)
19499           cleanVariables[members[j]] = 2;
19500       }
19501     }
19502   }
19503   return cleanVariables;
19504 }
19505 /* Returns postProcessed solution in solver(called from event handler)
19506    Normally used for integer solution (not really tested otherwise)
19507    solutionType 1 is best integer so far, 0 is current solution
19508    (may not be integer) */
19509 const OsiSolverInterface *
19510 CbcModel::postProcessedSolver(int solutionType)
19511 {
19512   CbcModel *model = this;
19513   CglPreProcess *processPointer = model->preProcess();
19514   OsiSolverInterface *originalModel = NULL;
19515   const double *solution = bestSolution();
19516   while (processPointer) {
19517     int numberSolvers = processPointer->numberSolvers();
19518     OsiSolverInterface *solver = processPointer->presolve(numberSolvers - 1)->presolvedModel();
19519     if (solutionType) {
19520       // massage solution
19521       int numberColumns = solver->getNumCols();
19522       double *saveLower = CoinCopyOfArray(model->solver()->getColLower(), numberColumns);
19523       double *saveUpper = CoinCopyOfArray(model->solver()->getColUpper(), numberColumns);
19524       const double *saveSolution = testSolution_;
19525       setTestSolution(solution);
19526       model->solver()->setColLower(solution);
19527       model->solver()->setColUpper(solution);
19528       OsiBranchingInformation usefulInfo = model->usefulInformation();
19529       /*
19530 	Run through the objects and use feasibleRegion() to set variable bounds
19531 	so as to fix the variables specified in the objects at their value in this
19532 	solution. Since the object list contains (at least) one object for every
19533 	integer variable, this has the effect of fixing all integer variables.
19534       */
19535       for (int i = 0; i < model->numberObjects(); i++)
19536         model->object(i)->feasibleRegion(solver, &usefulInfo);
19537       setTestSolution(saveSolution);
19538       model->solver()->setColLower(saveLower);
19539       model->solver()->setColUpper(saveUpper);
19540       delete[] saveLower;
19541       delete[] saveUpper;
19542     }
19543     solver->resolve();
19544     processPointer->postProcess(*solver, false);
19545     originalModel = processPointer->originalModel();
19546     solution = originalModel->getColSolution();
19547     processPointer = NULL;
19548     model = model->parentModel();
19549     processPointer = model ? model->preProcess() : NULL;
19550   }
19551   return originalModel;
19552 }
19553 // Delete a node and possibly null out currentNode_
19554 void
19555 CbcModel::deleteNode(CbcNode * node)
19556 {
19557   delete node;
19558   if (node==currentNode_)
19559     currentNode_ = NULL;
19560 }
19561 
19562