1 /* $Id$ */
2 // Copyright (C) 2007, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 /*! \file CbcSolverHeuristics.cpp
7     \brief Second level routines for the cbc stand-alone solver.
8 */
9 
10 #include "CbcConfig.h"
11 #include "CoinPragma.hpp"
12 
13 #include "CoinTime.hpp"
14 
15 #include "OsiClpSolverInterface.hpp"
16 
17 #include "ClpPresolve.hpp"
18 
19 #include "CbcOrClpParam.hpp"
20 
21 #include "CbcModel.hpp"
22 
23 #include "CbcHeuristicLocal.hpp"
24 #include "CbcHeuristicPivotAndFix.hpp"
25 //#include "CbcHeuristicPivotAndComplement.hpp"
26 #include "CbcHeuristicRandRound.hpp"
27 #include "CbcHeuristicGreedy.hpp"
28 #include "CbcHeuristicFPump.hpp"
29 #include "CbcHeuristicRINS.hpp"
30 #include "CbcHeuristicDW.hpp"
31 #include "CbcHeuristicVND.hpp"
32 
33 #include "CbcHeuristicDiveCoefficient.hpp"
34 #include "CbcHeuristicDiveFractional.hpp"
35 #include "CbcHeuristicDiveGuided.hpp"
36 #include "CbcHeuristicDiveVectorLength.hpp"
37 #include "CbcHeuristicDivePseudoCost.hpp"
38 #include "CbcHeuristicDiveLineSearch.hpp"
39 
40 #include "CbcStrategy.hpp"
41 #include "OsiAuxInfo.hpp"
42 
43 #include "ClpSimplexOther.hpp"
44 
45 // Crunch down model
crunchIt(ClpSimplex * model)46 void crunchIt(ClpSimplex *model)
47 {
48 #ifdef JJF_ZERO
49   model->dual();
50 #else
51   int numberColumns = model->numberColumns();
52   int numberRows = model->numberRows();
53   // Use dual region
54   double *rhs = model->dualRowSolution();
55   int *whichRow = new int[3 * numberRows];
56   int *whichColumn = new int[2 * numberColumns];
57   int nBound;
58   ClpSimplex *small = static_cast< ClpSimplexOther * >(model)->crunch(rhs, whichRow, whichColumn,
59     nBound, false, false);
60   if (small) {
61     small->dual();
62     if (small->problemStatus() == 0) {
63       model->setProblemStatus(0);
64       static_cast< ClpSimplexOther * >(model)->afterCrunch(*small, whichRow, whichColumn, nBound);
65     } else if (small->problemStatus() != 3) {
66       model->setProblemStatus(1);
67     } else {
68       if (small->problemStatus() == 3) {
69         // may be problems
70         small->computeObjectiveValue();
71         model->setObjectiveValue(small->objectiveValue());
72         model->setProblemStatus(3);
73       } else {
74         model->setProblemStatus(3);
75       }
76     }
77     delete small;
78   } else {
79     model->setProblemStatus(1);
80   }
81   delete[] whichRow;
82   delete[] whichColumn;
83 #endif
84 }
85 /*
86   On input
87   doAction - 0 just fix in original and return NULL
88              1 return fixed non-presolved solver
89              2 as one but use presolve Inside this
90 	     3 use presolve and fix ones with large cost
91              ? do heuristics and set best solution
92 	     ? do BAB and just set best solution
93 	     10+ then use lastSolution and relax a few
94              -2 cleanup afterwards if using 2
95   On output - number fixed
96 */
97 OsiClpSolverInterface *
fixVubs(CbcModel & model,int skipZero2,int & doAction,CoinMessageHandler *,const double * lastSolution,double dextra[6],int extra[5])98 fixVubs(CbcModel &model, int skipZero2,
99   int &doAction,
100   CoinMessageHandler * /*generalMessageHandler*/,
101   const double *lastSolution, double dextra[6],
102   int extra[5])
103 {
104   if (doAction == 11 && !lastSolution)
105     lastSolution = model.bestSolution();
106   assert(((doAction >= 0 && doAction <= 3) && !lastSolution) || (doAction == 11 && lastSolution));
107   double fractionIntFixed = dextra[3];
108   double fractionFixed = dextra[4];
109   double fixAbove = dextra[2];
110   double fixAboveValue = (dextra[5] > 0.0) ? dextra[5] : 1.0;
111 #ifdef COIN_DETAIL
112   double time1 = CoinCpuTime();
113 #endif
114   int leaveIntFree = extra[1];
115   OsiSolverInterface *originalSolver = model.solver();
116   OsiClpSolverInterface *originalClpSolver = dynamic_cast< OsiClpSolverInterface * >(originalSolver);
117   ClpSimplex *originalLpSolver = originalClpSolver->getModelPtr();
118   int *originalColumns = NULL;
119   OsiClpSolverInterface *clpSolver;
120   ClpSimplex *lpSolver;
121   ClpPresolve pinfo;
122   assert(originalSolver->getObjSense() > 0);
123   if (doAction == 2 || doAction == 3) {
124     double *saveLB = NULL;
125     double *saveUB = NULL;
126     int numberColumns = originalLpSolver->numberColumns();
127     if (fixAbove > 0.0) {
128 #ifdef COIN_DETAIL
129       double time1 = CoinCpuTime();
130 #endif
131       originalClpSolver->initialSolve();
132       COIN_DETAIL_PRINT(printf("first solve took %g seconds\n", CoinCpuTime() - time1));
133       double *columnLower = originalLpSolver->columnLower();
134       double *columnUpper = originalLpSolver->columnUpper();
135       const double *solution = originalLpSolver->primalColumnSolution();
136       saveLB = CoinCopyOfArray(columnLower, numberColumns);
137       saveUB = CoinCopyOfArray(columnUpper, numberColumns);
138       const double *objective = originalLpSolver->getObjCoefficients();
139       int iColumn;
140       int nFix = 0;
141       int nArt = 0;
142       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
143         if (objective[iColumn] > fixAbove) {
144           if (solution[iColumn] < columnLower[iColumn] + 1.0e-8) {
145             columnUpper[iColumn] = columnLower[iColumn];
146             nFix++;
147           } else {
148             nArt++;
149           }
150         } else if (objective[iColumn] < -fixAbove) {
151           if (solution[iColumn] > columnUpper[iColumn] - 1.0e-8) {
152             columnLower[iColumn] = columnUpper[iColumn];
153             nFix++;
154           } else {
155             nArt++;
156           }
157         }
158       }
159       COIN_DETAIL_PRINT(printf("%d artificials fixed, %d left as in solution\n", nFix, nArt));
160       lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10);
161       if (!lpSolver || doAction == 2) {
162         // take off fixing in original
163         memcpy(columnLower, saveLB, numberColumns * sizeof(double));
164         memcpy(columnUpper, saveUB, numberColumns * sizeof(double));
165       }
166       delete[] saveLB;
167       delete[] saveUB;
168       if (!lpSolver) {
169         // try again
170         pinfo.destroyPresolve();
171         lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10);
172         assert(lpSolver);
173       }
174     } else {
175       lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10);
176       assert(lpSolver);
177     }
178     clpSolver = new OsiClpSolverInterface(lpSolver, true);
179     assert(lpSolver == clpSolver->getModelPtr());
180     numberColumns = lpSolver->numberColumns();
181     originalColumns = CoinCopyOfArray(pinfo.originalColumns(), numberColumns);
182     doAction = 1;
183   } else {
184     OsiSolverInterface *solver = originalSolver->clone();
185     clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
186     lpSolver = clpSolver->getModelPtr();
187   }
188   // Tighten bounds
189   lpSolver->tightenPrimalBounds(0.0, 11, true);
190   int numberColumns = clpSolver->getNumCols();
191   double *saveColumnLower = CoinCopyOfArray(lpSolver->columnLower(), numberColumns);
192   double *saveColumnUpper = CoinCopyOfArray(lpSolver->columnUpper(), numberColumns);
193   //char generalPrint[200];
194   const double *objective = lpSolver->getObjCoefficients();
195   double *columnLower = lpSolver->columnLower();
196   double *columnUpper = lpSolver->columnUpper();
197   int numberRows = clpSolver->getNumRows();
198   int iRow, iColumn;
199 
200   // Row copy
201   CoinPackedMatrix matrixByRow(*clpSolver->getMatrixByRow());
202   const double *elementByRow = matrixByRow.getElements();
203   const int *column = matrixByRow.getIndices();
204   const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
205   const int *rowLength = matrixByRow.getVectorLengths();
206 
207   // Column copy
208   CoinPackedMatrix matrixByCol(*clpSolver->getMatrixByCol());
209   //const double * element = matrixByCol.getElements();
210   const int *row = matrixByCol.getIndices();
211   const CoinBigIndex *columnStart = matrixByCol.getVectorStarts();
212   const int *columnLength = matrixByCol.getVectorLengths();
213 
214   const double *rowLower = clpSolver->getRowLower();
215   const double *rowUpper = clpSolver->getRowUpper();
216 
217   // Get maximum size of VUB tree
218   // otherColumn is one fixed to 0 if this one zero
219   CoinBigIndex nEl = matrixByCol.getNumElements();
220   CoinBigIndex *fixColumn = new CoinBigIndex[numberColumns + 1];
221   int *otherColumn = new int[nEl];
222   int *fix = new int[numberColumns];
223   char *mark = new char[numberColumns];
224   memset(mark, 0, numberColumns);
225   int numberInteger = 0;
226   int numberOther = 0;
227   fixColumn[0] = 0;
228   double large = lpSolver->largeValue(); // treat bounds > this as infinite
229 #ifndef NDEBUG
230   double large2 = 1.0e10 * large;
231 #endif
232   double tolerance = lpSolver->primalTolerance();
233   int *check = new int[numberRows];
234   for (iRow = 0; iRow < numberRows; iRow++) {
235     check[iRow] = -2; // don't check
236     if (rowLower[iRow] < -1.0e6 && rowUpper[iRow] > 1.0e6)
237       continue; // unlikely
238     // possible row
239     int numberPositive = 0;
240     int iPositive = -1;
241     int numberNegative = 0;
242     int iNegative = -1;
243     CoinBigIndex rStart = rowStart[iRow];
244     CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow];
245     CoinBigIndex j;
246     int kColumn;
247     for (j = rStart; j < rEnd; ++j) {
248       double value = elementByRow[j];
249       kColumn = column[j];
250       if (columnUpper[kColumn] > columnLower[kColumn]) {
251         if (value > 0.0) {
252           numberPositive++;
253           iPositive = kColumn;
254         } else {
255           numberNegative++;
256           iNegative = kColumn;
257         }
258       }
259     }
260     if (numberPositive == 1 && numberNegative == 1)
261       check[iRow] = -1; // try both
262     if (numberPositive == 1 && rowLower[iRow] > -1.0e20)
263       check[iRow] = iPositive;
264     else if (numberNegative == 1 && rowUpper[iRow] < 1.0e20)
265       check[iRow] = iNegative;
266   }
267   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
268     fix[iColumn] = -1;
269     if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) {
270       if (clpSolver->isInteger(iColumn))
271         numberInteger++;
272       if (columnLower[iColumn] == 0.0) {
273         bool infeasible = false;
274         fix[iColumn] = 0;
275         // fake upper bound
276         double saveUpper = columnUpper[iColumn];
277         columnUpper[iColumn] = 0.0;
278         for (CoinBigIndex i = columnStart[iColumn];
279              i < columnStart[iColumn] + columnLength[iColumn]; i++) {
280           iRow = row[i];
281           if (check[iRow] != -1 && check[iRow] != iColumn)
282             continue; // unlikely
283           // possible row
284           int infiniteUpper = 0;
285           int infiniteLower = 0;
286           double maximumUp = 0.0;
287           double maximumDown = 0.0;
288           double newBound;
289           CoinBigIndex rStart = rowStart[iRow];
290           CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow];
291           CoinBigIndex j;
292           int kColumn;
293           // Compute possible lower and upper ranges
294           for (j = rStart; j < rEnd; ++j) {
295             double value = elementByRow[j];
296             kColumn = column[j];
297             if (value > 0.0) {
298               if (columnUpper[kColumn] >= large) {
299                 ++infiniteUpper;
300               } else {
301                 maximumUp += columnUpper[kColumn] * value;
302               }
303               if (columnLower[kColumn] <= -large) {
304                 ++infiniteLower;
305               } else {
306                 maximumDown += columnLower[kColumn] * value;
307               }
308             } else if (value < 0.0) {
309               if (columnUpper[kColumn] >= large) {
310                 ++infiniteLower;
311               } else {
312                 maximumDown += columnUpper[kColumn] * value;
313               }
314               if (columnLower[kColumn] <= -large) {
315                 ++infiniteUpper;
316               } else {
317                 maximumUp += columnLower[kColumn] * value;
318               }
319             }
320           }
321           // Build in a margin of error
322           maximumUp += 1.0e-8 * fabs(maximumUp);
323           maximumDown -= 1.0e-8 * fabs(maximumDown);
324           double maxUp = maximumUp + infiniteUpper * 1.0e31;
325           double maxDown = maximumDown - infiniteLower * 1.0e31;
326           if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) {
327             //printf("Redundant row in vubs %d\n",iRow);
328           } else {
329             if (maxUp < rowLower[iRow] - 100.0 * tolerance || maxDown > rowUpper[iRow] + 100.0 * tolerance) {
330               infeasible = true;
331               break;
332             }
333             double lower = rowLower[iRow];
334             double upper = rowUpper[iRow];
335             for (j = rStart; j < rEnd; ++j) {
336               double value = elementByRow[j];
337               kColumn = column[j];
338               double nowLower = columnLower[kColumn];
339               double nowUpper = columnUpper[kColumn];
340               if (value > 0.0) {
341                 // positive value
342                 if (lower > -large) {
343                   if (!infiniteUpper) {
344                     assert(nowUpper < large2);
345                     newBound = nowUpper + (lower - maximumUp) / value;
346                     // relax if original was large
347                     if (fabs(maximumUp) > 1.0e8)
348                       newBound -= 1.0e-12 * fabs(maximumUp);
349                   } else if (infiniteUpper == 1 && nowUpper > large) {
350                     newBound = (lower - maximumUp) / value;
351                     // relax if original was large
352                     if (fabs(maximumUp) > 1.0e8)
353                       newBound -= 1.0e-12 * fabs(maximumUp);
354                   } else {
355                     newBound = -COIN_DBL_MAX;
356                   }
357                   if (newBound > nowLower + 1.0e-12 && newBound > -large) {
358                     // Tighten the lower bound
359                     // check infeasible (relaxed)
360                     if (nowUpper < newBound) {
361                       if (nowUpper - newBound < -100.0 * tolerance) {
362                         infeasible = true;
363                         break;
364                       }
365                     }
366                   }
367                 }
368                 if (upper < large) {
369                   if (!infiniteLower) {
370                     assert(nowLower > -large2);
371                     newBound = nowLower + (upper - maximumDown) / value;
372                     // relax if original was large
373                     if (fabs(maximumDown) > 1.0e8)
374                       newBound += 1.0e-12 * fabs(maximumDown);
375                   } else if (infiniteLower == 1 && nowLower < -large) {
376                     newBound = (upper - maximumDown) / value;
377                     // relax if original was large
378                     if (fabs(maximumDown) > 1.0e8)
379                       newBound += 1.0e-12 * fabs(maximumDown);
380                   } else {
381                     newBound = COIN_DBL_MAX;
382                   }
383                   if (newBound < nowUpper - 1.0e-12 && newBound < large) {
384                     // Tighten the upper bound
385                     // check infeasible (relaxed)
386                     if (nowLower > newBound) {
387                       if (newBound - nowLower < -100.0 * tolerance) {
388                         infeasible = true;
389                         break;
390                       } else {
391                         newBound = nowLower;
392                       }
393                     }
394                     if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) {
395                       // fix to zero
396                       if (!mark[kColumn]) {
397                         otherColumn[numberOther++] = kColumn;
398                         mark[kColumn] = 1;
399                         if (check[iRow] == -1)
400                           check[iRow] = iColumn;
401                         else
402                           assert(check[iRow] == iColumn);
403                       }
404                     }
405                   }
406                 }
407               } else {
408                 // negative value
409                 if (lower > -large) {
410                   if (!infiniteUpper) {
411                     assert(nowLower < large2);
412                     newBound = nowLower + (lower - maximumUp) / value;
413                     // relax if original was large
414                     if (fabs(maximumUp) > 1.0e8)
415                       newBound += 1.0e-12 * fabs(maximumUp);
416                   } else if (infiniteUpper == 1 && nowLower < -large) {
417                     newBound = (lower - maximumUp) / value;
418                     // relax if original was large
419                     if (fabs(maximumUp) > 1.0e8)
420                       newBound += 1.0e-12 * fabs(maximumUp);
421                   } else {
422                     newBound = COIN_DBL_MAX;
423                   }
424                   if (newBound < nowUpper - 1.0e-12 && newBound < large) {
425                     // Tighten the upper bound
426                     // check infeasible (relaxed)
427                     if (nowLower > newBound) {
428                       if (newBound - nowLower < -100.0 * tolerance) {
429                         infeasible = true;
430                         break;
431                       } else {
432                         newBound = nowLower;
433                       }
434                     }
435                     if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) {
436                       // fix to zero
437                       if (!mark[kColumn]) {
438                         otherColumn[numberOther++] = kColumn;
439                         mark[kColumn] = 1;
440                         if (check[iRow] == -1)
441                           check[iRow] = iColumn;
442                         else
443                           assert(check[iRow] == iColumn);
444                       }
445                     }
446                   }
447                 }
448                 if (upper < large) {
449                   if (!infiniteLower) {
450                     assert(nowUpper < large2);
451                     newBound = nowUpper + (upper - maximumDown) / value;
452                     // relax if original was large
453                     if (fabs(maximumDown) > 1.0e8)
454                       newBound -= 1.0e-12 * fabs(maximumDown);
455                   } else if (infiniteLower == 1 && nowUpper > large) {
456                     newBound = (upper - maximumDown) / value;
457                     // relax if original was large
458                     if (fabs(maximumDown) > 1.0e8)
459                       newBound -= 1.0e-12 * fabs(maximumDown);
460                   } else {
461                     newBound = -COIN_DBL_MAX;
462                   }
463                   if (newBound > nowLower + 1.0e-12 && newBound > -large) {
464                     // Tighten the lower bound
465                     // check infeasible (relaxed)
466                     if (nowUpper < newBound) {
467                       if (nowUpper - newBound < -100.0 * tolerance) {
468                         infeasible = true;
469                         break;
470                       }
471                     }
472                   }
473                 }
474               }
475             }
476           }
477         }
478         for (CoinBigIndex i = fixColumn[iColumn]; i < numberOther; i++)
479           mark[otherColumn[i]] = 0;
480         // reset bound unless infeasible
481         if (!infeasible || !clpSolver->isInteger(iColumn))
482           columnUpper[iColumn] = saveUpper;
483         else if (clpSolver->isInteger(iColumn))
484           columnLower[iColumn] = 1.0;
485       }
486     }
487     fixColumn[iColumn + 1] = numberOther;
488   }
489   delete[] check;
490   delete[] mark;
491   // Now do reverse way
492   int *counts = new int[numberColumns];
493   CoinZeroN(counts, numberColumns);
494   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
495     for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++)
496       counts[otherColumn[i]]++;
497   }
498   numberOther = 0;
499   CoinBigIndex *fixColumn2 = new CoinBigIndex[numberColumns + 1];
500   int *otherColumn2 = new int[fixColumn[numberColumns]];
501   fixColumn2[0] = 0;
502   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
503     numberOther += counts[iColumn];
504     counts[iColumn] = 0;
505     fixColumn2[iColumn + 1] = numberOther;
506   }
507   // Create other way
508   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
509     for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) {
510       int jColumn = otherColumn[i];
511       CoinBigIndex put = fixColumn2[jColumn] + counts[jColumn];
512       counts[jColumn]++;
513       otherColumn2[put] = iColumn;
514     }
515   }
516   // get top layer i.e. those which are not fixed by any other
517   int kLayer = 0;
518   while (true) {
519     int numberLayered = 0;
520     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
521       if (fix[iColumn] == kLayer) {
522         for (CoinBigIndex i = fixColumn2[iColumn]; i < fixColumn2[iColumn + 1]; i++) {
523           int jColumn = otherColumn2[i];
524           if (fix[jColumn] == kLayer) {
525             fix[iColumn] = kLayer + 100;
526           }
527         }
528       }
529       if (fix[iColumn] == kLayer) {
530         numberLayered++;
531       }
532     }
533     if (numberLayered) {
534       kLayer += 100;
535     } else {
536       break;
537     }
538   }
539   for (int iPass = 0; iPass < 2; iPass++) {
540     for (int jLayer = 0; jLayer < kLayer; jLayer++) {
541       int check[] = { -1, 0, 1, 2, 3, 4, 5, 10, 50, 100, 500, 1000, 5000, 10000, COIN_INT_MAX };
542       int nCheck = static_cast< int >(sizeof(check) / sizeof(int));
543       int countsI[20];
544       int countsC[20];
545       assert(nCheck <= 20);
546       memset(countsI, 0, nCheck * sizeof(int));
547       memset(countsC, 0, nCheck * sizeof(int));
548       check[nCheck - 1] = numberColumns;
549       int numberLayered = 0;
550       int numberInteger = 0;
551       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
552         if (fix[iColumn] == jLayer) {
553           numberLayered++;
554           int nFix = static_cast< int >(fixColumn[iColumn + 1] - fixColumn[iColumn]);
555           if (iPass) {
556             // just integers
557             nFix = 0;
558             for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) {
559               int jColumn = otherColumn[i];
560               if (clpSolver->isInteger(jColumn))
561                 nFix++;
562             }
563           }
564           int iFix;
565           for (iFix = 0; iFix < nCheck; iFix++) {
566             if (nFix <= check[iFix])
567               break;
568           }
569           assert(iFix < nCheck);
570           if (clpSolver->isInteger(iColumn)) {
571             numberInteger++;
572             countsI[iFix]++;
573           } else {
574             countsC[iFix]++;
575           }
576         }
577       }
578 #ifdef COIN_DETAIL
579       if (numberLayered) {
580         printf("%d (%d integer) at priority %d\n", numberLayered, numberInteger, 1 + (jLayer / 100));
581         char buffer[50];
582         for (int i = 1; i < nCheck; i++) {
583           if (countsI[i] || countsC[i]) {
584             if (i == 1)
585               sprintf(buffer, " ==    zero            ");
586             else if (i < nCheck - 1)
587               sprintf(buffer, "> %6d and <= %6d ", check[i - 1], check[i]);
588             else
589               sprintf(buffer, "> %6d                ", check[i - 1]);
590             printf("%s %8d integers and %8d continuous\n", buffer, countsI[i], countsC[i]);
591           }
592         }
593       }
594 #endif
595     }
596   }
597   delete[] counts;
598   // Now do fixing
599   {
600     // switch off presolve and up weight
601     ClpSolve solveOptions;
602     //solveOptions.setPresolveType(ClpSolve::presolveOff,0);
603     solveOptions.setSolveType(ClpSolve::usePrimalorSprint);
604     //solveOptions.setSpecialOption(1,3,30); // sprint
605     int numberColumns = lpSolver->numberColumns();
606     int iColumn;
607     bool allSlack = true;
608     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
609       if (lpSolver->getColumnStatus(iColumn) == ClpSimplex::basic) {
610         allSlack = false;
611         break;
612       }
613     }
614     if (allSlack)
615       solveOptions.setSpecialOption(1, 2, 50); // idiot
616     lpSolver->setInfeasibilityCost(1.0e11);
617     lpSolver->defaultFactorizationFrequency();
618     if (doAction != 11)
619       lpSolver->initialSolve(solveOptions);
620     double *columnLower = lpSolver->columnLower();
621     double *columnUpper = lpSolver->columnUpper();
622     double *fullSolution = lpSolver->primalColumnSolution();
623     const double *dj = lpSolver->dualColumnSolution();
624     int iPass = 0;
625 #define MAXPROB 2
626     ClpSimplex models[MAXPROB];
627     int kPass = -1;
628     int kLayer = 0;
629     int skipZero = 0;
630     if (skipZero2 == -1)
631       skipZero2 = 40; //-1;
632     /* 0 fixed to 0 by choice
633            1 lb of 1 by choice
634            2 fixed to 0 by another
635            3 as 2 but this go
636            -1 free
637         */
638     char *state = new char[numberColumns];
639     for (iColumn = 0; iColumn < numberColumns; iColumn++)
640       state[iColumn] = -1;
641     while (true) {
642       double largest = -0.1;
643       double smallest = 1.1;
644       int iLargest = -1;
645       int iSmallest = -1;
646       int atZero = 0;
647       int atOne = 0;
648       int toZero = 0;
649       int toOne = 0;
650       int numberFree = 0;
651       int numberGreater = 0;
652       columnLower = lpSolver->columnLower();
653       columnUpper = lpSolver->columnUpper();
654       fullSolution = lpSolver->primalColumnSolution();
655       if (doAction == 11) {
656         {
657           double *columnLower = lpSolver->columnLower();
658           double *columnUpper = lpSolver->columnUpper();
659           //	  lpSolver->dual();
660           memcpy(columnLower, saveColumnLower, numberColumns * sizeof(double));
661           memcpy(columnUpper, saveColumnUpper, numberColumns * sizeof(double));
662           //	  lpSolver->dual();
663           int iColumn;
664           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
665             if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) {
666               if (clpSolver->isInteger(iColumn)) {
667                 double value = lastSolution[iColumn];
668                 int iValue = static_cast< int >(value + 0.5);
669                 assert(fabs(value - static_cast< double >(iValue)) < 1.0e-3);
670                 assert(iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]);
671                 columnLower[iColumn] = iValue;
672                 columnUpper[iColumn] = iValue;
673               }
674             }
675           }
676           lpSolver->initialSolve(solveOptions);
677           memcpy(columnLower, saveColumnLower, numberColumns * sizeof(double));
678           memcpy(columnUpper, saveColumnUpper, numberColumns * sizeof(double));
679         }
680         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
681           if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) {
682             if (clpSolver->isInteger(iColumn)) {
683               double value = lastSolution[iColumn];
684               int iValue = static_cast< int >(value + 0.5);
685               assert(fabs(value - static_cast< double >(iValue)) < 1.0e-3);
686               assert(iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]);
687               if (!fix[iColumn]) {
688                 if (iValue == 0) {
689                   state[iColumn] = 0;
690                   assert(!columnLower[iColumn]);
691                   columnUpper[iColumn] = 0.0;
692                 } else if (iValue == 1) {
693                   state[iColumn] = 1;
694                   columnLower[iColumn] = 1.0;
695                 } else {
696                   // leave fixed
697                   columnLower[iColumn] = iValue;
698                   columnUpper[iColumn] = iValue;
699                 }
700               } else if (iValue == 0) {
701                 state[iColumn] = 10;
702                 columnUpper[iColumn] = 0.0;
703               } else {
704                 // leave fixed
705                 columnLower[iColumn] = iValue;
706                 columnUpper[iColumn] = iValue;
707               }
708             }
709           }
710         }
711         int jLayer = 0;
712         int nFixed = -1;
713         int nTotalFixed = 0;
714         while (nFixed) {
715           nFixed = 0;
716           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
717             if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) {
718               for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) {
719                 int jColumn = otherColumn[i];
720                 if (columnUpper[jColumn]) {
721                   bool canFix = true;
722                   for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) {
723                     int kColumn = otherColumn2[k];
724                     if (state[kColumn] == 1) {
725                       canFix = false;
726                       break;
727                     }
728                   }
729                   if (canFix) {
730                     columnUpper[jColumn] = 0.0;
731                     nFixed++;
732                   }
733                 }
734               }
735             }
736           }
737           nTotalFixed += nFixed;
738           jLayer += 100;
739         }
740         COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed));
741         break;
742       }
743       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
744         if (!clpSolver->isInteger(iColumn) || fix[iColumn] > kLayer)
745           continue;
746         // skip if fixes nothing
747         if (fixColumn[iColumn + 1] - fixColumn[iColumn] <= skipZero2)
748           continue;
749         double value = fullSolution[iColumn];
750         if (value > 1.00001) {
751           numberGreater++;
752           continue;
753         }
754         double lower = columnLower[iColumn];
755         double upper = columnUpper[iColumn];
756         if (lower == upper) {
757           if (lower)
758             atOne++;
759           else
760             atZero++;
761           continue;
762         }
763         if (value < 1.0e-7) {
764           toZero++;
765           columnUpper[iColumn] = 0.0;
766           state[iColumn] = 10;
767           continue;
768         }
769         if (value > 1.0 - 1.0e-7) {
770           toOne++;
771           columnLower[iColumn] = 1.0;
772           state[iColumn] = 1;
773           continue;
774         }
775         numberFree++;
776         // skip if fixes nothing
777         if (fixColumn[iColumn + 1] - fixColumn[iColumn] <= skipZero)
778           continue;
779         if (value < smallest) {
780           smallest = value;
781           iSmallest = iColumn;
782         }
783         if (value > largest) {
784           largest = value;
785           iLargest = iColumn;
786         }
787       }
788       if (toZero || toOne)
789         COIN_DETAIL_PRINT(printf("%d at 0 fixed and %d at one fixed\n", toZero, toOne));
790       COIN_DETAIL_PRINT(printf("%d variables free, %d fixed to 0, %d to 1 - smallest %g, largest %g\n",
791         numberFree, atZero, atOne, smallest, largest));
792       if (numberGreater && !iPass)
793         COIN_DETAIL_PRINT(printf("%d variables have value > 1.0\n", numberGreater));
794       //skipZero2=0; // leave 0 fixing
795       int jLayer = 0;
796       int nFixed = -1;
797       int nTotalFixed = 0;
798       while (nFixed) {
799         nFixed = 0;
800         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
801           if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) {
802             for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) {
803               int jColumn = otherColumn[i];
804               if (columnUpper[jColumn]) {
805                 bool canFix = true;
806                 for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) {
807                   int kColumn = otherColumn2[k];
808                   if (state[kColumn] == 1) {
809                     canFix = false;
810                     break;
811                   }
812                 }
813                 if (canFix) {
814                   columnUpper[jColumn] = 0.0;
815                   nFixed++;
816                 }
817               }
818             }
819           }
820         }
821         nTotalFixed += nFixed;
822         jLayer += 100;
823       }
824       COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed));
825       if (iLargest < 0 || numberFree <= leaveIntFree)
826         break;
827       double movement;
828       int way;
829       if (smallest <= 1.0 - largest && smallest < 0.2 && largest < fixAboveValue) {
830         columnUpper[iSmallest] = 0.0;
831         state[iSmallest] = 0;
832         movement = smallest;
833         way = -1;
834       } else {
835         columnLower[iLargest] = 1.0;
836         state[iLargest] = 1;
837         movement = 1.0 - largest;
838         way = 1;
839       }
840       double saveObj = lpSolver->objectiveValue();
841       iPass++;
842       kPass = iPass % MAXPROB;
843       models[kPass] = *lpSolver;
844       if (way == -1) {
845         // fix others
846         for (CoinBigIndex i = fixColumn[iSmallest]; i < fixColumn[iSmallest + 1]; i++) {
847           int jColumn = otherColumn[i];
848           if (state[jColumn] == -1) {
849             columnUpper[jColumn] = 0.0;
850             state[jColumn] = 3;
851           }
852         }
853       }
854       double maxCostUp = COIN_DBL_MAX;
855       objective = lpSolver->getObjCoefficients();
856       if (way == -1)
857         maxCostUp = (1.0 - movement) * objective[iSmallest];
858       lpSolver->setDualObjectiveLimit(saveObj + maxCostUp);
859       crunchIt(lpSolver);
860       double moveObj = lpSolver->objectiveValue() - saveObj;
861       COIN_DETAIL_PRINT(printf("movement %s was %g costing %g\n",
862         (way == -1) ? "down" : "up", movement, moveObj));
863       if (way == -1 && (moveObj >= maxCostUp || lpSolver->status())) {
864         // go up
865         columnLower = models[kPass].columnLower();
866         columnUpper = models[kPass].columnUpper();
867         columnLower[iSmallest] = 1.0;
868         columnUpper[iSmallest] = saveColumnUpper[iSmallest];
869         *lpSolver = models[kPass];
870         columnLower = lpSolver->columnLower();
871         columnUpper = lpSolver->columnUpper();
872         fullSolution = lpSolver->primalColumnSolution();
873         dj = lpSolver->dualColumnSolution();
874         columnLower[iSmallest] = 1.0;
875         columnUpper[iSmallest] = saveColumnUpper[iSmallest];
876         state[iSmallest] = 1;
877         // unfix others
878         for (CoinBigIndex i = fixColumn[iSmallest]; i < fixColumn[iSmallest + 1]; i++) {
879           int jColumn = otherColumn[i];
880           if (state[jColumn] == 3) {
881             columnUpper[jColumn] = saveColumnUpper[jColumn];
882             state[jColumn] = -1;
883           }
884         }
885         crunchIt(lpSolver);
886       }
887       models[kPass] = *lpSolver;
888     }
889     lpSolver->dual();
890     COIN_DETAIL_PRINT(printf("Fixing took %g seconds\n", CoinCpuTime() - time1));
891     columnLower = lpSolver->columnLower();
892     columnUpper = lpSolver->columnUpper();
893     fullSolution = lpSolver->primalColumnSolution();
894     dj = lpSolver->dualColumnSolution();
895     int *sort = new int[numberColumns];
896     double *dsort = new double[numberColumns];
897     int chunk = 20;
898     int iRelax = 0;
899     //double fractionFixed=6.0/8.0;
900     // relax while lots fixed
901     while (true) {
902       if (skipZero2 > 10 && doAction < 10)
903         break;
904       iRelax++;
905       int n = 0;
906       double sum0 = 0.0;
907       double sum00 = 0.0;
908       double sum1 = 0.0;
909       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
910         if (!clpSolver->isInteger(iColumn) || fix[iColumn] > kLayer)
911           continue;
912         // skip if fixes nothing
913         if (fixColumn[iColumn + 1] - fixColumn[iColumn] == 0 && doAction < 10)
914           continue;
915         double djValue = dj[iColumn];
916         if (state[iColumn] == 1) {
917           assert(columnLower[iColumn]);
918           assert(fullSolution[iColumn] > 0.1);
919           if (djValue > 0.0) {
920             //printf("YY dj of %d at %g is %g\n",iColumn,value,djValue);
921             sum1 += djValue;
922             sort[n] = iColumn;
923             dsort[n++] = -djValue;
924           } else {
925             //printf("dj of %d at %g is %g\n",iColumn,value,djValue);
926           }
927         } else if (state[iColumn] == 0 || state[iColumn] == 10) {
928           assert(fullSolution[iColumn] < 0.1);
929           assert(!columnUpper[iColumn]);
930           double otherValue = 0.0;
931           int nn = 0;
932           for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) {
933             int jColumn = otherColumn[i];
934             if (columnUpper[jColumn] == 0.0) {
935               if (dj[jColumn] < -1.0e-5) {
936                 nn++;
937                 otherValue += dj[jColumn]; // really need to look at rest
938               }
939             }
940           }
941           if (djValue < -1.0e-2 || otherValue < -1.0e-2) {
942             //printf("XX dj of %d at %g is %g - %d out of %d contribute %g\n",iColumn,value,djValue,
943             // nn,fixColumn[iColumn+1]-fixColumn[iColumn],otherValue);
944             if (djValue < 1.0e-8) {
945               sum0 -= djValue;
946               sum00 -= otherValue;
947               sort[n] = iColumn;
948               if (djValue < -1.0e-2)
949                 dsort[n++] = djValue + otherValue;
950               else
951                 dsort[n++] = djValue + 0.001 * otherValue;
952             }
953           } else {
954             //printf("dj of %d at %g is %g - no contribution from %d\n",iColumn,value,djValue,
955             //   fixColumn[iColumn+1]-fixColumn[iColumn]);
956           }
957         }
958       }
959       CoinSort_2(dsort, dsort + n, sort);
960       double *originalColumnLower = saveColumnLower;
961       double *originalColumnUpper = saveColumnUpper;
962       double *lo = CoinCopyOfArray(columnLower, numberColumns);
963       double *up = CoinCopyOfArray(columnUpper, numberColumns);
964       for (int k = 0; k < CoinMin(chunk, n); k++) {
965         iColumn = sort[k];
966         state[iColumn] = -2;
967       }
968       memcpy(columnLower, originalColumnLower, numberColumns * sizeof(double));
969       memcpy(columnUpper, originalColumnUpper, numberColumns * sizeof(double));
970       int nFixed = 0;
971       int nFixed0 = 0;
972       int nFixed1 = 0;
973       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
974         if (state[iColumn] == 0 || state[iColumn] == 10) {
975           columnUpper[iColumn] = 0.0;
976           assert(lo[iColumn] == 0.0);
977           nFixed++;
978           nFixed0++;
979           for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) {
980             int jColumn = otherColumn[i];
981             if (columnUpper[jColumn]) {
982               bool canFix = true;
983               for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) {
984                 int kColumn = otherColumn2[k];
985                 if (state[kColumn] == 1 || state[kColumn] == -2) {
986                   canFix = false;
987                   break;
988                 }
989               }
990               if (canFix) {
991                 columnUpper[jColumn] = 0.0;
992                 assert(lo[jColumn] == 0.0);
993                 nFixed++;
994               }
995             }
996           }
997         } else if (state[iColumn] == 1) {
998           columnLower[iColumn] = 1.0;
999           nFixed1++;
1000         }
1001       }
1002       COIN_DETAIL_PRINT(printf("%d fixed %d orig 0 %d 1\n", nFixed, nFixed0, nFixed1));
1003       int jLayer = 0;
1004       nFixed = -1;
1005       int nTotalFixed = 0;
1006       while (nFixed) {
1007         nFixed = 0;
1008         for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1009           if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) {
1010             for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) {
1011               int jColumn = otherColumn[i];
1012               if (columnUpper[jColumn]) {
1013                 bool canFix = true;
1014                 for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) {
1015                   int kColumn = otherColumn2[k];
1016                   if (state[kColumn] == 1 || state[kColumn] == -2) {
1017                     canFix = false;
1018                     break;
1019                   }
1020                 }
1021                 if (canFix) {
1022                   columnUpper[jColumn] = 0.0;
1023                   assert(lo[jColumn] == 0.0);
1024                   nFixed++;
1025                 }
1026               }
1027             }
1028           }
1029         }
1030         nTotalFixed += nFixed;
1031         jLayer += 100;
1032       }
1033       nFixed = 0;
1034       int nFixedI = 0;
1035       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1036         if (columnLower[iColumn] == columnUpper[iColumn]) {
1037           if (clpSolver->isInteger(iColumn))
1038             nFixedI++;
1039           nFixed++;
1040         }
1041       }
1042       COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities - total %d (%d integer) - all target %d, int target %d\n",
1043         nTotalFixed, nFixed, nFixedI, static_cast< int >(fractionFixed * numberColumns), static_cast< int >(fractionIntFixed * numberInteger)));
1044       int nBad = 0;
1045       int nRelax = 0;
1046       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1047         if (lo[iColumn] < columnLower[iColumn] || up[iColumn] > columnUpper[iColumn]) {
1048           COIN_DETAIL_PRINT(printf("bad %d old %g %g, new %g %g\n", iColumn, lo[iColumn], up[iColumn],
1049             columnLower[iColumn], columnUpper[iColumn]));
1050           nBad++;
1051         }
1052         if (lo[iColumn] > columnLower[iColumn] || up[iColumn] < columnUpper[iColumn]) {
1053           nRelax++;
1054         }
1055       }
1056       COIN_DETAIL_PRINT(printf("%d relaxed\n", nRelax));
1057       if (iRelax > 20 && nRelax == chunk)
1058         nRelax = 0;
1059       if (iRelax > 50)
1060         nRelax = 0;
1061       assert(!nBad);
1062       delete[] lo;
1063       delete[] up;
1064       lpSolver->primal(1);
1065       if (nFixed < fractionFixed * numberColumns || nFixedI < fractionIntFixed * numberInteger || !nRelax)
1066         break;
1067     }
1068     delete[] state;
1069     delete[] sort;
1070     delete[] dsort;
1071   }
1072   delete[] fix;
1073   delete[] fixColumn;
1074   delete[] otherColumn;
1075   delete[] otherColumn2;
1076   delete[] fixColumn2;
1077   // See if was presolved
1078   if (originalColumns) {
1079     columnLower = lpSolver->columnLower();
1080     columnUpper = lpSolver->columnUpper();
1081     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1082       saveColumnLower[iColumn] = columnLower[iColumn];
1083       saveColumnUpper[iColumn] = columnUpper[iColumn];
1084     }
1085     pinfo.postsolve(true);
1086     columnLower = originalLpSolver->columnLower();
1087     columnUpper = originalLpSolver->columnUpper();
1088     double *newColumnLower = lpSolver->columnLower();
1089     double *newColumnUpper = lpSolver->columnUpper();
1090     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1091       int jColumn = originalColumns[iColumn];
1092       columnLower[jColumn] = CoinMax(columnLower[jColumn], newColumnLower[iColumn]);
1093       columnUpper[jColumn] = CoinMin(columnUpper[jColumn], newColumnUpper[iColumn]);
1094     }
1095     numberColumns = originalLpSolver->numberColumns();
1096     delete[] originalColumns;
1097   }
1098   delete[] saveColumnLower;
1099   delete[] saveColumnUpper;
1100   if (!originalColumns) {
1101     // Basis
1102     memcpy(originalLpSolver->statusArray(), lpSolver->statusArray(), numberRows + numberColumns);
1103     memcpy(originalLpSolver->primalColumnSolution(), lpSolver->primalColumnSolution(), numberColumns * sizeof(double));
1104     memcpy(originalLpSolver->primalRowSolution(), lpSolver->primalRowSolution(), numberRows * sizeof(double));
1105     // Fix in solver
1106     columnLower = lpSolver->columnLower();
1107     columnUpper = lpSolver->columnUpper();
1108   }
1109   double *originalColumnLower = originalLpSolver->columnLower();
1110   double *originalColumnUpper = originalLpSolver->columnUpper();
1111   // number fixed
1112   doAction = 0;
1113   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1114     originalColumnLower[iColumn] = columnLower[iColumn];
1115     originalColumnUpper[iColumn] = columnUpper[iColumn];
1116     if (columnLower[iColumn] == columnUpper[iColumn])
1117       doAction++;
1118   }
1119   COIN_DETAIL_PRINT(printf("%d fixed by vub preprocessing\n", doAction));
1120   if (originalColumns) {
1121     originalLpSolver->initialSolve();
1122   }
1123   delete clpSolver;
1124   return NULL;
1125 }
1126 
doHeuristics(CbcModel * model,int type,std::vector<CbcOrClpParam> parameters_,int noPrinting_,int initialPumpTune)1127 int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > parameters_,
1128   int noPrinting_, int initialPumpTune)
1129 {
1130 #ifdef JJF_ZERO //NEW_STYLE_SOLVER==0
1131   CbcOrClpParam *parameters_ = parameters;
1132   int numberParameters_ = numberParameters;
1133   bool noPrinting_ = noPrinting_;
1134 #endif
1135   char generalPrint[10000];
1136   CoinMessages generalMessages = model->messages();
1137   CoinMessageHandler *generalMessageHandler = model->messageHandler();
1138   //generalMessageHandler->setPrefix(false);
1139   bool anyToDo = false;
1140   int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].intValue();
1141   int useFpump = parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].currentOptionAsInteger();
1142   int useRounding = parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].currentOptionAsInteger();
1143   int useGreedy = parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].currentOptionAsInteger();
1144   int useCombine = parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].currentOptionAsInteger();
1145   int useProximity = parameters_[whichParam(CBC_PARAM_STR_PROXIMITY, parameters_)].currentOptionAsInteger();
1146   int useCrossover = parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters_)].currentOptionAsInteger();
1147   //int usePivotC = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters_)].currentOptionAsInteger();
1148   int usePivotF = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters_)].currentOptionAsInteger();
1149   int useRand = parameters_[whichParam(CBC_PARAM_STR_RANDROUND, parameters_)].currentOptionAsInteger();
1150   int useRINS = parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].currentOptionAsInteger();
1151   int useRENS = parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].currentOptionAsInteger();
1152   int useVND = parameters_[whichParam(CBC_PARAM_STR_VND, parameters_)].currentOptionAsInteger();
1153   int useDINS = parameters_[whichParam(CBC_PARAM_STR_DINS, parameters_)].currentOptionAsInteger();
1154   int useDIVING2 = parameters_[whichParam(CBC_PARAM_STR_DIVINGS, parameters_)].currentOptionAsInteger();
1155   int useNaive = parameters_[whichParam(CBC_PARAM_STR_NAIVE, parameters_)].currentOptionAsInteger();
1156   int useDW = parameters_[whichParam(CBC_PARAM_STR_DW, parameters_)].currentOptionAsInteger();
1157   int kType = (type < 10) ? type : 1;
1158   assert(kType == 1 || kType == 2);
1159   // FPump done first as it only works if no solution
1160   if (useFpump >= kType && useFpump <= kType + 1) {
1161     anyToDo = true;
1162     CbcHeuristicFPump heuristic4(*model);
1163     double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_SMALLBAB, parameters_)].doubleValue();
1164     heuristic4.setFractionSmall(dextra3);
1165     double dextra1 = parameters_[whichParam(CBC_PARAM_DBL_ARTIFICIALCOST, parameters_)].doubleValue();
1166     if (dextra1)
1167       heuristic4.setArtificialCost(dextra1);
1168     heuristic4.setMaximumPasses(parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, parameters_)].intValue());
1169     if (parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, parameters_)].intValue() == 21)
1170       heuristic4.setIterationRatio(1.0);
1171     int pumpTune = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_)].intValue();
1172     int pumpTune2 = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE2, parameters_)].intValue();
1173     if (pumpTune > 0) {
1174       bool printStuff = (pumpTune != initialPumpTune || logLevel > 1 || pumpTune2 > 0)
1175         && !noPrinting_;
1176       if (printStuff) {
1177         generalMessageHandler->message(CBC_GENERAL, generalMessages)
1178           << "Options for feasibility pump - "
1179           << CoinMessageEol;
1180       }
1181       /*
1182             >=10000000 for using obj
1183             >=1000000 use as accumulate switch
1184             >=1000 use index+1 as number of large loops
1185             >=100 use dextra1 as cutoff
1186             %100 == 10,20 etc for experimentation
1187             1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds
1188             4 and static continuous, 5 as 3 but no internal integers
1189             6 as 3 but all slack basis!
1190             */
1191       double value = model->solver()->getObjSense() * model->solver()->getObjValue();
1192       int w = pumpTune / 10;
1193       int i = w % 10;
1194       w /= 10;
1195       int c = w % 10;
1196       w /= 10;
1197       int r = w;
1198       int accumulate = r / 1000;
1199       r -= 1000 * accumulate;
1200       if (accumulate >= 100) {
1201         int which = accumulate / 100;
1202         accumulate -= 100 * which;
1203         which--;
1204         // weights and factors
1205         double weight[] = { 0.01, 0.01, 0.1, 0.1, 0.5, 0.5, 1.0, 1.0, 5.0, 5.0 };
1206         double factor[] = { 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5 };
1207         heuristic4.setInitialWeight(weight[which]);
1208         heuristic4.setWeightFactor(factor[which]);
1209         if (printStuff) {
1210           sprintf(generalPrint, "Initial weight for objective %g, decay factor %g",
1211             weight[which], factor[which]);
1212           generalMessageHandler->message(CBC_GENERAL, generalMessages)
1213             << generalPrint
1214             << CoinMessageEol;
1215         }
1216       }
1217       // fake cutoff
1218       if (c) {
1219         double cutoff;
1220         model->solver()->getDblParam(OsiDualObjectiveLimit, cutoff);
1221         cutoff = CoinMin(cutoff, value + 0.05 * fabs(value) * c);
1222         double fakeCutoff = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue();
1223         if (fakeCutoff)
1224           cutoff = fakeCutoff;
1225         heuristic4.setFakeCutoff(cutoff);
1226         if (printStuff) {
1227           sprintf(generalPrint, "Fake cutoff of %g", cutoff);
1228           generalMessageHandler->message(CBC_GENERAL, generalMessages)
1229             << generalPrint
1230             << CoinMessageEol;
1231         }
1232       }
1233       int offRandomEtc = 0;
1234       if (pumpTune2) {
1235         if ((pumpTune2 / 1000) != 0) {
1236           offRandomEtc = 1000000 * (pumpTune2 / 1000);
1237           if (printStuff) {
1238             generalMessageHandler->message(CBC_GENERAL, generalMessages)
1239               << "Feasibility pump may run twice"
1240               << CoinMessageEol;
1241           }
1242           pumpTune2 = pumpTune2 % 1000;
1243         }
1244         if ((pumpTune2 / 100) != 0) {
1245           offRandomEtc += 100 * (pumpTune2 / 100);
1246           if (printStuff) {
1247             generalMessageHandler->message(CBC_GENERAL, generalMessages)
1248               << "Not using randomized objective"
1249               << CoinMessageEol;
1250           }
1251         }
1252         int maxAllowed = pumpTune2 % 100;
1253         if (maxAllowed) {
1254           offRandomEtc += 1000 * maxAllowed;
1255           if (printStuff) {
1256             sprintf(generalPrint, "Fixing if same for %d passes",
1257               maxAllowed);
1258             generalMessageHandler->message(CBC_GENERAL, generalMessages)
1259               << generalPrint
1260               << CoinMessageEol;
1261           }
1262         }
1263       }
1264       if (accumulate) {
1265         heuristic4.setAccumulate(accumulate);
1266         if (printStuff) {
1267           if (accumulate) {
1268             sprintf(generalPrint, "Accumulate of %d", accumulate);
1269             generalMessageHandler->message(CBC_GENERAL, generalMessages)
1270               << generalPrint
1271               << CoinMessageEol;
1272           }
1273         }
1274       }
1275       if (r) {
1276         // also set increment
1277         //double increment = (0.01*i+0.005)*(fabs(value)+1.0e-12);
1278         double increment = 0.0;
1279         double fakeIncrement = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue();
1280         if (fakeIncrement)
1281           increment = fakeIncrement;
1282         if (increment >= 0.0)
1283           heuristic4.setAbsoluteIncrement(increment);
1284         else
1285           heuristic4.setRelativeIncrement(-increment);
1286         heuristic4.setMaximumRetries(r + 1);
1287         if (printStuff) {
1288           if (increment) {
1289             if (increment > 0.0)
1290               sprintf(generalPrint, "Absolute increment of %g", increment);
1291             else
1292               sprintf(generalPrint, "Relative increment of %g", -increment);
1293             generalMessageHandler->message(CBC_GENERAL, generalMessages)
1294               << generalPrint
1295               << CoinMessageEol;
1296           }
1297           sprintf(generalPrint, "%d retries", r + 1);
1298           generalMessageHandler->message(CBC_GENERAL, generalMessages)
1299             << generalPrint
1300             << CoinMessageEol;
1301         }
1302       }
1303       if (i + offRandomEtc) {
1304         heuristic4.setFeasibilityPumpOptions(i * 10 + offRandomEtc);
1305         if (printStuff) {
1306           sprintf(generalPrint, "Feasibility pump options of %d",
1307             i * 10 + offRandomEtc);
1308           generalMessageHandler->message(CBC_GENERAL, generalMessages)
1309             << generalPrint
1310             << CoinMessageEol;
1311         }
1312       }
1313       pumpTune = pumpTune % 100;
1314       if (pumpTune == 6)
1315         pumpTune = 13;
1316       heuristic4.setWhen((pumpTune % 10) + 10);
1317       if (printStuff) {
1318         sprintf(generalPrint, "Tuning (fixing) %d", pumpTune % 10);
1319         generalMessageHandler->message(CBC_GENERAL, generalMessages)
1320           << generalPrint
1321           << CoinMessageEol;
1322       }
1323     }
1324     heuristic4.setHeuristicName("feasibility pump");
1325     //#define ROLF
1326 #ifdef ROLF
1327     CbcHeuristicFPump pump(*model);
1328     pump.setMaximumTime(60);
1329     pump.setMaximumPasses(100);
1330     pump.setMaximumRetries(1);
1331     pump.setFixOnReducedCosts(0);
1332     pump.setHeuristicName("Feasibility pump");
1333     pump.setFractionSmall(1.0);
1334     pump.setWhen(13);
1335     model->addHeuristic(&pump);
1336 #else
1337     model->addHeuristic(&heuristic4);
1338 #endif
1339   }
1340   if (useRounding >= type && useRounding >= kType && useRounding <= kType + 1) {
1341     CbcRounding heuristic1(*model);
1342     heuristic1.setHeuristicName("rounding");
1343     model->addHeuristic(&heuristic1);
1344     anyToDo = true;
1345   }
1346   if (useGreedy >= type && useGreedy >= kType && useGreedy <= kType + 1) {
1347     CbcHeuristicGreedyCover heuristic3(*model);
1348     heuristic3.setHeuristicName("greedy cover");
1349     CbcHeuristicGreedyEquality heuristic3a(*model);
1350     heuristic3a.setHeuristicName("greedy equality");
1351     model->addHeuristic(&heuristic3);
1352     model->addHeuristic(&heuristic3a);
1353     anyToDo = true;
1354   }
1355   if ((useRENS == 7 && kType == 1) || (useRENS == 8 && kType == 2)) {
1356     useRENS = 1 + 2 * (useRENS - 7);
1357     CbcHeuristicRENS heuristic6a(*model);
1358     heuristic6a.setHeuristicName("RENSdj");
1359     heuristic6a.setFractionSmall(0.6 /*3.4*/);
1360     heuristic6a.setFeasibilityPumpOptions(3);
1361     heuristic6a.setNumberNodes(10);
1362     heuristic6a.setWhereFrom(4 * 256 + 4 * 1);
1363     heuristic6a.setWhen(2);
1364     heuristic6a.setRensType(1 + 16);
1365     model->addHeuristic(&heuristic6a);
1366     heuristic6a.setHeuristicName("RENSub");
1367     heuristic6a.setFractionSmall(0.4);
1368     heuristic6a.setFeasibilityPumpOptions(1008003);
1369     heuristic6a.setNumberNodes(50);
1370     heuristic6a.setWhereFrom(4 * 256 + 4 * 1);
1371     heuristic6a.setWhen(2);
1372     heuristic6a.setRensType(2 + 16);
1373     model->addHeuristic(&heuristic6a);
1374   }
1375   if ((useRENS >= kType && useRENS <= kType + 1) || useRENS > 2) {
1376     CbcHeuristicRENS heuristic6(*model);
1377     heuristic6.setHeuristicName("RENS");
1378     heuristic6.setFractionSmall(0.4);
1379     heuristic6.setFeasibilityPumpOptions(1008003);
1380     int nodes[] = { -2, 50, 50, 50, 200, 1000, 10000, -1, -1, 200 };
1381     heuristic6.setNumberNodes(nodes[useRENS]);
1382     heuristic6.setRensType(useRENS != 9 ? 0 : 32);
1383     model->addHeuristic(&heuristic6);
1384     anyToDo = true;
1385   }
1386   if (useVND >= kType && useVND <= kType + 1) {
1387     CbcHeuristicVND heuristic6b(*model);
1388     heuristic6b.setHeuristicName("VND");
1389     heuristic6b.setFractionSmall(0.4);
1390     heuristic6b.setFeasibilityPumpOptions(1008003);
1391     int nodes[] = { -2, 50, 50, 50, 200, 1000, 10000 };
1392     heuristic6b.setNumberNodes(nodes[useVND]);
1393     model->addHeuristic(&heuristic6b);
1394     anyToDo = true;
1395   }
1396   if (useNaive >= kType && useNaive <= kType + 1) {
1397     CbcHeuristicNaive heuristic5b(*model);
1398     heuristic5b.setHeuristicName("Naive");
1399     heuristic5b.setFractionSmall(0.4);
1400     heuristic5b.setNumberNodes(50);
1401     model->addHeuristic(&heuristic5b);
1402     anyToDo = true;
1403   }
1404   int useDIVING = 0;
1405   {
1406     int useD;
1407     useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGV, parameters_)].currentOptionAsInteger();
1408     useDIVING |= 1 * ((useD >= kType) ? 1 : 0);
1409     useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGG, parameters_)].currentOptionAsInteger();
1410     useDIVING |= 2 * ((useD >= kType) ? 1 : 0);
1411     useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGF, parameters_)].currentOptionAsInteger();
1412     useDIVING |= 4 * ((useD >= kType) ? 1 : 0);
1413     useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGC, parameters_)].currentOptionAsInteger();
1414     useDIVING |= 8 * ((useD >= kType) ? 1 : 0);
1415     useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGL, parameters_)].currentOptionAsInteger();
1416     useDIVING |= 16 * ((useD >= kType) ? 1 : 0);
1417     useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGP, parameters_)].currentOptionAsInteger();
1418     useDIVING |= 32 * ((useD >= kType) ? 1 : 0);
1419   }
1420   if (useDIVING2 >= kType && useDIVING2 <= kType + 1) {
1421     int diveOptions = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].intValue();
1422     if (diveOptions < 0 || diveOptions > 10)
1423       diveOptions = 2;
1424     CbcHeuristicJustOne heuristicJustOne(*model);
1425     heuristicJustOne.setHeuristicName("DiveAny");
1426     heuristicJustOne.setWhen(diveOptions);
1427     // add in others
1428     CbcHeuristicDiveCoefficient heuristicDC(*model);
1429     heuristicDC.setHeuristicName("DiveCoefficient");
1430     heuristicJustOne.addHeuristic(&heuristicDC, 1.0);
1431     CbcHeuristicDiveFractional heuristicDF(*model);
1432     heuristicDF.setHeuristicName("DiveFractional");
1433     heuristicJustOne.addHeuristic(&heuristicDF, 1.0);
1434     CbcHeuristicDiveGuided heuristicDG(*model);
1435     heuristicDG.setHeuristicName("DiveGuided");
1436     heuristicJustOne.addHeuristic(&heuristicDG, 1.0);
1437     CbcHeuristicDiveLineSearch heuristicDL(*model);
1438     heuristicDL.setHeuristicName("DiveLineSearch");
1439     heuristicJustOne.addHeuristic(&heuristicDL, 1.0);
1440     CbcHeuristicDivePseudoCost heuristicDP(*model);
1441     heuristicDP.setHeuristicName("DivePseudoCost");
1442     heuristicJustOne.addHeuristic(&heuristicDP, 1.0);
1443     CbcHeuristicDiveVectorLength heuristicDV(*model);
1444     heuristicDV.setHeuristicName("DiveVectorLength");
1445     heuristicJustOne.addHeuristic(&heuristicDV, 1.0);
1446     // Now normalize probabilities
1447     heuristicJustOne.normalizeProbabilities();
1448     model->addHeuristic(&heuristicJustOne);
1449   }
1450 
1451   if (useDIVING > 0) {
1452     int majorIterations = parameters_[whichParam(CBC_PARAM_INT_DIVEOPTSOLVES, parameters_)].intValue();
1453     int diveOptions2 = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].intValue();
1454     int diveOptions;
1455     if (diveOptions2 > 99) {
1456       // switch on various active set stuff
1457       diveOptions = diveOptions2 % 100;
1458       diveOptions2 /= 100;
1459     } else {
1460       diveOptions = diveOptions2;
1461       diveOptions2 = 0;
1462     }
1463     if (diveOptions < 0 || diveOptions > 29)
1464       diveOptions = 2;
1465     int diveOptionsNotC = diveOptions;
1466     if (diveOptions > 10) {
1467       if (diveOptions > 20) {
1468         diveOptions -= 20;
1469         diveOptionsNotC -= 20;
1470       } else {
1471         diveOptions -= 10;
1472         diveOptionsNotC = 4;
1473       }
1474       useDIVING = 63;
1475     }
1476     if ((useDIVING & 1) != 0) {
1477       CbcHeuristicDiveVectorLength heuristicDV(*model);
1478       heuristicDV.setHeuristicName("DiveVectorLength");
1479       heuristicDV.setWhen(diveOptionsNotC);
1480       heuristicDV.setMaxIterations(majorIterations);
1481       if (diveOptions2) {
1482         heuristicDV.setPercentageToFix(0.0);
1483         heuristicDV.setMaxSimplexIterations(COIN_INT_MAX);
1484         heuristicDV.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1));
1485       }
1486       model->addHeuristic(&heuristicDV);
1487     }
1488     if ((useDIVING & 2) != 0) {
1489       CbcHeuristicDiveGuided heuristicDG(*model);
1490       heuristicDG.setHeuristicName("DiveGuided");
1491       heuristicDG.setWhen(diveOptionsNotC);
1492       heuristicDG.setMaxIterations(majorIterations);
1493       if (diveOptions2) {
1494         heuristicDG.setPercentageToFix(0.0);
1495         heuristicDG.setMaxSimplexIterations(COIN_INT_MAX);
1496         heuristicDG.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1));
1497       }
1498       model->addHeuristic(&heuristicDG);
1499     }
1500     if ((useDIVING & 4) != 0) {
1501       CbcHeuristicDiveFractional heuristicDF(*model);
1502       heuristicDF.setHeuristicName("DiveFractional");
1503       heuristicDF.setWhen(diveOptionsNotC);
1504       heuristicDF.setMaxIterations(majorIterations);
1505       if (diveOptions2) {
1506         heuristicDF.setPercentageToFix(0.0);
1507         heuristicDF.setMaxSimplexIterations(COIN_INT_MAX);
1508         heuristicDF.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1));
1509       }
1510       model->addHeuristic(&heuristicDF);
1511     }
1512     if ((useDIVING & 8) != 0) {
1513       CbcHeuristicDiveCoefficient heuristicDC(*model);
1514       heuristicDC.setHeuristicName("DiveCoefficient");
1515       heuristicDC.setWhen(diveOptions);
1516       heuristicDC.setMaxIterations(majorIterations);
1517       if (diveOptions2) {
1518         heuristicDC.setPercentageToFix(0.0);
1519         heuristicDC.setMaxSimplexIterations(COIN_INT_MAX);
1520         heuristicDC.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1));
1521       }
1522       model->addHeuristic(&heuristicDC);
1523     }
1524     if ((useDIVING & 16) != 0) {
1525       CbcHeuristicDiveLineSearch heuristicDL(*model);
1526       heuristicDL.setHeuristicName("DiveLineSearch");
1527       heuristicDL.setWhen(diveOptionsNotC);
1528       heuristicDL.setMaxIterations(majorIterations);
1529       if (diveOptions2) {
1530         heuristicDL.setPercentageToFix(0.0);
1531         heuristicDL.setMaxSimplexIterations(COIN_INT_MAX);
1532         heuristicDL.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1));
1533       }
1534       model->addHeuristic(&heuristicDL);
1535     }
1536     if ((useDIVING & 32) != 0) {
1537       CbcHeuristicDivePseudoCost heuristicDP(*model);
1538       heuristicDP.setHeuristicName("DivePseudoCost");
1539       heuristicDP.setWhen(diveOptionsNotC /*+ diveOptions2*/);
1540       heuristicDP.setMaxIterations(majorIterations);
1541       if (diveOptions2) {
1542         heuristicDP.setPercentageToFix(0.0);
1543         heuristicDP.setMaxSimplexIterations(COIN_INT_MAX);
1544         heuristicDP.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1));
1545       }
1546       model->addHeuristic(&heuristicDP);
1547     }
1548     anyToDo = true;
1549   }
1550 #ifdef JJF_ZERO
1551   if (usePivotC >= type && usePivotC <= kType + 1) {
1552     CbcHeuristicPivotAndComplement heuristic(*model);
1553     heuristic.setHeuristicName("pivot and complement");
1554     heuristic.setFractionSmall(10.0); // normally 0.5
1555     model->addHeuristic(&heuristic);
1556     anyToDo = true;
1557   }
1558 #endif
1559   if (usePivotF >= type && usePivotF <= kType + 1) {
1560     CbcHeuristicPivotAndFix heuristic(*model);
1561     heuristic.setHeuristicName("pivot and fix");
1562     heuristic.setFractionSmall(10.0); // normally 0.5
1563     model->addHeuristic(&heuristic);
1564     anyToDo = true;
1565   }
1566   if (useRand >= type && useRand <= kType + 1) {
1567     CbcHeuristicRandRound heuristic(*model);
1568     heuristic.setHeuristicName("randomized rounding");
1569     heuristic.setFractionSmall(10.0); // normally 0.5
1570     model->addHeuristic(&heuristic);
1571     anyToDo = true;
1572   }
1573   if (useDINS >= kType && useDINS <= kType + 1) {
1574     CbcHeuristicDINS heuristic5a(*model);
1575     heuristic5a.setHeuristicName("DINS");
1576     heuristic5a.setFractionSmall(0.6);
1577     if (useDINS < 4)
1578       heuristic5a.setDecayFactor(5.0);
1579     else
1580       heuristic5a.setDecayFactor(1.5);
1581     heuristic5a.setNumberNodes(1000);
1582     model->addHeuristic(&heuristic5a);
1583     anyToDo = true;
1584   }
1585   if (useRINS >= kType && useRINS <= kType + 1) {
1586     CbcHeuristicRINS heuristic5(*model);
1587     heuristic5.setHeuristicName("RINS");
1588     if (useRINS < 4) {
1589       heuristic5.setFractionSmall(0.5);
1590       heuristic5.setDecayFactor(5.0);
1591     } else {
1592       heuristic5.setFractionSmall(0.6);
1593       heuristic5.setDecayFactor(1.5);
1594     }
1595     model->addHeuristic(&heuristic5);
1596     anyToDo = true;
1597   }
1598   if (useDW >= kType && useDW <= kType + 1) {
1599     CbcHeuristicDW heuristic13(*model);
1600     heuristic13.setHeuristicName("Dantzig-Wolfe");
1601     heuristic13.setNumberPasses(100);
1602     heuristic13.setNumberBadPasses(10);
1603     int numberIntegers = 0;
1604     const OsiSolverInterface *solver = model->solver();
1605     int numberColumns = solver->getNumCols();
1606     for (int i = 0; i < numberColumns; i++) {
1607       if (solver->isInteger(i))
1608         numberIntegers++;
1609     }
1610     heuristic13.setNumberNeeded(CoinMin(200, numberIntegers / 10));
1611     model->addHeuristic(&heuristic13);
1612     anyToDo = true;
1613   }
1614   if (useCombine >= kType && (useCombine - 1) % 3 <= kType) {
1615     CbcHeuristicLocal heuristic2(*model);
1616     heuristic2.setHeuristicName("combine solutions");
1617     heuristic2.setFractionSmall(0.5);
1618     int searchType = 1;
1619     if (useCombine > 3)
1620       searchType += 10; // experiment
1621     heuristic2.setSearchType(searchType);
1622     model->addHeuristic(&heuristic2);
1623     anyToDo = true;
1624   }
1625   if ((useProximity >= kType && useProximity <= kType + 1) || (kType == 1 && useProximity > 3)) {
1626     CbcHeuristicProximity heuristic2a(*model);
1627     heuristic2a.setHeuristicName("Proximity Search");
1628     heuristic2a.setFractionSmall(9999999.0);
1629     heuristic2a.setNumberNodes(30);
1630     heuristic2a.setFeasibilityPumpOptions(-2);
1631     if (useProximity >= 4) {
1632       const int nodes[] = { 10, 100, 300 };
1633       heuristic2a.setNumberNodes(nodes[useProximity - 4]);
1634       // more print out and stronger feasibility pump
1635       if (useProximity == 6)
1636         heuristic2a.setFeasibilityPumpOptions(-3);
1637     } else {
1638       int proximityNumber;
1639       parameters_[whichParam(CBC_PARAM_STR_PROXIMITY, parameters_)].currentOptionAsInteger(proximityNumber);
1640       if (proximityNumber > 0) {
1641         heuristic2a.setNumberNodes(proximityNumber);
1642         // more print out and stronger feasibility pump
1643         if (proximityNumber >= 300)
1644           heuristic2a.setFeasibilityPumpOptions(-3);
1645       }
1646     }
1647     model->addHeuristic(&heuristic2a);
1648     anyToDo = true;
1649   }
1650   if (useCrossover >= kType && useCrossover <= kType + 1) {
1651     CbcHeuristicCrossover heuristic2a(*model);
1652     heuristic2a.setHeuristicName("crossover");
1653     heuristic2a.setFractionSmall(0.3);
1654     // just fix at lower
1655     heuristic2a.setWhen(11);
1656     model->addHeuristic(&heuristic2a);
1657     model->setMaximumSavedSolutions(5);
1658     anyToDo = true;
1659   }
1660   int heurSwitches = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() % 100;
1661   if (heurSwitches) {
1662     for (int iHeur = 0; iHeur < model->numberHeuristics(); iHeur++) {
1663       CbcHeuristic *heuristic = model->heuristic(iHeur);
1664       heuristic->setSwitches(heurSwitches);
1665     }
1666   }
1667   if (type == 2 && anyToDo) {
1668     // Do heuristics
1669 #ifndef JJF_ONE
1670     // clean copy
1671     CbcModel model2(*model);
1672     // But get rid of heuristics in model
1673     model->doHeuristicsAtRoot(2);
1674     if (logLevel <= 1)
1675       model2.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
1676     OsiBabSolver defaultC;
1677     //solver_->setAuxiliaryInfo(&defaultC);
1678     model2.passInSolverCharacteristics(&defaultC);
1679     // Save bounds
1680     int numberColumns = model2.solver()->getNumCols();
1681     model2.createContinuousSolver();
1682     bool cleanModel = !model2.numberIntegers() && !model2.numberObjects();
1683     model2.findIntegers(false);
1684     int heurOptions = (parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 100) % 100;
1685     if (heurOptions == 0 || heurOptions == 2) {
1686       model2.doHeuristicsAtRoot(1);
1687     } else if (heurOptions == 1 || heurOptions == 3) {
1688       model2.setMaximumNodes(-1);
1689       CbcStrategyDefault strategy(0, 5, 5);
1690       strategy.setupPreProcessing(1, 0);
1691       model2.setStrategy(strategy);
1692       model2.branchAndBound();
1693     }
1694     if (cleanModel)
1695       model2.zapIntegerInformation(false);
1696     if (model2.bestSolution()) {
1697       double value = model2.getMinimizationObjValue();
1698       model->setCutoff(value);
1699       model->setBestSolution(model2.bestSolution(), numberColumns, value);
1700       model->setSolutionCount(1);
1701       model->setNumberHeuristicSolutions(1);
1702     }
1703 #else
1704     if (logLevel <= 1)
1705       model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
1706     OsiBabSolver defaultC;
1707     //solver_->setAuxiliaryInfo(&defaultC);
1708     model->passInSolverCharacteristics(&defaultC);
1709     // Save bounds
1710     int numberColumns = model->solver()->getNumCols();
1711     model->createContinuousSolver();
1712     bool cleanModel = !model->numberIntegers() && !model->numberObjects();
1713     model->findIntegers(false);
1714     model->doHeuristicsAtRoot(1);
1715     if (cleanModel)
1716       model->zapIntegerInformation(false);
1717 #endif
1718     return 0;
1719   } else {
1720     return 0;
1721   }
1722 }
1723 
1724 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
1725 */
1726