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