1 // Copyright (C) 2005, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 // This code is licensed under the terms of the Eclipse Public License (EPL).
4
5 #include <string>
6 #include <cassert>
7 #include <cmath>
8 #include <vector>
9 #include <algorithm>
10 #include <cfloat>
11
12 #include "CoinPragma.hpp"
13 #include "CglPreProcess.hpp"
14 #include "CglMessage.hpp"
15 #include "OsiRowCut.hpp"
16 #include "OsiColCut.hpp"
17 #include "OsiRowCutDebugger.hpp"
18 #include "CglStored.hpp"
19 #include "CglCutGenerator.hpp"
20 #include "CoinTime.hpp"
21 #include "CoinSort.hpp"
22 #include "CoinDenseFactorization.hpp"
23 #include "CoinBuild.hpp"
24 #include "CoinHelperFunctions.hpp"
25 #include "CoinWarmStartBasis.hpp"
26
27 #include "CglProbing.hpp"
28 #include "CglDuplicateRow.hpp"
29 #include "CglClique.hpp"
30 //#define PRINT_DEBUG 1
31 //#define COIN_DEVELOP 1
32 #ifdef COIN_DEVELOP
33 static int whichMps = 0;
34 char nameMps[50];
35 #endif
36
37 OsiSolverInterface *
preProcess(OsiSolverInterface & model,bool makeEquality,int numberPasses)38 CglPreProcess::preProcess(OsiSolverInterface &model,
39 bool makeEquality, int numberPasses)
40 {
41 // Tell solver we are in Branch and Cut
42 model.setHintParam(OsiDoInBranchAndCut, true, OsiHintDo);
43 // Default set of cut generators
44 CglProbing generator1;
45 generator1.setUsingObjective(true);
46 generator1.setMaxPass(3);
47 generator1.setMaxProbeRoot(model.getNumCols());
48 generator1.setMaxElements(100);
49 generator1.setMaxLookRoot(50);
50 generator1.setRowCuts(3);
51 // Add in generators
52 addCutGenerator(&generator1);
53 OsiSolverInterface *newSolver = preProcessNonDefault(model, makeEquality ? 1 : 0, numberPasses);
54 // Tell solver we are not in Branch and Cut
55 model.setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
56 if (newSolver)
57 newSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
58 return newSolver;
59 }
outSingletons(int & nCol,int & nRow,int * startCol,int * row,double * element,int * startRow,int * column)60 static void outSingletons(int &nCol, int &nRow,
61 int *startCol, int *row, double *element,
62 int *startRow, int *column)
63 {
64 int iRow, iCol;
65 bool singletons = false;
66 int *countRow = new int[nRow];
67 int *countCol = new int[nCol];
68 int *temp = new int[nRow];
69 // make row copy
70 memset(countRow, 0, nRow * sizeof(int));
71 memset(countCol, 0, nCol * sizeof(int));
72 for (iCol = 0; iCol < nCol; iCol++) {
73 for (int j = startCol[iCol]; j < startCol[iCol + 1]; j++) {
74 int iRow = row[j];
75 countRow[iRow]++;
76 countCol[iCol]++;
77 }
78 }
79 startRow[0] = 0;
80 for (iRow = 0; iRow < nRow; iRow++) {
81 int k = countRow[iRow] + startRow[iRow];
82 temp[iRow] = startRow[iRow];
83 startRow[iRow + 1] = k;
84 }
85 for (iCol = 0; iCol < nCol; iCol++) {
86 for (int j = startCol[iCol]; j < startCol[iCol + 1]; j++) {
87 int iRow = row[j];
88 int k = temp[iRow];
89 temp[iRow]++;
90 column[k] = iCol;
91 }
92 }
93 for (iRow = 0; iRow < nRow; iRow++) {
94 if (countRow[iRow] <= 1)
95 singletons = true;
96 }
97 for (iCol = 0; iCol < nCol; iCol++) {
98 if (countCol[iCol] <= 1)
99 singletons = true;
100 }
101 if (singletons) {
102 while (singletons) {
103 singletons = false;
104 for (iCol = 0; iCol < nCol; iCol++) {
105 if (countCol[iCol] == 1) {
106 singletons = true;
107 countCol[iCol] = 0;
108 int iRow = row[startCol[iCol]];
109 int start = startRow[iRow];
110 int end = start + countRow[iRow];
111 countRow[iRow]--;
112 int j;
113 for (j = start; j < end; j++) {
114 if (column[j] == iCol) {
115 column[j] = column[end - 1];
116 break;
117 }
118 }
119 assert(j < end);
120 }
121 }
122 for (iRow = 0; iRow < nRow; iRow++) {
123 if (countRow[iRow] == 1) {
124 singletons = true;
125 countRow[iRow] = 0;
126 int iCol = column[startRow[iRow]];
127 int start = startCol[iCol];
128 int end = start + countCol[iCol];
129 countCol[iCol]--;
130 int j;
131 for (j = start; j < end; j++) {
132 if (row[j] == iRow) {
133 row[j] = row[end - 1];
134 if (element)
135 element[j] = element[end - 1];
136 break;
137 }
138 }
139 assert(j < end);
140 }
141 }
142 }
143 // Pack down
144 int newNrow = 0;
145 for (iRow = 0; iRow < nRow; iRow++) {
146 if (countRow[iRow] == 0) {
147 temp[iRow] = -1;
148 } else {
149 assert(countRow[iRow] > 1);
150 temp[iRow] = newNrow;
151 newNrow++;
152 }
153 }
154 int newNcol = 0;
155 int nEl = 0;
156 int iNext = 0;
157 for (iCol = 0; iCol < nCol; iCol++) {
158 int start = iNext;
159 iNext = startCol[iCol + 1];
160 if (countCol[iCol] == 0) {
161 countCol[iCol] = -1;
162 } else {
163 assert(countCol[iCol] > 1);
164 int end = start + countCol[iCol];
165 countCol[iCol] = newNcol;
166 int j;
167 for (j = start; j < end; j++) {
168 int iRow = row[j];
169 iRow = temp[iRow];
170 assert(iRow >= 0);
171 row[nEl] = iRow;
172 if (element)
173 element[nEl] = element[j];
174 nEl++;
175 }
176 newNcol++;
177 startCol[newNcol] = nEl;
178 }
179 }
180 newNrow = 0;
181 nEl = 0;
182 iNext = 0;
183 for (iRow = 0; iRow < nRow; iRow++) {
184 int start = iNext;
185 iNext = startRow[iRow + 1];
186 if (countRow[iRow] > 1) {
187 int end = start + countRow[iRow];
188 int j;
189 for (j = start; j < end; j++) {
190 int iCol = column[j];
191 iCol = countCol[iCol];
192 assert(iCol >= 0);
193 column[nEl++] = iCol;
194 }
195 newNrow++;
196 startRow[newNrow] = nEl;
197 }
198 }
199 nRow = newNrow;
200 nCol = newNcol;
201 }
202 delete[] countCol;
203 delete[] countRow;
204 delete[] temp;
205 }
makeIntegers2(OsiSolverInterface * model,int mode)206 static int makeIntegers2(OsiSolverInterface *model, int mode)
207 {
208 // See whether we should make variables integer
209 const double *objective = model->getObjCoefficients();
210 const double *lower = model->getColLower();
211 const double *upper = model->getColUpper();
212 const double *rowLower = model->getRowLower();
213 const double *rowUpper = model->getRowUpper();
214 int numberRows = model->getNumRows();
215 double *rhs = new double[numberRows];
216 int *count = new int[numberRows];
217 int iColumn;
218 bool makeAll = (mode > 1);
219 int numberColumns = model->getNumCols();
220 // Column copy of matrix
221 const double *element = model->getMatrixByCol()->getElements();
222 const int *row = model->getMatrixByCol()->getIndices();
223 const CoinBigIndex *columnStart = model->getMatrixByCol()->getVectorStarts();
224 const int *columnLength = model->getMatrixByCol()->getVectorLengths();
225 // Row copy
226 CoinPackedMatrix matrixByRow(*model->getMatrixByRow());
227 //const double * elementByRow = matrixByRow.getElements();
228 const int *column = matrixByRow.getIndices();
229 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
230 const int *rowLength = matrixByRow.getVectorLengths();
231 int numberIntegers = 1;
232 int totalNumberIntegers = 0;
233 while (numberIntegers) {
234 memset(rhs, 0, numberRows * sizeof(double));
235 memset(count, 0, numberRows * sizeof(int));
236 int currentNumber = 0;
237 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
238 CoinBigIndex start = columnStart[iColumn];
239 CoinBigIndex end = start + columnLength[iColumn];
240 if (upper[iColumn] == lower[iColumn]) {
241 for (CoinBigIndex j = start; j < end; j++) {
242 int iRow = row[j];
243 rhs[iRow] += lower[iColumn] * element[j];
244 }
245 } else if (model->isInteger(iColumn)) {
246 currentNumber++;
247 for (CoinBigIndex j = start; j < end; j++) {
248 int iRow = row[j];
249 if (fabs(element[j] - floor(element[j] + 0.5)) > 1.0e-10)
250 rhs[iRow] = COIN_DBL_MAX;
251 }
252 } else {
253 for (CoinBigIndex j = start; j < end; j++) {
254 int iRow = row[j];
255 count[iRow]++;
256 if (fabs(element[j]) != 1.0)
257 rhs[iRow] = COIN_DBL_MAX;
258 }
259 }
260 }
261 #if CBC_USEFUL_PRINTING > 1
262 printf("Current number of integers is %d\n", currentNumber);
263 #endif
264 // now look at continuous
265 bool allGood = true;
266 double direction = model->getObjSense();
267 int numberObj = 0;
268 int numberEq = 0;
269 int numberEqI = 0;
270 int numberZero = 0;
271 int numberNonZero = 0;
272 if (false) {
273 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
274 if (upper[iColumn] > lower[iColumn]) {
275 if (!model->isInteger(iColumn)) {
276 CoinBigIndex start = columnStart[iColumn];
277 CoinBigIndex end = start + columnLength[iColumn];
278 int nC = 0;
279 for (CoinBigIndex j = start; j < end; j++) {
280 int iRow = row[j];
281 if (count[iRow] > 1) {
282 nC++;
283 }
284 }
285 if (nC > 2) {
286 for (CoinBigIndex j = start; j < end; j++) {
287 int iRow = row[j];
288 if (count[iRow] > 1)
289 count[iRow] = 999999;
290 }
291 }
292 }
293 }
294 }
295 }
296 int *newInts = new int[numberColumns];
297 // Columns to zap
298 int nColumnZap = 0;
299 int *columnZap = new int[numberColumns];
300 char *noGoodColumn = new char[numberColumns];
301 memset(noGoodColumn, 0, numberColumns);
302 int nNew = 0;
303 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
304 if (upper[iColumn] > lower[iColumn]) {
305 double objValue = objective[iColumn] * direction;
306 bool thisGood = true;
307 if ((objValue || makeAll) && !model->isInteger(iColumn)) {
308 if (objValue) {
309 numberObj++;
310 } else if (columnLength[iColumn] == 1) {
311 continue; // don't bother with singletons
312 }
313 CoinBigIndex start = columnStart[iColumn];
314 CoinBigIndex end = start + columnLength[iColumn];
315 if (objValue >= 0.0) {
316 // wants to be as low as possible
317 if (lower[iColumn] < -1.0e10 || fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
318 thisGood = false;
319 } else if (upper[iColumn] < 1.0e10 && fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
320 thisGood = false;
321 }
322 bool singletonRow = true;
323 bool equality = false;
324 int nC = 0;
325 int xxxx = 0;
326 #if CBC_USEFUL_PRINTING
327 bool badCount = false;
328 #endif
329 for (CoinBigIndex j = start; j < end; j++) {
330 int iRow = row[j];
331 if (count[iRow] > 1) {
332 singletonRow = false;
333 //printf("col %d row%d element %g - row count %d\n",iColumn,iRow,element[j],count[iRow]);
334 #if CBC_USEFUL_PRINTING
335 if (count[iRow] == 999999)
336 badCount = true;
337 #endif
338 if (element[j] == 1.0) {
339 if ((xxxx & 1) == 0)
340 xxxx |= 1;
341 else
342 xxxx = 15;
343 } else {
344 if ((xxxx & 2) == 0)
345 xxxx |= 2;
346 else
347 xxxx = 15;
348 }
349 nC++;
350 } else if (rowLower[iRow] == rowUpper[iRow]) {
351 equality = true;
352 }
353 double rhsValue = rhs[iRow];
354 double lowerValue = rowLower[iRow];
355 double upperValue = rowUpper[iRow];
356 if (rhsValue < 1.0e20) {
357 if (lowerValue > -1.0e20)
358 lowerValue -= rhsValue;
359 if (upperValue < 1.0e20)
360 upperValue -= rhsValue;
361 }
362 if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
363 || fabs(element[j]) != 1.0) {
364 // no good
365 thisGood = false;
366 break;
367 }
368 if (element[j] > 0.0) {
369 if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
370 // no good
371 thisGood = false;
372 break;
373 }
374 } else {
375 if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
376 // no good
377 thisGood = false;
378 break;
379 }
380 }
381 }
382 #if CBC_USEFUL_PRINTING
383 if (!model->isInteger(iColumn) && false)
384 printf("%d has %d rows with >1 - state network %s interaction %s\n", iColumn, nC, xxxx > 3 ? "bad" : "good",
385 badCount ? "too much" : "ok");
386 #endif
387 // If not good here then mark rows
388 if (!thisGood) {
389 for (CoinBigIndex j = start; j < end; j++) {
390 int iRow = row[j];
391 count[iRow] = 999999;
392 }
393 }
394 if (!singletonRow && end > start + 1 && !equality)
395 thisGood = false;
396 // Can we make equality
397 if (end == start + 1 && !equality && false) {
398 numberEq++;
399 int iRow = row[start];
400 if (element[start] > 0.0)
401 model->setRowUpper(iRow, rowLower[iRow]);
402 else
403 model->setRowLower(iRow, rowUpper[iRow]);
404 }
405 } else {
406 // wants to be as high as possible
407 if (upper[iColumn] > 1.0e10 || fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) {
408 thisGood = false;
409 } else if (lower[iColumn] > -1.0e10 && fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) {
410 thisGood = false;
411 }
412 bool singletonRow = true;
413 bool equality = false;
414 for (CoinBigIndex j = start; j < end; j++) {
415 int iRow = row[j];
416 if (count[iRow] > 1) {
417 singletonRow = false;
418 thisGood = false;
419 } else if (rowLower[iRow] == rowUpper[iRow]) {
420 equality = true;
421 }
422 double rhsValue = rhs[iRow];
423 double lowerValue = rowLower[iRow];
424 double upperValue = rowUpper[iRow];
425 if (rhsValue < 1.0e20) {
426 if (lowerValue > -1.0e20)
427 lowerValue -= rhsValue;
428 if (upperValue < 1.0e20)
429 upperValue -= rhsValue;
430 }
431 if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10
432 || fabs(element[j]) != 1.0) {
433 // no good
434 thisGood = false;
435 break;
436 }
437 if (element[j] < 0.0) {
438 if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) {
439 // no good
440 thisGood = false;
441 break;
442 }
443 } else {
444 if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) {
445 // no good
446 thisGood = false;
447 break;
448 }
449 }
450 }
451 if (!singletonRow && end > start + 1 && !equality)
452 thisGood = false;
453 // If not good here then mark rows
454 if (!thisGood) {
455 for (CoinBigIndex j = start; j < end; j++) {
456 int iRow = row[j];
457 count[iRow] = 999999;
458 }
459 }
460 // Can we make equality
461 if (end == start + 1 && !equality && false) {
462 numberEq++;
463 int iRow = row[start];
464 if (element[start] < 0.0)
465 model->setRowUpper(iRow, rowLower[iRow]);
466 else
467 model->setRowLower(iRow, rowUpper[iRow]);
468 }
469 }
470 } else if (objValue) {
471 CoinBigIndex start = columnStart[iColumn];
472 CoinBigIndex end = start + columnLength[iColumn];
473 if (end == start + 1) {
474 int iRow = row[start];
475 if (rowUpper[iRow] > rowLower[iRow] && !count[iRow]) {
476 if (fabs(rhs[iRow]) > 1.0e20 || fabs(rhs[iRow] - floor(rhs[iRow] + 0.5)) > 1.0e-10
477 || fabs(element[start]) != 1.0) {
478 // no good
479 } else if (false) {
480 numberEqI++;
481 if (element[start] * objValue > 0.0)
482 model->setRowUpper(iRow, rowLower[iRow]);
483 else
484 model->setRowLower(iRow, rowUpper[iRow]);
485 }
486 }
487 }
488 }
489 if (!thisGood) {
490 if (objValue)
491 allGood = false;
492 // look at again
493 columnZap[nColumnZap++] = iColumn;
494 } else if (makeAll && !model->isInteger(iColumn) && upper[iColumn] - lower[iColumn] < 10) {
495 newInts[nNew++] = iColumn;
496 }
497 }
498 }
499 // Rows to look at
500 int *rowLook = new int[numberRows];
501 while (nColumnZap) {
502 int nRowLook = 0;
503 for (int i = 0; i < nColumnZap; i++) {
504 int iColumn = columnZap[i];
505 noGoodColumn[iColumn] = 1;
506 CoinBigIndex start = columnStart[iColumn];
507 CoinBigIndex end = start + columnLength[iColumn];
508 for (CoinBigIndex j = start; j < end; j++) {
509 int iRow = row[j];
510 if (count[iRow] != 999999) {
511 count[iRow] = 999999;
512 rowLook[nRowLook++] = iRow;
513 }
514 }
515 }
516 nColumnZap = 0;
517 if (nRowLook) {
518 for (int i = 0; i < nRowLook; i++) {
519 int iRow = rowLook[i];
520 CoinBigIndex start = rowStart[iRow];
521 CoinBigIndex end = start + rowLength[iRow];
522 for (CoinBigIndex j = start; j < end; j++) {
523 int iColumn = column[j];
524 if (upper[iColumn] > lower[iColumn] && !model->isInteger(iColumn)) {
525 if (!noGoodColumn[iColumn]) {
526 noGoodColumn[iColumn] = 1;
527 columnZap[nColumnZap++] = iColumn;
528 }
529 }
530 }
531 }
532 }
533 }
534 delete[] rowLook;
535 delete[] noGoodColumn;
536 delete[] columnZap;
537 // Final look
538 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
539 if (upper[iColumn] > lower[iColumn] && !model->isInteger(iColumn) && objective[iColumn]) {
540 CoinBigIndex start = columnStart[iColumn];
541 CoinBigIndex end = start + columnLength[iColumn];
542 for (CoinBigIndex j = start; j < end; j++) {
543 int iRow = row[j];
544 if (count[iRow] == 999999)
545 allGood = false;
546 }
547 }
548 }
549 // do if some but not too many
550 if (nNew && nNew < currentNumber) {
551 double tolerance;
552 model->getDblParam(OsiPrimalTolerance, tolerance);
553 for (int i = 0; i < nNew; i++) {
554 int iColumn = newInts[i];
555 double objValue = objective[iColumn];
556 bool thisGood = true;
557 CoinBigIndex start = columnStart[iColumn];
558 CoinBigIndex end = start + columnLength[iColumn];
559 for (CoinBigIndex j = start; j < end; j++) {
560 int iRow = row[j];
561 if (count[iRow] == 999999) {
562 thisGood = false;
563 break;
564 }
565 }
566 if (thisGood && upper[iColumn] < lower[iColumn] + 10.0) {
567 model->setInteger(iColumn);
568 // clean up bounds
569 model->setColLower(iColumn, ceil(lower[iColumn] - tolerance));
570 model->setColUpper(iColumn, floor(upper[iColumn] + tolerance));
571 if (objValue)
572 numberNonZero++;
573 else
574 numberZero++;
575 } else if (objValue) {
576 // unable to fix all with obj
577 allGood = false;
578 }
579 }
580 }
581 delete[] newInts;
582 // Can we look at remainder and make any integer
583 if (makeAll && false) {
584 int nLook = 0;
585 int nEl = 0;
586 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
587 if (upper[iColumn] > lower[iColumn] && !model->isInteger(iColumn)) {
588 CoinBigIndex start = columnStart[iColumn];
589 CoinBigIndex end = start + columnLength[iColumn];
590 bool possible = true;
591 int n = 0;
592 for (CoinBigIndex j = start; j < end; j++) {
593 int iRow = row[j];
594 if (count[iRow] > 1) {
595 if (count[iRow] == 999999) {
596 possible = false;
597 break;
598 } else {
599 n++;
600 }
601 }
602 }
603 if (possible) {
604 nLook++;
605 nEl += n;
606 }
607 }
608 }
609 if (nLook) {
610 int *startC = new int[nLook + 1];
611 int *back = new int[nLook];
612 int *row2 = new int[nEl];
613 double *element2 = new double[nEl];
614 int *backRow = new int[numberRows];
615 int jRow;
616 for (jRow = 0; jRow < numberRows; jRow++) {
617 backRow[jRow] = -1;
618 }
619 int nCol = nLook;
620 nLook = 0;
621 nEl = 0;
622 startC[0] = 0;
623 int nRow = 0;
624 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
625 if (upper[iColumn] > lower[iColumn] && !model->isInteger(iColumn)) {
626 CoinBigIndex start = columnStart[iColumn];
627 CoinBigIndex end = start + columnLength[iColumn];
628 bool possible = true;
629 int n = 0;
630 for (CoinBigIndex j = start; j < end; j++) {
631 int iRow = row[j];
632 if (count[iRow] > 1) {
633 if (count[iRow] == 999999) {
634 possible = false;
635 break;
636 } else {
637 n++;
638 }
639 }
640 }
641 if (!n)
642 possible = false; // may be done later
643 if (possible) {
644 back[nLook] = iColumn;
645 for (CoinBigIndex j = start; j < end; j++) {
646 int iRow = row[j];
647 if (count[iRow] > 1) {
648 int jRow = backRow[iRow];
649 if (jRow < 0) {
650 // new row
651 backRow[iRow] = nRow;
652 jRow = nRow;
653 nRow++;
654 }
655 element2[nEl] = element[j];
656 row2[nEl++] = jRow;
657 }
658 }
659 nLook++;
660 startC[nLook] = nEl;
661 }
662 }
663 }
664 // Redo nCol
665 nCol = nLook;
666 delete[] backRow;
667 int *startRow = new int[nRow + 1];
668 int *column2 = new int[nEl];
669 // take out singletons and do row copy
670 outSingletons(nCol, nRow,
671 startC, row2, element2,
672 startRow, column2);
673 // Decompose
674 int *rowBlock = new int[nRow];
675 int *stack = new int[nRow];
676 for (int iRow = 0; iRow < nRow; iRow++)
677 rowBlock[iRow] = -2;
678 int numberBlocks = 0;
679 // to say if column looked at
680 int *columnBlock = new int[nCol];
681 int iColumn;
682 for (iColumn = 0; iColumn < nCol; iColumn++)
683 columnBlock[iColumn] = -2;
684 for (iColumn = 0; iColumn < nCol; iColumn++) {
685 int kstart = startC[iColumn];
686 int kend = startC[iColumn + 1];
687 if (columnBlock[iColumn] == -2) {
688 // column not allocated
689 int j;
690 int nstack = 0;
691 for (j = kstart; j < kend; j++) {
692 int iRow = row2[j];
693 if (rowBlock[iRow] != -1) {
694 assert(rowBlock[iRow] == -2);
695 rowBlock[iRow] = numberBlocks; // mark
696 stack[nstack++] = iRow;
697 }
698 }
699 if (nstack) {
700 // new block - put all connected in
701 numberBlocks++;
702 columnBlock[iColumn] = numberBlocks - 1;
703 while (nstack) {
704 int iRow = stack[--nstack];
705 int k;
706 for (k = startRow[iRow]; k < startRow[iRow + 1]; k++) {
707 int iColumn = column2[k];
708 int kkstart = startC[iColumn];
709 int kkend = startC[iColumn + 1];
710 if (columnBlock[iColumn] == -2) {
711 columnBlock[iColumn] = numberBlocks - 1; // mark
712 // column not allocated
713 int jj;
714 for (jj = kkstart; jj < kkend; jj++) {
715 int jRow = row2[jj];
716 if (rowBlock[jRow] == -2) {
717 rowBlock[jRow] = numberBlocks - 1;
718 stack[nstack++] = jRow;
719 }
720 }
721 } else {
722 assert(columnBlock[iColumn] == numberBlocks - 1);
723 }
724 }
725 }
726 } else {
727 // Only in master
728 columnBlock[iColumn] = -1;
729 // empty - should already be integer
730 abort();
731 }
732 }
733 }
734 // See if each block OK
735 for (int iBlock = 0; iBlock < numberBlocks; iBlock++) {
736 // Get block
737 int *startCB = new int[nCol + 1];
738 int *row2B = new int[nEl];
739 int *startCC = new int[nCol + 1];
740 int *row2C = new int[nEl];
741 int *startRowC = new int[nRow + 1];
742 int *column2C = new int[nEl];
743 int *whichRow = new int[nRow];
744 int *whichCol = new int[nCol];
745 int i;
746 int nRowB = 0;
747 int nColB = 0;
748 int nElB = 0;
749 for (i = 0; i < nRow; i++) {
750 if (rowBlock[i] == iBlock) {
751 whichRow[i] = nRowB;
752 nRowB++;
753 } else {
754 whichRow[i] = -1;
755 }
756 }
757 bool network = true;
758 // even if not network - take out network columns NO
759 startCB[0] = 0;
760 for (i = 0; i < nCol; i++) {
761 if (columnBlock[i] == iBlock) {
762 int type = 0;
763 whichCol[i] = nColB;
764 for (int j = startC[i]; j < startC[i + 1]; j++) {
765 int iRow = row2[j];
766 iRow = whichRow[iRow];
767 if (iRow >= 0) {
768 if (element2[j] == 1.0) {
769 if ((type & 1) == 0)
770 type |= 1;
771 else
772 type = 7;
773 } else {
774 assert(element2[j] == -1.0);
775 if ((type & 2) == 0)
776 type |= 2;
777 else
778 type = 7;
779 }
780 row2B[nElB++] = iRow;
781 }
782 }
783 if (type != 3)
784 network = false;
785 nColB++;
786 startCB[nColB] = nElB;
787 assert(startCB[nColB] > startCB[nColB - 1] + 1);
788 } else {
789 whichCol[i] = -1;
790 }
791 }
792 // See if network
793 bool goodInteger = false;
794 if (!network) {
795 // take out singletons
796 outSingletons(nColB, nRowB,
797 startCB, row2B, NULL,
798 startRowC, column2C);
799 // See if totally balanced;
800 int *split = new int[nRowB];
801 int *best = new int[nRowB];
802 int *current = new int[nRowB];
803 int *size = new int[nRowB];
804 {
805 memset(size, 0, nRowB * sizeof(int));
806 for (i = 0; i < nColB; i++) {
807 int j;
808 for (j = startCB[i]; j < startCB[i + 1]; j++) {
809 int iRow = row2B[j];
810 size[iRow]++;
811 }
812 }
813 #if CBC_USEFUL_PRINTING
814 for (i = 0; i < nRowB; i++)
815 if (size[i] < 2)
816 printf("%d entries in row %d\n", size[i], i);
817 #endif
818 }
819 for (i = 0; i < nColB; i++)
820 whichCol[i] = i;
821 for (i = 0; i < nRowB; i++)
822 whichRow[i] = 0;
823 int nLeft = nColB;
824 int nSet = 1;
825 size[0] = nRowB;
826 while (nLeft) {
827 // find best column
828 int iBest = -1;
829 memset(best, 0, nSet * sizeof(int));
830 memset(current, 0, nSet * sizeof(int));
831 for (i = 0; i < nColB; i++) {
832 if (whichCol[i] < nLeft) {
833 int j;
834 for (j = startCB[i]; j < startCB[i + 1]; j++) {
835 int iRow = row2B[j];
836 int iSet = whichRow[iRow];
837 current[iSet]++;
838 }
839 // See if better - could this be done faster
840 bool better = false;
841 for (j = nSet - 1; j >= 0; j--) {
842 if (current[j] > best[j]) {
843 better = true;
844 break;
845 } else if (current[j] < best[j]) {
846 break;
847 }
848 }
849 if (better) {
850 iBest = i;
851 memcpy(best, current, nSet * sizeof(int));
852 }
853 for (j = startCB[i]; j < startCB[i + 1]; j++) {
854 int iRow = row2B[j];
855 int iSet = whichRow[iRow];
856 current[iSet] = 0;
857 }
858 }
859 }
860 assert(iBest >= 0);
861 // swap
862 for (i = 0; i < nColB; i++) {
863 if (whichCol[i] == nLeft - 1) {
864 whichCol[i] = whichCol[iBest];
865 whichCol[iBest] = nLeft - 1;
866 break;
867 }
868 }
869 // See which ones will have to split
870 int nMore = 0;
871 for (i = 0; i < nSet; i++) {
872 current[i] = i + nMore;
873 if (best[i] > 0 && best[i] < size[i]) {
874 split[i] = i + nMore;
875 nMore++;
876 } else {
877 split[i] = -1;
878 }
879 }
880 if (nMore) {
881 int j;
882 for (j = startCB[iBest]; j < startCB[iBest + 1]; j++) {
883 int iRow = row2B[j];
884 int iSet = whichRow[iRow];
885 int newSet = split[iSet];
886 if (newSet >= 0) {
887 whichRow[iRow] = newSet + 1 + nRowB;
888 }
889 }
890 nSet += nMore;
891 memset(size, 0, nSet * sizeof(int));
892 for (i = 0; i < nRowB; i++) {
893 int iSet = whichRow[i];
894 if (iSet >= nRowB) {
895 // has 1 - correct it
896 iSet -= nRowB;
897 } else {
898 // 0 part of split set or not split
899 iSet = current[iSet];
900 }
901 whichRow[i] = iSet;
902 size[iSet]++;
903 }
904 }
905 nLeft--;
906 }
907 if (nSet < nRowB) {
908 // ties - need to spread out whichRow
909 memset(split, 0, nRowB * sizeof(int));
910 for (i = 0; i < nRowB; i++) {
911 int iSet = whichRow[i];
912 split[iSet]++;
913 }
914 current[0] = 0;
915 for (i = 0; i < nSet; i++) {
916 current[i + 1] = current[i] + split[i];
917 split[i] = current[i];
918 }
919 for (i = 0; i < nRowB; i++) {
920 int iSet = whichRow[i];
921 int k = split[iSet];
922 split[iSet] = k;
923 whichRow[i] = k;
924 }
925 }
926 // Get inverse of whichCol
927 for (i = 0; i < nColB; i++) {
928 int iColumn = whichCol[i];
929 startCC[iColumn] = i;
930 }
931 memcpy(whichCol, startCC, nColB * sizeof(int));
932 // Permute matrix
933 startCC[0] = 0;
934 int nelB = 0;
935 memset(split, 0, nRowB * sizeof(int));
936 for (i = 0; i < nColB; i++) {
937 int iColumn = whichCol[i];
938 int j;
939 for (j = startCB[iColumn]; j < startCB[iColumn + 1]; j++) {
940 int iRow = row2B[j];
941 int iSet = whichRow[iRow];
942 row2C[nelB++] = iSet;
943 split[iSet]++;
944 }
945 startCC[i + 1] = nelB;
946 }
947 startRowC[0] = 0;
948 for (i = 0; i < nRowB; i++) {
949 startRowC[i + 1] = startRowC[i] + split[i];
950 split[i] = 0;
951 }
952 for (i = 0; i < nColB; i++) {
953 int j;
954 for (j = startCC[i]; j < startCC[i + 1]; j++) {
955 int iRow = row2C[j];
956 int k = split[iRow] + startRowC[iRow];
957 split[iRow]++;
958 column2C[k] = i;
959 }
960 }
961 for (i = 0; i < nRowB; i++)
962 split[i] = 0;
963 goodInteger = true;
964 for (i = nColB - 1; i > 0; i--) {
965 int j;
966 for (j = startCC[i]; j < startCC[i + 1]; j++) {
967 int iRow = row2C[j];
968 split[iRow] = 1;
969 }
970 for (j = startCC[i]; j < startCC[i + 1]; j++) {
971 int iRow = row2C[j];
972 for (int k = startRowC[iRow]; k < startRowC[iRow + 1]; k++) {
973 int iColumn = column2C[k];
974 if (iColumn < i) {
975 for (int jj = startCC[iColumn]; jj < startCC[iColumn + 1]; jj++) {
976 int jRow = row2C[jj];
977 if (jRow > iRow && !split[jRow]) {
978 // bad
979 goodInteger = false;
980 break;
981 }
982 }
983 }
984 }
985 }
986 if (!goodInteger)
987 break;
988 for (j = startCC[i]; j < startCC[i + 1]; j++) {
989 int iRow = row2C[j];
990 split[iRow] = 0;
991 }
992 }
993 delete[] split;
994 delete[] best;
995 delete[] current;
996 delete[] size;
997 } else {
998 // was network
999 goodInteger = true;
1000 }
1001 if (goodInteger) {
1002 #if CBC_USEFUL_PRINTING
1003 printf("Block %d can be integer\n", iBlock);
1004 #endif
1005 for (i = 0; i < nCol; i++) {
1006 if (columnBlock[i] == iBlock) {
1007 int iBack = back[i];
1008 model->setInteger(iBack);
1009 }
1010 }
1011 }
1012 delete[] startRowC;
1013 delete[] column2C;
1014 delete[] startCB;
1015 delete[] row2B;
1016 delete[] startCC;
1017 delete[] row2C;
1018 delete[] whichRow;
1019 delete[] whichCol;
1020 }
1021 delete[] startRow;
1022 delete[] column2;
1023 delete[] element2;
1024 delete[] startC;
1025 delete[] row2;
1026 delete[] back;
1027 }
1028 }
1029 numberIntegers = numberNonZero;
1030 if (allGood && numberObj) {
1031 #if CBC_USEFUL_PRINTING > 1
1032 int numberPossible = 0;
1033 #endif
1034 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1035 if (upper[iColumn] > lower[iColumn] && objective[iColumn] && !model->isInteger(iColumn)) {
1036 #if CBC_USEFUL_PRINTING > 1
1037 numberPossible++;
1038 #endif
1039 if (upper[iColumn] <= lower[iColumn] + 10) {
1040 model->setInteger(iColumn);
1041 numberIntegers++;
1042 }
1043 }
1044 }
1045 #if CBC_USEFUL_PRINTING > 1
1046 printf("ZZZZYY CglPreProcess analysis says all (%d) continuous with costs could be made integer - %d were\n", numberPossible, numberIntegers - numberNonZero);
1047 #endif
1048 }
1049 #if CBC_USEFUL_PRINTING > 1
1050 if (numberZero)
1051 printf("ZZZZYY %d continuous with zero cost were made integer\n", numberZero);
1052 #endif
1053 numberIntegers += numberZero;
1054 #if CBC_USEFUL_PRINTING > 1
1055 if (numberEq || numberEqI)
1056 printf("ZZZZYY %d rows made equality from continuous, %d from integer\n", numberEq, numberEqI);
1057 #endif
1058 totalNumberIntegers += numberIntegers;
1059 if (!makeAll)
1060 numberIntegers = 0;
1061 }
1062 delete[] rhs;
1063 delete[] count;
1064 return (totalNumberIntegers);
1065 }
1066 //#define CGL_WRITEMPS 1
1067 #ifdef CGL_WRITEMPS
1068 #if CGL_WRITEMPS > 1
1069 extern double *debugSolution;
1070 extern int debugNumberColumns;
1071 #endif
1072 static int mpsNumber = 0;
writeDebugMps(const OsiSolverInterface * solver,const char * where,OsiPresolve * pinfo)1073 static void writeDebugMps(const OsiSolverInterface *solver,
1074 const char *where,
1075 OsiPresolve *pinfo)
1076 {
1077 mpsNumber++;
1078 char name[20];
1079 sprintf(name, "presolve%2.2d.mps", mpsNumber);
1080 printf("saving %s from %s - %d row, %d columns\n",
1081 name, where, solver->getNumRows(), solver->getNumCols());
1082 solver->writeMpsNative(name, NULL, NULL, 0, 1, 0);
1083 #if CGL_WRITEMPS > 1
1084 if (pinfo && debugSolution) {
1085 int n = solver->getNumCols();
1086 if (n < debugNumberColumns) {
1087 const int *original = pinfo->originalColumns();
1088 if (!original) {
1089 printf("No original columns\n");
1090 abort();
1091 }
1092 for (int i = 0; i < n; i++)
1093 debugSolution[i] = debugSolution[original[i]];
1094 debugNumberColumns = n;
1095 }
1096 }
1097 if (debugSolution) {
1098 OsiSolverInterface *newSolver = solver->clone();
1099 const double *lower = newSolver->getColLower();
1100 const double *upper = newSolver->getColUpper();
1101 for (int i = 0; i < debugNumberColumns; i++) {
1102 if (newSolver->isInteger(i)) {
1103 double value = floor(debugSolution[i] + 0.5);
1104 if (value < lower[i] || value > upper[i]) {
1105 printf("Bad value %d - %g %g %g\n", i, lower[i], debugSolution[i],
1106 upper[i]);
1107 } else {
1108 newSolver->setColLower(i, value);
1109 newSolver->setColUpper(i, value);
1110 }
1111 }
1112 }
1113 printf("Starting solve %d\n", mpsNumber);
1114 newSolver->resolve();
1115 printf("Ending solve %d - status %s obj %g\n", mpsNumber,
1116 newSolver->isProvenOptimal() ? "ok" : "bad",
1117 newSolver->getObjValue());
1118 delete newSolver;
1119 }
1120 #endif
1121 }
1122 #else
1123 #define writeDebugMps(x, y, z)
1124 #endif
1125 OsiSolverInterface *
preProcessNonDefault(OsiSolverInterface & model,int makeEquality,int numberPasses,int tuning)1126 CglPreProcess::preProcessNonDefault(OsiSolverInterface &model,
1127 int makeEquality, int numberPasses,
1128 int tuning)
1129 {
1130 double ppstart = getCurrentCPUTime();
1131 #ifdef CGL_WRITEMPS
1132 bool rcdActive = true;
1133 std::string modelName;
1134 model.getStrParam(OsiProbName, modelName);
1135 writeDebugMps(&model, "IPP:preProcessNonDefault", 0);
1136 std::cout
1137 << " Attempting to activate row cut debugger for "
1138 << modelName << " ... ";
1139 if (!appData_) {
1140 model.activateRowCutDebugger(modelName.c_str());
1141 } else {
1142 // see if passed in
1143 double *solution = CoinCopyOfArray(reinterpret_cast< double * >(appData_),
1144 model.getNumCols());
1145 model.activateRowCutDebugger(solution);
1146 delete[] solution;
1147 }
1148 if (model.getRowCutDebugger())
1149 std::cout << "on optimal path." << std::endl;
1150 else if (model.getRowCutDebuggerAlways())
1151 std::cout << "not on optimal path." << std::endl;
1152 else {
1153 std::cout << "failure." << std::endl;
1154 rcdActive = false;
1155 }
1156 if (rcdActive) {
1157 const OsiRowCutDebugger *debugger = model.getRowCutDebuggerAlways();
1158 std::cout << " Optimal solution is:" << std::endl;
1159 debugger->printOptimalSolution(model);
1160 }
1161 #endif
1162 originalModel_ = &model;
1163 if (tuning >= 1000000) {
1164 numberPasses = tuning / 1000000;
1165 tuning %= 1000000;
1166 //minimumLength = tuning;
1167 }
1168 if (numberPasses != 99) {
1169 numberSolvers_ = numberPasses;
1170 } else {
1171 numberSolvers_ = 1;
1172 }
1173 model_ = new OsiSolverInterface *[numberSolvers_];
1174 modifiedModel_ = new OsiSolverInterface *[numberSolvers_];
1175 presolve_ = new OsiPresolve *[numberSolvers_];
1176 for (int i = 0; i < numberSolvers_; i++) {
1177 model_[i] = NULL;
1178 modifiedModel_[i] = NULL;
1179 presolve_[i] = NULL;
1180 }
1181 // clear original
1182 delete[] originalColumn_;
1183 delete[] originalRow_;
1184 originalColumn_ = NULL;
1185 originalRow_ = NULL;
1186 if (numberPasses==99) {
1187 // keep very simple
1188 OsiSolverInterface *presolvedModel;
1189 OsiPresolve *pinfo = new OsiPresolve();
1190 int presolveActions = 0;
1191 // Allow dual stuff on integers
1192 // Allow stuff which may not unroll cleanly - unless told not to
1193 if ((tuning & 4096) == 0)
1194 presolveActions = 1 + 16;
1195 else
1196 presolveActions = 16; // actually just switch off duplicate columns for ints
1197 if ((tuning & 32) != 0)
1198 presolveActions |= 32;
1199 presolveActions |= 8;
1200 pinfo->setPresolveActions(presolveActions);
1201 if (prohibited_)
1202 assert(numberProhibited_ == originalModel_->getNumCols());
1203 presolvedModel =
1204 pinfo->presolvedModel(*originalModel_, 1.0e-7, true,
1205 5, prohibited_, true, rowType_);
1206 startModel_ = originalModel_;
1207 if (presolvedModel) {
1208 // update prohibited and rowType
1209 update(pinfo, presolvedModel);
1210 model_[0] = presolvedModel;
1211 presolve_[0] = pinfo;
1212 modifiedModel_[0] = presolvedModel->clone();
1213 createOriginalIndices();
1214 numberSolvers_ = 99; // mark as odd
1215 return modifiedModel_[0];
1216 } else {
1217 numberSolvers_ = 1;
1218 }
1219 }
1220 //startModel_=&model;
1221 // make clone
1222 delete startModel_;
1223 startModel_ = originalModel_->clone();
1224 CoinPackedMatrix matrixByRow(*originalModel_->getMatrixByRow());
1225 int numberRows = originalModel_->getNumRows();
1226 if (rowType_)
1227 assert(numberRowType_ == numberRows);
1228 int numberColumns = originalModel_->getNumCols();
1229 //int originalNumberColumns=numberColumns;
1230 int minimumLength = 5;
1231 int numberModifiedPasses = 10;
1232 if (numberPasses <= 1)
1233 numberModifiedPasses = 1; // lightweight preprocessing
1234 else if (numberPasses <= 2)
1235 numberModifiedPasses = 2; // fairly lightweight preprocessing
1236 if (tuning >= 10000) {
1237 numberModifiedPasses = tuning / 10000;
1238 tuning %= 10000;
1239 //minimumLength = tuning;
1240 }
1241 if ((tuning & 1) != 0)
1242 options_ |= 16; // heavy stuff
1243 //bool heavyProbing = (tuning&1)!=0;
1244 int makeIntegers = (tuning & 6) >> 1;
1245 // See if we want to do initial presolve
1246 int doInitialPresolve = 1;
1247 if (numberSolvers_ < 2)
1248 doInitialPresolve = 0;
1249 // We want to add columns
1250 int numberSlacks = 0;
1251 int *rows = new int[numberRows];
1252 double *element = new double[numberRows];
1253
1254 int iRow;
1255
1256 int numberCliques = 0;
1257 int *which = new int[numberColumns];
1258
1259 // Statistics
1260 int totalP1 = 0, totalM1 = 0;
1261 int numberFixed = 0;
1262 // May just find it is infeasible
1263 bool feasible = true;
1264
1265 // Row copy
1266 const double *elementByRow = matrixByRow.getElements();
1267 const int *column = matrixByRow.getIndices();
1268 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
1269 const int *rowLength = matrixByRow.getVectorLengths();
1270
1271 const double *lower = originalModel_->getColLower();
1272 const double *upper = originalModel_->getColUpper();
1273 const double *rowLower = originalModel_->getRowLower();
1274 const double *rowUpper = originalModel_->getRowUpper();
1275 // Clean bounds
1276 int iColumn;
1277 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1278 if (originalModel_->isInteger(iColumn)) {
1279 double lo = CoinMax(lower[iColumn], ceil(lower[iColumn] - 1.0e-6));
1280 if (lo > lower[iColumn])
1281 originalModel_->setColLower(iColumn, lo);
1282 double up = CoinMin(upper[iColumn], floor(upper[iColumn] + 1.0e-6));
1283 if (up < upper[iColumn])
1284 originalModel_->setColUpper(iColumn, up);
1285 if (lo > up)
1286 feasible = false;
1287 }
1288 }
1289 bool allToGub = makeEquality == 5;
1290 if (allToGub)
1291 makeEquality = 3;
1292 // Initialize random seed
1293 CoinThreadRandom randomGenerator(987654321);
1294 bool justOnesWithObj = false;
1295 if (makeEquality == 2 || makeEquality == 3 || makeEquality == 4) {
1296 int iRow, iColumn;
1297 int numberIntegers = 0;
1298 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1299 if (originalModel_->isInteger(iColumn))
1300 numberIntegers++;
1301 }
1302 // Look for possible SOS
1303 int numberSOS = 0;
1304 int *mark = new int[numberColumns];
1305 CoinFillN(mark, numberColumns, -1);
1306 int numberOverlap = 0;
1307 int numberInSOS = 0;
1308 // See if worthwhile creating accumulation variables
1309 int firstOther = numberRows;
1310 int *whichRow = new int[numberRows];
1311 for (iRow = 0; iRow < numberRows; iRow++) {
1312 if (rowUpper[iRow] == 1.0) {
1313 if (rowLength[iRow] < 5)
1314 continue;
1315 bool goodRow = true;
1316 bool overlap = false;
1317 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1318 int iColumn = column[j];
1319 if (elementByRow[j] != 1.0 || !originalModel_->isInteger(iColumn) || lower[iColumn]) {
1320 goodRow = false;
1321 break;
1322 }
1323 if (mark[iColumn] >= 0) {
1324 overlap = true;
1325 numberOverlap++;
1326 }
1327 }
1328 if (goodRow) {
1329 if (!overlap) {
1330 // mark all
1331 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1332 int iColumn = column[j];
1333 mark[iColumn] = numberSOS;
1334 }
1335 numberSOS++;
1336 numberInSOS += rowLength[iRow];
1337 }
1338 // May still be interesting even if overlap
1339 if (rowLength[iRow] >= 5) {
1340 firstOther--;
1341 whichRow[firstOther] = iRow;
1342 }
1343 }
1344 }
1345 }
1346 if (makeEquality == 2 && false) {
1347 if (numberOverlap || numberIntegers > numberInSOS + 1) {
1348 // try just ones with costs
1349 CoinFillN(mark, numberColumns, -1);
1350 numberOverlap = 0;
1351 numberInSOS = 0;
1352 bool allCostsInSOS = true;
1353 const double *objective = originalModel_->getObjCoefficients();
1354 for (iRow = 0; iRow < numberRows; iRow++) {
1355 if (rowUpper[iRow] == 1.0 && rowLength[iRow] >= 5) {
1356 bool goodRow = true;
1357 bool overlap = false;
1358 int nObj = 0;
1359 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1360 int iColumn = column[j];
1361 if (elementByRow[j] != 1.0 || !originalModel_->isInteger(iColumn) || lower[iColumn]) {
1362 goodRow = false;
1363 }
1364 if (objective[iColumn])
1365 nObj++;
1366 if (mark[iColumn] >= 0) {
1367 overlap = true;
1368 numberOverlap++;
1369 }
1370 }
1371 if (nObj && nObj >= rowLength[iRow] - 1) {
1372 if (goodRow) {
1373 if (!overlap) {
1374 // mark all
1375 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1376 int iColumn = column[j];
1377 mark[iColumn] = numberSOS;
1378 }
1379 numberSOS++;
1380 numberInSOS += rowLength[iRow];
1381 }
1382 } else {
1383 // no good
1384 allCostsInSOS = false;
1385 }
1386 }
1387 }
1388 }
1389 if (numberInSOS && allCostsInSOS) {
1390 int nGoodObj = 0;
1391 int nBadObj = 0;
1392 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
1393 if (objective[iColumn]) {
1394 if (mark[iColumn] >= 0)
1395 nGoodObj++;
1396 else
1397 nBadObj++;
1398 }
1399 }
1400 if (nBadObj * 10 < nGoodObj) {
1401 justOnesWithObj = true;
1402 makeEquality = 3;
1403 #if CBC_USEFUL_PRINTING > 1
1404 printf("trying SOS as all costs there\n");
1405 #endif
1406 }
1407 }
1408 }
1409 }
1410 if (firstOther < numberRows && makeEquality == 4) {
1411 CoinPackedMatrix *matrixByColumn = const_cast< CoinPackedMatrix * >(startModel_->getMatrixByCol());
1412 // Column copy
1413 const int *row = matrixByColumn->getIndices();
1414 const CoinBigIndex *columnStart = matrixByColumn->getVectorStarts();
1415 const int *columnLength = matrixByColumn->getVectorLengths();
1416 double *columnElements = matrixByColumn->getMutableElements();
1417 int *rowCount = new int[numberRows];
1418 memset(rowCount, 0, numberRows * sizeof(int));
1419 double *rowValue = new double[numberRows];
1420 int numberY = 0;
1421 CoinBigIndex numberElements = 0;
1422 int numberSOS = 0;
1423 for (int kRow = firstOther; kRow < numberRows; kRow++) {
1424 int iRow = whichRow[kRow];
1425 int n = 0;
1426 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1427 int iColumn = column[j];
1428 for (CoinBigIndex k = columnStart[iColumn]; k < columnStart[iColumn] + columnLength[iColumn];
1429 k++) {
1430 int jRow = row[k];
1431 double value = columnElements[k];
1432 if (jRow != iRow) {
1433 if (rowCount[jRow] > 0) {
1434 if (value != rowValue[jRow])
1435 rowCount[jRow] = -1; // no good
1436 else
1437 rowCount[jRow]++;
1438 } else if (!rowCount[jRow]) {
1439 whichRow[n++] = jRow;
1440 rowCount[jRow] = 1;
1441 rowValue[jRow] = value;
1442 }
1443 }
1444 }
1445 }
1446 int bestRow = -1;
1447 int bestCount = 4;
1448 for (int j = 0; j < n; j++) {
1449 int jRow = whichRow[j];
1450 int count = rowCount[jRow];
1451 rowCount[jRow] = 0;
1452 if (count >= 5) {
1453 numberY++;
1454 numberElements += count;
1455 }
1456 if (count > bestCount) {
1457 // possible
1458 bestRow = jRow;
1459 bestCount = count;
1460 }
1461 }
1462 if (bestRow >= 0) {
1463 numberSOS++;
1464 numberY++;
1465 numberElements += bestCount;
1466 }
1467 }
1468 if (numberY) {
1469 // Some may be duplicates
1470 // make sure ordered
1471 matrixByRow.orderMatrix();
1472 elementByRow = matrixByRow.getElements();
1473 column = matrixByRow.getIndices();
1474 rowStart = matrixByRow.getVectorStarts();
1475 rowLength = matrixByRow.getVectorLengths();
1476 CoinBigIndex *newStart = new CoinBigIndex[numberY + 1];
1477 int *newColumn = new int[numberElements];
1478 double *newValue = new double[numberElements];
1479 double *hash = new double[numberY];
1480 double *hashColumn = new double[numberColumns];
1481 int i;
1482 for (i = 0; i < numberColumns; i++)
1483 hashColumn[i] = randomGenerator.randomDouble();
1484 double *valueY = new double[3 * numberY];
1485 int *rowY = new int[3 * numberY];
1486 int *columnY = new int[3 * numberY];
1487 // For new solution
1488 double *newSolution = new double[numberColumns + numberY];
1489 memcpy(newSolution, startModel_->getColSolution(), numberColumns * sizeof(double));
1490 memset(rowCount, 0, numberRows * sizeof(int));
1491 // List of SOS entries to zero out
1492 CoinBigIndex *where = new CoinBigIndex[numberColumns];
1493 numberY = 0;
1494 numberElements = 0;
1495 int numberElementsY = 0;
1496 newStart[0] = 0;
1497 for (int kRow = firstOther; kRow < numberRows; kRow++) {
1498 int iRow = whichRow[kRow];
1499 int n = 0;
1500 int saveNumberY = numberY;
1501 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1502 int iColumn = column[j];
1503 for (CoinBigIndex k = columnStart[iColumn]; k < columnStart[iColumn] + columnLength[iColumn];
1504 k++) {
1505 int jRow = row[k];
1506 double value = columnElements[k];
1507 if (jRow != iRow) {
1508 if (rowCount[jRow] > 0) {
1509 if (value != rowValue[jRow])
1510 rowCount[jRow] = -1; // no good
1511 else
1512 rowCount[jRow]++;
1513 } else if (!rowCount[jRow]) {
1514 whichRow[n++] = jRow;
1515 rowCount[jRow] = 1;
1516 rowValue[jRow] = value;
1517 assert(value);
1518 }
1519 }
1520 }
1521 }
1522 for (i = 0; i < n; i++) {
1523 // Sort so fewest first
1524 std::sort(whichRow, whichRow + n);
1525 int jRow = whichRow[i];
1526 int count = rowCount[jRow];
1527 rowCount[jRow] = 0;
1528 if (count >= 5) {
1529 //assert (count<rowLength[jRow]); // not error - just need to think
1530 // mark so not looked at again
1531 rowCount[jRow] = -count;
1532 // form new row
1533 double value = 0.0;
1534 double hashValue = 0.0;
1535 int nInSOS = 0;
1536 double valueOfY = 0.0;
1537 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1538 int iColumn = column[j];
1539 for (CoinBigIndex k = columnStart[iColumn]; k < columnStart[iColumn] + columnLength[iColumn];
1540 k++) {
1541 if (row[k] == jRow) {
1542 value = columnElements[k];
1543 newColumn[numberElements] = iColumn;
1544 newValue[numberElements++] = 1.0;
1545 hashValue += hashColumn[iColumn];
1546 columnElements[k] = 0.0;
1547 valueOfY += newSolution[iColumn];
1548 } else if (row[k] == iRow) {
1549 if (columnElements[k])
1550 where[nInSOS++] = k;
1551 }
1552 }
1553 }
1554 // See if already exists
1555 int n = static_cast< int >(numberElements - newStart[numberY]);
1556 int j;
1557 for (j = 0; j < numberY; j++) {
1558 if (hashValue == hash[j]) {
1559 // Double check
1560 CoinBigIndex offset = newStart[numberY] - newStart[j];
1561 if (n == newStart[j + 1] - newStart[j]) {
1562 CoinBigIndex k;
1563 for (k = newStart[j]; k < newStart[j] + n; k++) {
1564 if (newColumn[k] != newColumn[k + offset])
1565 break;
1566 }
1567 if (k == newStart[j + 1])
1568 break;
1569 }
1570 }
1571 }
1572 if (j == numberY) {
1573 // not duplicate
1574 newSolution[numberY + numberColumns] = valueOfY;
1575 numberY++;
1576 newStart[numberY] = numberElements;
1577 hash[j] = hashValue;
1578 // Now do -1
1579 rowY[numberElementsY] = j + numberRows;
1580 columnY[numberElementsY] = j;
1581 valueY[numberElementsY++] = -1;
1582 if (n == nInSOS) {
1583 // SOS entry
1584 rowY[numberElementsY] = iRow;
1585 columnY[numberElementsY] = j;
1586 valueY[numberElementsY++] = 1;
1587 for (int i = 0; i < n; i++) {
1588 CoinBigIndex iEl = where[i];
1589 columnElements[iEl] = 0.0;
1590 }
1591 }
1592 } else {
1593 // duplicate
1594 numberElements = newStart[numberY];
1595 }
1596 // Now do
1597 rowY[numberElementsY] = jRow;
1598 columnY[numberElementsY] = j;
1599 valueY[numberElementsY++] = value;
1600 }
1601 }
1602 if (numberY > saveNumberY)
1603 rowCount[iRow] = -1000;
1604 }
1605 delete[] hash;
1606 delete[] hashColumn;
1607 matrixByColumn->cleanMatrix();
1608 // Now add rows
1609 double *rhs = new double[numberY];
1610 memset(rhs, 0, numberY * sizeof(double));
1611 startModel_->addRows(numberY, newStart, newColumn, newValue, rhs, rhs);
1612 delete[] rhs;
1613 delete[] newStart;
1614 delete[] newColumn;
1615 delete[] newValue;
1616 delete[] where;
1617 // Redo matrix
1618 CoinPackedMatrix add(true, rowY, columnY, valueY, numberElementsY);
1619 delete[] valueY;
1620 delete[] rowY;
1621 delete[] columnY;
1622 const int *row = add.getIndices();
1623 const CoinBigIndex *columnStart = add.getVectorStarts();
1624 //const int * columnLength = add.getVectorLengths();
1625 double *columnElements = add.getMutableElements();
1626 double *lo = new double[numberY];
1627 double *up = new double[numberY];
1628 for (i = 0; i < numberY; i++) {
1629 lo[i] = 0.0;
1630 up[i] = 1.0;
1631 }
1632 startModel_->addCols(numberY, columnStart, row, columnElements, lo, up, NULL);
1633 delete[] lo;
1634 delete[] up;
1635 for (i = 0; i < numberY; i++)
1636 startModel_->setInteger(i + numberColumns);
1637 CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(startModel_->getWarmStart());
1638 if (basis) {
1639 for (i = 0; i < numberY; i++) {
1640 basis->setArtifStatus(i + numberRows, CoinWarmStartBasis::atLowerBound);
1641 basis->setStructStatus(i + numberColumns, CoinWarmStartBasis::basic);
1642 }
1643 startModel_->setWarmStart(basis);
1644 delete basis;
1645 }
1646 startModel_->setColSolution(newSolution);
1647 delete[] newSolution;
1648 writeDebugMps(startModel_, "start", NULL);
1649 if (numberElements < 10 * CoinMin(numberColumns, 100 * numberY)) {
1650 handler_->message(CGL_ADDED_INTEGERS, messages_)
1651 << numberY << numberSOS << numberElements
1652 << CoinMessageEol;
1653 numberColumns += numberY;
1654 delete[] which;
1655 which = new int[numberColumns];
1656 bool saveTakeHint;
1657 OsiHintStrength saveStrength;
1658 startModel_->getHintParam(OsiDoDualInResolve,
1659 saveTakeHint, saveStrength);
1660 startModel_->setHintParam(OsiDoDualInResolve, false, OsiHintTry);
1661 startModel_->resolve();
1662 numberIterationsPre_ += startModel_->getIterationCount();
1663 startModel_->setHintParam(OsiDoDualInResolve, saveTakeHint, saveStrength);
1664 } else {
1665 // not such a good idea?
1666 delete startModel_;
1667 startModel_ = NULL;
1668 }
1669 }
1670 delete[] rowValue;
1671 delete[] rowCount;
1672 }
1673 if (makeEquality == 4) {
1674 makeEquality = 0;
1675 #if 1
1676 // Try and make continuous variables integer
1677 // make clone
1678 if (!startModel_)
1679 startModel_ = originalModel_->clone();
1680 makeInteger();
1681 #endif
1682 }
1683 delete[] whichRow;
1684 delete[] mark;
1685 if (numberSOS) {
1686 if (makeEquality == 2) {
1687 if (numberOverlap || numberIntegers * 4 > numberInSOS * 5 + 1) {
1688 handler_->message(CGL_PROCESS_SOS2, messages_)
1689 << numberSOS << numberInSOS << numberIntegers << numberOverlap
1690 << CoinMessageEol;
1691 makeEquality = 0;
1692 }
1693 }
1694 } else {
1695 // no sos
1696 makeEquality = 0;
1697 }
1698 }
1699 if (startModel_) {
1700 lower = originalModel_->getColLower();
1701 upper = originalModel_->getColUpper();
1702 rowLower = originalModel_->getRowLower();
1703 rowUpper = originalModel_->getRowUpper();
1704 }
1705 // See if all + 1
1706 bool allPlusOnes = true;
1707 int nPossible = 0;
1708 int numberMadeEquality = 0;
1709 for (iRow = 0; iRow < numberRows; iRow++) {
1710 int numberP1 = 0, numberM1 = 0;
1711 int numberTotal = 0;
1712 CoinBigIndex j;
1713 double upperValue = rowUpper[iRow];
1714 double lowerValue = rowLower[iRow];
1715 bool good = true;
1716 bool possibleSlack = true;
1717 bool allPlus = true;
1718 for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1719 int iColumn = column[j];
1720 double value = elementByRow[j];
1721 if (upper[iColumn] - lower[iColumn] < 1.0e-8) {
1722 // fixed
1723 upperValue -= lower[iColumn] * value;
1724 lowerValue -= lower[iColumn] * value;
1725 continue;
1726 } else if (!originalModel_->isBinary(iColumn)) {
1727 good = false;
1728 possibleSlack = false;
1729 //break;
1730 } else {
1731 numberTotal++;
1732 }
1733
1734 if (fabs(value - floor(value + 0.5)) > 1.0e-12)
1735 possibleSlack = false;
1736 ;
1737 if (fabs(value) != 1.0) {
1738 good = false;
1739 allPlus = false;
1740 } else if (value > 0.0) {
1741 which[numberP1++] = iColumn;
1742 } else {
1743 numberM1++;
1744 which[numberColumns - numberM1] = iColumn;
1745 allPlus = false;
1746 }
1747 }
1748 if (possibleSlack) {
1749 if (upperValue > 1.0e20 && lowerValue > -1.0e12) {
1750 possibleSlack = (fabs(lowerValue - floor(lowerValue + 0.5)) < 1.0e-12);
1751 } else if (lowerValue < -1.0e20 && upperValue < 1.0e12) {
1752 possibleSlack = (fabs(upperValue - floor(upperValue + 0.5)) < 1.0e-12);
1753 } else {
1754 possibleSlack = false;
1755 }
1756 }
1757 if (allPlus)
1758 nPossible++;
1759 int iUpper = static_cast< int >(floor(upperValue + 1.0e-5));
1760 int iLower = static_cast< int >(ceil(lowerValue - 1.0e-5));
1761 int state = 0;
1762 if (upperValue < 1.0e6) {
1763 if (iUpper == 1 - numberM1)
1764 state = 1;
1765 else if (iUpper == -numberM1)
1766 state = 2;
1767 else if (iUpper < -numberM1)
1768 state = 3;
1769 if (fabs((static_cast< double >(iUpper)) - upperValue) > 1.0e-9)
1770 state = -1;
1771 }
1772 if (!state && lowerValue > -1.0e6) {
1773 if (-iLower == 1 - numberP1)
1774 state = -1;
1775 else if (-iLower == -numberP1)
1776 state = -2;
1777 else if (-iLower < -numberP1)
1778 state = -3;
1779 if (fabs((static_cast< double >(iLower)) - lowerValue) > 1.0e-9)
1780 state = -1;
1781 }
1782 if (good && state > 0) {
1783 if (abs(state) == 3) {
1784 // infeasible
1785 feasible = false;
1786 break;
1787 } else if (abs(state) == 2) {
1788 // we can fix all
1789 numberFixed += numberP1 + numberM1;
1790 int i;
1791 if (state > 0) {
1792 // fix all +1 at 0, -1 at 1
1793 for (i = 0; i < numberP1; i++)
1794 originalModel_->setColUpper(which[i], 0.0);
1795 for (i = 0; i < numberM1; i++)
1796 originalModel_->setColLower(which[numberColumns - i - 1], 1.0);
1797 } else {
1798 // fix all +1 at 1, -1 at 0
1799 for (i = 0; i < numberP1; i++)
1800 originalModel_->setColLower(which[i], 1.0);
1801 for (i = 0; i < numberM1; i++)
1802 originalModel_->setColUpper(which[numberColumns - i - 1], 0.0);
1803 }
1804 } else {
1805 if (!makeEquality || (makeEquality == -1 && numberM1 + numberP1 < minimumLength))
1806 continue;
1807 if (makeEquality == 2 || makeEquality == 3) {
1808 if (numberM1 || numberP1 < minimumLength)
1809 continue;
1810 }
1811 numberCliques++;
1812 if (iLower != iUpper) {
1813 element[numberSlacks] = state;
1814 rows[numberSlacks++] = iRow;
1815 }
1816 if (state > 0) {
1817 totalP1 += numberP1;
1818 totalM1 += numberM1;
1819 } else {
1820 totalP1 += numberM1;
1821 totalM1 += numberP1;
1822 }
1823 }
1824 }
1825 if (possibleSlack && makeEquality == -2 && (!good || state <= 0)) {
1826 if (numberTotal < minimumLength)
1827 continue;
1828 numberMadeEquality++;
1829 element[numberSlacks] = (upperValue < 1.0e10) ? 1.0 : -1.0;
1830 rows[numberSlacks++] = iRow + numberRows;
1831 }
1832 }
1833 // allow if some +1's
1834 allPlusOnes = 10 * nPossible > numberRows;
1835 delete[] which;
1836 if (!feasible) {
1837 handler_->message(CGL_INFEASIBLE, messages_)
1838 << CoinMessageEol;
1839 delete[] rows;
1840 delete[] element;
1841 return NULL;
1842 } else {
1843 if (numberCliques) {
1844 handler_->message(CGL_CLIQUES, messages_)
1845 << numberCliques
1846 << (static_cast< double >(totalP1 + totalM1)) / (static_cast< double >(numberCliques))
1847 << CoinMessageEol;
1848 //printf("%d of these could be converted to equality constraints\n",
1849 // numberSlacks);
1850 }
1851 if (numberFixed)
1852 handler_->message(CGL_FIXED, messages_)
1853 << numberFixed
1854 << CoinMessageEol;
1855 }
1856 if (numberSlacks && makeEquality == 2 && !justOnesWithObj) {
1857 handler_->message(CGL_SLACKS, messages_)
1858 << numberSlacks
1859 << CoinMessageEol;
1860 // add variables to make equality rows
1861 // Get new model
1862 if (!startModel_) {
1863 startModel_ = originalModel_->clone();
1864 }
1865 CoinBigIndex *starts = new CoinBigIndex[numberSlacks + 1];
1866 double *loweretc = new double[3 * numberSlacks];
1867 double *upperetc = loweretc + numberSlacks;
1868 double *objetc = upperetc + numberSlacks;
1869 for (int i = 0; i < numberSlacks; i++) {
1870 int iRow = rows[i];
1871 double upperValue = 1.0;
1872 if (iRow >= numberRows) {
1873 // just a slack not a clique
1874 upperValue = COIN_DBL_MAX;
1875 iRow -= numberRows;
1876 }
1877 rows[i] = iRow;
1878 loweretc[i] = 0.0;
1879 upperetc[i] = upperValue;
1880 objetc[i] = 0.0;
1881 starts[i] = i;
1882 }
1883 starts[numberSlacks] = numberSlacks;
1884 startModel_->addCols(numberSlacks, starts, rows, element,
1885 loweretc, upperetc, objetc);
1886 delete[] starts;
1887 delete[] loweretc;
1888 CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(startModel_->getWarmStart());
1889 if (basis) {
1890 const double *rowActivity = startModel_->getRowActivity();
1891 double *solution = CoinCopyOfArray(startModel_->getColSolution(),
1892 numberColumns + numberSlacks);
1893 for (int i = 0; i < numberSlacks; i++) {
1894 int iRow = rows[i];
1895 if (basis->getArtifStatus(iRow) == CoinWarmStartBasis::basic) {
1896 basis->setArtifStatus(iRow, CoinWarmStartBasis::atLowerBound);
1897 basis->setStructStatus(i + numberColumns, CoinWarmStartBasis::basic);
1898 }
1899 double value = element[i];
1900 double slackvalue = rowActivity[iRow];
1901 if (value > 0) {
1902 slackvalue = rowUpper[iRow] - slackvalue;
1903 } else {
1904 slackvalue = slackvalue - rowLower[iRow];
1905 }
1906 solution[i + numberColumns] = slackvalue;
1907 }
1908 startModel_->setWarmStart(basis);
1909 startModel_->setColSolution(solution);
1910 delete basis;
1911 delete[] solution;
1912 }
1913 for (int i = 0; i < numberSlacks; i++) {
1914 int iRow = rows[i];
1915 double value = element[i];
1916 // set integer
1917 startModel_->setInteger(numberColumns + i);
1918 if (value > 0)
1919 startModel_->setRowLower(iRow, rowUpper[iRow]);
1920 else
1921 startModel_->setRowUpper(iRow, rowLower[iRow]);
1922 }
1923 if (prohibited_) {
1924 // extend
1925 int numberColumns = startModel_->getNumCols();
1926 char *temp = new char[numberColumns];
1927 memcpy(temp, prohibited_, numberProhibited_);
1928 memset(temp + numberProhibited_, 0, numberColumns - numberProhibited_);
1929 numberProhibited_ = numberColumns;
1930 delete[] prohibited_;
1931 prohibited_ = temp;
1932 }
1933 } else if (!startModel_) {
1934 // make clone anyway so can tighten bounds
1935 startModel_ = originalModel_->clone();
1936 }
1937 // move objective to integers or to aggregated
1938 lower = startModel_->getColLower();
1939 upper = startModel_->getColUpper();
1940 rowLower = startModel_->getRowLower();
1941 rowUpper = startModel_->getRowUpper();
1942 matrixByRow = CoinPackedMatrix(*startModel_->getMatrixByRow());
1943 elementByRow = matrixByRow.getElements();
1944 column = matrixByRow.getIndices();
1945 rowStart = matrixByRow.getVectorStarts();
1946 rowLength = matrixByRow.getVectorLengths();
1947 char *marked = new char[numberColumns];
1948 memset(marked, 0, numberColumns);
1949 numberRows = startModel_->getNumRows();
1950 numberColumns = startModel_->getNumCols();
1951 //CoinPackedMatrix * matrixByColumn = const_cast<CoinPackedMatrix *>(startModel_->getMatrixByCol());
1952 // Column copy
1953 //const int * row = matrixByColumn->getIndices();
1954 //const CoinBigIndex * columnStart = matrixByColumn->getVectorStarts();
1955 //const int * columnLength = startModel_->getMatrixByCol()->getVectorLengths();
1956 //const double * columnElements = matrixByColumn->getElements();
1957 double *obj = CoinCopyOfArray(startModel_->getObjCoefficients(), numberColumns);
1958 double offset;
1959 int numberMoved = 0;
1960 startModel_->getDblParam(OsiObjOffset, offset);
1961 // This is not a vital loop so be careful
1962 #ifndef SKIP_MOVE_COSTS_TO_INTEGERS
1963 for (iRow = 0; iRow < numberRows; iRow++) {
1964 //int slack = -1;
1965 int nPlus = 0;
1966 int nMinus = 0;
1967 int iPlus = -1;
1968 int iMinus = -1;
1969 double valuePlus = 0;
1970 double valueMinus = 0;
1971 //bool allInteger=true;
1972 double rhs = rowLower[iRow];
1973 if (rhs != rowUpper[iRow])
1974 continue;
1975 //int multiple=0;
1976 //int iSlack=-1;
1977 int numberContinuous = 0;
1978 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
1979 int iColumn = column[j];
1980 double value = elementByRow[j];
1981 if (upper[iColumn] > lower[iColumn]) {
1982 if (startModel_->isInteger(iColumn)) {
1983 #if 0
1984 if (columnLength[iColumn]==1) {
1985 if (value==1.0) {
1986 }
1987 }
1988 if (value!=floor(value+0.5))
1989 allInteger=false;
1990 if (allInteger&&fabs(value)<1.0e8) {
1991 if (!multiple)
1992 multiple = static_cast<int> (fabs(value));
1993 else if (multiple>0)
1994 multiple = gcd(multiple,static_cast<int> (fabs(value)));
1995 } else {
1996 allInteger=false;
1997 }
1998 #endif
1999 } else {
2000 numberContinuous++;
2001 }
2002 if (value > 0.0) {
2003 if (nPlus > 0 && value != valuePlus) {
2004 nPlus = -numberColumns;
2005 } else if (!nPlus) {
2006 nPlus = 1;
2007 iPlus = iColumn;
2008 valuePlus = value;
2009 } else {
2010 nPlus++;
2011 }
2012 } else {
2013 if (nMinus > 0 && value != valueMinus) {
2014 nMinus = -numberColumns;
2015 } else if (!nMinus) {
2016 nMinus = 1;
2017 iMinus = iColumn;
2018 valueMinus = value;
2019 } else {
2020 nMinus++;
2021 }
2022 }
2023 }
2024 }
2025 if (((nPlus == 1 && startModel_->isInteger(iPlus) && nMinus > 0 && !obj[iPlus]) ||
2026 (nMinus == 1 && startModel_->isInteger(iMinus) && nPlus > 0 && !obj[iMinus]))
2027 && numberContinuous) {
2028 int jColumn;
2029 double multiplier;
2030 double inverseValueOther;
2031 if (nPlus == 1) {
2032 jColumn = iPlus;
2033 multiplier = fabs(valuePlus / valueMinus);
2034 rhs /= -valueMinus;
2035 inverseValueOther = 1.0/valueMinus;
2036 } else {
2037 jColumn = iMinus;
2038 multiplier = fabs(valueMinus / valuePlus);
2039 rhs /= valuePlus;
2040 inverseValueOther = 1.0/valuePlus;
2041 }
2042 double smallestPos = COIN_DBL_MAX;
2043 double smallestNeg = -COIN_DBL_MAX;
2044 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
2045 int iColumn = column[j];
2046 if (iColumn != jColumn) {
2047 double objValue = obj[iColumn];
2048 if (upper[iColumn] > lower[iColumn]) {
2049 if (objValue >= 0.0)
2050 smallestPos = CoinMin(smallestPos, objValue);
2051 else
2052 smallestNeg = CoinMax(smallestNeg, objValue);
2053 }
2054 }
2055 }
2056 if (smallestPos > 0.0) {
2057 double move = 0.0;
2058 double multiply = (smallestNeg == -COIN_DBL_MAX) ? -1.0 : 1.0;
2059 if (smallestNeg == -COIN_DBL_MAX)
2060 move = smallestPos;
2061 else if (smallestPos == COIN_DBL_MAX)
2062 move = smallestNeg;
2063 if (move) {
2064 // can move objective
2065 numberMoved++;
2066 #if CBC_USEFUL_PRINTING > 1
2067 if (rhs)
2068 printf("ZZZ on col %d move %g offset %g\n",
2069 jColumn, move, move * rhs);
2070 #endif
2071 offset += move * multiply * rhs;
2072 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
2073 int iColumn = column[j];
2074 if (iColumn != jColumn) {
2075 if (upper[iColumn] > lower[iColumn]) {
2076 obj[iColumn] -= move;
2077 } else {
2078 double value = elementByRow[j];
2079 obj[iColumn] -= move*value*inverseValueOther;
2080 }
2081 } else {
2082 obj[jColumn] += move * multiplier;
2083 }
2084 }
2085 }
2086 }
2087 }
2088 }
2089 #endif
2090 #if CBC_USEFUL_PRINTING > 1
2091 if (numberMoved)
2092 printf("ZZZ %d costs moved\n", numberMoved);
2093 #endif
2094 startModel_->setDblParam(OsiObjOffset, offset);
2095 startModel_->setObjective(obj);
2096 delete[] obj;
2097 delete[] marked;
2098 delete[] rows;
2099 delete[] element;
2100 if (makeIntegers) {
2101 makeIntegers2(startModel_, makeIntegers);
2102 }
2103 int infeas = 0;
2104 OsiSolverInterface *startModel2 = startModel_;
2105 // Do we want initial presolve
2106 if (doInitialPresolve) {
2107 assert(doInitialPresolve == 1);
2108 OsiSolverInterface *presolvedModel;
2109 OsiSolverInterface *oldModel = startModel2;
2110 OsiPresolve *pinfo = new OsiPresolve();
2111 int presolveActions = 0;
2112 // Allow dual stuff on integers
2113 // Allow stuff which may not unroll cleanly - unless told not to
2114 if ((tuning & 4096) == 0)
2115 presolveActions = 1 + 16;
2116 else
2117 presolveActions = 16; // actually just switch off duplicate columns for ints
2118 if ((tuning & 32) != 0)
2119 presolveActions |= 32;
2120 // Do not allow all +1 to be tampered with
2121 //if (allPlusOnes)
2122 //presolveActions |= 2;
2123 // allow transfer of costs
2124 //presolveActions |= 4; can be slow
2125 // If trying for SOS don't allow some transfers
2126 if (makeEquality == 2 || makeEquality == 3)
2127 presolveActions |= 8;
2128 pinfo->setPresolveActions(presolveActions);
2129 if (prohibited_)
2130 assert(numberProhibited_ == oldModel->getNumCols());
2131 int saveLogLevel = oldModel->messageHandler()->logLevel();
2132 if (saveLogLevel == 1)
2133 oldModel->messageHandler()->setLogLevel(0);
2134 std::string solverName;
2135 oldModel->getStrParam(OsiSolverName, solverName);
2136 // Extend if you want other solvers to keep solution
2137 bool keepSolution = solverName == "clp";
2138 // Should not be hardwired tolerance - temporary fix
2139 #ifndef CGL_PREPROCESS_TOLERANCE
2140 #define CGL_PREPROCESS_TOLERANCE 1.0e-7
2141 #endif
2142 // So standalone version can switch off
2143 double feasibilityTolerance = ((tuning & 1024) == 0) ? CGL_PREPROCESS_TOLERANCE : 1.0e-4;
2144 presolvedModel = pinfo->presolvedModel(*oldModel, feasibilityTolerance, true, 5, prohibited_, keepSolution, rowType_);
2145 oldModel->messageHandler()->setLogLevel(saveLogLevel);
2146 if (presolvedModel) {
2147 //#define MAKE_LESS_THAN
2148 #ifdef MAKE_LESS_THAN
2149 {
2150 int numberRows = presolvedModel->getNumRows();
2151 int numberColumns = presolvedModel->getNumCols();
2152 CoinPackedMatrix *matrix = presolvedModel->getMutableMatrixByCol();
2153 const int *row = matrix->getIndices();
2154 const CoinBigIndex *columnStart = matrix->getVectorStarts();
2155 const int *columnLength = matrix->getVectorLengths();
2156 double *element = const_cast< double * >(matrix->getElements());
2157 const double *rowLower = presolvedModel->getRowLower();
2158 const double *rowUpper = presolvedModel->getRowUpper();
2159 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
2160 for (CoinBigIndex j = columnStart[iColumn];
2161 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
2162 int iRow = row[j];
2163 if (rowUpper[iRow] == COIN_DBL_MAX)
2164 element[j] = -element[j];
2165 }
2166 }
2167 for (int iRow = 0; iRow < numberRows; iRow++) {
2168 if (rowUpper[iRow] == COIN_DBL_MAX) {
2169 presolvedModel->setRowUpper(iRow, -rowLower[iRow]);
2170 presolvedModel->setRowLower(iRow, -COIN_DBL_MAX);
2171 }
2172 }
2173 }
2174 #endif
2175 presolvedModel->messageHandler()->setLogLevel(saveLogLevel);
2176 //presolvedModel->writeMps("new");
2177 writeDebugMps(presolvedModel, "ordinary", pinfo);
2178 // update prohibited and rowType
2179 update(pinfo, presolvedModel);
2180 if (!presolvedModel->getNumRows()) {
2181 doInitialPresolve = 0;
2182 delete presolvedModel;
2183 delete pinfo;
2184 } else {
2185 model_[0] = presolvedModel;
2186 presolve_[0] = pinfo;
2187 modifiedModel_[0] = presolvedModel->clone();
2188 startModel2 = modifiedModel_[0];
2189 }
2190 } else {
2191 infeas = 1;
2192 doInitialPresolve = 0;
2193 delete presolvedModel;
2194 delete pinfo;
2195 }
2196 }
2197 // tighten bounds
2198 /*
2199
2200 Virtuous solvers may require a refresh via initialSolve if this
2201 call is ever changed to give a nonzero value to the (default) second
2202 parameter. Previous actions may have made significant changes to the
2203 constraint system. Safe as long as tightenPrimalBounds doesn't ask for
2204 the current solution.
2205 */
2206 if (!infeas && true) {
2207 // may be better to just do at end
2208 writeDebugMps(startModel2, "before", NULL);
2209 infeas = tightenPrimalBounds(*startModel2);
2210 writeDebugMps(startModel2, "after", NULL);
2211 }
2212 if (infeas) {
2213 handler_->message(CGL_INFEASIBLE, messages_)
2214 << CoinMessageEol;
2215 return NULL;
2216 }
2217 OsiSolverInterface *returnModel = NULL;
2218 int numberChanges;
2219 if ((tuning & (128 + 1)) != 0) {
2220 OsiSolverInterface *newSolver = NULL;
2221 if ((tuning & 2048) != 0) {
2222 CglProbing generator1;
2223 generator1.setUsingObjective(false);
2224 generator1.setMaxPass(1);
2225 generator1.setMaxPassRoot(1);
2226 generator1.setMaxLook(100);
2227 generator1.setRowCuts(3);
2228 generator1.setMaxElements(300);
2229 generator1.setMaxProbeRoot(startModel2->getNumCols());
2230 CoinThreadRandom randomGenerator;
2231 CglTreeProbingInfo info(startModel2);
2232 info.level = 0;
2233 info.formulation_rows = startModel2->getNumRows();
2234 info.inTree = false;
2235 info.options = !numberProhibited_ ? 0 : 2;
2236 info.randomNumberGenerator = &randomGenerator;
2237 info.pass = 4;
2238 generator1.setMode(8);
2239 OsiCuts cs;
2240 generator1.generateCutsAndModify(*startModel2, cs, &info);
2241 OsiSolverInterface *temp = generator1.cliqueModel(startModel2, 2);
2242 OsiSolverInterface *temp2 = cliqueIt(*temp, 0.0001);
2243 delete temp;
2244 if (temp2) {
2245 if (temp2->getNumRows() < startModel2->getNumRows()) {
2246 delete newSolver;
2247 newSolver = temp2;
2248 } else {
2249 delete temp2;
2250 }
2251 }
2252 } else {
2253 // take out cliques
2254 newSolver = cliqueIt(*startModel2, 0.0001);
2255 }
2256 if (newSolver) {
2257 if (startModel2 == modifiedModel_[0])
2258 modifiedModel_[0] = newSolver;
2259 delete startModel2;
2260 startModel2 = newSolver;
2261 newSolver->setHintParam(OsiDoDualInInitial, true, OsiHintTry);
2262 newSolver->initialSolve();
2263 assert(newSolver->isProvenOptimal());
2264 //printf("new size %d rows, %d columns\n",
2265 // newSolver->getNumRows(),newSolver->getNumCols());
2266 }
2267 }
2268 {
2269 // Give a hint to do dual
2270 bool saveTakeHint;
2271 OsiHintStrength saveStrength;
2272 startModel2->getHintParam(OsiDoDualInInitial,
2273 saveTakeHint, saveStrength);
2274 startModel2->setHintParam(OsiDoDualInInitial, true, OsiHintTry);
2275 startModel2->initialSolve();
2276 numberIterationsPre_ += startModel2->getIterationCount();
2277 // double check
2278 if (!startModel2->isProvenOptimal()) {
2279 if (!startModel2->isProvenDualInfeasible()) {
2280 // Do presolves
2281 bool saveHint;
2282 OsiHintStrength saveStrength;
2283 startModel2->getHintParam(OsiDoPresolveInInitial, saveHint, saveStrength);
2284 startModel2->setHintParam(OsiDoPresolveInInitial, true, OsiHintTry);
2285 startModel2->setHintParam(OsiDoDualInInitial, false, OsiHintTry);
2286 startModel2->initialSolve();
2287 numberIterationsPre_ += startModel2->getIterationCount();
2288 if (!startModel2->isProvenDualInfeasible()) {
2289 CoinWarmStart *empty = startModel2->getEmptyWarmStart();
2290 startModel2->setWarmStart(empty);
2291 delete empty;
2292 startModel2->setHintParam(OsiDoDualInInitial, true, OsiHintTry);
2293 startModel2->initialSolve();
2294 numberIterationsPre_ += startModel2->getIterationCount();
2295 }
2296 startModel2->setHintParam(OsiDoPresolveInInitial, saveHint, saveStrength);
2297 }
2298 }
2299 startModel2->setHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength);
2300 }
2301 if (!startModel2->isProvenOptimal()) {
2302 if (!startModel2->isProvenDualInfeasible()) {
2303 handler_->message(CGL_INFEASIBLE, messages_) << CoinMessageEol;
2304 #if CBC_USEFUL_PRINTING > 1
2305 startModel2->writeMps("infeas");
2306 #endif
2307 } else {
2308 handler_->message(CGL_UNBOUNDED, messages_) << CoinMessageEol;
2309 }
2310 return NULL;
2311 }
2312 reducedCostFix(*startModel2);
2313 if (!numberSolvers_) {
2314 // just fix
2315 OsiSolverInterface *newModel = modified(startModel2, false, numberChanges, 0, numberModifiedPasses);
2316 if (startModel_ != originalModel_)
2317 delete startModel_;
2318 if (startModel2 != startModel_)
2319 delete startModel2;
2320 startModel_ = newModel;
2321 returnModel = startModel_;
2322 } else {
2323 OsiSolverInterface *presolvedModel;
2324 OsiSolverInterface *oldModel = startModel2;
2325 if (doInitialPresolve)
2326 oldModel = modifiedModel_[0];
2327 //CglDuplicateRow dupCuts(oldModel);
2328 //dupCuts.setLogLevel(1);
2329 // If +1 try duplicate rows
2330 #define USECGLCLIQUE 512
2331 if ((options_ & 8) != 0)
2332 tuning &= ~USECGLCLIQUE;
2333 if ((options_ & 4) != 0)
2334 allPlusOnes = false;
2335 if ((allPlusOnes && (options_ & 8) == 0) || (tuning & USECGLCLIQUE) != 0) {
2336 #if 1
2337 // put at beginning
2338 int nAdd = ((tuning & (64 + USECGLCLIQUE)) == 64 + USECGLCLIQUE && allPlusOnes) ? 2 : 1;
2339 CglCutGenerator **temp = generator_;
2340 generator_ = new CglCutGenerator *[numberCutGenerators_ + nAdd];
2341 memcpy(generator_ + nAdd, temp, numberCutGenerators_ * sizeof(CglCutGenerator *));
2342 delete[] temp;
2343 numberCutGenerators_ += nAdd;
2344 if (nAdd == 2 || (tuning & USECGLCLIQUE) != 0) {
2345 CglClique *cliqueGen = new CglClique(false, true);
2346 cliqueGen->setStarCliqueReport(false);
2347 cliqueGen->setRowCliqueReport(false);
2348 if ((tuning & USECGLCLIQUE) == 0)
2349 cliqueGen->setMinViolation(-2.0);
2350 else
2351 cliqueGen->setMinViolation(-3.0);
2352 generator_[0] = cliqueGen;
2353 }
2354 if ((allPlusOnes || (tuning & 256) != 0) && (options_ & 4) == 0) {
2355 CglDuplicateRow *dupCuts = new CglDuplicateRow(oldModel);
2356 if ((tuning & 256) != 0)
2357 dupCuts->setMaximumDominated(numberColumns);
2358 generator_[nAdd - 1] = dupCuts;
2359 }
2360 #else
2361 CglDuplicateRow dupCuts(oldModel);
2362 addCutGenerator(&dupCuts);
2363 #endif
2364 }
2365 for (int iPass = doInitialPresolve; ((iPass < numberSolvers_) && ((getCurrentCPUTime() - ppstart) < timeLimit_)); iPass++) {
2366 // Look at Vubs
2367 {
2368 const double *columnLower = oldModel->getColLower();
2369 const double *columnUpper = oldModel->getColUpper();
2370 const CoinPackedMatrix *rowCopy = oldModel->getMatrixByRow();
2371 const int *column = rowCopy->getIndices();
2372 const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
2373 const int *rowLength = rowCopy->getVectorLengths();
2374 const double *rowElements = rowCopy->getElements();
2375 const CoinPackedMatrix *columnCopy = oldModel->getMatrixByCol();
2376 //const int * row = columnCopy->getIndices();
2377 //const CoinBigIndex * columnStart = columnCopy->getVectorStarts();
2378 const int *columnLength = columnCopy->getVectorLengths();
2379 //const double * columnElements = columnCopy->getElements();
2380 const double *rowLower = oldModel->getRowLower();
2381 const double *rowUpper = oldModel->getRowUpper();
2382 const double *objective = oldModel->getObjCoefficients();
2383 double direction = oldModel->getObjSense();
2384 int numberRows = oldModel->getNumRows();
2385 for (int iRow = 0; iRow < numberRows; iRow++) {
2386 if (rowLength[iRow] == 2 && (rowLower[iRow] < -1.0e20 || rowUpper[iRow] > 1.0e20)) {
2387 CoinBigIndex start = rowStart[iRow];
2388 int iColumn1 = column[start];
2389 int iColumn2 = column[start + 1];
2390 double value1 = rowElements[start];
2391 double value2 = rowElements[start + 1];
2392 double upper;
2393 if (rowLower[iRow] < -1.0e20) {
2394 if (rowUpper[iRow] < 1.0e20)
2395 upper = rowUpper[iRow];
2396 else
2397 continue; // free row
2398 } else {
2399 upper = -rowLower[iRow];
2400 value1 = -value1;
2401 value2 = -value2;
2402 }
2403 //for now just singletons
2404 bool integer1 = oldModel->isInteger(iColumn1);
2405 bool integer2 = oldModel->isInteger(iColumn2);
2406 int debug = 0;
2407 if (columnLength[iColumn1] == 1) {
2408 if (integer1) {
2409 debug = 0; // no good
2410 } else if (integer2) {
2411 // possible
2412 debug = 1;
2413 }
2414 } else if (columnLength[iColumn2] == 1) {
2415 if (integer2) {
2416 debug = -1; // print and skip
2417 } else if (integer1) {
2418 // possible
2419 debug = 1;
2420 double valueD = value1;
2421 value1 = value2;
2422 value2 = valueD;
2423 int valueI = iColumn1;
2424 iColumn1 = iColumn2;
2425 iColumn2 = valueI;
2426 bool valueB = integer1;
2427 integer1 = integer2;
2428 integer2 = valueB;
2429 }
2430 }
2431 #if CBC_USEFUL_PRINTING
2432 if (debug && 0) {
2433 printf("%d %d elements%selement %g and %d %d elements%selement %g <= %g\n",
2434 iColumn1, columnLength[iColumn1], integer1 ? " (integer) " : " ", value1,
2435 iColumn2, columnLength[iColumn2], integer2 ? " (integer) " : " ", value2,
2436 upper);
2437 }
2438 #endif
2439 if (debug > 0) {
2440 if (value1 > 0.0 && objective[iColumn1] * direction < 0.0) {
2441 // will push as high as possible so make ==
2442 // highest effective rhs
2443 if (value2 > 0)
2444 upper -= value2 * columnLower[iColumn2];
2445 else
2446 upper -= value2 * columnUpper[iColumn2];
2447 if (columnUpper[iColumn1] > 1.0e20 || columnUpper[iColumn1] * value1 >= upper) {
2448 //printf("looks possible\n");
2449 // make equality
2450 if (rowLower[iRow] < -1.0e20)
2451 oldModel->setRowLower(iRow, rowUpper[iRow]);
2452 else
2453 oldModel->setRowUpper(iRow, rowLower[iRow]);
2454 } else {
2455 // may be able to make integer
2456 // may just be better to use to see objective integral
2457 if (upper == floor(upper) && value2 == floor(value2) && value1 == floor(value1) && objective[iColumn1] == floor(objective[iColumn1]))
2458 oldModel->setInteger(iColumn1);
2459 //printf("odd3\n");
2460 }
2461 } else if (value1 < 0.0 && objective[iColumn1] * direction > 0.0) {
2462 //printf("odd4\n");
2463 } else {
2464 //printf("odd2\n");
2465 }
2466 } else if (debug < 0) {
2467 //printf("odd1\n");
2468 }
2469 }
2470 }
2471 }
2472 OsiPresolve *pinfo = new OsiPresolve();
2473 int presolveActions = 0;
2474 // Allow dual stuff on integers
2475 // Allow stuff which may not unroll cleanly
2476 if ((tuning & 4096) == 0)
2477 presolveActions = 1 + 16;
2478 else
2479 presolveActions = 16; // actually just switch off duplicate columns for ints
2480 if ((tuning & 32) != 0)
2481 presolveActions |= 32;
2482 // Do not allow all +1 to be tampered with
2483 //if (allPlusOnes)
2484 //presolveActions |= 2;
2485 // allow transfer of costs
2486 // presolveActions |= 4;
2487 // If trying for SOS don't allow some transfers
2488 if (makeEquality == 2 || makeEquality == 3)
2489 presolveActions |= 8;
2490 pinfo->setPresolveActions(presolveActions);
2491 if (prohibited_)
2492 assert(numberProhibited_ == oldModel->getNumCols());
2493 /*
2494 VIRTUOUS but possible bad for performance
2495
2496 At this point, the solution is most likely stale: we may have added cuts as
2497 we left the previous call to modified(), or we may have changed row bounds
2498 in VUB analysis just above. Continuous presolve doesn't need a solution
2499 unless we want it to transform the current solution to match the presolved
2500 model.
2501 */
2502 int saveLogLevel = oldModel->messageHandler()->logLevel();
2503 if (saveLogLevel == 1)
2504 oldModel->messageHandler()->setLogLevel(0);
2505 std::string solverName;
2506 oldModel->getStrParam(OsiSolverName, solverName);
2507 // Extend if you want other solvers to keep solution
2508 bool keepSolution = solverName == "clp";
2509 presolvedModel = pinfo->presolvedModel(*oldModel, CGL_PREPROCESS_TOLERANCE, true, 5,
2510 prohibited_, keepSolution, rowType_);
2511 oldModel->messageHandler()->setLogLevel(saveLogLevel);
2512 if (!presolvedModel) {
2513 returnModel = NULL;
2514 delete pinfo;
2515 break;
2516 }
2517 presolvedModel->messageHandler()->setLogLevel(saveLogLevel);
2518 // update prohibited and rowType
2519 update(pinfo, presolvedModel);
2520 writeDebugMps(presolvedModel, "ordinary2", pinfo);
2521 model_[iPass] = presolvedModel;
2522 presolve_[iPass] = pinfo;
2523 if (!presolvedModel->getNumRows()) {
2524 // was returnModel=oldModel;
2525 returnModel = presolvedModel;
2526 numberSolvers_ = iPass + 1;
2527 break; // model totally solved
2528 }
2529 bool constraints = iPass < numberPasses - 1;
2530 // Give a hint to do primal
2531 bool saveTakeHint;
2532 OsiHintStrength saveStrength;
2533 presolvedModel->getHintParam(OsiDoDualInInitial,
2534 saveTakeHint, saveStrength);
2535 //if (iPass)
2536 presolvedModel->setHintParam(OsiDoDualInInitial, false, OsiHintTry);
2537 presolvedModel->initialSolve();
2538 numberIterationsPre_ += presolvedModel->getIterationCount();
2539 presolvedModel->setHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength);
2540 if (!presolvedModel->isProvenOptimal()) {
2541 writeDebugMps(presolvedModel, "bad2", NULL);
2542 CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(presolvedModel->getEmptyWarmStart());
2543 presolvedModel->setWarmStart(slack);
2544 delete slack;
2545 presolvedModel->resolve();
2546 if (!presolvedModel->isProvenOptimal()) {
2547 returnModel = NULL;
2548 //printf("infeasible\n");
2549 break;
2550 } else {
2551 //printf("feasible on second try\n");
2552 }
2553 }
2554 // maybe we can fix some
2555 int numberFixed = reducedCostFix(*presolvedModel);
2556 #if CBC_USEFUL_PRINTING > 1
2557 if (numberFixed)
2558 printf("%d variables fixed on reduced cost\n", numberFixed);
2559 #endif
2560 #if CGL_WRITEMPS
2561 const OsiRowCutDebugger *debugger = presolvedModel->getRowCutDebugger();
2562 if (debugger)
2563 printf("Contains optimal before modified\n");
2564 #endif
2565 OsiSolverInterface *newModel = modified(presolvedModel, constraints, numberChanges, iPass - doInitialPresolve, numberModifiedPasses);
2566 #if CGL_WRITEMPS
2567 if (debugger)
2568 assert(newModel->getRowCutDebugger());
2569 #endif
2570 returnModel = newModel;
2571 if (!newModel) {
2572 break;
2573 }
2574 modifiedModel_[iPass] = newModel;
2575 oldModel = newModel;
2576 writeDebugMps(newModel, "ordinary3", NULL);
2577 newModel->resolve();
2578 if ((!numberChanges && !numberFixed) || !newModel->isProvenOptimal()) {
2579 #if CBC_USEFUL_PRINTING > 1
2580 printf("exiting after pass %d of %d\n", iPass, numberSolvers_);
2581 #endif
2582 numberSolvers_ = iPass + 1;
2583 break;
2584 }
2585 }
2586 }
2587 #if CGL_WRITEMPS
2588 const OsiRowCutDebugger *debugger = returnModel->getRowCutDebugger();
2589 if (debugger)
2590 printf("Contains optimal before tighten\n");
2591 #endif
2592 if (returnModel) {
2593 if (returnModel->getNumRows()) {
2594 // tighten bounds
2595 int infeas = tightenPrimalBounds(*returnModel);
2596 #if CGL_WRITEMPS
2597 if (debugger)
2598 assert(returnModel->getRowCutDebugger());
2599 #endif
2600 if (infeas) {
2601 delete returnModel;
2602 for (int iPass = 0; iPass < numberSolvers_; iPass++) {
2603 if (returnModel == modifiedModel_[iPass])
2604 modifiedModel_[iPass] = NULL;
2605 }
2606 //printf("startModel_ %p startModel2 %p originalModel_ %p returnModel %p\n",
2607 // startModel_,startModel2,originalModel_,returnModel);
2608 if (returnModel == startModel_ && startModel_ != originalModel_)
2609 startModel_ = NULL;
2610 returnModel = NULL;
2611 }
2612 }
2613 } else {
2614 handler_->message(CGL_INFEASIBLE, messages_)
2615 << CoinMessageEol;
2616 }
2617 int numberIntegers = 0;
2618 if (returnModel) {
2619 int iColumn;
2620 int numberColumns = returnModel->getNumCols();
2621 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2622 if (returnModel->isInteger(iColumn))
2623 numberIntegers++;
2624 }
2625 }
2626 if ((makeEquality == 2 || makeEquality == 3) && numberCliques && returnModel) {
2627 int iRow, iColumn;
2628 int numberColumns = returnModel->getNumCols();
2629 int numberRows = returnModel->getNumRows();
2630 const double *objective = returnModel->getObjCoefficients();
2631 // get row copy
2632 const CoinPackedMatrix *matrix = returnModel->getMatrixByRow();
2633 const double *element = matrix->getElements();
2634 const int *column = matrix->getIndices();
2635 const CoinBigIndex *rowStart = matrix->getVectorStarts();
2636 const int *rowLength = matrix->getVectorLengths();
2637 const double *rowLower = returnModel->getRowLower();
2638 const double *rowUpper = returnModel->getRowUpper();
2639 const double *columnLower = returnModel->getColLower();
2640
2641 // Look for possible SOS
2642 int numberSOS = 0;
2643 int *mark = new int[numberColumns];
2644 int *sosRow = new int[numberRows];
2645 CoinZeroN(sosRow, numberRows);
2646 CoinFillN(mark, numberColumns, -1);
2647 int numberOverlap = 0;
2648 int numberInSOS = 0;
2649 for (iRow = 0; iRow < numberRows; iRow++) {
2650 if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0) {
2651 if ((rowLength[iRow] < 5 && !justOnesWithObj) || (rowLength[iRow] < 20 && allToGub))
2652 continue;
2653 bool goodRow = true;
2654 int nObj = 0;
2655 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
2656 iColumn = column[j];
2657 if (element[j] != 1.0 || !returnModel->isInteger(iColumn) || columnLower[iColumn]) {
2658 goodRow = false;
2659 break;
2660 }
2661 if (mark[iColumn] >= 0 && !allToGub) {
2662 goodRow = false;
2663 numberOverlap++;
2664 }
2665 if (objective[iColumn])
2666 nObj++;
2667 }
2668 if (goodRow && justOnesWithObj) {
2669 if (!nObj || nObj < rowLength[iRow] - 1)
2670 goodRow = false;
2671 }
2672 if (goodRow) {
2673 // mark all
2674 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
2675 int iColumn = column[j];
2676 mark[iColumn] = numberSOS;
2677 }
2678 sosRow[numberSOS++] = iRow;
2679 numberInSOS += rowLength[iRow];
2680 }
2681 }
2682 }
2683 if (numberSOS) {
2684 if (makeEquality == 2 && (numberOverlap || numberIntegers > numberInSOS + 1)) {
2685 handler_->message(CGL_PROCESS_SOS2, messages_)
2686 << numberSOS << numberInSOS << numberIntegers << numberOverlap
2687 << CoinMessageEol;
2688 } else {
2689 handler_->message(CGL_PROCESS_SOS1, messages_)
2690 << numberSOS << numberInSOS
2691 << CoinMessageEol;
2692 numberSOS_ = numberSOS;
2693 typeSOS_ = new int[numberSOS_];
2694 startSOS_ = new int[numberSOS_ + 1];
2695 whichSOS_ = new int[numberInSOS];
2696 weightSOS_ = new double[numberInSOS];
2697 numberInSOS = 0;
2698 startSOS_[0] = 0;
2699 const CoinPackedMatrix *columnCopy = returnModel->getMatrixByCol();
2700 const int *row = columnCopy->getIndices();
2701 const CoinBigIndex *columnStart = columnCopy->getVectorStarts();
2702 const int *columnLength = columnCopy->getVectorLengths();
2703 const double *columnElements = columnCopy->getElements();
2704 const double *objective = returnModel->getObjCoefficients();
2705 int *numberInRow = new int[numberRows];
2706 double *sort = new double[numberColumns];
2707 int *which = new int[numberColumns];
2708 for (int iSOS = 0; iSOS < numberSOS_; iSOS++) {
2709 int n = 0;
2710 int numberObj = 0;
2711 CoinZeroN(numberInRow, numberRows);
2712 int kRow = sosRow[iSOS];
2713 for (CoinBigIndex j = rowStart[kRow]; j < rowStart[kRow] + rowLength[kRow]; j++) {
2714 int iColumn = column[j];
2715 whichSOS_[numberInSOS] = iColumn;
2716 weightSOS_[numberInSOS] = n;
2717 numberInSOS++;
2718 n++;
2719 if (objective[iColumn])
2720 numberObj++;
2721 for (CoinBigIndex j = columnStart[iColumn];
2722 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
2723 int iRow = row[j];
2724 if (!sosRow[iRow])
2725 numberInRow[iRow]++;
2726 }
2727 }
2728 // See if any rows look good
2729 int bestRow = -1;
2730 int numberDifferent = 1;
2731 int start = startSOS_[iSOS];
2732 for (int iRow = 0; iRow < numberRows; iRow++) {
2733 if (numberInRow[iRow] >= n - 1) {
2734 // See how many different
2735 int i;
2736 for (i = 0; i < n; i++) {
2737 int iColumn = whichSOS_[i + start];
2738 sort[i] = 0.0;
2739 which[i] = iColumn;
2740 for (CoinBigIndex j = columnStart[iColumn];
2741 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
2742 int jRow = row[j];
2743 if (jRow == iRow) {
2744 sort[i] = columnElements[j];
2745 break;
2746 }
2747 }
2748 }
2749 // sort
2750 CoinSort_2(sort, sort + n, which);
2751 double last = sort[0];
2752 int nDiff = 1;
2753 for (i = 1; i < n; i++) {
2754 if (sort[i] > last + CoinMax(fabs(last) * 1.0e-8, 1.0e-5)) {
2755 nDiff++;
2756 }
2757 last = sort[i];
2758 }
2759 if (nDiff > numberDifferent) {
2760 numberDifferent = nDiff;
2761 bestRow = iRow;
2762 }
2763 }
2764 }
2765 if (numberObj >= n - 1 || bestRow < 0) {
2766 int i;
2767 for (i = 0; i < n; i++) {
2768 int iColumn = whichSOS_[i + start];
2769 sort[i] = objective[iColumn];
2770 which[i] = iColumn;
2771 }
2772 // sort
2773 CoinSort_2(sort, sort + n, which);
2774 double last = sort[0];
2775 int nDiff = 1;
2776 for (i = 1; i < n; i++) {
2777 if (sort[i] > last + CoinMax(fabs(last) * 1.0e-8, 1.0e-5)) {
2778 nDiff++;
2779 }
2780 last = sort[i];
2781 }
2782 if (nDiff > numberDifferent) {
2783 numberDifferent = nDiff;
2784 bestRow = numberRows;
2785 }
2786 }
2787 if (bestRow >= 0) {
2788 // if not objective - recreate
2789 if (bestRow < numberRows) {
2790 int i;
2791 for (i = 0; i < n; i++) {
2792 int iColumn = whichSOS_[i + start];
2793 sort[i] = 0.0;
2794 which[i] = iColumn;
2795 for (CoinBigIndex j = columnStart[iColumn];
2796 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
2797 int jRow = row[j];
2798 if (jRow == bestRow) {
2799 sort[i] = columnElements[j];
2800 break;
2801 }
2802 }
2803 }
2804 // sort
2805 CoinSort_2(sort, sort + n, which);
2806 }
2807 // make sure gaps OK
2808 double last = sort[0];
2809 for (int i = 1; i < n; i++) {
2810 double next = last + CoinMax(fabs(last) * 1.0e-8, 1.0e-5);
2811 sort[i] = CoinMax(sort[i], next);
2812 last = sort[i];
2813 }
2814 //CoinCopyN(sort,n,weightSOS_+start);
2815 //CoinCopyN(which,n,whichSOS_+start);
2816 }
2817 typeSOS_[iSOS] = 1;
2818 startSOS_[iSOS + 1] = numberInSOS;
2819 }
2820 delete[] numberInRow;
2821 delete[] sort;
2822 delete[] which;
2823 }
2824 }
2825 delete[] mark;
2826 delete[] sosRow;
2827 }
2828 #if CGL_WRITEMPS
2829 if (debugger)
2830 assert(returnModel->getRowCutDebugger());
2831 #endif
2832 if (returnModel) {
2833 if (makeIntegers)
2834 makeIntegers2(returnModel, makeIntegers);
2835 #if CGL_WRITEMPS
2836 if (debugger)
2837 assert(returnModel->getRowCutDebugger());
2838 #endif
2839 numberIntegers = 0;
2840 int numberBinary = 0;
2841 int numberColumns = returnModel->getNumCols();
2842 for (int i = 0; i < numberColumns; i++) {
2843 if (returnModel->isInteger(i)) {
2844 numberIntegers++;
2845 if (returnModel->isBinary(i)) {
2846 numberBinary++;
2847 }
2848 }
2849 }
2850 handler_->message(CGL_PROCESS_STATS2, messages_)
2851 << returnModel->getNumRows() << numberColumns
2852 << numberIntegers << numberBinary << returnModel->getNumElements()
2853 << CoinMessageEol;
2854 #if CGL_WRITEMPS
2855 if (debugger)
2856 assert(returnModel->getRowCutDebugger());
2857 #endif
2858 // If can make some cuts then do so
2859 if (rowType_) {
2860 int numberRows = returnModel->getNumRows();
2861 int numberCuts = 0;
2862 for (int i = 0; i < numberRows; i++) {
2863 if (rowType_[i] > 0)
2864 numberCuts++;
2865 }
2866 if (numberCuts) {
2867 CglStored stored;
2868
2869 int *whichRow = new int[numberRows];
2870 // get row copy
2871 const CoinPackedMatrix *rowCopy = returnModel->getMatrixByRow();
2872 const int *column = rowCopy->getIndices();
2873 const int *rowLength = rowCopy->getVectorLengths();
2874 const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
2875 const double *rowLower = returnModel->getRowLower();
2876 const double *rowUpper = returnModel->getRowUpper();
2877 const double *element = rowCopy->getElements();
2878 int iRow, nDelete = 0;
2879 for (iRow = 0; iRow < numberRows; iRow++) {
2880 if (rowType_[iRow] == 1) {
2881 // take out
2882 whichRow[nDelete++] = iRow;
2883 }
2884 }
2885 for (int jRow = 0; jRow < nDelete; jRow++) {
2886 iRow = whichRow[jRow];
2887 CoinBigIndex start = rowStart[iRow];
2888 stored.addCut(rowLower[iRow], rowUpper[iRow], rowLength[iRow],
2889 column + start, element + start);
2890 }
2891 returnModel->deleteRows(nDelete, whichRow);
2892 delete[] whichRow;
2893 cuts_ = stored;
2894 }
2895 }
2896 }
2897 #if CGL_WRITEMPS
2898 if (debugger)
2899 assert(returnModel->getRowCutDebugger());
2900 #endif
2901 #if 0
2902 if (returnModel) {
2903 int numberColumns = returnModel->getNumCols();
2904 int numberRows = returnModel->getNumRows();
2905 int * del = new int [CoinMax(numberColumns,numberRows)];
2906 int * original = new int [numberColumns];
2907 int nDel=0;
2908 for (int i=0;i<numberColumns;i++) {
2909 original[i]=i;
2910 if (returnModel->isInteger(i))
2911 del[nDel++]=i;
2912 }
2913 int nExtra=0;
2914 if (nDel&&nDel!=numberColumns&&(options_&1)!=0&&false) {
2915 OsiSolverInterface * yyyy = returnModel->clone();
2916 int nPass=0;
2917 while (nDel&&nPass<10) {
2918 nPass++;
2919 OsiSolverInterface * xxxx = yyyy->clone();
2920 int nLeft=0;
2921 for (int i=0;i<nDel;i++)
2922 original[del[i]]=-1;
2923 for (int i=0;i<numberColumns;i++) {
2924 int kOrig=original[i];
2925 if (kOrig>=0)
2926 original[nLeft++]=kOrig;
2927 }
2928 assert (nLeft==numberColumns-nDel);
2929 xxxx->deleteCols(nDel,del);
2930 numberColumns = xxxx->getNumCols();
2931 const CoinPackedMatrix * rowCopy = xxxx->getMatrixByRow();
2932 numberRows = rowCopy->getNumRows();
2933 const int * column = rowCopy->getIndices();
2934 const int * rowLength = rowCopy->getVectorLengths();
2935 const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
2936 const double * rowLower = xxxx->getRowLower();
2937 const double * rowUpper = xxxx->getRowUpper();
2938 const double * element = rowCopy->getElements();
2939 const CoinPackedMatrix * columnCopy = xxxx->getMatrixByCol();
2940 const int * columnLength = columnCopy->getVectorLengths();
2941 nDel=0;
2942 // Could do gcd stuff on ones with costs
2943 for (int i=0;i<numberRows;i++) {
2944 if (!rowLength[i]) {
2945 del[nDel++]=i;
2946 } else if (rowLength[i]==1) {
2947 int k=rowStart[i];
2948 int iColumn = column[k];
2949 if (!xxxx->isInteger(iColumn)) {
2950 double mult =1.0/fabs(element[k]);
2951 if (rowLower[i]<-1.0e20) {
2952 double value = rowUpper[i]*mult;
2953 if (fabs(value-floor(value+0.5))<1.0e-8) {
2954 del[nDel++]=i;
2955 if (columnLength[iColumn]==1) {
2956 xxxx->setInteger(iColumn);
2957 int kOrig=original[iColumn];
2958 returnModel->setInteger(kOrig);
2959 }
2960 }
2961 } else if (rowUpper[i]>1.0e20) {
2962 double value = rowLower[i]*mult;
2963 if (fabs(value-floor(value+0.5))<1.0e-8) {
2964 del[nDel++]=i;
2965 if (columnLength[iColumn]==1) {
2966 xxxx->setInteger(iColumn);
2967 int kOrig=original[iColumn];
2968 returnModel->setInteger(kOrig);
2969 }
2970 }
2971 } else {
2972 double value = rowUpper[i]*mult;
2973 if (rowLower[i]==rowUpper[i]&&
2974 fabs(value-floor(value+0.5))<1.0e-8) {
2975 del[nDel++]=i;
2976 xxxx->setInteger(iColumn);
2977 int kOrig=original[iColumn];
2978 returnModel->setInteger(kOrig);
2979 }
2980 }
2981 }
2982 } else {
2983 // only if all singletons
2984 bool possible=false;
2985 if (rowLower[i]<-1.0e20) {
2986 double value = rowUpper[i];
2987 if (fabs(value-floor(value+0.5))<1.0e-8)
2988 possible=true;
2989 } else if (rowUpper[i]>1.0e20) {
2990 double value = rowLower[i];
2991 if (fabs(value-floor(value+0.5))<1.0e-8)
2992 possible=true;
2993 } else {
2994 double value = rowUpper[i];
2995 if (rowLower[i]==rowUpper[i]&&
2996 fabs(value-floor(value+0.5))<1.0e-8)
2997 possible=true;
2998 }
2999 if (possible) {
3000 for (CoinBigIndex j=rowStart[i];
3001 j<rowStart[i]+rowLength[i];j++) {
3002 int iColumn = column[j];
3003 if (columnLength[iColumn]!=1||fabs(element[j])!=1.0) {
3004 possible=false;
3005 break;
3006 }
3007 }
3008 if (possible) {
3009 for (CoinBigIndex j=rowStart[i];
3010 j<rowStart[i]+rowLength[i];j++) {
3011 int iColumn = column[j];
3012 if (!xxxx->isInteger(iColumn)) {
3013 xxxx->setInteger(iColumn);
3014 int kOrig=original[iColumn];
3015 returnModel->setInteger(kOrig);
3016 }
3017 }
3018 del[nDel++]=i;
3019 }
3020 }
3021 }
3022 }
3023 if (nDel) {
3024 xxxx->deleteRows(nDel,del);
3025 }
3026 if (nDel!=numberRows) {
3027 nDel=0;
3028 for (int i=0;i<numberColumns;i++) {
3029 if (xxxx->isInteger(i)) {
3030 del[nDel++]=i;
3031 nExtra++;
3032 }
3033 }
3034 }
3035 delete yyyy;
3036 yyyy=xxxx->clone();
3037 }
3038 numberColumns = yyyy->getNumCols();
3039 numberRows = yyyy->getNumRows();
3040 if (!numberColumns||!numberRows) {
3041 printf("All gone\n");
3042 int numberColumns = returnModel->getNumCols();
3043 for (int i=0;i<numberColumns;i++)
3044 assert(returnModel->isInteger(i));
3045 }
3046 // Would need to check if original bounds integer
3047 //yyyy->writeMps("noints");
3048 delete yyyy;
3049 printf("Creating simplified model with %d rows and %d columns - %d extra integers\n",
3050 numberRows,numberColumns,nExtra);
3051 }
3052 delete [] del;
3053 delete [] original;
3054 //exit(2);
3055 }
3056 #endif
3057 //writeDebugMps(returnModel, "returnModel", NULL);
3058 #if CGL_WRITEMPS
3059 if (debugger)
3060 assert(returnModel->getRowCutDebugger());
3061 #endif
3062
3063
3064 if (returnModel != &model && keepColumnNames_)
3065 {
3066 returnModel->setIntParam( OsiNameDiscipline, 1 );
3067 for ( int i=0 ; (i<returnModel->getNumCols()) ; i++ )
3068 returnModel->setColName( i, model.getColName( originalColumns()[i] ) );
3069 }
3070
3071 return returnModel;
3072 }
3073
3074 /* Tightens primal bounds to make dual and branch and cutfaster. Unless
3075 fixed, bounds are slightly looser than they could be.
3076 Returns non-zero if problem infeasible
3077 Fudge for branch and bound - put bounds on columns of factor *
3078 largest value (at continuous) - should improve stability
3079 in branch and bound on infeasible branches (0.0 is off)
3080 */
tightenPrimalBounds(OsiSolverInterface & model,double factor)3081 int CglPreProcess::tightenPrimalBounds(OsiSolverInterface &model, double factor)
3082 {
3083
3084 // Get a row copy in standard format
3085 CoinPackedMatrix copy = *model.getMatrixByRow();
3086 // get matrix data pointers
3087 const int *column = copy.getIndices();
3088 const CoinBigIndex *rowStart = copy.getVectorStarts();
3089 const int *rowLength = copy.getVectorLengths();
3090 double *element = copy.getMutableElements();
3091 int numberChanged = 1, iPass = 0;
3092 double large = model.getInfinity() * 0.1; // treat bounds > this as infinite
3093 int numberInfeasible = 0;
3094 int totalTightened = 0;
3095
3096 double tolerance;
3097 model.getDblParam(OsiPrimalTolerance, tolerance);
3098
3099 int numberColumns = model.getNumCols();
3100 const double *colLower = model.getColLower();
3101 const double *colUpper = model.getColUpper();
3102 // New and saved column bounds
3103 double *newLower = new double[numberColumns];
3104 memcpy(newLower, colLower, numberColumns * sizeof(double));
3105 double *newUpper = new double[numberColumns];
3106 memcpy(newUpper, colUpper, numberColumns * sizeof(double));
3107 double *columnLower = new double[numberColumns];
3108 memcpy(columnLower, colLower, numberColumns * sizeof(double));
3109 double *columnUpper = new double[numberColumns];
3110 memcpy(columnUpper, colUpper, numberColumns * sizeof(double));
3111
3112 int iRow, iColumn;
3113
3114 // If wanted - tighten column bounds using solution
3115 if (factor) {
3116 /*
3117 Callers need to ensure that the solution is fresh
3118 */
3119 const double *solution = model.getColSolution();
3120 double largest = 0.0;
3121 if (factor > 0.0) {
3122 assert(factor > 1.0);
3123 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3124 if (columnUpper[iColumn] - columnLower[iColumn] > tolerance) {
3125 largest = CoinMax(largest, fabs(solution[iColumn]));
3126 }
3127 }
3128 largest *= factor;
3129 } else {
3130 // absolute
3131 largest = -factor;
3132 }
3133 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3134 if (columnUpper[iColumn] - columnLower[iColumn] > tolerance) {
3135 newUpper[iColumn] = CoinMin(columnUpper[iColumn], largest);
3136 newLower[iColumn] = CoinMax(columnLower[iColumn], -largest);
3137 }
3138 }
3139 }
3140 int numberRows = model.getNumRows();
3141 const double *rowLower = model.getRowLower();
3142 const double *rowUpper = model.getRowUpper();
3143 #ifndef NDEBUG
3144 double large2 = 1.0e10 * large;
3145 #endif
3146 #define MAXPASS 10
3147
3148 // Loop round seeing if we can tighten bounds
3149 // Would be faster to have a stack of possible rows
3150 // and we put altered rows back on stack
3151 int numberCheck = -1;
3152 while (numberChanged > numberCheck) {
3153
3154 numberChanged = 0; // Bounds tightened this pass
3155
3156 if (iPass == MAXPASS)
3157 break;
3158 iPass++;
3159
3160 for (iRow = 0; iRow < numberRows; iRow++) {
3161
3162 if (rowLower[iRow] > -large || rowUpper[iRow] < large) {
3163
3164 // possible row
3165 int infiniteUpper = 0;
3166 int infiniteLower = 0;
3167 double maximumUp = 0.0;
3168 double maximumDown = 0.0;
3169 double newBound;
3170 CoinBigIndex rStart = rowStart[iRow];
3171 CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow];
3172 CoinBigIndex j;
3173 // Compute possible lower and upper ranges
3174
3175 for (j = rStart; j < rEnd; ++j) {
3176 double value = element[j];
3177 iColumn = column[j];
3178 if (value > 0.0) {
3179 if (newUpper[iColumn] >= large) {
3180 ++infiniteUpper;
3181 } else {
3182 maximumUp += newUpper[iColumn] * value;
3183 }
3184 if (newLower[iColumn] <= -large) {
3185 ++infiniteLower;
3186 } else {
3187 maximumDown += newLower[iColumn] * value;
3188 }
3189 } else if (value < 0.0) {
3190 if (newUpper[iColumn] >= large) {
3191 ++infiniteLower;
3192 } else {
3193 maximumDown += newUpper[iColumn] * value;
3194 }
3195 if (newLower[iColumn] <= -large) {
3196 ++infiniteUpper;
3197 } else {
3198 maximumUp += newLower[iColumn] * value;
3199 }
3200 }
3201 }
3202 // Build in a margin of error
3203 maximumUp += 1.0e-8 * fabs(maximumUp);
3204 maximumDown -= 1.0e-8 * fabs(maximumDown);
3205 double maxUp = maximumUp + infiniteUpper * 1.0e31;
3206 double maxDown = maximumDown - infiniteLower * 1.0e31;
3207 if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) {
3208
3209 // Row is redundant - make totally free
3210 } else {
3211 if (maxUp < rowLower[iRow] - 100.0 * tolerance || maxDown > rowUpper[iRow] + 100.0 * tolerance) {
3212 // problem is infeasible - exit at once
3213 numberInfeasible++;
3214 break;
3215 }
3216 double lower = rowLower[iRow];
3217 double upper = rowUpper[iRow];
3218 for (j = rStart; j < rEnd; ++j) {
3219 double value = element[j];
3220 iColumn = column[j];
3221 double nowLower = newLower[iColumn];
3222 double nowUpper = newUpper[iColumn];
3223 if (value > 0.0) {
3224 // positive value
3225 if (lower > -large) {
3226 if (!infiniteUpper) {
3227 assert(nowUpper < large2);
3228 newBound = nowUpper + (lower - maximumUp) / value;
3229 // relax if original was large
3230 if (fabs(maximumUp) > 1.0e8)
3231 newBound -= 1.0e-12 * fabs(maximumUp);
3232 } else if (infiniteUpper == 1 && nowUpper > large) {
3233 newBound = (lower - maximumUp) / value;
3234 // relax if original was large
3235 if (fabs(maximumUp) > 1.0e8)
3236 newBound -= 1.0e-12 * fabs(maximumUp);
3237 } else {
3238 newBound = -COIN_DBL_MAX;
3239 }
3240 if (newBound > nowLower + 1.0e-12 && newBound > -large) {
3241 // Tighten the lower bound
3242 newLower[iColumn] = newBound;
3243 numberChanged++;
3244 // check infeasible (relaxed)
3245 if (nowUpper - newBound < -100.0 * tolerance) {
3246 numberInfeasible++;
3247 }
3248 // adjust
3249 double now;
3250 if (nowLower < -large) {
3251 now = 0.0;
3252 infiniteLower--;
3253 } else {
3254 now = nowLower;
3255 }
3256 maximumDown += (newBound - now) * value;
3257 nowLower = newBound;
3258 }
3259 }
3260 if (upper < large) {
3261 if (!infiniteLower) {
3262 assert(nowLower > -large2);
3263 newBound = nowLower + (upper - maximumDown) / value;
3264 // relax if original was large
3265 if (fabs(maximumDown) > 1.0e8)
3266 newBound += 1.0e-12 * fabs(maximumDown);
3267 } else if (infiniteLower == 1 && nowLower < -large) {
3268 newBound = (upper - maximumDown) / value;
3269 // relax if original was large
3270 if (fabs(maximumDown) > 1.0e8)
3271 newBound += 1.0e-12 * fabs(maximumDown);
3272 } else {
3273 newBound = COIN_DBL_MAX;
3274 }
3275 if (newBound < nowUpper - 1.0e-12 && newBound < large) {
3276 // Tighten the upper bound
3277 newUpper[iColumn] = newBound;
3278 numberChanged++;
3279 // check infeasible (relaxed)
3280 if (newBound - nowLower < -100.0 * tolerance) {
3281 numberInfeasible++;
3282 }
3283 // adjust
3284 double now;
3285 if (nowUpper > large) {
3286 now = 0.0;
3287 infiniteUpper--;
3288 } else {
3289 now = nowUpper;
3290 }
3291 maximumUp += (newBound - now) * value;
3292 nowUpper = newBound;
3293 }
3294 }
3295 } else {
3296 // negative value
3297 if (lower > -large) {
3298 if (!infiniteUpper) {
3299 assert(nowLower < large2);
3300 newBound = nowLower + (lower - maximumUp) / value;
3301 // relax if original was large
3302 if (fabs(maximumUp) > 1.0e8)
3303 newBound += 1.0e-12 * fabs(maximumUp);
3304 } else if (infiniteUpper == 1 && nowLower < -large) {
3305 newBound = (lower - maximumUp) / value;
3306 // relax if original was large
3307 if (fabs(maximumUp) > 1.0e8)
3308 newBound += 1.0e-12 * fabs(maximumUp);
3309 } else {
3310 newBound = COIN_DBL_MAX;
3311 }
3312 if (newBound < nowUpper - 1.0e-12 && newBound < large) {
3313 // Tighten the upper bound
3314 newUpper[iColumn] = newBound;
3315 numberChanged++;
3316 // check infeasible (relaxed)
3317 if (newBound - nowLower < -100.0 * tolerance) {
3318 numberInfeasible++;
3319 }
3320 // adjust
3321 double now;
3322 if (nowUpper > large) {
3323 now = 0.0;
3324 infiniteLower--;
3325 } else {
3326 now = nowUpper;
3327 }
3328 maximumDown += (newBound - now) * value;
3329 nowUpper = newBound;
3330 }
3331 }
3332 if (upper < large) {
3333 if (!infiniteLower) {
3334 assert(nowUpper < large2);
3335 newBound = nowUpper + (upper - maximumDown) / value;
3336 // relax if original was large
3337 if (fabs(maximumDown) > 1.0e8)
3338 newBound -= 1.0e-12 * fabs(maximumDown);
3339 } else if (infiniteLower == 1 && nowUpper > large) {
3340 newBound = (upper - maximumDown) / value;
3341 // relax if original was large
3342 if (fabs(maximumDown) > 1.0e8)
3343 newBound -= 1.0e-12 * fabs(maximumDown);
3344 } else {
3345 newBound = -COIN_DBL_MAX;
3346 }
3347 if (newBound > nowLower + 1.0e-12 && newBound > -large) {
3348 // Tighten the lower bound
3349 newLower[iColumn] = newBound;
3350 numberChanged++;
3351 // check infeasible (relaxed)
3352 if (nowUpper - newBound < -100.0 * tolerance) {
3353 numberInfeasible++;
3354 }
3355 // adjust
3356 double now;
3357 if (nowLower < -large) {
3358 now = 0.0;
3359 infiniteUpper--;
3360 } else {
3361 now = nowLower;
3362 }
3363 maximumUp += (newBound - now) * value;
3364 nowLower = newBound;
3365 }
3366 }
3367 }
3368 }
3369 }
3370 }
3371 }
3372 totalTightened += numberChanged;
3373 if (iPass == 1)
3374 numberCheck = numberChanged >> 4;
3375 if (numberInfeasible)
3376 break;
3377 }
3378 if (!numberInfeasible) {
3379 // Set bounds slightly loose unless integral - now tighter
3380 double useTolerance = 1.0e-5;
3381 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3382 if (columnUpper[iColumn] > columnLower[iColumn]) {
3383 double lower = newLower[iColumn];
3384 double upper = newUpper[iColumn];
3385 if (model.isInteger(iColumn)) {
3386 if (fabs(lower - floor(lower + 0.5)) < 1.0e-5)
3387 lower = floor(lower + 0.5);
3388 else
3389 lower = ceil(lower);
3390 if (fabs(upper - floor(upper + 0.5)) < 1.0e-5)
3391 upper = floor(upper + 0.5);
3392 else
3393 upper = floor(upper);
3394 if (lower > upper)
3395 numberInfeasible++;
3396 } else {
3397 if (fabs(upper) < 1.0e-8 && fabs(lower) < 1.0e-8) {
3398 lower = 0.0;
3399 upper = 0.0;
3400 } else {
3401 // Relax unless integral
3402 if (fabs(lower - floor(lower + 0.5)) > 1.0e-9)
3403 lower -= useTolerance;
3404 else
3405 lower = floor(lower + 0.5);
3406 lower = CoinMax(columnLower[iColumn], lower);
3407 if (fabs(upper - floor(upper + 0.5)) > 1.0e-9)
3408 upper += useTolerance;
3409 else
3410 upper = floor(upper + 0.5);
3411 upper = CoinMin(columnUpper[iColumn], upper);
3412 }
3413 }
3414 model.setColLower(iColumn, lower);
3415 model.setColUpper(iColumn, upper);
3416 newLower[iColumn] = lower;
3417 newUpper[iColumn] = upper;
3418 }
3419 }
3420 if (!numberInfeasible) {
3421 // check common bad formulations
3422 int numberChanges = 0;
3423 for (iRow = 0; iRow < numberRows; iRow++) {
3424 if (rowLower[iRow] > -large || rowUpper[iRow] < large) {
3425 // possible row
3426 double sumFixed = 0.0;
3427 int infiniteUpper = 0;
3428 int infiniteLower = 0;
3429 double maximumUp = 0.0;
3430 double maximumDown = 0.0;
3431 double largest = 0.0;
3432 CoinBigIndex rStart = rowStart[iRow];
3433 CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow];
3434 CoinBigIndex j;
3435 int numberInteger = 0;
3436 //int whichInteger=-1;
3437 // Compute possible lower and upper ranges
3438 for (j = rStart; j < rEnd; ++j) {
3439 double value = element[j];
3440 iColumn = column[j];
3441 if (newUpper[iColumn] > newLower[iColumn]) {
3442 if (model.isInteger(iColumn)) {
3443 numberInteger++;
3444 //whichInteger=iColumn;
3445 }
3446 largest = CoinMax(largest, fabs(value));
3447 if (value > 0.0) {
3448 if (newUpper[iColumn] >= large) {
3449 ++infiniteUpper;
3450 } else {
3451 maximumUp += newUpper[iColumn] * value;
3452 }
3453 if (newLower[iColumn] <= -large) {
3454 ++infiniteLower;
3455 } else {
3456 maximumDown += newLower[iColumn] * value;
3457 }
3458 } else if (value < 0.0) {
3459 if (newUpper[iColumn] >= large) {
3460 ++infiniteLower;
3461 } else {
3462 maximumDown += newUpper[iColumn] * value;
3463 }
3464 if (newLower[iColumn] <= -large) {
3465 ++infiniteUpper;
3466 } else {
3467 maximumUp += newLower[iColumn] * value;
3468 }
3469 }
3470 } else {
3471 // fixed
3472 sumFixed += newLower[iColumn] * value;
3473 }
3474 }
3475 // Adjust
3476 maximumUp += sumFixed;
3477 maximumDown += sumFixed;
3478 // For moment just when all one sign and ints
3479 //maximumUp += 1.0e-8*fabs(maximumUp);
3480 //maximumDown -= 1.0e-8*fabs(maximumDown);
3481 double gap = 0.0;
3482 if ((rowLower[iRow] > maximumDown && largest > rowLower[iRow] - maximumDown) && ((maximumUp <= rowUpper[iRow] && !infiniteUpper) || rowUpper[iRow] >= 1.0e30)) {
3483 gap = rowLower[iRow] - maximumDown;
3484 if (infiniteLower)
3485 gap = 0.0; // switch off
3486 } else if ((maximumUp > rowUpper[iRow] && largest > maximumUp - rowUpper[iRow]) && ((maximumDown >= rowLower[iRow] && !infiniteLower) || rowLower[iRow] <= -1.0e30)) {
3487 gap = -(maximumUp - rowUpper[iRow]);
3488 if (infiniteUpper)
3489 gap = 0.0; // switch off
3490 }
3491 if (fabs(gap) > 1.0e-8) {
3492 for (j = rStart; j < rEnd; ++j) {
3493 double value = element[j];
3494 iColumn = column[j];
3495 double difference = newUpper[iColumn] - newLower[iColumn];
3496 if (difference > 0.0 && difference <= 1.0) {
3497 double newValue = value;
3498 if (value * gap > 0.0 && model.isInteger(iColumn)) {
3499 if (fabs(value * difference) > fabs(gap)) {
3500 // No need for it to be larger than
3501 newValue = gap / difference;
3502 }
3503 if (fabs(value - newValue) > 1.0e-12) {
3504 numberChanges++;
3505 // BUT variable may have bound
3506 double rhsAdjust = 0.0;
3507 if (gap > 0.0) {
3508 // rowLower
3509 if (value > 0.0) {
3510 // new value is based on going up from lower bound
3511 if (colLower[iColumn])
3512 rhsAdjust = colLower[iColumn] * (value - newValue);
3513 } else {
3514 // new value is based on going down from upper bound
3515 if (colUpper[iColumn])
3516 rhsAdjust = colUpper[iColumn] * (value - newValue);
3517 }
3518 } else {
3519 // rowUpper
3520 if (value < 0.0) {
3521 // new value is based on going up from lower bound
3522 if (colLower[iColumn])
3523 rhsAdjust = colLower[iColumn] * (value - newValue);
3524 } else {
3525 // new value is based on going down from upper bound
3526 if (colUpper[iColumn])
3527 rhsAdjust = colUpper[iColumn] * (value - newValue);
3528 }
3529 }
3530 if (rhsAdjust) {
3531 #if CBC_USEFUL_PRINTING > 1
3532 printf("FFor column %d bounds %g, %g on row %d bounds %g, %g coefficient was changed from %g to %g with rhs adjustment of %g\n",
3533 iColumn, colLower[iColumn], colUpper[iColumn],
3534 iRow, rowLower[iRow], rowUpper[iRow],
3535 value, newValue, rhsAdjust);
3536 #endif
3537 if (rowLower[iRow] > -1.0e20)
3538 model.setRowLower(iRow, rowLower[iRow] - rhsAdjust);
3539 if (rowUpper[iRow] < 1.0e20)
3540 model.setRowUpper(iRow, rowUpper[iRow] - rhsAdjust);
3541 #if CBC_USEFUL_PRINTING > 1
3542 printf("FFor column %d bounds %g, %g on row %d bounds %g, %g coefficient was changed from %g to %g with rhs adjustment of %g\n",
3543 iColumn, colLower[iColumn], colUpper[iColumn],
3544 iRow, rowLower[iRow], rowUpper[iRow],
3545 value, newValue, rhsAdjust);
3546 #endif
3547 }
3548 element[j] = newValue;
3549 handler_->message(CGL_ELEMENTS_CHANGED2, messages_)
3550 << iRow << iColumn << value << newValue
3551 << CoinMessageEol;
3552 #if CGL_WRITEMPS
3553 const OsiRowCutDebugger *debugger = model.getRowCutDebugger();
3554 if (debugger && debugger->numberColumns() == numberColumns) {
3555 const double *optimal = debugger->optimalSolution();
3556 double sum = 0.0;
3557 for (int jj = rStart; jj < rEnd; ++jj) {
3558 double value = element[j];
3559 int jColumn = column[jj];
3560 sum += value * optimal[jColumn];
3561 }
3562 assert(sum >= rowLower[iRow] - 1.0e7 && sum <= rowUpper[iRow] + 1.0e-7);
3563 }
3564 #endif
3565 }
3566 }
3567 }
3568 }
3569 }
3570 }
3571 }
3572 if (numberChanges) {
3573 handler_->message(CGL_ELEMENTS_CHANGED1, messages_)
3574 << numberChanges << CoinMessageEol;
3575 model.replaceMatrixOptional(copy);
3576 }
3577 }
3578 }
3579 if (numberInfeasible) {
3580 handler_->message(CGL_INFEASIBLE, messages_)
3581 << CoinMessageEol;
3582 // restore column bounds
3583 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3584 model.setColLower(iColumn, columnLower[iColumn]);
3585 model.setColUpper(iColumn, columnUpper[iColumn]);
3586 }
3587 }
3588 delete[] newLower;
3589 delete[] newUpper;
3590 delete[] columnLower;
3591 delete[] columnUpper;
3592 return (numberInfeasible);
3593 }
3594
3595 /* Creates solution in original model
3596 deleteStuff 0 - don't, 1 do (but not if infeasible), 2 always */
postProcess(OsiSolverInterface & modelIn,int deleteStuff)3597 void CglPreProcess::postProcess(OsiSolverInterface &modelIn, int deleteStuff)
3598 {
3599 // Do presolves
3600 bool saveHint;
3601 OsiHintStrength saveStrength;
3602 originalModel_->getHintParam(OsiDoPresolveInInitial, saveHint, saveStrength);
3603 bool saveHint2;
3604 OsiHintStrength saveStrength2;
3605 originalModel_->getHintParam(OsiDoDualInInitial,
3606 saveHint2, saveStrength2);
3607 OsiSolverInterface *clonedCopy = NULL;
3608 double saveObjectiveValue = modelIn.getObjValue();
3609 // Make sure cutoff is ignored
3610 modelIn.setDblParam(OsiDualObjectiveLimit, 1.0e50);
3611 if (!modelIn.isProvenOptimal()) {
3612 CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(modelIn.getEmptyWarmStart());
3613 modelIn.setWarmStart(slack);
3614 delete slack;
3615 modelIn.resolve();
3616 }
3617 if (modelIn.isProvenOptimal()) {
3618 #if COIN_DEVELOP > 1
3619 whichMps++;
3620 sprintf(nameMps, "start_%d", whichMps);
3621 modelIn.writeMps(nameMps);
3622 printf("Mps file %s saved in %s at line %d\n",
3623 nameMps, __FILE__, __LINE__);
3624 #endif
3625 OsiSolverInterface *modelM = &modelIn;
3626 // If some cuts add back rows
3627 if (cuts_.sizeRowCuts()) {
3628 clonedCopy = modelM->clone();
3629 modelM = clonedCopy;
3630 int numberRowCuts = cuts_.sizeRowCuts();
3631 // add in
3632 CoinBuild build;
3633 for (int k = 0; k < numberRowCuts; k++) {
3634 const OsiRowCut *thisCut = cuts_.rowCutPointer(k);
3635 int n = thisCut->row().getNumElements();
3636 const int *columnCut = thisCut->row().getIndices();
3637 const double *elementCut = thisCut->row().getElements();
3638 double lower = thisCut->lb();
3639 double upper = thisCut->ub();
3640 build.addRow(n, columnCut, elementCut, lower, upper);
3641 }
3642 modelM->addRows(build);
3643 // basis is wrong
3644 CoinWarmStartBasis empty;
3645 modelM->setWarmStart(&empty);
3646 }
3647 if (numberSolvers_==99) {
3648 // was simple presolve
3649 numberSolvers_ = 1;
3650 }
3651 for (int iPass = numberSolvers_ - 1; iPass >= 0; iPass--) {
3652 OsiSolverInterface *model = model_[iPass];
3653 if (model->getNumCols()) {
3654 CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(modelM->getWarmStart());
3655 if (basis) {
3656 model->setWarmStart(basis);
3657 delete basis;
3658 }
3659 int numberColumns = modelM->getNumCols();
3660 const double *solutionM = modelM->getColSolution();
3661 const double *columnLower2 = model->getColLower();
3662 const double *columnUpper2 = model->getColUpper();
3663 const double *columnLower = modelM->getColLower();
3664 const double *columnUpper = modelM->getColUpper();
3665 int iColumn;
3666 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3667 if (modelM->isInteger(iColumn)) {
3668 double value = solutionM[iColumn];
3669 double value2 = floor(value + 0.5);
3670 // if test fails then empty integer
3671 if (fabs(value - value2) < 1.0e-3) {
3672 model->setColLower(iColumn, value2);
3673 model->setColUpper(iColumn, value2);
3674 } else {
3675 #if CBC_USEFUL_PRINTING > 1
3676 printf("NPASS=%d, ipass %d var %d values %g %g %g\n",
3677 numberSolvers_, iPass, iColumn, model->getColLower()[iColumn],
3678 value, model->getColUpper()[iColumn]);
3679 #endif
3680 }
3681 } else if (columnUpper[iColumn] == columnLower[iColumn]) {
3682 if (columnUpper2[iColumn] > columnLower2[iColumn] && !model->isInteger(iColumn)) {
3683 model->setColUpper(iColumn, columnLower[iColumn]);
3684 model->setColLower(iColumn, columnLower[iColumn]);
3685 }
3686 }
3687 }
3688 }
3689 int numberColumns = modelM->getNumCols();
3690 const double *solutionM = modelM->getColSolution();
3691 int iColumn;
3692 // Give a hint to do primal
3693 //model->setHintParam(OsiDoPresolveInInitial,true,OsiHintTry);
3694 model->setHintParam(OsiDoDualInInitial, false, OsiHintTry);
3695 // clean
3696 /*
3697 VIRTUOUS - I am not happy here (JJF) - This was put in for Special Ordered Sets of type 2
3698
3699 Previous loop has likely made nontrivial bound changes, hence invalidated
3700 solution. Why do we need this? We're about to do an initialSolve, which
3701 will overwrite solution. Perhaps belongs in same guarded block with
3702 following feasibility check? If this is necessary for clp, solution should
3703 be acquired before bounds changes.
3704 */
3705 if (0) {
3706 int numberColumns = model->getNumCols();
3707 const double *lower = model->getColLower();
3708 const double *upper = model->getColUpper();
3709 double *solution = CoinCopyOfArray(model->getColSolution(), numberColumns);
3710 int i;
3711 for (i = 0; i < numberColumns; i++) {
3712 double value = solution[i];
3713 value = CoinMin(value, upper[i]);
3714 value = CoinMax(value, lower[i]);
3715 solution[i] = value;
3716 }
3717 model->setColSolution(solution);
3718 delete[] solution;
3719 }
3720 #if CBC_USEFUL_PRINTING > 1
3721 {
3722 int numberColumns = model->getNumCols();
3723 int numberRows = model->getNumRows();
3724 const double *lower = model->getColLower();
3725 const double *upper = model->getColUpper();
3726 const double *rowLower = model->getRowLower();
3727 const double *rowUpper = model->getRowUpper();
3728 #ifndef NDEBUG
3729 double primalTolerance = 1.0e-8;
3730 #endif
3731 // Column copy
3732 const CoinPackedMatrix *matrix = model->getMatrixByCol();
3733 const double *element = matrix->getElements();
3734 const int *row = matrix->getIndices();
3735 const CoinBigIndex *columnStart = matrix->getVectorStarts();
3736 const int *columnLength = matrix->getVectorLengths();
3737 double *rowActivity = new double[numberRows];
3738 memset(rowActivity, 0, numberRows * sizeof(double));
3739 int i;
3740 for (i = 0; i < numberColumns; i++) {
3741 int j;
3742 double value = lower[i];
3743 if (value < lower[i]) {
3744 value = lower[i];
3745 } else if (value > upper[i]) {
3746 value = upper[i];
3747 }
3748 assert(upper[i] >= lower[i]);
3749 assert((fabs(value) < 1.0e20));
3750 if (value) {
3751 for (j = columnStart[i];
3752 j < columnStart[i] + columnLength[i]; j++) {
3753 int iRow = row[j];
3754 rowActivity[iRow] += value * element[j];
3755 }
3756 }
3757 }
3758 // check was feasible - if not adjust (cleaning may move)
3759 bool feasible = true;
3760 for (i = 0; i < numberRows; i++) {
3761 if (rowActivity[i] < rowLower[i]) {
3762 if (rowActivity[i] < rowLower[i] - 1000.0 * primalTolerance) {
3763 feasible = false;
3764 #if CBC_USEFUL_PRINTING
3765 printf("Bad row %d %g <= %g <= %g\n",
3766 i, rowLower[i], rowActivity[i], rowUpper[i]);
3767 #endif
3768 }
3769 rowActivity[i] = rowLower[i];
3770 } else if (rowActivity[i] > rowUpper[i]) {
3771 if (rowActivity[i] > rowUpper[i] + 1000.0 * primalTolerance) {
3772 feasible = false;
3773 #if CBC_USEFUL_PRINTING
3774 printf("Bad row %d %g <= %g <= %g\n",
3775 i, rowLower[i], rowActivity[i], rowUpper[i]);
3776 #endif
3777 }
3778 rowActivity[i] = rowUpper[i];
3779 }
3780 }
3781 assert(feasible);
3782 }
3783 #endif
3784 {
3785 int numberFixed = 0;
3786 int numberColumns = model->getNumCols();
3787 const double *columnLower = model->getColLower();
3788 const double *columnUpper = model->getColUpper();
3789 int iColumn;
3790 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3791 if (columnLower[iColumn] == columnUpper[iColumn])
3792 numberFixed++;
3793 }
3794 if (numberColumns > 2000 && numberFixed < numberColumns && numberFixed * 5 > numberColumns) {
3795 model->setHintParam(OsiDoPresolveInInitial, true, OsiHintTry);
3796 }
3797 }
3798 model->setHintParam(OsiDoDualInInitial, true, OsiHintTry);
3799 model->initialSolve();
3800 numberIterationsPost_ += model->getIterationCount();
3801 if (!model->isProvenOptimal()) {
3802 // try without basis
3803 CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(model->getEmptyWarmStart());
3804 model->setWarmStart(basis);
3805 delete basis;
3806 model->initialSolve();
3807 }
3808 if (!model->isProvenOptimal()) {
3809 #if COIN_DEVELOP
3810 whichMps++;
3811 sprintf(nameMps, "bad2_%d", whichMps);
3812 model->writeMps(nameMps);
3813 printf("Mps file %s saved in %s at line %d\n",
3814 nameMps, __FILE__, __LINE__);
3815 printf("bad unwind in postprocess\n");
3816 OsiSolverInterface *temp = model->clone();
3817 temp->setDblParam(OsiDualObjectiveLimit, 1.0e30);
3818 temp->setHintParam(OsiDoReducePrint, false, OsiHintTry);
3819 temp->initialSolve();
3820 if (temp->isProvenOptimal()) {
3821 printf("Was infeasible on objective limit\n");
3822 }
3823 delete temp;
3824 #endif
3825 } else {
3826 #if COIN_DEVELOP > 1
3827 whichMps++;
3828 sprintf(nameMps, "good2_%d", whichMps);
3829 model->writeMps(nameMps);
3830 printf("Mps file %s saved in %s at line %d\n",
3831 nameMps, __FILE__, __LINE__);
3832 #endif
3833 }
3834 const int *originalColumns = presolve_[iPass]->originalColumns();
3835 const double *columnLower = modelM->getColLower();
3836 const double *columnUpper = modelM->getColUpper();
3837 OsiSolverInterface *modelM2;
3838 if (iPass)
3839 modelM2 = modifiedModel_[iPass - 1];
3840 else
3841 modelM2 = startModel_;
3842 const double *solutionM2 = modelM2->getColSolution();
3843 const double *columnLower2 = modelM2->getColLower();
3844 const double *columnUpper2 = modelM2->getColUpper();
3845 double primalTolerance;
3846 modelM->getDblParam(OsiPrimalTolerance, primalTolerance);
3847 /* clean up status for any bound alterations made by preprocess which
3848 postsolve won't understand.
3849 Could move inside OsiPresolve but some people might object */
3850 CoinWarmStartBasis *presolvedBasis = dynamic_cast< CoinWarmStartBasis * >(model->getWarmStart());
3851 assert(presolvedBasis);
3852 int numberChanged = 0;
3853 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3854 int jColumn = originalColumns[iColumn];
3855 switch (presolvedBasis->getStructStatus(iColumn)) {
3856 case CoinWarmStartBasis::basic:
3857 case CoinWarmStartBasis::superBasic:
3858 case CoinWarmStartBasis::isFree:
3859 break;
3860 case CoinWarmStartBasis::atLowerBound:
3861 if (solutionM[iColumn] > columnLower2[jColumn] + primalTolerance) {
3862 presolvedBasis->setStructStatus(iColumn, CoinWarmStartBasis::isFree);
3863 numberChanged++;
3864 }
3865 break;
3866 case CoinWarmStartBasis::atUpperBound:
3867 if (solutionM[iColumn] < columnUpper2[jColumn] - primalTolerance) {
3868 presolvedBasis->setStructStatus(iColumn, CoinWarmStartBasis::isFree);
3869 numberChanged++;
3870 }
3871 break;
3872 }
3873 }
3874 if (numberChanged)
3875 model->setWarmStart(presolvedBasis);
3876 delete presolvedBasis;
3877 presolve_[iPass]->postsolve(true);
3878 // and fix values
3879 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3880 int jColumn = originalColumns[iColumn];
3881 if (!modelM2->isInteger(jColumn)) {
3882 if (columnUpper[iColumn] == columnLower[iColumn]) {
3883 if (columnUpper2[jColumn] > columnLower2[jColumn] && !modelM2->isInteger(jColumn)) {
3884 double value = solutionM[iColumn];
3885 value = CoinMax(value, columnLower[iColumn]);
3886 value = CoinMin(value, columnUpper[iColumn]);
3887 #if CBC_USEFUL_PRINTING > 1
3888 printf("assuming %d fixed to solution of %g (was %g) - bounds %g %g, old bounds and sol %g %g\n",
3889 jColumn, value, solutionM2[jColumn], columnLower2[jColumn], columnUpper2[jColumn],
3890 columnLower[iColumn], columnUpper[iColumn]);
3891 #endif
3892 modelM2->setColLower(jColumn, value);
3893 modelM2->setColUpper(jColumn, value);
3894 }
3895 } else {
3896 #if CBC_USEFUL_PRINTING
3897 if (columnUpper2[jColumn] > columnLower2[jColumn] && !modelM2->isInteger(jColumn)) {
3898 double value = solutionM[iColumn];
3899 value = CoinMax(value, columnLower[iColumn]);
3900 value = CoinMin(value, columnUpper[iColumn]);
3901 printf("assuming %d not fixed to solution of %g (was %g) - bounds %g %g, old bounds and sol %g %g\n",
3902 jColumn, value, solutionM2[jColumn], columnLower2[jColumn], columnUpper2[jColumn],
3903 columnLower[iColumn], columnUpper[iColumn]);
3904 }
3905 #endif
3906 }
3907 } else {
3908 // integer - dupcol bounds may be odd so use solution
3909 double value = floor(solutionM2[jColumn] + 0.5);
3910 if (value < columnLower2[jColumn]) {
3911 //printf("changing lower bound for %d from %g to %g to allow feasibility\n",
3912 // jColumn,columnLower2[jColumn],value);
3913 modelM2->setColLower(jColumn, value);
3914 } else if (value > columnUpper2[jColumn]) {
3915 //printf("changing upper bound for %d from %g to %g to allow feasibility\n",
3916 // jColumn,columnUpper2[jColumn],value);
3917 modelM2->setColUpper(jColumn, value);
3918 }
3919 }
3920 }
3921 if (deleteStuff) {
3922 delete modifiedModel_[iPass];
3923 ;
3924 delete model_[iPass];
3925 ;
3926 delete presolve_[iPass];
3927 modifiedModel_[iPass] = NULL;
3928 model_[iPass] = NULL;
3929 presolve_[iPass] = NULL;
3930 }
3931 modelM = modelM2;
3932 }
3933 // should be back to startModel_;
3934 OsiSolverInterface *model = originalModel_;
3935 // Use number of columns in original
3936 int numberColumns = model->getNumCols();
3937 const double *solutionM = modelM->getColSolution();
3938 int iColumn;
3939 const double *columnLower2 = model->getColLower();
3940 const double *columnUpper2 = model->getColUpper();
3941 const double *columnLower = modelM->getColLower();
3942 const double *columnUpper = modelM->getColUpper();
3943 int numberBadValues = 0;
3944 CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(modelM->getWarmStart());
3945 if (basis) {
3946 model->setWarmStart(basis);
3947 delete basis;
3948 }
3949 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3950 if (modelM->isInteger(iColumn)) {
3951 double value = solutionM[iColumn];
3952 double value2 = floor(value + 0.5);
3953 // if test fails then empty integer
3954 if (fabs(value - value2) < 1.0e-3) {
3955 value2 = CoinMax(CoinMin(value2, columnUpper[iColumn]), columnLower[iColumn]);
3956 model->setColLower(iColumn, value2);
3957 model->setColUpper(iColumn, value2);
3958 } else {
3959 #if CBC_USEFUL_PRINTING > 1
3960 printf("NPASS=%d, ipass end var %d values %g %g %g\n",
3961 numberSolvers_, iColumn, model->getColLower()[iColumn],
3962 value, model->getColUpper()[iColumn]);
3963 #endif
3964 numberBadValues++;
3965 }
3966 } else if (columnUpper[iColumn] == columnLower[iColumn]) {
3967 if (columnUpper2[iColumn] > columnLower2[iColumn] && !model->isInteger(iColumn)) {
3968 model->setColUpper(iColumn, columnLower[iColumn]);
3969 model->setColLower(iColumn, columnLower[iColumn]);
3970 }
3971 }
3972 }
3973 if (numberBadValues) {
3974 const CoinPackedMatrix *columnCopy = model->getMatrixByCol();
3975 const int *row = columnCopy->getIndices();
3976 const CoinBigIndex *columnStart = columnCopy->getVectorStarts();
3977 const int *columnLength = columnCopy->getVectorLengths();
3978 const double *element = columnCopy->getElements();
3979 int numberRows = model->getNumRows();
3980 double *rowActivity = new double[numberRows];
3981 memset(rowActivity, 0, numberRows * sizeof(double));
3982 double *solution = CoinCopyOfArray(solutionM, numberColumns);
3983 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3984 double value = solutionM[iColumn];
3985 if (modelM->isInteger(iColumn)) {
3986 double value2 = floor(value + 0.5);
3987 // if test fails then empty integer
3988 if (fabs(value - value2) < 1.0e-3)
3989 value = value2;
3990 }
3991 solution[iColumn] = value;
3992 for (CoinBigIndex j = columnStart[iColumn];
3993 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
3994 int iRow = row[j];
3995 rowActivity[iRow] += value * element[j];
3996 }
3997 }
3998 const double *rowLower = model->getRowLower();
3999 const double *rowUpper = model->getRowUpper();
4000 //const double * columnLower = model->getColLower();
4001 //const double * columnUpper = model->getColUpper();
4002 const double *objective = model->getObjCoefficients();
4003 double direction = model->getObjSense();
4004 int numberCheck = 0;
4005 double tolerance;
4006 model->getDblParam(OsiPrimalTolerance, tolerance);
4007 tolerance *= 10.0;
4008 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4009 double value = solution[iColumn];
4010 if (model->isInteger(iColumn)) {
4011 double value2 = floor(value);
4012 // See if empty integer
4013 if (value != value2) {
4014 numberCheck++;
4015 int allowed = 0;
4016 // can we go up
4017 double movement = value2 + 1.0 - value;
4018 CoinBigIndex j;
4019 bool good = true;
4020 for (j = columnStart[iColumn];
4021 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4022 int iRow = row[j];
4023 #if CBC_USEFUL_PRINTING > 1
4024 if (rowLower[iRow] > -1.0e20 && rowUpper[iRow] < 1.0e20)
4025 printf("odd row with both bounds %d %g %g - element %g\n",
4026 iRow, rowLower[iRow], rowUpper[iRow], element[j]);
4027 #endif
4028 double newActivity = rowActivity[iRow] + movement * element[j];
4029 if (newActivity > rowUpper[iRow] + tolerance || newActivity < rowLower[iRow] - tolerance)
4030 good = false;
4031 }
4032 if (good)
4033 allowed = 1;
4034 // can we go down
4035 movement = value2 - value;
4036 good = true;
4037 for (j = columnStart[iColumn];
4038 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4039 int iRow = row[j];
4040 double newActivity = rowActivity[iRow] + movement * element[j];
4041 if (newActivity > rowUpper[iRow] + tolerance || newActivity < rowLower[iRow] - tolerance)
4042 good = false;
4043 }
4044 if (good)
4045 allowed |= 2;
4046 if (allowed) {
4047 if (allowed == 3) {
4048 if (direction * objective[iColumn] > 0.0)
4049 allowed = 2;
4050 else
4051 allowed = 1;
4052 }
4053 if (allowed == 1)
4054 value2++;
4055 movement = value2 - value;
4056 solution[iColumn] = value2;
4057 model->setColLower(iColumn, value2);
4058 model->setColUpper(iColumn, value2);
4059 for (j = columnStart[iColumn];
4060 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4061 int iRow = row[j];
4062 rowActivity[iRow] += movement * element[j];
4063 }
4064 } else {
4065 #if CBC_USEFUL_PRINTING > 1
4066 printf("Unable to move %d\n", iColumn);
4067 #endif
4068 }
4069 }
4070 }
4071 }
4072 assert(numberCheck == numberBadValues);
4073 model->setColSolution(solution);
4074 delete[] rowActivity;
4075 delete[] solution;
4076 }
4077 } else {
4078 // infeasible
4079 // Back to startModel_;
4080 OsiSolverInterface *model = originalModel_;
4081 // Use number of columns in original
4082 int numberColumns = model->getNumCols();
4083 const double *columnLower = model->getColLower();
4084 int iColumn;
4085 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4086 if (model->isInteger(iColumn))
4087 model->setColUpper(iColumn, columnLower[iColumn]);
4088 }
4089 }
4090 delete clonedCopy;
4091 originalModel_->setHintParam(OsiDoPresolveInInitial, true, OsiHintTry);
4092 originalModel_->setHintParam(OsiDoDualInInitial, false, OsiHintTry);
4093 {
4094 int numberFixed = 0;
4095 int numberColumns = originalModel_->getNumCols();
4096 const double *columnLower = originalModel_->getColLower();
4097 const double *columnUpper = originalModel_->getColUpper();
4098 int iColumn;
4099 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4100 if (columnLower[iColumn] == columnUpper[iColumn])
4101 numberFixed++;
4102 }
4103 //printf("XX %d columns, %d fixed\n",numberColumns,numberFixed);
4104 //double time1 = CoinCpuTime();
4105 //originalModel_->initialSolve();
4106 //printf("Time with basis %g seconds, %d iterations\n",CoinCpuTime()-time1,originalModel_->getIterationCount());
4107 if (numberColumns < 10000 || numberFixed == numberColumns) {
4108 CoinWarmStart *empty = originalModel_->getEmptyWarmStart();
4109 originalModel_->setWarmStart(empty);
4110 delete empty;
4111 }
4112 }
4113 //double time1 = CoinCpuTime();
4114 originalModel_->initialSolve();
4115 numberIterationsPost_ += originalModel_->getIterationCount();
4116 //printf("Time without basis %g seconds, %d iterations\n",CoinCpuTime()-time1,originalModel_->getIterationCount());
4117 double objectiveValue = originalModel_->getObjValue();
4118 double testObj = 1.0e-8 * CoinMax(fabs(saveObjectiveValue), fabs(objectiveValue)) + 1.0e-4;
4119 if (!originalModel_->isProvenOptimal()) {
4120 #if COIN_DEVELOP
4121 whichMps++;
4122 sprintf(nameMps, "bad3_%d", whichMps);
4123 originalModel_->writeMps(nameMps);
4124 printf("Mps file %s saved in %s at line %d\n",
4125 nameMps, __FILE__, __LINE__);
4126 printf("bad end unwind in postprocess\n");
4127 #endif
4128 handler_->message(CGL_POST_INFEASIBLE, messages_)
4129 << CoinMessageEol;
4130 if (deleteStuff) {
4131 for (int iPass = numberSolvers_ - 1; iPass >= 0; iPass--) {
4132 delete modifiedModel_[iPass];
4133 ;
4134 delete model_[iPass];
4135 ;
4136 delete presolve_[iPass];
4137 modifiedModel_[iPass] = NULL;
4138 model_[iPass] = NULL;
4139 presolve_[iPass] = NULL;
4140 }
4141 }
4142 } else if (fabs(saveObjectiveValue - objectiveValue) > testObj
4143 && deleteStuff) {
4144 handler_->message(CGL_POST_CHANGED, messages_)
4145 << saveObjectiveValue << objectiveValue
4146 << CoinMessageEol;
4147 }
4148 originalModel_->setHintParam(OsiDoDualInInitial, saveHint2, saveStrength2);
4149 originalModel_->setHintParam(OsiDoPresolveInInitial, saveHint, saveStrength);
4150 }
4151 //-------------------------------------------------------------------
4152 // Returns the greatest common denominator of two
4153 // positive integers, a and b, found using Euclid's algorithm
4154 //-------------------------------------------------------------------
gcd(int a,int b)4155 static int gcd(int a, int b)
4156 {
4157 int remainder = -1;
4158 // make sure a<=b (will always remain so)
4159 if (a > b) {
4160 // Swap a and b
4161 int temp = a;
4162 a = b;
4163 b = temp;
4164 }
4165 // if zero then gcd is nonzero (zero may occur in rhs of packed)
4166 if (!a) {
4167 if (b) {
4168 return b;
4169 } else {
4170 printf("**** gcd given two zeros!!\n");
4171 abort();
4172 }
4173 }
4174 while (remainder) {
4175 remainder = b % a;
4176 b = a;
4177 a = remainder;
4178 }
4179 return b;
4180 }
4181 #define CGL_PREPROCESS_DENSE_CODE
4182 #define F77_FUNC(x, y) x##_
4183 /* Type of Fortran integer translated into C */
4184 #ifndef ipfint
4185 //typedef ipfint FORTRAN_INTEGER_TYPE ;
4186 typedef int ipfint;
4187 typedef const int cipfint;
4188 #endif
4189 //#define COIN_HAS_LAPACK
4190 //#include "CoinFactorization.hpp"
4191 #ifdef CGL_PREPROCESS_DENSE_CODE
4192 // using simple lapack interface
4193 extern "C" {
4194 /** LAPACK Fortran subroutine DGETRF. */
4195 void F77_FUNC(dgetrf, DGETRF)(ipfint *m, ipfint *n,
4196 double *A, ipfint *ldA,
4197 ipfint *ipiv, ipfint *info);
4198 /** LAPACK Fortran subroutine DGETRS. */
4199 void F77_FUNC(dgetrs, DGETRS)(char *trans, cipfint *n,
4200 cipfint *nrhs, const double *A, cipfint *ldA,
4201 cipfint *ipiv, double *B, cipfint *ldB, ipfint *info,
4202 int trans_len);
4203 }
4204 #endif
4205 /* Return model with useful modifications.
4206 If constraints true then adds any x+y=1 or x-y=0 constraints
4207 If NULL infeasible
4208 */
4209 OsiSolverInterface *
modified(OsiSolverInterface * model,bool constraints,int & numberChanges,int iBigPass,int numberPasses)4210 CglPreProcess::modified(OsiSolverInterface *model,
4211 bool constraints,
4212 int &numberChanges,
4213 int iBigPass,
4214 int numberPasses)
4215 {
4216 OsiSolverInterface *newModel = model->clone();
4217 int numberRows = newModel->getNumRows();
4218 CglUniqueRowCuts twoCuts(numberRows);
4219 int numberColumns = newModel->getNumCols();
4220 int number01Integers = 0;
4221 int iColumn;
4222 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4223 if (newModel->isBinary(iColumn))
4224 number01Integers++;
4225 }
4226 #if CBC_USEFUL_PRINTING > 0
4227 printf("At beginning of modified %d rows and %d columns (pass %d - doing %d minor passes)\n",
4228 numberRows, numberColumns, iBigPass, numberPasses);
4229 #endif
4230 OsiRowCut **whichCut = new OsiRowCut *[numberRows + 1];
4231 memset(whichCut, 0, (numberRows + 1) * sizeof(OsiRowCut *));
4232 numberChanges = 0;
4233 CoinThreadRandom randomGenerator;
4234 CglTreeProbingInfo info(model);
4235 info.level = 0;
4236 info.pass = 0;
4237 info.formulation_rows = numberRows;
4238 info.inTree = false;
4239 info.options = !numberProhibited_ ? 0 : 2;
4240 info.randomNumberGenerator = &randomGenerator;
4241 info.strengthenRow = whichCut;
4242 #ifdef HEAVY_PROBING
4243 // See if user asked for heavy probing
4244 bool heavyProbing = false;
4245 for (int iGenerator = 0; iGenerator < numberCutGenerators_; iGenerator++) {
4246 CglProbing *probingCut = dynamic_cast< CglProbing * >(generator_[iGenerator]);
4247 if (probingCut && probingCut->getMaxPassRoot() > 1) {
4248 heavyProbing = true;
4249 break;
4250 }
4251 }
4252 #endif
4253 bool feasible = true;
4254 int firstGenerator = 0;
4255 int lastGenerator = numberCutGenerators_;
4256 bool useSolution = getCutoff() < 1.0e20;
4257 #if 1
4258 // Do triple stuff
4259 if (iBigPass == 0) {
4260 // Row copy
4261 CoinPackedMatrix matrixByRow(*newModel->getMatrixByRow());
4262 const double *elementByRow = matrixByRow.getElements();
4263 const int *column = matrixByRow.getIndices();
4264 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
4265 const int *rowLength = matrixByRow.getVectorLengths();
4266
4267 // Column copy
4268 CoinPackedMatrix matrixByCol(*newModel->getMatrixByCol());
4269 //const double * element = matrixByCol.getElements();
4270 const int *row = matrixByCol.getIndices();
4271 const CoinBigIndex *columnStart = matrixByCol.getVectorStarts();
4272 const int *columnLength = matrixByCol.getVectorLengths();
4273
4274 const double *rowLower = newModel->getRowLower();
4275 const double *rowUpper = newModel->getRowUpper();
4276 const double *columnLower = newModel->getColLower();
4277 const double *columnUpper = newModel->getColUpper();
4278 #define TRIPLE_ROWS 4
4279 #define TRIPLE_COLS 3
4280 // just allow TRIPLE_ROWS rows
4281 double el[TRIPLE_COLS][2 * TRIPLE_ROWS];
4282 double rhs[2 * TRIPLE_ROWS], lower[TRIPLE_ROWS], upper[TRIPLE_ROWS];
4283 double modifiedRhs[2 * TRIPLE_ROWS], scaleFactor[2 * TRIPLE_ROWS];
4284 memset(modifiedRhs, 0, sizeof(modifiedRhs));
4285 memset(scaleFactor, 0, sizeof(scaleFactor));
4286 int rowNumber[2 * TRIPLE_ROWS];
4287 double colLower[TRIPLE_COLS], colUpper[TRIPLE_COLS];
4288 #if CBC_USEFUL_PRINTING > 0
4289 int binary[TRIPLE_COLS];
4290 int colNumber[TRIPLE_COLS];
4291 #endif
4292 unsigned char result[2 * TRIPLE_ROWS][2 * TRIPLE_ROWS];
4293 int rowType[2 * TRIPLE_ROWS];
4294 #define MAX_ELS 20
4295 #define MAX_LOOK_ROWS 40
4296 #define MAX_LOOK_COLS 32 // for more go to long
4297 unsigned int bitMask[MAX_LOOK_ROWS];
4298 int *which = new int[2 * numberColumns + 3 * numberRows + MAX_LOOK_ROWS + MAX_LOOK_COLS];
4299 int *marked = which + MAX_LOOK_COLS;
4300 int *whichRow = marked + numberColumns;
4301 int *markRow = whichRow + MAX_LOOK_ROWS;
4302 int *backwardRow = markRow + numberRows;
4303 int *backwardColumn = backwardRow + numberRows;
4304 int *rowTypeAll = backwardColumn + numberColumns;
4305 memset(marked, 0, numberColumns * sizeof(int));
4306 memset(markRow, 0, numberRows * sizeof(int));
4307 for (int iRow = 0; iRow < numberRows; iRow++) {
4308 int type = 0;
4309 if (rowLower[iRow] != rowUpper[iRow]) {
4310 if (rowLower[iRow] > -1.0e30) {
4311 if (rowUpper[iRow] < 1.0e30) {
4312 type = 2;
4313 } else {
4314 type = 1;
4315 }
4316 } else {
4317 if (rowUpper[iRow] < 1.0e30) {
4318 type = 2;
4319 } else {
4320 type = 0;
4321 }
4322 }
4323 } else {
4324 type = 3;
4325 }
4326 if (rowType_ && rowType_[iRow])
4327 type = 0; // not allowed if may be cut
4328 rowTypeAll[iRow] = type;
4329 }
4330 // clean model
4331 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
4332 if (newModel->isInteger(iColumn)) {
4333 double lower = columnLower[iColumn];
4334 double upper = columnUpper[iColumn];
4335 double saveLower = lower;
4336 double saveUpper = upper;
4337 if (lower != ceil(lower)) {
4338 if (fabs(lower - floor(lower + 0.5)) < 1.0e-6)
4339 lower = floor(lower + 0.5);
4340 else
4341 lower = ceil(lower);
4342 newModel->setColLower(iColumn, lower);
4343 }
4344 if (upper != floor(upper)) {
4345 if (fabs(upper - floor(upper + 0.5)) < 1.0e-6)
4346 upper = floor(upper + 0.5);
4347 else
4348 upper = floor(upper);
4349 newModel->setColUpper(iColumn, upper);
4350 }
4351 if (lower > upper) {
4352 char generalPrint[100];
4353 sprintf(generalPrint, "%d input bounds %g %g",
4354 iColumn, saveLower, saveUpper);
4355 handler_->message(CGL_GENERAL, messages_)
4356 << generalPrint
4357 << CoinMessageEol;
4358 handler_->message(CGL_INFEASIBLE, messages_)
4359 << CoinMessageEol;
4360 feasible = false;
4361 }
4362 if (lower < 0.0) {
4363 // take out for now
4364 for (CoinBigIndex j = columnStart[iColumn];
4365 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4366 int iRow = row[j];
4367 rowTypeAll[iRow] = 0;
4368 }
4369 }
4370 }
4371 }
4372 #if CBC_USEFUL_PRINTING > 0
4373 int nFreed = 0;
4374 #endif
4375 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
4376 if (!feasible)
4377 break;
4378 if (newModel->isInteger(iColumn) && columnLength[iColumn] <= MAX_ELS
4379 && columnLength[iColumn] > 1 && columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1.0) {
4380 int nMarked = 0;
4381 backwardColumn[iColumn] = 0;
4382 marked[iColumn] = 1;
4383 which[nMarked++] = iColumn;
4384 int nMarkRow = 0;
4385 for (CoinBigIndex j = columnStart[iColumn];
4386 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4387 int iRow = row[j];
4388 markRow[iRow] = nMarkRow + 1;
4389 backwardRow[iRow] = nMarkRow;
4390 bitMask[nMarkRow] = 0;
4391 if (!rowTypeAll[iRow]) {
4392 // no good
4393 bitMask[nMarkRow] = 0xffffffff;
4394 }
4395 whichRow[nMarkRow++] = iRow;
4396 }
4397 for (CoinBigIndex j = columnStart[iColumn];
4398 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4399 int iRow = row[j];
4400 if (rowLength[iRow] <= 3) {
4401 for (CoinBigIndex k = rowStart[iRow];
4402 k < rowStart[iRow] + rowLength[iRow]; k++) {
4403 int kColumn = column[k];
4404 if (!marked[kColumn]) {
4405 int iMask = backwardRow[iRow];
4406 if (nMarked == MAX_LOOK_COLS) {
4407 // say row no good
4408 bitMask[iMask] = 0xffffffff;
4409 continue;
4410 } else if (bitMask[iMask] == 0xffffffff) {
4411 continue;
4412 }
4413 backwardColumn[kColumn] = nMarked;
4414 marked[kColumn] = nMarked + 1;
4415 which[nMarked++] = kColumn;
4416 }
4417 int iMask = backwardRow[iRow];
4418 int iShift = backwardColumn[kColumn];
4419 bitMask[iMask] |= (1 << iShift);
4420 }
4421 }
4422 }
4423 // See if any match
4424 for (int iLook = 0; iLook < nMarkRow - 1; iLook++) {
4425 unsigned int mask = bitMask[iLook];
4426 if (mask && mask != 0xffffffff && markRow) {
4427 int nMatch = 0;
4428 // count bits
4429 int nBits = 0;
4430 for (int i = 0; i < nMarked; i++) {
4431 if ((mask & 1) != 0)
4432 nBits++;
4433 mask = mask >> 1;
4434 }
4435 mask = bitMask[iLook];
4436 for (int jLook = iLook + 1; jLook < nMarkRow; jLook++) {
4437 if (bitMask[jLook] == mask)
4438 nMatch++;
4439 }
4440 if (nMatch) {
4441 #if CBC_USEFUL_PRINTING > 0
4442 printf("For column %d %d matches on size %d\n",
4443 iColumn, nMatch, nBits);
4444 if (nMatch > 1) {
4445 printf("WHAT NOW\n");
4446 }
4447 #endif
4448 // Pad out here
4449 int jColumn1 = -1, jColumn2 = -1;
4450 int iRow1 = whichRow[iLook];
4451 int iRow2 = -1;
4452 for (int jLook = iLook + 1; jLook < nMarkRow; jLook++) {
4453 if (bitMask[jLook] == mask) {
4454 iRow2 = whichRow[jLook];
4455 break;
4456 }
4457 }
4458 rowNumber[0] = iRow1;
4459 rowNumber[1] = iRow2;
4460 colLower[0] = 0.0;
4461 colUpper[0] = 1.0;
4462 #if CBC_USEFUL_PRINTING > 0
4463 binary[0] = 1;
4464 int nCol = nBits;
4465 #endif
4466 assert(rowLength[iRow1] <= 3);
4467 int nRow = 2;
4468 for (int j = 0; j < 2; j++) {
4469 int iRow = rowNumber[j];
4470 lower[j] = rowLower[iRow];
4471 upper[j] = rowUpper[iRow];
4472 for (CoinBigIndex k = rowStart[iRow];
4473 k < rowStart[iRow] + rowLength[iRow]; k++) {
4474 int kColumn = column[k];
4475 if (kColumn == iColumn) {
4476 el[0][j] = elementByRow[k];
4477 } else if (kColumn == jColumn1) {
4478 el[1][j] = elementByRow[k];
4479 } else if (kColumn == jColumn2) {
4480 el[2][j] = elementByRow[k];
4481 } else if (jColumn1 < 0) {
4482 jColumn1 = kColumn;
4483 el[1][j] = elementByRow[k];
4484 colLower[1] = columnLower[kColumn];
4485 colUpper[1] = columnUpper[kColumn];
4486 #if CBC_USEFUL_PRINTING > 0
4487 binary[1] = 0;
4488 if (!colLower[1] && colUpper[1] == 1.0 && newModel->isInteger(kColumn))
4489 binary[1] = 1;
4490 #endif
4491 } else if (jColumn2 < 0) {
4492 jColumn2 = kColumn;
4493 el[2][j] = elementByRow[k];
4494 colLower[2] = columnLower[kColumn];
4495 colUpper[2] = columnUpper[kColumn];
4496 #if CBC_USEFUL_PRINTING > 0
4497 binary[2] = 0;
4498 if (!colLower[2] && colUpper[2] == 1.0 && newModel->isInteger(kColumn))
4499 binary[2] = 1;
4500 #endif
4501 } else {
4502 abort();
4503 }
4504 }
4505 }
4506 if (jColumn1 < 0) {
4507 #if CBC_USEFUL_PRINTING > 0
4508 printf("**Why jColumn1 negative\n");
4509 #endif
4510 continue;
4511 }
4512 #if CBC_USEFUL_PRINTING > 0
4513 colNumber[0] = iColumn;
4514 colNumber[1] = jColumn1;
4515 colNumber[2] = jColumn2;
4516 #endif
4517 // do something
4518 assert(columnLower[iColumn] == 0.0);
4519 assert(columnUpper[iColumn] == 1.0);
4520 if (nBits == 2) {
4521 #if CBC_USEFUL_PRINTING > 0
4522 printf("iColumn %d %g %g binary\n", iColumn, colLower[0],
4523 colUpper[0]);
4524 printf("jColumn1 %d %g %g %s\n", jColumn1, colLower[1],
4525 colUpper[1], newModel->isInteger(jColumn1) ? "integer" : "continuous");
4526 for (int i = 0; i < 2; i++) {
4527 printf("%d row %d %g <= %g*x0%s%g*x1 <= %g\n",
4528 i, rowNumber[i], lower[i], el[0][i],
4529 el[1][i] > 0.0 ? " +" : " -", fabs(el[1][i]), upper[i]);
4530 }
4531 #endif
4532 double lower1[2], upper1[2];
4533 lower1[0] = lower1[1] = colLower[1];
4534 upper1[0] = upper1[1] = colUpper[1];
4535 double l, u;
4536 // binary at 0
4537 l = lower[0];
4538 u = upper[0];
4539 if (el[1][0] > 0.0) {
4540 lower1[0] = CoinMax(lower1[0], l / el[1][0]);
4541 upper1[0] = CoinMin(upper1[0], u / el[1][0]);
4542 } else {
4543 lower1[0] = CoinMax(lower1[0], u / el[1][0]);
4544 upper1[0] = CoinMin(upper1[0], l / el[1][0]);
4545 }
4546 l = lower[1];
4547 u = upper[1];
4548 if (el[1][1] > 0.0) {
4549 lower1[0] = CoinMax(lower1[0], l / el[1][1]);
4550 upper1[0] = CoinMin(upper1[0], u / el[1][1]);
4551 } else {
4552 lower1[0] = CoinMax(lower1[0], u / el[1][1]);
4553 upper1[0] = CoinMin(upper1[0], l / el[1][1]);
4554 }
4555 l = lower[0] - el[0][0];
4556 u = upper[0] - el[0][0];
4557 if (el[1][0] > 0.0) {
4558 lower1[1] = CoinMax(lower1[1], l / el[1][0]);
4559 upper1[1] = CoinMin(upper1[1], u / el[1][0]);
4560 } else {
4561 lower1[1] = CoinMax(lower1[1], u / el[1][0]);
4562 upper1[1] = CoinMin(upper1[1], l / el[1][0]);
4563 }
4564 l = lower[1] - el[0][1];
4565 u = upper[1] - el[0][1];
4566 if (el[1][1] > 0.0) {
4567 lower1[1] = CoinMax(lower1[1], l / el[1][1]);
4568 upper1[1] = CoinMin(upper1[1], u / el[1][1]);
4569 } else {
4570 lower1[1] = CoinMax(lower1[1], u / el[1][1]);
4571 upper1[1] = CoinMin(upper1[1], l / el[1][1]);
4572 }
4573 if (CoinMin(lower1[0], lower1[1]) > colLower[1]) {
4574 #if CBC_USEFUL_PRINTING > 0
4575 printf("for jColumn1 0-bounds %g,%g 1-bounds %g,%g\n",
4576 lower1[0], upper1[0], lower1[1], upper1[1]);
4577 #endif
4578 double value = CoinMin(lower1[0], lower1[1]);
4579 if (newModel->isInteger(jColumn1))
4580 value = ceil(value - 1.0e-5);
4581 #if CBC_USEFUL_PRINTING > 0
4582 printf("increasing lb on %d from %g to %g\n",
4583 jColumn1, colLower[1], value);
4584 #endif
4585 colLower[1] = value;
4586 newModel->setColLower(jColumn1, value);
4587 }
4588 if (CoinMax(upper1[0], upper1[1]) < colUpper[1]) {
4589 #if CBC_USEFUL_PRINTING > 0
4590 printf("for jColumn1 0-bounds %g,%g 1-bounds %g,%g\n",
4591 lower1[0], upper1[0], lower1[1], upper1[1]);
4592 #endif
4593 double value = CoinMax(upper1[0], upper1[1]);
4594 if (newModel->isInteger(jColumn1))
4595 value = floor(value + 1.0e-5);
4596 #if CBC_USEFUL_PRINTING > 0
4597 printf("decreasing ub on %d from %g to %g\n",
4598 jColumn1, colUpper[1], value);
4599 #endif
4600 colUpper[1] = value;
4601 newModel->setColUpper(jColumn1, value);
4602 }
4603 if (lower1[0] > colUpper[1] || upper1[0] < colLower[1]) {
4604 #if CBC_USEFUL_PRINTING > 0
4605 printf("for jColumn1 0-bounds %g,%g 1-bounds %g,%g\n",
4606 lower1[0], upper1[0], lower1[1], upper1[1]);
4607 printf("fixing %d to 1\n", iColumn);
4608 #endif
4609 colLower[0] = 1.0;
4610 newModel->setColLower(iColumn, 1.0);
4611 nMarkRow = 0; // stop looking
4612 }
4613 if (lower1[1] > colUpper[1] || upper1[1] < colLower[1]) {
4614 #if CBC_USEFUL_PRINTING > 0
4615 printf("for jColumn1 0-bounds %g,%g 1-bounds %g,%g\n",
4616 lower1[0], upper1[0], lower1[1], upper1[1]);
4617 printf("fixing %d to 0\n", iColumn);
4618 #endif
4619 colUpper[0] = 0.0;
4620 newModel->setColLower(iColumn, 0.0);
4621 nMarkRow = 0; // stop looking
4622 }
4623 if (colLower[0] > colUpper[0] || colLower[1] > colUpper[1] + 1.0e-6) {
4624 #if CBC_USEFUL_PRINTING > 0
4625 printf("** infeasible\n");
4626 #endif
4627 feasible = false;
4628 }
4629 } else {
4630 #if CBC_USEFUL_PRINTING > 0
4631 printf("iColumn %d %g %g binary\n", iColumn, colLower[0],
4632 colUpper[0]);
4633 printf("jColumn1 %d %g %g %s\n", jColumn1, colLower[1],
4634 colUpper[1], newModel->isInteger(jColumn1) ? "integer" : "continuous");
4635 printf("jColumn2 %d %g %g %s\n", jColumn2, colLower[2],
4636 colUpper[2], newModel->isInteger(jColumn2) ? "integer" : "continuous");
4637 for (int i = 0; i < 2; i++) {
4638 printf("%d row %d %g <= %g*x0%s%g*x1%s%g*x2 <= %g\n",
4639 i, rowNumber[i], lower[i], el[0][i],
4640 el[1][i] > 0.0 ? " +" : " -", fabs(el[1][i]),
4641 el[2][i] > 0.0 ? " +" : " -", fabs(el[2][i]), upper[i]);
4642 }
4643 #endif
4644 // Find other doubleton rows
4645 for (CoinBigIndex j1 = columnStart[jColumn1];
4646 j1 < columnStart[jColumn1] + columnLength[jColumn1]; j1++) {
4647 int iRow = row[j1];
4648 if (rowLength[iRow] == 2 && rowTypeAll[iRow]) {
4649 CoinBigIndex start = rowStart[iRow];
4650 bool good = false;
4651 if (jColumn1 == column[start] && jColumn2 == column[start + 1]) {
4652 good = true;
4653 el[1][nRow] = elementByRow[start];
4654 el[2][nRow] = elementByRow[start + 1];
4655 } else if (jColumn1 == column[start + 1] && jColumn2 == column[start]) {
4656 good = true;
4657 el[1][nRow] = elementByRow[start + 1];
4658 el[2][nRow] = elementByRow[start];
4659 }
4660 if (good) {
4661 rowNumber[nRow] = iRow;
4662 lower[nRow] = rowLower[iRow];
4663 upper[nRow] = rowUpper[iRow];
4664 el[0][nRow] = 0.0;
4665 #if CBC_USEFUL_PRINTING > 0
4666 printf("%d row %d %g <= %g*x0%s%g*x1%s%g*x2 <= %g\n",
4667 nRow, iRow, lower[nRow], el[0][nRow],
4668 el[1][nRow] > 0.0 ? " +" : " -", fabs(el[1][nRow]),
4669 el[2][nRow] > 0.0 ? " +" : " -", fabs(el[2][nRow]), upper[nRow]);
4670 #endif
4671 nRow++;
4672 if (nRow == TRIPLE_ROWS)
4673 break;
4674 }
4675 }
4676 }
4677 }
4678 // Now put in <= form
4679 int nLook = nRow;
4680 // types 1 <=, -1 >= 2 first ==, -2 second ==, 3 <= from range, -3 >= from range
4681 for (int i = 0; i < nRow; i++) {
4682 rowType[i] = 1;
4683 if (lower[i] < -1.0e20) {
4684 rhs[i] = upper[i];
4685 } else if (upper[i] > 1.0e20) {
4686 rowType[i] = -1;
4687 rhs[i] = -lower[i];
4688 for (int j = 0; j < nBits; j++)
4689 el[j][i] = -el[j][i];
4690 } else if (lower[i] == upper[i]) {
4691 rhs[i] = upper[i];
4692 rowType[i] = 2;
4693 rowType[nLook] = -2;
4694 rowNumber[nLook] = rowNumber[i];
4695 rhs[nLook] = -upper[i];
4696 for (int j = 0; j < nBits; j++)
4697 el[j][nLook] = -el[j][i];
4698 nLook++;
4699 } else {
4700 rhs[i] = upper[i];
4701 rowType[i] = 3;
4702 rowType[nLook] = -3;
4703 rowNumber[nLook] = rowNumber[i];
4704 rhs[nLook] = -lower[i];
4705 for (int j = 0; j < nBits; j++)
4706 el[j][nLook] = -el[j][i];
4707 nLook++;
4708 }
4709 }
4710 // scale
4711 for (int i = 0; i < nRow; i++) {
4712 double largest = 0.0;
4713 double smallest = COIN_DBL_MAX;
4714 for (int k = 1; k < nBits; k++) {
4715 double value = fabs(el[k][i]);
4716 if (value) {
4717 largest = CoinMax(largest, value);
4718 smallest = CoinMin(smallest, value);
4719 }
4720 }
4721 scaleFactor[i] = 1.0 / sqrt(largest * smallest);
4722 }
4723 // Look at all possible combinations
4724 // For now just look at first
4725 // also ignore bounds (should subtract out lbs from rhs)
4726 assert(nBits <= 3);
4727 memset(result, 0, sizeof(result));
4728 // bottom 4 bits for 0, next 4 for 1
4729 // 0 not stronger, 1 ==, 2 stronger (els)
4730 // 0 not stronger, 4 ==, 8 stronger (rhs)
4731 for (int j = 0; j < 2; j++) {
4732 for (int k = 0; k < nLook; k++)
4733 modifiedRhs[k] = scaleFactor[k] * (rhs[k] - j * el[0][k]);
4734 for (int k1 = 0; k1 < nLook; k1++) {
4735 for (int k2 = 0; k2 < nLook; k2++) {
4736 if (k1 != k2 && rowNumber[k1] != rowNumber[k2]) {
4737 int stronger = 8;
4738 if (modifiedRhs[k1] > modifiedRhs[k2] + 1.0e-7) {
4739 stronger = 0;
4740 } else if (modifiedRhs[k1] > modifiedRhs[k2] - 1.0e-7) {
4741 stronger = 4;
4742 }
4743 if (stronger) {
4744 int strongerEl = 2;
4745 for (int k3 = 1; k3 < nBits; k3++) {
4746 if (scaleFactor[k1] * el[k3][k1] < scaleFactor[k2] * el[k3][k2] - 1.0e-9) {
4747 stronger = 0;
4748 break;
4749 } else if (scaleFactor[k1] * el[k3][k1] < scaleFactor[k2] * el[k3][k2] + 1.0e-9) {
4750 strongerEl = 1;
4751 }
4752 }
4753 if (stronger) {
4754 stronger |= strongerEl;
4755 }
4756 result[k1][k2] |= static_cast< unsigned char >(stronger << (4 * j));
4757 }
4758 }
4759 }
4760 }
4761 }
4762 int dropped = -1;
4763 for (int k1 = 0; k1 < nLook; k1++) {
4764 for (int k2 = 0; k2 < nLook; k2++) {
4765 if (k1 != k2 && rowNumber[k1] != rowNumber[k2]) {
4766 int state0 = result[k1][k2] & 15;
4767 int state1 = result[k1][k2] >> 4;
4768 if (state0 && state1) {
4769 if (state0 == 5) {
4770 if (state1 == 5) {
4771 // same
4772 if (abs(rowType[k1]) == 1)
4773 dropped = k1;
4774 else
4775 dropped = k2;
4776 #if CBC_USEFUL_PRINTING > 0
4777 printf("ZZZsame ");
4778 #endif
4779 } else if (state1 == 9) {
4780 // drop second
4781 dropped = k2;
4782 #if CBC_USEFUL_PRINTING > 0
4783 printf("ZZZfirst ");
4784 #endif
4785 } else {
4786 #if CBC_USEFUL_PRINTING > 0
4787 printf("ZZYY ");
4788 #endif
4789 }
4790 } else if (state0 == 9) {
4791 // drop second
4792 dropped = k2;
4793 #if CBC_USEFUL_PRINTING > 0
4794 printf("ZZZsecond ");
4795 #endif
4796 } else {
4797 #if CBC_USEFUL_PRINTING > 0
4798 printf("ZZYY ");
4799 #endif
4800 }
4801 #if CBC_USEFUL_PRINTING > 0
4802 printf("row %d (%d) and row %d (%d) status at 0 is %d status at 1 is %d\n",
4803 k1, rowNumber[k1], k2, rowNumber[k2],
4804 state0, state1);
4805 #endif
4806 if (dropped >= 0)
4807 break;
4808 }
4809 }
4810 }
4811 if (dropped >= 0)
4812 break;
4813 }
4814 if (dropped >= 0) {
4815 int iRow = rowNumber[dropped];
4816 // Think if ranged or ==
4817 if (rowLower[iRow] < -1.0e30 || rowUpper[iRow] > 1.0e30) {
4818 newModel->setRowLower(iRow, -COIN_DBL_MAX);
4819 newModel->setRowUpper(iRow, COIN_DBL_MAX);
4820 #if CBC_USEFUL_PRINTING > 0
4821 nFreed++;
4822 #endif
4823 } else {
4824 #if CBC_USEFUL_PRINTING > 0
4825 printf("XXXYYY - shouldn't drop ranged/equality row????\n");
4826 #endif
4827 }
4828 }
4829 // stop rest
4830 for (int jLook = iLook; jLook < nMarkRow; jLook++) {
4831 if (bitMask[jLook] == mask)
4832 bitMask[jLook] = 0;
4833 }
4834 }
4835 }
4836 }
4837 for (int i = 0; i < nMarked; i++) {
4838 marked[which[i]] = 0;
4839 }
4840 for (int i = 0; i < nMarkRow; i++) {
4841 markRow[whichRow[i]] = 0;
4842 }
4843 }
4844 }
4845 #if CBC_USEFUL_PRINTING > 0
4846 if (nFreed)
4847 printf("%d rows freed up\n", nFreed);
4848 #endif
4849 delete[] which;
4850 }
4851 #endif
4852 #if 0
4853 // Do domination stuff
4854 if (iBigPass==0) {
4855 // Row copy
4856 CoinPackedMatrix matrixByRow(*newModel->getMatrixByRow());
4857 const double * elementByRow = matrixByRow.getElements();
4858 const int * column = matrixByRow.getIndices();
4859 const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
4860 const int * rowLength = matrixByRow.getVectorLengths();
4861
4862 // Column copy
4863 CoinPackedMatrix matrixByCol(*newModel->getMatrixByCol());
4864 //const double * element = matrixByCol.getElements();
4865 const int * row = matrixByCol.getIndices();
4866 const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
4867 const int * columnLength = matrixByCol.getVectorLengths();
4868
4869 const double * rowLower = newModel->getRowLower();
4870 const double * rowUpper = newModel->getRowUpper();
4871 const double * columnLower = newModel->getColLower();
4872 const double * columnUpper = newModel->getColUpper();
4873 // get sizes for canonical form (overestimate if free columns)
4874 int nRows=numberRows;
4875 CoinBigIndex nEls=matrixByRow.getNumElements();
4876 for (int iRow=0;iRow<numberRows;iRow++) {
4877 if (rowLower[iRow]>-1.0e30&&rowUpper[iRow]<1.0e30) {
4878 nRows++;
4879 nEls += rowLength[iRow];
4880 }
4881 }
4882 int * rowNumber = new int[3*nRows+numberColumns];
4883 int * rowBinary = rowNumber+nRows;
4884 int * rowPos = rowBinary+nRows;
4885 int * whichColumn = rowPos+nRows;
4886 double * elementByRow2 = new double [nEls+numberColumns+nRows];
4887 double * columnValue = elementByRow2+nEls;
4888 double * rhs = columnValue+numberColumns;
4889 int * column2 = new int [nEls];
4890 CoinBigIndex * rowStart2 = new CoinBigIndex[nRows+1];
4891 char * marked = new char [numberColumns+nRows];
4892 char * markedRow = marked + numberColumns;
4893 for (int iColumn=0;iColumn<numberColumns;iColumn++) {
4894 columnValue[iColumn]=0.0;
4895 if (columnLower[iColumn]<-1.0e10&&columnUpper[iColumn]>1.0e10) {
4896 marked[iColumn]=-1;
4897 } else if (fabs(columnUpper[iColumn])<fabs(columnLower[iColumn])) {
4898 // flip
4899 marked[iColumn]=2;
4900 columnValue[iColumn]=-columnUpper[iColumn];
4901 if (newModel->isInteger(iColumn) &&
4902 columnUpper[iColumn]==columnLower[iColumn]+1)
4903 marked[iColumn]=3;
4904 } else {
4905 marked[iColumn]=0;
4906 columnValue[iColumn]=columnLower[iColumn];
4907 if (newModel->isInteger(iColumn) &&
4908 columnUpper[iColumn]==columnLower[iColumn]+1)
4909 marked[iColumn]=1;
4910 }
4911 }
4912 nRows=0;
4913 nEls=0;
4914 rowStart2[0]=0;
4915 for (int iRow=0;iRow<numberRows;iRow++) {
4916 CoinBigIndex start = rowStart[iRow];
4917 CoinBigIndex end = start + rowLength[iRow];
4918 for (int iTry=0;iTry<2;iTry++) {
4919 double multiplier;
4920 double rhsValue;
4921 if (!iTry) {
4922 multiplier=1.0;
4923 rhsValue = rowUpper[iRow];
4924 } else {
4925 multiplier=-1.0;
4926 rhsValue = -rowLower[iRow];
4927 }
4928 if (rhsValue<1.0e30) {
4929 char typeRow=iTry;
4930 int nPos=0;
4931 int nInt=0;
4932 double largest=0.0;
4933 double smallest=COIN_DBL_MAX;
4934 for (CoinBigIndex k=start;k<end;k++) {
4935 int kColumn = column[k];
4936 int type = marked[kColumn];
4937 double value = multiplier*elementByRow[k];
4938 if (type<0) {
4939 nEls=rowStart2[nRows];
4940 typeRow=-1;;
4941 break;
4942 } else if ((type&2)!=0) {
4943 value = -value;
4944 }
4945 if ((type&1)!=0)
4946 nInt++;
4947 rhsValue -= value*columnValue[kColumn];
4948 elementByRow2[nEls]=value;
4949 if (value>0.0)
4950 nPos++;
4951 largest=CoinMax(fabs(value),largest);
4952 smallest=CoinMin(fabs(value),smallest);
4953 column2[nEls++]=kColumn;
4954 }
4955 if (typeRow>=0 && smallest*1.0e7>largest) {
4956 double scale = sqrt(largest*smallest);
4957 if (fabs(rhsValue)>1.0e6*scale||
4958 (rhsValue&&fabs(rhsValue)<1.0e-6*scale)) {
4959 scale=0.0;
4960 } else if (rhsValue) {
4961 scale=1.0/fabs(rhsValue);
4962 }
4963 if (scale) {
4964 rhs[nRows]=scale*rhsValue;
4965 for (CoinBigIndex k=rowStart2[nRows];k<nEls;k++)
4966 elementByRow2[k] *= scale;
4967 rowPos[nRows]=nPos;
4968 markedRow[nRows]=typeRow;
4969 rowBinary[nRows]=nInt;
4970 rowNumber[nRows++]=iRow;
4971 rowStart2[nRows]=nEls;
4972 } else {
4973 nEls=rowStart2[nRows];
4974 }
4975 }
4976 }
4977 }
4978 }
4979 memset(columnValue,0,numberColumns*sizeof(double));
4980 double tolerance = 1.0e-9;
4981 for (int iRow=0;iRow<nRows;iRow++) {
4982 CoinBigIndex start = rowStart2[iRow];
4983 CoinBigIndex end = rowStart2[iRow+1];
4984 int n=0;
4985 int nInt=rowBinary[iRow];
4986 for (CoinBigIndex k=start;k<end;k++) {
4987 int kColumn = column2[k];
4988 double value = elementByRow2[k];
4989 columnValue[kColumn]=value;
4990 whichColumn[n++]=kColumn;
4991 }
4992 double rhsValue=rhs[iRow];
4993 int nPos=rowPos[iRow];
4994 int nNeg=n-nPos;
4995 // initially only short integer rows
4996 if (n>3)
4997 nInt=0;
4998 // for first try ignore integers!
4999 nInt=0;
5000 if (nInt) {
5001 } else {
5002 for (int jRow=iRow+1;jRow<nRows;jRow++) {
5003 CoinBigIndex start2 = rowStart2[jRow];
5004 CoinBigIndex end2 = rowStart2[jRow+1];
5005 int n2=end2-start2;
5006 int nPos2=rowPos[jRow];
5007 int nNeg2=n2-nPos2;
5008 int nInt2=rowBinary[jRow];
5009 double rhsValue2=rhs[jRow];
5010 // initially only short integer rows
5011 if (n2>3)
5012 nInt2=0;
5013 // for first try ignore integers!
5014 nInt2=0;
5015 if (nInt2) {
5016 } else {
5017 // continuous tests
5018 // -1 iRow may be stronger, +1 jRow may be stronger, 0 continue, 2 == els
5019 int way=2;
5020 if (rhsValue>rhsValue2+tolerance)
5021 way=1;
5022 else if (rhsValue2>rhsValue+tolerance)
5023 way=-1;
5024 if (nNeg2>nNeg) {
5025 // iRow can be stronger
5026 if (nPos2>nPos || way == 1)
5027 way=0;
5028 else
5029 way=-1;
5030 } else if (nNeg2==nNeg) {
5031 // iRow can be either way
5032 if (nPos2>nPos) {
5033 if (way!=-1)
5034 way=1;
5035 else
5036 way=0;
5037 } else if (nPos2<nPos) {
5038 if (way!=1)
5039 way=-1;
5040 else
5041 way=0;
5042 }
5043 } else {
5044 // jRow can be stronger
5045 if (nPos2<nPos || way==-1)
5046 way=0;
5047 else
5048 way=1;
5049 }
5050 int nHitPos=0;
5051 int nHitNeg=0;
5052 if (way==-1) {
5053 // iRow may be stronger
5054 for (CoinBigIndex k2=start2;k2<end2;k2++) {
5055 int kColumn = column2[k2];
5056 double value = elementByRow2[k2];
5057 double valueI=columnValue[kColumn];
5058 if (value>valueI+1.0e-12) {
5059 way=0;
5060 break;
5061 } else {
5062 if (valueI<0.0)
5063 nHitNeg++;
5064 }
5065 }
5066 if (nHitNeg<nNeg2)
5067 way=0;
5068 } else if (way==1) {
5069 // jRow may be stronger
5070 for (CoinBigIndex k2=start2;k2<end2;k2++) {
5071 int kColumn = column2[k2];
5072 double value = elementByRow2[k2];
5073 double valueI=columnValue[kColumn];
5074 if (value<valueI-1.0e-12) {
5075 way=0;
5076 break;
5077 } else {
5078 if (valueI>0.0)
5079 nHitPos++;
5080 }
5081 }
5082 if (nHitPos<nPos)
5083 way=0;
5084 } else if (way==2) {
5085 // same number and rhs - could go either way
5086 CoinBigIndex k2;
5087 for (k2=start2;k2<end2;k2++) {
5088 int kColumn = column2[k2];
5089 double value = elementByRow2[k2];
5090 if (value<columnValue[kColumn]-1.0e-12) {
5091 way=-1;
5092 break;
5093 } else if (value>columnValue[kColumn]+1.0e-12) {
5094 way=1;
5095 break;
5096 }
5097 }
5098 k2++;
5099 if (way==1) {
5100 for (;k2<end2;k2++) {
5101 int kColumn = column2[k2];
5102 double value = elementByRow2[k2];
5103 double valueI=columnValue[kColumn];
5104 if (value<valueI-1.0e-12) {
5105 way=0;
5106 break;
5107 } else {
5108 if (valueI>0.0)
5109 nHitPos++;
5110 }
5111 }
5112 if (nHitPos<nPos)
5113 way=0;
5114 } else if (way==-1) {
5115 for (;k2<end2;k2++) {
5116 int kColumn = column2[k2];
5117 double value = elementByRow2[k2];
5118 double valueI=columnValue[kColumn];
5119 if (value>valueI+1.0e-12) {
5120 way=0;
5121 break;
5122 } else {
5123 if (valueI<0.0)
5124 nHitNeg++;
5125 }
5126 }
5127 if (nHitNeg<nNeg2)
5128 way=0;
5129 }
5130 }
5131 #if CBC_USEFUL_PRINTING
5132 if (way) {
5133 int iRowX=rowNumber[iRow];
5134 int jRowX=rowNumber[jRow];
5135 CoinBigIndex startI = rowStart[iRowX];
5136 CoinBigIndex endI = startI + rowLength[iRowX];
5137 CoinBigIndex startJ = rowStart[jRowX];
5138 CoinBigIndex endJ = startJ + rowLength[jRowX];
5139 printf("way %d for row %d (%d - %d els) and %d (%d - %d els)\n",
5140 way,iRow,iRowX,endI-startI,jRow,jRowX,endJ-startJ);
5141 printf("%g <= ",rowLower[iRowX]);
5142 if (endI-startI<100&&endJ-startJ<10) {
5143 for (CoinBigIndex k=startI;k<endI;k++)
5144 printf("(%d,%g) ",column[k],elementByRow[k]);
5145 } else {
5146 printf("something ");
5147 }
5148 printf("<= %g\n",rowUpper[iRowX]);
5149 printf("%g <= ",rowLower[jRowX]);
5150 if (endI-startI<100&&endJ-startJ<10) {
5151 for (CoinBigIndex k=startJ;k<endJ;k++)
5152 printf("(%d,%g) ",column[k],elementByRow[k]);
5153 } else {
5154 printf("something ");
5155 }
5156 printf("<= %g\n",rowUpper[jRowX]);
5157 }
5158 #endif
5159 }
5160 }
5161 }
5162 for (int j=0;j<n;j++) {
5163 int kColumn = whichColumn[j];
5164 columnValue[kColumn]=0.0;
5165 }
5166 }
5167 delete [] rowNumber;
5168 delete [] elementByRow2;
5169 delete [] column2;
5170 delete [] rowStart2;
5171 delete [] marked;
5172 }
5173 #endif
5174 bool noStrengthening = false;
5175 for (int iPass = 0; iPass < numberPasses; iPass++) {
5176 // Statistics
5177 int numberFixed = 0;
5178 int numberTwo = twoCuts.sizeRowCuts();
5179 int numberStrengthened = 0;
5180 info.pass = iPass;
5181 info.options = 0;
5182 int numberChangedThisPass = 0;
5183 #if 1
5184 // look at cliques every time
5185 if ((options_ & 32) != 0) {
5186 OsiSolverInterface *temp = cliqueIt(*newModel, 0.0001);
5187 if (temp) {
5188 #if CBC_USEFUL_PRINTING
5189 printf("bigpass %d pass %d after cliques %d rows, before %d\n",
5190 iBigPass, iPass, temp->getNumRows(), newModel->getNumRows());
5191 #endif
5192 if (temp->getNumRows() < newModel->getNumRows()) {
5193 numberChangedThisPass += newModel->getNumRows() - temp->getNumRows();
5194 delete newModel;
5195 newModel = temp;
5196 numberRows = newModel->getNumRows();
5197 } else {
5198 delete temp;
5199 }
5200 } else {
5201 #if CBC_USEFUL_PRINTING
5202 printf("bigpass %d pass %d no more cliques %d rows\n",
5203 iBigPass, iPass, newModel->getNumRows());
5204 #endif
5205 }
5206 }
5207 #endif
5208 /*
5209 needResolve solution is stale
5210 rebuilt constraint system deleted and recreated (implies initialSolve)
5211 */
5212 for (int iGenerator = firstGenerator; iGenerator < lastGenerator; iGenerator++) {
5213 bool needResolve = false;
5214 bool rebuilt = false;
5215 OsiCuts cs;
5216 CoinZeroN(whichCut, numberRows);
5217 CglProbing *probingCut = NULL;
5218 int numberFromCglDuplicate = 0;
5219 const int *duplicate = NULL;
5220 CglDuplicateRow *dupRow = NULL;
5221 CglClique *cliqueGen = NULL;
5222 if (iGenerator >= 0) {
5223 //char name[20];
5224 //sprintf(name,"prex%2.2d.mps",iGenerator);
5225 //newModel->writeMpsNative(name, NULL, NULL,0,1,0);
5226 // refresh as model may have changed
5227 generator_[iGenerator]->refreshSolver(newModel);
5228 // skip duplicate rows except once
5229 dupRow = dynamic_cast< CglDuplicateRow * >(generator_[iGenerator]);
5230 cliqueGen = dynamic_cast< CglClique * >(generator_[iGenerator]);
5231 if (cliqueGen && iPass)
5232 continue;
5233 if (dupRow && (iPass || iBigPass))
5234 continue;
5235 probingCut = dynamic_cast< CglProbing * >(generator_[iGenerator]);
5236 #if CBC_USEFUL_PRINTING > 0
5237 double time1 = CoinCpuTime();
5238 #endif
5239 if (!probingCut) {
5240 generator_[iGenerator]->generateCuts(*newModel, cs, info);
5241 } else {
5242 info.options = 64;
5243 probingCut->setMode(useSolution ? 4 : 4 | 64);
5244 int saveMaxElements = probingCut->getMaxElementsRoot();
5245 int saveMaxProbe = probingCut->getMaxProbeRoot();
5246 int saveMaxLook = probingCut->getMaxLookRoot();
5247 if ((!iBigPass||(options_&64)!=0)&&!iPass&&(options_&(16|64))!=0) {
5248 //if (/*!iBigPass &&*/ !iPass /*&&(options_&(16|64))!=0*/) {
5249 noStrengthening = true;
5250 numberPasses = 1;
5251 probingCut->setMaxProbeRoot(CoinMax(saveMaxProbe, 1000));
5252 probingCut->setMaxElementsRoot(CoinMax(saveMaxElements, 2000));
5253 probingCut->setMaxLookRoot(CoinMax(saveMaxLook,
5254 CoinMin(numberColumns, numberRows))
5255 / 2);
5256 options_ &= ~16;
5257 } else if (iPass || (options_ & 64) == 0) {
5258 // cut back
5259 probingCut->setMaxElementsRoot(probingCut->getMaxElements());
5260 probingCut->setMaxProbeRoot(probingCut->getMaxProbe());
5261 probingCut->setMaxLookRoot(probingCut->getMaxLook());
5262 }
5263 probingCut->generateCutsAndModify(*newModel, cs, &info);
5264 probingCut->setMaxElementsRoot(saveMaxElements);
5265 probingCut->setMaxProbeRoot(saveMaxProbe);
5266 probingCut->setMaxLookRoot(saveMaxLook);
5267 if (!iPass && (!cs.sizeColCuts() || iBigPass > 2))
5268 options_ &= ~64; // switch off heavy
5269 }
5270 #if CBC_USEFUL_PRINTING > 0
5271 printf("Generator %d took %g seconds\n",
5272 iGenerator, CoinCpuTime() - time1);
5273 printf("After probing1 %d row cuts and %d column cuts\n",
5274 cs.sizeRowCuts(), cs.sizeColCuts());
5275 #endif
5276 if (cs.sizeColCuts() && iPass < numberPasses - 100 && !iBigPass) {
5277 // delete all row cuts for now????
5278 int n = cs.sizeRowCuts();
5279 for (int i = n - 1; i >= 0; i--)
5280 cs.eraseRowCut(i);
5281 for (int i = 0; i < numberRows; i++)
5282 whichCut[i] = 0;
5283 }
5284 #if 1 //def CLIQUE_ANALYSIS
5285 if (probingCut) {
5286 //printf("ordinary probing\n");
5287 info.analyze(*newModel);
5288 }
5289 #endif
5290 // If CglDuplicate may give us useless rows
5291 if (dupRow) {
5292 numberFromCglDuplicate = dupRow->numberOriginalRows();
5293 duplicate = dupRow->duplicate();
5294 if (cs.sizeRowCuts()) {
5295 // add to twoCuts (may be more, but ....)
5296 int numberRowCuts = cs.sizeRowCuts();
5297 for (int k = 0; k < numberRowCuts; k++) {
5298 OsiRowCut *thisCut = cs.rowCutPtr(k);
5299 twoCuts.insert(*thisCut);
5300 }
5301 }
5302 }
5303 if (cliqueGen && cs.sizeRowCuts()) {
5304 int n = cs.sizeRowCuts();
5305 #if CBC_USEFUL_PRINTING
5306 printf("%d clique cuts\n", n);
5307 #endif
5308 OsiSolverInterface *copySolver = newModel->clone();
5309 numberRows = copySolver->getNumRows();
5310 copySolver->applyCuts(cs);
5311 //static int kk=0;
5312 //char name[20];
5313 //kk++;
5314 //sprintf(name,"matrix%d",kk);
5315 //printf("writing matrix %s\n",name);
5316 //copySolver->writeMps(name);
5317 CglDuplicateRow dupCuts(copySolver);
5318 dupCuts.setMode(8);
5319 OsiCuts cs2;
5320 dupCuts.generateCuts(*copySolver, cs2, info);
5321 #if CBC_USEFUL_PRINTING > 0
5322 printf("After probing dupCuts %d row cuts and %d column cuts\n",
5323 cs2.sizeRowCuts(), cs2.sizeColCuts());
5324 #endif
5325 // -1 not used, -2 delete, -3 not clique
5326 const int *duplicate = dupCuts.duplicate();
5327 // -1 not used, >=0 earliest row affected
5328 const int *used = duplicate + numberRows + n;
5329 int numberDrop = 0;
5330 int *drop = new int[numberRows];
5331 for (int iRow = 0; iRow < numberRows; iRow++) {
5332 if (duplicate[iRow] == -2)
5333 drop[numberDrop++] = iRow;
5334 }
5335 int nOther = 0;
5336 for (int iRow = numberRows + n - 1; iRow >= numberRows; iRow--) {
5337 #if 1
5338 int earliest = used[iRow];
5339 while (earliest >= numberRows) {
5340 if (duplicate[earliest] == -2)
5341 earliest = used[earliest];
5342 else
5343 break;
5344 }
5345 #else
5346 int earliest = 0;
5347 #endif
5348 if (duplicate[iRow] == -2 || earliest == -1 || earliest >= numberRows) {
5349 cs.eraseRowCut(iRow - numberRows);
5350 nOther++;
5351 }
5352 }
5353 n -= nOther;
5354 int newNumberRows = numberRows - numberDrop + n;
5355 bool special = (cliqueGen->getMinViolation() == -3.0);
5356 #if CBC_USEFUL_PRINTING
5357 printf("could drop %d rows - current nrows %d other %d - new nrows %d\n",
5358 numberDrop, numberRows, nOther, newNumberRows);
5359 #endif
5360 if (n <= numberDrop || special) {
5361 #if CBC_USEFUL_PRINTING
5362 printf("Dropping rows current nrows %d - new nrows %d\n",
5363 numberRows, newNumberRows);
5364 #endif
5365 if (newNumberRows > numberRows) {
5366 // need new array
5367 delete[] whichCut;
5368 whichCut = new OsiRowCut *[newNumberRows + 1];
5369 CoinZeroN(whichCut, newNumberRows);
5370 info.strengthenRow = whichCut;
5371 }
5372 newModel->deleteRows(numberDrop, drop);
5373 // may be able to delete some added cliques
5374 newModel->applyCuts(cs);
5375 numberRows = newModel->getNumRows();
5376 newModel->resolve();
5377 #if 0
5378 int numberRows2=copySolver->getNumRows();
5379 const double * rowLower = copySolver->getRowLower();
5380 const double * rowUpper = copySolver->getRowUpper();
5381 const CoinPackedMatrix * matrixByRow = copySolver->getMatrixByRow();
5382 // Row copy
5383 const double * elementByRow = matrixByRow->getElements();
5384 const int * column = matrixByRow->getIndices();
5385 const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
5386 const int * rowLength = matrixByRow->getVectorLengths();
5387 const double * solution = newModel->getColSolution();
5388 for (int iRow=0;iRow<numberRows2;iRow++) {
5389 double sum=0.0;
5390 for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
5391 int iColumn = column[j];
5392 double value = elementByRow[j];
5393 sum += value*solution[iColumn];
5394 }
5395 assert (sum>rowLower[iRow]-1.0e-4&&sum<rowUpper[iRow]+1.0e-4);
5396 }
5397 #endif
5398 }
5399 delete copySolver;
5400 delete[] drop;
5401 continue;
5402 //for (int i=0;i<n;i++) {
5403 //OsiRowCut & thisCut = cs.rowCut(i);
5404 //thisCut.print();
5405 //}
5406 }
5407 } else {
5408 #ifdef HEAVY_PROBING
5409 // special probing
5410 CglProbing generator1;
5411 probingCut = &generator1;
5412 generator1.setUsingObjective(false);
5413 generator1.setMaxPass(1);
5414 generator1.setMaxPassRoot(1);
5415 generator1.setMaxProbeRoot(100);
5416 generator1.setMaxLook(100);
5417 generator1.setRowCuts(3);
5418 if (heavyProbing) {
5419 generator1.setMaxElements(400);
5420 //generator1.setMaxLook(10000);
5421 generator1.setMaxProbeRoot(model->getNumCols());
5422 }
5423 // out for now - think about cliques
5424 if (!generator1.snapshot(*newModel, NULL, false)) {
5425 generator1.createCliques(*newModel, 2, 1000);
5426 // To get special stuff
5427 info.pass = 4;
5428 CoinZeroN(whichCut, numberRows);
5429 generator1.setMode(16 + 4);
5430 generator1.generateCutsAndModify(*newModel, cs, &info);
5431 #if CBC_USEFUL_PRINTING > 0
5432 printf("After probing clique stuff %d row cuts and %d column cuts\n",
5433 cs.sizeRowCuts(), cs.sizeColCuts());
5434 #endif
5435 // can we extend cliques?
5436 // make fake model
5437 OsiSolverInterface *fakeModel = generator1.cliqueModel(newModel, 1);
5438 // if above added rows then take out duplicates
5439 OsiSolverInterface *fakeModel2 = cliqueIt(*fakeModel, 0.0);
5440 delete fakeModel;
5441 //delete fakeModel2;
5442 delete newModel;
5443 newModel = fakeModel2;
5444 #ifdef CLIQUE_ANALYSIS
5445 printf("special probing\n");
5446 info.analyze(*newModel);
5447 #endif
5448 } else {
5449 feasible = false;
5450 }
5451 #endif
5452 }
5453 // check changes
5454 // first are any rows strengthened by cuts
5455 int iRow;
5456 #ifdef MAX_ADD_ELEMENTS_PREPROCESS
5457 const CoinPackedMatrix *tempRowCopy = newModel->getMatrixByRow();
5458 const int *tempRowLength = tempRowCopy->getVectorLengths();
5459 #endif
5460 for (iRow = 0; iRow < numberRows; iRow++) {
5461 if (whichCut[iRow]) {
5462 #ifdef MAX_ADD_ELEMENTS_PREPROCESS
5463 OsiRowCut *thisCut = whichCut[iRow];
5464 CoinPackedVector row = thisCut->row();
5465 if (row.getNumElements() <= tempRowLength[iRow]
5466 + MAX_ADD_ELEMENTS_PREPROCESS) {
5467 numberStrengthened++;
5468 } else {
5469 delete thisCut;
5470 whichCut[iRow] = NULL;
5471 }
5472 #else
5473 numberStrengthened++;
5474 #endif
5475 }
5476 }
5477 // Also can we get rid of duplicate rows
5478 int numberDrop = 0;
5479 for (iRow = 0; iRow < numberFromCglDuplicate; iRow++) {
5480 if (duplicate[iRow] == -2 || duplicate[iRow] >= 0) {
5481 numberDrop++;
5482 newModel->setRowBounds(iRow, -COIN_DBL_MAX, COIN_DBL_MAX);
5483 }
5484 }
5485 const double *columnLower = newModel->getColLower();
5486 const double *columnUpper = newModel->getColUpper();
5487 if ((numberStrengthened || numberDrop) && feasible) {
5488 /*
5489
5490 Deleting all rows and rebuilding invalidates everything, initialSolve will
5491 be required.
5492 */
5493 if (useSolution)
5494 needResolve = true;
5495 rebuilt = true;
5496 // Easier to recreate entire matrix
5497 const CoinPackedMatrix *rowCopy = newModel->getMatrixByRow();
5498 const int *column = rowCopy->getIndices();
5499 const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
5500 const int *rowLength = rowCopy->getVectorLengths();
5501 const double *rowElements = rowCopy->getElements();
5502 const double *rowLower = newModel->getRowLower();
5503 const double *rowUpper = newModel->getRowUpper();
5504 CoinBuild build;
5505 // For basis
5506 char *keepRow = new char[numberRows];
5507 for (iRow = 0; iRow < numberRows; iRow++) {
5508 keepRow[iRow] = 0;
5509 OsiRowCut *thisCut = whichCut[iRow];
5510 //whichCut[iRow]=NULL;
5511 if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) {
5512 #if 0
5513 if (thisCut) {
5514 double * allColumns = new double[numberColumns];
5515 int which[]={0,8,11,19,21,29,30,38,42,61,77,90,104,105,7,37};
5516 memset(allColumns,0,numberColumns*sizeof(double));
5517 for (int k=0;k<sizeof(which)/sizeof(int);k++) {
5518 allColumns[which[k]]=1.0;
5519 }
5520 double lb = thisCut->lb();
5521 double ub = thisCut->ub();
5522 CoinPackedVector row = thisCut->row();
5523 printf("Cut on row %d - %g <= ",iRow,lb);
5524 bool feas1=true;
5525 double sum1=0.0;
5526 for (int k = 0; k < row.getNumElements(); ++k) {
5527 int j = row.getIndices()[k];
5528 double value = row.getElements()[k];
5529 printf("(%d,%g) ",j,value);
5530 sum1 += value*allColumns[j];
5531 }
5532 if (sum1<lb-1.0e-3||sum1>ub+1.0e-3) {
5533 printf(" ******** ");
5534 feas1 = false;
5535 }
5536 printf("<= %g\n",ub);
5537 printf("Old row %g <= ",rowLower[iRow]);
5538 bool feas2=true;
5539 double sum2=0.0;
5540 int start=rowStart[iRow];
5541 int end = start + rowLength[iRow];
5542 for (int k = start; k < end; ++k) {
5543 CoinBigIndex j = column[k];
5544 double value = rowElements[k];
5545 printf("(%d,%g) ",j,value);
5546 sum2 += value*allColumns[j];
5547 }
5548 if (sum2<rowLower[iRow]-1.0e-3||sum2>rowUpper[iRow]+1.0e-3) {
5549 printf(" ******** ");
5550 feas2 = false;
5551 }
5552 printf("<= %g\n",rowUpper[iRow]);
5553 if (feas1 && !feas2)
5554 abort();
5555 delete [] allColumns;
5556 }
5557 #endif
5558 if (!thisCut) {
5559 // put in old row
5560 CoinBigIndex start = rowStart[iRow];
5561 int kInt = -1;
5562 double newValue = 0.0;
5563 if (!iPass && !iBigPass) {
5564 // worthwhile seeing if odd gcd
5565 CoinBigIndex end = start + rowLength[iRow];
5566 double rhsAdjustment = 0.0;
5567 int nPosInt = 0;
5568 int nNegInt = 0;
5569 // Find largest integer coefficient
5570 CoinBigIndex k;
5571 for (k = start; k < end; ++k) {
5572 int j = column[k];
5573 if (columnUpper[j] > columnLower[j]) {
5574 if (newModel->isInteger(j)) {
5575 if (rowElements[k] > 0.0)
5576 nPosInt++;
5577 else
5578 nNegInt++;
5579 } else {
5580 break; // no good
5581 }
5582 } else {
5583 rhsAdjustment += columnLower[j] * rowElements[k];
5584 }
5585 }
5586 if (k == end) {
5587 // see if singleton coefficient can be strengthened
5588 if ((nPosInt == 1 && nNegInt > 1) || (nNegInt == 1 && nPosInt > 1)) {
5589 double lo;
5590 double up;
5591 if (rowLower[iRow] > -1.0e20)
5592 lo = rowLower[iRow] - rhsAdjustment;
5593 else
5594 lo = -COIN_DBL_MAX;
5595 if (rowUpper[iRow] < 1.0e20)
5596 up = rowUpper[iRow] - rhsAdjustment;
5597 else
5598 up = COIN_DBL_MAX;
5599 double multiplier = 1.0;
5600 if (nNegInt == 1) {
5601 // swap signs
5602 multiplier = lo;
5603 lo = -up;
5604 up = -multiplier;
5605 multiplier = -1.0;
5606 }
5607 bool possible = true;
5608 double singletonValue = 0;
5609 double scale = 4.0 * 5.0 * 6.0;
5610 int kGcd = -1;
5611 double smallestSum = 0.0;
5612 double largestSum = 0.0;
5613 for (k = start; k < end; ++k) {
5614 int j = column[k];
5615 double value = multiplier * rowElements[k];
5616 if (columnUpper[j] > columnLower[j]) {
5617 if (value > 0.0) {
5618 // singleton
5619 kInt = j;
5620 if (columnUpper[j] - columnLower[j] != 1.0) {
5621 possible = false;
5622 break;
5623 } else {
5624 singletonValue = value;
5625 }
5626 } else {
5627 if (columnLower[j] > -1.0e10)
5628 smallestSum += value * columnLower[j];
5629 else
5630 smallestSum = -COIN_DBL_MAX;
5631 if (columnUpper[j] < -1.0e10)
5632 largestSum += value * columnUpper[j];
5633 else
5634 largestSum = COIN_DBL_MAX;
5635 value *= -scale;
5636 if (fabs(value - floor(value + 0.5)) > 1.0e-12) {
5637 possible = false;
5638 break;
5639 } else {
5640 int kVal = static_cast< int >(floor(value + 0.5));
5641 if (kGcd > 0)
5642 kGcd = gcd(kGcd, kVal);
5643 else
5644 kGcd = kVal;
5645 }
5646 }
5647 }
5648 }
5649 if (possible) {
5650 double multiple = (static_cast< double >(kGcd)) / scale;
5651 int interesting = 0;
5652 double saveLo = lo;
5653 double saveUp = up;
5654 #if CBC_USEFUL_PRINTING > 1
5655 double nearestLo0 = lo;
5656 double nearestLo1 = lo;
5657 #endif
5658 double nearestUp0 = up;
5659 double nearestUp1 = up;
5660 // adjust rhs for singleton
5661 if (lo != -COIN_DBL_MAX) {
5662 // singleton at lb
5663 lo -= columnLower[kInt] * singletonValue;
5664 double exact = lo / multiple;
5665 if (fabs(exact - floor(exact + 0.5)) > 1.0e-4) {
5666 interesting += 1;
5667 #if CBC_USEFUL_PRINTING > 1
5668 nearestLo0 = ceil(exact) * multiple;
5669 #endif
5670 }
5671 // singleton at ub
5672 lo -= singletonValue;
5673 exact = lo / multiple;
5674 if (fabs(exact - floor(exact + 0.5)) > 1.0e-4) {
5675 interesting += 2;
5676 #if CBC_USEFUL_PRINTING > 1
5677 nearestLo1 = ceil(exact) * multiple;
5678 #endif
5679 }
5680 }
5681 if (up != COIN_DBL_MAX) {
5682 // singleton at lb
5683 up -= columnLower[kInt] * singletonValue;
5684 double exact = up / multiple;
5685 if (fabs(exact - floor(exact + 0.5)) > 1.0e-4) {
5686 interesting += 4;
5687 nearestUp0 = floor(exact) * multiple;
5688 }
5689 // singleton at ub
5690 up -= singletonValue;
5691 exact = up / multiple;
5692 if (fabs(exact - floor(exact + 0.5)) > 1.0e-4) {
5693 interesting += 8;
5694 nearestUp1 = floor(exact) * multiple;
5695 }
5696 }
5697 if (interesting) {
5698 #if CBC_USEFUL_PRINTING > 1
5699 printf("Row %d interesting %d lo,up %g,%g singleton %d value %g bounds %g,%g - gcd %g\n", iRow, interesting, saveLo, saveUp, kInt, singletonValue,
5700 columnLower[kInt], columnUpper[kInt], multiple);
5701 printf("Orig lo,up %g,%g %d\n", rowLower[iRow], rowUpper[iRow], end - start);
5702 for (k = start; k < end; ++k) {
5703 CoinBigIndex j = column[k];
5704 double value = multiplier * rowElements[k];
5705 printf(" (%d, %g - bds %g, %g)", j, value,
5706 columnLower[j], columnUpper[j]);
5707 }
5708 printf("\n");
5709 #endif
5710 if (columnLower[kInt]) {
5711 #if CBC_USEFUL_PRINTING > 1
5712 printf("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\n"); //think
5713 #endif
5714 interesting = 0;
5715 }
5716 newValue = singletonValue;
5717 #if CBC_USEFUL_PRINTING > 1
5718 double newLoRhs = rowLower[iRow];
5719 double newUpRhs = rowUpper[iRow];
5720 if ((interesting & 3) != 0) {
5721 newLoRhs = nearestLo0;
5722 newValue = nearestLo0 - nearestLo1;
5723 }
5724 #endif
5725 if (saveLo == saveUp && ((interesting & 5) == 5 || (interesting & 10) == 10)) {
5726 #if CBC_USEFUL_PRINTING > 1
5727 printf("INFEAS? ");
5728 #endif
5729 interesting = 0; //ninfeas++;
5730 }
5731 if ((interesting & 12)) {
5732 #if CBC_USEFUL_PRINTING > 1
5733 double value2 = newValue;
5734 newUpRhs = nearestUp0;
5735 #endif
5736 newValue = nearestUp0 - nearestUp1;
5737 #if CBC_USEFUL_PRINTING > 1
5738 if (newValue != value2) {
5739 printf("??? old newvalue %g ", newValue);
5740 }
5741 #endif
5742 }
5743 #if CBC_USEFUL_PRINTING > 1
5744 printf("guess is new lo %g, new up %g, new value %g\n",
5745 newLoRhs, newUpRhs, newValue);
5746 #endif
5747 }
5748 // Just do mzzv11 case
5749 double exact = singletonValue / multiple;
5750 if (fabs(exact - floor(exact + 0.5)) < 1.0e-5)
5751 interesting &= ~2;
5752 if (!smallestSum && interesting == 2 && !saveLo && saveUp > 1.0e20) {
5753 newValue = multiple * floor(exact);
5754 newValue *= multiplier;
5755 #if CBC_USEFUL_PRINTING > 1
5756 printf("New coefficient for %d will be %g\n", kInt, newValue);
5757 #endif
5758 } else {
5759 // don't do
5760 kInt = -1;
5761 }
5762 } else {
5763 kInt = -1;
5764 }
5765 }
5766 }
5767 // endgcd
5768 }
5769 int length = rowLength[iRow];
5770 if (kInt < 0) {
5771 build.addRow(length, column + start, rowElements + start,
5772 rowLower[iRow], rowUpper[iRow]);
5773 } else {
5774 double *els = CoinCopyOfArray(rowElements + start, length);
5775 if (fabs(newValue) > 1.0e-13) {
5776 for (int k = 0; k < length; ++k) {
5777 int j = column[k + start];
5778 if (j == kInt) {
5779 els[k] = newValue;
5780 break;
5781 }
5782 }
5783 build.addRow(length, column + start, els,
5784 rowLower[iRow], rowUpper[iRow]);
5785 } else {
5786 // strengthened to zero!
5787 #if CBC_USEFUL_PRINTING > 1
5788 printf("CglPreProcess - element strenthened to zero!\n");
5789 #endif
5790 int *cols = CoinCopyOfArray(column + start, length);
5791 int n = 0;
5792 for (int k = 0; k < length; ++k) {
5793 int j = cols[k];
5794 if (j != kInt) {
5795 els[n] = els[k];
5796 cols[n++] = j;
5797 }
5798 }
5799 build.addRow(n, cols, els,
5800 rowLower[iRow], rowUpper[iRow]);
5801 delete[] cols;
5802 }
5803 delete[] els;
5804 }
5805 keepRow[iRow] = 1;
5806 } else {
5807 // strengthens this row (should we check?)
5808 // may be worth going round again
5809 numberChangedThisPass++;
5810 int n = thisCut->row().getNumElements();
5811 const int *columnCut = thisCut->row().getIndices();
5812 const double *elementCut = thisCut->row().getElements();
5813 double lower = thisCut->lb();
5814 double upper = thisCut->ub();
5815 if (probingCut) {
5816 int i;
5817 int nFree = 0;
5818 for (i = 0; i < n; i++) {
5819 int iColumn = columnCut[i];
5820 if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-12)
5821 nFree++;
5822 }
5823 bool good = (n == nFree);
5824 nFree = 0;
5825 int n1 = rowLength[iRow];
5826 CoinBigIndex start = rowStart[iRow];
5827 for (i = 0; i < n1; i++) {
5828 int iColumn = column[start + i];
5829 if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-12)
5830 nFree++;
5831 }
5832 if (n1 != nFree)
5833 good = false;
5834 if (noStrengthening && n > n1) {
5835 good = false;
5836 //printf("Skipping row %d strengthened row has %d (%d)\n",
5837 // iRow,n,n1);
5838 }
5839 if (good) {
5840 #if PRINT_DEBUG > 1
5841 printf("Original row %.8d %g <= ", iRow, rowLower[iRow]);
5842 for (i = 0; i < n1; i++)
5843 printf("%g * x%d ", rowElements[start + i], column[start + i]);
5844 printf("<= %g\n", rowUpper[iRow]);
5845 printf("New %g <= ", lower);
5846 for (i = 0; i < n; i++)
5847 printf("%g * x%d ", elementCut[i], columnCut[i]);
5848 printf("<= %g\n", upper);
5849 #endif
5850 } else {
5851 // can't use
5852 n = -1;
5853 numberStrengthened--;
5854 // put in old row
5855 CoinBigIndex start = rowStart[iRow];
5856 build.addRow(rowLength[iRow], column + start, rowElements + start,
5857 rowLower[iRow], rowUpper[iRow]);
5858 keepRow[iRow] = 1;
5859 }
5860 }
5861 if (n > 0) {
5862 build.addRow(n, columnCut, elementCut, lower, upper);
5863 keepRow[iRow] = 1;
5864 } else if (!n) {
5865 // Either infeasible or redundant
5866 if (lower <= 0.0 && upper >= 0.0) {
5867 // redundant - row will go
5868 } else {
5869 // infeasible!
5870 feasible = false;
5871 break;
5872 }
5873 }
5874 }
5875 }
5876 }
5877 // Get rid of all whichCut not in cs
5878 int nCuts = cs.sizeRowCuts();
5879 if (nCuts) {
5880 std::sort(whichCut, whichCut + numberRows);
5881 OsiRowCut **tempCuts = new OsiRowCut *[nCuts + 1];
5882 for (int i = 0; i < nCuts; i++)
5883 tempCuts[i] = cs.rowCutPtr(i);
5884 std::sort(tempCuts, tempCuts + nCuts);
5885 tempCuts[nCuts] = CoinMax(whichCut[numberRows - 1], tempCuts[nCuts - 1]) + 1;
5886 int iCut = 0;
5887 void *cut = tempCuts[0];
5888 for (int i = 0; i < numberRows; i++) {
5889 OsiRowCut *thisCut = whichCut[i];
5890 if (!thisCut)
5891 continue;
5892 while (cut < thisCut)
5893 cut = tempCuts[++iCut];
5894 if (cut > thisCut)
5895 delete thisCut;
5896 whichCut[i] = NULL;
5897 }
5898 delete[] tempCuts;
5899 } else {
5900 for (int i = 0; i < numberRows; i++) {
5901 delete whichCut[i];
5902 whichCut[i] = NULL;
5903 }
5904 }
5905 if (rowType_) {
5906 assert(numberRowType_ == numberRows);
5907 int numberRowType_ = 0;
5908 for (iRow = 0; iRow < numberRows; iRow++) {
5909 if (keepRow[iRow]) {
5910 rowType_[numberRowType_++] = rowType_[iRow];
5911 }
5912 }
5913 }
5914 // recreate
5915 int *del = new int[numberRows];
5916 // save and modify basis
5917 CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(newModel->getWarmStart());
5918 if (basis) {
5919 int n = 0;
5920 for (iRow = 0; iRow < numberRows; iRow++) {
5921 if (!keepRow[iRow]) {
5922 del[n++] = iRow;
5923 }
5924 }
5925 basis->deleteRows(n, del);
5926 }
5927 for (iRow = 0; iRow < numberRows; iRow++)
5928 del[iRow] = iRow;
5929 newModel->deleteRows(numberRows, del);
5930 newModel->addRows(build);
5931 numberRows = newModel->getNumRows();
5932 #if CBC_USEFUL_PRINTING > 0
5933 printf("After build %d rows and %d columns (%d rows strengthened)\n",
5934 numberRows, newModel->getNumCols(), numberStrengthened);
5935 #endif
5936 if (basis) {
5937 assert(numberRows == basis->getNumArtificial());
5938 newModel->setWarmStart(basis);
5939 delete basis;
5940 }
5941 if (dupRow && cs.sizeRowCuts())
5942 newModel->applyCuts(cs);
5943 delete[] keepRow;
5944 delete[] del;
5945 /*
5946 VIRTUOUS
5947
5948 A solver is not required to hold these pointers constant across complete
5949 row deletion and rebuild.
5950 */
5951 columnLower = newModel->getColLower();
5952 columnUpper = newModel->getColUpper();
5953 }
5954 if (!feasible)
5955 break;
5956 // now see if we have any x=y x+y=1
5957 if (constraints) {
5958 int numberRowCuts = cs.sizeRowCuts();
5959 for (int k = 0; k < numberRowCuts; k++) {
5960 OsiRowCut *thisCut = cs.rowCutPtr(k);
5961 int n = thisCut->row().getNumElements();
5962 double lower = thisCut->lb();
5963 double upper = thisCut->ub();
5964 if (n == 2 && lower == upper) {
5965 twoCuts.insert(*thisCut);
5966 }
5967 }
5968 }
5969 if (probingCut) {
5970 // we could look harder for infeasibilities
5971 assert(info.numberVariables() == numberColumns);
5972 int number01 = info.numberIntegers();
5973 const CliqueEntry *entry = info.fixEntries();
5974 const int *toZero = info.toZero();
5975 const int *toOne = info.toOne();
5976 const int *which = info.integerVariable();
5977 int numberBounds = 0;
5978 char *markLB = new char[number01];
5979 memset(markLB, 0, number01);
5980 char *markUB = new char[number01];
5981 memset(markUB, 0, number01);
5982 for (int k = 0; k < number01; k++) {
5983 int start = toZero[k];
5984 int end = toOne[k];
5985 // to zero
5986 int j;
5987 for (j = start; j < end; j++) {
5988 int goingToOne = oneFixesInCliqueEntry(entry[j]);
5989 int v = sequenceInCliqueEntry(entry[j]);
5990 if (v >= number01)
5991 continue;
5992 if (goingToOne) {
5993 // If v -> 1 means k -> 0 we have k+v==1
5994 int startV = toOne[v];
5995 int endV = toZero[v + 1];
5996 for (int jv = startV; jv < endV; jv++) {
5997 if (k == static_cast< int >(sequenceInCliqueEntry(entry[jv]))) {
5998 int goingToOneV = oneFixesInCliqueEntry(entry[jv]);
5999 double lo, up;
6000 if (!goingToOneV) {
6001 lo = 1.0;
6002 up = 1.0;
6003 OsiRowCut thisCut;
6004 thisCut.setLb(lo);
6005 thisCut.setUb(up);
6006 double values[] = { 1.0, 1.0 };
6007 int columns[2];
6008 columns[0] = which[k];
6009 columns[1] = which[v];
6010 thisCut.setRow(2, columns, values, false);
6011 twoCuts.insertIfNotDuplicate(thisCut);
6012 } else {
6013 // means infeasible for k to go to 0
6014 markLB[k] = 1;
6015 numberBounds++;
6016 }
6017 break;
6018 }
6019 }
6020 } else {
6021 // If v -> 0 means k -> 0 we have k==v
6022 int startV = toZero[v];
6023 int endV = toOne[v];
6024 for (int jv = startV; jv < endV; jv++) {
6025 if (k == static_cast< int >(sequenceInCliqueEntry(entry[jv]))) {
6026 int goingToOneV = oneFixesInCliqueEntry(entry[jv]);
6027 double lo, up;
6028 if (!goingToOneV) {
6029 lo = 0.0;
6030 up = 0.0;
6031 OsiRowCut thisCut;
6032 thisCut.setLb(lo);
6033 thisCut.setUb(up);
6034 double values[] = { 1.0, -1.0 };
6035 int columns[2];
6036 columns[0] = which[k];
6037 columns[1] = which[v];
6038 thisCut.setRow(2, columns, values, false);
6039 twoCuts.insertIfNotDuplicate(thisCut);
6040 } else {
6041 // means infeasible for k to go to 0
6042 markLB[k] = 1;
6043 numberBounds++;
6044 }
6045 break;
6046 }
6047 }
6048 }
6049 }
6050 start = toOne[k];
6051 end = toZero[k + 1];
6052 // to one
6053 for (j = start; j < end; j++) {
6054 int goingToOne = oneFixesInCliqueEntry(entry[j]);
6055 int v = sequenceInCliqueEntry(entry[j]);
6056 if (v >= number01)
6057 continue;
6058 if (goingToOne) {
6059 // If v -> 1 means k -> 1 we have k==v
6060 int startV = toOne[v];
6061 int endV = toZero[v + 1];
6062 for (int jv = startV; jv < endV; jv++) {
6063 if (k == static_cast< int >(sequenceInCliqueEntry(entry[jv]))) {
6064 int goingToOneV = oneFixesInCliqueEntry(entry[jv]);
6065 double lo, up;
6066 if (goingToOneV) {
6067 lo = 0.0;
6068 up = 0.0;
6069 OsiRowCut thisCut;
6070 thisCut.setLb(lo);
6071 thisCut.setUb(up);
6072 double values[] = { 1.0, -1.0 };
6073 int columns[2];
6074 columns[0] = which[k];
6075 columns[1] = which[v];
6076 thisCut.setRow(2, columns, values, false);
6077 twoCuts.insertIfNotDuplicate(thisCut);
6078 } else {
6079 // means infeasible for k to go to 1
6080 markUB[k] = 1;
6081 numberBounds++;
6082 }
6083 break;
6084 }
6085 }
6086 } else {
6087 // If v -> 0 means k -> 1 we have k+v==1
6088 int startV = toZero[v];
6089 int endV = toOne[v];
6090 for (int jv = startV; jv < endV; jv++) {
6091 if (k == static_cast< int >(sequenceInCliqueEntry(entry[jv]))) {
6092 int goingToOneV = oneFixesInCliqueEntry(entry[jv]);
6093 double lo, up;
6094 if (goingToOneV) {
6095 lo = 1.0;
6096 up = 1.0;
6097 OsiRowCut thisCut;
6098 thisCut.setLb(lo);
6099 thisCut.setUb(up);
6100 double values[] = { 1.0, 1.0 };
6101 int columns[2];
6102 columns[0] = which[k];
6103 columns[1] = which[v];
6104 thisCut.setRow(2, columns, values, false);
6105 twoCuts.insertIfNotDuplicate(thisCut);
6106 } else {
6107 // means infeasible for k to go to 1
6108 markUB[k] = 1;
6109 numberBounds++;
6110 }
6111 break;
6112 }
6113 }
6114 }
6115 }
6116 }
6117 if (numberBounds) {
6118 CoinPackedVector lbs;
6119 CoinPackedVector ubs;
6120 for (int k = 0; k < number01; k++) {
6121 if (markLB[k] && markUB[k]) {
6122 // infeasible
6123 feasible = false;
6124 break;
6125 } else if (markLB[k]) {
6126 lbs.insert(which[k], 1.0);
6127 } else if (markUB[k]) {
6128 ubs.insert(which[k], 0.0);
6129 }
6130 }
6131 OsiColCut cc;
6132 cc.setUbs(ubs);
6133 cc.setLbs(lbs);
6134 cc.setEffectiveness(1.0e-5);
6135 cs.insert(cc);
6136 }
6137 delete[] markLB;
6138 delete[] markUB;
6139 }
6140 // see if we have any column cuts
6141 int numberColumnCuts = cs.sizeColCuts();
6142 int numberBounds = 0;
6143 for (int k = 0; k < numberColumnCuts; k++) {
6144 OsiColCut *thisCut = cs.colCutPtr(k);
6145 /*
6146 Nontrivial bound changes will invalidate current solution.
6147 */
6148 if (thisCut->effectiveness() > 1.0 && useSolution) {
6149 needResolve = true;
6150 }
6151 const CoinPackedVector &lbs = thisCut->lbs();
6152 const CoinPackedVector &ubs = thisCut->ubs();
6153 int j;
6154 int n;
6155 const int *which;
6156 const double *values;
6157 n = lbs.getNumElements();
6158 which = lbs.getIndices();
6159 values = lbs.getElements();
6160 for (j = 0; j < n; j++) {
6161 int iColumn = which[j];
6162 if (values[j] > columnLower[iColumn] && values[j] > -1.0e20) {
6163 //printf("%d lower from %g to %g\n",iColumn,columnLower[iColumn],values[j]);
6164 newModel->setColLower(iColumn, values[j]);
6165 if (false) {
6166 OsiSolverInterface *xx = newModel->clone();
6167 xx->initialSolve();
6168 assert(xx->isProvenOptimal());
6169 delete xx;
6170 }
6171 numberChangedThisPass++;
6172 if (columnLower[iColumn] == columnUpper[iColumn]) {
6173 numberFixed++;
6174 } else {
6175 numberBounds++;
6176 if (columnLower[iColumn] > columnUpper[iColumn])
6177 feasible = false;
6178 }
6179 }
6180 }
6181 n = ubs.getNumElements();
6182 which = ubs.getIndices();
6183 values = ubs.getElements();
6184 for (j = 0; j < n; j++) {
6185 int iColumn = which[j];
6186 if (values[j] < columnUpper[iColumn] && values[j] < 1.0e20) {
6187 //printf("%d upper from %g to %g\n",iColumn,columnUpper[iColumn],values[j]);
6188 newModel->setColUpper(iColumn, values[j]);
6189 if (false) {
6190 OsiSolverInterface *xx = newModel->clone();
6191 xx->initialSolve();
6192 assert(xx->isProvenOptimal());
6193 delete xx;
6194 }
6195 numberChangedThisPass++;
6196 if (columnLower[iColumn] == columnUpper[iColumn]) {
6197 numberFixed++;
6198 } else {
6199 numberBounds++;
6200 if (columnLower[iColumn] > columnUpper[iColumn])
6201 feasible = false;
6202 }
6203 }
6204 }
6205 }
6206 numberTwo = twoCuts.sizeRowCuts() - numberTwo;
6207 numberChanges += numberTwo + numberStrengthened / 10;
6208 if (numberFixed || numberTwo || numberStrengthened || numberBounds)
6209 handler_->message(CGL_PROCESS_STATS, messages_)
6210 << numberFixed << numberBounds << numberStrengthened << numberTwo
6211 << CoinMessageEol;
6212 if (!feasible)
6213 break;
6214 /*
6215 If solution needs to be refreshed, do resolve or initialSolve as appropriate.
6216 */
6217 if (needResolve) {
6218 if (rebuilt) {
6219 // basis shot to bits?
6220 //CoinWarmStartBasis *slack =
6221 //dynamic_cast<CoinWarmStartBasis *>(newModel->getEmptyWarmStart()) ;
6222 //newModel->setWarmStart(slack);
6223 //delete slack ;
6224 bool saveHint;
6225 OsiHintStrength saveStrength;
6226 newModel->getHintParam(OsiDoPresolveInInitial, saveHint, saveStrength);
6227 // Do presolves
6228 if ((numberFixed + numberTwo) * 4 > numberColumns)
6229 newModel->setHintParam(OsiDoPresolveInInitial, true, OsiHintTry);
6230 newModel->setHintParam(OsiDoDualInInitial, true, OsiHintTry);
6231 newModel->initialSolve();
6232 newModel->setHintParam(OsiDoPresolveInInitial, saveHint, saveStrength);
6233 } else {
6234 newModel->resolve();
6235 }
6236 numberIterationsPre_ += newModel->getIterationCount();
6237 feasible = newModel->isProvenOptimal();
6238 if (!feasible) {
6239 // Better double check
6240 CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(newModel->getEmptyWarmStart());
6241 newModel->setWarmStart(slack);
6242 delete slack;
6243 newModel->resolve();
6244 numberIterationsPre_ += newModel->getIterationCount();
6245 feasible = newModel->isProvenOptimal();
6246 //if (!feasible)
6247 //newModel->writeMpsNative("infeas.mps",NULL,NULL,2,1);
6248 }
6249 }
6250 if (!feasible) {
6251 writeDebugMps(newModel, "infeasible", NULL);
6252 break;
6253 }
6254 }
6255 if (!feasible)
6256 break;
6257 numberChanges += numberChangedThisPass;
6258 if (iPass < numberPasses - 1) {
6259 int multiplier = (numberPasses > 10) ? numberRows + 1000 : 1;
6260 if ((!numberFixed && numberChangedThisPass * multiplier < numberRows + numberColumns) || iPass == numberPasses - 2) {
6261 // do special probing at end - but not if very last pass
6262 if (iBigPass < numberSolvers_ - 1 && numberPasses > 4) {
6263 firstGenerator = -1;
6264 lastGenerator = 0;
6265 }
6266 iPass = numberPasses - 2;
6267 }
6268 }
6269 }
6270 delete[] whichCut;
6271 int numberRowCuts = twoCuts.sizeRowCuts();
6272 if (numberRowCuts) {
6273 // add in x=y etc
6274 CoinBuild build;
6275 for (int k = 0; k < numberRowCuts; k++) {
6276 OsiRowCut *thisCut = twoCuts.rowCutPtr(k);
6277 int n = thisCut->row().getNumElements();
6278 const int *columnCut = thisCut->row().getIndices();
6279 const double *elementCut = thisCut->row().getElements();
6280 double lower = thisCut->lb();
6281 double upper = thisCut->ub();
6282 build.addRow(n, columnCut, elementCut, lower, upper);
6283 }
6284 newModel->addRows(build);
6285 if (rowType_) {
6286 // adjust
6287 int numberRows = newModel->getNumRows();
6288 char *temp = CoinCopyOfArrayPartial(rowType_, numberRows, numberRowType_);
6289 delete[] rowType_;
6290 rowType_ = temp;
6291 for (int iRow = numberRowType_; iRow < numberRows; iRow++)
6292 rowType_[iRow] = -1;
6293 numberRowType_ = numberRows;
6294 }
6295 }
6296 if (!feasible) {
6297 delete newModel;
6298 newModel = NULL;
6299 }
6300 return newModel;
6301 }
6302
6303 /* Default Constructor
6304
6305 */
CglPreProcess()6306 CglPreProcess::CglPreProcess()
6307 : originalModel_(NULL)
6308 , startModel_(NULL)
6309 , numberSolvers_(0)
6310 , model_(NULL)
6311 , modifiedModel_(NULL)
6312 , presolve_(NULL)
6313 , handler_(NULL)
6314 , defaultHandler_(true)
6315 , appData_(NULL)
6316 , originalColumn_(NULL)
6317 , originalRow_(NULL)
6318 , numberCutGenerators_(0)
6319 , generator_(NULL)
6320 , numberSOS_(0)
6321 , typeSOS_(NULL)
6322 , startSOS_(NULL)
6323 , whichSOS_(NULL)
6324 , weightSOS_(NULL)
6325 , numberProhibited_(0)
6326 , numberIterationsPre_(0)
6327 , numberIterationsPost_(0)
6328 , prohibited_(NULL)
6329 , numberRowType_(0)
6330 , options_(0)
6331 , rowType_(NULL)
6332 , useElapsedTime_(true)
6333 , timeLimit_(COIN_DBL_MAX)
6334 , keepColumnNames_(false)
6335 {
6336 handler_ = new CoinMessageHandler();
6337 handler_->setLogLevel(2);
6338 messages_ = CglMessage();
6339 }
6340
6341 // Copy constructor.
6342
CglPreProcess(const CglPreProcess & rhs)6343 CglPreProcess::CglPreProcess(const CglPreProcess &rhs)
6344 : numberSolvers_(rhs.numberSolvers_)
6345 , defaultHandler_(rhs.defaultHandler_)
6346 , appData_(rhs.appData_)
6347 , originalColumn_(NULL)
6348 , originalRow_(NULL)
6349 , numberCutGenerators_(rhs.numberCutGenerators_)
6350 , numberProhibited_(rhs.numberProhibited_)
6351 , numberIterationsPre_(rhs.numberIterationsPre_)
6352 , numberIterationsPost_(rhs.numberIterationsPost_)
6353 , numberRowType_(rhs.numberRowType_)
6354 , options_(rhs.options_)
6355 , useElapsedTime_(true)
6356 , timeLimit_(COIN_DBL_MAX)
6357 , keepColumnNames_(false)
6358 {
6359 if (defaultHandler_) {
6360 handler_ = new CoinMessageHandler();
6361 handler_->setLogLevel(rhs.handler_->logLevel());
6362 } else {
6363 handler_ = rhs.handler_;
6364 }
6365 messages_ = rhs.messages_;
6366 if (numberCutGenerators_) {
6367 generator_ = new CglCutGenerator *[numberCutGenerators_];
6368 for (int i = 0; i < numberCutGenerators_; i++) {
6369 generator_[i] = rhs.generator_[i]->clone();
6370 }
6371 } else {
6372 generator_ = NULL;
6373 }
6374 if (rhs.originalModel_) {
6375 originalModel_ = rhs.originalModel_;
6376 // If no make equality then solvers are same
6377 if (rhs.originalModel_ != rhs.startModel_) {
6378 startModel_ = rhs.startModel_->clone();
6379 } else {
6380 startModel_ = originalModel_;
6381 }
6382 } else {
6383 originalModel_ = NULL;
6384 startModel_ = NULL;
6385 }
6386 if (numberSolvers_) {
6387 model_ = new OsiSolverInterface *[numberSolvers_];
6388 modifiedModel_ = new OsiSolverInterface *[numberSolvers_];
6389 presolve_ = new OsiPresolve *[numberSolvers_];
6390 for (int i = 0; i < numberSolvers_; i++) {
6391 model_[i] = rhs.model_[i]->clone();
6392 modifiedModel_[i] = rhs.modifiedModel_[i]->clone();
6393 presolve_[i] = new OsiPresolve(*rhs.presolve_[i]);
6394 }
6395 } else {
6396 model_ = NULL;
6397 presolve_ = NULL;
6398 }
6399 numberSOS_ = rhs.numberSOS_;
6400 if (numberSOS_) {
6401 int numberTotal = rhs.startSOS_[numberSOS_];
6402 typeSOS_ = CoinCopyOfArray(rhs.typeSOS_, numberSOS_);
6403 startSOS_ = CoinCopyOfArray(rhs.startSOS_, numberSOS_ + 1);
6404 whichSOS_ = CoinCopyOfArray(rhs.whichSOS_, numberTotal);
6405 weightSOS_ = CoinCopyOfArray(rhs.weightSOS_, numberTotal);
6406 } else {
6407 typeSOS_ = NULL;
6408 startSOS_ = NULL;
6409 whichSOS_ = NULL;
6410 weightSOS_ = NULL;
6411 }
6412 prohibited_ = CoinCopyOfArray(rhs.prohibited_, numberProhibited_);
6413 rowType_ = CoinCopyOfArray(rhs.rowType_, numberRowType_);
6414 cuts_ = rhs.cuts_;
6415 }
6416
6417 // Assignment operator
6418 CglPreProcess &
operator =(const CglPreProcess & rhs)6419 CglPreProcess::operator=(const CglPreProcess &rhs)
6420 {
6421 if (this != &rhs) {
6422 gutsOfDestructor();
6423 numberSolvers_ = rhs.numberSolvers_;
6424 defaultHandler_ = rhs.defaultHandler_;
6425 appData_ = rhs.appData_;
6426 numberCutGenerators_ = rhs.numberCutGenerators_;
6427 numberProhibited_ = rhs.numberProhibited_;
6428 numberIterationsPre_ = rhs.numberIterationsPre_;
6429 numberIterationsPost_ = rhs.numberIterationsPost_;
6430 numberRowType_ = rhs.numberRowType_;
6431 options_ = rhs.options_;
6432 if (defaultHandler_) {
6433 handler_ = new CoinMessageHandler();
6434 handler_->setLogLevel(rhs.handler_->logLevel());
6435 } else {
6436 handler_ = rhs.handler_;
6437 }
6438 messages_ = rhs.messages_;
6439 if (numberCutGenerators_) {
6440 generator_ = new CglCutGenerator *[numberCutGenerators_];
6441 for (int i = 0; i < numberCutGenerators_; i++) {
6442 generator_[i] = rhs.generator_[i]->clone();
6443 }
6444 }
6445 if (rhs.originalModel_) {
6446 originalModel_ = rhs.originalModel_;
6447 // If no make equality then solvers are same
6448 if (rhs.originalModel_ != rhs.startModel_) {
6449 startModel_ = rhs.startModel_->clone();
6450 } else {
6451 startModel_ = originalModel_;
6452 }
6453 } else {
6454 originalModel_ = NULL;
6455 startModel_ = NULL;
6456 }
6457 if (numberSolvers_) {
6458 model_ = new OsiSolverInterface *[numberSolvers_];
6459 modifiedModel_ = new OsiSolverInterface *[numberSolvers_];
6460 presolve_ = new OsiPresolve *[numberSolvers_];
6461 for (int i = 0; i < numberSolvers_; i++) {
6462 model_[i] = rhs.model_[i]->clone();
6463 modifiedModel_[i] = rhs.modifiedModel_[i]->clone();
6464 presolve_[i] = new OsiPresolve(*rhs.presolve_[i]);
6465 }
6466 } else {
6467 model_ = NULL;
6468 presolve_ = NULL;
6469 }
6470 numberSOS_ = rhs.numberSOS_;
6471 if (numberSOS_) {
6472 int numberTotal = rhs.startSOS_[numberSOS_];
6473 typeSOS_ = CoinCopyOfArray(rhs.typeSOS_, numberSOS_);
6474 startSOS_ = CoinCopyOfArray(rhs.startSOS_, numberSOS_ + 1);
6475 whichSOS_ = CoinCopyOfArray(rhs.whichSOS_, numberTotal);
6476 weightSOS_ = CoinCopyOfArray(rhs.weightSOS_, numberTotal);
6477 } else {
6478 typeSOS_ = NULL;
6479 startSOS_ = NULL;
6480 whichSOS_ = NULL;
6481 weightSOS_ = NULL;
6482 }
6483 prohibited_ = CoinCopyOfArray(rhs.prohibited_, numberProhibited_);
6484 rowType_ = CoinCopyOfArray(rhs.rowType_, numberRowType_);
6485 cuts_ = rhs.cuts_;
6486 timeLimit_ = rhs.timeLimit_;
6487 keepColumnNames_ = rhs.keepColumnNames_;
6488 }
6489 return *this;
6490 }
6491
6492 // Destructor
~CglPreProcess()6493 CglPreProcess::~CglPreProcess()
6494 {
6495 gutsOfDestructor();
6496 }
6497 // Clears out as much as possible (except solver)
gutsOfDestructor()6498 void CglPreProcess::gutsOfDestructor()
6499 {
6500 if (defaultHandler_) {
6501 delete handler_;
6502 handler_ = NULL;
6503 }
6504 if (startModel_ != originalModel_)
6505 delete startModel_;
6506 startModel_ = NULL;
6507 //delete originalModel_;
6508 originalModel_ = NULL;
6509 int i;
6510 for (i = 0; i < numberCutGenerators_; i++) {
6511 delete generator_[i];
6512 }
6513 delete[] generator_;
6514 generator_ = NULL;
6515 if (numberSolvers_==99)
6516 numberSolvers_ = 1;
6517 for (i = 0; i < numberSolvers_; i++) {
6518 delete model_[i];
6519 delete modifiedModel_[i];
6520 delete presolve_[i];
6521 }
6522 delete[] model_;
6523 delete[] modifiedModel_;
6524 delete[] presolve_;
6525 model_ = NULL;
6526 presolve_ = NULL;
6527 delete[] originalColumn_;
6528 delete[] originalRow_;
6529 originalColumn_ = NULL;
6530 originalRow_ = NULL;
6531 delete[] typeSOS_;
6532 delete[] startSOS_;
6533 delete[] whichSOS_;
6534 delete[] weightSOS_;
6535 typeSOS_ = NULL;
6536 startSOS_ = NULL;
6537 whichSOS_ = NULL;
6538 weightSOS_ = NULL;
6539 delete[] prohibited_;
6540 prohibited_ = NULL;
6541 numberProhibited_ = 0;
6542 numberIterationsPre_ = 0;
6543 numberIterationsPost_ = 0;
6544 delete[] rowType_;
6545 rowType_ = NULL;
6546 numberRowType_ = 0;
6547 }
6548 // Add one generator
addCutGenerator(CglCutGenerator * generator)6549 void CglPreProcess::addCutGenerator(CglCutGenerator *generator)
6550 {
6551 CglCutGenerator **temp = generator_;
6552 generator_ = new CglCutGenerator *[numberCutGenerators_ + 1];
6553 memcpy(generator_, temp, numberCutGenerators_ * sizeof(CglCutGenerator *));
6554 delete[] temp;
6555 generator_[numberCutGenerators_++] = generator->clone();
6556 }
6557 //#############################################################################
6558 // Set/Get Application Data
6559 // This is a pointer that the application can store into and retrieve
6560 // This field is the application to optionally define and use.
6561 //#############################################################################
6562
setApplicationData(void * appData)6563 void CglPreProcess::setApplicationData(void *appData)
6564 {
6565 appData_ = appData;
6566 }
6567 //-----------------------------------------------------------------------------
getApplicationData() const6568 void *CglPreProcess::getApplicationData() const
6569 {
6570 return appData_;
6571 }
6572 /* Set cutoff bound on the objective function.
6573
6574 When using strict comparison, the bound is adjusted by a tolerance to
6575 avoid accidentally cutting off the optimal solution.
6576 */
setCutoff(double value)6577 void CglPreProcess::setCutoff(double value)
6578 {
6579 // Solvers know about direction
6580 double direction = originalModel_->getObjSense();
6581 originalModel_->setDblParam(OsiDualObjectiveLimit, value * direction);
6582 }
6583
6584 // Get the cutoff bound on the objective function - always as minimize
6585 double
getCutoff() const6586 CglPreProcess::getCutoff() const
6587 {
6588 double value;
6589 originalModel_->getDblParam(OsiDualObjectiveLimit, value);
6590 return value * originalModel_->getObjSense();
6591 }
6592 // Pass in Message handler (not deleted at end)
passInMessageHandler(CoinMessageHandler * handler)6593 void CglPreProcess::passInMessageHandler(CoinMessageHandler *handler)
6594 {
6595 if (defaultHandler_)
6596 delete handler_;
6597 defaultHandler_ = false;
6598 handler_ = handler;
6599 }
6600 // Set language
newLanguage(CoinMessages::Language language)6601 void CglPreProcess::newLanguage(CoinMessages::Language language)
6602 {
6603 messages_ = CglMessage(language);
6604 }
6605 // Return a pointer to the original columns (without clique slacks)
6606 const int *
originalColumns()6607 CglPreProcess::originalColumns()
6608 {
6609 if (!originalColumn_)
6610 createOriginalIndices();
6611 return originalColumn_;
6612 }
6613 // Return a pointer to the original rows
6614 const int *
originalRows()6615 CglPreProcess::originalRows()
6616 {
6617 if (!originalRow_)
6618 createOriginalIndices();
6619 return originalRow_;
6620 }
6621 // create original columns and rows
createOriginalIndices()6622 void CglPreProcess::createOriginalIndices()
6623 {
6624 // Find last model and presolve
6625 int iPass;
6626 for (iPass = numberSolvers_ - 1; iPass >= 0; iPass--) {
6627 if (presolve_[iPass])
6628 break;
6629 }
6630 int nRows, nColumns;
6631 if (iPass >= 0) {
6632 nRows = model_[iPass]->getNumRows();
6633 nColumns = model_[iPass]->getNumCols();
6634 } else {
6635 nRows = originalModel_->getNumRows();
6636 nColumns = originalModel_->getNumCols();
6637 }
6638 delete[] originalColumn_;
6639 originalColumn_ = new int[nColumns];
6640 delete[] originalRow_;
6641 originalRow_ = new int[nRows];
6642 if (iPass >= 0) {
6643 memcpy(originalColumn_, presolve_[iPass]->originalColumns(),
6644 nColumns * sizeof(int));
6645 memcpy(originalRow_, presolve_[iPass]->originalRows(),
6646 nRows * sizeof(int));
6647 iPass--;
6648 for (; iPass >= 0; iPass--) {
6649 const int *originalColumns = presolve_[iPass]->originalColumns();
6650 int i;
6651 for (i = 0; i < nColumns; i++)
6652 originalColumn_[i] = originalColumns[originalColumn_[i]];
6653 const int *originalRows = presolve_[iPass]->originalRows();
6654 int nRowsNow = model_[iPass]->getNumRows();
6655 for (i = 0; i < nRows; i++) {
6656 int iRow = originalRow_[i];
6657 if (iRow >= 0 && iRow < nRowsNow)
6658 originalRow_[i] = originalRows[iRow];
6659 else
6660 originalRow_[i] = -1;
6661 }
6662 }
6663 std::sort(originalColumn_, originalColumn_ + nColumns);
6664 } else {
6665 int i;
6666 for (i = 0; i < nColumns; i++)
6667 originalColumn_[i] = i;
6668 for (i = 0; i < nRows; i++)
6669 originalRow_[i] = i;
6670 }
6671 }
6672 // Update prohibited and rowType
update(const OsiPresolve * pinfo,const OsiSolverInterface * solver)6673 void CglPreProcess::update(const OsiPresolve *pinfo,
6674 const OsiSolverInterface *solver)
6675 {
6676 if (prohibited_) {
6677 const int *original = pinfo->originalColumns();
6678 int numberColumns = solver->getNumCols();
6679 // number prohibited must stay constant
6680 int n = 0;
6681 int i;
6682 for (i = 0; i < numberProhibited_; i++) {
6683 if (prohibited_[i])
6684 n++;
6685 }
6686 int n2 = 0;
6687 for (i = 0; i < numberColumns; i++) {
6688 int iColumn = original[i];
6689 assert(i == 0 || iColumn > original[i - 1]);
6690 char p = prohibited_[iColumn];
6691 if (p)
6692 n2++;
6693 prohibited_[i] = p;
6694 }
6695 assert(n == n2);
6696 numberProhibited_ = numberColumns;
6697 }
6698 if (rowType_) {
6699 const int *original = pinfo->originalRows();
6700 int numberRows = solver->getNumRows();
6701 #if CBC_USEFUL_PRINTING > 1
6702 int nMarked1 = 0;
6703 for (int i = 0; i < pinfo->getNumRows(); i++) {
6704 if (rowType_[i])
6705 nMarked1++;
6706 }
6707 int nMarked2 = 0;
6708 int k = -1;
6709 for (int i = 0; i < numberRows; i++) {
6710 int iRow = original[i];
6711 if (iRow < i)
6712 abort();
6713 if (iRow <= k)
6714 abort();
6715 k = iRow;
6716 if (rowType_[iRow])
6717 nMarked2++;
6718 }
6719 if (nMarked1 > nMarked2)
6720 printf("Marked rows reduced from %d to %d\n",
6721 nMarked1, nMarked2);
6722 #endif
6723 for (int i = 0; i < numberRows; i++) {
6724 int iRow = original[i];
6725 rowType_[i] = rowType_[iRow];
6726 }
6727 numberRowType_ = numberRows;
6728 }
6729 }
6730 /* Fix some of problem - returning new problem.
6731 Uses reduced costs.
6732 Optional signed character array
6733 1 always keep, -1 always discard, 0 use djs
6734
6735 */
6736 OsiSolverInterface *
someFixed(OsiSolverInterface & model,double fractionToKeep,bool fixContinuousAsWell,char * keep) const6737 CglPreProcess::someFixed(OsiSolverInterface &model,
6738 double fractionToKeep,
6739 bool fixContinuousAsWell,
6740 char *keep) const
6741 {
6742 model.resolve();
6743 int numberColumns = model.getNumCols();
6744 OsiSolverInterface *newModel = model.clone();
6745 int i;
6746 const double *lower = model.getColLower();
6747 const double *upper = model.getColUpper();
6748 const double *solution = model.getColSolution();
6749 double *dj = CoinCopyOfArray(model.getReducedCost(), numberColumns);
6750 int *sort = new int[numberColumns];
6751 int number = 0;
6752 int numberThrow = 0;
6753 int numberContinuous = 0;
6754 for (i = 0; i < numberColumns; i++) {
6755 if (!model.isInteger(i) && upper[i] > lower[i])
6756 numberContinuous++;
6757 if (model.isInteger(i) || fixContinuousAsWell) {
6758 if (keep) {
6759 if (keep[i] == 1) {
6760 continue; // always keep
6761 } else if (keep[i] == -1) {
6762 // always fix
6763 dj[number] = -1.0e30;
6764 numberThrow++;
6765 sort[number++] = i;
6766 continue;
6767 }
6768 }
6769 double value = solution[i];
6770 if (value < lower[i] + 1.0e-8) {
6771 dj[number] = -dj[i];
6772 sort[number++] = i;
6773 } else if (value > upper[number] - 1.0e-8) {
6774 dj[number] = -dj[i];
6775 sort[number++] = i;
6776 }
6777 }
6778 }
6779 CoinSort_2(dj, dj + number, sort);
6780 int numberToFix = static_cast< int >(numberColumns * (1.0 - fractionToKeep));
6781 if (!fixContinuousAsWell)
6782 numberToFix = static_cast< int >((numberColumns - numberContinuous) * (1.0 - fractionToKeep));
6783 numberToFix = CoinMax(numberToFix, numberThrow);
6784 numberToFix = CoinMin(number, numberToFix);
6785 #if CBC_USEFUL_PRINTING
6786 printf("%d columns fixed\n", numberToFix);
6787 #endif
6788 for (i = 0; i < numberToFix; i++) {
6789 int iColumn = sort[i];
6790 double value = solution[iColumn];
6791 if (value < lower[iColumn] + 1.0e-8) {
6792 newModel->setColUpper(iColumn, lower[iColumn]);
6793 } else if (value > upper[number] - 1.0e-8) {
6794 newModel->setColLower(iColumn, lower[iColumn]);
6795 } else {
6796 // must be a throw away on - go to lower
6797 newModel->setColUpper(iColumn, lower[iColumn]);
6798 }
6799 }
6800 delete[] sort;
6801 delete[] dj;
6802 return newModel;
6803 }
6804 // If we have a cutoff - fix variables
reducedCostFix(OsiSolverInterface & model)6805 int CglPreProcess::reducedCostFix(OsiSolverInterface &model)
6806 {
6807 double cutoff;
6808 model.getDblParam(OsiDualObjectiveLimit, cutoff);
6809 double direction = model.getObjSense();
6810 cutoff *= direction;
6811 double gap = cutoff - model.getObjValue() * direction;
6812 double tolerance;
6813 model.getDblParam(OsiDualTolerance, tolerance);
6814 if (gap <= 0.0 || fabs(cutoff) > 1.0e20)
6815 return 0;
6816 gap += 100.0 * tolerance;
6817 // not really but thats all we can get
6818 double integerTolerance;
6819 model.getDblParam(OsiPrimalTolerance, integerTolerance);
6820 int numberColumns = model.getNumCols();
6821
6822 const double *lower = model.getColLower();
6823 const double *upper = model.getColUpper();
6824 const double *solution = model.getColSolution();
6825 const double *reducedCost = model.getReducedCost();
6826
6827 int numberFixed = 0;
6828 int iColumn;
6829 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6830 if (model.isInteger(iColumn) && upper[iColumn] > lower[iColumn]) {
6831 double djValue = direction * reducedCost[iColumn];
6832 if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
6833 model.setColUpper(iColumn, lower[iColumn]);
6834 numberFixed++;
6835 } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
6836 model.setColLower(iColumn, upper[iColumn]);
6837 numberFixed++;
6838 }
6839 }
6840 }
6841 return numberFixed;
6842 }
6843 // Pass in prohibited columns
passInProhibited(const char * prohibited,int numberColumns)6844 void CglPreProcess::passInProhibited(const char *prohibited, int numberColumns)
6845 {
6846 char *temp = prohibited_;
6847 prohibited_ = CoinCopyOfArray(prohibited, numberColumns);
6848 if (temp && numberProhibited_ == numberColumns) {
6849 // merge
6850 for (int i = 0; i < numberColumns; i++)
6851 prohibited_[i] |= temp[i];
6852 }
6853 numberProhibited_ = numberColumns;
6854 delete[] temp;
6855 }
6856 /* Pass in row types
6857 0 normal
6858 1 cut rows - will be dropped if remain in
6859 At end of preprocess cut rows will be dropped
6860 and put into cuts
6861 */
passInRowTypes(const char * rowTypes,int numberRows)6862 void CglPreProcess::passInRowTypes(const char *rowTypes, int numberRows)
6863 {
6864 delete[] rowType_;
6865 rowType_ = CoinCopyOfArray(rowTypes, numberRows);
6866 numberRowType_ = numberRows;
6867 cuts_ = CglStored();
6868 }
6869 // Make continuous variables integer
makeInteger()6870 void CglPreProcess::makeInteger()
6871 {
6872 // First check if we need to
6873 int numberInteger = 0;
6874 {
6875 const double *lower = startModel_->getColLower();
6876 const double *upper = startModel_->getColUpper();
6877 int numberColumns = startModel_->getNumCols();
6878 int iColumn;
6879 int numberContinuous = 0;
6880 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6881 if (upper[iColumn] > lower[iColumn] + 1.0e-8) {
6882 if (startModel_->isInteger(iColumn))
6883 numberInteger++;
6884 else
6885 numberContinuous++;
6886 }
6887 }
6888 if (!numberContinuous)
6889 return;
6890 }
6891 OsiSolverInterface *solver = startModel_->clone();
6892 const double *objective = solver->getObjCoefficients();
6893 const double *lower = solver->getColLower();
6894 const double *upper = solver->getColUpper();
6895 int numberColumns = solver->getNumCols();
6896 int numberRows = solver->getNumRows();
6897 double direction = solver->getObjSense();
6898 int iRow, iColumn;
6899
6900 // Row copy
6901 CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
6902 const double *elementByRow = matrixByRow.getElements();
6903 const int *column = matrixByRow.getIndices();
6904 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
6905 const int *rowLength = matrixByRow.getVectorLengths();
6906
6907 // Column copy
6908 CoinPackedMatrix matrixByCol(*solver->getMatrixByCol());
6909 const double *element = matrixByCol.getElements();
6910 const int *row = matrixByCol.getIndices();
6911 const CoinBigIndex *columnStart = matrixByCol.getVectorStarts();
6912 const int *columnLength = matrixByCol.getVectorLengths();
6913
6914 const double *rowLower = solver->getRowLower();
6915 const double *rowUpper = solver->getRowUpper();
6916
6917 char *ignore = new char[numberRows];
6918 int *changed = new int[numberColumns];
6919 int *which = new int[numberRows];
6920 double *changeRhs = new double[numberRows];
6921 memset(changeRhs, 0, numberRows * sizeof(double));
6922 memset(ignore, 0, numberRows);
6923 int numberChanged = 0;
6924 bool finished = false;
6925 while (!finished) {
6926 int saveNumberChanged = numberChanged;
6927 for (iRow = 0; iRow < numberRows; iRow++) {
6928 int numberContinuous = 0;
6929 double value1 = 0.0, value2 = 0.0;
6930 bool allIntegerCoeff = true;
6931 double sumFixed = 0.0;
6932 int jColumn1 = -1, jColumn2 = -1;
6933 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
6934 int jColumn = column[j];
6935 double value = elementByRow[j];
6936 if (upper[jColumn] > lower[jColumn] + 1.0e-8) {
6937 if (!solver->isInteger(jColumn)) {
6938 if (numberContinuous == 0) {
6939 jColumn1 = jColumn;
6940 value1 = value;
6941 } else {
6942 jColumn2 = jColumn;
6943 value2 = value;
6944 }
6945 numberContinuous++;
6946 } else {
6947 if (fabs(value - floor(value + 0.5)) > 1.0e-12)
6948 allIntegerCoeff = false;
6949 }
6950 } else {
6951 sumFixed += lower[jColumn] * value;
6952 }
6953 }
6954 double low = rowLower[iRow];
6955 if (low > -1.0e20) {
6956 low -= sumFixed;
6957 if (fabs(low - floor(low + 0.5)) > 1.0e-12)
6958 allIntegerCoeff = false;
6959 }
6960 double up = rowUpper[iRow];
6961 if (up < 1.0e20) {
6962 up -= sumFixed;
6963 if (fabs(up - floor(up + 0.5)) > 1.0e-12)
6964 allIntegerCoeff = false;
6965 }
6966 if (!allIntegerCoeff)
6967 continue; // can't do
6968 if (numberContinuous == 1) {
6969 // see if really integer
6970 // This does not allow for complicated cases
6971 if (low == up) {
6972 if (fabs(value1) > 1.0e-3) {
6973 value1 = 1.0 / value1;
6974 if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) {
6975 // integer
6976 changed[numberChanged++] = jColumn1;
6977 solver->setInteger(jColumn1);
6978 if (upper[jColumn1] > 1.0e20)
6979 solver->setColUpper(jColumn1, 1.0e20);
6980 if (lower[jColumn1] < -1.0e20)
6981 solver->setColLower(jColumn1, -1.0e20);
6982 }
6983 }
6984 } else {
6985 if (fabs(value1) > 1.0e-3) {
6986 value1 = 1.0 / value1;
6987 if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) {
6988 // This constraint will not stop it being integer
6989 ignore[iRow] = 1;
6990 }
6991 }
6992 }
6993 } else if (numberContinuous == 2) {
6994 if (low == up) {
6995 /* need general theory - for now just look at 2 cases -
6996 1 - +- 1 one in column and just costs i.e. matching objective
6997 2 - +- 1 two in column but feeds into G/L row which will try and minimize
6998 */
6999 if (fabs(value1) == 1.0 && value1 * value2 == -1.0 && !lower[jColumn1]
7000 && !lower[jColumn2]) {
7001 int n = 0;
7002 CoinBigIndex i;
7003 double objChange = direction * (objective[jColumn1] + objective[jColumn2]);
7004 double bound = CoinMin(upper[jColumn1], upper[jColumn2]);
7005 bound = CoinMin(bound, 1.0e20);
7006 for (i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) {
7007 int jRow = row[i];
7008 double value = element[i];
7009 if (jRow != iRow) {
7010 which[n++] = jRow;
7011 changeRhs[jRow] = value;
7012 }
7013 }
7014 for (i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) {
7015 int jRow = row[i];
7016 double value = element[i];
7017 if (jRow != iRow) {
7018 if (!changeRhs[jRow]) {
7019 which[n++] = jRow;
7020 changeRhs[jRow] = value;
7021 } else {
7022 changeRhs[jRow] += value;
7023 }
7024 }
7025 }
7026 if (objChange >= 0.0) {
7027 // see if all rows OK
7028 bool good = true;
7029 for (i = 0; i < n; i++) {
7030 int jRow = which[i];
7031 double value = changeRhs[jRow];
7032 if (value) {
7033 value *= bound;
7034 if (rowLength[jRow] == 1) {
7035 if (value > 0.0) {
7036 double rhs = rowLower[jRow];
7037 if (rhs > 0.0) {
7038 double ratio = rhs / value;
7039 if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12)
7040 good = false;
7041 }
7042 } else {
7043 double rhs = rowUpper[jRow];
7044 if (rhs < 0.0) {
7045 double ratio = rhs / value;
7046 if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12)
7047 good = false;
7048 }
7049 }
7050 } else if (rowLength[jRow] == 2) {
7051 if (value > 0.0) {
7052 if (rowLower[jRow] > -1.0e20)
7053 good = false;
7054 } else {
7055 if (rowUpper[jRow] < 1.0e20)
7056 good = false;
7057 }
7058 } else {
7059 good = false;
7060 }
7061 }
7062 }
7063 if (good) {
7064 // both can be integer
7065 changed[numberChanged++] = jColumn1;
7066 solver->setInteger(jColumn1);
7067 if (upper[jColumn1] > 1.0e20)
7068 solver->setColUpper(jColumn1, 1.0e20);
7069 if (lower[jColumn1] < -1.0e20)
7070 solver->setColLower(jColumn1, -1.0e20);
7071 changed[numberChanged++] = jColumn2;
7072 solver->setInteger(jColumn2);
7073 if (upper[jColumn2] > 1.0e20)
7074 solver->setColUpper(jColumn2, 1.0e20);
7075 if (lower[jColumn2] < -1.0e20)
7076 solver->setColLower(jColumn2, -1.0e20);
7077 }
7078 }
7079 // clear
7080 for (i = 0; i < n; i++) {
7081 changeRhs[which[i]] = 0.0;
7082 }
7083 }
7084 }
7085 }
7086 }
7087 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
7088 if (upper[iColumn] > lower[iColumn] + 1.0e-8 && !solver->isInteger(iColumn)) {
7089 double value;
7090 value = upper[iColumn];
7091 if (value < 1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12)
7092 continue;
7093 value = lower[iColumn];
7094 if (value > -1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12)
7095 continue;
7096 bool integer = true;
7097 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
7098 int iRow = row[j];
7099 if (!ignore[iRow]) {
7100 integer = false;
7101 break;
7102 }
7103 }
7104 if (integer) {
7105 // integer
7106 changed[numberChanged++] = iColumn;
7107 solver->setInteger(iColumn);
7108 if (upper[iColumn] > 1.0e20)
7109 solver->setColUpper(iColumn, 1.0e20);
7110 if (lower[iColumn] < -1.0e20)
7111 solver->setColLower(iColumn, -1.0e20);
7112 }
7113 }
7114 }
7115 finished = numberChanged == saveNumberChanged;
7116 }
7117 delete[] which;
7118 delete[] changeRhs;
7119 delete[] ignore;
7120 //increment=0.0;
7121 if (numberChanged) {
7122 handler_->message(CGL_MADE_INTEGER, messages_)
7123 << numberChanged
7124 << CoinMessageEol;
7125 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
7126 if (solver->isInteger(iColumn) && objective[iColumn])
7127 startModel_->setInteger(iColumn);
7128 }
7129 }
7130 delete solver;
7131 delete[] changed;
7132 }
7133 //#define BRON_TIMES
7134 #ifdef BRON_TIMES
7135 static int numberTimesX = 0;
7136 #endif
7137 /* Replace cliques by more maximal cliques
7138 Returns NULL if rows not reduced by greater than cliquesNeeded*rows
7139
7140 */
7141 OsiSolverInterface *
cliqueIt(OsiSolverInterface & model,double cliquesNeeded) const7142 CglPreProcess::cliqueIt(OsiSolverInterface &model,
7143 double cliquesNeeded) const
7144 {
7145 /*
7146 Initial arrays
7147 * Candidate nodes (columns)
7148 First nIn already in
7149 Next nCandidate are candidates
7150 numberColumns-1 back to nNot are Nots
7151 * Starts
7152 * Other node
7153 * Original row (paired with other node)
7154 * CliqueIn expanded array with 1 in, 2 not, 3 out, 0 possible, -1 never
7155 * Type (for original row)
7156 */
7157 const double *lower = model.getColLower();
7158 const double *upper = model.getColUpper();
7159 const double *rowLower = model.getRowLower();
7160 const double *rowUpper = model.getRowUpper();
7161 int numberRows = model.getNumRows();
7162 int numberColumns = model.getNumCols();
7163 // Column copy of matrix
7164 //const double * element = model.getMatrixByCol()->getElements();
7165 //const int * row = model.getMatrixByCol()->getIndices();
7166 //const CoinBigIndex * columnStart = model.getMatrixByCol()->getVectorStarts();
7167 //const int * columnLength = model.getMatrixByCol()->getVectorLengths();
7168 // Row copy
7169 CoinPackedMatrix matrixByRow(*model.getMatrixByRow());
7170 const double *elementByRow = matrixByRow.getElements();
7171 const int *column = matrixByRow.getIndices();
7172 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
7173 const int *rowLength = matrixByRow.getVectorLengths();
7174 char *type = new char[numberRows + 3 * numberColumns];
7175 char *numberInColumn = type + numberRows;
7176 char *negativeInColumn = numberInColumn + numberColumns;
7177 char *positiveInColumn = negativeInColumn + numberColumns;
7178 memset(numberInColumn, 0, 3 * numberColumns);
7179 // First pass to mark columns
7180 int numberCliques = 0;
7181 //int numberOddCliques=0;
7182 for (int i = 0; i < numberRows; i++) {
7183 type[i] = -1;
7184 double rupper = rowUpper[i];
7185 double rlower = rowLower[i];
7186 if (rupper == 1.0 && (rlower <= 0.0 || rlower == 1.0)) {
7187 bool possible = true;
7188 CoinBigIndex start = rowStart[i];
7189 CoinBigIndex end = start + rowLength[i];
7190 int n = 0;
7191 for (CoinBigIndex j = start; j < end; j++) {
7192 int iColumn = column[j];
7193 if (upper[iColumn] == 1.0 && lower[iColumn] == 0.0 && model.isInteger(iColumn) && elementByRow[j] == 1.0) {
7194 n++;
7195 } else {
7196 possible = false;
7197 break;
7198 }
7199 }
7200 if (n > 1000)
7201 possible = false;
7202 if (possible) {
7203 for (CoinBigIndex j = start; j < end; j++) {
7204 int iColumn = column[j];
7205 if (numberInColumn[iColumn] < 100)
7206 numberInColumn[iColumn]++;
7207 }
7208 numberCliques++;
7209 if (rowLower[i] > 0.0)
7210 type[i] = 1;
7211 else
7212 type[i] = 0;
7213 }
7214 } else if ((rupper == 0.0 || rlower == 0.0) && rowLength[i] == 2) {
7215 int multiplier;
7216 if (rupper == 0.0 && rlower < -1.0e20)
7217 multiplier = 1;
7218 else if (rlower == 0.0 && rupper > 1.0e20)
7219 multiplier = -1;
7220 else
7221 multiplier = 0;
7222 if (multiplier) {
7223 CoinBigIndex start = rowStart[i];
7224 if (fabs(elementByRow[start]) == 1.0 && fabs(elementByRow[start + 1]) == 1.0) {
7225 if (elementByRow[start] * elementByRow[start + 1] == -1.0) {
7226 int iPColumn, iNColumn;
7227 if (multiplier * elementByRow[start] == 1.0) {
7228 iPColumn = column[start];
7229 iNColumn = column[start + 1];
7230 } else {
7231 iNColumn = column[start];
7232 iPColumn = column[start + 1];
7233 }
7234 if (upper[iPColumn] == 1.0 && lower[iPColumn] == 0.0 && model.isInteger(iPColumn) && upper[iNColumn] == 1.0 && lower[iNColumn] == 0.0 && model.isInteger(iNColumn)) {
7235 type[i] = -2;
7236 if (positiveInColumn[iPColumn] < 100)
7237 positiveInColumn[iPColumn]++;
7238 if (negativeInColumn[iNColumn] < 100)
7239 negativeInColumn[iNColumn]++;
7240 }
7241 }
7242 }
7243 }
7244 }
7245 }
7246 #if CBC_USEFUL_PRINTING > 0
7247 // look at odd cliques
7248 int nOdd = 0;
7249 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
7250 if (!numberInColumn[iColumn] && negativeInColumn[iColumn] > 1) {
7251 nOdd++;
7252 }
7253 }
7254 if (nOdd)
7255 printf("%d possible odd cliques?\n", nOdd);
7256 #endif
7257 double numberElements = 0;
7258 if (numberCliques > CoinMax(1, static_cast< int >(cliquesNeeded * numberRows))) {
7259 numberCliques = 0;
7260 for (int i = 0; i < numberRows; i++) {
7261 if (type[i] >= 0) {
7262 bool possible = true;
7263 int n = 0;
7264 CoinBigIndex start = rowStart[i];
7265 CoinBigIndex end = start + rowLength[i];
7266 for (CoinBigIndex j = start; j < end; j++) {
7267 int iColumn = column[j];
7268 if (numberInColumn[iColumn] < 2) {
7269 possible = false;
7270 break;
7271 } else {
7272 n++;
7273 }
7274 }
7275 if (possible) {
7276 numberElements += n * (n - 1);
7277 numberCliques++;
7278 } else {
7279 type[i] = -1;
7280 }
7281 }
7282 }
7283 }
7284 OsiSolverInterface *newSolver = NULL;
7285 if (numberCliques > CoinMax(1, static_cast< int >(cliquesNeeded * numberRows))) {
7286 if (numberElements < 5.0e7 && numberElements < numberCliques * 100) {
7287 #if CBC_USEFUL_PRINTING > 0
7288 printf("%d cliques needing 2 * %g ints\n",
7289 numberCliques, numberElements);
7290 #endif
7291 #ifdef BRON_TIMES
7292 double time1 = CoinCpuTime();
7293 #endif
7294 CglBK bk(model, type, static_cast< int >(numberElements));
7295 bk.bronKerbosch();
7296 newSolver = bk.newSolver(model);
7297 #ifdef BRON_TIMES
7298 printf("Time %g - bron called %d times\n", CoinCpuTime() - time1, numberTimesX);
7299 #endif
7300 } else {
7301 #if CBC_USEFUL_PRINTING > 0
7302 printf("*** %d cliques needing 2 * %g ints\n",
7303 numberCliques, numberElements);
7304 #endif
7305 }
7306 }
7307 delete[] type;
7308 return newSolver;
7309 }
7310 // Default constructor
CglBK()7311 CglBK::CglBK()
7312 {
7313 candidates_ = NULL;
7314 mark_ = NULL;
7315 start_ = NULL;
7316 otherColumn_ = NULL;
7317 originalRow_ = NULL;
7318 dominated_ = NULL;
7319 cliqueMatrix_ = NULL;
7320 rowType_ = NULL;
7321 numberColumns_ = 0;
7322 numberRows_ = 0;
7323 numberPossible_ = 0;
7324 numberCandidates_ = 0;
7325 firstNot_ = 0;
7326 numberIn_ = 0;
7327 left_ = 0;
7328 lastColumn_ = 0;
7329 }
7330
7331 // Useful constructor
CglBK(const OsiSolverInterface & model,const char * rowType,int numberElements)7332 CglBK::CglBK(const OsiSolverInterface &model, const char *rowType,
7333 int numberElements)
7334 {
7335 const double *lower = model.getColLower();
7336 const double *upper = model.getColUpper();
7337 const double *rowLower = model.getRowLower();
7338 const double *rowUpper = model.getRowUpper();
7339 numberRows_ = model.getNumRows();
7340 numberColumns_ = model.getNumCols();
7341 // Column copy of matrix
7342 #ifndef NDEBUG
7343 const double *element = model.getMatrixByCol()->getElements();
7344 #endif
7345 const int *row = model.getMatrixByCol()->getIndices();
7346 const CoinBigIndex *columnStart = model.getMatrixByCol()->getVectorStarts();
7347 const int *columnLength = model.getMatrixByCol()->getVectorLengths();
7348 start_ = new CoinBigIndex[numberColumns_ + 1];
7349 otherColumn_ = new int[numberElements];
7350 candidates_ = new int[2 * numberColumns_];
7351 CoinZeroN(candidates_, 2 * numberColumns_); // for valgrind
7352 originalRow_ = new int[numberElements];
7353 dominated_ = new int[numberRows_];
7354 CoinZeroN(dominated_, numberRows_);
7355 //int inputNumber=numberElements;
7356 numberElements = 0;
7357 numberPossible_ = 0;
7358 rowType_ = rowType;
7359 // Row copy
7360 CoinPackedMatrix matrixByRow(*model.getMatrixByRow());
7361 const double *elementByRow = matrixByRow.getElements();
7362 const int *column = matrixByRow.getIndices();
7363 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
7364 const int *rowLength = matrixByRow.getVectorLengths();
7365 #if 1
7366 // take out duplicate doubleton rows
7367 double *sort = new double[numberRows_];
7368 int *which = new int[numberRows_];
7369 double *randomValues = new double[numberColumns_];
7370 // Initialize random seed
7371 CoinThreadRandom randomGenerator(987654321);
7372 for (int i = 0; i < numberColumns_; i++)
7373 randomValues[i] = randomGenerator.randomDouble();
7374 int nSort = 0;
7375 for (int i = 0; i < numberRows_; i++) {
7376 if (rowLength[i] == 2 && rowUpper[i] == 1.0) {
7377 CoinBigIndex first = rowStart[i];
7378 CoinBigIndex last = first + 1;
7379 if (column[first] > column[last]) {
7380 first = last;
7381 last = rowStart[i];
7382 }
7383 int iColumn1 = column[first];
7384 int iColumn2 = column[last];
7385 double value = elementByRow[first] * randomValues[iColumn1] + elementByRow[last] * randomValues[iColumn2];
7386 sort[nSort] = value;
7387 which[nSort++] = i;
7388 }
7389 }
7390 CoinSort_2(sort, sort + nSort, which);
7391 double value = sort[0];
7392 int nDominated = 0;
7393 for (int i = 1; i < nSort; i++) {
7394 if (sort[i] == value) {
7395 int i1 = which[i - 1];
7396 int i2 = which[i];
7397 if (rowLower[i1] == rowLower[i2]) {
7398 CoinBigIndex first1 = rowStart[i1];
7399 CoinBigIndex last1 = first1 + 1;
7400 if (column[first1] > column[last1]) {
7401 first1 = last1;
7402 last1 = rowStart[i1];
7403 }
7404 int iColumn11 = column[first1];
7405 int iColumn12 = column[last1];
7406 CoinBigIndex first2 = rowStart[i2];
7407 CoinBigIndex last2 = first2 + 1;
7408 if (column[first2] > column[last2]) {
7409 first2 = last2;
7410 last2 = rowStart[i2];
7411 }
7412 int iColumn21 = column[first2];
7413 int iColumn22 = column[last2];
7414 if (iColumn11 == iColumn21 && iColumn12 == iColumn22 && elementByRow[first1] == elementByRow[first2] && elementByRow[last1] == elementByRow[last2]) {
7415 dominated_[i2] = 1;
7416 nDominated++;
7417 }
7418 }
7419 }
7420 value = sort[i];
7421 }
7422 //if (nDominated)
7423 //printf("%d duplicate doubleton rows!\n",nDominated);
7424 delete[] randomValues;
7425 delete[] sort;
7426 delete[] which;
7427 #endif
7428 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
7429 start_[iColumn] = numberElements;
7430 CoinBigIndex start = columnStart[iColumn];
7431 CoinBigIndex end = start + columnLength[iColumn];
7432 if (upper[iColumn] == 1.0 && lower[iColumn] == 0.0 && model.isInteger(iColumn)) {
7433 for (CoinBigIndex j = start; j < end; j++) {
7434 int iRow = row[j];
7435 if (rowType[iRow] >= 0 && !dominated_[iRow]) {
7436 assert(element[j] == 1.0);
7437 #if 0
7438 CoinBigIndex r=rowStart[iRow];
7439 assert (rowLength[iRow]==2);
7440 int kColumn = column[r];
7441 if (kColumn==iColumn)
7442 kColumn=column[r+1];
7443 originalRow_[numberElements]=iRow;
7444 otherColumn_[numberElements++]=kColumn;
7445 #else
7446 for (CoinBigIndex r = rowStart[iRow]; r < rowStart[iRow] + rowLength[iRow]; r++) {
7447 int kColumn = column[r];
7448 if (kColumn != iColumn) {
7449 originalRow_[numberElements] = iRow;
7450 otherColumn_[numberElements++] = kColumn;
7451 }
7452 }
7453
7454 #endif
7455 }
7456 }
7457 if (numberElements > start_[iColumn]) {
7458 candidates_[numberPossible_++] = iColumn;
7459 }
7460 }
7461 }
7462 //printf("input number %d, computed number %d\n",inputNumber,numberElements);
7463 start_[numberColumns_] = numberElements;
7464 numberCandidates_ = numberPossible_;
7465 numberIn_ = 0;
7466 firstNot_ = numberPossible_;
7467 left_ = numberPossible_;
7468 lastColumn_ = -1;
7469 mark_ = new char[numberColumns_];
7470 memset(mark_, 0, numberColumns_);
7471 cliqueMatrix_ = new CoinPackedMatrix(false, 0.5, 0.0);
7472 int n = 0;
7473 for (int i = 0; i < numberRows_; i++) {
7474 if (rowType[i] >= 0)
7475 n++;
7476 }
7477 cliqueMatrix_->reserve(CoinMin(100, n), 5 * numberPossible_);
7478 }
7479
7480 // Copy constructor .
CglBK(const CglBK & rhs)7481 CglBK::CglBK(const CglBK &rhs)
7482 {
7483 // This only copies data in candidates_
7484 // rest just points
7485 candidates_ = CoinCopyOfArray(rhs.candidates_, 2 * rhs.numberPossible_);
7486 mark_ = rhs.mark_;
7487 start_ = rhs.start_;
7488 otherColumn_ = rhs.otherColumn_;
7489 originalRow_ = rhs.originalRow_;
7490 dominated_ = rhs.dominated_;
7491 cliqueMatrix_ = rhs.cliqueMatrix_;
7492 rowType_ = rhs.rowType_;
7493 numberColumns_ = rhs.numberColumns_;
7494 numberRows_ = rhs.numberRows_;
7495 numberPossible_ = rhs.numberPossible_;
7496 numberCandidates_ = rhs.numberCandidates_;
7497 firstNot_ = rhs.firstNot_;
7498 numberIn_ = rhs.numberIn_;
7499 left_ = rhs.left_;
7500 lastColumn_ = rhs.lastColumn_;
7501 }
7502
7503 // Assignment operator
operator =(const CglBK & rhs)7504 CglBK &CglBK::operator=(const CglBK &rhs)
7505 {
7506 if (this != &rhs) {
7507 delete[] candidates_;
7508 // This only copies data in candidates_
7509 // rest just points
7510 candidates_ = CoinCopyOfArray(rhs.candidates_, 2 * numberPossible_);
7511 mark_ = rhs.mark_;
7512 start_ = rhs.start_;
7513 otherColumn_ = rhs.otherColumn_;
7514 originalRow_ = rhs.originalRow_;
7515 dominated_ = rhs.dominated_;
7516 cliqueMatrix_ = rhs.cliqueMatrix_;
7517 rowType_ = rhs.rowType_;
7518 numberColumns_ = rhs.numberColumns_;
7519 numberRows_ = rhs.numberRows_;
7520 numberPossible_ = rhs.numberPossible_;
7521 numberCandidates_ = rhs.numberCandidates_;
7522 firstNot_ = rhs.firstNot_;
7523 numberIn_ = rhs.numberIn_;
7524 left_ = rhs.left_;
7525 lastColumn_ = rhs.lastColumn_;
7526 }
7527 return *this;
7528 }
7529
7530 // Destructor
~CglBK()7531 CglBK::~CglBK()
7532 {
7533 delete[] candidates_;
7534 // only deletes if left_==-1
7535 if (left_ == -1) {
7536 delete[] mark_;
7537 delete[] start_;
7538 delete[] otherColumn_;
7539 delete[] originalRow_;
7540 delete[] dominated_;
7541 delete cliqueMatrix_;
7542 }
7543 }
7544 // For Bron-Kerbosch
bronKerbosch()7545 void CglBK::bronKerbosch()
7546 {
7547 #ifdef BRON_TIMES
7548 numberTimesX++;
7549 if ((numberTimesX % 1000) == 0)
7550 printf("times %d - %d candidates left\n", numberTimesX, numberCandidates_);
7551 #endif
7552 if (!numberCandidates_ && firstNot_ == numberPossible_) {
7553 // mark original rows which are dominated
7554 // save if clique size >2
7555 if (numberIn_ > 2) {
7556 double *elements = new double[numberIn_];
7557 int *column = candidates_ + numberPossible_;
7558 // mark those in clique
7559 for (int i = 0; i < numberIn_; i++) {
7560 int iColumn = column[i];
7561 mark_[iColumn] = 1;
7562 }
7563 for (int i = 0; i < numberIn_; i++) {
7564 elements[i] = 1.0;
7565 int iColumn = column[i];
7566 for (CoinBigIndex j = start_[iColumn]; j < start_[iColumn + 1]; j++) {
7567 int jColumn = otherColumn_[j];
7568 if (mark_[jColumn]) {
7569 int iRow = originalRow_[j];
7570 /* only get rid of <= cliques
7571 can we find dominating clique??
7572 should really look further if dominating clique also ==
7573 or could make that == */
7574 if (rowType_[iRow] == 0)
7575 dominated_[iRow]++;
7576 }
7577 }
7578 }
7579 for (int i = 0; i < numberIn_; i++) {
7580 int iColumn = column[i];
7581 mark_[iColumn] = 0;
7582 }
7583 cliqueMatrix_->appendRow(numberIn_, column, elements);
7584 delete[] elements;
7585 }
7586 } else {
7587 #if 0
7588 int nCplusN=numberCandidates_+(numberPossible_-firstNot_);
7589 int iChoose = CoinDrand48()*nCplusN;
7590 iChoose=CoinMin(0,nCplusN-1);
7591 if (iChoose>=numberCandidates_) {
7592 iChoose -= numberCandidates_;
7593 iChoose += firstNot_;
7594 }
7595 #else
7596 for (int i = 0; i < numberCandidates_; i++) {
7597 int jColumn = candidates_[i];
7598 mark_[jColumn] = 1;
7599 }
7600 int nMax = 0;
7601 int iChoose = 0;
7602 for (int i = numberPossible_ - 1; i >= firstNot_; i--) {
7603 int iColumn = candidates_[i];
7604 int n = 0;
7605 for (CoinBigIndex j = start_[iColumn]; j < start_[iColumn + 1]; j++) {
7606 int jColumn = otherColumn_[j];
7607 n += mark_[jColumn];
7608 }
7609 if (n > nMax) {
7610 nMax = n;
7611 iChoose = i;
7612 }
7613 }
7614 if (nMax < numberCandidates_ - 1 || !nMax) {
7615 for (int i = 0; i < numberCandidates_; i++) {
7616 int iColumn = candidates_[i];
7617 int n = 0;
7618 for (CoinBigIndex j = start_[iColumn]; j < start_[iColumn + 1]; j++) {
7619 int jColumn = otherColumn_[j];
7620 n += mark_[jColumn];
7621 }
7622 if (n > nMax) {
7623 nMax = n;
7624 iChoose = i;
7625 }
7626 }
7627 }
7628 for (int i = 0; i < numberCandidates_; i++) {
7629 int jColumn = candidates_[i];
7630 mark_[jColumn] = 0;
7631 }
7632 #endif
7633 iChoose = candidates_[iChoose];
7634 int *temp = candidates_ + numberPossible_ + numberIn_;
7635 int nTemp = 0;
7636 if (nMax < numberCandidates_) {
7637 // Neighborhood of iColumn
7638 for (CoinBigIndex j = start_[iChoose]; j < start_[iChoose + 1]; j++) {
7639 int jColumn = otherColumn_[j];
7640 mark_[jColumn] = 1;
7641 }
7642 for (int i = 0; i < numberCandidates_; i++) {
7643 int jColumn = candidates_[i];
7644 if (!mark_[jColumn])
7645 temp[nTemp++] = jColumn;
7646 }
7647 for (CoinBigIndex j = start_[iChoose]; j < start_[iChoose + 1]; j++) {
7648 int jColumn = otherColumn_[j];
7649 mark_[jColumn] = 0;
7650 }
7651 }
7652 //if (nMax==numberCandidates_)
7653 //assert (!nTemp);
7654 for (int kk = 0; kk < nTemp; kk++) {
7655 int iColumn = temp[kk];
7656 // move up
7657 int put = 0;
7658 for (int i = 0; i < numberCandidates_; i++) {
7659 if (candidates_[i] != iColumn)
7660 candidates_[put++] = candidates_[i];
7661 }
7662 numberCandidates_--;
7663 CglBK bk2(*this);
7664 int *newCandidates = bk2.candidates_;
7665 #if 0
7666 printf("%p (next %p) iColumn %d, %d candidates %d not %d in\n",
7667 this,&bk2,iColumn,numberCandidates_,
7668 numberPossible_-firstNot_,numberIn_);
7669 for (int i=0;i<numberCandidates_;i++) {
7670 printf(" %d",candidates_[i]);
7671 }
7672 printf("\n");
7673 #endif
7674 newCandidates[numberPossible_ + numberIn_] = iColumn;
7675 bk2.numberIn_ = numberIn_ + 1;
7676 // Neighborhood of iColumn
7677 for (CoinBigIndex j = start_[iColumn]; j < start_[iColumn + 1]; j++) {
7678 int jColumn = otherColumn_[j];
7679 mark_[jColumn] = 1;
7680 }
7681 // Intersection of candidates with neighborhood
7682 int numberCandidates = 0;
7683 for (int i = 0; i < bk2.numberCandidates_; i++) {
7684 int jColumn = newCandidates[i];
7685 if (mark_[jColumn])
7686 newCandidates[numberCandidates++] = jColumn;
7687 }
7688 bk2.numberCandidates_ = numberCandidates;
7689 // Intersection of not with neighborhood
7690 int firstNot = numberPossible_;
7691 for (int i = numberPossible_ - 1; i >= bk2.firstNot_; i--) {
7692 int jColumn = newCandidates[i];
7693 if (mark_[jColumn])
7694 newCandidates[--firstNot] = jColumn;
7695 }
7696 bk2.firstNot_ = firstNot;
7697 for (CoinBigIndex j = start_[iColumn]; j < start_[iColumn + 1]; j++) {
7698 int jColumn = otherColumn_[j];
7699 mark_[jColumn] = 0;
7700 }
7701 //for (int i=0;i<numberColumns_;i++)
7702 //assert (!mark_[i]);
7703 bk2.bronKerbosch();
7704 candidates_[--firstNot_] = iColumn;
7705 }
7706 }
7707 }
7708 // Creates strengthened smaller model
7709 OsiSolverInterface *
newSolver(const OsiSolverInterface & model)7710 CglBK::newSolver(const OsiSolverInterface &model)
7711 {
7712 // See how many rows can be deleted
7713 int nDelete = 0;
7714 int *deleted = new int[numberRows_];
7715 for (int i = 0; i < numberRows_; i++) {
7716 if (dominated_[i]) {
7717 deleted[nDelete++] = i;
7718 }
7719 }
7720 int nAdd = cliqueMatrix_->getNumRows();
7721 #if CBC_USEFUL_PRINTING > 0
7722 printf("%d rows can be deleted with %d new cliques\n",
7723 nDelete, nAdd);
7724 #endif
7725
7726 OsiSolverInterface *newSolver = NULL;
7727 if (nDelete > nAdd) {
7728 newSolver = model.clone();
7729 newSolver->deleteRows(nDelete, deleted);
7730 double *lower = new double[nAdd];
7731 double *upper = new double[nAdd];
7732 for (int i = 0; i < nAdd; i++) {
7733 lower[i] = -COIN_DBL_MAX;
7734 upper[i] = 1.0;
7735 }
7736 const double *elementByRow = cliqueMatrix_->getElements();
7737 const int *column = cliqueMatrix_->getIndices();
7738 const CoinBigIndex *rowStart = cliqueMatrix_->getVectorStarts();
7739 //const int * rowLength = cliqueMatrix_->getVectorLengths();
7740 assert(cliqueMatrix_->getNumElements() == rowStart[nAdd]);
7741 newSolver->addRows(nAdd, rowStart, column, elementByRow, lower, upper);
7742 #if PRINT_DEBUG
7743 for (int i = 0; i < nAdd; i++) {
7744 if (rowStart[i + 1] - rowStart[i] > 10)
7745 printf("Clique %d has %d entries\n", i, rowStart[i + 1] - rowStart[i]);
7746 }
7747 #endif
7748 delete[] lower;
7749 delete[] upper;
7750 }
7751 delete[] deleted;
7752 // mark so everything will be deleted
7753 left_ = -1;
7754 return newSolver;
7755 }
7756 static double multiplier[] = { 1.23456789e2, -9.87654321 };
hashCut(const OsiRowCut & x,int size)7757 static int hashCut(const OsiRowCut &x, int size)
7758 {
7759 int xN = x.row().getNumElements();
7760 double xLb = x.lb();
7761 double xUb = x.ub();
7762 const int *xIndices = x.row().getIndices();
7763 const double *xElements = x.row().getElements();
7764 unsigned int hashValue;
7765 double value = 1.0;
7766 if (xLb > -1.0e10)
7767 value += xLb * multiplier[0];
7768 if (xUb < 1.0e10)
7769 value += xUb * multiplier[1];
7770 for (int j = 0; j < xN; j++) {
7771 int xColumn = xIndices[j];
7772 double xValue = xElements[j];
7773 int k = (j & 1);
7774 value += (j + 1) * multiplier[k] * (xColumn + 1) * xValue;
7775 }
7776 // should be compile time but too lazy for now
7777 if (sizeof(value) > sizeof(hashValue)) {
7778 assert(sizeof(value) == 2 * sizeof(hashValue));
7779 union {
7780 double d;
7781 int i[2];
7782 } xx;
7783 xx.d = value;
7784 hashValue = (xx.i[0] + xx.i[1]);
7785 } else {
7786 assert(sizeof(value) == sizeof(hashValue));
7787 union {
7788 double d;
7789 unsigned int i[2];
7790 } xx;
7791 xx.d = value;
7792 hashValue = xx.i[0];
7793 }
7794 return hashValue % (size);
7795 }
same(const OsiRowCut & x,const OsiRowCut & y)7796 static bool same(const OsiRowCut &x, const OsiRowCut &y)
7797 {
7798 int xN = x.row().getNumElements();
7799 int yN = y.row().getNumElements();
7800 bool identical = false;
7801 if (xN == yN) {
7802 double xLb = x.lb();
7803 double xUb = x.ub();
7804 double yLb = y.lb();
7805 double yUb = y.ub();
7806 if (fabs(xLb - yLb) < 1.0e-8 && fabs(xUb - yUb) < 1.0e-8) {
7807 const int *xIndices = x.row().getIndices();
7808 const double *xElements = x.row().getElements();
7809 const int *yIndices = y.row().getIndices();
7810 const double *yElements = y.row().getElements();
7811 int j;
7812 for (j = 0; j < xN; j++) {
7813 if (xIndices[j] != yIndices[j])
7814 break;
7815 if (fabs(xElements[j] - yElements[j]) > 1.0e-12)
7816 break;
7817 }
7818 identical = (j == xN);
7819 }
7820 }
7821 return identical;
7822 }
CglUniqueRowCuts(int initialMaxSize,int hashMultiplier)7823 CglUniqueRowCuts::CglUniqueRowCuts(int initialMaxSize, int hashMultiplier)
7824 {
7825 numberCuts_ = 0;
7826 size_ = initialMaxSize;
7827 hashMultiplier_ = hashMultiplier;
7828 int hashSize = hashMultiplier_ * size_;
7829 if (size_) {
7830 rowCut_ = new OsiRowCut *[size_];
7831 hash_ = new CglHashLink[hashSize];
7832 } else {
7833 rowCut_ = NULL;
7834 hash_ = NULL;
7835 }
7836 for (int i = 0; i < hashSize; i++) {
7837 hash_[i].index = -1;
7838 hash_[i].next = -1;
7839 }
7840 lastHash_ = -1;
7841 }
~CglUniqueRowCuts()7842 CglUniqueRowCuts::~CglUniqueRowCuts()
7843 {
7844 for (int i = 0; i < numberCuts_; i++)
7845 delete rowCut_[i];
7846 delete[] rowCut_;
7847 delete[] hash_;
7848 }
CglUniqueRowCuts(const CglUniqueRowCuts & rhs)7849 CglUniqueRowCuts::CglUniqueRowCuts(const CglUniqueRowCuts &rhs)
7850 {
7851 numberCuts_ = rhs.numberCuts_;
7852 hashMultiplier_ = rhs.hashMultiplier_;
7853 size_ = rhs.size_;
7854 int hashSize = size_ * hashMultiplier_;
7855 lastHash_ = rhs.lastHash_;
7856 if (size_) {
7857 rowCut_ = new OsiRowCut *[size_];
7858 hash_ = new CglHashLink[hashSize];
7859 for (int i = 0; i < hashSize; i++) {
7860 hash_[i] = rhs.hash_[i];
7861 }
7862 for (int i = 0; i < size_; i++) {
7863 if (rhs.rowCut_[i])
7864 rowCut_[i] = new OsiRowCut(*rhs.rowCut_[i]);
7865 else
7866 rowCut_[i] = NULL;
7867 }
7868 } else {
7869 rowCut_ = NULL;
7870 hash_ = NULL;
7871 }
7872 }
7873 CglUniqueRowCuts &
operator =(const CglUniqueRowCuts & rhs)7874 CglUniqueRowCuts::operator=(const CglUniqueRowCuts &rhs)
7875 {
7876 if (this != &rhs) {
7877 for (int i = 0; i < numberCuts_; i++)
7878 delete rowCut_[i];
7879 delete[] rowCut_;
7880 delete[] hash_;
7881 numberCuts_ = rhs.numberCuts_;
7882 hashMultiplier_ = rhs.hashMultiplier_;
7883 size_ = rhs.size_;
7884 lastHash_ = rhs.lastHash_;
7885 if (size_) {
7886 rowCut_ = new OsiRowCut *[size_];
7887 int hashSize = size_ * hashMultiplier_;
7888 hash_ = new CglHashLink[hashSize];
7889 for (int i = 0; i < hashSize; i++) {
7890 hash_[i] = rhs.hash_[i];
7891 }
7892 for (int i = 0; i < size_; i++) {
7893 if (rhs.rowCut_[i])
7894 rowCut_[i] = new OsiRowCut(*rhs.rowCut_[i]);
7895 else
7896 rowCut_[i] = NULL;
7897 }
7898 } else {
7899 rowCut_ = NULL;
7900 hash_ = NULL;
7901 }
7902 }
7903 return *this;
7904 }
eraseRowCut(int sequence)7905 void CglUniqueRowCuts::eraseRowCut(int sequence)
7906 {
7907 // find
7908 assert(sequence >= 0 && sequence < numberCuts_);
7909 OsiRowCut *cut = rowCut_[sequence];
7910 int hashSize = size_ * hashMultiplier_;
7911 int ipos = hashCut(*cut, hashSize);
7912 int found = -1;
7913 while (true) {
7914 int j1 = hash_[ipos].index;
7915 if (j1 >= 0) {
7916 if (j1 != sequence) {
7917 int k = hash_[ipos].next;
7918 if (k != -1)
7919 ipos = k;
7920 else
7921 break;
7922 } else {
7923 found = j1;
7924 break;
7925 }
7926 } else {
7927 break;
7928 }
7929 }
7930 assert(found >= 0);
7931 assert(hash_[ipos].index == sequence);
7932 // shuffle up
7933 while (hash_[ipos].next >= 0) {
7934 int k = hash_[ipos].next;
7935 hash_[ipos] = hash_[k];
7936 ipos = k;
7937 }
7938 delete cut;
7939 // move last to found
7940 numberCuts_--;
7941 if (numberCuts_) {
7942 ipos = hashCut(*rowCut_[numberCuts_], hashSize);
7943 while (true) {
7944 int j1 = hash_[ipos].index;
7945 if (j1 != numberCuts_) {
7946 int k = hash_[ipos].next;
7947 ipos = k;
7948 } else {
7949 // change
7950 hash_[ipos].index = found;
7951 rowCut_[found] = rowCut_[numberCuts_];
7952 rowCut_[numberCuts_] = NULL;
7953 break;
7954 }
7955 }
7956 }
7957 assert(!rowCut_[numberCuts_]);
7958 }
7959 // Return 0 if added, 1 if not
insertIfNotDuplicate(const OsiRowCut & cut)7960 int CglUniqueRowCuts::insertIfNotDuplicate(const OsiRowCut &cut)
7961 {
7962 int hashSize = size_ * hashMultiplier_;
7963 if (numberCuts_ == size_) {
7964 size_ = 2 * size_ + 100;
7965 hashSize = hashMultiplier_ * size_;
7966 OsiRowCut **temp = new OsiRowCut *[size_];
7967 delete[] hash_;
7968 hash_ = new CglHashLink[hashSize];
7969 for (int i = 0; i < hashSize; i++) {
7970 hash_[i].index = -1;
7971 hash_[i].next = -1;
7972 }
7973 for (int i = 0; i < numberCuts_; i++) {
7974 temp[i] = rowCut_[i];
7975 int ipos = hashCut(*temp[i], hashSize);
7976 int found = -1;
7977 int jpos = ipos;
7978 while (true) {
7979 int j1 = hash_[ipos].index;
7980
7981 if (j1 >= 0) {
7982 if (!same(*temp[i], *temp[j1])) {
7983 int k = hash_[ipos].next;
7984 if (k != -1)
7985 ipos = k;
7986 else
7987 break;
7988 } else {
7989 found = j1;
7990 break;
7991 }
7992 } else {
7993 break;
7994 }
7995 }
7996 if (found < 0) {
7997 assert(hash_[ipos].next == -1);
7998 if (ipos == jpos) {
7999 // first
8000 hash_[ipos].index = i;
8001 } else {
8002 // find next space
8003 while (true) {
8004 ++lastHash_;
8005 assert(lastHash_ < hashSize);
8006 if (hash_[lastHash_].index == -1)
8007 break;
8008 }
8009 hash_[ipos].next = lastHash_;
8010 hash_[lastHash_].index = i;
8011 }
8012 }
8013 }
8014 delete[] rowCut_;
8015 rowCut_ = temp;
8016 }
8017 if (numberCuts_ < size_) {
8018 double newLb = cut.lb();
8019 double newUb = cut.ub();
8020 CoinPackedVector vector = cut.row();
8021 int numberElements = vector.getNumElements();
8022 int *newIndices = vector.getIndices();
8023 double *newElements = vector.getElements();
8024 CoinSort_2(newIndices, newIndices + numberElements, newElements);
8025 int i;
8026 bool bad = false;
8027 for (i = 0; i < numberElements; i++) {
8028 double value = fabs(newElements[i]);
8029 if (value < 1.0e-12 || value > 1.0e12)
8030 bad = true;
8031 }
8032 if (bad)
8033 return 1;
8034 OsiRowCut newCut;
8035 newCut.setLb(newLb);
8036 newCut.setUb(newUb);
8037 newCut.setRow(vector);
8038 int ipos = hashCut(newCut, hashSize);
8039 int found = -1;
8040 int jpos = ipos;
8041 while (true) {
8042 int j1 = hash_[ipos].index;
8043
8044 if (j1 >= 0) {
8045 if (!same(newCut, *rowCut_[j1])) {
8046 int k = hash_[ipos].next;
8047 if (k != -1)
8048 ipos = k;
8049 else
8050 break;
8051 } else {
8052 found = j1;
8053 break;
8054 }
8055 } else {
8056 break;
8057 }
8058 }
8059 if (found < 0) {
8060 assert(hash_[ipos].next == -1);
8061 if (ipos == jpos) {
8062 // first
8063 hash_[ipos].index = numberCuts_;
8064 } else {
8065 // find next space
8066 while (true) {
8067 ++lastHash_;
8068 assert(lastHash_ < hashSize);
8069 if (hash_[lastHash_].index == -1)
8070 break;
8071 }
8072 hash_[ipos].next = lastHash_;
8073 hash_[lastHash_].index = numberCuts_;
8074 }
8075 OsiRowCut *newCutPtr = new OsiRowCut();
8076 newCutPtr->setLb(newLb);
8077 newCutPtr->setUb(newUb);
8078 newCutPtr->setRow(vector);
8079 rowCut_[numberCuts_++] = newCutPtr;
8080 return 0;
8081 } else {
8082 return 1;
8083 }
8084 } else {
8085 return -1;
8086 }
8087 }
8088 // Add in cuts as normal cuts and delete
addCuts(OsiCuts & cs)8089 void CglUniqueRowCuts::addCuts(OsiCuts &cs)
8090 {
8091 for (int i = 0; i < numberCuts_; i++) {
8092 cs.insertIfNotDuplicate(*rowCut_[i]);
8093 delete rowCut_[i];
8094 rowCut_[i] = NULL;
8095 }
8096 numberCuts_ = 0;
8097 }
8098
setTimeLimit(const double timeLimit,const bool useElapsedTime)8099 void CglPreProcess::setTimeLimit(const double timeLimit, const bool useElapsedTime)
8100 {
8101 this->timeLimit_ = timeLimit;
8102 this->useElapsedTime_ = useElapsedTime;
8103 }
8104
setKeepColumnNames(const bool keep)8105 void CglPreProcess::setKeepColumnNames(const bool keep)
8106 {
8107 this->keepColumnNames_ = keep;
8108 }
8109
getCurrentCPUTime() const8110 double CglPreProcess::getCurrentCPUTime() const
8111 {
8112 if (!useElapsedTime_)
8113 return CoinCpuTime();
8114 else
8115 return CoinGetTimeOfDay();
8116 }
8117
8118 // # vim: ts=2 sw=2 et
8119
8120 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
8121 */
8122