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_&¤tDepth_==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&¤tDepth_&&!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