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 CbcSolver.cpp
7     \brief Second level routines for the cbc stand-alone solver.
8 */
9 
10 
11 #include "CbcConfig.h"
12 #include "CoinPragma.hpp"
13 
14 #include <cassert>
15 #include <cstdio>
16 #include <cstdlib>
17 #include <cmath>
18 #include <cfloat>
19 #include <cstring>
20 #include <iostream>
21 
22 #include "CoinPragma.hpp"
23 #include "CoinHelperFunctions.hpp"
24 
25 #include "CoinMpsIO.hpp"
26 #include "CoinModel.hpp"
27 
28 #include "ClpFactorization.hpp"
29 #include "ClpQuadraticObjective.hpp"
30 #include "CoinTime.hpp"
31 #include "ClpSimplex.hpp"
32 #include "ClpSimplexOther.hpp"
33 #include "ClpSolve.hpp"
34 #include "ClpMessage.hpp"
35 #include "ClpPackedMatrix.hpp"
36 #include "ClpPlusMinusOneMatrix.hpp"
37 #include "ClpNetworkMatrix.hpp"
38 #include "ClpDualRowSteepest.hpp"
39 #include "ClpDualRowDantzig.hpp"
40 #include "ClpPEDualRowSteepest.hpp"
41 #include "ClpPEDualRowDantzig.hpp"
42 #include "ClpPEPrimalColumnSteepest.hpp"
43 #include "ClpPEPrimalColumnDantzig.hpp"
44 #include "ClpLinearObjective.hpp"
45 #include "ClpPrimalColumnSteepest.hpp"
46 #include "ClpPrimalColumnDantzig.hpp"
47 
48 #include "ClpPresolve.hpp"
49 #ifndef COIN_HAS_CBC
50 #define COIN_HAS_CBC
51 #endif
52 #include "CbcOrClpParam.hpp"
53 #include "OsiRowCutDebugger.hpp"
54 #include "OsiChooseVariable.hpp"
55 #include "OsiAuxInfo.hpp"
56 #include "CbcMipStartIO.hpp"
57 #include "CbcMessage.hpp"
58 // for printing
59 #ifndef CLP_OUTPUT_FORMAT
60 #define CLP_OUTPUT_FORMAT % 15.8g
61 #endif
62 #define CLP_QUOTE(s) CLP_STRING(s)
63 #define CLP_STRING(s) #s
64 
65 #include "CbcSolverHeuristics.hpp"
66 #ifdef COIN_HAS_GLPK
67 #include "glpk.h"
68 extern glp_tran *cbc_glp_tran;
69 extern glp_prob *cbc_glp_prob;
70 #else
71 #define GLP_UNDEF 1
72 #define GLP_FEAS 2
73 #define GLP_INFEAS 3
74 #define GLP_NOFEAS 4
75 #define GLP_OPT 5
76 #endif
77 
78 #ifndef CBC_QUIET
79 #define CBC_QUIET 0
80 #endif
81 
82 //#define USER_HAS_FAKE_CLP
83 //#define USER_HAS_FAKE_CBC
84 //#define NEW_DEBUG_AND_FILL // use this to make it easier to trap unset
85 
86 #ifdef NEW_DEBUG_AND_FILL
87 #include <malloc.h>
88 #include <exception>
89 #include <new>
operator new(size_t size)90 void *operator new(size_t size)
91 {
92   void * p = malloc(size);
93   char * xx = (char *) p;
94   memset(xx,0x20,size);
95   return p;
96 }
operator delete(void * p)97 void operator delete(void *p) throw()
98 {
99   free(p);
100 }
101 #endif // end NEW_DEBUG
102 //#define CLP_MALLOC_STATISTICS
103 
104 #ifdef CLP_MALLOC_STATISTICS
105 #include <malloc.h>
106 #include <exception>
107 #include <new>
108 #include "stolen_from_ekk_malloc.cpp"
109 static double malloc_times = 0.0;
110 static double malloc_total = 0.0;
111 static int malloc_amount[] = { 0, 32, 128, 256, 1024, 4096, 16384, 65536, 262144, INT_MAX };
112 static int malloc_n = 10;
113 double malloc_counts[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
114 bool malloc_counts_on = true;
operator new(size_t size)115 void *operator new(size_t size) throw(std::bad_alloc)
116 {
117   malloc_times++;
118   malloc_total += size;
119   int i;
120   for (i = 0; i < malloc_n; i++) {
121     if ((int)size <= malloc_amount[i]) {
122       malloc_counts[i]++;
123       break;
124     }
125   }
126 #ifdef DEBUG_MALLOC
127   void *p;
128   if (malloc_counts_on)
129     p = stolen_from_ekk_mallocBase(size);
130   else
131     p = malloc(size);
132 #else
133   void *p = malloc(size);
134 #endif
135   //char * xx = (char *) p;
136   //memset(xx,0,size);
137   // Initialize random seed
138   //CoinSeedRandom(987654321);
139   return p;
140 }
operator delete(void * p)141 void operator delete(void *p) throw()
142 {
143 #ifdef DEBUG_MALLOC
144   if (malloc_counts_on)
145     stolen_from_ekk_freeBase(p);
146   else
147     free(p);
148 #else
149   free(p);
150 #endif
151 }
malloc_stats2()152 static void malloc_stats2()
153 {
154   double average = malloc_total / malloc_times;
155   printf("count %g bytes %g - average %g\n", malloc_times, malloc_total, average);
156   for (int i = 0; i < malloc_n; i++)
157     printf("%g ", malloc_counts[i]);
158   printf("\n");
159   malloc_times = 0.0;
160   malloc_total = 0.0;
161   memset(malloc_counts, 0, sizeof(malloc_counts));
162   // print results
163 }
164 #else //CLP_MALLOC_STATISTICS
165 //void stolen_from_ekk_memory(void * dummy,int type)
166 //{
167 //}
168 //bool malloc_counts_on=false;
169 #endif //CLP_MALLOC_STATISTICS
170 
171 //#define DMALLOC
172 #ifdef DMALLOC
173 #include "dmalloc.h"
174 #endif
175 
176 #ifdef WSSMP_BARRIER
177 #define FOREIGN_BARRIER
178 #endif
179 
180 #ifdef UFL_BARRIER
181 #define FOREIGN_BARRIER
182 #endif
183 
184 #ifdef TAUCS_BARRIER
185 #define FOREIGN_BARRIER
186 #endif
187 
188 static int initialPumpTune = -1;
189 #include "CoinWarmStartBasis.hpp"
190 
191 #include "OsiSolverInterface.hpp"
192 #include "OsiCuts.hpp"
193 #include "OsiRowCut.hpp"
194 #include "OsiColCut.hpp"
195 
196 #ifndef COIN_HAS_LINK
197 #define COIN_HAS_LINK
198 #endif
199 #ifdef COIN_HAS_LINK
200 #include "CbcLinked.hpp"
201 #endif
202 
203 #include "CglPreProcess.hpp"
204 #include "CglCutGenerator.hpp"
205 #include "CglGomory.hpp"
206 #include "CglProbing.hpp"
207 #include "CglKnapsackCover.hpp"
208 #include "CglRedSplit.hpp"
209 #include "CglRedSplit2.hpp"
210 #include "CglGMI.hpp"
211 #include "CglClique.hpp"
212 #include "CglFlowCover.hpp"
213 #include "CglMixedIntegerRounding2.hpp"
214 #include "CglTwomir.hpp"
215 #include "CglDuplicateRow.hpp"
216 #include "CglStored.hpp"
217 #include "CglLandP.hpp"
218 #include "CglResidualCapacity.hpp"
219 #include "CglZeroHalf.hpp"
220 //#define CGL_WRITEMPS
221 #ifdef CGL_WRITEMPS
222 extern double *debugSolution;
223 extern int debugNumberColumns;
224 #endif
225 #include "CbcModel.hpp"
226 #include "CbcHeuristic.hpp"
227 #include "CbcHeuristicLocal.hpp"
228 #include "CbcHeuristicPivotAndFix.hpp"
229 //#include "CbcHeuristicPivotAndComplement.hpp"
230 #include "CbcHeuristicRandRound.hpp"
231 #include "CbcHeuristicGreedy.hpp"
232 #include "CbcHeuristicFPump.hpp"
233 #include "CbcHeuristicRINS.hpp"
234 #include "CbcHeuristicDiveCoefficient.hpp"
235 #include "CbcHeuristicDiveFractional.hpp"
236 #include "CbcHeuristicDiveGuided.hpp"
237 #include "CbcHeuristicDiveVectorLength.hpp"
238 #include "CbcHeuristicDivePseudoCost.hpp"
239 #include "CbcHeuristicDiveLineSearch.hpp"
240 #include "CbcTreeLocal.hpp"
241 #include "CbcCompareActual.hpp"
242 #include "CbcCompareObjective.hpp"
243 #include "CbcBranchActual.hpp"
244 #include "CbcBranchLotsize.hpp"
245 #include "CbcOrClpParam.hpp"
246 #include "CbcCutGenerator.hpp"
247 #include "CbcStrategy.hpp"
248 #include "CbcBranchCut.hpp"
249 
250 #include "OsiClpSolverInterface.hpp"
251 
252 #include "CbcSolverAnalyze.hpp"
253 #include "CbcSolverExpandKnapsack.hpp"
254 
255 #include "CbcSolver.hpp"
256 
257 //#define IN_BRANCH_AND_BOUND (0x01000000|262144)
258 #define IN_BRANCH_AND_BOUND (0x01000000 | 262144 | 128 | 1024 | 2048)
259 //#define IN_BRANCH_AND_BOUND (0x01000000|262144|128)
260 
261 /*
262   CbcStopNow class definitions.
263 */
264 
CbcStopNow()265 CbcStopNow::CbcStopNow()
266 {
267 }
~CbcStopNow()268 CbcStopNow::~CbcStopNow()
269 {
270 }
271 // Copy constructor
CbcStopNow(const CbcStopNow &)272 CbcStopNow::CbcStopNow(const CbcStopNow &)
273 {
274 }
275 // Assignment operator
276 CbcStopNow &
operator =(const CbcStopNow & rhs)277 CbcStopNow::operator=(const CbcStopNow &rhs)
278 {
279   if (this != &rhs) {
280   }
281   return *this;
282 }
283 // Clone
284 CbcStopNow *
clone() const285 CbcStopNow::clone() const
286 {
287   return new CbcStopNow(*this);
288 }
289 
290 /*
291   CbcUser class definitions.
292 */
293 
294 // User stuff (base class)
CbcUser()295 CbcUser::CbcUser()
296   : coinModel_(NULL)
297   , userName_("null")
298 {
299 }
~CbcUser()300 CbcUser::~CbcUser()
301 {
302   delete coinModel_;
303 }
304 // Copy constructor
CbcUser(const CbcUser & rhs)305 CbcUser::CbcUser(const CbcUser &rhs)
306 {
307   if (rhs.coinModel_)
308     coinModel_ = new CoinModel(*rhs.coinModel_);
309   else
310     coinModel_ = NULL;
311   userName_ = rhs.userName_;
312 }
313 // Assignment operator
314 CbcUser &
operator =(const CbcUser & rhs)315 CbcUser::operator=(const CbcUser &rhs)
316 {
317   if (this != &rhs) {
318     if (rhs.coinModel_)
319       coinModel_ = new CoinModel(*rhs.coinModel_);
320     else
321       coinModel_ = NULL;
322     userName_ = rhs.userName_;
323   }
324   return *this;
325 }
326 
putBackOtherSolutions(CbcModel * presolvedModel,CbcModel * model,CglPreProcess * preProcess)327 static void putBackOtherSolutions(CbcModel *presolvedModel, CbcModel *model,
328   CglPreProcess *preProcess)
329 {
330   int numberSolutions = presolvedModel->numberSavedSolutions();
331   int numberColumns = presolvedModel->getNumCols();
332   if (numberSolutions > 1) {
333     model->deleteSolutions();
334     double *bestSolution = CoinCopyOfArray(presolvedModel->bestSolution(), numberColumns);
335     //double cutoff = presolvedModel->getCutoff();
336     double objectiveValue = presolvedModel->getObjValue();
337     //model->createSpaceForSavedSolutions(numberSolutions-1);
338     for (int iSolution = numberSolutions - 1; iSolution >= 0; iSolution--) {
339       presolvedModel->setCutoff(COIN_DBL_MAX);
340       presolvedModel->solver()->setColSolution(presolvedModel->savedSolution(iSolution));
341       //presolvedModel->savedSolutionObjective(iSolution));
342       preProcess->postProcess(*presolvedModel->solver(), false);
343       model->setBestSolution(preProcess->originalModel()->getColSolution(), model->solver()->getNumCols(),
344         presolvedModel->savedSolutionObjective(iSolution));
345     }
346     presolvedModel->setBestObjectiveValue(objectiveValue);
347     presolvedModel->solver()->setColSolution(bestSolution);
348     //presolvedModel->setBestSolution(bestSolution,numberColumns,objectiveValue);
349   }
350 }
351 
352 // For when number of column is messed up e.g. BiLinear
numberPrintingColumns(const OsiSolverInterface * solver)353 static int numberPrintingColumns(const OsiSolverInterface * solver)
354 {
355 #ifdef COIN_HAS_LINK
356   const OsiSolverLink *linkSolver =
357     dynamic_cast< const OsiSolverLink * >(solver);
358   if (!linkSolver)
359     return solver->getNumCols();
360   return linkSolver->coinModel()->numberColumns();
361 #else
362   return solver->getNumCols();
363 #endif
364 }
365 
366 /*
367   CbcSolver class definitions
368 */
369 
CbcSolver()370 CbcSolver::CbcSolver()
371   : babModel_(NULL)
372   , userFunction_(NULL)
373   , statusUserFunction_(NULL)
374   , originalSolver_(NULL)
375   , originalCoinModel_(NULL)
376   , cutGenerator_(NULL)
377   , numberUserFunctions_(0)
378   , numberCutGenerators_(0)
379   , startTime_(CoinCpuTime())
380   , doMiplib_(false)
381   , noPrinting_(false)
382   , readMode_(1)
383 {
384   callBack_ = new CbcStopNow();
385   fillParameters();
386 }
CbcSolver(const OsiClpSolverInterface & solver)387 CbcSolver::CbcSolver(const OsiClpSolverInterface &solver)
388   : babModel_(NULL)
389   , userFunction_(NULL)
390   , statusUserFunction_(NULL)
391   , originalSolver_(NULL)
392   , originalCoinModel_(NULL)
393   , cutGenerator_(NULL)
394   , numberUserFunctions_(0)
395   , numberCutGenerators_(0)
396   , startTime_(CoinCpuTime())
397   , doMiplib_(false)
398   , noPrinting_(false)
399   , readMode_(1)
400 {
401   callBack_ = new CbcStopNow();
402   model_ = CbcModel(solver);
403   fillParameters();
404 }
CbcSolver(const CbcModel & solver)405 CbcSolver::CbcSolver(const CbcModel &solver)
406   : babModel_(NULL)
407   , userFunction_(NULL)
408   , statusUserFunction_(NULL)
409   , originalSolver_(NULL)
410   , originalCoinModel_(NULL)
411   , cutGenerator_(NULL)
412   , numberUserFunctions_(0)
413   , numberCutGenerators_(0)
414   , startTime_(CoinCpuTime())
415   , doMiplib_(false)
416   , noPrinting_(false)
417   , readMode_(1)
418 {
419   callBack_ = new CbcStopNow();
420   model_ = solver;
421   fillParameters();
422 }
~CbcSolver()423 CbcSolver::~CbcSolver()
424 {
425   int i;
426   for (i = 0; i < numberUserFunctions_; i++)
427     delete userFunction_[i];
428   delete[] userFunction_;
429   for (i = 0; i < numberCutGenerators_; i++)
430     delete cutGenerator_[i];
431   delete[] cutGenerator_;
432   delete[] statusUserFunction_;
433   delete originalSolver_;
434   delete originalCoinModel_;
435   delete babModel_;
436   delete callBack_;
437 }
438 // Copy constructor
CbcSolver(const CbcSolver & rhs)439 CbcSolver::CbcSolver(const CbcSolver &rhs)
440   : model_(rhs.model_)
441   , babModel_(NULL)
442   , userFunction_(NULL)
443   , statusUserFunction_(NULL)
444   , cutGenerator_(new CglCutGenerator *[rhs.numberCutGenerators()])
445   , numberUserFunctions_(rhs.numberUserFunctions_)
446   , numberCutGenerators_(rhs.numberCutGenerators())
447   , startTime_(CoinCpuTime())
448   , doMiplib_(rhs.doMiplib_)
449   , noPrinting_(rhs.noPrinting_)
450   , readMode_(rhs.readMode_)
451 {
452   fillParameters();
453   if (rhs.babModel_)
454     babModel_ = new CbcModel(*rhs.babModel_);
455   userFunction_ = new CbcUser *[numberUserFunctions_];
456   int i;
457   for (i = 0; i < numberUserFunctions_; i++)
458     userFunction_[i] = rhs.userFunction_[i]->clone();
459   this->parameters_ = rhs.parameters_;
460   for (i = 0; i < numberCutGenerators_; i++)
461     cutGenerator_[i] = rhs.cutGenerator_[i]->clone();
462   callBack_ = rhs.callBack_->clone();
463   originalSolver_ = NULL;
464   if (rhs.originalSolver_) {
465     OsiSolverInterface *temp = rhs.originalSolver_->clone();
466     originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp);
467     assert(originalSolver_);
468   }
469   originalCoinModel_ = NULL;
470   if (rhs.originalCoinModel_)
471     originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_);
472 }
473 // Assignment operator
474 CbcSolver &
operator =(const CbcSolver & rhs)475 CbcSolver::operator=(const CbcSolver &rhs)
476 {
477   if (this != &rhs) {
478     int i;
479     for (i = 0; i < numberUserFunctions_; i++)
480       delete userFunction_[i];
481     delete[] userFunction_;
482     for (i = 0; i < numberCutGenerators_; i++)
483       delete cutGenerator_[i];
484     delete[] statusUserFunction_;
485     delete originalSolver_;
486     delete originalCoinModel_;
487     statusUserFunction_ = NULL;
488     delete babModel_;
489     delete callBack_;
490     numberUserFunctions_ = rhs.numberUserFunctions_;
491     startTime_ = rhs.startTime_;
492     this->parameters_ = rhs.parameters_;
493     for (i = 0; i < numberCutGenerators_; i++)
494       cutGenerator_[i] = rhs.cutGenerator_[i]->clone();
495     noPrinting_ = rhs.noPrinting_;
496     readMode_ = rhs.readMode_;
497     doMiplib_ = rhs.doMiplib_;
498     model_ = rhs.model_;
499     if (rhs.babModel_)
500       babModel_ = new CbcModel(*rhs.babModel_);
501     else
502       babModel_ = NULL;
503     userFunction_ = new CbcUser *[numberUserFunctions_];
504     for (i = 0; i < numberUserFunctions_; i++)
505       userFunction_[i] = rhs.userFunction_[i]->clone();
506     callBack_ = rhs.callBack_->clone();
507     originalSolver_ = NULL;
508     if (rhs.originalSolver_) {
509       OsiSolverInterface *temp = rhs.originalSolver_->clone();
510       originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp);
511       assert(originalSolver_);
512     }
513     originalCoinModel_ = NULL;
514     if (rhs.originalCoinModel_)
515       originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_);
516   }
517   return *this;
518 }
519 // Get int value
intValue(CbcOrClpParameterType type) const520 int CbcSolver::intValue(CbcOrClpParameterType type) const
521 {
522   return parameters_[whichParam(type, parameters_)].intValue();
523 }
524 // Set int value
setIntValue(CbcOrClpParameterType type,int value)525 void CbcSolver::setIntValue(CbcOrClpParameterType type, int value)
526 {
527   parameters_[whichParam(type, parameters_)].setIntValue(value);
528 }
529 // Get double value
doubleValue(CbcOrClpParameterType type) const530 double CbcSolver::doubleValue(CbcOrClpParameterType type) const
531 {
532   return parameters_[whichParam(type, parameters_)].doubleValue();
533 }
534 // Set double value
setDoubleValue(CbcOrClpParameterType type,double value)535 void CbcSolver::setDoubleValue(CbcOrClpParameterType type, double value)
536 {
537   parameters_[whichParam(type, parameters_)].setDoubleValue(value);
538 }
539 // User function (NULL if no match)
userFunction(const char * name) const540 CbcUser *CbcSolver::userFunction(const char *name) const
541 {
542   int i;
543   for (i = 0; i < numberUserFunctions_; i++) {
544     if (!strcmp(name, userFunction_[i]->name().c_str()))
545       break;
546   }
547   if (i < numberUserFunctions_)
548     return userFunction_[i];
549   else
550     return NULL;
551 }
fillParameters()552 void CbcSolver::fillParameters()
553 {
554   establishParams(parameters_);
555   const char dirsep = CoinFindDirSeparator();
556   std::string directory;
557   std::string dirSample;
558   std::string dirNetlib;
559   std::string dirMiplib;
560   if (dirsep == '/') {
561     directory = "./";
562     dirSample = "../../Data/Sample/";
563     dirNetlib = "../../Data/Netlib/";
564     dirMiplib = "../../Data/miplib3/";
565   } else {
566     directory = ".\\";
567     dirSample = "..\\..\\..\\..\\Data\\Sample\\";
568     dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
569     dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
570   }
571   std::string defaultDirectory = directory;
572   std::string importFile = "";
573   std::string exportFile = "default.mps";
574   std::string importBasisFile = "";
575   std::string importPriorityFile = "";
576   std::string mipStartFile = "";
577   std::string debugFile = "";
578   std::string printMask = "";
579   std::string exportBasisFile = "default.bas";
580   std::string saveFile = "default.prob";
581   std::string restoreFile = "default.prob";
582   std::string solutionFile = "stdout";
583   std::string solutionSaveFile = "solution.file";
584   int doIdiot = -1;
585   int outputFormat = 2;
586   int substitution = 3;
587   int dualize = 3;
588   int preSolve = 5;
589   int doSprint = -1;
590   int testOsiParameters = -1;
591   int createSolver = 0;
592   ClpSimplex *lpSolver;
593   OsiClpSolverInterface *clpSolver;
594   if (model_.solver()) {
595     clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
596     assert(clpSolver);
597     lpSolver = clpSolver->getModelPtr();
598     assert(lpSolver);
599   } else {
600     lpSolver = new ClpSimplex();
601     clpSolver = new OsiClpSolverInterface(lpSolver, true);
602     createSolver = 1;
603   }
604   parameters_[whichParam(CLP_PARAM_ACTION_BASISIN, parameters_)].setStringValue(importBasisFile);
605   parameters_[whichParam(CBC_PARAM_ACTION_PRIORITYIN, parameters_)].setStringValue(importPriorityFile);
606   parameters_[whichParam(CBC_PARAM_ACTION_MIPSTART, parameters_)].setStringValue(mipStartFile);
607   parameters_[whichParam(CLP_PARAM_ACTION_BASISOUT, parameters_)].setStringValue(exportBasisFile);
608   parameters_[whichParam(CLP_PARAM_ACTION_DEBUG, parameters_)].setStringValue(debugFile);
609   parameters_[whichParam(CLP_PARAM_ACTION_PRINTMASK, parameters_)].setStringValue(printMask);
610   parameters_[whichParam(CLP_PARAM_ACTION_DIRECTORY, parameters_)].setStringValue(directory);
611   parameters_[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, parameters_)].setStringValue(dirSample);
612   parameters_[whichParam(CLP_PARAM_ACTION_DIRNETLIB, parameters_)].setStringValue(dirNetlib);
613   parameters_[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, parameters_)].setStringValue(dirMiplib);
614   parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters_)].setDoubleValue(lpSolver->dualBound());
615   parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters_)].setDoubleValue(lpSolver->dualTolerance());
616   parameters_[whichParam(CLP_PARAM_ACTION_EXPORT, parameters_)].setStringValue(exportFile);
617   parameters_[whichParam(CLP_PARAM_INT_IDIOT, parameters_)].setIntValue(doIdiot);
618   parameters_[whichParam(CLP_PARAM_ACTION_IMPORT, parameters_)].setStringValue(importFile);
619   parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].setDoubleValue(1.0e-8);
620   int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_);
621   int value = 1;
622   clpSolver->messageHandler()->setLogLevel(1);
623   lpSolver->setLogLevel(1);
624   parameters_[iParam].setIntValue(value);
625   iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_);
626   model_.messageHandler()->setLogLevel(value);
627   parameters_[iParam].setIntValue(value);
628   parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters_)].setIntValue(lpSolver->factorizationFrequency());
629   parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, parameters_)].setIntValue(lpSolver->maximumIterations());
630   parameters_[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, parameters_)].setIntValue(outputFormat);
631   parameters_[whichParam(CLP_PARAM_INT_PRESOLVEPASS, parameters_)].setIntValue(preSolve);
632   parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, parameters_)].setIntValue(lpSolver->perturbation());
633   parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters_)].setDoubleValue(lpSolver->primalTolerance());
634   parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters_)].setDoubleValue(lpSolver->infeasibilityCost());
635   parameters_[whichParam(CLP_PARAM_ACTION_RESTORE, parameters_)].setStringValue(restoreFile);
636   parameters_[whichParam(CLP_PARAM_ACTION_SAVE, parameters_)].setStringValue(saveFile);
637   //parameters_[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters_,parameters_)].setDoubleValue(1.0e8);
638   parameters_[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, parameters_)].setDoubleValue(1.0e8);
639   parameters_[whichParam(CLP_PARAM_ACTION_SOLUTION, parameters_)].setStringValue(solutionFile);
640   parameters_[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, parameters_)].setStringValue(solutionFile);
641   parameters_[whichParam(CLP_PARAM_ACTION_SAVESOL, parameters_)].setStringValue(solutionSaveFile);
642   parameters_[whichParam(CLP_PARAM_INT_SPRINT, parameters_)].setIntValue(doSprint);
643   parameters_[whichParam(CLP_PARAM_INT_SUBSTITUTION, parameters_)].setIntValue(substitution);
644   parameters_[whichParam(CLP_PARAM_INT_DUALIZE, parameters_)].setIntValue(dualize);
645   parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters_)].setIntValue(model_.numberBeforeTrust());
646   parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].setIntValue(model_.getMaximumNodes());
647   parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters_)].setIntValue(model_.numberStrong());
648   parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight));
649   parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance));
650   parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement));
651   parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(testOsiParameters);
652   parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_)].setIntValue(1003);
653   initialPumpTune = 1003;
654 #ifdef CBC_THREAD
655   parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].setIntValue(0);
656 #endif
657   // Set up likely cut generators and defaults
658   parameters_[whichParam(CBC_PARAM_STR_PREPROCESS, parameters_)].setCurrentOption("sos");
659   parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].setIntValue(1057);
660   parameters_[whichParam(CBC_PARAM_INT_CUTPASSINTREE, parameters_)].setIntValue(1);
661   parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters_)].setIntValue(-1);
662   parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValue(100);
663   parameters_[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters_)].setCurrentOption("on");
664   parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].setCurrentOption("on");
665   parameters_[whichParam(CBC_PARAM_STR_NODESTRATEGY, parameters_)].setCurrentOption("fewest");
666   parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption("ifmove");
667   parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption("ifmove");
668   parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption("ifmove");
669   parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOption("ifmove");
670   parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, parameters_)].setCurrentOption("off");
671   parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, parameters_)].setCurrentOption("off");
672   parameters_[whichParam(CBC_PARAM_STR_GMICUTS, parameters_)].setCurrentOption("off");
673   parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters_)].setCurrentOption("ifmove");
674   parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters_)].setCurrentOption("ifmove");
675   parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters_)].setCurrentOption("ifmove");
676   parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters_)].setCurrentOption("ifmove");
677   parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, parameters_)].setCurrentOption("off");
678   parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, parameters_)].setCurrentOption("off");
679   parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].setCurrentOption("on");
680   parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].setCurrentOption("on");
681   parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].setCurrentOption("on");
682   parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].setCurrentOption("on");
683   parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters_)].setCurrentOption("off");
684   parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters_)].setCurrentOption("off");
685   parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters_)].setCurrentOption("off");
686   parameters_[whichParam(CBC_PARAM_STR_RANDROUND, parameters_)].setCurrentOption("off");
687   parameters_[whichParam(CBC_PARAM_STR_NAIVE, parameters_)].setCurrentOption("off");
688   parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].setCurrentOption("off");
689   parameters_[whichParam(CBC_PARAM_STR_DINS, parameters_)].setCurrentOption("off");
690   parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].setCurrentOption("off");
691   parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, parameters_)].setCurrentOption("off");
692   parameters_[whichParam(CBC_PARAM_STR_COSTSTRATEGY, parameters_)].setCurrentOption("off");
693   if (createSolver)
694     delete clpSolver;
695 }
696 
697 /*
698   Initialise a subset of the parameters prior to processing any input from
699   the user.
700 
701   Why this choice of subset?
702 */
703 /*!
704   \todo Guard/replace clp-specific code
705 */
fillValuesInSolver()706 void CbcSolver::fillValuesInSolver()
707 {
708   OsiSolverInterface *solver = model_.solver();
709   OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
710   assert(clpSolver);
711   ClpSimplex *lpSolver = clpSolver->getModelPtr();
712 
713   /*
714       Why are we reaching into the underlying solver(s) for these settings?
715       Shouldn't CbcSolver have its own defaults, which are then imposed on the
716       underlying solver?
717 
718       Coming at if from the other side, if CbcSolver had the capability to use
719       multiple solvers then it definitely makes sense to acquire the defaults from
720       the solver (on the assumption that we haven't processed command line
721       parameters yet, which can then override the defaults). But then it's more of
722       a challenge to avoid solver-specific coding here.
723     */
724   noPrinting_ = (lpSolver->logLevel() == 0);
725   CoinMessageHandler *generalMessageHandler = clpSolver->messageHandler();
726   generalMessageHandler->setPrefix(true);
727 
728   lpSolver->setPerturbation(50);
729   lpSolver->messageHandler()->setPrefix(false);
730 
731   parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters_)].setDoubleValue(lpSolver->dualBound());
732   parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters_)].setDoubleValue(lpSolver->dualTolerance());
733   /*
734      Why are we doing this? We read the log level from parameters_, set it into
735      the message handlers for cbc and the underlying solver. Then we read the
736      log level back from the handlers and use it to set the values in
737      parameters_!
738      */
739   int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_);
740   int value = parameters_[iParam].intValue();
741   clpSolver->messageHandler()->setLogLevel(value);
742   lpSolver->setLogLevel(value);
743   iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_);
744   value = parameters_[iParam].intValue();
745   model_.messageHandler()->setLogLevel(value);
746   parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].setIntValue(model_.logLevel());
747   parameters_[whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_)].setIntValue(lpSolver->logLevel());
748   parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters_)].setIntValue(lpSolver->factorizationFrequency());
749   parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, parameters_)].setIntValue(lpSolver->maximumIterations());
750   parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, parameters_)].setIntValue(lpSolver->perturbation());
751   parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters_)].setDoubleValue(lpSolver->primalTolerance());
752   parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters_)].setDoubleValue(lpSolver->infeasibilityCost());
753   parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters_)].setIntValue(model_.numberBeforeTrust());
754   parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].setIntValue(model_.getMaximumNodes());
755   parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters_)].setIntValue(model_.numberStrong());
756   parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight));
757   parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance));
758   parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement));
759 }
760 // Add user function
addUserFunction(CbcUser * function)761 void CbcSolver::addUserFunction(CbcUser *function)
762 {
763   CbcUser **temp = new CbcUser *[numberUserFunctions_ + 1];
764   int i;
765   for (i = 0; i < numberUserFunctions_; i++)
766     temp[i] = userFunction_[i];
767   delete[] userFunction_;
768   userFunction_ = temp;
769   userFunction_[numberUserFunctions_++] = function->clone();
770   delete[] statusUserFunction_;
771   statusUserFunction_ = NULL;
772 }
773 // Set user call back
setUserCallBack(CbcStopNow * function)774 void CbcSolver::setUserCallBack(CbcStopNow *function)
775 {
776   delete callBack_;
777   callBack_ = function->clone();
778 }
779 // Copy of model on initial load (will contain output solutions)
setOriginalSolver(OsiClpSolverInterface * originalSolver)780 void CbcSolver::setOriginalSolver(OsiClpSolverInterface *originalSolver)
781 {
782   delete originalSolver_;
783   OsiSolverInterface *temp = originalSolver->clone();
784   originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp);
785   assert(originalSolver_);
786 }
787 // Copy of model on initial load
setOriginalCoinModel(CoinModel * originalCoinModel)788 void CbcSolver::setOriginalCoinModel(CoinModel *originalCoinModel)
789 {
790   delete originalCoinModel_;
791   originalCoinModel_ = new CoinModel(*originalCoinModel);
792 }
793 // Add cut generator
addCutGenerator(CglCutGenerator * generator)794 void CbcSolver::addCutGenerator(CglCutGenerator *generator)
795 {
796   CglCutGenerator **temp = new CglCutGenerator *[numberCutGenerators_ + 1];
797   int i;
798   for (i = 0; i < numberCutGenerators_; i++)
799     temp[i] = cutGenerator_[i];
800   delete[] cutGenerator_;
801   cutGenerator_ = temp;
802   cutGenerator_[numberCutGenerators_++] = generator->clone();
803 }
804 
805 /*
806   The only other solver that's ever been used is cplex, and the use is
807   limited -- do the root with clp and all the cbc smarts, then give the
808   problem over to cplex to finish. Although the defines can be read in some
809   places to allow other options, nothing's been tested and success is
810   unlikely.
811 
812   CBC_OTHER_SOLVER == 1 is cplex.
813 */
814 
815 #if CBC_OTHER_SOLVER == 1
816 #ifndef COIN_HAS_CPX
817 #error "Configuration did not detect cplex installation."
818 #else
819 #include "OsiCpxSolverInterface.hpp"
820 #endif
821 #endif
822 
823 #ifdef COIN_HAS_ASL
824 #include "Cbc_ampl.h"
825 #endif
826 
827 static void statistics(ClpSimplex *originalModel, ClpSimplex *model);
828 static bool maskMatches(const int *starts, char **masks,
829   std::string &check);
830 static void generateCode(CbcModel *model, const char *fileName, int type, int preProcess);
831 #ifdef COIN_HAS_NTY
832 // returns number of constraints added
833 static int nautiedConstraints(CbcModel &model, int maxPass);
834 #endif
835 
836 // dummy fake main programs for UserClp and UserCbc
837 void fakeMain(ClpSimplex &model, OsiSolverInterface &osiSolver, CbcModel &babSolver);
838 void fakeMain2(ClpSimplex &model, OsiClpSolverInterface &osiSolver, int options);
839 
840 // Allow for interrupts
841 // But is this threadsafe? (so switched off by option)
842 
843 #include "CoinSignal.hpp"
844 static CbcModel *currentBranchModel = NULL;
845 
846 extern "C" {
signal_handler(int whichSignal)847 static void signal_handler(int whichSignal)
848 {
849   if (currentBranchModel != NULL) {
850     currentBranchModel->sayEventHappened(); // say why stopped
851     if (currentBranchModel->heuristicModel())
852       currentBranchModel->heuristicModel()->sayEventHappened();
853   }
854   return;
855 }
856 }
857 
858 //#define CBC_SIG_TRAP
859 #ifdef CBC_SIG_TRAP
860 #include <setjmp.h>
861 static sigjmp_buf cbc_seg_buffer;
862 extern "C" {
signal_handler_error(int whichSignal)863 static void signal_handler_error(int whichSignal)
864 {
865   siglongjmp(cbc_seg_buffer, 1);
866 }
867 }
868 #endif
869 
870 /*
871   Debug checks on special ordered sets.
872 
873   This is active only for debugging. The entire body of the routine becomes
874   a noop when COIN_DEVELOP is not defined. To avoid compiler warnings, the
875   formal parameters also need to go away.
876 */
877 #ifdef COIN_DEVELOP
checkSOS(CbcModel * babModel,const OsiSolverInterface * solver)878 void checkSOS(CbcModel *babModel, const OsiSolverInterface *solver)
879 #else
880 void checkSOS(CbcModel * /*babModel*/, const OsiSolverInterface * /*solver*/)
881 #endif
882 {
883 #ifdef COIN_DEVELOP
884   if (!babModel->ownObjects())
885     return;
886 #if COIN_DEVELOP > 2
887   //const double *objective = solver->getObjCoefficients() ;
888   const double *columnLower = solver->getColLower();
889   const double *columnUpper = solver->getColUpper();
890   const double *solution = solver->getColSolution();
891   //int numberRows = solver->getNumRows();
892   //double direction = solver->getObjSense();
893   //int iRow,iColumn;
894 #endif
895 
896   // Row copy
897   CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
898   //const double * elementByRow = matrixByRow.getElements();
899   //const int * column = matrixByRow.getIndices();
900   //const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
901   const int *rowLength = matrixByRow.getVectorLengths();
902 
903   // Column copy
904   CoinPackedMatrix matrixByCol(*solver->getMatrixByCol());
905   const double *element = matrixByCol.getElements();
906   const int *row = matrixByCol.getIndices();
907   const CoinBigIndex *columnStart = matrixByCol.getVectorStarts();
908   const int *columnLength = matrixByCol.getVectorLengths();
909 
910   const double *rowLower = solver->getRowLower();
911   const double *rowUpper = solver->getRowUpper();
912   OsiObject **objects = babModel->objects();
913   int numberObjects = babModel->numberObjects();
914   int numberColumns = solver->getNumCols();
915   for (int iObj = 0; iObj < numberObjects; iObj++) {
916     CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]);
917     if (objSOS) {
918       int n = objSOS->numberMembers();
919       const int *which = objSOS->members();
920 #if COIN_DEVELOP > 2
921       const double *weight = objSOS->weights();
922 #endif
923       int type = objSOS->sosType();
924       // convexity row?
925       int iColumn;
926       iColumn = which[0];
927       int j;
928       int convex = -1;
929       for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
930         int iRow = row[j];
931         double value = element[j];
932         if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0 && value == 1.0) {
933           // possible
934           if (rowLength[iRow] == n) {
935             if (convex == -1)
936               convex = iRow;
937             else
938               convex = -2;
939           }
940         }
941       }
942       printf("set %d of type %d has %d members - possible convexity row %d\n",
943         iObj, type, n, convex);
944       for (int i = 0; i < n; i++) {
945         iColumn = which[i];
946         // Column may have been added
947         if (iColumn < numberColumns) {
948           int convex2 = -1;
949           for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
950             int iRow = row[j];
951             if (iRow == convex) {
952               double value = element[j];
953               if (value == 1.0) {
954                 convex2 = iRow;
955               }
956             }
957           }
958           if (convex2 < 0 && convex >= 0) {
959             printf("odd convexity row\n");
960             convex = -2;
961           }
962 #if COIN_DEVELOP > 2
963           printf("col %d has weight %g and value %g, bounds %g %g\n",
964             iColumn, weight[i], solution[iColumn], columnLower[iColumn],
965             columnUpper[iColumn]);
966 #endif
967         }
968       }
969     }
970   }
971 #endif // COIN_DEVELOP
972 }
973 
dummyCallBack(CbcModel *,int)974 static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/)
975 {
976   return 0;
977 }
978 
979 /*
980   Global parameters for command processing.
981 
982   These will need to be moved into an object of some sort in order to make
983   this set of calls thread-safe.
984 */
985 
986 int CbcOrClpRead_mode = 1;
987 FILE *CbcOrClpReadCommand = stdin;
988 // Alternative to environment
989 extern char *alternativeEnvironment;
990 extern int CbcOrClpEnvironmentIndex;
991 
992 int callCbc1(const char *input2, CbcModel &model,
993   int callBack(CbcModel *currentSolver, int whereFrom),
994   CbcSolverUsefulData &parameterData);
995 
996 /*
997   Wrappers for CbcMain0, CbcMain1. The various forms of callCbc will eventually
998   resolve to a call to CbcMain0 followed by a call to callCbc1.
999 */
1000 /*
1001   Simplest calling form: supply just a string with the command options. The
1002   wrapper creates an OsiClpSolverInterface and calls the next wrapper.
1003 */
callCbc(const std::string input2)1004 int callCbc(const std::string input2)
1005 {
1006   char *input3 = CoinStrdup(input2.c_str());
1007   OsiClpSolverInterface solver1;
1008   int returnCode = callCbc(input3, solver1);
1009   free(input3);
1010   return returnCode;
1011 }
1012 
callCbc(const char * input2)1013 int callCbc(const char *input2)
1014 {
1015   {
1016     OsiClpSolverInterface solver1;
1017     return callCbc(input2, solver1);
1018   }
1019 }
1020 
1021 /*
1022   Second calling form: supply the command line and an OsiClpSolverInterface.
1023   the wrapper will create a CbcModel and call the next wrapper.
1024 */
1025 
callCbc(const std::string input2,OsiClpSolverInterface & solver1)1026 int callCbc(const std::string input2, OsiClpSolverInterface &solver1)
1027 {
1028   char *input3 = CoinStrdup(input2.c_str());
1029   int returnCode = callCbc(input3, solver1);
1030   free(input3);
1031   return returnCode;
1032 }
1033 
callCbc(const char * input2,OsiClpSolverInterface & solver1)1034 int callCbc(const char *input2, OsiClpSolverInterface &solver1)
1035 {
1036   CbcModel model(solver1);
1037   return callCbc(input2, model);
1038 }
1039 
1040 /*
1041   Third calling form: supply the command line and a CbcModel. This wrapper will
1042   actually call CbcMain0 and then call the next set of wrappers (callCbc1) to
1043   handle the call to CbcMain1.
1044 */
callCbc(const char * input2,CbcModel & babSolver)1045 int callCbc(const char *input2, CbcModel &babSolver)
1046 {
1047   CbcSolverUsefulData data;
1048 #ifndef CBC_NO_INTERRUPT
1049   data.useSignalHandler_ = true;
1050 #endif
1051 #ifndef CBC_NO_PRINTING
1052   data.noPrinting_ = false;
1053 #endif
1054   CbcMain0(babSolver, data);
1055   return callCbc1(input2, babSolver, dummyCallBack, data);
1056 }
1057 
callCbc(const std::string input2,CbcModel & babSolver)1058 int callCbc(const std::string input2, CbcModel &babSolver)
1059 {
1060   CbcSolverUsefulData cbcData;
1061   cbcData.noPrinting_ = false;
1062   char *input3 = CoinStrdup(input2.c_str());
1063   CbcMain0(babSolver, cbcData);
1064   int returnCode = callCbc1(input3, babSolver, dummyCallBack, cbcData);
1065   free(input3);
1066   return returnCode;
1067 }
1068 
1069 /*
1070   Various overloads of callCbc1. The first pair accepts just a CbcModel and
1071   supplements it with a dummy callback routine. The second pair allows the
1072   user to supply a callback. See CbcMain1 for further explanation of the
1073   callback. The various overloads of callCbc1 resolve to the final version,
1074   which breaks the string into individual parameter strings (i.e., creates
1075   something that looks like a standard argv vector).
1076 */
1077 
1078 // Disabling non thread safe overloads
1079 /*
1080    int callCbc1(const std::string input2, CbcModel & babSolver)
1081    {
1082    char * input3 = CoinStrdup(input2.c_str());
1083    int returnCode = callCbc1(input3, babSolver);
1084    free(input3);
1085    return returnCode;
1086    }
1087 
1088    int callCbc1(const char * input2, CbcModel & model)
1089    {
1090    return callCbc1(input2, model, dummyCallBack);
1091    }
1092 
1093    int callCbc1(const std::string input2, CbcModel & babSolver,
1094    int callBack(CbcModel * currentSolver, int whereFrom))
1095    {
1096    char * input3 = CoinStrdup(input2.c_str());
1097    int returnCode = callCbc1(input3, babSolver, callBack);
1098    free(input3);
1099    return returnCode;
1100    }
1101    */
callCbc1(const char * input2,CbcModel & model,int callBack (CbcModel * currentSolver,int whereFrom),CbcSolverUsefulData & parameterData)1102 int callCbc1(const char *input2, CbcModel &model,
1103   int callBack(CbcModel *currentSolver, int whereFrom),
1104   CbcSolverUsefulData &parameterData)
1105 {
1106   char *input = CoinStrdup(input2 ? input2 : "");
1107   size_t length = strlen(input);
1108   bool blank = input[0] == ' ';
1109   int n = blank ? 0 : 1;
1110   for (size_t i = 0; i < length; i++) {
1111     if (blank) {
1112       // look for next non blank
1113       if (input[i] == ' ') {
1114         continue;
1115       } else {
1116         n++;
1117         blank = false;
1118       }
1119     } else {
1120       // look for next blank
1121       if (input[i] != ' ') {
1122         continue;
1123       } else {
1124         blank = true;
1125       }
1126     }
1127   }
1128   char **argv = new char *[n + 2];
1129   argv[0] = CoinStrdup("cbc");
1130   size_t i = 0;
1131   while (input[i] == ' ')
1132     i++;
1133   for (int j = 0; j < n; j++) {
1134     size_t saveI = i;
1135     for (; i < length; i++) {
1136       // look for next blank
1137       if (input[i] != ' ') {
1138         continue;
1139       } else {
1140         break;
1141       }
1142     }
1143     input[i++] = '\0';
1144     argv[j + 1] = CoinStrdup(input + saveI);
1145     while (input[i] == ' ')
1146       i++;
1147   }
1148   argv[n + 1] = CoinStrdup("-quit");
1149   free(input);
1150   currentBranchModel = NULL;
1151   CbcOrClpRead_mode = 1;
1152   CbcOrClpReadCommand = stdin;
1153   int returnCode = CbcMain1(n + 2, const_cast< const char ** >(argv),
1154     model, callBack, parameterData);
1155   for (int k = 0; k < n + 2; k++)
1156     free(argv[k]);
1157   delete[] argv;
1158   return returnCode;
1159 }
1160 
callCbc1(const char * input2,CbcModel & model,int callBack (CbcModel * currentSolver,int whereFrom))1161 int callCbc1(const char *input2, CbcModel &model,
1162   int callBack(CbcModel *currentSolver, int whereFrom))
1163 {
1164   CbcSolverUsefulData data;
1165   // allow interrupts and printing
1166 #ifndef CBC_NO_INTERRUPT
1167   data.useSignalHandler_ = true;
1168 #endif
1169 #ifndef CBC_NO_PRINTING
1170   data.noPrinting_ = false;
1171 #endif
1172   return callCbc1(input2, model, callBack, data);
1173 }
1174 
1175 CglPreProcess *cbcPreProcessPointer = NULL;
1176 
1177 int CbcClpUnitTest(const CbcModel &saveModel,
1178   const std::string &dirMiplib, int testSwitch,
1179   const double *stuff);
1180 
1181 /*
1182    int CbcMain1 (int argc, const char *argv[],
1183    CbcModel  & model)
1184    {
1185    return CbcMain1(argc, argv, model, dummyCallBack);
1186    }*/
1187 
1188 #ifdef CBC_THREAD_SAFE
1189 // Copies of some input decoding
1190 
1191 static std::string
CoinReadGetCommand(int & whichArgument,int argc,const char * argv[])1192 CoinReadGetCommand(int &whichArgument, int argc, const char *argv[])
1193 {
1194   std::string field;
1195   if (whichArgument < argc)
1196     field = argv[whichArgument++];
1197   else
1198     field = "quit";
1199   if (field[0] == '-')
1200     field = field.substr(1);
1201   return field;
1202 }
1203 static std::string
CoinReadGetString(int & whichArgument,int argc,const char * argv[])1204 CoinReadGetString(int &whichArgument, int argc, const char *argv[])
1205 {
1206   std::string field;
1207   if (whichArgument < argc)
1208     field = argv[whichArgument++];
1209   else
1210     field = "";
1211   return field;
1212 }
1213 // valid 0 - okay, 1 bad, 2 not there
1214 static int
CoinReadGetIntField(int & whichArgument,int argc,const char * argv[],int * valid)1215 CoinReadGetIntField(int &whichArgument, int argc, const char *argv[], int *valid)
1216 {
1217   std::string field;
1218   if (whichArgument < argc)
1219     field = argv[whichArgument++];
1220   else
1221     field = "0";
1222   long int value = 0;
1223   const char *start = field.c_str();
1224   char *endPointer = NULL;
1225   // check valid
1226   value = strtol(start, &endPointer, 10);
1227   if (*endPointer == '\0') {
1228     *valid = 0;
1229   } else {
1230     *valid = 1;
1231     std::cout << "String of " << field;
1232   }
1233   return static_cast< int >(value);
1234 }
1235 static double
CoinReadGetDoubleField(int & whichArgument,int argc,const char * argv[],int * valid)1236 CoinReadGetDoubleField(int &whichArgument, int argc, const char *argv[], int *valid)
1237 {
1238   std::string field;
1239   if (whichArgument < argc)
1240     field = argv[whichArgument++];
1241   else
1242     field = "0.0";
1243   double value = 0.0;
1244   const char *start = field.c_str();
1245   char *endPointer = NULL;
1246   // check valid
1247   value = strtod(start, &endPointer);
1248   if (*endPointer == '\0') {
1249     *valid = 0;
1250   } else {
1251     *valid = 1;
1252     std::cout << "String of " << field;
1253   }
1254   return value;
1255 }
1256 // Redefine all
1257 #define CoinReadGetCommand(x, y) CoinReadGetCommand(whichArgument, x, y)
1258 #define CoinReadGetString(x, y) CoinReadGetString(whichArgument, x, y)
1259 #define CoinReadGetIntField(x, y, z) CoinReadGetIntField(whichArgument, x, y, z)
1260 #define CoinReadGetDoubleField(x, y, z) CoinReadGetDoubleField(whichArgument, x, y, z)
1261 #endif
1262 // Default Constructor
CbcSolverUsefulData()1263 CbcSolverUsefulData::CbcSolverUsefulData()
1264 {
1265   totalTime_ = 0.0;
1266   noPrinting_ = true;
1267   useSignalHandler_ = false;
1268   establishParams(parameters_);
1269 }
1270 
1271 /* Copy constructor .
1272  */
CbcSolverUsefulData(const CbcSolverUsefulData & rhs)1273 CbcSolverUsefulData::CbcSolverUsefulData(const CbcSolverUsefulData &rhs)
1274 {
1275   totalTime_ = rhs.totalTime_;
1276   noPrinting_ = rhs.noPrinting_;
1277   useSignalHandler_ = rhs.useSignalHandler_;
1278   this->parameters_ = rhs.parameters_;
1279 }
1280 
1281 // Assignment operator
operator =(const CbcSolverUsefulData & rhs)1282 CbcSolverUsefulData &CbcSolverUsefulData::operator=(const CbcSolverUsefulData &rhs)
1283 {
1284   if (this != &rhs) {
1285     totalTime_ = rhs.totalTime_;
1286     noPrinting_ = rhs.noPrinting_;
1287     useSignalHandler_ = rhs.useSignalHandler_;
1288     this->parameters_ = rhs.parameters_;
1289   }
1290   return *this;
1291 }
1292 
1293 // Destructor
~CbcSolverUsefulData()1294 CbcSolverUsefulData::~CbcSolverUsefulData()
1295 {
1296 }
1297 
1298 /*
1299   Meaning of whereFrom:
1300     1 after initial solve by dualsimplex etc
1301     2 after preprocessing
1302     3 just before branchAndBound (so user can override)
1303     4 just after branchAndBound (before postprocessing)
1304     5 after postprocessing
1305     6 after a user called heuristic phase
1306 */
1307 
CbcMain1(int argc,const char * argv[],CbcModel & model,int callBack (CbcModel * currentSolver,int whereFrom))1308 int CbcMain1(int argc, const char *argv[],
1309   CbcModel &model,
1310   int callBack(CbcModel *currentSolver, int whereFrom))
1311 {
1312   CbcSolverUsefulData data;
1313   // allow interrupts and printing
1314   data.noPrinting_ = false;
1315   data.useSignalHandler_ = true;
1316   return CbcMain1(argc, argv, model, callBack, data);
1317 }
1318 // and simpler version
CbcMain1(int argc,const char * argv[],CbcModel & model)1319 int CbcMain1(int argc, const char *argv[],
1320 	     CbcModel &model)
1321 {
1322   CbcSolverUsefulData data;
1323   // allow interrupts and printing
1324   data.noPrinting_ = false;
1325   data.useSignalHandler_ = true;
1326   return CbcMain1(argc, argv, model, dummyCallBack, data);
1327 }
1328 static void printGeneralMessage(CbcModel &model, const char *message);
1329 /*
1330   Meaning of whereFrom:
1331     1 after initial solve by dualsimplex etc
1332     2 after preprocessing
1333     3 just before branchAndBound (so user can override)
1334     4 just after branchAndBound (before postprocessing)
1335     5 after postprocessing
1336     6 after a user called heuristic phase
1337 */
CbcMain1(int argc,const char * argv[],CbcModel & model,int callBack (CbcModel * currentSolver,int whereFrom),CbcSolverUsefulData & parameterData)1338 int CbcMain1(int argc, const char *argv[],
1339   CbcModel &model,
1340   int callBack(CbcModel *currentSolver, int whereFrom),
1341   CbcSolverUsefulData &parameterData)
1342 {
1343   std::vector< CbcOrClpParam > parameters_(parameterData.parameters_);
1344   double totalTime = parameterData.totalTime_;
1345   bool noPrinting = parameterData.noPrinting_;
1346   bool useSignalHandler = parameterData.useSignalHandler_;
1347   CbcModel &model_ = model;
1348   CglPreProcess *preProcessPointer = NULL;
1349 #ifdef CBC_THREAD_SAFE
1350   // Initialize argument
1351   int whichArgument = 1;
1352 #endif
1353 #ifdef CBC_USE_INITIAL_TIME
1354   if (model_.useElapsedTime())
1355     model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay());
1356   else
1357     model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime());
1358 #endif
1359   CbcModel *babModel_ = NULL;
1360   int returnMode = 1;
1361   CbcOrClpRead_mode = 1;
1362   int statusUserFunction_[1];
1363   int numberUserFunctions_ = 1; // to allow for ampl
1364   // Statistics
1365   double statistics_seconds = 0.0, statistics_obj = 0.0;
1366   double statistics_sys_seconds = 0.0, statistics_elapsed_seconds = 0.0;
1367   CoinWallclockTime();
1368   double statistics_continuous = 0.0, statistics_tighter = 0.0;
1369   double statistics_cut_time = 0.0;
1370   int statistics_nodes = 0, statistics_iterations = 0;
1371   int statistics_nrows = 0, statistics_ncols = 0;
1372   int statistics_nprocessedrows = 0, statistics_nprocessedcols = 0;
1373   std::string statistics_result;
1374   int *statistics_number_cuts = NULL;
1375   const char **statistics_name_generators = NULL;
1376   int statistics_number_generators = 0;
1377   memset(statusUserFunction_, 0, numberUserFunctions_ * sizeof(int));
1378   /* Note
1379        This is meant as a stand-alone executable to do as much of coin as possible.
1380        It should only have one solver known to it.
1381     */
1382   CoinMessageHandler *generalMessageHandler = model_.messageHandler();
1383   generalMessageHandler->setPrefix(false);
1384   int numberLotSizing = 0;
1385   typedef struct {
1386     double low;
1387     double high;
1388     int column;
1389   } lotStruct;
1390   lotStruct *lotsize = NULL;
1391 #ifndef CBC_OTHER_SOLVER
1392   OsiClpSolverInterface *originalSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
1393   assert(originalSolver);
1394   // Move handler across if not default
1395   if (!originalSolver->defaultHandler() && originalSolver->getModelPtr()->defaultHandler())
1396     originalSolver->getModelPtr()->passInMessageHandler(originalSolver->messageHandler());
1397   CoinMessages generalMessages = originalSolver->getModelPtr()->messages();
1398   char generalPrint[10000];
1399   if (originalSolver->getModelPtr()->logLevel() == 0)
1400     noPrinting = true;
1401 #elif CBC_OTHER_SOLVER == 1
1402   OsiCpxSolverInterface *originalSolver = dynamic_cast< OsiCpxSolverInterface * >(model_.solver());
1403   assert(originalSolver);
1404   OsiClpSolverInterface dummySolver;
1405   OsiCpxSolverInterface *clpSolver = originalSolver;
1406   CoinMessages generalMessages = dummySolver.getModelPtr()->messages();
1407   char generalPrint[10000];
1408   noPrinting = true;
1409 #endif
1410   bool noPrinting_ = noPrinting;
1411   // Say not in integer
1412   int integerStatus = -1;
1413   // Say no resolve after cuts
1414   model_.setResolveAfterTakeOffCuts(false);
1415   // see if log in list
1416   for (int i = 1; i < argc; i++) {
1417     if (!strncmp(argv[i], "log", 3)) {
1418       const char *equals = strchr(argv[i], '=');
1419       if (equals && atoi(equals + 1) != 0)
1420         noPrinting_ = false;
1421       else
1422         noPrinting_ = true;
1423       break;
1424     } else if (!strncmp(argv[i], "-log", 4) && i < argc - 1) {
1425       if (atoi(argv[i + 1]) != 0)
1426         noPrinting_ = false;
1427       else
1428         noPrinting_ = true;
1429       break;
1430     }
1431   }
1432   double time0;
1433   double time0Elapsed = CoinGetTimeOfDay();
1434   {
1435     double time1 = CoinCpuTime(), time2;
1436     time0 = time1;
1437     double time1Elapsed = time0Elapsed;
1438     bool goodModel = (originalSolver->getNumCols()) ? true : false;
1439 
1440     // register signal handler
1441     //CoinSighandler_t saveSignal=signal(SIGINT,signal_handler);
1442 #if CBC_QUIET < 2
1443     if (useSignalHandler)
1444       signal(SIGINT, signal_handler);
1445 #endif
1446     // Set up all non-standard stuff
1447     int cutPass = -1234567;
1448     int cutPassInTree = -1234567;
1449     int tunePreProcess = 0;
1450     int testOsiParameters = -1;
1451     // 0 normal, 1 from ampl or MIQP etc (2 allows cuts)
1452     int complicatedInteger = 0;
1453     OsiSolverInterface *solver = model_.solver();
1454     if (noPrinting_)
1455       setCbcOrClpPrinting(false);
1456 #ifndef CBC_OTHER_SOLVER
1457     OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
1458     ClpSimplex *lpSolver = clpSolver->getModelPtr();
1459     if (noPrinting_) {
1460       lpSolver->setLogLevel(0);
1461     }
1462 #else
1463     ClpSimplex *lpSolver = NULL;
1464 #endif
1465     // For priorities etc
1466     int *priorities = NULL;
1467     int *branchDirection = NULL;
1468     double *pseudoDown = NULL;
1469     double *pseudoUp = NULL;
1470     double *solutionIn = NULL;
1471     int *prioritiesIn = NULL;
1472     std::vector< std::pair< std::string, double > > mipStart;
1473     std::vector< std::pair< std::string, double > > mipStartBefore;
1474     int numberSOS = 0;
1475     int *sosStart = NULL;
1476     int *sosIndices = NULL;
1477     char *sosType = NULL;
1478     double *sosReference = NULL;
1479     int *cut = NULL;
1480     int *sosPriority = NULL;
1481     CglStored storedAmpl;
1482     CoinModel *coinModel = NULL;
1483     CoinModel saveCoinModel;
1484     CoinModel saveTightenedModel;
1485     int *whichColumn = NULL;
1486     int *knapsackStart = NULL;
1487     int *knapsackRow = NULL;
1488     int numberKnapsack = 0;
1489 #ifdef COIN_HAS_ASL
1490     ampl_info info;
1491     {
1492       memset(&info, 0, sizeof(info));
1493       if (argc > 2 && !strcmp(argv[2], "-AMPL")) {
1494         statusUserFunction_[0] = 1;
1495         // see if log in list
1496         noPrinting_ = true;
1497         for (int i = 1; i < argc; i++) {
1498           if (!strncmp(argv[i], "log", 3)) {
1499             const char *equals = strchr(argv[i], '=');
1500             if (equals && atoi(equals + 1) > 0) {
1501               noPrinting_ = false;
1502               info.logLevel = atoi(equals + 1);
1503               int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_);
1504               parameters_[log].setIntValue(info.logLevel);
1505               // mark so won't be overWritten
1506               info.numberRows = -1234567;
1507               break;
1508             }
1509           }
1510         }
1511 
1512         union {
1513           void *voidModel;
1514           CoinModel *model;
1515         } coinModelStart;
1516         coinModelStart.model = NULL;
1517         int returnCode = readAmpl(&info, argc, const_cast< char ** >(argv), &coinModelStart.voidModel);
1518         coinModel = coinModelStart.model;
1519         if (returnCode)
1520           return returnCode;
1521         CbcOrClpRead_mode = 2; // so will start with parameters
1522         // see if log in list (including environment)
1523         for (int i = 1; i < info.numberArguments; i++) {
1524           if (!strcmp(info.arguments[i], "log")) {
1525             if (i < info.numberArguments - 1 && atoi(info.arguments[i + 1]) > 0)
1526               noPrinting_ = false;
1527             break;
1528           }
1529         }
1530         if (noPrinting_) {
1531           model_.messageHandler()->setLogLevel(0);
1532           setCbcOrClpPrinting(false);
1533         }
1534         if (!noPrinting_)
1535           printf("%d rows, %d columns and %d elements\n",
1536             info.numberRows, info.numberColumns, info.numberElements);
1537 #ifdef COIN_HAS_LINK
1538         if (!coinModel) {
1539 #endif
1540           solver->loadProblem(info.numberColumns, info.numberRows,
1541             reinterpret_cast< const CoinBigIndex * >(info.starts),
1542             info.rows, info.elements,
1543             info.columnLower, info.columnUpper, info.objective,
1544             info.rowLower, info.rowUpper);
1545           // take off cuts if ampl wants that
1546           if (info.cut && 0) {
1547             printf("AMPL CUTS OFF until global cuts fixed\n");
1548             info.cut = NULL;
1549           }
1550           if (info.cut) {
1551             int numberRows = info.numberRows;
1552             int *whichRow = new int[numberRows];
1553             // Row copy
1554             const CoinPackedMatrix *matrixByRow = solver->getMatrixByRow();
1555             const double *elementByRow = matrixByRow->getElements();
1556             const int *column = matrixByRow->getIndices();
1557             const CoinBigIndex *rowStart = matrixByRow->getVectorStarts();
1558             const int *rowLength = matrixByRow->getVectorLengths();
1559 
1560             const double *rowLower = solver->getRowLower();
1561             const double *rowUpper = solver->getRowUpper();
1562             int nDelete = 0;
1563             for (int iRow = 0; iRow < numberRows; iRow++) {
1564               if (info.cut[iRow]) {
1565                 whichRow[nDelete++] = iRow;
1566                 int start = rowStart[iRow];
1567                 storedAmpl.addCut(rowLower[iRow], rowUpper[iRow],
1568                   rowLength[iRow], column + start, elementByRow + start);
1569               }
1570             }
1571             solver->deleteRows(nDelete, whichRow);
1572             delete[] whichRow;
1573           }
1574 #ifdef COIN_HAS_LINK
1575         } else {
1576 #ifndef CBC_OTHER_SOLVER
1577           // save
1578           saveCoinModel = *coinModel;
1579           // load from coin model
1580           OsiSolverLink solver1;
1581           OsiSolverInterface *solver2 = solver1.clone();
1582           model_.assignSolver(solver2, false);
1583           OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver());
1584           assert(si != NULL);
1585           si->setDefaultMeshSize(0.001);
1586           // need some relative granularity
1587           si->setDefaultBound(100.0);
1588           double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue();
1589           if (dextra3)
1590             si->setDefaultMeshSize(dextra3);
1591           si->setDefaultBound(100000.0);
1592           si->setIntegerPriority(1000);
1593           si->setBiLinearPriority(10000);
1594           CoinModel *model2 = reinterpret_cast< CoinModel * >(coinModel);
1595           int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].intValue();
1596           si->load(*model2, true, logLevel);
1597           // redo
1598           solver = model_.solver();
1599           clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
1600           lpSolver = clpSolver->getModelPtr();
1601           clpSolver->messageHandler()->setLogLevel(0);
1602           testOsiParameters = 0;
1603           parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(0);
1604           complicatedInteger = 1;
1605           if (info.cut) {
1606             printf("Sorry - can't do cuts with LOS as ruins delicate row order\n");
1607             abort();
1608             int numberRows = info.numberRows;
1609             int *whichRow = new int[numberRows];
1610             // Row copy
1611             const CoinPackedMatrix *matrixByRow = solver->getMatrixByRow();
1612             const double *elementByRow = matrixByRow->getElements();
1613             const int *column = matrixByRow->getIndices();
1614             const CoinBigIndex *rowStart = matrixByRow->getVectorStarts();
1615             const int *rowLength = matrixByRow->getVectorLengths();
1616 
1617             const double *rowLower = solver->getRowLower();
1618             const double *rowUpper = solver->getRowUpper();
1619             int nDelete = 0;
1620             for (int iRow = 0; iRow < numberRows; iRow++) {
1621               if (info.cut[iRow]) {
1622                 whichRow[nDelete++] = iRow;
1623                 int start = rowStart[iRow];
1624                 storedAmpl.addCut(rowLower[iRow], rowUpper[iRow],
1625                   rowLength[iRow], column + start, elementByRow + start);
1626               }
1627             }
1628             solver->deleteRows(nDelete, whichRow);
1629             // and special matrix
1630             si->cleanMatrix()->deleteRows(nDelete, whichRow);
1631             delete[] whichRow;
1632           }
1633 #endif
1634         }
1635 #endif
1636         // If we had a solution use it
1637         if (info.primalSolution) {
1638           solver->setColSolution(info.primalSolution);
1639         }
1640         // status
1641         if (info.rowStatus) {
1642           unsigned char *statusArray = lpSolver->statusArray();
1643           int i;
1644           for (i = 0; i < info.numberColumns; i++)
1645             statusArray[i] = static_cast< unsigned char >(info.columnStatus[i]);
1646           statusArray += info.numberColumns;
1647           for (i = 0; i < info.numberRows; i++)
1648             statusArray[i] = static_cast< unsigned char >(info.rowStatus[i]);
1649           CoinWarmStartBasis *basis = lpSolver->getBasis();
1650           solver->setWarmStart(basis);
1651           delete basis;
1652         }
1653         freeArrays1(&info);
1654         // modify objective if necessary
1655         solver->setObjSense(info.direction);
1656         solver->setDblParam(OsiObjOffset, -info.offset);
1657         if (info.offset) {
1658           sprintf(generalPrint, "Ampl objective offset is %g",
1659             info.offset);
1660           generalMessageHandler->message(CLP_GENERAL, generalMessages)
1661             << generalPrint
1662             << CoinMessageEol;
1663         }
1664         // Set integer variables (unless nonlinear when set)
1665         if (!info.nonLinear) {
1666           for (int i = info.numberColumns - info.numberIntegers;
1667                i < info.numberColumns; i++)
1668             solver->setInteger(i);
1669         }
1670         goodModel = true;
1671         // change argc etc
1672         argc = info.numberArguments;
1673         argv = const_cast< const char ** >(info.arguments);
1674       }
1675     }
1676 #endif
1677     // default action on import
1678     int allowImportErrors = 0;
1679     int keepImportNames = 1;
1680     int doIdiot = -1;
1681     int outputFormat = 2;
1682     int slpValue = -1;
1683     int cppValue = -1;
1684     int printOptions = 0;
1685     int printMode = 0;
1686     int presolveOptions = 0;
1687     int substitution = 3;
1688     int dualize = 3;
1689     int doCrash = 0;
1690     int doVector = 0;
1691     int doSprint = -1;
1692     int doScaling = 4;
1693     // set reasonable defaults
1694     int preSolve = 5;
1695     int preProcess = 4;
1696     bool useStrategy = false;
1697     bool preSolveFile = false;
1698     bool strongChanged = false;
1699     bool pumpChanged = false;
1700 
1701     double djFix = 1.0e100;
1702     double tightenFactor = 0.0;
1703     const char dirsep = CoinFindDirSeparator();
1704     std::string directory;
1705     std::string dirSample;
1706     std::string dirNetlib;
1707     std::string dirMiplib;
1708     if (dirsep == '/') {
1709       directory = "./";
1710       dirSample = "../../Data/Sample/";
1711       dirNetlib = "../../Data/Netlib/";
1712       dirMiplib = "../../Data/miplib3/";
1713     } else {
1714       directory = ".\\";
1715       dirSample = "..\\..\\..\\..\\Data\\Sample\\";
1716       dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
1717       dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
1718     }
1719     std::string defaultDirectory = directory;
1720     std::string importFile = "";
1721     std::string exportFile = "default.mps";
1722     std::string importBasisFile = "";
1723     std::string importPriorityFile = "";
1724     std::string debugFile = "";
1725     std::string printMask = "";
1726     double *debugValues = NULL;
1727     int numberDebugValues = -1;
1728     int basisHasValues = 0;
1729     std::string exportBasisFile = "default.bas";
1730     std::string saveFile = "default.prob";
1731     std::string restoreFile = "default.prob";
1732     std::string solutionFile = "stdout";
1733     std::string solutionSaveFile = "solution.file";
1734     int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_);
1735     int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_);
1736 #ifndef CBC_OTHER_SOLVER
1737     double normalIncrement = model_.getCutoffIncrement();
1738     ;
1739 #endif
1740     if (testOsiParameters >= 0) {
1741       // trying nonlinear - switch off some stuff
1742       preProcess = 0;
1743     }
1744     // Set up likely cut generators and defaults
1745     int nodeStrategy = 0;
1746     bool dominatedCuts = false;
1747     int doSOS = 1;
1748     int verbose = 0;
1749     CglGomory gomoryGen;
1750     // try larger limit
1751     gomoryGen.setLimitAtRoot(1000);
1752     gomoryGen.setLimit(50);
1753     // set default action (0=off,1=on,2=root)
1754     int gomoryAction = 3;
1755 
1756     CglProbing probingGen;
1757     probingGen.setUsingObjective(1);
1758     probingGen.setMaxPass(1);
1759     probingGen.setMaxPassRoot(1);
1760     // Number of unsatisfied variables to look at
1761     probingGen.setMaxProbe(10);
1762     probingGen.setMaxProbeRoot(50);
1763     // How far to follow the consequences
1764     probingGen.setMaxLook(10);
1765     probingGen.setMaxLookRoot(50);
1766     probingGen.setMaxLookRoot(10);
1767     // Only look at rows with fewer than this number of elements
1768     probingGen.setMaxElements(200);
1769     probingGen.setMaxElementsRoot(300);
1770     probingGen.setRowCuts(3);
1771     // set default action (0=off,1=on,2=root)
1772     int probingAction = 1;
1773 
1774     CglKnapsackCover knapsackGen;
1775     //knapsackGen.switchOnExpensive();
1776     //knapsackGen.setMaxInKnapsack(100);
1777     // set default action (0=off,1=on,2=root)
1778     int knapsackAction = 3;
1779 
1780     CglRedSplit redsplitGen;
1781     //redsplitGen.setLimit(100);
1782     // set default action (0=off,1=on,2=root)
1783     // Off as seems to give some bad cuts
1784     int redsplitAction = 0;
1785 
1786     CglRedSplit2 redsplit2Gen;
1787     //redsplit2Gen.setLimit(100);
1788     // set default action (0=off,1=on,2=root)
1789     // Off
1790     int redsplit2Action = 0;
1791 
1792     CglGMI GMIGen;
1793     //GMIGen.setLimit(100);
1794     // set default action (0=off,1=on,2=root)
1795     // Off
1796     int GMIAction = 0;
1797 
1798     CglFakeClique cliqueGen(NULL, false);
1799     //CglClique cliqueGen(false,true);
1800     cliqueGen.setStarCliqueReport(false);
1801     cliqueGen.setRowCliqueReport(false);
1802     cliqueGen.setMinViolation(0.1);
1803     // set default action (0=off,1=on,2=root)
1804     int cliqueAction = 3;
1805 
1806     // maxaggr,multiply,criterion(1-3)
1807     CglMixedIntegerRounding2 mixedGen(1, true, 1);
1808     // set default action (0=off,1=on,2=root)
1809     int mixedAction = 3;
1810     mixedGen.setDoPreproc(1); // safer (and better)
1811 
1812     CglFlowCover flowGen;
1813     // set default action (0=off,1=on,2=root)
1814     int flowAction = 3;
1815 
1816     CglTwomir twomirGen;
1817     twomirGen.setMaxElements(250);
1818     // set default action (0=off,1=on,2=root)
1819     int twomirAction = 3;
1820 #ifndef DEBUG_MALLOC
1821     CglLandP landpGen;
1822     landpGen.validator().setMinViolation(1.0e-4);
1823 #endif
1824     // set default action (0=off,1=on,2=root)
1825     int landpAction = 0;
1826     CglResidualCapacity residualCapacityGen;
1827     residualCapacityGen.setDoPreproc(1); // always preprocess
1828     // set default action (0=off,1=on,2=root)
1829     int residualCapacityAction = 0;
1830 
1831     CglZeroHalf zerohalfGen;
1832     //zerohalfGen.switchOnExpensive();
1833     // set default action (0=off,1=on,2=root)
1834     int zerohalfAction = 3;
1835 
1836     // Stored cuts
1837     //bool storedCuts = false;
1838 
1839     int useCosts = 0;
1840     // don't use input solution
1841     int useSolution = -1;
1842 
1843     // total number of commands read
1844     int numberGoodCommands = 0;
1845     // Set false if user does anything advanced
1846     bool defaultSettings = true;
1847 
1848     // Hidden stuff for barrier
1849     int choleskyType = 0;
1850     int gamma = 0;
1851     int scaleBarrier = 0;
1852     int doKKT = 0;
1853     int crossover = 2; // do crossover unless quadratic
1854     bool biLinearProblem = false;
1855     // For names
1856     int lengthName = 0;
1857     std::vector< std::string > rowNames;
1858     std::vector< std::string > columnNames;
1859     // Default strategy stuff
1860     {
1861       // try changing tolerance at root
1862 #define MORE_CUTS
1863 #ifdef MORE_CUTS
1864       gomoryGen.setAwayAtRoot(0.005);
1865       twomirGen.setAwayAtRoot(0.005);
1866       twomirGen.setAway(0.01);
1867       //twomirGen.setMirScale(1,1);
1868       //twomirGen.setTwomirScale(1,1);
1869       //twomirGen.setAMax(2);
1870 #else
1871       gomoryGen.setAwayAtRoot(0.01);
1872       twomirGen.setAwayAtRoot(0.01);
1873       twomirGen.setAway(0.01);
1874 #endif
1875       int iParam;
1876       iParam = whichParam(CBC_PARAM_INT_DIVEOPT, parameters_);
1877       parameters_[iParam].setIntValue(2);
1878       iParam = whichParam(CBC_PARAM_INT_FPUMPITS, parameters_);
1879       parameters_[iParam].setIntValue(30);
1880       iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_);
1881       parameters_[iParam].setIntValue(1005043);
1882       initialPumpTune = 1005043;
1883       iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_);
1884       parameters_[iParam].setIntValue(6);
1885       tunePreProcess = 6;
1886       iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_);
1887       parameters_[iParam].setCurrentOption("on");
1888       iParam = whichParam(CBC_PARAM_STR_RINS, parameters_);
1889       parameters_[iParam].setCurrentOption("on");
1890       iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_);
1891       parameters_[iParam].setCurrentOption("on");
1892       probingAction = 3;
1893       //parameters_[iParam].setCurrentOption("forceOnStrong");
1894       //probingAction = 8;
1895     }
1896     std::string field;
1897 #if CBC_QUIET == 0
1898     if (!noPrinting_) {
1899       sprintf(generalPrint,
1900         "Welcome to the CBC MILP Solver \n");
1901       if (strcmp(CBC_VERSION, "trunk")) {
1902         sprintf(generalPrint + strlen(generalPrint),
1903           "Version: %s \n", CBC_VERSION);
1904       } else {
1905         sprintf(generalPrint + strlen(generalPrint),
1906           "Version: Trunk (unstable) \n");
1907       }
1908       sprintf(generalPrint + strlen(generalPrint),
1909         "Build Date: %s \n", __DATE__);
1910 #ifdef CBC_SVN_REV
1911       sprintf(generalPrint + strlen(generalPrint),
1912         "Revision Number: %d \n", CBC_SVN_REV);
1913 #endif
1914       generalMessageHandler->message(CLP_GENERAL, generalMessages)
1915         << generalPrint
1916         << CoinMessageEol;
1917       // Print command line
1918       if (argc > 1) {
1919         bool foundStrategy = false;
1920         sprintf(generalPrint, "command line - ");
1921         for (int i = 0; i < argc; i++) {
1922           if (!argv[i])
1923             break;
1924           if (strstr(argv[i], "strat"))
1925             foundStrategy = true;
1926           sprintf(generalPrint + strlen(generalPrint), "%s ", argv[i]);
1927         }
1928         if (!foundStrategy)
1929           sprintf(generalPrint + strlen(generalPrint), "(default strategy 1)");
1930         generalMessageHandler->message(CLP_GENERAL, generalMessages)
1931           << generalPrint
1932           << CoinMessageEol;
1933       }
1934     }
1935 #endif
1936     while (1) {
1937       // next command
1938       field = CoinReadGetCommand(argc, argv);
1939       // Reset time
1940       time1 = CoinCpuTime();
1941       time1Elapsed = CoinGetTimeOfDay();
1942       // adjust field if has odd trailing characters
1943       char temp[200];
1944       strcpy(temp, field.c_str());
1945       int length = static_cast< int >(strlen(temp));
1946       for (int k = length - 1; k >= 0; k--) {
1947         if (temp[k] < ' ')
1948           length--;
1949         else
1950           break;
1951       }
1952       temp[length] = '\0';
1953       field = temp;
1954       // exit if null or similar
1955       if (!field.length()) {
1956         if (numberGoodCommands == 1 && goodModel) {
1957           // we just had file name - do branch and bound
1958           field = "branch";
1959         } else if (!numberGoodCommands) {
1960           // let's give the sucker a hint
1961           std::cout
1962             << "CoinSolver takes input from arguments ( - switches to stdin)"
1963             << std::endl
1964             << "Enter ? for list of commands or help" << std::endl;
1965           field = "-";
1966         } else {
1967           break;
1968         }
1969       }
1970 
1971       // see if ? at end
1972       size_t numberQuery = 0;
1973       if (field != "?" && field != "???") {
1974         size_t length = field.length();
1975         size_t i;
1976         for (i = length - 1; i > 0; i--) {
1977           if (field[i] == '?')
1978             numberQuery++;
1979           else
1980             break;
1981         }
1982         field = field.substr(0, length - numberQuery);
1983       }
1984       // find out if valid command
1985       int iParam;
1986       int numberMatches = 0;
1987       int firstMatch = -1;
1988       for (iParam = 0; iParam < (int)parameters_.size(); iParam++) {
1989         int match = parameters_[iParam].matches(field);
1990         if (match == 1) {
1991           numberMatches = 1;
1992           firstMatch = iParam;
1993           break;
1994         } else {
1995           if (match && firstMatch < 0)
1996             firstMatch = iParam;
1997           numberMatches += match >> 1;
1998         }
1999       }
2000       if (iParam < (int)parameters_.size() && !numberQuery) {
2001         // found
2002         CbcOrClpParam found = parameters_[iParam];
2003         CbcOrClpParameterType type = found.type();
2004         int valid;
2005         numberGoodCommands++;
2006         if (type == CBC_PARAM_ACTION_BAB && goodModel) {
2007 #ifndef CBC_USE_INITIAL_TIME
2008           if (model_.useElapsedTime())
2009             model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay());
2010           else
2011             model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime());
2012 #endif
2013           biLinearProblem = false;
2014           // check if any integers
2015 #ifndef CBC_OTHER_SOLVER
2016 #ifdef COIN_HAS_ASL
2017           if (info.numberSos && doSOS && statusUserFunction_[0]) {
2018             // SOS
2019             numberSOS = info.numberSos;
2020           }
2021 #endif
2022           lpSolver = clpSolver->getModelPtr();
2023           if (!lpSolver->integerInformation() && !numberSOS && !clpSolver->numberSOS() && !model_.numberObjects() && !clpSolver->numberObjects()) {
2024             type = CLP_PARAM_ACTION_DUALSIMPLEX;
2025 #ifdef CBC_MAXIMUM_BOUND
2026 	  } else {
2027 	    double * lower = lpSolver->columnLower();
2028 	    double * upper = lpSolver->columnUpper();
2029 	    int numberColumns = lpSolver->numberColumns();
2030 	    for (int i=0;i<numberColumns;i++) {
2031 	      lower[i] = CoinMax(lower[i],-CBC_MAXIMUM_BOUND);
2032 	      upper[i] = CoinMin(upper[i],CBC_MAXIMUM_BOUND);
2033 	    }
2034 #endif
2035 	  }
2036 #endif
2037         }
2038         if (type == CBC_PARAM_GENERALQUERY) {
2039           bool evenHidden = false;
2040           int printLevel = parameters_[whichParam(CLP_PARAM_STR_ALLCOMMANDS,
2041                                          parameters_)]
2042                              .currentOptionAsInteger();
2043           int convertP[] = { 2, 1, 0 };
2044           printLevel = convertP[printLevel];
2045           if ((verbose & 8) != 0) {
2046             // even hidden
2047             evenHidden = true;
2048             verbose &= ~8;
2049           }
2050 #ifdef COIN_HAS_ASL
2051           if (verbose < 4 && statusUserFunction_[0])
2052             verbose += 4;
2053 #endif
2054           if (verbose < 4) {
2055             std::cout << "In argument list keywords have leading - "
2056                          ", -stdin or just - switches to stdin"
2057                       << std::endl;
2058             std::cout << "One command per line (and no -)" << std::endl;
2059             std::cout << "abcd? gives list of possibilities, if only one + explanation" << std::endl;
2060             std::cout << "abcd?? adds explanation, if only one fuller help" << std::endl;
2061             std::cout << "abcd without value (where expected) gives current value" << std::endl;
2062             std::cout << "abcd value sets value" << std::endl;
2063             std::cout << "Commands are:" << std::endl;
2064           } else {
2065             std::cout << "Cbc options are set within AMPL with commands like:" << std::endl
2066                       << std::endl;
2067             std::cout << "         option cbc_options \"cuts=root log=2 feas=on slog=1\"" << std::endl
2068                       << std::endl;
2069             std::cout << "only maximize, dual, primal, help and quit are recognized without =" << std::endl;
2070           }
2071           int maxAcross = 10;
2072           if ((verbose % 4) != 0)
2073             maxAcross = 1;
2074           int limits[] = { 1, 51, 101, 151, 201, 301, 401, 501, 601 };
2075           std::vector< std::string > types;
2076           types.push_back("Double parameters:");
2077           types.push_back("Branch and Cut double parameters:");
2078           types.push_back("Integer parameters:");
2079           types.push_back("Branch and Cut integer parameters:");
2080           types.push_back("Keyword parameters:");
2081           types.push_back("Branch and Cut keyword parameters:");
2082           types.push_back("Actions or string parameters:");
2083           types.push_back("Branch and Cut actions:");
2084           int iType;
2085           for (iType = 0; iType < 8; iType++) {
2086             int across = 0;
2087             int lengthLine = 0;
2088             if ((verbose % 4) != 0)
2089               std::cout << std::endl;
2090             std::cout << types[iType] << std::endl;
2091             if ((verbose & 2) != 0)
2092               std::cout << std::endl;
2093             for (iParam = 0; iParam < (int)parameters_.size(); iParam++) {
2094               int type = parameters_[iParam].type();
2095               //printf("%d type %d limits %d %d display %d\n",iParam,
2096               //     type,limits[iType],limits[iType+1],parameters_[iParam].displayThis());
2097               if ((parameters_[iParam].displayThis() >= printLevel || evenHidden) && type >= limits[iType]
2098                 && type < limits[iType + 1]) {
2099                 // but skip if not useful for ampl (and in ampl mode)
2100                 if (verbose >= 4 && (parameters_[iParam].whereUsed() & 4) == 0)
2101                   continue;
2102                 if (!across) {
2103                   if ((verbose & 2) != 0)
2104                     std::cout << "Command ";
2105                 }
2106                 int length = parameters_[iParam].lengthMatchName() + 1;
2107                 if (lengthLine + length > 80) {
2108                   std::cout << std::endl;
2109                   across = 0;
2110                   lengthLine = 0;
2111                 }
2112                 std::cout << " " << parameters_[iParam].matchName();
2113                 lengthLine += length;
2114                 across++;
2115                 if (across == maxAcross) {
2116                   across = 0;
2117                   if ((verbose % 4) != 0) {
2118                     // put out description as well
2119                     if ((verbose & 1) != 0)
2120                       std::cout << " " << parameters_[iParam].shortHelp();
2121                     std::cout << std::endl;
2122                     if ((verbose & 2) != 0) {
2123                       std::cout << "---- description" << std::endl;
2124                       parameters_[iParam].printLongHelp();
2125                       std::cout << "----" << std::endl
2126                                 << std::endl;
2127                     }
2128                   } else {
2129                     std::cout << std::endl;
2130                   }
2131                 }
2132               }
2133             }
2134             if (across)
2135               std::cout << std::endl;
2136           }
2137         } else if (type == CBC_PARAM_FULLGENERALQUERY) {
2138           std::cout << "Full list of commands is:" << std::endl;
2139           int maxAcross = 5;
2140           int limits[] = { 1, 51, 101, 151, 201, 301, 401, 501, 601 };
2141           std::vector< std::string > types;
2142           types.push_back("Double parameters:");
2143           types.push_back("Branch and Cut double parameters:");
2144           types.push_back("Integer parameters:");
2145           types.push_back("Branch and Cut integer parameters:");
2146           types.push_back("Keyword parameters:");
2147           types.push_back("Branch and Cut keyword parameters:");
2148           types.push_back("Actions or string parameters:");
2149           types.push_back("Branch and Cut actions:");
2150           int iType;
2151           for (iType = 0; iType < 8; iType++) {
2152             int across = 0;
2153             std::cout << types[iType] << "  ";
2154             for (iParam = 0; iParam < (int)parameters_.size(); iParam++) {
2155               int type = parameters_[iParam].type();
2156               if (type >= limits[iType]
2157                 && type < limits[iType + 1]) {
2158                 if (!across)
2159                   std::cout << "  ";
2160                 std::cout << parameters_[iParam].matchName() << "  ";
2161                 across++;
2162                 if (across == maxAcross) {
2163                   std::cout << std::endl;
2164                   across = 0;
2165                 }
2166               }
2167             }
2168             if (across)
2169               std::cout << std::endl;
2170           }
2171         } else if (type < 101) {
2172           // get next field as double
2173           double value = CoinReadGetDoubleField(argc, argv, &valid);
2174           if (!valid) {
2175             if (type < 51) {
2176               int returnCode;
2177               const char *message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode);
2178               if (!noPrinting_ && strlen(message)) {
2179                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
2180                   << message
2181                   << CoinMessageEol;
2182               }
2183             } else if (type < 81) {
2184               int returnCode;
2185               const char *message = parameters_[iParam].setDoubleParameterWithMessage(model_, value, returnCode);
2186               if (!noPrinting_ && strlen(message)) {
2187                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
2188                   << message
2189                   << CoinMessageEol;
2190               }
2191             } else {
2192               int returnCode;
2193               const char *message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode);
2194               if (!noPrinting_ && strlen(message)) {
2195                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
2196                   << message
2197                   << CoinMessageEol;
2198               }
2199               switch (type) {
2200               case CBC_PARAM_DBL_DJFIX:
2201                 djFix = value;
2202 #ifndef CBC_OTHER_SOLVER
2203                 if (goodModel && djFix < 1.0e20) {
2204                   // do some fixing
2205                   clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
2206                   clpSolver->initialSolve();
2207                   lpSolver = clpSolver->getModelPtr();
2208                   int numberColumns = lpSolver->numberColumns();
2209                   int i;
2210                   const char *type = lpSolver->integerInformation();
2211                   double *lower = lpSolver->columnLower();
2212                   double *upper = lpSolver->columnUpper();
2213                   double *solution = lpSolver->primalColumnSolution();
2214                   double *dj = lpSolver->dualColumnSolution();
2215                   int numberFixed = 0;
2216                   double dextra4 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue();
2217                   if (dextra4)
2218                     printf("Multiple for continuous dj fixing is %g\n", dextra4);
2219                   for (i = 0; i < numberColumns; i++) {
2220                     double djValue = dj[i];
2221                     if (!type[i])
2222                       djValue *= dextra4;
2223                     if (type[i] || dextra4) {
2224                       double value = solution[i];
2225                       if (value < lower[i] + 1.0e-5 && djValue > djFix) {
2226                         solution[i] = lower[i];
2227                         upper[i] = lower[i];
2228                         numberFixed++;
2229                       } else if (value > upper[i] - 1.0e-5 && djValue < -djFix) {
2230                         solution[i] = upper[i];
2231                         lower[i] = upper[i];
2232                         numberFixed++;
2233                       }
2234                     }
2235                   }
2236                   sprintf(generalPrint, "%d columns fixed\n", numberFixed);
2237                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
2238                     << generalPrint
2239                     << CoinMessageEol;
2240                 }
2241 #endif
2242                 break;
2243               case CBC_PARAM_DBL_TIGHTENFACTOR:
2244                 tightenFactor = value;
2245                 if (!complicatedInteger)
2246                   defaultSettings = false; // user knows what she is doing
2247                 break;
2248               default:
2249                 break;
2250               }
2251             }
2252           } else if (valid == 1) {
2253             std::cout << " is illegal for double parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].doubleValue() << std::endl;
2254           } else {
2255             std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].doubleValue() << std::endl;
2256           }
2257         } else if (type < 201) {
2258           // get next field as int
2259           int value = CoinReadGetIntField(argc, argv, &valid);
2260           if (!valid) {
2261             if (type < 151) {
2262               if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEPASS)
2263                 preSolve = value;
2264               else if (parameters_[iParam].type() == CLP_PARAM_INT_IDIOT)
2265                 doIdiot = value;
2266               else if (parameters_[iParam].type() == CLP_PARAM_INT_SPRINT)
2267                 doSprint = value;
2268               else if (parameters_[iParam].type() == CLP_PARAM_INT_OUTPUTFORMAT)
2269                 outputFormat = value;
2270               else if (parameters_[iParam].type() == CLP_PARAM_INT_SLPVALUE)
2271                 slpValue = value;
2272               else if (parameters_[iParam].type() == CLP_PARAM_INT_CPP)
2273                 cppValue = value;
2274               else if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEOPTIONS)
2275                 presolveOptions = value;
2276               else if (parameters_[iParam].type() == CLP_PARAM_INT_PRINTOPTIONS)
2277                 printOptions = value;
2278               else if (parameters_[iParam].type() == CLP_PARAM_INT_SUBSTITUTION)
2279                 substitution = value;
2280               else if (parameters_[iParam].type() == CLP_PARAM_INT_DUALIZE)
2281                 dualize = value;
2282               else if (parameters_[iParam].type() == CLP_PARAM_INT_PROCESSTUNE)
2283                 tunePreProcess = value;
2284               else if (parameters_[iParam].type() == CLP_PARAM_INT_USESOLUTION)
2285                 useSolution = value;
2286               else if (parameters_[iParam].type() == CLP_PARAM_INT_VERBOSE)
2287                 verbose = value;
2288               int returnCode;
2289               const char *message = parameters_[iParam].setIntParameterWithMessage(lpSolver, value, returnCode);
2290               if (!noPrinting_ && strlen(message)) {
2291                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
2292                   << message
2293                   << CoinMessageEol;
2294               }
2295             } else {
2296               if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASS)
2297                 cutPass = value;
2298               else if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASSINTREE)
2299                 cutPassInTree = value;
2300               else if (parameters_[iParam].type() == CBC_PARAM_INT_STRONGBRANCHING || parameters_[iParam].type() == CBC_PARAM_INT_NUMBERBEFORE)
2301                 strongChanged = true;
2302               else if (parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE2 || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPITS)
2303                 pumpChanged = true;
2304               else if (parameters_[iParam].type() == CBC_PARAM_INT_EXPERIMENT) {
2305                 int addFlags = 0;
2306                 // switch on some later features if >999
2307                 if (value > 999) {
2308                   int switchValue = value / 1000;
2309                   const char *message = NULL;
2310                   value -= 1000 * switchValue;
2311                   parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].setIntValue(0 /*value*/);
2312                   switch (switchValue) {
2313                   default:
2314                   case 4:
2315                     // hotstart 500, -200 cut passes
2316                     message = parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValueWithMessage(500);
2317                     if (!noPrinting_ && message)
2318                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2319                         << message << CoinMessageEol;
2320                     message = parameters_[whichParam(CBC_PARAM_INT_CUTPASS, parameters_)].setIntValueWithMessage(-200);
2321                     if (!noPrinting_ && message)
2322                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2323                         << message << CoinMessageEol;
2324                   case 3:
2325                     // multiple 4
2326                     message = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].setIntValueWithMessage(4);
2327                     if (!noPrinting_ && message)
2328                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2329                         << message << CoinMessageEol;
2330                   case 2:
2331                     // rens plus all diving at root
2332                     message = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].setIntValueWithMessage(16);
2333                     if (!noPrinting_ && message)
2334                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2335                         << message << CoinMessageEol;
2336                     model_.setNumberAnalyzeIterations(-value);
2337                     // -tune 7 zero,lagomory,gmi at root - probing on
2338                   case 1:
2339                     tunePreProcess = 7;
2340                     message = parameters_[whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_)].setIntValueWithMessage(7);
2341                     if (!noPrinting_ && message)
2342                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2343                         << message << CoinMessageEol;
2344                     //message = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].setIntValueWithMessage(1025);
2345                     //if (!noPrinting_&&message)
2346                     //    generalMessageHandler->message(CLP_GENERAL, generalMessages)
2347                     //  << message << CoinMessageEol;
2348                     message = parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOptionWithMessage("on");
2349                     probingAction = 1;
2350                     if (!noPrinting_ && message)
2351                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2352                         << message << CoinMessageEol;
2353                     message = parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOptionWithMessage("root");
2354                     if (!noPrinting_ && message)
2355                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2356                         << message << CoinMessageEol;
2357                     message = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, parameters_)].setCurrentOptionWithMessage("root");
2358                     if (!noPrinting_ && message)
2359                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2360                         << message << CoinMessageEol;
2361                     GMIAction = 2;
2362                     message = parameters_[whichParam(CBC_PARAM_STR_GMICUTS, parameters_)].setCurrentOptionWithMessage("root");
2363                     if (!noPrinting_ && message)
2364                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
2365                         << message << CoinMessageEol;
2366                   }
2367                   value = 0;
2368                 }
2369                 if (value >= 10) {
2370                   addFlags = 1048576 * (value / 10);
2371                   value = value % 10;
2372                   parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].setIntValue(value);
2373                 }
2374                 if (value >= 1) {
2375                   int values[] = { 24003, 280003, 792003, 24003, 24003 };
2376                   if (value >= 2 && value <= 3) {
2377                     // swap default diving
2378                     int iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_);
2379                     parameters_[iParam].setCurrentOption("off");
2380                     iParam = whichParam(CBC_PARAM_STR_DIVINGP, parameters_);
2381                     parameters_[iParam].setCurrentOption("on");
2382                   }
2383                   int extra4 = values[value - 1] + addFlags;
2384                   parameters_[whichParam(CBC_PARAM_INT_EXTRA4, parameters_)].setIntValue(extra4);
2385                   if (!noPrinting_) {
2386                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
2387                       << "switching on global root cuts for gomory and knapsack"
2388                       << CoinMessageEol;
2389                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
2390                       << "using OSL factorization"
2391                       << CoinMessageEol;
2392                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
2393                       << "extra options - -rens on -extra4 "
2394                       << extra4 << " -passc 1000!"
2395                       << CoinMessageEol;
2396                   }
2397                   parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption("forceOnStrong");
2398                   probingAction = 8;
2399                   parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption("onGlobal");
2400                   gomoryAction = 5;
2401                   parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption("onGlobal");
2402                   knapsackAction = 5;
2403                   parameters_[whichParam(CLP_PARAM_STR_FACTORIZATION, parameters_)].setCurrentOption("osl");
2404                   lpSolver->factorization()->forceOtherFactorization(3);
2405                   parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValue(100);
2406                   parameters_[whichParam(CBC_PARAM_INT_CUTPASS, parameters_)].setIntValue(1000);
2407                   cutPass = 1000;
2408                   parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].setCurrentOption("on");
2409                 }
2410               } else if (parameters_[iParam].type() == CBC_PARAM_INT_STRATEGY) {
2411                 if (value == 0) {
2412                   gomoryGen.setAwayAtRoot(0.05);
2413                   int iParam;
2414                   iParam = whichParam(CBC_PARAM_INT_DIVEOPT, parameters_);
2415                   parameters_[iParam].setIntValue(-1);
2416                   iParam = whichParam(CBC_PARAM_INT_FPUMPITS, parameters_);
2417                   parameters_[iParam].setIntValue(20);
2418                   iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_);
2419                   parameters_[iParam].setIntValue(1003);
2420                   initialPumpTune = 1003;
2421                   iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_);
2422                   parameters_[iParam].setIntValue(0);
2423                   tunePreProcess = 0;
2424                   iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_);
2425                   parameters_[iParam].setCurrentOption("off");
2426                   iParam = whichParam(CBC_PARAM_STR_RINS, parameters_);
2427                   parameters_[iParam].setCurrentOption("off");
2428                   iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_);
2429                   // but not if cuts off
2430                   int jParam = whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters_);
2431 
2432                   jParam = parameters_[jParam].currentOptionAsInteger();
2433                   if (jParam) {
2434                     parameters_[iParam].setCurrentOption("on");
2435                     probingAction = 1;
2436                   } else {
2437                     parameters_[iParam].setCurrentOption("off");
2438                     probingAction = 0;
2439                   }
2440                 }
2441               }
2442               int returnCode;
2443               const char *message = parameters_[iParam].setIntParameterWithMessage(model_, value, returnCode);
2444               if (!noPrinting_ && strlen(message)) {
2445                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
2446                   << message
2447                   << CoinMessageEol;
2448               }
2449             }
2450           } else if (valid == 1) {
2451             std::cout << " is illegal for integer parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].intValue() << std::endl;
2452           } else {
2453             std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].intValue() << std::endl;
2454           }
2455         } else if (type < 401) {
2456           // one of several strings
2457           std::string value = CoinReadGetString(argc, argv);
2458           int action = parameters_[iParam].parameterOption(value);
2459           if (action < 0) {
2460             if (value != "EOL") {
2461               // no match
2462               parameters_[iParam].printOptions();
2463             } else {
2464               // print current value
2465               std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].currentOption() << std::endl;
2466             }
2467           } else {
2468             const char *message = parameters_[iParam].setCurrentOptionWithMessage(action);
2469             if (!noPrinting_ && strlen(message)) {
2470               generalMessageHandler->message(CLP_GENERAL, generalMessages)
2471                 << message
2472                 << CoinMessageEol;
2473             }
2474             // for now hard wired
2475             switch (type) {
2476             case CLP_PARAM_STR_DIRECTION:
2477               if (action == 0)
2478                 lpSolver->setOptimizationDirection(1);
2479               else if (action == 1)
2480                 lpSolver->setOptimizationDirection(-1);
2481               else
2482                 lpSolver->setOptimizationDirection(0);
2483               break;
2484             case CLP_PARAM_STR_DUALPIVOT:
2485               if (action == 0) {
2486                 ClpDualRowSteepest steep(3);
2487                 lpSolver->setDualRowPivotAlgorithm(steep);
2488               } else if (action == 1) {
2489                 ClpDualRowDantzig dantzig;
2490                 //ClpDualRowSteepest dantzig(5);
2491                 lpSolver->setDualRowPivotAlgorithm(dantzig);
2492               } else if (action == 2) {
2493                 // partial steep
2494                 ClpDualRowSteepest steep(2);
2495                 lpSolver->setDualRowPivotAlgorithm(steep);
2496               } else if (action == 3) {
2497                 ClpDualRowSteepest steep;
2498                 lpSolver->setDualRowPivotAlgorithm(steep);
2499               } else if (action == 4) {
2500                 // Positive edge steepest
2501                 ClpPEDualRowSteepest p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue()));
2502                 lpSolver->setDualRowPivotAlgorithm(p);
2503               } else if (action == 5) {
2504                 // Positive edge Dantzig
2505                 ClpPEDualRowDantzig p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue()));
2506                 lpSolver->setDualRowPivotAlgorithm(p);
2507               }
2508               break;
2509             case CLP_PARAM_STR_PRIMALPIVOT:
2510               if (action == 0) {
2511                 ClpPrimalColumnSteepest steep(3);
2512                 lpSolver->setPrimalColumnPivotAlgorithm(steep);
2513               } else if (action == 1) {
2514                 ClpPrimalColumnSteepest steep(0);
2515                 lpSolver->setPrimalColumnPivotAlgorithm(steep);
2516               } else if (action == 2) {
2517                 ClpPrimalColumnDantzig dantzig;
2518                 lpSolver->setPrimalColumnPivotAlgorithm(dantzig);
2519               } else if (action == 3) {
2520                 ClpPrimalColumnSteepest steep(4);
2521                 lpSolver->setPrimalColumnPivotAlgorithm(steep);
2522               } else if (action == 4) {
2523                 ClpPrimalColumnSteepest steep(1);
2524                 lpSolver->setPrimalColumnPivotAlgorithm(steep);
2525               } else if (action == 5) {
2526                 ClpPrimalColumnSteepest steep(2);
2527                 lpSolver->setPrimalColumnPivotAlgorithm(steep);
2528               } else if (action == 6) {
2529                 ClpPrimalColumnSteepest steep(10);
2530                 lpSolver->setPrimalColumnPivotAlgorithm(steep);
2531               } else if (action == 7) {
2532                 // Positive edge steepest
2533                 ClpPEPrimalColumnSteepest p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue()));
2534                 lpSolver->setPrimalColumnPivotAlgorithm(p);
2535               } else if (action == 8) {
2536                 // Positive edge Dantzig
2537                 ClpPEPrimalColumnDantzig p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue()));
2538                 lpSolver->setPrimalColumnPivotAlgorithm(p);
2539               }
2540               break;
2541             case CLP_PARAM_STR_SCALING:
2542               lpSolver->scaling(action);
2543               solver->setHintParam(OsiDoScale, action != 0, OsiHintTry);
2544               doScaling = action;
2545               break;
2546             case CLP_PARAM_STR_AUTOSCALE:
2547               lpSolver->setAutomaticScaling(action != 0);
2548               break;
2549             case CLP_PARAM_STR_SPARSEFACTOR:
2550               lpSolver->setSparseFactorization((1 - action) != 0);
2551               break;
2552             case CLP_PARAM_STR_BIASLU:
2553               lpSolver->factorization()->setBiasLU(action);
2554               break;
2555             case CLP_PARAM_STR_PERTURBATION:
2556               if (action == 0)
2557                 lpSolver->setPerturbation(50);
2558               else
2559                 lpSolver->setPerturbation(100);
2560               break;
2561             case CLP_PARAM_STR_ERRORSALLOWED:
2562               allowImportErrors = action;
2563               break;
2564             case CLP_PARAM_STR_INTPRINT:
2565               printMode = action;
2566               break;
2567               //case CLP_PARAM_NOTUSED_ALGORITHM:
2568               //algorithm  = action;
2569               //defaultSettings=false; // user knows what she is doing
2570               //abort();
2571               //break;
2572             case CLP_PARAM_STR_KEEPNAMES:
2573               keepImportNames = 1 - action;
2574               break;
2575             case CLP_PARAM_STR_PRESOLVE:
2576               if (action == 0)
2577                 preSolve = 5;
2578               else if (action == 1)
2579                 preSolve = 0;
2580               else if (action == 2)
2581                 preSolve = 10;
2582               else
2583                 preSolveFile = true;
2584               break;
2585             case CLP_PARAM_STR_PFI:
2586               lpSolver->factorization()->setForrestTomlin(action == 0);
2587               break;
2588             case CLP_PARAM_STR_FACTORIZATION:
2589               lpSolver->factorization()->forceOtherFactorization(action);
2590               break;
2591             case CLP_PARAM_STR_CRASH:
2592               doCrash = action;
2593               break;
2594             case CLP_PARAM_STR_VECTOR:
2595               doVector = action;
2596               break;
2597             case CLP_PARAM_STR_MESSAGES:
2598               lpSolver->messageHandler()->setPrefix(action != 0);
2599               break;
2600             case CLP_PARAM_STR_CHOLESKY:
2601               choleskyType = action;
2602               break;
2603             case CLP_PARAM_STR_GAMMA:
2604               gamma = action;
2605               break;
2606             case CLP_PARAM_STR_BARRIERSCALE:
2607               scaleBarrier = action;
2608               break;
2609             case CLP_PARAM_STR_KKT:
2610               doKKT = action;
2611               break;
2612             case CLP_PARAM_STR_CROSSOVER:
2613               crossover = action;
2614               break;
2615             case CLP_PARAM_STR_TIME_MODE:
2616               model_.setUseElapsedTime(action != 0);
2617               break;
2618             case CBC_PARAM_STR_SOS:
2619               doSOS = action;
2620               break;
2621             case CBC_PARAM_STR_GOMORYCUTS:
2622               defaultSettings = false; // user knows what she is doing
2623               gomoryAction = action;
2624               break;
2625             case CBC_PARAM_STR_PROBINGCUTS:
2626               defaultSettings = false; // user knows what she is doing
2627               probingAction = action;
2628               break;
2629             case CBC_PARAM_STR_KNAPSACKCUTS:
2630               defaultSettings = false; // user knows what she is doing
2631               knapsackAction = action;
2632               break;
2633             case CBC_PARAM_STR_REDSPLITCUTS:
2634               defaultSettings = false; // user knows what she is doing
2635               redsplitAction = action;
2636               break;
2637             case CBC_PARAM_STR_REDSPLIT2CUTS:
2638               defaultSettings = false; // user knows what she is doing
2639               redsplit2Action = action;
2640               break;
2641             case CBC_PARAM_STR_GMICUTS:
2642               defaultSettings = false; // user knows what she is doing
2643               GMIAction = action;
2644               break;
2645             case CBC_PARAM_STR_CLIQUECUTS:
2646               defaultSettings = false; // user knows what she is doing
2647               cliqueAction = action;
2648               break;
2649             case CBC_PARAM_STR_FLOWCUTS:
2650               defaultSettings = false; // user knows what she is doing
2651               flowAction = action;
2652               break;
2653             case CBC_PARAM_STR_MIXEDCUTS:
2654               defaultSettings = false; // user knows what she is doing
2655               mixedAction = action;
2656               break;
2657             case CBC_PARAM_STR_TWOMIRCUTS:
2658               defaultSettings = false; // user knows what she is doing
2659               twomirAction = action;
2660               break;
2661             case CBC_PARAM_STR_LANDPCUTS:
2662               defaultSettings = false; // user knows what she is doing
2663               landpAction = action;
2664               break;
2665             case CBC_PARAM_STR_RESIDCUTS:
2666               defaultSettings = false; // user knows what she is doing
2667               residualCapacityAction = action;
2668               break;
2669             case CBC_PARAM_STR_ZEROHALFCUTS:
2670               defaultSettings = false; // user knows what she is doing
2671               zerohalfAction = action;
2672               break;
2673             case CBC_PARAM_STR_ROUNDING:
2674               defaultSettings = false; // user knows what she is doing
2675               break;
2676             case CBC_PARAM_STR_FPUMP:
2677               defaultSettings = false; // user knows what she is doing
2678               break;
2679             case CBC_PARAM_STR_RINS:
2680               break;
2681             case CBC_PARAM_STR_DINS:
2682               break;
2683             case CBC_PARAM_STR_RENS:
2684               break;
2685             case CBC_PARAM_STR_CUTSSTRATEGY:
2686               gomoryAction = action;
2687               probingAction = action;
2688               knapsackAction = action;
2689               cliqueAction = action;
2690               flowAction = action;
2691               mixedAction = action;
2692               twomirAction = action;
2693               zerohalfAction = action;
2694               parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption(action);
2695               parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption(action);
2696               parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption(action);
2697               parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters_)].setCurrentOption(action);
2698               parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters_)].setCurrentOption(action);
2699               parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters_)].setCurrentOption(action);
2700               parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters_)].setCurrentOption(action);
2701               if (!action) {
2702                 zerohalfAction = action;
2703                 parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOption(action);
2704                 redsplitAction = action;
2705                 parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, parameters_)].setCurrentOption(action);
2706                 redsplit2Action = action;
2707                 parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, parameters_)].setCurrentOption(action);
2708                 GMIAction = action;
2709                 parameters_[whichParam(CBC_PARAM_STR_GMICUTS, parameters_)].setCurrentOption(action);
2710                 landpAction = action;
2711                 parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, parameters_)].setCurrentOption(action);
2712                 residualCapacityAction = action;
2713                 parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, parameters_)].setCurrentOption(action);
2714               }
2715               break;
2716             case CBC_PARAM_STR_HEURISTICSTRATEGY:
2717               parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].setCurrentOption(action);
2718               parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].setCurrentOption(action);
2719               parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].setCurrentOption(action);
2720               //parameters_[whichParam(CBC_PARAM_STR_LOCALTREE,numberParameters_,parameters_)].setCurrentOption(action);
2721               parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].setCurrentOption(action);
2722               parameters_[whichParam(CBC_PARAM_STR_DIVINGC, parameters_)].setCurrentOption(action);
2723               parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].setCurrentOption(action);
2724               break;
2725             case CBC_PARAM_STR_GREEDY:
2726             case CBC_PARAM_STR_DIVINGS:
2727             case CBC_PARAM_STR_DIVINGC:
2728             case CBC_PARAM_STR_DIVINGF:
2729             case CBC_PARAM_STR_DIVINGG:
2730             case CBC_PARAM_STR_DIVINGL:
2731             case CBC_PARAM_STR_DIVINGP:
2732             case CBC_PARAM_STR_DIVINGV:
2733             case CBC_PARAM_STR_COMBINE:
2734             case CBC_PARAM_STR_PIVOTANDCOMPLEMENT:
2735             case CBC_PARAM_STR_PIVOTANDFIX:
2736             case CBC_PARAM_STR_RANDROUND:
2737             case CBC_PARAM_STR_LOCALTREE:
2738             case CBC_PARAM_STR_NAIVE:
2739             case CBC_PARAM_STR_CPX:
2740               defaultSettings = false; // user knows what she is doing
2741               break;
2742             case CBC_PARAM_STR_COSTSTRATEGY:
2743               useCosts = action;
2744               break;
2745             case CBC_PARAM_STR_NODESTRATEGY:
2746               nodeStrategy = action;
2747               break;
2748             case CBC_PARAM_STR_PREPROCESS:
2749               preProcess = action;
2750               break;
2751             default:
2752               //abort();
2753               break;
2754             }
2755           }
2756         } else {
2757           // action
2758           if (type == CLP_PARAM_ACTION_EXIT) {
2759 #ifdef COIN_HAS_ASL
2760             if (statusUserFunction_[0]) {
2761               if (info.numberIntegers || info.numberBinary) {
2762                 // integer
2763               } else {
2764                 // linear
2765               }
2766               writeAmpl(&info);
2767               freeArrays2(&info);
2768               freeArgs(&info);
2769             }
2770 #endif
2771             break; // stop all
2772           }
2773           switch (type) {
2774           case CLP_PARAM_ACTION_DUALSIMPLEX:
2775           case CLP_PARAM_ACTION_PRIMALSIMPLEX:
2776           case CLP_PARAM_ACTION_SOLVECONTINUOUS:
2777           case CLP_PARAM_ACTION_BARRIER:
2778             if (goodModel) {
2779               // Say not in integer
2780               integerStatus = -1;
2781               double objScale = parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, parameters_)].doubleValue();
2782               // deal with positive edge
2783               double psi = parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue();
2784               if (psi > 0.0) {
2785                 ClpDualRowPivot *dualp = lpSolver->dualRowPivot();
2786                 ClpDualRowSteepest *d1 = dynamic_cast< ClpDualRowSteepest * >(dualp);
2787                 ClpDualRowDantzig *d2 = dynamic_cast< ClpDualRowDantzig * >(dualp);
2788                 if (d1) {
2789                   ClpPEDualRowSteepest p(psi, d1->mode());
2790                   lpSolver->setDualRowPivotAlgorithm(p);
2791                 } else if (d2) {
2792                   ClpPEDualRowDantzig p(psi);
2793                   lpSolver->setDualRowPivotAlgorithm(p);
2794                 }
2795                 ClpPrimalColumnPivot *primalp = lpSolver->primalColumnPivot();
2796                 ClpPrimalColumnSteepest *p1 = dynamic_cast< ClpPrimalColumnSteepest * >(primalp);
2797                 ClpPrimalColumnDantzig *p2 = dynamic_cast< ClpPrimalColumnDantzig * >(primalp);
2798                 if (p1) {
2799                   ClpPEPrimalColumnSteepest p(psi, p1->mode());
2800                   lpSolver->setPrimalColumnPivotAlgorithm(p);
2801                 } else if (p2) {
2802                   ClpPEPrimalColumnDantzig p(psi);
2803                   lpSolver->setPrimalColumnPivotAlgorithm(p);
2804                 }
2805               }
2806               if (objScale != 1.0) {
2807                 int iColumn;
2808                 int numberColumns = lpSolver->numberColumns();
2809                 double *dualColumnSolution = lpSolver->dualColumnSolution();
2810                 ClpObjective *obj = lpSolver->objectiveAsObject();
2811                 assert(dynamic_cast< ClpLinearObjective * >(obj));
2812                 double offset;
2813                 double *objective = obj->gradient(NULL, NULL, offset, true);
2814                 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2815                   dualColumnSolution[iColumn] *= objScale;
2816                   objective[iColumn] *= objScale;
2817                   ;
2818                 }
2819                 int iRow;
2820                 int numberRows = lpSolver->numberRows();
2821                 double *dualRowSolution = lpSolver->dualRowSolution();
2822                 for (iRow = 0; iRow < numberRows; iRow++)
2823                   dualRowSolution[iRow] *= objScale;
2824                 lpSolver->setObjectiveOffset(objScale * lpSolver->objectiveOffset());
2825               }
2826               ClpSolve::SolveType method;
2827               ClpSolve::PresolveType presolveType;
2828               ClpSimplex *model2 = lpSolver;
2829               if (dualize) {
2830                 bool tryIt = true;
2831                 double fractionColumn = 1.0;
2832                 double fractionRow = 1.0;
2833                 if (dualize == 3) {
2834                   dualize = 1;
2835                   int numberColumns = lpSolver->numberColumns();
2836                   int numberRows = lpSolver->numberRows();
2837                   if (numberRows < 50000 || 5 * numberColumns > numberRows) {
2838                     tryIt = false;
2839                   } else {
2840                     fractionColumn = 0.1;
2841                     fractionRow = 0.1;
2842                   }
2843                 }
2844                 if (tryIt) {
2845                   model2 = static_cast< ClpSimplexOther * >(model2)->dualOfModel(fractionRow, fractionColumn);
2846                   if (model2) {
2847                     sprintf(generalPrint, "Dual of model has %d rows and %d columns",
2848                       model2->numberRows(), model2->numberColumns());
2849                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
2850                       << generalPrint
2851                       << CoinMessageEol;
2852                     model2->setOptimizationDirection(1.0);
2853                   } else {
2854                     model2 = lpSolver;
2855                     dualize = 0;
2856                   }
2857                 } else {
2858                   dualize = 0;
2859                 }
2860               }
2861               if (noPrinting_)
2862                 lpSolver->setLogLevel(0);
2863               ClpSolve solveOptions;
2864               solveOptions.setPresolveActions(presolveOptions);
2865               solveOptions.setSubstitution(substitution);
2866               if (preSolve != 5 && preSolve) {
2867                 presolveType = ClpSolve::presolveNumber;
2868                 if (preSolve < 0) {
2869                   preSolve = -preSolve;
2870                   if (preSolve <= 100) {
2871                     presolveType = ClpSolve::presolveNumber;
2872                     sprintf(generalPrint, "Doing %d presolve passes - picking up non-costed slacks",
2873                       preSolve);
2874                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
2875                       << generalPrint
2876                       << CoinMessageEol;
2877                     solveOptions.setDoSingletonColumn(true);
2878                   } else {
2879                     preSolve -= 100;
2880                     presolveType = ClpSolve::presolveNumberCost;
2881                     sprintf(generalPrint, "Doing %d presolve passes - picking up costed slacks",
2882                       preSolve);
2883                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
2884                       << generalPrint
2885                       << CoinMessageEol;
2886                   }
2887                 }
2888               } else if (preSolve) {
2889                 presolveType = ClpSolve::presolveOn;
2890               } else {
2891                 presolveType = ClpSolve::presolveOff;
2892               }
2893               solveOptions.setPresolveType(presolveType, preSolve);
2894               if (type == CLP_PARAM_ACTION_DUALSIMPLEX || type == CLP_PARAM_ACTION_SOLVECONTINUOUS) {
2895                 method = ClpSolve::useDual;
2896               } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) {
2897                 method = ClpSolve::usePrimalorSprint;
2898               } else {
2899                 method = ClpSolve::useBarrier;
2900                 if (crossover == 1) {
2901                   method = ClpSolve::useBarrierNoCross;
2902                 } else if (crossover == 2) {
2903                   ClpObjective *obj = lpSolver->objectiveAsObject();
2904                   if (obj->type() > 1) {
2905                     method = ClpSolve::useBarrierNoCross;
2906                     presolveType = ClpSolve::presolveOff;
2907                     solveOptions.setPresolveType(presolveType, preSolve);
2908                   }
2909                 }
2910               }
2911               solveOptions.setSolveType(method);
2912               if (preSolveFile)
2913                 presolveOptions |= 0x40000000;
2914               solveOptions.setSpecialOption(4, presolveOptions);
2915               solveOptions.setSpecialOption(5, printOptions);
2916               if (doVector) {
2917                 ClpMatrixBase *matrix = lpSolver->clpMatrix();
2918                 if (dynamic_cast< ClpPackedMatrix * >(matrix)) {
2919                   ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix);
2920                   clpMatrix->makeSpecialColumnCopy();
2921                 }
2922               }
2923               if (method == ClpSolve::useDual) {
2924                 // dual
2925                 if (doCrash)
2926                   solveOptions.setSpecialOption(0, 1, doCrash); // crash
2927                 else if (doIdiot)
2928                   solveOptions.setSpecialOption(0, 2, doIdiot); // possible idiot
2929               } else if (method == ClpSolve::usePrimalorSprint) {
2930                 // primal
2931                 // if slp turn everything off
2932                 if (slpValue > 0) {
2933                   doCrash = false;
2934                   doSprint = 0;
2935                   doIdiot = -1;
2936                   solveOptions.setSpecialOption(1, 10, slpValue); // slp
2937                   method = ClpSolve::usePrimal;
2938                 }
2939                 if (doCrash) {
2940                   solveOptions.setSpecialOption(1, 1, doCrash); // crash
2941                 } else if (doSprint > 0) {
2942                   // sprint overrides idiot
2943                   solveOptions.setSpecialOption(1, 3, doSprint); // sprint
2944                 } else if (doIdiot > 0) {
2945                   solveOptions.setSpecialOption(1, 2, doIdiot); // idiot
2946                 } else if (slpValue <= 0) {
2947                   if (doIdiot == 0) {
2948                     if (doSprint == 0)
2949                       solveOptions.setSpecialOption(1, 4); // all slack
2950                     else
2951                       solveOptions.setSpecialOption(1, 9); // all slack or sprint
2952                   } else {
2953                     if (doSprint == 0)
2954                       solveOptions.setSpecialOption(1, 8); // all slack or idiot
2955                     else
2956                       solveOptions.setSpecialOption(1, 7); // initiative
2957                   }
2958                 }
2959                 if (basisHasValues == -1)
2960                   solveOptions.setSpecialOption(1, 11); // switch off values
2961               } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) {
2962                 int barrierOptions = choleskyType;
2963                 if (scaleBarrier)
2964                   barrierOptions |= 8;
2965                 if (doKKT)
2966                   barrierOptions |= 16;
2967                 if (gamma)
2968                   barrierOptions |= 32 * gamma;
2969                 if (crossover == 3)
2970                   barrierOptions |= 256; // try presolve in crossover
2971                 solveOptions.setSpecialOption(4, barrierOptions);
2972               }
2973               model2->setMaximumSeconds(model_.getMaximumSeconds());
2974 #ifdef COIN_HAS_LINK
2975               OsiSolverInterface *coinSolver = model_.solver();
2976               OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(coinSolver);
2977               if (!linkSolver) {
2978                 model2->initialSolve(solveOptions);
2979               } else {
2980                 // special solver
2981                 int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue();
2982                 double *solution = NULL;
2983                 if (testOsiOptions < 10) {
2984                   solution = linkSolver->nonlinearSLP(slpValue > 0 ? slpValue : 20, 1.0e-5);
2985                 } else if (testOsiOptions >= 10) {
2986                   CoinModel coinModel = *linkSolver->coinModel();
2987                   ClpSimplex *tempModel = approximateSolution(coinModel, slpValue > 0 ? slpValue : 50, 1.0e-5, 0);
2988                   assert(tempModel);
2989                   solution = CoinCopyOfArray(tempModel->primalColumnSolution(), coinModel.numberColumns());
2990                   model2->setObjectiveValue(tempModel->objectiveValue());
2991                   model2->setProblemStatus(tempModel->problemStatus());
2992                   model2->setSecondaryStatus(tempModel->secondaryStatus());
2993                   delete tempModel;
2994                 }
2995                 if (solution) {
2996                   memcpy(model2->primalColumnSolution(), solution,
2997                     CoinMin(model2->numberColumns(), linkSolver->coinModel()->numberColumns()) * sizeof(double));
2998                   delete[] solution;
2999                 } else {
3000                   printf("No nonlinear solution\n");
3001                 }
3002               }
3003 #else
3004               model2->initialSolve(solveOptions);
3005 #endif
3006               {
3007                 // map states
3008                 /* clp status
3009                                    -1 - unknown e.g. before solve or if postSolve says not optimal
3010                                    0 - optimal
3011                                    1 - primal infeasible
3012                                    2 - dual infeasible
3013                                    3 - stopped on iterations or time
3014                                    4 - stopped due to errors
3015                                    5 - stopped by event handler (virtual int ClpEventHandler::event()) */
3016                 /* cbc status
3017                                    -1 before branchAndBound
3018                                    0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found
3019                                    (or check value of best solution)
3020                                    1 stopped - on maxnodes, maxsols, maxtime
3021                                    2 difficulties so run was abandoned
3022                                    (5 event user programmed event occurred) */
3023                 /* clp secondary status of problem - may get extended
3024                                    0 - none
3025                                    1 - primal infeasible because dual limit reached OR probably primal
3026                                    infeasible but can't prove it (main status 4)
3027                                    2 - scaled problem optimal - unscaled problem has primal infeasibilities
3028                                    3 - scaled problem optimal - unscaled problem has dual infeasibilities
3029                                    4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities
3030                                    5 - giving up in primal with flagged variables
3031                                    6 - failed due to empty problem check
3032                                    7 - postSolve says not optimal
3033                                    8 - failed due to bad element check
3034                                    9 - status was 3 and stopped on time
3035                                    100 up - translation of enum from ClpEventHandler
3036                                 */
3037                 /* cbc secondary status of problem
3038                                    -1 unset (status_ will also be -1)
3039                                    0 search completed with solution
3040                                    1 linear relaxation not feasible (or worse than cutoff)
3041                                    2 stopped on gap
3042                                    3 stopped on nodes
3043                                    4 stopped on time
3044                                    5 stopped on user event
3045                                    6 stopped on solutions
3046                                    7 linear relaxation unbounded
3047                                    8 stopped on iterations limit
3048                                 */
3049                 int iStatus = model2->status();
3050                 int iStatus2 = model2->secondaryStatus();
3051                 if (iStatus == 0) {
3052                   iStatus2 = 0;
3053                   if (found.type() == CBC_PARAM_ACTION_BAB) {
3054                     // set best solution in model as no integers
3055                     model_.setBestSolution(model2->primalColumnSolution(),
3056                       model2->numberColumns(),
3057                       model2->getObjValue() * model2->getObjSense());
3058                   }
3059                 } else if (iStatus == 1) {
3060                   iStatus = 0;
3061                   iStatus2 = 1; // say infeasible
3062                 } else if (iStatus == 2) {
3063                   iStatus = 0;
3064                   iStatus2 = 7; // say unbounded
3065                 } else if (iStatus == 3) {
3066                   iStatus = 1;
3067                   if (iStatus2 == 9) // what does 9 mean ?????????????
3068                     iStatus2 = 4;
3069                   else
3070                     iStatus2 = 3; // Use nodes - as closer than solutions
3071                 } else if (iStatus == 4) {
3072                   iStatus = 2; // difficulties
3073                   iStatus2 = 0;
3074                 }
3075                 model_.setProblemStatus(iStatus);
3076                 model_.setSecondaryStatus(iStatus2);
3077                 if ((iStatus == 2 || iStatus2 > 0) && !noPrinting_) {
3078                   std::string statusName[] = { "", "Stopped on ", "Run abandoned", "", "", "User ctrl-c" };
3079                   std::string minor[] = { "Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "iterations limit", "Problem proven infeasible" };
3080                   sprintf(generalPrint, "\nResult - %s%s\n\n",
3081                     statusName[iStatus].c_str(),
3082                     minor[iStatus2].c_str());
3083                   sprintf(generalPrint + strlen(generalPrint),
3084                     "Enumerated nodes:           0\n");
3085                   sprintf(generalPrint + strlen(generalPrint),
3086                     "Total iterations:           0\n");
3087 #if CBC_QUIET == 0
3088                   sprintf(generalPrint + strlen(generalPrint),
3089                     "Time (CPU seconds):         %.2f\n",
3090                     CoinCpuTime() - time0);
3091                   sprintf(generalPrint + strlen(generalPrint),
3092                     "Time (Wallclock Seconds):   %.2f\n",
3093                     CoinGetTimeOfDay() - time0Elapsed);
3094 #endif
3095                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
3096                     << generalPrint
3097                     << CoinMessageEol;
3098                 }
3099                 //assert (lpSolver==clpSolver->getModelPtr());
3100                 assert(clpSolver == model_.solver());
3101                 clpSolver->setWarmStart(NULL);
3102                 // and in babModel if exists
3103                 if (babModel_) {
3104                   babModel_->setProblemStatus(iStatus);
3105                   babModel_->setSecondaryStatus(iStatus2);
3106                 }
3107                 int returnCode = callBack(&model, 1);
3108                 if (returnCode) {
3109                   // exit if user wants
3110                   delete babModel_;
3111                   babModel_ = NULL;
3112                   return returnCode;
3113                 }
3114               }
3115               basisHasValues = 1;
3116               if (dualize) {
3117                 int returnCode = static_cast< ClpSimplexOther * >(lpSolver)->restoreFromDual(model2);
3118                 if (model2->status() == 3)
3119                   returnCode = 0;
3120                 delete model2;
3121                 if (returnCode && dualize != 2)
3122                   lpSolver->primal(1);
3123                 model2 = lpSolver;
3124               }
3125 #ifdef COIN_HAS_ASL
3126               if (statusUserFunction_[0]) {
3127                 double value = model2->getObjValue();
3128                 char buf[300];
3129                 int pos = 0;
3130                 int iStat = model2->status();
3131                 if (iStat == 0) {
3132                   pos += sprintf(buf + pos, "optimal,");
3133                 } else if (iStat == 1) {
3134                   // infeasible
3135                   pos += sprintf(buf + pos, "infeasible,");
3136                 } else if (iStat == 2) {
3137                   // unbounded
3138                   pos += sprintf(buf + pos, "unbounded,");
3139                 } else if (iStat == 3) {
3140                   pos += sprintf(buf + pos, "stopped on iterations or time,");
3141                 } else if (iStat == 4) {
3142                   iStat = 7;
3143                   pos += sprintf(buf + pos, "stopped on difficulties,");
3144                 } else if (iStat == 5) {
3145                   iStat = 3;
3146                   pos += sprintf(buf + pos, "stopped on ctrl-c,");
3147                 } else if (iStat == 6) {
3148                   // bab infeasible
3149                   pos += sprintf(buf + pos, "integer infeasible,");
3150                   iStat = 1;
3151                 } else {
3152                   pos += sprintf(buf + pos, "status unknown,");
3153                   iStat = 6;
3154                 }
3155                 info.problemStatus = iStat;
3156                 info.objValue = value;
3157                 pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
3158                   value);
3159                 sprintf(buf + pos, "\n%d iterations",
3160                   model2->getIterationCount());
3161                 free(info.primalSolution);
3162                 int numberColumns = model2->numberColumns();
3163                 info.primalSolution = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double)));
3164                 CoinCopyN(model2->primalColumnSolution(), numberColumns, info.primalSolution);
3165                 int numberRows = model2->numberRows();
3166                 free(info.dualSolution);
3167                 info.dualSolution = reinterpret_cast< double * >(malloc(numberRows * sizeof(double)));
3168                 CoinCopyN(model2->dualRowSolution(), numberRows, info.dualSolution);
3169                 CoinWarmStartBasis *basis = model2->getBasis();
3170                 free(info.rowStatus);
3171                 info.rowStatus = reinterpret_cast< int * >(malloc(numberRows * sizeof(int)));
3172                 free(info.columnStatus);
3173                 info.columnStatus = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int)));
3174                 // Put basis in
3175                 int i;
3176                 // free,basic,ub,lb are 0,1,2,3
3177                 for (i = 0; i < numberRows; i++) {
3178                   CoinWarmStartBasis::Status status = basis->getArtifStatus(i);
3179                   info.rowStatus[i] = status;
3180                 }
3181                 for (i = 0; i < numberColumns; i++) {
3182                   CoinWarmStartBasis::Status status = basis->getStructStatus(i);
3183                   info.columnStatus[i] = status;
3184                 }
3185                 // put buffer into info
3186                 strcpy(info.buffer, buf);
3187                 delete basis;
3188               }
3189 #endif
3190             } else {
3191               sprintf(generalPrint, "** Current model not valid");
3192               printGeneralMessage(model_, generalPrint);
3193             }
3194             break;
3195           case CLP_PARAM_ACTION_STATISTICS:
3196             if (goodModel) {
3197               // If presolve on look at presolved
3198               bool deleteModel2 = false;
3199               ClpSimplex *model2 = lpSolver;
3200               if (preSolve) {
3201                 ClpPresolve pinfo;
3202                 int presolveOptions2 = presolveOptions & ~0x40000000;
3203                 if ((presolveOptions2 & 0xffff) != 0)
3204                   pinfo.setPresolveActions(presolveOptions2);
3205                 pinfo.setSubstitution(substitution);
3206                 if ((printOptions & 1) != 0)
3207                   pinfo.statistics();
3208                 double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue();
3209                 model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance,
3210                   true, preSolve);
3211                 if (model2) {
3212                   printf("Statistics for presolved model\n");
3213                   deleteModel2 = true;
3214                 } else {
3215                   printf("Presolved model looks infeasible - will use unpresolved\n");
3216                   model2 = lpSolver;
3217                 }
3218               } else {
3219                 printf("Statistics for unpresolved model\n");
3220                 model2 = lpSolver;
3221               }
3222               statistics(lpSolver, model2);
3223               if (deleteModel2)
3224                 delete model2;
3225             } else {
3226               sprintf(generalPrint, "** Current model not valid");
3227               printGeneralMessage(model_, generalPrint);
3228             }
3229             break;
3230           case CLP_PARAM_ACTION_TIGHTEN:
3231             if (goodModel) {
3232               int numberInfeasibilities = lpSolver->tightenPrimalBounds();
3233               if (numberInfeasibilities) {
3234                 sprintf(generalPrint, "** Analysis indicates model infeasible");
3235                 printGeneralMessage(model_, generalPrint);
3236               }
3237             } else {
3238               sprintf(generalPrint, "** Current model not valid");
3239               printGeneralMessage(model_, generalPrint);
3240             }
3241             break;
3242           case CLP_PARAM_ACTION_PLUSMINUS:
3243             if (goodModel) {
3244               ClpMatrixBase *saveMatrix = lpSolver->clpMatrix();
3245               ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(saveMatrix);
3246               if (clpMatrix) {
3247                 ClpPlusMinusOneMatrix *newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
3248                 if (newMatrix->getIndices()) {
3249                   lpSolver->replaceMatrix(newMatrix);
3250                   delete saveMatrix;
3251                   sprintf(generalPrint, "Matrix converted to +- one matrix");
3252                   printGeneralMessage(model_, generalPrint);
3253                 } else {
3254                   sprintf(generalPrint, "Matrix can not be converted to +- 1 matrix");
3255                   printGeneralMessage(model_, generalPrint);
3256                 }
3257               } else {
3258                 sprintf(generalPrint, "Matrix not a ClpPackedMatrix");
3259                 printGeneralMessage(model_, generalPrint);
3260               }
3261             } else {
3262               sprintf(generalPrint, "** Current model not valid");
3263               printGeneralMessage(model_, generalPrint);
3264             }
3265             break;
3266           case CLP_PARAM_ACTION_OUTDUPROWS:
3267             dominatedCuts = true;
3268 #ifdef JJF_ZERO
3269             if (goodModel) {
3270               int numberRows = clpSolver->getNumRows();
3271               //int nOut = outDupRow(clpSolver);
3272               CglDuplicateRow dupcuts(clpSolver);
3273               storedCuts = dupcuts.outDuplicates(clpSolver) != 0;
3274               int nOut = numberRows - clpSolver->getNumRows();
3275               if (nOut && !noPrinting_)
3276                 sprintf(generalPrint, "%d rows eliminated", nOut);
3277               generalMessageHandler->message(CLP_GENERAL, generalMessages)
3278                 << generalPrint
3279                 << CoinMessageEol;
3280             } else {
3281               sprintf(generalPrint, "** Current model not valid");
3282               printGeneralMessage(model_, generalPrint);
3283             }
3284 #endif
3285             break;
3286           case CLP_PARAM_ACTION_NETWORK:
3287             if (goodModel) {
3288               ClpMatrixBase *saveMatrix = lpSolver->clpMatrix();
3289               ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(saveMatrix);
3290               if (clpMatrix) {
3291                 ClpNetworkMatrix *newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
3292                 if (newMatrix->getIndices()) {
3293                   lpSolver->replaceMatrix(newMatrix);
3294                   delete saveMatrix;
3295                   sprintf(generalPrint, "Matrix converted to network matrix");
3296                   printGeneralMessage(model_, generalPrint);
3297                 } else {
3298                   sprintf(generalPrint, "Matrix can not be converted to network matrix");
3299                   printGeneralMessage(model_, generalPrint);
3300                 }
3301               } else {
3302                 sprintf(generalPrint, "Matrix not a ClpPackedMatrix");
3303                 printGeneralMessage(model_, generalPrint);
3304               }
3305             } else {
3306               sprintf(generalPrint, "** Current model not valid");
3307               printGeneralMessage(model_, generalPrint);
3308             }
3309             break;
3310           case CBC_PARAM_ACTION_DOHEURISTIC:
3311             if (goodModel) {
3312 #ifndef CBC_USE_INITIAL_TIME
3313               if (model_.useElapsedTime())
3314                 model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay());
3315               else
3316                 model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime());
3317 #endif
3318               int vubAction = parameters_[whichParam(CBC_PARAM_INT_VUBTRY, parameters_)].intValue();
3319               if (vubAction != -1) {
3320                 // look at vubs
3321                 // extra1 is number of ints to leave free
3322                 // Just ones which affect >= extra3
3323                 int extra3 = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, parameters_)].intValue();
3324                 /* 2 is cost above which to fix if feasible
3325                                    3 is fraction of integer variables fixed if relaxing (0.97)
3326                                    4 is fraction of all variables fixed if relaxing (0.0)
3327                                 */
3328                 double dextra[6];
3329                 int extra[5];
3330                 extra[1] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue();
3331                 int exp1 = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].intValue();
3332                 if (exp1 == 4 && extra[1] == -1)
3333                   extra[1] = 999998;
3334                 dextra[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue();
3335                 dextra[2] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue();
3336                 dextra[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue();
3337                 dextra[4] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue();
3338                 dextra[5] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA5, parameters_)].doubleValue();
3339                 if (!dextra[3])
3340                   dextra[3] = 0.97;
3341                 //OsiClpSolverInterface * newSolver =
3342                 fixVubs(model_, extra3, vubAction, generalMessageHandler,
3343                   debugValues, dextra, extra);
3344                 //assert (!newSolver);
3345               }
3346               // Actually do heuristics
3347               // may need to flip objective
3348               bool needFlip = model_.solver()->getObjSense() < 0.0;
3349               if (needFlip)
3350                 model_.flipModel();
3351               //if we do then - fix priorities in clonebutmodel_.convertToDynamic();
3352               bool objectsExist = model_.objects() != NULL;
3353               if (!objectsExist) {
3354                 model_.findIntegers(false);
3355                 model_.convertToDynamic();
3356               }
3357               // set priorities etc
3358               if (priorities) {
3359                 OsiObject **objects = model_.objects();
3360                 int numberObjects = model_.numberObjects();
3361                 for (int iObj = 0; iObj < numberObjects; iObj++) {
3362                   CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[iObj]);
3363                   if (!obj)
3364                     continue;
3365                   int iColumn = obj->columnNumber();
3366                   if (branchDirection) {
3367                     obj->setPreferredWay(branchDirection[iColumn]);
3368                   }
3369                   if (priorities) {
3370                     int iPriority = priorities[iColumn];
3371                     if (iPriority > 0)
3372                       obj->setPriority(iPriority);
3373                   }
3374                   if (pseudoUp && pseudoUp[iColumn]) {
3375                     CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(objects[iObj]);
3376                     assert(obj1a);
3377                     if (pseudoDown[iColumn] > 0.0)
3378                       obj1a->setDownPseudoCost(pseudoDown[iColumn]);
3379                     if (pseudoUp[iColumn] > 0.0)
3380                       obj1a->setUpPseudoCost(pseudoUp[iColumn]);
3381                   }
3382                 }
3383               }
3384               doHeuristics(&model_, 2, parameters_,
3385                 noPrinting_, initialPumpTune);
3386               if (!objectsExist) {
3387                 model_.deleteObjects(false);
3388               }
3389               if (needFlip)
3390                 model_.flipModel();
3391               if (model_.bestSolution()) {
3392                 model_.setProblemStatus(1);
3393                 model_.setSecondaryStatus(6);
3394 #ifdef COIN_HAS_ASL
3395                 if (statusUserFunction_[0]) {
3396                   double value = model_.getObjValue();
3397                   char buf[300];
3398                   int pos = 0;
3399                   pos += sprintf(buf + pos, "feasible,");
3400                   info.problemStatus = 0;
3401                   info.objValue = value;
3402                   pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
3403                     value);
3404                   sprintf(buf + pos, "\n0 iterations");
3405                   free(info.primalSolution);
3406                   int numberColumns = lpSolver->numberColumns();
3407                   info.primalSolution = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double)));
3408                   CoinCopyN(model_.bestSolution(), numberColumns, info.primalSolution);
3409                   int numberRows = lpSolver->numberRows();
3410                   free(info.dualSolution);
3411                   info.dualSolution = reinterpret_cast< double * >(malloc(numberRows * sizeof(double)));
3412                   CoinZeroN(info.dualSolution, numberRows);
3413                   CoinWarmStartBasis *basis = lpSolver->getBasis();
3414                   free(info.rowStatus);
3415                   info.rowStatus = reinterpret_cast< int * >(malloc(numberRows * sizeof(int)));
3416                   free(info.columnStatus);
3417                   info.columnStatus = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int)));
3418                   // Put basis in
3419                   int i;
3420                   // free,basic,ub,lb are 0,1,2,3
3421                   for (i = 0; i < numberRows; i++) {
3422                     CoinWarmStartBasis::Status status = basis->getArtifStatus(i);
3423                     info.rowStatus[i] = status;
3424                   }
3425                   for (i = 0; i < numberColumns; i++) {
3426                     CoinWarmStartBasis::Status status = basis->getStructStatus(i);
3427                     info.columnStatus[i] = status;
3428                   }
3429                   // put buffer into info
3430                   strcpy(info.buffer, buf);
3431                   delete basis;
3432                 }
3433 #endif
3434               }
3435               int returnCode = callBack(&model, 6);
3436               if (returnCode) {
3437                 // exit if user wants
3438                 delete babModel_;
3439                 babModel_ = NULL;
3440                 return returnCode;
3441               }
3442             }
3443             break;
3444           case CBC_PARAM_ACTION_MIPLIB:
3445             // User can set options - main difference is lack of model and CglPreProcess
3446             goodModel = true;
3447             parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].setIntValue(0);
3448             /*
3449                           Run branch-and-cut. First set a few options -- node comparison, scaling.
3450                           Print elapsed time at the end.
3451                         */
3452           case CBC_PARAM_ACTION_BAB: // branchAndBound
3453             // obsolete case STRENGTHEN:
3454             if (goodModel) {
3455               bool miplib = type == CBC_PARAM_ACTION_MIPLIB;
3456               int logLevel = parameters_[slog].intValue();
3457               int truncateColumns = COIN_INT_MAX;
3458               int truncateRows = -1;
3459               bool redoSOS = false;
3460               double *truncatedRhsLower = NULL;
3461               double *truncatedRhsUpper = NULL;
3462               int *newPriorities = NULL;
3463               // Reduce printout
3464               if (logLevel <= 1) {
3465                 model_.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
3466               } else {
3467                 model_.solver()->setHintParam(OsiDoReducePrint, false, OsiHintTry);
3468               }
3469               {
3470                 OsiSolverInterface *solver = model_.solver();
3471 #ifndef CBC_OTHER_SOLVER
3472                 OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver);
3473                 assert(si != NULL);
3474                 si->getModelPtr()->scaling(doScaling);
3475                 ClpSimplex *lpSolver = si->getModelPtr();
3476                 // deal with positive edge
3477                 double psi = parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue();
3478                 if (psi > 0.0) {
3479                   ClpDualRowPivot *dualp = lpSolver->dualRowPivot();
3480                   ClpDualRowSteepest *d1 = dynamic_cast< ClpDualRowSteepest * >(dualp);
3481                   ClpDualRowDantzig *d2 = dynamic_cast< ClpDualRowDantzig * >(dualp);
3482                   if (d1) {
3483                     ClpPEDualRowSteepest p(psi, d1->mode());
3484                     lpSolver->setDualRowPivotAlgorithm(p);
3485                   } else if (d2) {
3486                     ClpPEDualRowDantzig p(psi);
3487                     lpSolver->setDualRowPivotAlgorithm(p);
3488                   }
3489                   ClpPrimalColumnPivot *primalp = lpSolver->primalColumnPivot();
3490                   ClpPrimalColumnSteepest *p1 = dynamic_cast< ClpPrimalColumnSteepest * >(primalp);
3491                   ClpPrimalColumnDantzig *p2 = dynamic_cast< ClpPrimalColumnDantzig * >(primalp);
3492                   if (p1) {
3493                     ClpPEPrimalColumnSteepest p(psi, p1->mode());
3494                     lpSolver->setPrimalColumnPivotAlgorithm(p);
3495                   } else if (p2) {
3496                     ClpPEPrimalColumnDantzig p(psi);
3497                     lpSolver->setPrimalColumnPivotAlgorithm(p);
3498                   }
3499                 }
3500                 if (doVector) {
3501                   ClpMatrixBase *matrix = lpSolver->clpMatrix();
3502                   if (dynamic_cast< ClpPackedMatrix * >(matrix)) {
3503                     ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix);
3504                     clpMatrix->makeSpecialColumnCopy();
3505                   }
3506                 }
3507 #elif CBC_OTHER_SOLVER == 1
3508                 OsiCpxSolverInterface *si = dynamic_cast< OsiCpxSolverInterface * >(solver);
3509                 assert(si != NULL);
3510 #endif
3511                 statistics_nrows = si->getNumRows();
3512                 statistics_ncols = si->getNumCols();
3513                 statistics_nprocessedrows = si->getNumRows();
3514                 statistics_nprocessedcols = si->getNumCols();
3515                 // See if quadratic
3516 #ifndef CBC_OTHER_SOLVER
3517 #ifdef COIN_HAS_LINK
3518                 if (!complicatedInteger) {
3519                   ClpQuadraticObjective *obj = (dynamic_cast< ClpQuadraticObjective * >(lpSolver->objectiveAsObject()));
3520                   if (obj) {
3521                     preProcess = 0;
3522                     int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue();
3523                     parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(CoinMax(0, testOsiOptions));
3524                     // create coin model
3525                     coinModel = lpSolver->createCoinModel();
3526                     assert(coinModel);
3527                     // load from coin model
3528                     OsiSolverLink solver1;
3529                     OsiSolverInterface *solver2 = solver1.clone();
3530                     model_.assignSolver(solver2, false);
3531                     OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver());
3532                     assert(si != NULL);
3533                     si->setDefaultMeshSize(0.001);
3534                     // need some relative granularity
3535                     si->setDefaultBound(100.0);
3536                     double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue();
3537                     if (dextra3)
3538                       si->setDefaultMeshSize(dextra3);
3539                     si->setDefaultBound(1000.0);
3540                     si->setIntegerPriority(1000);
3541                     si->setBiLinearPriority(10000);
3542                     biLinearProblem = true;
3543                     si->setSpecialOptions2(2 + 4 + 8);
3544                     CoinModel *model2 = coinModel;
3545                     si->load(*model2, true, parameters_[log].intValue());
3546                     // redo
3547                     solver = model_.solver();
3548                     clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
3549                     lpSolver = clpSolver->getModelPtr();
3550                     clpSolver->messageHandler()->setLogLevel(0);
3551                     testOsiParameters = 0;
3552                     complicatedInteger = 2; // allow cuts
3553                     OsiSolverInterface *coinSolver = model_.solver();
3554                     OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(coinSolver);
3555                     if (linkSolver->quadraticModel()) {
3556                       ClpSimplex *qp = linkSolver->quadraticModel();
3557                       //linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5);
3558                       qp->nonlinearSLP(CoinMax(slpValue, 40), 1.0e-5);
3559                       qp->primal(1);
3560                       OsiSolverLinearizedQuadratic solver2(qp);
3561                       const double *solution = NULL;
3562                       // Reduce printout
3563                       solver2.setHintParam(OsiDoReducePrint, true, OsiHintTry);
3564                       CbcModel model2(solver2);
3565                       // Now do requested saves and modifications
3566                       CbcModel *cbcModel = &model2;
3567                       OsiSolverInterface *osiModel = model2.solver();
3568                       OsiClpSolverInterface *osiclpModel = dynamic_cast< OsiClpSolverInterface * >(osiModel);
3569                       ClpSimplex *clpModel = osiclpModel->getModelPtr();
3570 
3571                       // Set changed values
3572                       int numCutGens = 0;
3573 
3574 
3575                       CglProbing probing;
3576                       probing.setMaxProbe(10);
3577                       probing.setMaxLook(10);
3578                       probing.setMaxElements(200);
3579                       probing.setMaxProbeRoot(50);
3580                       probing.setMaxLookRoot(10);
3581                       probing.setRowCuts(3);
3582                       probing.setUsingObjective(true);
3583                       cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1);
3584                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3585 
3586                       CglGomory gomory;
3587                       gomory.setLimitAtRoot(512);
3588                       cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1);
3589                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3590 
3591                       CglKnapsackCover knapsackCover;
3592                       cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1);
3593                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3594 
3595                       CglRedSplit redSplit;
3596                       cbcModel->addCutGenerator(&redSplit, -99, "RedSplit", true, false, false, -100, -1, -1);
3597                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3598 
3599                       CglClique clique;
3600                       clique.setStarCliqueReport(false);
3601                       clique.setRowCliqueReport(false);
3602                       clique.setMinViolation(0.1);
3603                       cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1);
3604                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3605 
3606                       CglMixedIntegerRounding2 mixedIntegerRounding2;
3607                       cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1);
3608                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3609 
3610                       CglFlowCover flowCover;
3611                       cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1);
3612                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3613 
3614                       CglTwomir twomir;
3615                       twomir.setMaxElements(250);
3616                       cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1);
3617                       cbcModel->cutGenerator(numCutGens++)->setTiming(true);
3618                       int heuristicOption = parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].currentOptionAsInteger();
3619 		      if (heuristicOption) {
3620 			CbcHeuristicFPump heuristicFPump(*cbcModel);
3621 			heuristicFPump.setWhen(13);
3622 			heuristicFPump.setMaximumPasses(20);
3623 			heuristicFPump.setMaximumRetries(7);
3624 			heuristicFPump.setHeuristicName("feasibility pump");
3625 			heuristicFPump.setInitialWeight(1);
3626 			heuristicFPump.setFractionSmall(0.6);
3627 			cbcModel->addHeuristic(&heuristicFPump);
3628 
3629 			CbcRounding rounding(*cbcModel);
3630 			rounding.setHeuristicName("rounding");
3631 			cbcModel->addHeuristic(&rounding);
3632 
3633 			CbcHeuristicLocal heuristicLocal(*cbcModel);
3634 			heuristicLocal.setHeuristicName("combine solutions");
3635 			heuristicLocal.setSearchType(1);
3636 			heuristicLocal.setFractionSmall(0.6);
3637 			cbcModel->addHeuristic(&heuristicLocal);
3638 
3639 			CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel);
3640 			heuristicGreedyCover.setHeuristicName("greedy cover");
3641 			cbcModel->addHeuristic(&heuristicGreedyCover);
3642 
3643 			CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel);
3644 			heuristicGreedyEquality.setHeuristicName("greedy equality");
3645 			cbcModel->addHeuristic(&heuristicGreedyEquality);
3646 		      }
3647 		      CbcCompareDefault compare;
3648 		      cbcModel->setNodeComparison(compare);
3649 		      cbcModel->setNumberBeforeTrust(5);
3650                       cbcModel->setSpecialOptions(2);
3651                       cbcModel->messageHandler()->setLogLevel(1);
3652                       cbcModel->setMaximumCutPassesAtRoot(-100);
3653                       cbcModel->setMaximumCutPasses(1);
3654                       cbcModel->setMinimumDrop(0.05);
3655                       // For branchAndBound this may help
3656                       clpModel->defaultFactorizationFrequency();
3657                       clpModel->setDualBound(1.0001e+08);
3658                       clpModel->setPerturbation(50);
3659                       osiclpModel->setSpecialOptions(193);
3660                       osiclpModel->messageHandler()->setLogLevel(0);
3661                       osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100);
3662                       osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry);
3663                       // You can save some time by switching off message building
3664                       // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);
3665 
3666                       // Solve
3667 
3668                       cbcModel->initialSolve();
3669                       if (clpModel->tightenPrimalBounds() != 0) {
3670                         sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!");
3671                         printGeneralMessage(model_, generalPrint);
3672                         break;
3673                       }
3674                       clpModel->dual(); // clean up
3675                       cbcModel->initialSolve();
3676 #ifdef CBC_THREAD
3677                       int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue();
3678                       cbcModel->setNumberThreads(numberThreads % 100);
3679                       cbcModel->setThreadMode(CoinMin(numberThreads / 100, 7));
3680 #endif
3681                       //setCutAndHeuristicOptions(*cbcModel);
3682                       cbcModel->branchAndBound();
3683                       OsiSolverLinearizedQuadratic *solver3 = dynamic_cast< OsiSolverLinearizedQuadratic * >(model2.solver());
3684                       assert(solver3);
3685                       solution = solver3->bestSolution();
3686                       double bestObjectiveValue = solver3->bestObjectiveValue();
3687                       linkSolver->setBestObjectiveValue(bestObjectiveValue);
3688                       if (solution) {
3689                         linkSolver->setBestSolution(solution, solver3->getNumCols());
3690                       }
3691                       CbcHeuristicDynamic3 dynamic(model_);
3692                       dynamic.setHeuristicName("dynamic pass thru");
3693 		      if (heuristicOption)
3694 			model_.addHeuristic(&dynamic);
3695                       // if convex
3696                       if ((linkSolver->specialOptions2() & 4) != 0 && solution) {
3697                         int numberColumns = coinModel->numberColumns();
3698                         assert(linkSolver->objectiveVariable() == numberColumns);
3699                         // add OA cut
3700                         double offset;
3701                         double *gradient = new double[numberColumns + 1];
3702                         memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2),
3703                           numberColumns * sizeof(double));
3704                         double rhs = 0.0;
3705                         int *column = new int[numberColumns + 1];
3706                         int n = 0;
3707                         for (int i = 0; i < numberColumns; i++) {
3708                           double value = gradient[i];
3709                           if (fabs(value) > 1.0e-12) {
3710                             gradient[n] = value;
3711                             rhs += value * solution[i];
3712                             column[n++] = i;
3713                           }
3714                         }
3715                         gradient[n] = -1.0;
3716                         column[n++] = numberColumns;
3717                         storedAmpl.addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient);
3718                         delete[] gradient;
3719                         delete[] column;
3720                       }
3721                       // could do three way branching round a) continuous b) best solution
3722                       printf("obj %g\n", bestObjectiveValue);
3723                       linkSolver->initialSolve();
3724                     }
3725                   }
3726                 }
3727 #endif
3728 #endif
3729                 if (logLevel <= 1)
3730                   si->setHintParam(OsiDoReducePrint, true, OsiHintTry);
3731 #ifndef CBC_OTHER_SOLVER
3732                 si->setSpecialOptions(0x40000000);
3733 #endif
3734               }
3735               if (!miplib) {
3736                 if (!preSolve) {
3737                   model_.solver()->setHintParam(OsiDoPresolveInInitial, false, OsiHintTry);
3738                   model_.solver()->setHintParam(OsiDoPresolveInResolve, false, OsiHintTry);
3739                 }
3740                 double time1a = CoinCpuTime();
3741                 OsiSolverInterface *solver = model_.solver();
3742 #ifndef CBC_OTHER_SOLVER
3743                 OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver);
3744                 if (si)
3745                   si->setSpecialOptions(si->specialOptions() | 1024);
3746 #endif
3747                 model_.initialSolve();
3748 #ifndef CBC_OTHER_SOLVER
3749                 ClpSimplex *clpSolver = si->getModelPtr();
3750                 int iStatus = clpSolver->status();
3751                 int iStatus2 = clpSolver->secondaryStatus();
3752                 if (iStatus == 0) {
3753                   iStatus2 = 0;
3754                 } else if (iStatus == 1) {
3755                   iStatus = 0;
3756                   iStatus2 = 1; // say infeasible
3757                 } else if (iStatus == 2) {
3758                   iStatus = 0;
3759                   iStatus2 = 7; // say unbounded
3760                 } else if (iStatus == 3) {
3761                   iStatus = 1;
3762                   if (iStatus2 == 9)
3763                     iStatus2 = 4;
3764                   else
3765                     iStatus2 = 3; // Use nodes - as closer than solutions
3766                 } else if (iStatus == 4) {
3767                   iStatus = 2; // difficulties
3768                   iStatus2 = 0;
3769                 }
3770                 model_.setProblemStatus(iStatus);
3771                 model_.setSecondaryStatus(iStatus2);
3772                 si->setWarmStart(NULL);
3773                 int returnCode = 0;
3774                 if (callBack != NULL)
3775                   callBack(&model_, 1);
3776                 if (returnCode) {
3777                   // exit if user wants
3778                   delete babModel_;
3779                   babModel_ = NULL;
3780                   return returnCode;
3781                 }
3782                 if (clpSolver->status() > 0) {
3783                   // and in babModel if exists
3784                   if (babModel_) {
3785                     babModel_->setProblemStatus(iStatus);
3786                     babModel_->setSecondaryStatus(iStatus2);
3787                   }
3788                   if (!noPrinting_) {
3789                     iStatus = clpSolver->status();
3790                     const char *msg[] = { "infeasible", "unbounded", "stopped",
3791                       "difficulties", "other" };
3792                     sprintf(generalPrint, "Problem is %s - %.2f seconds",
3793                       msg[iStatus - 1], CoinCpuTime() - time1a);
3794                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
3795                       << generalPrint
3796                       << CoinMessageEol;
3797                   }
3798                   break;
3799                 }
3800                 clpSolver->setSpecialOptions(clpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound)
3801 #elif CBC_OTHER_SOLVER == 1
3802 #endif
3803                 if (!noPrinting_) {
3804                   sprintf(generalPrint, "Continuous objective value is %g - %.2f seconds",
3805                     solver->getObjValue(), CoinCpuTime() - time1a);
3806                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
3807                     << generalPrint
3808                     << CoinMessageEol;
3809                 }
3810                 if (model_.getMaximumNodes() == -987654321) {
3811                   // See if No objective!
3812                   int numberColumns = clpSolver->getNumCols();
3813                   const double *obj = clpSolver->getObjCoefficients();
3814                   const double *lower = clpSolver->getColLower();
3815                   const double *upper = clpSolver->getColUpper();
3816                   int nObj = 0;
3817                   for (int i = 0; i < numberColumns; i++) {
3818                     if (upper[i] > lower[i] && obj[i])
3819                       nObj++;
3820                   }
3821                   if (!nObj) {
3822                     printf("************No objective!!\n");
3823                     model_.setMaximumSolutions(1);
3824                     // Column copy
3825                     CoinPackedMatrix matrixByCol(*model_.solver()->getMatrixByCol());
3826                     //const double * element = matrixByCol.getElements();
3827                     //const int * row = matrixByCol.getIndices();
3828                     //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
3829                     const int *columnLength = matrixByCol.getVectorLengths();
3830                     for (int i = 0; i < numberColumns; i++) {
3831                       double value = (CoinDrand48() + 0.5) * 10000;
3832                       value = 10;
3833                       value *= columnLength[i];
3834                       int iValue = static_cast< int >(value) / 10;
3835                       //iValue=1;
3836                       clpSolver->setObjCoeff(i, iValue);
3837                     }
3838                   }
3839                 }
3840 #ifndef CBC_OTHER_SOLVER
3841                 if (!complicatedInteger && preProcess == 0 && clpSolver->tightenPrimalBounds(0.0, 0, true) != 0) {
3842                   sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!");
3843                   printGeneralMessage(model_, generalPrint);
3844                   model_.setProblemStatus(0);
3845                   model_.setSecondaryStatus(1);
3846                   // say infeasible for solution
3847                   integerStatus = 6;
3848                   // and in babModel if exists
3849                   if (babModel_) {
3850                     babModel_->setProblemStatus(0);
3851                     babModel_->setSecondaryStatus(1);
3852                   }
3853                   break;
3854                 }
3855                 if (clpSolver->dualBound() == 1.0e10) {
3856                   ClpSimplex temp = *clpSolver;
3857                   temp.setLogLevel(0);
3858                   temp.dual(0, 7);
3859                   // user did not set - so modify
3860                   // get largest scaled away from bound
3861                   double largest = 1.0e-12;
3862                   double largestScaled = 1.0e-12;
3863                   int numberRows = temp.numberRows();
3864                   const double *rowPrimal = temp.primalRowSolution();
3865                   const double *rowLower = temp.rowLower();
3866                   const double *rowUpper = temp.rowUpper();
3867                   const double *rowScale = temp.rowScale();
3868                   int iRow;
3869                   for (iRow = 0; iRow < numberRows; iRow++) {
3870                     double value = rowPrimal[iRow];
3871                     double above = value - rowLower[iRow];
3872                     double below = rowUpper[iRow] - value;
3873                     if (above < 1.0e12) {
3874                       largest = CoinMax(largest, above);
3875                     }
3876                     if (below < 1.0e12) {
3877                       largest = CoinMax(largest, below);
3878                     }
3879                     if (rowScale) {
3880                       double multiplier = rowScale[iRow];
3881                       above *= multiplier;
3882                       below *= multiplier;
3883                     }
3884                     if (above < 1.0e12) {
3885                       largestScaled = CoinMax(largestScaled, above);
3886                     }
3887                     if (below < 1.0e12) {
3888                       largestScaled = CoinMax(largestScaled, below);
3889                     }
3890                   }
3891 
3892                   int numberColumns = temp.numberColumns();
3893                   const double *columnPrimal = temp.primalColumnSolution();
3894                   const double *columnLower = temp.columnLower();
3895                   const double *columnUpper = temp.columnUpper();
3896                   const double *columnScale = temp.columnScale();
3897                   int iColumn;
3898                   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3899                     double value = columnPrimal[iColumn];
3900                     double above = value - columnLower[iColumn];
3901                     double below = columnUpper[iColumn] - value;
3902                     if (above < 1.0e12) {
3903                       largest = CoinMax(largest, above);
3904                     }
3905                     if (below < 1.0e12) {
3906                       largest = CoinMax(largest, below);
3907                     }
3908                     if (columnScale) {
3909                       double multiplier = 1.0 / columnScale[iColumn];
3910                       above *= multiplier;
3911                       below *= multiplier;
3912                     }
3913                     if (above < 1.0e12) {
3914                       largestScaled = CoinMax(largestScaled, above);
3915                     }
3916                     if (below < 1.0e12) {
3917                       largestScaled = CoinMax(largestScaled, below);
3918                     }
3919                   }
3920 #ifdef COIN_DEVELOP
3921                   if (!noPrinting_)
3922                     std::cout << "Largest (scaled) away from bound " << largestScaled
3923                               << " unscaled " << largest << std::endl;
3924 #endif
3925                   clpSolver->setDualBound(CoinMax(1.0001e8, CoinMin(100.0 * largest, 1.00001e10)));
3926                 }
3927                 si->resolve(); // clean up
3928 #endif
3929               }
3930               // If user made settings then use them
3931               if (!defaultSettings) {
3932                 OsiSolverInterface *solver = model_.solver();
3933                 if (!doScaling)
3934                   solver->setHintParam(OsiDoScale, false, OsiHintTry);
3935 #ifndef CBC_OTHER_SOLVER
3936                 OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver);
3937                 assert(si != NULL);
3938                 // get clp itself
3939                 ClpSimplex *modelC = si->getModelPtr();
3940                 //if (modelC->tightenPrimalBounds()!=0) {
3941                 //std::cout<<"Problem is infeasible!"<<std::endl;
3942                 //break;
3943                 //}
3944                 // bounds based on continuous
3945                 if (tightenFactor && !complicatedInteger) {
3946                   if (modelC->tightenPrimalBounds(tightenFactor) != 0) {
3947                     sprintf(generalPrint, "Problem is infeasible!");
3948                     printGeneralMessage(model_, generalPrint);
3949                     model_.setProblemStatus(0);
3950                     model_.setSecondaryStatus(1);
3951                     // and in babModel if exists
3952                     if (babModel_) {
3953                       babModel_->setProblemStatus(0);
3954                       babModel_->setSecondaryStatus(1);
3955                     }
3956                     break;
3957                   }
3958                 }
3959 #endif
3960               }
3961               // See if we want preprocessing
3962               OsiSolverInterface *saveSolver = NULL;
3963               CglPreProcess process;
3964               // Say integers in sync
3965               bool integersOK = true;
3966               delete babModel_;
3967               babModel_ = new CbcModel(model_);
3968 #ifndef CBC_OTHER_SOLVER
3969               int numberChanged = 0;
3970               OsiSolverInterface *solver3 = clpSolver->clone();
3971               babModel_->assignSolver(solver3);
3972               OsiClpSolverInterface *clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
3973               if (clpSolver2->messageHandler()->logLevel())
3974                 clpSolver2->messageHandler()->setLogLevel(1);
3975               if (logLevel > -1)
3976                 clpSolver2->messageHandler()->setLogLevel(logLevel);
3977               lpSolver = clpSolver2->getModelPtr();
3978               if (lpSolver->factorizationFrequency() == 200 && !miplib) {
3979                 // User did not touch preset
3980                 int numberRows = lpSolver->numberRows();
3981                 const int cutoff1 = 10000;
3982                 const int cutoff2 = 100000;
3983                 const int base = 75;
3984                 const int freq0 = 50;
3985                 const int freq1 = 200;
3986                 const int freq2 = 400;
3987                 const int maximum = 1000;
3988                 int frequency;
3989                 if (numberRows < cutoff1)
3990                   frequency = base + numberRows / freq0;
3991                 else if (numberRows < cutoff2)
3992                   frequency = base + cutoff1 / freq0 + (numberRows - cutoff1) / freq1;
3993                 else
3994                   frequency = base + cutoff1 / freq0 + (cutoff2 - cutoff1) / freq1 + (numberRows - cutoff2) / freq2;
3995                 lpSolver->setFactorizationFrequency(CoinMin(maximum, frequency));
3996               }
3997 #elif CBC_OTHER_SOLVER == 1
3998               OsiSolverInterface *solver3 = model_.solver()->clone();
3999               babModel_->assignSolver(solver3);
4000 #endif
4001               time2 = CoinCpuTime();
4002               totalTime += time2 - time1;
4003               //time1 = time2;
4004               double timeLeft = babModel_->getMaximumSeconds();
4005               int numberOriginalColumns = babModel_->solver()->getNumCols();
4006               if (preProcess == 7) {
4007                 // use strategy instead
4008                 preProcess = 0;
4009                 useStrategy = true;
4010 #ifdef COIN_HAS_LINK
4011                 // empty out any cuts
4012                 if (storedAmpl.sizeRowCuts()) {
4013                   printf("Emptying ampl stored cuts as internal preprocessing\n");
4014                   CglStored temp;
4015                   storedAmpl = temp;
4016                 }
4017 #endif
4018               }
4019               if (preProcess && type == CBC_PARAM_ACTION_BAB) {
4020                 // see whether to switch off preprocessing
4021                 // only allow SOS and integer
4022                 OsiObject **objects = babModel_->objects();
4023                 int numberObjects = babModel_->numberObjects();
4024                 for (int iObj = 0; iObj < numberObjects; iObj++) {
4025                   CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]);
4026                   CbcSimpleInteger *objSimpleInteger = dynamic_cast< CbcSimpleInteger * >(objects[iObj]);
4027                   if (!objSimpleInteger && !objSOS) {
4028                     // find all integers anyway
4029                     babModel_->findIntegers(true);
4030                     preProcess = 0;
4031                     break;
4032                   }
4033                 }
4034               }
4035               if (type == CBC_PARAM_ACTION_BAB) {
4036                 if (preProcess == 0 && numberLotSizing) {
4037                   if (!babModel_->numberObjects()) {
4038                     /* model may not have created objects
4039 				       If none then create
4040 				    */
4041                     babModel_->findIntegers(true);
4042                   }
4043                   // Lotsizing
4044                   //int numberColumns = babModel_->solver()->getNumCols();
4045                   CbcObject **objects = new CbcObject *[numberLotSizing];
4046                   double points[] = { 0.0, 0.0, 0.0, 0.0 };
4047                   for (int i = 0; i < numberLotSizing; i++) {
4048                     int iColumn = lotsize[i].column;
4049                     points[2] = lotsize[i].low;
4050                     points[3] = lotsize[i].high;
4051                     objects[i] = new CbcLotsize(&model_, iColumn, 2,
4052                       points, true);
4053                   }
4054                   babModel_->addObjects(numberLotSizing, objects);
4055                   for (int i = 0; i < numberLotSizing; i++)
4056                     delete objects[i];
4057                   delete[] objects;
4058                 }
4059                 double limit;
4060                 clpSolver->getDblParam(OsiDualObjectiveLimit, limit);
4061                 if (clpSolver->getObjValue() * clpSolver->getObjSense() >= limit * clpSolver->getObjSense())
4062                   preProcess = 0;
4063               }
4064               if (mipStartBefore.size()) {
4065                 CbcModel tempModel = *babModel_;
4066                 assert(babModel_->getNumCols() == model_.getNumCols());
4067                 std::vector< std::string > colNames;
4068                 for (int i = 0; (i < model_.solver()->getNumCols()); ++i)
4069                   colNames.push_back(model_.solver()->getColName(i));
4070                 std::vector< double > x(model_.getNumCols(), 0.0);
4071                 double obj;
4072                 int status = computeCompleteSolution(&tempModel, colNames, mipStartBefore, &x[0], obj);
4073                 // set cutoff ( a trifle high)
4074                 if (!status) {
4075                   double newCutoff = CoinMin(babModel_->getCutoff(), obj + 1.0e-4);
4076                   babModel_->setBestSolution(&x[0], static_cast< int >(x.size()), obj, false);
4077                   babModel_->setCutoff(newCutoff);
4078                   babModel_->setSolutionCount(1);
4079                   model_.setBestSolution(&x[0], static_cast< int >(x.size()), obj, false);
4080                   model_.setCutoff(newCutoff);
4081                   model_.setSolutionCount(1);
4082                 }
4083               }
4084               bool hasTimePreproc = !babModel_->maximumSecondsReached();
4085               if (!hasTimePreproc)
4086                 preProcess = 0;
4087               if (preProcess && type == CBC_PARAM_ACTION_BAB) {
4088                 saveSolver = babModel_->solver()->clone();
4089                 /* Do not try and produce equality cliques and
4090                                    do up to 10 passes */
4091                 OsiSolverInterface *solver2;
4092                 {
4093                   // Tell solver we are in Branch and Cut
4094                   saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo);
4095                   // Default set of cut generators
4096                   CglProbing generator1;
4097                   generator1.setUsingObjective(1);
4098                   generator1.setMaxPass(1);
4099                   generator1.setMaxPassRoot(1);
4100                   generator1.setMaxProbeRoot(CoinMin(3000, saveSolver->getNumCols()));
4101                   generator1.setMaxElements(100);
4102                   generator1.setMaxElementsRoot(200);
4103                   generator1.setMaxLookRoot(50);
4104                   if (saveSolver->getNumCols() > 3000)
4105                     generator1.setMaxProbeRoot(123);
4106                   generator1.setRowCuts(3);
4107                   // switch off duplicate columns if we have a solution
4108                   if (model_.bestSolution() /*||debugValues*/)
4109                     tunePreProcess |= 4096;
4110                   if ((tunePreProcess & 1) != 0) {
4111                     // heavy probing
4112                     generator1.setMaxPassRoot(2);
4113                     generator1.setMaxElements(1000);
4114                     generator1.setMaxProbeRoot(saveSolver->getNumCols());
4115                     generator1.setMaxLookRoot(saveSolver->getNumCols());
4116                   }
4117                   if ((babModel_->specialOptions() & 65536) != 0)
4118                     process.setOptions(1);
4119                   // Add in generators
4120                   if ((model_.moreSpecialOptions() & 65536) == 0)
4121                     process.addCutGenerator(&generator1);
4122                   int translate[] = { 9999, 0, 0, -3, 2, 3, -2, 9999, 4, 5, 0 };
4123                   process.passInMessageHandler(babModel_->messageHandler());
4124                   //process.messageHandler()->setLogLevel(babModel_->logLevel());
4125 #ifdef COIN_HAS_ASL
4126                   if (info.numberSos && doSOS && statusUserFunction_[0]) {
4127                     // SOS
4128                     numberSOS = info.numberSos;
4129                     sosStart = info.sosStart;
4130                     sosIndices = info.sosIndices;
4131                   }
4132 #endif
4133                   if (numberSOS && doSOS) {
4134                     // SOS
4135                     int numberColumns = saveSolver->getNumCols();
4136                     char *prohibited = new char[numberColumns];
4137                     memset(prohibited, 0, numberColumns);
4138                     // worth looking to see if any members can be made integer
4139 
4140                     int numberRows = saveSolver->getNumRows();
4141                     const CoinPackedMatrix *matrixByCol = saveSolver->getMatrixByCol();
4142                     const double *element = matrixByCol->getElements();
4143                     const int *row = matrixByCol->getIndices();
4144                     const CoinBigIndex *columnStart = matrixByCol->getVectorStarts();
4145                     const int *columnLength = matrixByCol->getVectorLengths();
4146                     const double *columnLower = saveSolver->getColLower();
4147                     const double *columnUpper = saveSolver->getColUpper();
4148                     const double *rowLower = saveSolver->getRowLower();
4149                     const double *rowUpper = saveSolver->getRowUpper();
4150                     double *sameElement = new double[numberRows];
4151                     int *rowCount = new int[2 * numberRows];
4152                     int *rowUsed = rowCount + numberRows;
4153                     memset(sameElement, 0, numberRows * sizeof(double));
4154                     memset(rowCount, 0, numberRows * sizeof(int));
4155                     int numberInteresting1 = 0;
4156                     int numberInteresting2 = 0;
4157                     int numberChanged = 0;
4158                     for (int iSet = 0; iSet < numberSOS; iSet++) {
4159                       if (sosType[iSet] != 1) {
4160                         for (int i = sosStart[iSet];
4161                              i < sosStart[iSet + 1]; i++) {
4162                           numberInteresting2++;
4163                           int iColumn = sosIndices[i];
4164                           prohibited[iColumn] = 1;
4165                         }
4166                       } else {
4167                         int nUsed = 0;
4168                         for (int i = sosStart[iSet];
4169                              i < sosStart[iSet + 1]; i++) {
4170                           int iColumn = sosIndices[i];
4171                           for (CoinBigIndex j = columnStart[iColumn];
4172                                j < columnStart[iColumn] + columnLength[iColumn]; j++) {
4173                             int iRow = row[j];
4174                             double el = element[j];
4175                             if (rowCount[iRow]) {
4176                               if (el != sameElement[iRow])
4177                                 sameElement[iRow] = 0.0;
4178                             } else {
4179                               sameElement[iRow] = el;
4180                               rowUsed[nUsed++] = iRow;
4181                             }
4182                             rowCount[iRow]++;
4183                           }
4184                         }
4185                         int nInSet = sosStart[iSet + 1] - sosStart[iSet];
4186                         double nonzeroValue = COIN_DBL_MAX;
4187                         for (int iUsed = 0; iUsed < nUsed; iUsed++) {
4188                           int iRow = rowUsed[iUsed];
4189                           if (rowCount[iRow] == nInSet && sameElement[iRow] && rowLower[iRow] == rowUpper[iRow]) {
4190                             // all entries must be 0.0 or xx
4191                             nonzeroValue = rowLower[iRow] / sameElement[iRow];
4192                           }
4193                           rowCount[iRow] = 0;
4194                           sameElement[iRow] = 0.0;
4195                         }
4196                         if (nonzeroValue != COIN_DBL_MAX) {
4197                           // could do scaling otherwise
4198                           if (fabs(nonzeroValue - 1.0) < 1.0e-8) {
4199                             for (int i = sosStart[iSet];
4200                                  i < sosStart[iSet + 1]; i++) {
4201                               int iColumn = sosIndices[i];
4202                               if (columnUpper[iColumn] < 0.0 || columnLower[iColumn] > 1.0) {
4203                                 printf("sos says infeasible\n");
4204                               }
4205                               if (!saveSolver->isInteger(iColumn)) {
4206                                 numberChanged++;
4207                                 saveSolver->setInteger(iColumn);
4208                               }
4209                               if (columnUpper[iColumn] < 1.0)
4210                                 saveSolver->setColUpper(iColumn, 0.0);
4211                               else
4212                                 saveSolver->setColUpper(iColumn, 1.0);
4213                               if (columnLower[iColumn] > 0.0)
4214                                 saveSolver->setColLower(iColumn, 1.0);
4215                               else
4216                                 saveSolver->setColLower(iColumn, 0.0);
4217 #ifndef DO_LESS_PROHIBITED
4218                               prohibited[iColumn] = 1;
4219 #endif
4220                             }
4221                           } else {
4222                             for (int i = sosStart[iSet];
4223                                  i < sosStart[iSet + 1]; i++) {
4224                               int iColumn = sosIndices[i];
4225 #ifndef DO_LESS_PROHIBITED
4226                               prohibited[iColumn] = 1;
4227 #endif
4228                             }
4229                           }
4230                         } else {
4231                           for (int i = sosStart[iSet];
4232                                i < sosStart[iSet + 1]; i++) {
4233                             int iColumn = sosIndices[i];
4234                             if (!saveSolver->isInteger(iColumn))
4235                               numberInteresting1++;
4236 #ifdef DO_LESS_PROHIBITED
4237                             if (!saveSolver->isInteger(iColumn))
4238 #endif
4239                               prohibited[iColumn] = 1;
4240                           }
4241                         }
4242                       }
4243                     }
4244                     if (numberChanged || numberInteresting1 || numberInteresting2) {
4245                       sprintf(generalPrint, "%d variables in SOS1 sets made integer, %d non integer in SOS1, %d in SOS2\n",
4246                         numberChanged, numberInteresting1, numberInteresting2);
4247                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
4248                         << generalPrint
4249                         << CoinMessageEol;
4250                     }
4251                     delete[] sameElement;
4252                     delete[] rowCount;
4253                     process.passInProhibited(prohibited, numberColumns);
4254                     delete[] prohibited;
4255                   }
4256                   if (0) {
4257 
4258                     // Special integers
4259                     int numberColumns = saveSolver->getNumCols();
4260                     char *prohibited = new char[numberColumns];
4261                     memset(prohibited, 0, numberColumns);
4262                     const CoinPackedMatrix *matrix = saveSolver->getMatrixByCol();
4263                     const int *columnLength = matrix->getVectorLengths();
4264                     int numberProhibited = 0;
4265                     for (int iColumn = numberColumns - 1; iColumn >= 0; iColumn--) {
4266                       if (!saveSolver->isInteger(iColumn) || columnLength[iColumn] > 1)
4267                         break;
4268                       numberProhibited++;
4269                       prohibited[iColumn] = 1;
4270                     }
4271                     if (numberProhibited) {
4272                       process.passInProhibited(prohibited, numberColumns);
4273                       printf("**** Treating last %d integers as special - give high priority?\n", numberProhibited);
4274                     }
4275                     delete[] prohibited;
4276                   }
4277                   if (!model_.numberObjects() && true) {
4278                     /* model may not have created objects
4279                                            If none then create
4280                                         */
4281                     model_.findIntegers(true);
4282                   }
4283                   // Lotsizing
4284                   if (numberLotSizing) {
4285                     int numberColumns = saveSolver->getNumCols();
4286                     char *prohibited = new char[numberColumns];
4287                     memset(prohibited, 0, numberColumns);
4288                     for (int i = 0; i < numberLotSizing; i++) {
4289                       int iColumn = lotsize[i].column;
4290                       prohibited[iColumn] = 1;
4291                     }
4292                     process.passInProhibited(prohibited, numberColumns);
4293                     delete[] prohibited;
4294                   }
4295                   if (model_.numberObjects()) {
4296                     OsiObject **oldObjects = babModel_->objects();
4297                     int numberOldObjects = babModel_->numberObjects();
4298                     if (!numberOldObjects) {
4299                       oldObjects = model_.objects();
4300                       numberOldObjects = model_.numberObjects();
4301                     }
4302                     // SOS
4303                     int numberColumns = saveSolver->getNumCols();
4304                     char *prohibited = new char[numberColumns];
4305                     memset(prohibited, 0, numberColumns);
4306                     int numberProhibited = 0;
4307                     for (int iObj = 0; iObj < numberOldObjects; iObj++) {
4308                       CbcSOS *obj = dynamic_cast< CbcSOS * >(oldObjects[iObj]);
4309                       if (obj) {
4310                         int n = obj->numberMembers();
4311                         const int *which = obj->members();
4312                         for (int i = 0; i < n; i++) {
4313                           int iColumn = which[i];
4314 #ifdef DO_LESS_PROHIBITED
4315                           if (!saveSolver->isInteger(iColumn))
4316 #endif
4317                             prohibited[iColumn] = 1;
4318                           numberProhibited++;
4319                         }
4320                       }
4321                       CbcLotsize *obj2 = dynamic_cast< CbcLotsize * >(oldObjects[iObj]);
4322                       if (obj2) {
4323                         int iColumn = obj2->columnNumber();
4324                         prohibited[iColumn] = 1;
4325                         numberProhibited++;
4326                       }
4327                     }
4328                     if (numberProhibited)
4329                       process.passInProhibited(prohibited, numberColumns);
4330                     delete[] prohibited;
4331                   }
4332                   int numberPasses = 10;
4333 #ifndef CBC_OTHER_SOLVER
4334                   if (doSprint > 0) {
4335                     // Sprint for primal solves
4336                     ClpSolve::SolveType method = ClpSolve::usePrimalorSprint;
4337                     ClpSolve::PresolveType presolveType = ClpSolve::presolveOff;
4338                     int numberPasses = 5;
4339                     int options[] = { 0, 3, 0, 0, 0, 0 };
4340                     int extraInfo[] = { -1, 20, -1, -1, -1, -1 };
4341                     extraInfo[1] = doSprint;
4342                     int independentOptions[] = { 0, 0, 3 };
4343                     ClpSolve clpSolve(method, presolveType, numberPasses,
4344                       options, extraInfo, independentOptions);
4345                     // say use in OsiClp
4346                     clpSolve.setSpecialOption(6, 1);
4347                     OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver);
4348                     osiclp->setSolveOptions(clpSolve);
4349                     osiclp->setHintParam(OsiDoDualInResolve, false);
4350                     // switch off row copy
4351                     osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256);
4352                     osiclp->getModelPtr()->setInfeasibilityCost(1.0e11);
4353                   }
4354 #endif
4355 #ifndef CBC_OTHER_SOLVER
4356                   {
4357                     OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver);
4358                     osiclp->setSpecialOptions(osiclp->specialOptions() | 1024);
4359                     int savePerturbation = osiclp->getModelPtr()->perturbation();
4360                     //#define CBC_TEMP1
4361 #ifdef CBC_TEMP1
4362                     if (savePerturbation == 50)
4363                       osiclp->getModelPtr()->setPerturbation(52); // try less
4364 #endif
4365                     if ((model_.moreSpecialOptions() & 65536) != 0)
4366                       process.setOptions(2 + 4 + 8); // no cuts
4367                     cbcPreProcessPointer = &process;
4368                     preProcessPointer = &process; // threadsafe
4369                     int saveOptions = osiclp->getModelPtr()->moreSpecialOptions();
4370                     if ((model_.specialOptions() & 16777216) != 0 && model_.getCutoff() > 1.0e30) {
4371                       osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions | 262144);
4372                     }
4373 #ifdef CGL_WRITEMPS
4374                     if (debugValues) {
4375                       process.setApplicationData(const_cast< double * >(debugValues));
4376                     }
4377 #endif
4378                     redoSOS = true;
4379                     bool keepPPN = parameters_[whichParam(CBC_PARAM_STR_PREPROCNAMES, parameters_)].currentOptionAsInteger();
4380 #ifdef SAVE_NAUTY
4381                     keepPPN = 1;
4382 #endif
4383                     process.setKeepColumnNames(keepPPN);
4384                     process.setTimeLimit(babModel_->getMaximumSeconds() - babModel_->getCurrentSeconds(), babModel_->useElapsedTime());
4385                     if (model.getKeepNamesPreproc())
4386                       process.setKeepColumnNames(true);
4387                     solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses,
4388                       tunePreProcess);
4389                     if (solver2) {
4390                       model_.setOriginalColumns(process.originalColumns(), solver2->getNumCols());
4391 
4392                       osiclp->getModelPtr()->setPerturbation(savePerturbation);
4393                       osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions);
4394                     }
4395                   }
4396 #elif CBC_OTHER_SOLVER == 1
4397                   cbcPreProcessPointer = &process;
4398                   preProcessPointer = &process; // threadsafe
4399                   redoSOS = true;
4400                   if (model.getKeepNamesPreproc())
4401                     process.setKeepColumnNames(true);
4402                   solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses,
4403                     tunePreProcess);
4404 #endif
4405                   integersOK = false; // We need to redo if CbcObjects exist
4406                   // Tell solver we are not in Branch and Cut
4407                   saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
4408                   if (solver2)
4409                     solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo);
4410                 }
4411 #ifdef COIN_HAS_ASL
4412                 if (!solver2 && statusUserFunction_[0]) {
4413                   // infeasible
4414                   info.problemStatus = 1;
4415                   info.objValue = 1.0e100;
4416                   sprintf(info.buffer, "infeasible/unbounded by pre-processing");
4417                   info.primalSolution = NULL;
4418                   info.dualSolution = NULL;
4419                   break;
4420                 }
4421 #endif
4422                 if (!noPrinting_) {
4423                   if (!solver2) {
4424                     sprintf(generalPrint, "Pre-processing says infeasible or unbounded");
4425                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
4426                       << generalPrint
4427                       << CoinMessageEol;
4428                   } else {
4429                     //printf("processed model has %d rows, %d columns and %d elements\n",
4430                     //     solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements());
4431                   }
4432                 }
4433                 if (!solver2) {
4434                   // say infeasible for solution
4435                   integerStatus = 6;
4436                   delete saveSolver;
4437                   saveSolver = NULL;
4438                   model_.setProblemStatus(0);
4439                   model_.setSecondaryStatus(1);
4440                   babModel_->setProblemStatus(0);
4441                   babModel_->setSecondaryStatus(1);
4442                 } else {
4443                   statistics_nprocessedrows = solver2->getNumRows();
4444                   statistics_nprocessedcols = solver2->getNumCols();
4445                   model_.setProblemStatus(-1);
4446                   babModel_->setProblemStatus(-1);
4447                 }
4448                 int returnCode = 0;
4449                 if (callBack != NULL)
4450                   returnCode = callBack(babModel_, 2);
4451                 if (returnCode) {
4452                   // exit if user wants
4453                   delete babModel_;
4454                   babModel_ = NULL;
4455                   return returnCode;
4456                 }
4457                 if (!solver2)
4458                   break;
4459                 if (model_.bestSolution()) {
4460                   // need to redo - in case no better found in BAB
4461                   // just get integer part right
4462                   const int *originalColumns = process.originalColumns();
4463                   int numberColumns =
4464 		    CoinMin(solver2->getNumCols(), babModel_->getNumCols());
4465                   double *bestSolution = babModel_->bestSolution();
4466                   const double *oldBestSolution = model_.bestSolution();
4467                   for (int i = 0; i < numberColumns; i++) {
4468                     int jColumn = originalColumns[i];
4469                     bestSolution[i] = oldBestSolution[jColumn];
4470                   }
4471                 }
4472                 //solver2->resolve();
4473                 if (preProcess == 2 || preProcess == 10) {
4474                   // names are wrong - redo
4475                   const int *originalColumns = process.originalColumns();
4476                   int numberColumns = solver2->getNumCols();
4477                   OsiSolverInterface *originalSolver = model.solver();
4478                   for (int i = 0; i < numberColumns; i++) {
4479                     int iColumn = originalColumns[i];
4480                     solver2->setColName(i, originalSolver->getColName(iColumn));
4481                   }
4482                   OsiClpSolverInterface *clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(solver2);
4483                   ClpSimplex *lpSolver = clpSolver2->getModelPtr();
4484                   char name[100];
4485                   if (preProcess == 2) {
4486                     strcpy(name, "presolved.mps");
4487                   } else {
4488                     //strcpy(name,lpSolver->problemName().c_str());
4489                     int iParam;
4490                     for (iParam = 0; iParam < (int)parameters_.size(); iParam++) {
4491                       int match = parameters_[iParam].matches("import");
4492                       if (match == 1)
4493                         break;
4494                     }
4495                     strcpy(name, parameters_[iParam].stringValue().c_str());
4496                     char *dot = strstr(name, ".mps");
4497                     if (!dot)
4498                       dot = strstr(name, ".lp");
4499                     if (dot) {
4500                       *dot = '\0';
4501                       int n = static_cast< int >(dot - name);
4502                       int i;
4503                       for (i = n - 1; i >= 0; i--) {
4504                         if (name[i] == '/')
4505                           break;
4506                       }
4507                       if (i >= 0)
4508                         memmove(name, name + i + 1, n);
4509                       strcat(name, "_preprocessed.mps");
4510                     } else {
4511                       strcpy(name, "preprocessed.mps");
4512                     }
4513                   }
4514                   lpSolver->writeMps(name, 0, 1, lpSolver->optimizationDirection());
4515                   printf("Preprocessed model (minimization) on %s\n", name);
4516                   if (preProcess == 10) {
4517                     printf("user wanted to stop\n");
4518                     exit(0);
4519                   }
4520                 }
4521                 {
4522                   // look at new integers
4523                   int numberOriginalColumns = process.originalModel()->getNumCols();
4524                   const int *originalColumns = process.originalColumns();
4525                   OsiClpSolverInterface *osiclp2 = dynamic_cast< OsiClpSolverInterface * >(solver2);
4526                   int numberColumns = osiclp2->getNumCols();
4527                   OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver);
4528                   for (int i = 0; i < numberColumns; i++) {
4529                     int iColumn = originalColumns[i];
4530                     if (iColumn < numberOriginalColumns) {
4531                       if (osiclp2->isInteger(i) && !osiclp->isInteger(iColumn))
4532                         osiclp2->setOptionalInteger(i); // say optional
4533                     }
4534                   }
4535                   // do lotsizing
4536                   if (numberLotSizing) {
4537                     CbcObject **objects = new CbcObject *[numberLotSizing];
4538                     double points[] = { 0.0, 0.0, 0.0, 0.0 };
4539                     for (int i = 0; i < numberLotSizing; i++) {
4540                       int iColumn = lotsize[i].column;
4541                       points[2] = lotsize[i].low;
4542                       points[3] = lotsize[i].high;
4543                       objects[i] = new CbcLotsize(babModel_, iColumn, 2,
4544                         points, true);
4545                     }
4546                     babModel_->addObjects(numberLotSizing, objects);
4547                     for (int i = 0; i < numberLotSizing; i++)
4548                       delete objects[i];
4549                     delete[] objects;
4550                   }
4551                   // redo existing SOS
4552                   if (osiclp->numberSOS()) {
4553                     redoSOS = false;
4554                     int *back = new int[numberOriginalColumns];
4555                     for (int i = 0; i < numberOriginalColumns; i++)
4556                       back[i] = -1;
4557                     for (int i = 0; i < numberColumns; i++) {
4558                       int iColumn = originalColumns[i];
4559                       back[iColumn] = i;
4560                     }
4561                     int numberSOSOld = osiclp->numberSOS();
4562                     int numberSOS = osiclp2->numberSOS();
4563                     assert(numberSOS == numberSOSOld);
4564                     CoinSet *setInfo = const_cast< CoinSet * >(osiclp2->setInfo());
4565                     for (int i = 0; i < numberSOS; i++) {
4566                       //int type = setInfo[i].setType();
4567                       int n = setInfo[i].numberEntries();
4568                       int *which = setInfo[i].modifiableWhich();
4569 #ifndef DO_LESS_PROHIBITED
4570                       for (int j = 0; j < n; j++) {
4571                         int iColumn = which[j];
4572                         iColumn = back[iColumn];
4573                         assert(iColumn >= 0);
4574                         which[j] = iColumn;
4575                       }
4576 #else
4577                       double *weights = setInfo[i].modifiableWeights();
4578                       int n2 = 0;
4579                       for (int j = 0; j < n; j++) {
4580                         int iColumn = which[j];
4581                         iColumn = back[iColumn];
4582                         if (iColumn >= 0) {
4583                           which[n2] = iColumn;
4584                           weights[n2++] = weights[j];
4585                         }
4586                       }
4587                       setInfo[i].setNumberEntries(n2);
4588 #endif
4589                     }
4590                     delete[] back;
4591                   }
4592                 }
4593                 // we have to keep solver2 so pass clone
4594                 solver2 = solver2->clone();
4595                 // see if extra variables wanted
4596                 int threshold = parameters_[whichParam(CBC_PARAM_INT_EXTRA_VARIABLES, parameters_)].intValue();
4597                 int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue();
4598                 if (threshold || (more2 & (512 | 1024)) != 0) {
4599                   int numberColumns = solver2->getNumCols();
4600                   truncateRows = solver2->getNumRows();
4601                   bool modifiedModel = false;
4602                   int highPriority = 0;
4603                   /*
4604 				    normal - no priorities
4605 				    >10000 equal high priority
4606 				    >20000 higher priority for higher cost
4607 				  */
4608                   if (threshold > 10000) {
4609                     highPriority = threshold / 10000;
4610                     threshold -= 10000 * highPriority;
4611                   }
4612                   // If 1000 set then don't put obj on ne variables
4613                   bool moveObjective = true;
4614                   if (threshold > 1000) {
4615                     moveObjective = false;
4616                     threshold -= 1000;
4617                   }
4618                   const double *columnLower = solver2->getColLower();
4619                   const double *columnUpper = solver2->getColUpper();
4620                   const double *objective = solver2->getObjCoefficients();
4621                   int numberIntegers = 0;
4622                   int numberBinary = 0;
4623                   int numberTotalIntegers = 0;
4624                   double *obj = new double[numberColumns];
4625                   int *which = new int[numberColumns];
4626                   for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
4627                     if (solver2->isInteger(iColumn)) {
4628                       numberTotalIntegers++;
4629                       if (columnUpper[iColumn] > columnLower[iColumn]) {
4630                         numberIntegers++;
4631                         if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1)
4632                           numberBinary++;
4633                       }
4634                     }
4635                   }
4636                   int numberSort = 0;
4637                   int numberZero = 0;
4638                   int numberZeroContinuous = 0;
4639                   int numberDifferentObj = 0;
4640                   int numberContinuous = 0;
4641                   for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
4642                     if (columnUpper[iColumn] > columnLower[iColumn]) {
4643                       if (solver2->isInteger(iColumn)) {
4644                         if (!objective[iColumn]) {
4645                           numberZero++;
4646                         } else {
4647                           obj[numberSort] = fabs(objective[iColumn]);
4648                           which[numberSort++] = iColumn;
4649                         }
4650                       } else if (objective[iColumn]) {
4651                         numberContinuous++;
4652                       } else {
4653                         numberZeroContinuous++;
4654                       }
4655                     }
4656                   }
4657                   CoinSort_2(obj, obj + numberSort, which);
4658                   double last = obj[0];
4659                   for (int jColumn = 1; jColumn < numberSort; jColumn++) {
4660                     if (fabs(obj[jColumn] - last) > 1.0e-12) {
4661                       numberDifferentObj++;
4662                       last = obj[jColumn];
4663                     }
4664                   }
4665                   numberDifferentObj++;
4666                   sprintf(generalPrint, "Problem has %d integers (%d of which binary) and %d continuous",
4667                     numberIntegers, numberBinary, numberColumns - numberIntegers);
4668                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
4669                     << generalPrint
4670                     << CoinMessageEol;
4671                   if (numberColumns > numberIntegers) {
4672                     sprintf(generalPrint, "%d continuous have nonzero objective, %d have zero objective",
4673                       numberContinuous, numberZeroContinuous);
4674                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
4675                       << generalPrint
4676                       << CoinMessageEol;
4677                   }
4678                   sprintf(generalPrint, "%d integer have nonzero objective, %d have zero objective, %d different nonzero (taking abs)",
4679                     numberSort, numberZero, numberDifferentObj);
4680                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
4681                     << generalPrint
4682                     << CoinMessageEol;
4683                   if (numberDifferentObj <= threshold + (numberZero) ? 1 : 0 && numberDifferentObj) {
4684                     int *backward = NULL;
4685                     if (highPriority) {
4686                       newPriorities = new int[numberTotalIntegers + numberDifferentObj + numberColumns];
4687                       backward = newPriorities + numberTotalIntegers + numberDifferentObj;
4688                       numberTotalIntegers = 0;
4689                       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
4690                         if (solver2->isInteger(iColumn)) {
4691                           backward[iColumn] = numberTotalIntegers;
4692                           newPriorities[numberTotalIntegers++] = 10000;
4693                         }
4694                       }
4695                     }
4696                     int iLast = 0;
4697                     double last = obj[0];
4698                     for (int jColumn = 1; jColumn < numberSort; jColumn++) {
4699                       if (fabs(obj[jColumn] - last) > 1.0e-12) {
4700                         sprintf(generalPrint, "%d variables have objective of %g",
4701                           jColumn - iLast, last);
4702                         generalMessageHandler->message(CLP_GENERAL, generalMessages)
4703                           << generalPrint
4704                           << CoinMessageEol;
4705                         iLast = jColumn;
4706                         last = obj[jColumn];
4707                       }
4708                     }
4709                     sprintf(generalPrint, "%d variables have objective of %g",
4710                       numberSort - iLast, last);
4711                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
4712                       << generalPrint
4713                       << CoinMessageEol;
4714                     int spaceNeeded = numberSort + numberDifferentObj;
4715                     CoinBigIndex *columnAddDummy = new CoinBigIndex[numberDifferentObj + 1];
4716                     int *columnAdd = new int[spaceNeeded];
4717                     double *elementAdd = new double[spaceNeeded];
4718                     CoinBigIndex *rowAdd = new CoinBigIndex[numberDifferentObj + 1];
4719                     double *objectiveNew = new double[3 * numberDifferentObj];
4720                     double *lowerNew = objectiveNew + numberDifferentObj;
4721                     double *upperNew = lowerNew + numberDifferentObj;
4722                     memset(columnAddDummy, 0,
4723                       (numberDifferentObj + 1) * sizeof(CoinBigIndex));
4724                     iLast = 0;
4725                     last = obj[0];
4726                     numberDifferentObj = 0;
4727                     int priorityLevel = 9999;
4728                     int numberElements = 0;
4729                     rowAdd[0] = 0;
4730                     for (int jColumn = 1; jColumn < numberSort + 1; jColumn++) {
4731                       if (jColumn == numberSort || fabs(obj[jColumn] - last) > 1.0e-12) {
4732                         // not if just one
4733                         if (jColumn - iLast > 1) {
4734                           // do priority
4735                           if (highPriority == 1) {
4736                             newPriorities[numberTotalIntegers + numberDifferentObj]
4737                               = 500;
4738                           } else if (highPriority == 2) {
4739                             newPriorities[numberTotalIntegers + numberDifferentObj]
4740                               = priorityLevel;
4741                             priorityLevel--;
4742                           }
4743                           int iColumn = which[iLast];
4744                           objectiveNew[numberDifferentObj] = objective[iColumn];
4745                           double lower = 0.0;
4746                           double upper = 0.0;
4747                           for (int kColumn = iLast; kColumn < jColumn; kColumn++) {
4748                             iColumn = which[kColumn];
4749                             if (moveObjective)
4750                               solver2->setObjCoeff(iColumn, 0.0);
4751                             double lowerValue = columnLower[iColumn];
4752                             double upperValue = columnUpper[iColumn];
4753                             double elementValue = -1.0;
4754                             if (objectiveNew[numberDifferentObj] * objective[iColumn] < 0.0) {
4755                               lowerValue = -columnUpper[iColumn];
4756                               upperValue = -columnLower[iColumn];
4757                               elementValue = 1.0;
4758                             }
4759                             if (!moveObjective)
4760                               objectiveNew[numberDifferentObj] = 0.0;
4761                             columnAdd[numberElements] = iColumn;
4762                             elementAdd[numberElements++] = elementValue;
4763                             if (lower != -COIN_DBL_MAX) {
4764                               if (lowerValue != -COIN_DBL_MAX)
4765                                 lower += lowerValue;
4766                               else
4767                                 lower = -COIN_DBL_MAX;
4768                             }
4769                             if (upper != COIN_DBL_MAX) {
4770                               if (upperValue != COIN_DBL_MAX)
4771                                 upper += upperValue;
4772                               else
4773                                 upper = COIN_DBL_MAX;
4774                             }
4775                           }
4776                           columnAdd[numberElements] = numberColumns + numberDifferentObj;
4777                           elementAdd[numberElements++] = 1.0;
4778                           lowerNew[numberDifferentObj] = lower;
4779                           upperNew[numberDifferentObj] = upper;
4780                           numberDifferentObj++;
4781                           rowAdd[numberDifferentObj] = numberElements;
4782                         } else if (highPriority) {
4783                           // just one
4784                           // do priority
4785                           int iColumn = which[iLast];
4786                           int iInt = backward[iColumn];
4787                           if (highPriority == 1) {
4788                             newPriorities[iInt] = 500;
4789                           } else {
4790                             newPriorities[iInt] = priorityLevel;
4791                             priorityLevel--;
4792                           }
4793                         }
4794                         if (jColumn < numberSort) {
4795                           iLast = jColumn;
4796                           last = obj[jColumn];
4797                         }
4798                       }
4799                     }
4800                     if (numberDifferentObj) {
4801                       // add columns
4802                       solver2->addCols(numberDifferentObj,
4803                         columnAddDummy, NULL, NULL,
4804                         lowerNew, upperNew, objectiveNew);
4805                       // add constraints and make integer if all integer in group
4806 #ifdef COIN_HAS_CLP
4807                       OsiClpSolverInterface *clpSolver2
4808                         = dynamic_cast< OsiClpSolverInterface * >(solver2);
4809 #endif
4810                       for (int iObj = 0; iObj < numberDifferentObj; iObj++) {
4811                         lowerNew[iObj] = 0.0;
4812                         upperNew[iObj] = 0.0;
4813                         solver2->setInteger(numberColumns + iObj);
4814 #ifdef COIN_HAS_CLP
4815                         if (clpSolver2)
4816                           clpSolver2->setOptionalInteger(numberColumns + iObj);
4817 #endif
4818                       }
4819                       solver2->addRows(numberDifferentObj,
4820                         rowAdd, columnAdd, elementAdd,
4821                         lowerNew, upperNew);
4822                       sprintf(generalPrint, "Replacing model - %d new variables", numberDifferentObj);
4823                       modifiedModel = true;
4824                     }
4825                     delete[] columnAdd;
4826                     delete[] columnAddDummy;
4827                     delete[] elementAdd;
4828                     delete[] rowAdd;
4829                     delete[] objectiveNew;
4830                   }
4831                   delete[] which;
4832                   delete[] obj;
4833                   if ((more2 & (512 | 1024)) != 0) {
4834                     // try for row slacks etc
4835                     // later do row branching
4836                     int iRow, iColumn;
4837                     int numberColumns = solver2->getNumCols();
4838                     int numberRows = solver2->getNumRows();
4839                     int fudgeObjective = more2 & 512;
4840                     int addSlacks = more2 & 1024;
4841                     if (fudgeObjective) {
4842                       bool moveObj = false;
4843                       fudgeObjective = 0;
4844                       const double *objective = solver2->getObjCoefficients();
4845                       const double *columnLower = solver2->getColLower();
4846                       const double *columnUpper = solver2->getColUpper();
4847                       double *newValues = new double[numberColumns + 1];
4848                       int *newColumn = new int[numberColumns + 1];
4849                       bool allInteger = true;
4850                       int n = 0;
4851                       double newLower = 0.0;
4852                       double newUpper = 0.0;
4853                       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4854                         if (objective[iColumn]) {
4855                           if (!solver2->isInteger(iColumn)) {
4856                             allInteger = false;
4857                             break;
4858                           } else {
4859                             double value = objective[iColumn];
4860                             double nearest = floor(value + 0.5);
4861                             if (fabs(value - nearest) > 1.0e-8) {
4862                               allInteger = false;
4863                               break;
4864                             } else {
4865                               newValues[n] = nearest;
4866                               newColumn[n++] = iColumn;
4867                               if (nearest > 0.0) {
4868                                 newLower += CoinMax(columnLower[iColumn], -1.0e20) * nearest;
4869                                 newUpper += CoinMin(columnUpper[iColumn], 1.0e20) * nearest;
4870                               } else {
4871                                 newUpper += CoinMax(columnLower[iColumn], -1.0e20) * nearest;
4872                                 newLower += CoinMin(columnUpper[iColumn], 1.0e20) * nearest;
4873                               }
4874                             }
4875                           }
4876                         }
4877                       }
4878                       if (allInteger && n) {
4879                         fudgeObjective = n;
4880                         solver2->addCol(0, NULL, NULL, newLower, newUpper, 0.0, "obj_col");
4881                         solver2->setInteger(numberColumns);
4882                         newValues[n] = -1.0;
4883                         newColumn[n++] = numberColumns;
4884                         solver2->addRow(n, newColumn, newValues, 0.0, 0.0);
4885                         if (moveObj) {
4886                           memset(newValues, 0, numberColumns * sizeof(double));
4887                           newValues[numberColumns] = 1.0;
4888                           solver2->setObjective(newValues);
4889                         }
4890                         numberRows++;
4891                         numberColumns++;
4892                       }
4893                       delete[] newValues;
4894                       delete[] newColumn;
4895                     }
4896                     if (addSlacks) {
4897                       bool moveObj = false;
4898                       addSlacks = 0;
4899                       // get row copy
4900                       const CoinPackedMatrix *matrix = solver2->getMatrixByRow();
4901                       const double *element = matrix->getElements();
4902                       const int *column = matrix->getIndices();
4903                       const CoinBigIndex *rowStart = matrix->getVectorStarts();
4904                       const int *rowLength = matrix->getVectorLengths();
4905                       const double *rowLower = solver2->getRowLower();
4906                       const double *rowUpper = solver2->getRowUpper();
4907                       const double *columnLower = solver2->getColLower();
4908                       const double *columnUpper = solver2->getColUpper();
4909 
4910                       // maximum space for additional columns
4911                       CoinBigIndex *newColumnStart = new CoinBigIndex[numberRows + 1];
4912                       newColumnStart[0] = 0;
4913                       int *newRow = new int[numberRows];
4914                       double *newElement = new double[numberRows];
4915                       double *newObjective = new double[numberRows];
4916                       double *newColumnLower = new double[numberRows];
4917                       double *newColumnUpper = new double[numberRows];
4918                       double *oldObjective = CoinCopyOfArray(solver2->getObjCoefficients(),
4919                         numberColumns);
4920                       for (iRow = 0; iRow < numberRows; iRow++) {
4921                         if (rowLower[iRow] != rowUpper[iRow]) {
4922                           bool allInteger = true;
4923                           double newLower = 0.0;
4924                           double newUpper = 0.0;
4925                           double constantObjective = 0.0;
4926                           for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
4927                             int iColumn = column[j];
4928                             if (!solver2->isInteger(iColumn)) {
4929                               allInteger = false;
4930                               break;
4931                             } else {
4932                               double value = element[j];
4933                               double nearest = floor(value + 0.5);
4934                               if (fabs(value - nearest) > 1.0e-8) {
4935                                 allInteger = false;
4936                                 break;
4937                               } else {
4938                                 if (!oldObjective[iColumn])
4939                                   constantObjective = COIN_DBL_MAX;
4940                                 if (!constantObjective) {
4941                                   constantObjective = oldObjective[iColumn] / nearest;
4942                                 } else if (constantObjective != COIN_DBL_MAX) {
4943                                   double newConstant = oldObjective[iColumn] / nearest;
4944                                   if (constantObjective > 0.0) {
4945                                     if (newConstant <= 0.0)
4946                                       constantObjective = COIN_DBL_MAX;
4947                                     else
4948                                       constantObjective = CoinMin(constantObjective, newConstant);
4949                                   } else {
4950                                     if (newConstant >= 0.0)
4951                                       constantObjective = COIN_DBL_MAX;
4952                                     else
4953                                       constantObjective = CoinMax(constantObjective, newConstant);
4954                                   }
4955                                 }
4956                                 if (nearest > 0.0) {
4957                                   newLower += CoinMax(columnLower[iColumn], -1.0e20) * nearest;
4958                                   newUpper += CoinMin(columnUpper[iColumn], 1.0e20) * nearest;
4959                                 } else {
4960                                   newUpper += CoinMax(columnLower[iColumn], -1.0e20) * nearest;
4961                                   newLower += CoinMin(columnUpper[iColumn], 1.0e20) * nearest;
4962                                 }
4963                               }
4964                             }
4965                           }
4966                           if (allInteger) {
4967                             newColumnStart[addSlacks + 1] = addSlacks + 1;
4968                             newRow[addSlacks] = iRow;
4969                             newElement[addSlacks] = -1.0;
4970                             newObjective[addSlacks] = 0.0;
4971                             if (moveObj && constantObjective != COIN_DBL_MAX) {
4972                               // move some of objective here if looks constant
4973                               newObjective[addSlacks] = constantObjective;
4974                               for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
4975                                 int iColumn = column[j];
4976                                 double value = element[j];
4977                                 double nearest = floor(value + 0.5);
4978                                 oldObjective[iColumn] -= nearest * constantObjective;
4979                               }
4980                             }
4981                             newColumnLower[addSlacks] = CoinMax(newLower, ceil(rowLower[iRow]));
4982                             ;
4983                             newColumnUpper[addSlacks] = CoinMin(newUpper, floor(rowUpper[iRow]));
4984                             addSlacks++;
4985                           }
4986                         }
4987                       }
4988                       if (addSlacks) {
4989                         solver2->setObjective(oldObjective);
4990                         solver2->addCols(addSlacks, newColumnStart, newRow, newElement,
4991                           newColumnLower, newColumnUpper, newObjective);
4992                         truncatedRhsLower = CoinCopyOfArray(solver2->getRowLower(), numberRows);
4993                         truncatedRhsUpper = CoinCopyOfArray(solver2->getRowUpper(), numberRows);
4994                         for (int j = 0; j < addSlacks; j++) {
4995                           int iRow = newRow[j];
4996                           solver2->setRowLower(iRow, 0.0);
4997                           solver2->setRowUpper(iRow, 0.0);
4998                           int iColumn = j + numberColumns;
4999                           solver2->setInteger(iColumn);
5000                           std::string name = solver2->getRowName(iRow);
5001                           name += "_int";
5002                           solver2->setColName(iColumn, name);
5003                         }
5004                       }
5005                     }
5006                     if (fudgeObjective || addSlacks) {
5007                       modifiedModel = true;
5008                       if (fudgeObjective && addSlacks) {
5009                         sprintf(generalPrint, "Objective integer added with %d elements and %d Integer slacks added",
5010                           fudgeObjective, addSlacks);
5011                       } else if (fudgeObjective) {
5012                         // just objective
5013                         sprintf(generalPrint, "Objective integer added with %d elements",
5014                           fudgeObjective);
5015                         more2 &= ~1024;
5016                       } else {
5017                         // just slacks
5018                         sprintf(generalPrint, "%d Integer slacks added", addSlacks);
5019                         more2 &= ~512;
5020                       }
5021                     } else {
5022                       more2 &= ~(512 | 1024);
5023                     }
5024                     parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].setIntValue(more2);
5025                   }
5026                   if (modifiedModel) {
5027                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
5028                       << generalPrint
5029                       << CoinMessageEol;
5030                     truncateColumns = numberColumns;
5031                   }
5032                 }
5033                 babModel_->assignSolver(solver2);
5034                 babModel_->setOriginalColumns(process.originalColumns(),
5035                   truncateColumns);
5036                 babModel_->initialSolve();
5037                 babModel_->setMaximumSeconds(timeLeft - (CoinCpuTime() - time2));
5038               }
5039               // now tighten bounds
5040               if (!miplib) {
5041 #ifndef CBC_OTHER_SOLVER
5042                 OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
5043                 assert(si != NULL);
5044                 // get clp itself
5045                 ClpSimplex *modelC = si->getModelPtr();
5046                 //if (noPrinting_)
5047                 //modelC->setLogLevel(0);
5048                 if (!complicatedInteger && modelC->tightenPrimalBounds() != 0) {
5049                   sprintf(generalPrint, "Problem is infeasible!");
5050                   printGeneralMessage(model_, generalPrint);
5051                   model_.setProblemStatus(0);
5052                   model_.setSecondaryStatus(1);
5053                   // say infeasible for solution
5054                   integerStatus = 6;
5055                   delete saveSolver;
5056                   saveSolver = NULL;
5057                   // and in babModel_ if exists
5058                   if (babModel_) {
5059                     babModel_->setProblemStatus(0);
5060                     babModel_->setSecondaryStatus(1);
5061                   }
5062                   break;
5063                 }
5064                 si->resolve();
5065 #elif CBC_OTHER_SOLVER == 1
5066 #endif
5067               }
5068               if (debugValues) {
5069                 // for debug
5070                 std::string problemName;
5071                 babModel_->solver()->getStrParam(OsiProbName, problemName);
5072                 babModel_->solver()->activateRowCutDebugger(problemName.c_str());
5073                 twomirGen.probname_ = CoinStrdup(problemName.c_str());
5074                 // checking seems odd
5075                 //redsplitGen.set_given_optsol(babModel_->solver()->getRowCutDebuggerAlways()->optimalSolution(),
5076                 //                         babModel_->getNumCols());
5077               }
5078               int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue();
5079               //#ifdef COIN_HAS_ASL
5080 #ifndef JJF_ONE
5081               // If linked then see if expansion wanted
5082               {
5083                 OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver());
5084                 int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() / 10000;
5085                 if (solver3 || (options & 16) != 0) {
5086                   if (options) {
5087                     /*
5088                                           1 - force mini branch and bound
5089                                           2 - set priorities high on continuous
5090                                           4 - try adding OA cuts
5091                                           8 - try doing quadratic linearization
5092                                           16 - try expanding knapsacks
5093                                         */
5094                     if ((options & 16)) {
5095                       int numberColumns = saveCoinModel.numberColumns();
5096                       int numberRows = saveCoinModel.numberRows();
5097                       whichColumn = new int[numberColumns];
5098                       knapsackStart = new int[numberRows + 1];
5099                       knapsackRow = new int[numberRows];
5100                       numberKnapsack = 10000;
5101                       int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue();
5102                       int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue();
5103                       int logLevel = parameters_[log].intValue();
5104                       OsiSolverInterface *solver = expandKnapsack(saveCoinModel, whichColumn, knapsackStart,
5105                         knapsackRow, numberKnapsack,
5106                         storedAmpl, logLevel, extra1, extra2,
5107                         saveTightenedModel);
5108                       if (solver) {
5109 #ifndef CBC_OTHER_SOLVER
5110                         clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
5111                         assert(clpSolver);
5112                         lpSolver = clpSolver->getModelPtr();
5113 #endif
5114                         babModel_->assignSolver(solver);
5115                         testOsiOptions = 0;
5116                         // allow gomory
5117                         complicatedInteger = 0;
5118 #ifdef COIN_HAS_ASL
5119                         // Priorities already done
5120                         free(info.priorities);
5121                         info.priorities = NULL;
5122 #endif
5123                       } else {
5124                         numberKnapsack = 0;
5125                         delete[] whichColumn;
5126                         delete[] knapsackStart;
5127                         delete[] knapsackRow;
5128                         whichColumn = NULL;
5129                         knapsackStart = NULL;
5130                         knapsackRow = NULL;
5131                       }
5132                     }
5133                   }
5134                 }
5135               }
5136 #endif
5137               if (useCosts && testOsiOptions < 0) {
5138                 int numberColumns = babModel_->getNumCols();
5139                 int *sort = new int[numberColumns];
5140                 double *dsort = new double[numberColumns];
5141                 int *priority = new int[numberColumns];
5142                 const double *objective = babModel_->getObjCoefficients();
5143                 const double *lower = babModel_->getColLower();
5144                 const double *upper = babModel_->getColUpper();
5145                 const CoinPackedMatrix *matrix = babModel_->solver()->getMatrixByCol();
5146                 const int *columnLength = matrix->getVectorLengths();
5147                 int iColumn;
5148                 int n = 0;
5149                 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5150                   if (babModel_->isInteger(iColumn)) {
5151                     sort[n] = n;
5152                     if (useCosts == 1)
5153                       dsort[n++] = -fabs(objective[iColumn]);
5154                     else if (useCosts == 2)
5155                       dsort[n++] = iColumn;
5156                     else if (useCosts == 3)
5157                       dsort[n++] = upper[iColumn] - lower[iColumn];
5158                     else if (useCosts == 4)
5159                       dsort[n++] = -(upper[iColumn] - lower[iColumn]);
5160                     else if (useCosts == 5)
5161                       dsort[n++] = -columnLength[iColumn];
5162                     else if (useCosts == 6)
5163                       dsort[n++] = (columnLength[iColumn] == 1) ? -1.0 : 0.0;
5164                     else if (useCosts == 7)
5165                       dsort[n++] = (objective[iColumn]) ? -1.0 : 0.0;
5166                   }
5167                 }
5168                 CoinSort_2(dsort, dsort + n, sort);
5169                 int level = 0;
5170                 double last = -1.0e100;
5171                 for (int i = 0; i < n; i++) {
5172                   int iPut = sort[i];
5173                   if (dsort[i] != last) {
5174                     level++;
5175                     last = dsort[i];
5176                   }
5177                   priority[iPut] = level;
5178                 }
5179                 if (newPriorities) {
5180                   // get rid of
5181                   delete[] newPriorities;
5182                   newPriorities = NULL;
5183                 }
5184                 babModel_->passInPriorities(priority, false);
5185                 integersOK = true;
5186                 delete[] priority;
5187                 delete[] sort;
5188                 delete[] dsort;
5189               }
5190               // Set up heuristics
5191               doHeuristics(babModel_, ((!miplib) ? 1 : 10), parameters_,
5192                 noPrinting_, initialPumpTune);
5193               if (!miplib) {
5194                 if (parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, parameters_)].currentOptionAsInteger()) {
5195                   CbcTreeLocal localTree(babModel_, NULL, 10, 0, 0, 10000, 2000);
5196                   babModel_->passInTreeHandler(localTree);
5197                 }
5198               }
5199               if (type == CBC_PARAM_ACTION_MIPLIB) {
5200                 if (babModel_->numberStrong() == 5 && babModel_->numberBeforeTrust() == 5)
5201                   babModel_->setNumberBeforeTrust(10);
5202               }
5203               int experimentFlag = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].intValue();
5204               int strategyFlag = parameters_[whichParam(CBC_PARAM_INT_STRATEGY, parameters_)].intValue();
5205               int bothFlags = CoinMax(CoinMin(experimentFlag, 1), strategyFlag);
5206               // add cut generators if wanted
5207               int switches[30] = {};
5208               int accuracyFlag[30] = {};
5209               char doAtEnd[30] = {};
5210               int numberGenerators = 0;
5211               int translate[] = { -100, -1, -99, -98, 1, -1098, -999, 1, 1, 1, -1 };
5212               int maximumSlowPasses = parameters_[whichParam(CBC_PARAM_INT_MAX_SLOW_CUTS,
5213                                                     parameters_)]
5214                                         .intValue();
5215               if (probingAction) {
5216                 int numberColumns = babModel_->solver()->getNumCols();
5217                 if (probingAction > 7) {
5218                   probingGen.setMaxElements(numberColumns);
5219                   probingGen.setMaxElementsRoot(numberColumns);
5220                 }
5221                 probingGen.setMaxProbeRoot(CoinMin(2000, numberColumns));
5222                 probingGen.setMaxProbeRoot(123);
5223                 probingGen.setMaxProbe(123);
5224                 probingGen.setMaxLookRoot(20);
5225                 if (probingAction == 7 || probingAction == 9)
5226                   probingGen.setRowCuts(-3); // strengthening etc just at root
5227                 if (probingAction == 8 || probingAction == 9) {
5228                   // Number of unsatisfied variables to look at
5229                   probingGen.setMaxProbeRoot(numberColumns);
5230                   probingGen.setMaxProbe(numberColumns);
5231                   // How far to follow the consequences
5232                   probingGen.setMaxLook(50);
5233                   probingGen.setMaxLookRoot(50);
5234                 }
5235                 if (probingAction == 10) {
5236                   probingGen.setMaxPassRoot(2);
5237                   probingGen.setMaxProbeRoot(numberColumns);
5238                   probingGen.setMaxLookRoot(numberColumns);
5239                 }
5240                 // If 5 then force on
5241                 int iAction = translate[probingAction];
5242                 if (probingAction == 5)
5243                   iAction = 1;
5244                 babModel_->addCutGenerator(&probingGen, iAction, "Probing");
5245                 accuracyFlag[numberGenerators] = 5;
5246                 switches[numberGenerators++] = 0;
5247               }
5248               if (gomoryAction && (complicatedInteger != 1 || (gomoryAction == 1 || gomoryAction >= 4))) {
5249                 // try larger limit
5250                 int numberColumns = babModel_->getNumCols();
5251                 if (gomoryAction == 7) {
5252                   gomoryAction = 4;
5253                   gomoryGen.setLimitAtRoot(numberColumns);
5254                   gomoryGen.setLimit(numberColumns);
5255                 } else if (gomoryAction == 8) {
5256                   gomoryAction = 3;
5257                   gomoryGen.setLimitAtRoot(numberColumns);
5258                   gomoryGen.setLimit(200);
5259                 } else if (numberColumns > 5000) {
5260                   //#define MORE_CUTS2
5261 #ifdef MORE_CUTS2
5262                   // try larger limit
5263                   gomoryGen.setLimitAtRoot(numberColumns);
5264                   gomoryGen.setLimit(200);
5265 #else
5266                   gomoryGen.setLimitAtRoot(2000);
5267                   //gomoryGen.setLimit(200);
5268 #endif
5269                 } else {
5270 #ifdef MORE_CUTS2
5271                   // try larger limit
5272                   gomoryGen.setLimitAtRoot(numberColumns);
5273                   gomoryGen.setLimit(200);
5274 #endif
5275                 }
5276                 int cutLength = parameters_[whichParam(CBC_PARAM_INT_CUTLENGTH, parameters_)].intValue();
5277                 if (cutLength != -1) {
5278                   gomoryGen.setLimitAtRoot(cutLength);
5279                   if (cutLength < 10000000) {
5280                     gomoryGen.setLimit(cutLength);
5281                   } else {
5282                     gomoryGen.setLimit(cutLength % 10000000);
5283                   }
5284                 }
5285                 int laGomory = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, parameters_)].currentOptionAsInteger();
5286                 int gType = translate[gomoryAction];
5287                 if (!laGomory) {
5288                   // Normal
5289                   babModel_->addCutGenerator(&gomoryGen, translate[gomoryAction], "Gomory");
5290                   accuracyFlag[numberGenerators] = 3;
5291                   switches[numberGenerators++] = 0;
5292                 } else {
5293                   laGomory--;
5294                   int type = (laGomory % 3) + 1;
5295                   int when = laGomory / 3;
5296                   char atEnd = (when < 2) ? 1 : 0;
5297                   int gomoryTypeMajor = 10;
5298                   if (when != 3) {
5299                     // normal as well
5300                     babModel_->addCutGenerator(&gomoryGen, gType, "Gomory");
5301                     accuracyFlag[numberGenerators] = 3;
5302                     switches[numberGenerators++] = 0;
5303                     if (when == 2) {
5304                       gomoryTypeMajor = 20;
5305                     } else if (when == 4) {
5306                       gomoryTypeMajor = 20;
5307 		      when = 0;
5308 		    }
5309                   } else {
5310                     when--; // so on
5311                     gomoryTypeMajor = 20;
5312                   }
5313                   if (!when)
5314                     gType = -99; // root
5315                   gomoryGen.passInOriginalSolver(babModel_->solver());
5316                   if ((type & 1) != 0) {
5317                     // clean
5318                     gomoryGen.setGomoryType(gomoryTypeMajor + 1);
5319                     babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL1");
5320                     accuracyFlag[numberGenerators] = 3;
5321                     doAtEnd[numberGenerators] = atEnd;
5322                     if (atEnd) {
5323                       babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999);
5324                       babModel_->cutGenerator(numberGenerators)->setHowOften(1);
5325                     }
5326                     switches[numberGenerators++] = 0;
5327                   }
5328                   if ((type & 2) != 0) {
5329                     // simple
5330                     gomoryGen.setGomoryType(gomoryTypeMajor + 2);
5331                     babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL2");
5332                     accuracyFlag[numberGenerators] = 3;
5333                     doAtEnd[numberGenerators] = atEnd;
5334                     if (atEnd) {
5335                       babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999);
5336                       babModel_->cutGenerator(numberGenerators)->setHowOften(1);
5337                     }
5338                     switches[numberGenerators++] = 0;
5339                   }
5340                 }
5341               }
5342 #ifdef CLIQUE_ANALYSIS
5343               if (miplib && !storedAmpl.sizeRowCuts()) {
5344                 printf("looking at probing\n");
5345                 babModel_->addCutGenerator(&storedAmpl, 1, "Stored");
5346               }
5347 #endif
5348               if (knapsackAction) {
5349                 babModel_->addCutGenerator(&knapsackGen, translate[knapsackAction], "Knapsack");
5350                 accuracyFlag[numberGenerators] = 1;
5351                 switches[numberGenerators++] = -2;
5352               }
5353               if (redsplitAction && !complicatedInteger) {
5354                 babModel_->addCutGenerator(&redsplitGen, translate[redsplitAction], "Reduce-and-split");
5355                 accuracyFlag[numberGenerators] = 5;
5356                 // slow ? - just do a few times
5357                 if (redsplitAction != 1) {
5358                   babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses);
5359                   babModel_->cutGenerator(numberGenerators)->setHowOften(10);
5360                 }
5361                 switches[numberGenerators++] = 1;
5362               }
5363               if (redsplit2Action && !complicatedInteger) {
5364                 int maxLength = 256;
5365                 if (redsplit2Action > 2) {
5366                   redsplit2Action -= 2;
5367                   maxLength = COIN_INT_MAX;
5368                 }
5369                 CglRedSplit2Param &parameters = redsplit2Gen.getParam();
5370                 parameters.setMaxNonzeroesTab(maxLength);
5371                 babModel_->addCutGenerator(&redsplit2Gen, translate[redsplit2Action], "Reduce-and-split(2)");
5372                 accuracyFlag[numberGenerators] = 5;
5373                 // slow ? - just do a few times
5374                 if (redsplit2Action != 1) {
5375                   babModel_->cutGenerator(numberGenerators)->setHowOften(maximumSlowPasses);
5376                   babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses);
5377                   babModel_->cutGenerator(numberGenerators)->setHowOften(5);
5378                 }
5379 
5380                 switches[numberGenerators++] = 1;
5381               }
5382               if (GMIAction && !complicatedInteger) {
5383                 if (GMIAction > 5) {
5384                   // long
5385                   GMIAction -= 5;
5386                   CglGMIParam &parameters = GMIGen.getParam();
5387                   parameters.setMaxSupportRel(1.0);
5388                 }
5389                 babModel_->addCutGenerator(&GMIGen, translate[GMIAction], "Gomory(2)");
5390                 if (GMIAction == 5) {
5391                   // just at end and root
5392                   GMIAction = 2;
5393                   doAtEnd[numberGenerators] = 1;
5394                   babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999);
5395                   babModel_->cutGenerator(numberGenerators)->setHowOften(1);
5396                 }
5397                 accuracyFlag[numberGenerators] = 5;
5398                 switches[numberGenerators++] = 0;
5399               }
5400               if (cliqueAction) {
5401                 babModel_->addCutGenerator(&cliqueGen, translate[cliqueAction], "Clique");
5402                 accuracyFlag[numberGenerators] = 0;
5403                 switches[numberGenerators++] = 0;
5404               }
5405               if (mixedAction) {
5406                 babModel_->addCutGenerator(&mixedGen, translate[mixedAction], "MixedIntegerRounding2");
5407                 accuracyFlag[numberGenerators] = 2;
5408                 switches[numberGenerators++] = 0;
5409               }
5410               if (flowAction) {
5411                 babModel_->addCutGenerator(&flowGen, translate[flowAction], "FlowCover");
5412                 accuracyFlag[numberGenerators] = 2;
5413                 switches[numberGenerators++] = 0;
5414               }
5415               if (twomirAction && (complicatedInteger != 1 || (twomirAction == 1 || twomirAction >= 4))) {
5416                 // try larger limit
5417                 int numberColumns = babModel_->getNumCols();
5418                 if (twomirAction == 7) {
5419                   twomirAction = 4;
5420                   twomirGen.setMaxElements(numberColumns);
5421                 } else if (numberColumns > 5000 && twomirAction == 4) {
5422                   twomirGen.setMaxElements(2000);
5423                 }
5424                 int laTwomir = parameters_[whichParam(CBC_PARAM_STR_LATWOMIRCUTS, parameters_)].currentOptionAsInteger();
5425                 int twomirType = translate[twomirAction];
5426                 if (!laTwomir) {
5427                   // Normal
5428                   babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts");
5429                   accuracyFlag[numberGenerators] = 4;
5430                   switches[numberGenerators++] = 1;
5431                 } else {
5432                   laTwomir--;
5433                   int type = (laTwomir % 3) + 1;
5434                   int when = laTwomir / 3;
5435                   char atEnd = (when < 2) ? 1 : 0;
5436                   int twomirTypeMajor = 10;
5437                   if (when < 3) {
5438                     // normal as well
5439                     babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts");
5440                     accuracyFlag[numberGenerators] = 4;
5441                     switches[numberGenerators++] = 1;
5442                     if (when == 2)
5443                       twomirTypeMajor = 10;
5444                   } else {
5445                     when--; // so on
5446                     twomirTypeMajor = 20;
5447                   }
5448                   if (!when)
5449                     twomirType = -99; // root
5450                   twomirGen.passInOriginalSolver(babModel_->solver());
5451                   if ((type & 1) != 0) {
5452                     // clean
5453                     twomirGen.setTwomirType(twomirTypeMajor + 1);
5454                     babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL1");
5455                     accuracyFlag[numberGenerators] = 4;
5456                     doAtEnd[numberGenerators] = atEnd;
5457                     switches[numberGenerators++] = atEnd ? 0 : 1;
5458                   }
5459                   if ((type & 2) != 0) {
5460                     // simple
5461                     twomirGen.setTwomirType(twomirTypeMajor + 2);
5462                     babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL2");
5463                     accuracyFlag[numberGenerators] = 4;
5464                     doAtEnd[numberGenerators] = atEnd;
5465                     switches[numberGenerators++] = atEnd ? 0 : 1;
5466                   }
5467                 }
5468               }
5469 #ifndef DEBUG_MALLOC
5470               if (landpAction) {
5471                 babModel_->addCutGenerator(&landpGen, translate[landpAction], "LiftAndProject");
5472                 accuracyFlag[numberGenerators] = 5;
5473                 // slow ? - just do a few times
5474                 if (landpAction != 1) {
5475                   babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses);
5476                   babModel_->cutGenerator(numberGenerators)->setHowOften(10);
5477                 }
5478                 switches[numberGenerators++] = 1;
5479               }
5480 #endif
5481               if (residualCapacityAction) {
5482                 babModel_->addCutGenerator(&residualCapacityGen, translate[residualCapacityAction], "ResidualCapacity");
5483                 accuracyFlag[numberGenerators] = 5;
5484                 switches[numberGenerators++] = 1;
5485               }
5486               if (zerohalfAction) {
5487                 if (zerohalfAction > 4) {
5488                   //zerohalfAction -=4;
5489                   zerohalfGen.setFlags(1);
5490                 }
5491                 babModel_->addCutGenerator(&zerohalfGen, translate[zerohalfAction], "ZeroHalf");
5492                 accuracyFlag[numberGenerators] = 5;
5493                 babModel_->cutGenerator(numberGenerators)->setNeedsRefresh(true);
5494                 switches[numberGenerators++] = 2;
5495               }
5496               if (dominatedCuts)
5497                 babModel_->setSpecialOptions(babModel_->specialOptions() | 64);
5498               // Say we want timings
5499               numberGenerators = babModel_->numberCutGenerators();
5500               int iGenerator;
5501               int cutDepth = parameters_[whichParam(CBC_PARAM_INT_CUTDEPTH, parameters_)].intValue();
5502               for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
5503                 CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator);
5504                 int howOften = generator->howOften();
5505                 if (howOften == -98 || howOften == -99 || generator->maximumTries() > 0)
5506                   generator->setSwitchOffIfLessThan(switches[iGenerator]);
5507                 // Use if any at root as more likely later and fairly cheap
5508                 //if (switches[iGenerator]==-2)
5509                 //generator->setWhetherToUse(true);
5510                 generator->setInaccuracy(accuracyFlag[iGenerator]);
5511                 if (doAtEnd[iGenerator]) {
5512                   generator->setWhetherCallAtEnd(true);
5513                   //generator->setMustCallAgain(true);
5514                 }
5515                 generator->setTiming(true);
5516                 if (cutDepth >= 0)
5517                   generator->setWhatDepth(cutDepth);
5518               }
5519               // Could tune more
5520               if (!miplib) {
5521                 double minimumDrop = fabs(babModel_->solver()->getObjValue()) * 1.0e-5 + 1.0e-5;
5522                 babModel_->setMinimumDrop(CoinMin(5.0e-2, minimumDrop));
5523                 if (cutPass == -1234567) {
5524                   if (babModel_->getNumCols() < 500)
5525                     babModel_->setMaximumCutPassesAtRoot(-100); // always do 100 if possible
5526                   else if (babModel_->getNumCols() < 5000)
5527                     babModel_->setMaximumCutPassesAtRoot(100); // use minimum drop
5528                   else
5529                     babModel_->setMaximumCutPassesAtRoot(50);
5530                 } else {
5531                   babModel_->setMaximumCutPassesAtRoot(cutPass);
5532                 }
5533                 if (cutPassInTree == -1234567)
5534                   babModel_->setMaximumCutPasses(4);
5535                 else
5536                   babModel_->setMaximumCutPasses(cutPassInTree);
5537               } else if (cutPass != -1234567) {
5538                 babModel_->setMaximumCutPassesAtRoot(cutPass);
5539               }
5540               // Do more strong branching if small
5541               //if (babModel_->getNumCols()<5000)
5542               //babModel_->setNumberStrong(20);
5543               // Switch off strong branching if wanted
5544               //if (babModel_->getNumCols()>10*babModel_->getNumRows())
5545               //babModel_->setNumberStrong(0);
5546               if (!noPrinting_) {
5547                 int iLevel = parameters_[log].intValue();
5548                 if (iLevel < 0) {
5549                   if (iLevel > -10) {
5550                     babModel_->setPrintingMode(1);
5551                   } else {
5552                     babModel_->setPrintingMode(2);
5553                     iLevel += 10;
5554                     parameters_[log].setIntValue(iLevel);
5555                   }
5556                   iLevel = -iLevel;
5557                 }
5558                 babModel_->messageHandler()->setLogLevel(iLevel);
5559                 if (babModel_->getNumCols() > 2000 || babModel_->getNumRows() > 1500 || babModel_->messageHandler()->logLevel() > 1)
5560                   babModel_->setPrintFrequency(100);
5561               }
5562 
5563               babModel_->solver()->setIntParam(OsiMaxNumIterationHotStart,
5564                 parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].intValue());
5565 #ifndef CBC_OTHER_SOLVER
5566               OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
5567               // go faster stripes
5568               if ((osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500)) {
5569                 osiclp->setupForRepeatedUse(2, parameters_[slog].intValue());
5570                 if (bothFlags >= 1) {
5571                   ClpSimplex *lp = osiclp->getModelPtr();
5572                   int specialOptions = lp->specialOptions();
5573                   lp->setSpecialOptions(specialOptions | (2048 + 4096));
5574                 }
5575               } else {
5576                 osiclp->setupForRepeatedUse(0, parameters_[slog].intValue());
5577               }
5578               if (bothFlags >= 2) {
5579                 ClpSimplex *lp = osiclp->getModelPtr();
5580                 int specialOptions = lp->specialOptions();
5581                 lp->setSpecialOptions(specialOptions | (2048 + 4096));
5582               }
5583               double increment = babModel_->getCutoffIncrement();
5584               ;
5585               int *changed = NULL;
5586               if (!miplib && increment == normalIncrement)
5587                 changed = analyze(osiclp, numberChanged, increment, false, generalMessageHandler, noPrinting);
5588 #elif CBC_OTHER_SOLVER == 1
5589               double increment = babModel_->getCutoffIncrement();
5590               ;
5591 #endif
5592               if (debugValues) {
5593                 int numberColumns = babModel_->solver()->getNumCols();
5594                 if (numberDebugValues == numberColumns) {
5595                   // for debug
5596                   babModel_->solver()->activateRowCutDebugger(debugValues);
5597                 } else {
5598                   int numberOriginalColumns = process.originalModel()->getNumCols();
5599                   if (numberDebugValues <= numberOriginalColumns) {
5600                     const int *originalColumns = process.originalColumns();
5601                     double *newValues = new double[numberColumns];
5602                     // in case preprocess added columns!
5603                     // need to find values
5604                     OsiSolverInterface *siCopy = babModel_->solver()->clone();
5605                     for (int i = 0; i < numberColumns; i++) {
5606                       int jColumn = originalColumns[i];
5607                       if (jColumn < numberDebugValues && siCopy->isInteger(i)) {
5608                         // integer variable
5609                         double soln = floor(debugValues[jColumn] + 0.5);
5610                         // Set bounds to fix variable to its solution
5611                         siCopy->setColUpper(i, soln);
5612                         siCopy->setColLower(i, soln);
5613                       }
5614                     }
5615                     // All integers have been fixed at optimal value.
5616                     // Now solve to get continuous values
5617                     siCopy->setHintParam(OsiDoScale, false);
5618                     siCopy->initialSolve();
5619                     if (siCopy->isProvenOptimal()) {
5620                       memcpy(newValues, siCopy->getColSolution(),
5621                         numberColumns * sizeof(double));
5622                     } else {
5623                       printf("BAD debug file\n");
5624                       siCopy->writeMps("Bad");
5625                       exit(22);
5626                     }
5627                     delete siCopy;
5628                     // for debug
5629                     babModel_->solver()->activateRowCutDebugger(newValues);
5630                     delete[] newValues;
5631                   } else {
5632                     printf("debug file has incorrect number of columns\n");
5633                   }
5634                 }
5635               }
5636               babModel_->setCutoffIncrement(CoinMax(babModel_->getCutoffIncrement(), increment));
5637               // Turn this off if you get problems
5638               // Used to be automatically set
5639               int mipOptions = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() % 10000;
5640               if (mipOptions != (1057) && mipOptions != 1025) {
5641                 sprintf(generalPrint, "mip options %d", mipOptions);
5642                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
5643                   << generalPrint
5644                   << CoinMessageEol;
5645               }
5646 #ifndef CBC_OTHER_SOLVER
5647               osiclp->setSpecialOptions(mipOptions);
5648 #elif CBC_OTHER_SOLVER == 1
5649 #endif
5650               // probably faster to use a basis to get integer solutions
5651               babModel_->setSpecialOptions(babModel_->specialOptions() | 2);
5652               currentBranchModel = babModel_;
5653               //OsiSolverInterface * strengthenedModel=NULL;
5654               if (type == CBC_PARAM_ACTION_BAB || type == CBC_PARAM_ACTION_MIPLIB) {
5655                 if (strategyFlag == 1) {
5656                   // try reduced model
5657                   babModel_->setSpecialOptions(babModel_->specialOptions() | 512);
5658                 }
5659                 if (experimentFlag >= 5 || strategyFlag == 2) {
5660                   // try reduced model at root
5661                   babModel_->setSpecialOptions(babModel_->specialOptions() | 32768);
5662                 }
5663                 {
5664                   int depthMiniBab = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, parameters_)].intValue();
5665                   if (depthMiniBab != -1)
5666                     babModel_->setFastNodeDepth(depthMiniBab);
5667                 }
5668                 int extra4 = parameters_[whichParam(CBC_PARAM_INT_EXTRA4, parameters_)].intValue();
5669                 if (extra4 >= 0) {
5670                   int strategy = extra4 % 10;
5671                   extra4 /= 10;
5672                   int method = extra4 % 100;
5673                   extra4 /= 100;
5674                   extra4 = strategy + method * 8 + extra4 * 1024;
5675                   babModel_->setMoreSpecialOptions(extra4);
5676                 }
5677                 int moreMipOptions = parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters_)].intValue();
5678                 if (moreMipOptions >= 0) {
5679                   sprintf(generalPrint, "more mip options %d", moreMipOptions);
5680                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
5681                     << generalPrint
5682                     << CoinMessageEol;
5683 #if 1
5684                   // some options may have been set already
5685                   // e.g. use elapsed time
5686                   babModel_->setMoreSpecialOptions(moreMipOptions | babModel_->moreSpecialOptions());
5687 #else
5688                   OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
5689                   if (moreMipOptions == 10000) {
5690                     // test memory saving
5691                     moreMipOptions -= 10000;
5692                     ClpSimplex *lpSolver = osiclp->getModelPtr();
5693                     lpSolver->setPersistenceFlag(1);
5694                     // switch off row copy if few rows
5695                     if (lpSolver->numberRows() < 150)
5696                       lpSolver->setSpecialOptions(lpSolver->specialOptions() | 256);
5697                   }
5698                   if (moreMipOptions < 10000 && moreMipOptions) {
5699                     if (((moreMipOptions + 1) % 1000000) != 0)
5700                       babModel_->setSearchStrategy(moreMipOptions % 1000000);
5701                   } else if (moreMipOptions < 100000) {
5702                     // try reduced model
5703                     babModel_->setSpecialOptions(babModel_->specialOptions() | 512);
5704                   }
5705                   // go faster stripes
5706                   if (moreMipOptions >= 999999) {
5707                     if (osiclp) {
5708                       int save = osiclp->specialOptions();
5709                       osiclp->setupForRepeatedUse(2, 0);
5710                       osiclp->setSpecialOptions(save | osiclp->specialOptions());
5711                     }
5712                   }
5713 #endif
5714                 }
5715               }
5716               {
5717                 int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue();
5718                 if (extra1 != -1) {
5719                   if (extra1 < 0) {
5720                     if (extra1 == -7777)
5721                       extra1 = -1;
5722                     else if (extra1 == -8888)
5723                       extra1 = 1;
5724                     babModel_->setWhenCuts(-extra1);
5725                   } else if (extra1 < 19000) {
5726                     babModel_->setSearchStrategy(extra1);
5727                     printf("XXXXX searchStrategy %d\n", extra1);
5728                   } else {
5729                     int n = extra1 - 20000;
5730                     if (!n)
5731                       n--;
5732                     babModel_->setNumberAnalyzeIterations(n);
5733                     printf("XXXXX analyze %d\n", extra1);
5734                   }
5735                 } else if (bothFlags >= 1) {
5736                   babModel_->setWhenCuts(999998);
5737                 }
5738               }
5739               if (type == CBC_PARAM_ACTION_BAB) {
5740 #ifdef COIN_HAS_ASL
5741                 if (statusUserFunction_[0]) {
5742                   priorities = info.priorities;
5743                   branchDirection = info.branchDirection;
5744                   pseudoDown = info.pseudoDown;
5745                   pseudoUp = info.pseudoUp;
5746                   solutionIn = info.primalSolution;
5747                   prioritiesIn = info.priorities;
5748                   if (info.numberSos && doSOS) {
5749                     // SOS
5750                     numberSOS = info.numberSos;
5751                     sosStart = info.sosStart;
5752                     sosIndices = info.sosIndices;
5753                     sosType = info.sosType;
5754                     sosReference = info.sosReference;
5755                     sosPriority = info.sosPriority;
5756                   }
5757                 }
5758 #endif
5759                 const int *originalColumns = preProcess ? process.originalColumns() : NULL;
5760                 if (model.getMIPStart().size())
5761                   mipStart = model.getMIPStart();
5762                 if (mipStart.size() && !mipStartBefore.size() && babModel_->getNumCols()) {
5763                   std::vector< std::string > colNames;
5764                   if (preProcess) {
5765                     /* translating mipstart solution */
5766                     std::map< std::string, double > mipStartV;
5767                     for (size_t i = 0; (i < mipStart.size()); ++i)
5768                       mipStartV[mipStart[i].first] = mipStart[i].second;
5769 
5770                     std::vector< std::pair< std::string, double > > mipStart2;
5771                     for (int i = 0; (i < babModel_->solver()->getNumCols()); ++i) {
5772                       int iColumn = babModel_->originalColumns()[i];
5773                       if (iColumn >= 0) {
5774                         std::string cname = model_.solver()->getColName(iColumn);
5775                         colNames.push_back(cname);
5776                         babModel_->solver()->setColName(i, cname);
5777                         std::map< std::string, double >::const_iterator msIt = mipStartV.find(cname);
5778                         if (msIt != mipStartV.end())
5779                           mipStart2.push_back(std::pair< std::string, double >(cname, msIt->second));
5780                       } else {
5781                         // created variable
5782                         char newName[15];
5783                         sprintf(newName, "C%7.7d", i);
5784                         colNames.push_back(newName);
5785                       }
5786                     }
5787                     mipStart = mipStart2;
5788                   } else {
5789                     for (int i = 0; (i < babModel_->solver()->getNumCols()); ++i)
5790                       colNames.push_back(model_.solver()->getColName(i));
5791                   }
5792                   //printf("--- %s %d\n", babModel_->solver()->getColName(0).c_str(), babModel_->solver()->getColNames().size() );
5793                   //printf("-- SIZES of models %d %d %d\n", model_.getNumCols(),  babModel_->solver()->getNumCols(), babModel_->solver()->getColNames().size() );
5794                   std::vector< double > x(babModel_->getNumCols(), 0.0);
5795                   double obj;
5796                   babModel_->findIntegers(true);
5797                   int status = computeCompleteSolution(babModel_, colNames, mipStart, &x[0], obj);
5798                   if (!status) {
5799                     // need to check more babModel_->setBestSolution( &x[0], static_cast<int>(x.size()), obj, false );
5800                     OsiBabSolver dummy;
5801                     babModel_->passInSolverCharacteristics(&dummy);
5802                     babModel_->createContinuousSolver();
5803                     babModel_->setBestSolution(CBC_ROUNDING,
5804                       obj, &x[0], 1);
5805                     babModel_->clearContinuousSolver();
5806                     babModel_->passInSolverCharacteristics(NULL);
5807                     if (useSolution == 0)
5808                       babModel_->setHotstartSolution(&x[0]);
5809                   }
5810                 }
5811 
5812                 if (solutionIn && useSolution >= 0) {
5813                   if (!prioritiesIn) {
5814                     int n;
5815                     if (preProcess) {
5816                       int numberColumns = babModel_->getNumCols();
5817                       // extend arrays in case SOS
5818                       n = originalColumns[numberColumns - 1] + 1;
5819                     } else {
5820                       n = babModel_->getNumCols();
5821                     }
5822                     prioritiesIn = reinterpret_cast< int * >(malloc(n * sizeof(int)));
5823                     for (int i = 0; i < n; i++)
5824                       prioritiesIn[i] = 100;
5825                   }
5826                   if (preProcess) {
5827                     int numberColumns = babModel_->getNumCols();
5828                     // extend arrays in case SOS
5829                     int n = originalColumns[numberColumns - 1] + 1;
5830                     int nSmaller = CoinMin(n, numberOriginalColumns);
5831                     double *solutionIn2 = new double[n];
5832                     int *prioritiesIn2 = new int[n];
5833                     int i;
5834                     for (i = 0; i < nSmaller; i++) {
5835                       solutionIn2[i] = solutionIn[i];
5836                       prioritiesIn2[i] = prioritiesIn[i];
5837                     }
5838                     for (; i < n; i++) {
5839                       solutionIn2[i] = 0.0;
5840                       prioritiesIn2[i] = 1000000;
5841                     }
5842 #ifndef NDEBUG
5843                     int iLast = -1;
5844 #endif
5845                     for (i = 0; i < numberColumns; i++) {
5846                       int iColumn = originalColumns[i];
5847 #ifndef NDEBUG
5848                       assert(iColumn > iLast);
5849                       iLast = iColumn;
5850 #endif
5851                       solutionIn2[i] = solutionIn2[iColumn];
5852                       if (prioritiesIn)
5853                         prioritiesIn2[i] = prioritiesIn2[iColumn];
5854                     }
5855                     if (useSolution)
5856                       babModel_->setHotstartSolution(solutionIn2, prioritiesIn2);
5857                     else
5858                       babModel_->setBestSolution(solutionIn2, numberColumns,
5859                         COIN_DBL_MAX, true);
5860                     delete[] solutionIn2;
5861                     delete[] prioritiesIn2;
5862                   } else {
5863                     if (useSolution)
5864                       babModel_->setHotstartSolution(solutionIn, prioritiesIn);
5865                     else
5866                       babModel_->setBestSolution(solutionIn, babModel_->getNumCols(),
5867                         COIN_DBL_MAX, true);
5868                   }
5869                 }
5870                 OsiSolverInterface *testOsiSolver = (testOsiOptions >= 0) ? babModel_->solver() : NULL;
5871                 if (!testOsiSolver) {
5872                   // *************************************************************
5873                   // CbcObjects
5874                   if (preProcess && (process.numberSOS() || babModel_->numberObjects())) {
5875                     int numberSOS = process.numberSOS();
5876                     int numberIntegers = babModel_->numberIntegers();
5877                     /* model may not have created objects
5878                                            If none then create
5879                                         */
5880                     if (!numberIntegers || !babModel_->numberObjects()) {
5881                       int type = (pseudoUp) ? 1 : 0;
5882                       babModel_->findIntegers(true, type);
5883                       numberIntegers = babModel_->numberIntegers();
5884                       integersOK = true;
5885                     }
5886                     OsiObject **oldObjects = babModel_->objects();
5887                     // Do sets and priorities
5888                     OsiObject **objects = new OsiObject *[numberSOS];
5889                     // set old objects to have low priority
5890                     int numberOldObjects = babModel_->numberObjects();
5891                     int numberColumns = babModel_->getNumCols();
5892                     // backward pointer to new variables
5893                     // extend arrays in case SOS
5894                     assert(originalColumns);
5895                     int n = CoinMin(truncateColumns, numberColumns);
5896                     // allow for empty problem
5897                     n = (n) ? originalColumns[n - 1] + 1 : 0;
5898                     n = CoinMax(n, CoinMax(numberColumns, numberOriginalColumns));
5899                     int *newColumn = new int[n];
5900                     int i;
5901                     for (i = 0; i < numberOriginalColumns; i++)
5902                       newColumn[i] = -1;
5903                     for (i = 0; i < CoinMin(truncateColumns, numberColumns); i++)
5904                       newColumn[originalColumns[i]] = i;
5905                     if (!integersOK) {
5906                       // Change column numbers etc
5907                       int n = 0;
5908                       for (int iObj = 0; iObj < numberOldObjects; iObj++) {
5909                         int iColumn = oldObjects[iObj]->columnNumber();
5910                         if (iColumn < 0 || iColumn >= numberOriginalColumns) {
5911                           oldObjects[n++] = oldObjects[iObj];
5912                         } else {
5913                           iColumn = newColumn[iColumn];
5914                           if (iColumn >= 0) {
5915                             CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(oldObjects[iObj]);
5916                             if (obj) {
5917                               obj->setColumnNumber(iColumn);
5918                             } else {
5919                               // only other case allowed is lotsizing
5920                               CbcLotsize *obj2 = dynamic_cast< CbcLotsize * >(oldObjects[iObj]);
5921                               assert(obj2);
5922                               obj2->setModelSequence(iColumn);
5923                             }
5924                             oldObjects[n++] = oldObjects[iObj];
5925                           } else {
5926                             delete oldObjects[iObj];
5927                           }
5928                         }
5929                       }
5930                       babModel_->setNumberObjects(n);
5931                       numberOldObjects = n;
5932                       babModel_->zapIntegerInformation();
5933                     }
5934                     int nMissing = 0;
5935                     for (int iObj = 0; iObj < numberOldObjects; iObj++) {
5936                       if (process.numberSOS())
5937                         oldObjects[iObj]->setPriority(numberColumns + 1);
5938                       int iColumn = oldObjects[iObj]->columnNumber();
5939                       if (iColumn < 0 || iColumn >= numberOriginalColumns) {
5940                         if (redoSOS) { // now done earlier??
5941                           CbcSOS *obj = dynamic_cast< CbcSOS * >(oldObjects[iObj]);
5942                           if (obj) {
5943                             int n = obj->numberMembers();
5944                             int *which = obj->mutableMembers();
5945                             double *weights = obj->mutableWeights();
5946                             int nn = 0;
5947                             for (i = 0; i < n; i++) {
5948                               int iColumn = which[i];
5949                               int jColumn = newColumn[iColumn];
5950                               if (jColumn >= 0) {
5951                                 which[nn] = jColumn;
5952                                 weights[nn++] = weights[i];
5953                               } else {
5954                                 nMissing++;
5955                               }
5956                             }
5957                             obj->setNumberMembers(nn);
5958                           }
5959                         }
5960                         continue;
5961                       }
5962                       if (originalColumns)
5963                         iColumn = originalColumns[iColumn];
5964                       if (branchDirection) {
5965                         CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(oldObjects[iObj]);
5966                         if (obj) {
5967                           obj->setPreferredWay(branchDirection[iColumn]);
5968                         } else {
5969                           CbcObject *obj = dynamic_cast< CbcObject * >(oldObjects[iObj]);
5970                           assert(obj);
5971                           obj->setPreferredWay(branchDirection[iColumn]);
5972                         }
5973                       }
5974                       if (pseudoUp) {
5975                         CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(oldObjects[iObj]);
5976                         assert(obj1a);
5977                         if (pseudoDown[iColumn] > 0.0)
5978                           obj1a->setDownPseudoCost(pseudoDown[iColumn]);
5979                         if (pseudoUp[iColumn] > 0.0)
5980                           obj1a->setUpPseudoCost(pseudoUp[iColumn]);
5981                       }
5982                     }
5983                     if (nMissing) {
5984 #ifndef DO_LESS_PROHIBITED
5985                       sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing);
5986 #else
5987                       sprintf(generalPrint, "%d SOS variables eliminated by pre processing", nMissing);
5988 #endif
5989                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
5990                         << generalPrint
5991                         << CoinMessageEol;
5992                     }
5993                     delete[] newColumn;
5994                     const int *starts = process.startSOS();
5995                     const int *which = process.whichSOS();
5996                     const int *type = process.typeSOS();
5997                     const double *weight = process.weightSOS();
5998                     int iSOS;
5999                     for (iSOS = 0; iSOS < numberSOS; iSOS++) {
6000                       int iStart = starts[iSOS];
6001                       int n = starts[iSOS + 1] - iStart;
6002                       //#define MAKE_SOS_CLIQUES
6003 #ifndef MAKE_SOS_CLIQUES
6004                       objects[iSOS] = new CbcSOS(babModel_, n, which + iStart, weight + iStart,
6005 						 iSOS, type[iSOS]);
6006 #else
6007                       objects[iSOS] = new CbcClique(babModel_, 1, n, which + iStart,
6008                         NULL, -iSOS - 1);
6009 #endif
6010                       // branch on long sets first
6011                       objects[iSOS]->setPriority(numberColumns - n);
6012                     }
6013                     if (numberSOS)
6014                       babModel_->addObjects(numberSOS, objects);
6015                     for (iSOS = 0; iSOS < numberSOS; iSOS++)
6016                       delete objects[iSOS];
6017                     delete[] objects;
6018                   } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) {
6019                     // do anyway for priorities etc
6020                     int numberIntegers = babModel_->numberIntegers();
6021                     /* model may not have created objects
6022                                            If none then create
6023                                         */
6024                     if (!numberIntegers || !babModel_->numberObjects()) {
6025                       int type = (pseudoUp) ? 1 : 0;
6026                       babModel_->findIntegers(true, type);
6027                     }
6028                     if (numberSOS) {
6029                       // Do sets and priorities
6030                       OsiObject **objects = new OsiObject *[numberSOS];
6031                       int iSOS;
6032                       if (originalColumns) {
6033                         // redo sequence numbers
6034                         int numberColumns = babModel_->getNumCols();
6035                         int nOld = originalColumns[numberColumns - 1] + 1;
6036                         int *back = new int[nOld];
6037                         int i;
6038                         for (i = 0; i < nOld; i++)
6039                           back[i] = -1;
6040                         for (i = 0; i < numberColumns; i++)
6041                           back[originalColumns[i]] = i;
6042                         // Really need better checks
6043                         int nMissing = 0;
6044 #ifndef DO_LESS_PROHIBITED
6045                         int n = sosStart[numberSOS];
6046                         for (i = 0; i < n; i++) {
6047                           int iColumn = sosIndices[i];
6048                           int jColumn = back[iColumn];
6049                           if (jColumn >= 0)
6050                             sosIndices[i] = jColumn;
6051                           else
6052                             nMissing++;
6053                         }
6054 #else
6055                         int startSet = 0;
6056                         int iPut = 0;
6057                         for (int j = 0; j < numberSOS; j++) {
6058                           for (i = startSet; i < sosStart[j + 1]; i++) {
6059                             int iColumn = sosIndices[i];
6060                             int jColumn = back[iColumn];
6061                             if (jColumn >= 0) {
6062                               sosReference[iPut] = sosReference[i];
6063                               sosIndices[iPut++] = jColumn;
6064                             } else {
6065                               nMissing++;
6066                             }
6067                           }
6068                           startSet = sosStart[j + 1];
6069                           sosStart[j + 1] = iPut;
6070                         }
6071 #endif
6072                         delete[] back;
6073                         if (nMissing) {
6074 #ifndef DO_LESS_PROHIBITED
6075                           sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing);
6076 #else
6077                           sprintf(generalPrint, "%d SOS variables eliminated by pre processing", nMissing);
6078 #endif
6079                           generalMessageHandler->message(CLP_GENERAL, generalMessages)
6080                             << generalPrint
6081                             << CoinMessageEol;
6082                         }
6083                       }
6084                       int sosPriorityOption = parameters_[whichParam(CBC_PARAM_STR_SOSPRIORITIZE, parameters_)].currentOptionAsInteger();
6085                       if (sosPriorityOption) {
6086                         const char *msg[4] = {
6087                           "high with equal priority",
6088                           "low with equal priority",
6089                           "high but with decreasing priority",
6090                           "low and decreasing priority"
6091                         };
6092                         sprintf(generalPrint, "Setting %d SOS priorities %s", numberSOS, msg[sosPriorityOption - 1]);
6093                         generalMessageHandler->message(CLP_GENERAL, generalMessages)
6094                           << generalPrint
6095                           << CoinMessageEol;
6096                       }
6097                       for (iSOS = 0; iSOS < numberSOS; iSOS++) {
6098                         int iStart = sosStart[iSOS];
6099                         int n = sosStart[iSOS + 1] - iStart;
6100                         CbcSOS *sosObject = new CbcSOS(babModel_, n, sosIndices + iStart, sosReference + iStart,
6101                           iSOS, sosType[iSOS]);
6102                         if (sosPriority) {
6103                           sosObject->setPriority(sosPriority[iSOS]);
6104                         } else if (sosPriorityOption) {
6105                           int priority = 10;
6106                           switch (sosPriorityOption) {
6107                           case 2:
6108                             priority = 100000;
6109                             break;
6110                           case 3:
6111                             // really should check <990 sets
6112                             priority = 10 + iSOS;
6113                             break;
6114                           case 4:
6115                             priority = 100000 + iSOS;
6116                             break;
6117                           }
6118                           sosObject->setPriority(priority);
6119                         } else if (!prioritiesIn) {
6120                           sosObject->setPriority(10); // rather than 1000
6121                         }
6122                         objects[iSOS] = sosObject;
6123                       }
6124                       // delete any existing SOS objects
6125                       int numberObjects = babModel_->numberObjects();
6126                       OsiObject **oldObjects = babModel_->objects();
6127                       int nNew = 0;
6128                       for (int i = 0; i < numberObjects; i++) {
6129                         OsiObject *objThis = oldObjects[i];
6130                         CbcSOS *obj1 = dynamic_cast< CbcSOS * >(objThis);
6131                         OsiSOS *obj2 = dynamic_cast< OsiSOS * >(objThis);
6132                         if (!obj1 && !obj2) {
6133                           oldObjects[nNew++] = objThis;
6134                         } else {
6135                           delete objThis;
6136                         }
6137                       }
6138                       babModel_->setNumberObjects(nNew);
6139                       babModel_->addObjects(numberSOS, objects);
6140                       for (iSOS = 0; iSOS < numberSOS; iSOS++)
6141                         delete objects[iSOS];
6142                       delete[] objects;
6143                     }
6144                   }
6145                   OsiObject **objects = babModel_->objects();
6146                   int numberObjects = babModel_->numberObjects();
6147                   for (int iObj = 0; iObj < numberObjects; iObj++) {
6148                     // skip sos
6149                     CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]);
6150                     if (objSOS)
6151                       continue;
6152 #ifdef MAKE_SOS_CLIQUES
6153                     // skip cliques
6154                     CbcClique *objClique = dynamic_cast< CbcClique * >(objects[iObj]);
6155                     if (objClique)
6156                       continue;
6157 #endif
6158                     int iColumn = objects[iObj]->columnNumber();
6159                     assert(iColumn >= 0);
6160                     if (originalColumns)
6161                       iColumn = originalColumns[iColumn];
6162                     if (branchDirection) {
6163                       CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[iObj]);
6164                       if (obj) {
6165                         obj->setPreferredWay(branchDirection[iColumn]);
6166                       } else {
6167                         CbcObject *obj = dynamic_cast< CbcObject * >(objects[iObj]);
6168                         assert(obj);
6169                         obj->setPreferredWay(branchDirection[iColumn]);
6170                       }
6171                     }
6172                     if (priorities) {
6173                       int iPriority = priorities[iColumn];
6174                       if (iPriority > 0)
6175                         objects[iObj]->setPriority(iPriority);
6176                     }
6177                     if (pseudoUp && pseudoUp[iColumn]) {
6178                       CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(objects[iObj]);
6179                       assert(obj1a);
6180                       if (pseudoDown[iColumn] > 0.0)
6181                         obj1a->setDownPseudoCost(pseudoDown[iColumn]);
6182                       if (pseudoUp[iColumn] > 0.0)
6183                         obj1a->setUpPseudoCost(pseudoUp[iColumn]);
6184                     }
6185                   }
6186                   // *************************************************************
6187                 } else {
6188                   // *************************************************************
6189                   // OsiObjects
6190                   // Find if none
6191                   int numberIntegers = testOsiSolver->getNumIntegers();
6192                   /* model may not have created objects
6193                                        If none then create
6194                                     */
6195                   if (!numberIntegers || !testOsiSolver->numberObjects()) {
6196                     //int type = (pseudoUp) ? 1 : 0;
6197                     testOsiSolver->findIntegers(false);
6198                     numberIntegers = testOsiSolver->getNumIntegers();
6199                   }
6200                   if (preProcess && process.numberSOS()) {
6201                     int numberSOS = process.numberSOS();
6202                     OsiObject **oldObjects = testOsiSolver->objects();
6203                     // Do sets and priorities
6204                     OsiObject **objects = new OsiObject *[numberSOS];
6205                     // set old objects to have low priority
6206                     int numberOldObjects = testOsiSolver->numberObjects();
6207                     int numberColumns = testOsiSolver->getNumCols();
6208                     for (int iObj = 0; iObj < numberOldObjects; iObj++) {
6209                       oldObjects[iObj]->setPriority(numberColumns + 1);
6210                       int iColumn = oldObjects[iObj]->columnNumber();
6211                       assert(iColumn >= 0);
6212                       if (iColumn >= numberOriginalColumns)
6213                         continue;
6214                       if (originalColumns)
6215                         iColumn = originalColumns[iColumn];
6216                       if (branchDirection) {
6217                         OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(oldObjects[iObj]);
6218                         if (obj) {
6219                           obj->setPreferredWay(branchDirection[iColumn]);
6220                         } else {
6221                           OsiObject2 *obj = dynamic_cast< OsiObject2 * >(oldObjects[iObj]);
6222                           if (obj)
6223                             obj->setPreferredWay(branchDirection[iColumn]);
6224                         }
6225                       }
6226                       if (pseudoUp) {
6227                         abort();
6228                       }
6229                     }
6230                     const int *starts = process.startSOS();
6231                     const int *which = process.whichSOS();
6232                     const int *type = process.typeSOS();
6233                     const double *weight = process.weightSOS();
6234                     int iSOS;
6235                     for (iSOS = 0; iSOS < numberSOS; iSOS++) {
6236                       int iStart = starts[iSOS];
6237                       int n = starts[iSOS + 1] - iStart;
6238                       objects[iSOS] = new OsiSOS(testOsiSolver, n, which + iStart, weight + iStart,
6239                         type[iSOS]);
6240                       // branch on long sets first
6241                       objects[iSOS]->setPriority(numberColumns - n);
6242                     }
6243                     testOsiSolver->addObjects(numberSOS, objects);
6244                     for (iSOS = 0; iSOS < numberSOS; iSOS++)
6245                       delete objects[iSOS];
6246                     delete[] objects;
6247                   } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) {
6248                     if (numberSOS) {
6249                       // Do sets and priorities
6250                       OsiObject **objects = new OsiObject *[numberSOS];
6251                       int iSOS;
6252                       if (originalColumns) {
6253                         // redo sequence numbers
6254                         int numberColumns = testOsiSolver->getNumCols();
6255                         int nOld = originalColumns[numberColumns - 1] + 1;
6256                         int *back = new int[nOld];
6257                         int i;
6258                         for (i = 0; i < nOld; i++)
6259                           back[i] = -1;
6260                         for (i = 0; i < numberColumns; i++)
6261                           back[originalColumns[i]] = i;
6262                         // Really need better checks
6263                         int nMissing = 0;
6264                         int n = sosStart[numberSOS];
6265                         for (i = 0; i < n; i++) {
6266                           int iColumn = sosIndices[i];
6267                           int jColumn = back[iColumn];
6268                           if (jColumn >= 0)
6269                             sosIndices[i] = jColumn;
6270                           else
6271                             nMissing++;
6272                         }
6273                         delete[] back;
6274                         if (nMissing) {
6275                           sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing);
6276                           generalMessageHandler->message(CLP_GENERAL, generalMessages)
6277                             << generalPrint
6278                             << CoinMessageEol;
6279                         }
6280                       }
6281                       for (iSOS = 0; iSOS < numberSOS; iSOS++) {
6282                         int iStart = sosStart[iSOS];
6283                         int n = sosStart[iSOS + 1] - iStart;
6284                         objects[iSOS] = new OsiSOS(testOsiSolver, n, sosIndices + iStart, sosReference + iStart,
6285                           sosType[iSOS]);
6286                         if (sosPriority)
6287                           objects[iSOS]->setPriority(sosPriority[iSOS]);
6288                         else if (!prioritiesIn)
6289                           objects[iSOS]->setPriority(10); // rather than 1000
6290                       }
6291                       // delete any existing SOS objects
6292                       int numberObjects = testOsiSolver->numberObjects();
6293                       OsiObject **oldObjects = testOsiSolver->objects();
6294                       int nNew = 0;
6295                       for (int i = 0; i < numberObjects; i++) {
6296                         OsiObject *objThis = oldObjects[i];
6297                         OsiSOS *obj1 = dynamic_cast< OsiSOS * >(objThis);
6298                         OsiSOS *obj2 = dynamic_cast< OsiSOS * >(objThis);
6299                         if (!obj1 && !obj2) {
6300                           oldObjects[nNew++] = objThis;
6301                         } else {
6302                           delete objThis;
6303                         }
6304                       }
6305                       testOsiSolver->setNumberObjects(nNew);
6306                       testOsiSolver->addObjects(numberSOS, objects);
6307                       for (iSOS = 0; iSOS < numberSOS; iSOS++)
6308                         delete objects[iSOS];
6309                       delete[] objects;
6310                     }
6311                   }
6312                   OsiObject **objects = testOsiSolver->objects();
6313                   int numberObjects = testOsiSolver->numberObjects();
6314                   int logLevel = parameters_[log].intValue();
6315                   for (int iObj = 0; iObj < numberObjects; iObj++) {
6316                     // skip sos
6317                     OsiSOS *objSOS = dynamic_cast< OsiSOS * >(objects[iObj]);
6318                     if (objSOS) {
6319                       if (logLevel > 2)
6320                         printf("Set %d is SOS - priority %d\n", iObj, objSOS->priority());
6321                       continue;
6322                     }
6323                     int iColumn = objects[iObj]->columnNumber();
6324                     if (iColumn >= 0) {
6325                       if (originalColumns)
6326                         iColumn = originalColumns[iColumn];
6327                       if (branchDirection) {
6328                         OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(objects[iObj]);
6329                         if (obj) {
6330                           obj->setPreferredWay(branchDirection[iColumn]);
6331                         } else {
6332                           OsiObject2 *obj = dynamic_cast< OsiObject2 * >(objects[iObj]);
6333                           if (obj)
6334                             obj->setPreferredWay(branchDirection[iColumn]);
6335                         }
6336                       }
6337                       if (priorities) {
6338                         int iPriority = priorities[iColumn];
6339                         if (iPriority > 0)
6340                           objects[iObj]->setPriority(iPriority);
6341                       }
6342                       if (logLevel > 2)
6343                         printf("Obj %d is int? - priority %d\n", iObj, objects[iObj]->priority());
6344                       if (pseudoUp && pseudoUp[iColumn]) {
6345                         abort();
6346                       }
6347                     }
6348                   }
6349                   // *************************************************************
6350                 }
6351                 int statistics = (printOptions > 0) ? printOptions : 0;
6352 #ifdef COIN_HAS_ASL
6353                 if (!statusUserFunction_[0]) {
6354 #endif
6355                   free(priorities);
6356                   priorities = NULL;
6357                   free(branchDirection);
6358                   branchDirection = NULL;
6359                   free(pseudoDown);
6360                   pseudoDown = NULL;
6361                   free(pseudoUp);
6362                   pseudoUp = NULL;
6363                   free(solutionIn);
6364                   solutionIn = NULL;
6365                   free(prioritiesIn);
6366                   prioritiesIn = NULL;
6367                   free(sosStart);
6368                   sosStart = NULL;
6369                   free(sosIndices);
6370                   sosIndices = NULL;
6371                   free(sosType);
6372                   sosType = NULL;
6373                   free(sosReference);
6374                   sosReference = NULL;
6375                   free(cut);
6376                   cut = NULL;
6377                   free(sosPriority);
6378                   sosPriority = NULL;
6379 #ifdef COIN_HAS_ASL
6380                 }
6381 #endif
6382                 if (nodeStrategy) {
6383                   // change default
6384                   if (nodeStrategy > 2) {
6385                     // up or down
6386                     int way = (((nodeStrategy - 1) % 2) == 1) ? -1 : +1;
6387                     babModel_->setPreferredWay(way);
6388 #ifdef JJF_ZERO
6389                     OsiObject **objects = babModel_->objects();
6390                     int numberObjects = babModel_->numberObjects();
6391                     for (int iObj = 0; iObj < numberObjects; iObj++) {
6392                       CbcObject *obj = dynamic_cast< CbcObject * >(objects[iObj]);
6393                       assert(obj);
6394                       obj->setPreferredWay(way);
6395                     }
6396 #endif
6397                   }
6398                   if (nodeStrategy == 2 || nodeStrategy > 4) {
6399                     // depth
6400                     CbcCompareDefault compare;
6401                     compare.setWeight(-3.0);
6402                     babModel_->setNodeComparison(compare);
6403                   } else if (nodeStrategy == 0) {
6404                     // hybrid was default i.e. mixture of low depth and infeasibility
6405                   } else if (nodeStrategy == 1) {
6406                     // real fewest
6407                     CbcCompareDefault compare;
6408                     compare.setWeight(-2.0);
6409                     babModel_->setNodeComparison(compare);
6410                   }
6411                 }
6412                 if (cppValue >= 0) {
6413                   int prepro = useStrategy ? -1 : preProcess;
6414                   // generate code
6415                   FILE *fp = fopen("user_driver.cpp", "w");
6416                   if (fp) {
6417                     // generate enough to do BAB
6418                     babModel_->generateCpp(fp, 1);
6419                     OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
6420                     // Make general so do factorization
6421                     int factor = osiclp->getModelPtr()->factorizationFrequency();
6422                     osiclp->getModelPtr()->setFactorizationFrequency(200);
6423                     osiclp->generateCpp(fp);
6424                     osiclp->getModelPtr()->setFactorizationFrequency(factor);
6425                     //solveOptions.generateCpp(fp);
6426                     fclose(fp);
6427                     // now call generate code
6428                     generateCode(babModel_, "user_driver.cpp", cppValue, prepro);
6429                   } else {
6430                     std::cout << "Unable to open file user_driver.cpp" << std::endl;
6431                   }
6432                 }
6433                 if (!babModel_->numberStrong() && babModel_->numberBeforeTrust() > 0)
6434                   babModel_->setNumberBeforeTrust(0);
6435                 if (useStrategy) {
6436                   CbcStrategyDefault strategy(1, babModel_->numberStrong(), babModel_->numberBeforeTrust());
6437                   strategy.setupPreProcessing(1);
6438                   babModel_->setStrategy(strategy);
6439                 }
6440                 if (testOsiOptions >= 0) {
6441                   sprintf(generalPrint, "Testing OsiObject options %d", testOsiOptions);
6442                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
6443                     << generalPrint
6444                     << CoinMessageEol;
6445                   if (!numberSOS) {
6446                     babModel_->solver()->findIntegersAndSOS(false);
6447 #ifdef COIN_HAS_LINK
6448                     // If linked then pass in model
6449                     OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver());
6450                     if (solver3) {
6451                       CbcHeuristicDynamic3 serendipity(*babModel_);
6452                       serendipity.setHeuristicName("linked");
6453                       int heuristicOption = parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].currentOptionAsInteger();
6454 		      if (heuristicOption)
6455 			babModel_->addHeuristic(&serendipity);
6456                       double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue();
6457                       if (dextra3)
6458                         solver3->setMeshSizes(dextra3);
6459                       int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() / 10000;
6460                       CglStored stored;
6461                       if (options) {
6462                         printf("nlp options %d\n", options);
6463                         /*
6464                                                   1 - force mini branch and bound
6465                                                   2 - set priorities high on continuous
6466                                                   4 - try adding OA cuts
6467                                                   8 - try doing quadratic linearization
6468                                                   16 - try expanding knapsacks
6469                                                               32 - OA cuts strictly concave
6470                                                   64 - no branching at all on bilinear x-x!
6471                                                 */
6472                         if ((options & 2)) {
6473                           solver3->setBiLinearPriorities(10, tightenFactor > 0.0 ? tightenFactor : 1.0);
6474                         } else if (tightenFactor > 0.0) {
6475                           // set grid size for all continuous bi-linear
6476                           solver3->setMeshSizes(tightenFactor);
6477                         }
6478                         if ((options & 4)) {
6479                           solver3->setSpecialOptions2(solver3->specialOptions2() | (8 + 4));
6480                           // say convex
6481                           solver3->sayConvex((options & 32) == 0);
6482                         }
6483                         int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue();
6484                         if ((options & 1) != 0 && extra1 > 0)
6485                           solver3->setFixedPriority(extra1);
6486                         double cutoff = COIN_DBL_MAX;
6487                         if ((options & 8))
6488                           cutoff = solver3->linearizedBAB(&stored);
6489                         if (cutoff < babModel_->getCutoff()) {
6490                           babModel_->setCutoff(cutoff);
6491                           // and solution
6492                           //babModel_->setBestObjectiveValue(solver3->bestObjectiveValue());
6493                           babModel_->setBestSolution(solver3->bestSolution(), solver3->getNumCols(),
6494                             solver3->bestObjectiveValue());
6495                         }
6496                         if ((options & 64))
6497                           solver3->setBranchingStrategyOnVariables(16, -1, 4);
6498                       }
6499                       solver3->setCbcModel(babModel_);
6500                       if (stored.sizeRowCuts())
6501                         babModel_->addCutGenerator(&stored, 1, "Stored");
6502                       CglTemporary temp;
6503                       babModel_->addCutGenerator(&temp, 1, "OnceOnly");
6504                       //choose.setNumberBeforeTrusted(2000);
6505                       //choose.setNumberStrong(20);
6506                     }
6507                     // For temporary testing of heuristics
6508                     //int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI,numberParameters_,parameters_)].intValue();
6509                     if (testOsiOptions >= 10) {
6510                       if (testOsiOptions >= 20)
6511                         testOsiOptions -= 10;
6512                       printf("*** Temp heuristic with mode %d\n", testOsiOptions - 10);
6513                       OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver());
6514                       assert(solver3);
6515                       int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue();
6516                       solver3->setBiLinearPriority(extra1);
6517                       printf("bilinear priority now %d\n", extra1);
6518                       int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue();
6519                       double saveDefault = solver3->defaultBound();
6520                       solver3->setDefaultBound(static_cast< double >(extra2));
6521                       double *solution = solver3->heuristicSolution(slpValue > 0 ? slpValue : 40, 1.0e-5, testOsiOptions - 10);
6522                       solver3->setDefaultBound(saveDefault);
6523                       if (!solution)
6524                         printf("Heuristic failed\n");
6525                     }
6526 #endif
6527                   } else {
6528                     // move across
6529                     babModel_->deleteObjects(false);
6530                     //babModel_->addObjects(babModel_->solver()->numberObjects(),babModel_->solver()->objects());
6531                   }
6532                   CbcBranchDefaultDecision decision;
6533                   if (babModel_->numberStrong()) {
6534                     OsiChooseStrong choose(babModel_->solver());
6535                     choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust());
6536                     choose.setNumberStrong(babModel_->numberStrong());
6537                     choose.setShadowPriceMode(testOsiOptions);
6538                     decision.setChooseMethod(choose);
6539                   } else {
6540                     OsiChooseVariable choose(babModel_->solver());
6541                     decision.setChooseMethod(choose);
6542                   }
6543                   babModel_->setBranchingMethod(decision);
6544                   if (useCosts && testOsiOptions >= 0) {
6545                     if (newPriorities) {
6546                       // get rid of
6547                       delete[] newPriorities;
6548                       newPriorities = NULL;
6549                     }
6550                     int numberColumns = babModel_->getNumCols();
6551                     int *sort = new int[numberColumns];
6552                     double *dsort = new double[numberColumns];
6553                     int *priority = new int[numberColumns];
6554                     const double *objective = babModel_->getObjCoefficients();
6555                     const double *lower = babModel_->getColLower();
6556                     const double *upper = babModel_->getColUpper();
6557                     const CoinPackedMatrix *matrix = babModel_->solver()->getMatrixByCol();
6558                     const int *columnLength = matrix->getVectorLengths();
6559                     int iColumn;
6560                     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6561                       sort[iColumn] = iColumn;
6562                       if (useCosts == 1)
6563                         dsort[iColumn] = -fabs(objective[iColumn]);
6564                       else if (useCosts == 2)
6565                         dsort[iColumn] = iColumn;
6566                       else if (useCosts == 3)
6567                         dsort[iColumn] = upper[iColumn] - lower[iColumn];
6568                       else if (useCosts == 4)
6569                         dsort[iColumn] = -(upper[iColumn] - lower[iColumn]);
6570                       else if (useCosts == 5)
6571                         dsort[iColumn] = -columnLength[iColumn];
6572                     }
6573                     CoinSort_2(dsort, dsort + numberColumns, sort);
6574                     int level = 0;
6575                     double last = -1.0e100;
6576                     for (int i = 0; i < numberColumns; i++) {
6577                       int iPut = sort[i];
6578                       if (dsort[i] != last) {
6579                         level++;
6580                         last = dsort[i];
6581                       }
6582                       priority[iPut] = level;
6583                     }
6584                     OsiObject **objects = babModel_->objects();
6585                     int numberObjects = babModel_->numberObjects();
6586                     for (int iObj = 0; iObj < numberObjects; iObj++) {
6587                       OsiObject *obj = objects[iObj];
6588                       int iColumn = obj->columnNumber();
6589                       if (iColumn >= 0)
6590                         obj->setPriority(priority[iColumn]);
6591                     }
6592                     delete[] priority;
6593                     delete[] sort;
6594                     delete[] dsort;
6595                   }
6596                 }
6597                 checkSOS(babModel_, babModel_->solver());
6598                 if (doSprint > 0) {
6599                   // Sprint for primal solves
6600                   ClpSolve::SolveType method = ClpSolve::usePrimalorSprint;
6601                   ClpSolve::PresolveType presolveType = ClpSolve::presolveOff;
6602                   int numberPasses = 5;
6603                   int options[] = { 0, 3, 0, 0, 0, 0 };
6604                   int extraInfo[] = { -1, 20, -1, -1, -1, -1 };
6605                   extraInfo[1] = doSprint;
6606                   int independentOptions[] = { 0, 0, 3 };
6607                   ClpSolve clpSolve(method, presolveType, numberPasses,
6608                     options, extraInfo, independentOptions);
6609                   // say use in OsiClp
6610                   clpSolve.setSpecialOption(6, 1);
6611                   OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
6612                   osiclp->setSolveOptions(clpSolve);
6613                   osiclp->setHintParam(OsiDoDualInResolve, false);
6614                   // switch off row copy
6615                   osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256);
6616                   osiclp->getModelPtr()->setInfeasibilityCost(1.0e11);
6617                 }
6618 #ifdef COIN_HAS_LINK
6619                 if (storedAmpl.sizeRowCuts()) {
6620                   if (preProcess) {
6621                     const int *originalColumns = process.originalColumns();
6622                     int numberColumns = babModel_->getNumCols();
6623                     int *newColumn = new int[numberOriginalColumns];
6624                     int i;
6625                     for (i = 0; i < numberOriginalColumns; i++)
6626                       newColumn[i] = -1;
6627                     for (i = 0; i < numberColumns; i++) {
6628                       int iColumn = originalColumns[i];
6629                       newColumn[iColumn] = i;
6630                     }
6631                     int *buildColumn = new int[numberColumns];
6632                     // Build up valid cuts
6633                     int nBad = 0;
6634                     int nCuts = storedAmpl.sizeRowCuts();
6635                     CglStored newCuts;
6636                     for (i = 0; i < nCuts; i++) {
6637                       const OsiRowCut *cut = storedAmpl.rowCutPointer(i);
6638                       double lb = cut->lb();
6639                       double ub = cut->ub();
6640                       int n = cut->row().getNumElements();
6641                       const int *column = cut->row().getIndices();
6642                       const double *element = cut->row().getElements();
6643                       bool bad = false;
6644                       for (int i = 0; i < n; i++) {
6645                         int iColumn = column[i];
6646                         iColumn = newColumn[iColumn];
6647                         if (iColumn >= 0) {
6648                           buildColumn[i] = iColumn;
6649                         } else {
6650                           bad = true;
6651                           break;
6652                         }
6653                       }
6654                       if (!bad) {
6655                         newCuts.addCut(lb, ub, n, buildColumn, element);
6656                       } else {
6657                         nBad++;
6658                       }
6659                     }
6660                     storedAmpl = newCuts;
6661                     if (nBad)
6662                       printf("%d cuts dropped\n", nBad);
6663                     delete[] newColumn;
6664                     delete[] buildColumn;
6665                   }
6666                 }
6667 #endif
6668 #ifdef CLP_MALLOC_STATISTICS
6669                 malloc_stats();
6670                 malloc_stats2();
6671 #endif
6672 #ifndef CBC_OTHER_SOLVER
6673                 if (outputFormat == 5) {
6674                   osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
6675                   lpSolver = osiclp->getModelPtr();
6676                   lpSolver->setPersistenceFlag(1);
6677                 }
6678 #endif
6679 #ifdef COIN_HAS_ASL
6680                 // add in lotsizing
6681                 if (statusUserFunction_[0] && info.special) {
6682                   int numberColumns = babModel_->getNumCols();
6683                   int i;
6684                   int n = 0;
6685                   if (preProcess) {
6686                     const int *originalColumns = process.originalColumns();
6687                     for (i = 0; i < numberColumns; i++) {
6688                       int iColumn = originalColumns[i];
6689                       assert(iColumn >= i);
6690                       int iType = info.special[iColumn];
6691                       if (iType) {
6692                         assert(iType == 1);
6693                         n++;
6694                       }
6695                       info.special[i] = iType;
6696                     }
6697                   }
6698                   if (n) {
6699                     int numberIntegers = 0;
6700                     int numberOldObjects = 0;
6701                     OsiObject **oldObjects = NULL;
6702                     const double *lower = babModel_->solver()->getColLower();
6703                     const double *upper = babModel_->solver()->getColUpper();
6704                     if (testOsiOptions < 0) {
6705                       // *************************************************************
6706                       // CbcObjects
6707                       numberIntegers = babModel_->numberIntegers();
6708                       /* model may not have created objects
6709                                             If none then create
6710                                             */
6711                       if (!numberIntegers || !babModel_->numberObjects()) {
6712                         int type = (pseudoUp) ? 1 : 0;
6713                         babModel_->findIntegers(true, type);
6714                         numberIntegers = babModel_->numberIntegers();
6715                       }
6716                       oldObjects = babModel_->objects();
6717                       numberOldObjects = babModel_->numberObjects();
6718                     } else {
6719                       numberIntegers = testOsiSolver->getNumIntegers();
6720                       if (!numberIntegers || !testOsiSolver->numberObjects()) {
6721                         /* model may not have created objects
6722                                                    If none then create
6723                                                 */
6724                         testOsiSolver->findIntegers(false);
6725                         numberIntegers = testOsiSolver->getNumIntegers();
6726                       }
6727                       oldObjects = testOsiSolver->objects();
6728                       numberOldObjects = testOsiSolver->numberObjects();
6729                     }
6730                     OsiObject **objects = new OsiObject *[n];
6731                     n = 0;
6732                     // set new objects to have one lower priority
6733                     double ranges[] = { -COIN_DBL_MAX, -1.0, 1.0, COIN_DBL_MAX };
6734                     for (int iObj = 0; iObj < numberOldObjects; iObj++) {
6735                       int iColumn = oldObjects[iObj]->columnNumber();
6736                       if (iColumn >= 0 && info.special[iColumn]) {
6737                         if (lower[iColumn] <= -1.0 && upper[iColumn] >= 0.0) {
6738                           ranges[0] = lower[iColumn];
6739                           ranges[3] = upper[iColumn];
6740                           int priority = oldObjects[iObj]->priority();
6741                           if (testOsiOptions < 0) {
6742                             objects[n] = new CbcLotsize(babModel_, iColumn, 2, ranges, true);
6743                           } else {
6744                             objects[n] = new OsiLotsize(testOsiSolver, iColumn, 2, ranges, true);
6745                           }
6746                           objects[n++]->setPriority(priority - 1);
6747                         }
6748                       }
6749                     }
6750                     if (testOsiOptions < 0) {
6751                       babModel_->addObjects(n, objects);
6752                     } else {
6753                       testOsiSolver->addObjects(n, objects);
6754                     }
6755                     for (i = 0; i < n; i++)
6756                       delete objects[i];
6757                     delete[] objects;
6758                   }
6759                 }
6760 #endif
6761                 if (storedAmpl.sizeRowCuts()) {
6762                   //babModel_->addCutGenerator(&storedAmpl,1,"AmplStored");
6763                   int numberRowCuts = storedAmpl.sizeRowCuts();
6764                   for (int i = 0; i < numberRowCuts; i++) {
6765                     const OsiRowCut *rowCutPointer = storedAmpl.rowCutPointer(i);
6766                     babModel_->makeGlobalCut(rowCutPointer);
6767                   }
6768                 }
6769                 // If defaults then increase trust for small models
6770                 if (!strongChanged) {
6771                   int numberColumns = babModel_->getNumCols();
6772                   if (numberColumns <= 50)
6773                     babModel_->setNumberBeforeTrust(1000);
6774                   else if (numberColumns <= 100)
6775                     babModel_->setNumberBeforeTrust(100);
6776                   else if (numberColumns <= 300)
6777                     babModel_->setNumberBeforeTrust(50);
6778                 }
6779 #ifdef CBC_THREAD
6780                 int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue();
6781                 babModel_->setNumberThreads(numberThreads % 100);
6782                 babModel_->setThreadMode(numberThreads / 100);
6783 #endif
6784                 int returnCode = 0;
6785                 if (callBack != NULL)
6786                   returnCode = callBack(babModel_, 3);
6787                 if (returnCode) {
6788                   // exit if user wants
6789                   delete babModel_;
6790                   babModel_ = NULL;
6791                   return returnCode;
6792                 }
6793 #ifndef CBC_OTHER_SOLVER
6794                 osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
6795                 lpSolver = osiclp->getModelPtr();
6796                 int hotits = parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].intValue();
6797                 if (hotits > 100) {
6798                   osiclp->setSpecialOptions(osiclp->specialOptions() & ~32);
6799                   osiclp->setIntParam(OsiMaxNumIterationHotStart, hotits);
6800                 } else {
6801                   osiclp->setIntParam(OsiMaxNumIterationHotStart, hotits);
6802                 }
6803 #elif CBC_OTHER_SOLVER == 1
6804 #endif
6805                 if ((experimentFlag >= 1 || strategyFlag >= 1) && babModel_->fastNodeDepth() == -1) {
6806                   if (babModel_->solver()->getNumCols() + babModel_->solver()->getNumRows() < 500)
6807                     babModel_->setFastNodeDepth(-12);
6808                 } else if (babModel_->fastNodeDepth() == -999) {
6809                   babModel_->setFastNodeDepth(-1);
6810                 }
6811                 int heurOptions = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue();
6812                 if (heurOptions > 100)
6813                   babModel_->setSpecialOptions(babModel_->specialOptions() | 8192);
6814 
6815 #ifndef CBC_OTHER_SOLVER
6816 #ifdef CLP_MULTIPLE_FACTORIZATIONS
6817                 int denseCode = parameters_[whichParam(CBC_PARAM_INT_DENSE, parameters_)].intValue();
6818                 int smallCode = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, parameters_)].intValue();
6819                 if (bothFlags >= 1) {
6820                   if (denseCode < 0)
6821                     denseCode = 40;
6822                   if (smallCode < 0 && !lpSolver->factorization()->isDenseOrSmall())
6823                     smallCode = 40;
6824                 }
6825                 if (denseCode > 0) {
6826                   lpSolver->factorization()->setGoDenseThreshold(denseCode);
6827                   assert(osiclp == babModel_->solver());
6828                   osiclp->setSpecialOptions(osiclp->specialOptions() | 1024);
6829                 }
6830                 if (smallCode > 0 && smallCode > denseCode)
6831                   lpSolver->factorization()->setGoSmallThreshold(smallCode);
6832                 //if (denseCode>=lpSolver->numberRows()) {
6833                 //lpSolver->factorization()->goDense();
6834                 //}
6835                 if (lpSolver->factorization()->goOslThreshold() > 1000) {
6836                   // use osl in gomory (may not if CglGomory decides not to)
6837                   int numberGenerators = babModel_->numberCutGenerators();
6838                   int nGomory = 0;
6839                   for (int iGenerator = 0; iGenerator < numberGenerators;
6840                        iGenerator++) {
6841                     CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator);
6842                     CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator());
6843                     if (gomory) {
6844                       if (nGomory < 2) {
6845                         gomory->useAlternativeFactorization();
6846                       } else if (gomory->originalSolver()) {
6847                         OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(gomory->originalSolver());
6848                         if (clpSolver) {
6849                           ClpSimplex *simplex = clpSolver->getModelPtr();
6850                           simplex->factorization()->setGoOslThreshold(0);
6851                         }
6852                       }
6853                       nGomory++;
6854                     }
6855                   }
6856                 }
6857 #endif
6858 #endif
6859 #ifdef CLIQUE_ANALYSIS
6860                 if (!storedAmpl.sizeRowCuts()) {
6861                   printf("looking at probing\n");
6862                   babModel_->addCutGenerator(&storedAmpl, 1, "Stored");
6863                 }
6864 #endif
6865 #ifdef SOS_AS_CUTS
6866 #ifdef COIN_HAS_CLP
6867                 /* SOS as cuts
6868 				   Could be a bit more sophisticated e.g. only non duplicates
6869 				   Could do something for SOS 2?
6870 				*/
6871                 {
6872                   OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
6873                   if (clpSolver && clpSolver->numberSOS()) {
6874                     // SOS
6875                     int numberSOS = clpSolver->numberSOS();
6876                     const CoinSet *setInfo = clpSolver->setInfo();
6877                     CglStored sosCuts;
6878                     const double *lower = clpSolver->getColLower();
6879                     const double *upper = clpSolver->getColUpper();
6880                     // Start Cliques
6881                     // sizes
6882                     int nEls = 0;
6883                     for (int i = 0; i < numberSOS; i++)
6884                       nEls += setInfo[i].numberEntries();
6885                     double *els = new double[nEls + 2 * numberSOS];
6886                     for (int i = 0; i < nEls; i++)
6887                       els[i] = 1.0;
6888                     double *lo = els + nEls;
6889                     double *up = lo + numberSOS;
6890                     // need to get rid of sos
6891                     ClpSimplex *fakeSimplex = new ClpSimplex(*clpSolver->getModelPtr());
6892 #if 0
6893 				    int numberRows=fakeSimplex->numberRows();
6894 				    int * starts =
6895 				      new int[CoinMax(numberSOS+1,numberRows)];
6896 				    int * columns = new int[nEls];
6897 				    for (int i=0;i<numberRows;i++)
6898 				      starts[i]=i;
6899 				    fakeSimplex->deleteRows(numberRows,starts);
6900 #else
6901                     int *starts = new int[numberSOS + 1];
6902                     int *columns = new int[nEls];
6903 #endif
6904                     int nAdded = 0;
6905                     starts[0] = 0;
6906                     nEls = 0;
6907 
6908                     // just SOS 1 with 0-1
6909                     for (int i = 0; i < numberSOS; i++) {
6910                       int type = setInfo[i].setType();
6911                       if (type == 2)
6912                         continue;
6913                       int n = setInfo[i].numberEntries();
6914                       const int *which = setInfo[i].which();
6915                       for (int j = 0; j < n; j++) {
6916                         int iColumn = which[j];
6917                         if (lower[iColumn] || upper[iColumn] != 1.0) {
6918                           n = -1;
6919                           break; // no good
6920                         }
6921                       }
6922                       if (n > 0) {
6923                         memcpy(columns + nEls, which, n * sizeof(int));
6924                         lo[nAdded] = -COIN_DBL_MAX;
6925                         up[nAdded] = 1.0;
6926                         nAdded++;
6927                         nEls += n;
6928                         starts[nAdded] = nEls;
6929                       }
6930                     }
6931                     if (nAdded)
6932                       fakeSimplex->addRows(nAdded,
6933                         lo, up,
6934                         starts, columns, els);
6935                     if (nAdded) {
6936                       OsiClpSolverInterface fakeSolver(fakeSimplex);
6937                       CglFakeClique fakeGen(&fakeSolver, false);
6938                       fakeGen.setStarCliqueReport(false);
6939                       fakeGen.setRowCliqueReport(false);
6940                       fakeGen.setMinViolation(0.05);
6941                       babModel_->addCutGenerator(&fakeGen, 1, "SosCuts");
6942                       //fakeSimplex->writeMps("bad.mps",0,1);
6943                       sosCuts.setProbingInfo(new CglTreeProbingInfo(&fakeSolver));
6944                     }
6945                     delete fakeSimplex;
6946                     // End Cliques
6947                     // Start Stored
6948                     nAdded = 0;
6949                     for (int i = 0; i < numberSOS; i++) {
6950                       int type = setInfo[i].setType();
6951                       int n = setInfo[i].numberEntries();
6952                       const int *which = setInfo[i].which();
6953                       double rhs = 0.0;
6954                       double previous = 0.0;
6955                       for (int j = 0; j < n; j++) {
6956                         int iColumn = which[j];
6957                         if (lower[iColumn]) {
6958                           n = -1;
6959                           break; // no good
6960                         }
6961                         rhs = CoinMax(upper[iColumn] + previous, rhs);
6962                         if (type == 2)
6963                           previous = upper[iColumn];
6964                       }
6965                       if (n > 0) {
6966                         sosCuts.addCut(0.0, rhs,
6967                           n, which, els);
6968                         nAdded++;
6969                       }
6970                     }
6971                     if (nAdded)
6972                       babModel_->addCutGenerator(&sosCuts, 1, "SosCuts2");
6973                     // End Stored
6974                     delete[] els;
6975                     delete[] columns;
6976                     delete[] starts;
6977                   }
6978                 }
6979 #endif
6980 #endif
6981                 if (useSolution > 1) {
6982                   // use hotstart to try and find solution
6983                   CbcHeuristicPartial partial(*babModel_, 10000, useSolution);
6984                   partial.setHeuristicName("Partial solution given");
6985                   babModel_->addHeuristic(&partial);
6986                 }
6987                 if (logLevel <= 1 && babModel_->solver()->messageHandler() != babModel_->messageHandler())
6988                   babModel_->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
6989 #ifdef CBC_TEMP1
6990                 if (osiclp->getModelPtr()->perturbation() == 50)
6991                   osiclp->getModelPtr()->setPerturbation(52); // try less
6992 #endif
6993 #ifdef JJF_ZERO
6994                 if (osiclp->getNumCols() == 29404) {
6995                   void restoreSolution(ClpSimplex * lpSolver,
6996                     std::string fileName, int mode);
6997                   restoreSolution(osiclp->getModelPtr(), "debug.file", 0);
6998                   int numberColumns = osiclp->getNumCols();
6999                   const double *solution = osiclp->getColSolution();
7000                   const int *originalColumns = process.originalColumns();
7001                   for (int i = 0; i < numberColumns; i++) {
7002                     int iColumn = originalColumns[i];
7003                     if (saveSolver->isInteger(iColumn)) {
7004                       double value = solution[i];
7005                       double value2 = floor(value + 0.5);
7006                       assert(fabs(value - value2) < 1.0e-3);
7007                       saveSolver->setColLower(iColumn, value2);
7008                       saveSolver->setColUpper(iColumn, value2);
7009                     }
7010                   }
7011                   saveSolver->writeMps("fixed");
7012                   babModel_->setBestSolution(osiclp->getColSolution(),
7013                     osiclp->getNumCols(),
7014                     1.5325e10);
7015                 } else {
7016                   babModel_->branchAndBound(statistics);
7017                 }
7018 #else
7019 #ifdef ORBITAL
7020                 CbcOrbital orbit(babModel_);
7021                 orbit.morph();
7022                 exit(1);
7023 #endif
7024                 int hOp1 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 100000;
7025                 if (hOp1 % 10) {
7026                   CbcCompareDefault compare;
7027                   compare.setBreadthDepth(hOp1 % 10);
7028                   babModel_->setNodeComparison(compare);
7029                 } else if (hOp1 == 10) {
7030                   CbcCompareObjective compare;
7031                   babModel_->setNodeComparison(compare);
7032                 }
7033 #if CBC_OTHER_SOLVER == 1
7034                 if (dynamic_cast< OsiCpxSolverInterface * >(babModel_->solver()))
7035                   babModel_->solver()->messageHandler()->setLogLevel(0);
7036 #endif
7037                 if (parameters_[whichParam(CBC_PARAM_STR_CPX, parameters_)].currentOptionAsInteger()) {
7038                   babModel_->setSpecialOptions(babModel_->specialOptions() | 16384);
7039                   //if (babModel_->fastNodeDepth()==-1)
7040                   babModel_->setFastNodeDepth(-2); // Use Cplex at root
7041                 }
7042                 int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 10000;
7043                 if (hOp2 % 10) {
7044                   babModel_->setSpecialOptions(babModel_->specialOptions() | 16384);
7045                   if (babModel_->fastNodeDepth() == -1)
7046                     babModel_->setFastNodeDepth(-2); // Use Cplex at root
7047                 }
7048                 if (experimentFlag >= 5) {
7049                   CbcModel donor(*babModel_);
7050                   int options = babModel_->specialOptions();
7051                   donor.setSpecialOptions(options | 262144);
7052                   ClpSimplex *lpSolver2;
7053                   OsiClpSolverInterface *clpSolver2;
7054                   clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(donor.solver());
7055                   assert(clpSolver2);
7056                   lpSolver2 = clpSolver2->getModelPtr();
7057                   assert(lpSolver2);
7058                   if (lpSolver->factorization()->isDenseOrSmall()) {
7059                     lpSolver2->factorization()->forceOtherFactorization(0);
7060                     lpSolver2->factorization()->setGoOslThreshold(0);
7061                     lpSolver2->factorization()->setGoDenseThreshold(0);
7062                     lpSolver2->factorization()->setGoSmallThreshold(0);
7063                     lpSolver2->allSlackBasis();
7064                     lpSolver2->initialSolve();
7065                     int numberGenerators = donor.numberCutGenerators();
7066                     for (int iGenerator = 0; iGenerator < numberGenerators;
7067                          iGenerator++) {
7068                       CbcCutGenerator *generator = donor.cutGenerator(iGenerator);
7069                       CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator());
7070                       if (gomory)
7071                         gomory->useAlternativeFactorization(false);
7072                     }
7073                   } else {
7074                     printf("code this\n");
7075                     abort();
7076                   }
7077                   babModel_->setSpecialOptions(options | 524288);
7078                   CglStored *stored = new CglStored(donor.getNumCols());
7079                   donor.setStoredRowCuts(stored);
7080                   donor.branchAndBound(0);
7081                   babModel_->setStoredRowCuts(donor.storedRowCuts());
7082                   donor.setStoredRowCuts(NULL);
7083                 }
7084                 // We may have priorities from extra variables
7085                 int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue();
7086                 if (newPriorities) {
7087                   if (truncateColumns < babModel_->getNumCols()) {
7088                     // set new ones as high prority
7089                     babModel_->passInPriorities(newPriorities, false);
7090                   }
7091                   delete[] newPriorities;
7092                 } else if ((more2 & (512 | 1024)) != 0) {
7093                   babModel_->findIntegers(true);
7094                   int numberIntegers = babModel_->numberIntegers();
7095                   int *newPriorities = new int[numberIntegers];
7096                   int n = numberIntegers - (babModel_->getNumCols() - truncateColumns);
7097                   for (int i = 0; i < n; i++)
7098                     newPriorities[i] = babModel_->priority(i);
7099 #if 1
7100                   int ixxxxxx = parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].intValue();
7101                   int obj_priority = 1000;
7102                   int slack_priority = 1000;
7103                   if (ixxxxxx >= 1000000 && ixxxxxx < 1010000) {
7104                     ixxxxxx -= 1000000;
7105                     if (ixxxxxx == 0) {
7106                       obj_priority = 1000;
7107                       slack_priority = 1000;
7108                     } else if (ixxxxxx == 1) {
7109                       obj_priority = 10000;
7110                       slack_priority = 10000;
7111                     } else if (ixxxxxx == 2) {
7112                       obj_priority = 100;
7113                       slack_priority = 100;
7114                     } else if (ixxxxxx == 3) {
7115                       obj_priority = 100;
7116                       slack_priority = 10000;
7117                     } else if (ixxxxxx == 4) {
7118                       obj_priority = 10000;
7119                       slack_priority = 100;
7120                     } else if (ixxxxxx == 5) {
7121                       obj_priority = 100;
7122                       slack_priority = 200;
7123                     } else if (ixxxxxx == 6) {
7124                       obj_priority = 200;
7125                       slack_priority = 100;
7126                     } else {
7127                       abort();
7128                     }
7129                   }
7130                   if ((more2 & 512) != 0) {
7131                     newPriorities[n++] = obj_priority;
7132                   }
7133                   if ((more2 & 1024) != 0) {
7134                     for (int i = n; i < numberIntegers; i++)
7135                       newPriorities[i] = slack_priority;
7136                   }
7137 #else
7138 #define PRIORITY_TRY 0
7139 #if PRIORITY_TRY == 0
7140 #define OBJ_PRIORITY 1000
7141 #define SLACK_PRIORITY 1000
7142 #elif PRIORITY_TRY == 1
7143 #define OBJ_PRIORITY 10000
7144 #define SLACK_PRIORITY 10000
7145 #elif PRIORITY_TRY == 2
7146 #define OBJ_PRIORITY 100
7147 #define SLACK_PRIORITY 100
7148 #elif PRIORITY_TRY == 3
7149 #define OBJ_PRIORITY 100
7150 #define SLACK_PRIORITY 10000
7151 #elif PRIORITY_TRY == 4
7152 #define OBJ_PRIORITY 10000
7153 #define SLACK_PRIORITY 100
7154 #elif PRIORITY_TRY == 5
7155 #define OBJ_PRIORITY 100
7156 #define SLACK_PRIORITY 200
7157 #elif PRIORITY_TRY == 6
7158 #define OBJ_PRIORITY 200
7159 #define SLACK_PRIORITY 100
7160 #endif
7161                   if ((more2 & 512) != 0) {
7162                     newPriorities[n++] = OBJ_PRIORITY;
7163                   }
7164                   if ((more2 & 1024) != 0) {
7165                     for (int i = n; i < numberIntegers; i++)
7166                       newPriorities[i] = SLACK_PRIORITY;
7167                   }
7168 #endif
7169                   babModel_->passInPriorities(newPriorities, false);
7170                   delete[] newPriorities;
7171                 }
7172 #ifdef JJF_ZERO
7173                 int extra5 = parameters_[whichParam(EXTRA5, parameters_)].intValue();
7174                 if (extra5 > 0) {
7175                   int numberGenerators = babModel_->numberCutGenerators();
7176                   for (int iGenerator = 0; iGenerator < numberGenerators;
7177                        iGenerator++) {
7178                     CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator);
7179                     CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator());
7180                     if (gomory) {
7181                       CglGomory gomory2(*gomory);
7182                       gomory2.useAlternativeFactorization(!gomory->alternativeFactorization());
7183                       babModel_->addCutGenerator(&gomory2, -99, "Gomory2");
7184                     }
7185                   }
7186                 }
7187 #endif
7188                 int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, parameters_)].intValue();
7189                 if (specialOptions >= 0)
7190                   babModel_->setStrongStrategy(specialOptions);
7191                 int jParam = whichParam(CBC_PARAM_STR_CUTOFF_CONSTRAINT,
7192                   parameters_);
7193                 if (parameters_[jParam].currentOptionAsInteger()) {
7194                   babModel_->setCutoffAsConstraint(true);
7195                   int moreOptions = babModel_->moreSpecialOptions();
7196                   if (parameters_[jParam].currentOptionAsInteger() == 4)
7197                     babModel_->setMoreSpecialOptions(moreOptions | 4194304);
7198                 }
7199                 int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].intValue();
7200                 if (multipleRoot < 10000) {
7201                   babModel_->setMultipleRootTries(multipleRoot);
7202                 } else {
7203                   // will be doing repeated solves and saves
7204                   int numberGoes = multipleRoot / 10000;
7205                   multipleRoot -= 10000 * numberGoes;
7206                   int moreOptions = babModel_->moreSpecialOptions();
7207                   if (numberGoes < 100) {
7208                     remove("global.cuts");
7209                     remove("global.fix");
7210                     moreOptions |= (67108864 | 134217728);
7211                   } else {
7212                     moreOptions |= 67108864 * (numberGoes / 100);
7213                     numberGoes = numberGoes % 100;
7214                   }
7215                   babModel_->setMultipleRootTries(multipleRoot);
7216                   babModel_->setMoreSpecialOptions(moreOptions);
7217                   int numberColumns = babModel_->getNumCols();
7218                   double *bestValues = new double[numberGoes];
7219                   double **bestSolutions = new double *[numberGoes];
7220                   int *which = new int[numberGoes];
7221                   int numberSolutions = 0;
7222                   sprintf(generalPrint, "Starting %d passes each with %d solvers",
7223                     numberGoes, multipleRoot % 10);
7224                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
7225                     << generalPrint
7226                     << CoinMessageEol;
7227                   for (int iGo = 0; iGo < numberGoes; iGo++) {
7228                     sprintf(generalPrint, "Starting pass %d", iGo + 1);
7229                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
7230                       << generalPrint
7231                       << CoinMessageEol;
7232                     CbcModel tempModel = *babModel_;
7233                     tempModel.setMaximumNodes(0);
7234                     // switch off cuts if none generated
7235                     int numberGenerators = tempModel.numberCutGenerators();
7236                     for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
7237                       CbcCutGenerator *generator = tempModel.cutGenerator(iGenerator);
7238                       generator->setSwitchOffIfLessThan(1);
7239                     }
7240                     // random
7241                     tempModel.setRandomSeed(tempModel.getRandomSeed() + 100000000 * (iGo + 1 + 5 * numberGoes));
7242                     for (int i = 0; i < tempModel.numberHeuristics(); i++)
7243                       tempModel.heuristic(i)->setSeed(tempModel.heuristic(i)->getSeed() + 100000000 * iGo);
7244 #ifndef CBC_OTHER_SOLVER
7245                     OsiClpSolverInterface *solver = dynamic_cast< OsiClpSolverInterface * >(tempModel.solver());
7246                     ClpSimplex *simplex = solver->getModelPtr();
7247                     int solverSeed = simplex->randomNumberGenerator()->getSeed();
7248                     simplex->setRandomSeed(solverSeed + 100000000 * (iGo + 1));
7249 #endif
7250                     tempModel.branchAndBound();
7251                     if (tempModel.bestSolution()) {
7252                       bestSolutions[numberSolutions] = CoinCopyOfArray(tempModel.bestSolution(),
7253                         numberColumns);
7254                       bestValues[numberSolutions] = -tempModel.getMinimizationObjValue();
7255                       which[numberSolutions] = numberSolutions;
7256                       numberSolutions++;
7257                     }
7258                   }
7259                   // allow solutions
7260                   double sense = babModel_->solver()->getObjSense();
7261                   ;
7262                   CoinSort_2(bestValues, bestValues + numberSolutions, which);
7263                   babModel_->setMoreSpecialOptions(moreOptions & (~16777216));
7264                   for (int i = 0; i < numberSolutions; i++) {
7265                     int k = which[i];
7266                     if (bestValues[i] < babModel_->getCutoff()) {
7267                       babModel_->setBestSolution(bestSolutions[k], numberColumns,
7268                         -bestValues[i] * sense, true);
7269                       babModel_->incrementUsed(bestSolutions[k]);
7270                     }
7271                     delete[] bestSolutions[k];
7272                   }
7273                   babModel_->setMoreSpecialOptions(moreOptions);
7274                   if (numberSolutions)
7275                     sprintf(generalPrint, "Ending major passes - best solution %g", -bestValues[numberSolutions - 1]);
7276                   else
7277                     sprintf(generalPrint, "Ending major passes - no solution found");
7278                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
7279                     << generalPrint
7280                     << CoinMessageEol;
7281                   delete[] which;
7282                   delete[] bestValues;
7283                   delete[] bestSolutions;
7284                 }
7285                 if (biLinearProblem)
7286                   babModel_->setSpecialOptions(babModel_->specialOptions() & (~(512 | 32768)));
7287                 babModel_->setMoreSpecialOptions2(parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue());
7288 #ifdef COIN_HAS_NTY
7289                 int nautyAdded = 0;
7290                 {
7291                   int jParam = whichParam(CBC_PARAM_STR_ORBITAL,
7292                     parameters_);
7293                   if (parameters_[jParam].currentOptionAsInteger()) {
7294                     int k = parameters_[jParam].currentOptionAsInteger();
7295                     if (k < 4) {
7296                       babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | (k * 128));
7297                     } else {
7298 #define MAX_NAUTY_PASS 2000
7299                       nautyAdded = nautiedConstraints(*babModel_,
7300                         MAX_NAUTY_PASS);
7301                     }
7302                   }
7303                 }
7304 #endif
7305                 // Set up pointer to preProcess
7306                 if (preProcessPointer) {
7307                   babModel_->setPreProcess(preProcessPointer);
7308                 }
7309                 babModel_->branchAndBound(statistics);
7310 #ifdef COIN_HAS_NTY
7311                 if (nautyAdded) {
7312                   int *which = new int[nautyAdded];
7313                   int numberOldRows = babModel_->solver()->getNumRows() - nautyAdded;
7314                   for (int i = 0; i < nautyAdded; i++)
7315                     which[i] = i + numberOldRows;
7316                   babModel_->solver()->deleteRows(nautyAdded, which);
7317                   delete[] which;
7318                   babModel_->solver()->resolve();
7319                 }
7320 #endif
7321                 if (truncateColumns < babModel_->solver()->getNumCols()) {
7322                   OsiSolverInterface *solverX = babModel_->solver();
7323                   int numberColumns = solverX->getNumCols();
7324                   int numberRows = solverX->getNumRows();
7325                   int numberDelete = numberColumns - truncateColumns;
7326                   int *delStuff = new int[numberDelete];
7327                   for (int i = 0; i < numberDelete; i++)
7328                     delStuff[i] = i + truncateColumns;
7329                   solverX->deleteCols(numberDelete, delStuff);
7330                   numberDelete = numberRows - truncateRows;
7331                   for (int i = 0; i < numberDelete; i++)
7332                     delStuff[i] = i + truncateRows;
7333                   solverX->deleteRows(numberDelete, delStuff);
7334                   delete[] delStuff;
7335                   if (truncatedRhsLower) {
7336                     numberRows = solverX->getNumRows();
7337                     for (int i = 0; i < numberRows; i++) {
7338                       solverX->setRowLower(i, truncatedRhsLower[i]);
7339                       solverX->setRowUpper(i, truncatedRhsUpper[i]);
7340                     }
7341                     delete[] truncatedRhsLower;
7342                     delete[] truncatedRhsUpper;
7343                   }
7344                 }
7345                 //#define CLP_FACTORIZATION_INSTRUMENT
7346 #ifdef CLP_FACTORIZATION_INSTRUMENT
7347                 extern double factorization_instrument(int type);
7348                 double facTime = factorization_instrument(0);
7349                 printf("Factorization %g seconds\n",
7350                   facTime);
7351 #endif
7352 #endif
7353 #ifdef COIN_DEVELOP
7354 #ifndef JJF_ONE
7355                 {
7356                   int numberColumns = babModel_->getNumCols();
7357                   const double *solution = babModel_->bestSolution();
7358                   if (solution && numberColumns < 1000) {
7359                     for (int i = 0; i < numberColumns; i++) {
7360                       if (solution[i])
7361                         printf("SOL %d %.18g\n", i, solution[i]);
7362                     }
7363                   }
7364                 }
7365 #endif
7366                 void printHistory(const char *file /*,CbcModel * model*/);
7367                 printHistory("branch.log" /*,babModel_*/);
7368 #endif
7369                 returnCode = 0;
7370                 if (callBack != NULL)
7371                   returnCode = callBack(babModel_, 4);
7372                 if (returnCode) {
7373                   // exit if user wants
7374                   model_.moveInfo(*babModel_);
7375                   delete babModel_;
7376                   babModel_ = NULL;
7377                   return returnCode;
7378                 } else {
7379                   int numberSolutions = babModel_->numberSavedSolutions();
7380                   if (numberSolutions > 1) {
7381                     for (int iSolution = numberSolutions - 1; iSolution >= 0; iSolution--) {
7382                       model_.setBestSolution(babModel_->savedSolution(iSolution),
7383                         model_.solver()->getNumCols(),
7384                         babModel_->savedSolutionObjective(iSolution));
7385                     }
7386                   }
7387                 }
7388 #ifdef CLP_MALLOC_STATISTICS
7389                 malloc_stats();
7390                 malloc_stats2();
7391 #endif
7392                 checkSOS(babModel_, babModel_->solver());
7393               } else if (type == CBC_PARAM_ACTION_MIPLIB) {
7394                 int typeOfCuts = babModel_->numberCutGenerators() ? 1 : -1;
7395                 CbcStrategyDefault strategy(typeOfCuts,
7396                   babModel_->numberStrong(),
7397                   babModel_->numberBeforeTrust());
7398                 // Set up pre-processing
7399                 int translate2[] = { 9999, 1, 1, 3, 2, 4, 5, 6, 6 };
7400                 if (preProcess)
7401                   strategy.setupPreProcessing(translate2[preProcess]);
7402                 babModel_->setStrategy(strategy);
7403 #ifdef CBC_THREAD
7404                 int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue();
7405                 babModel_->setNumberThreads(numberThreads % 100);
7406                 babModel_->setThreadMode(numberThreads / 100);
7407 #endif
7408 #ifndef CBC_OTHER_SOLVER
7409                 if (outputFormat == 5) {
7410                   osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
7411                   lpSolver = osiclp->getModelPtr();
7412                   lpSolver->setPersistenceFlag(1);
7413                 }
7414 #endif
7415                 if (testOsiOptions >= 0) {
7416                   printf("Testing OsiObject options %d\n", testOsiOptions);
7417                   CbcBranchDefaultDecision decision;
7418                   OsiChooseStrong choose(babModel_->solver());
7419                   choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust());
7420                   choose.setNumberStrong(babModel_->numberStrong());
7421                   choose.setShadowPriceMode(testOsiOptions);
7422                   //babModel_->deleteObjects(false);
7423                   decision.setChooseMethod(choose);
7424                   babModel_->setBranchingMethod(decision);
7425                 }
7426                 model_ = *babModel_;
7427 #ifndef CBC_OTHER_SOLVER
7428                 {
7429                   osiclp = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
7430                   lpSolver = osiclp->getModelPtr();
7431                   lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound)
7432                   if (lpSolver->factorization()->goOslThreshold() > 1000) {
7433                     // use osl in gomory (may not if CglGomory decides not to)
7434                     int numberGenerators = model_.numberCutGenerators();
7435                     for (int iGenerator = 0; iGenerator < numberGenerators;
7436                          iGenerator++) {
7437                       CbcCutGenerator *generator = model_.cutGenerator(iGenerator);
7438                       CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator());
7439                       if (gomory)
7440                         gomory->useAlternativeFactorization();
7441                     }
7442                   }
7443                 }
7444 #endif
7445                 /* LL: this was done in CoinSolve.cpp: main(argc, argv).
7446                                    I have moved it here so that the miplib directory location
7447                                    could be passed to CbcClpUnitTest. */
7448                 /* JJF: No need to have 777 flag at all - user
7449                      says -miplib
7450                      */
7451                 int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue();
7452                 double stuff[11];
7453                 stuff[0] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue();
7454                 stuff[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue();
7455                 stuff[2] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue();
7456                 stuff[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue();
7457                 stuff[4] = parameters_[whichParam(CBC_PARAM_INT_DENSE, parameters_)].intValue();
7458                 stuff[5] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue();
7459                 stuff[6] = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, parameters_)].intValue();
7460                 stuff[7] = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, parameters_)].intValue();
7461                 stuff[8] = bothFlags;
7462                 stuff[9] = doVector;
7463                 stuff[10] = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, parameters_)].intValue();
7464                 if (dominatedCuts)
7465                   model_.setSpecialOptions(model_.specialOptions() | 64);
7466                 if (parameters_[whichParam(CBC_PARAM_STR_CPX, parameters_)].currentOptionAsInteger()) {
7467                   model_.setSpecialOptions(model_.specialOptions() | 16384);
7468                   //if (model_.fastNodeDepth()==-1)
7469                   model_.setFastNodeDepth(-2); // Use Cplex at root
7470                 }
7471                 int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 10000;
7472                 if (hOp2 % 10) {
7473                   model_.setSpecialOptions(model_.specialOptions() | 16384);
7474                   if (model_.fastNodeDepth() == -1)
7475                     model_.setFastNodeDepth(-2); // Use Cplex at root
7476                 }
7477                 int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].intValue();
7478                 model_.setMultipleRootTries(multipleRoot);
7479                 int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, parameters_)].intValue();
7480                 if (specialOptions >= 0)
7481                   model_.setStrongStrategy(specialOptions);
7482                 if (!pumpChanged) {
7483                   // Make more lightweight
7484                   for (int iHeur = 0; iHeur < model_.numberHeuristics(); iHeur++) {
7485                     CbcHeuristic *heuristic = model_.heuristic(iHeur);
7486                     CbcHeuristicFPump *pump = dynamic_cast< CbcHeuristicFPump * >(heuristic);
7487                     if (pump) {
7488                       CbcHeuristicFPump heuristic4(model_);
7489                       heuristic4.setFractionSmall(0.5);
7490                       heuristic4.setMaximumPasses(5);
7491                       heuristic4.setFeasibilityPumpOptions(30);
7492                       heuristic4.setWhen(13);
7493                       heuristic4.setHeuristicName("feasibility pump");
7494                       //CbcHeuristicFPump & pump2 = pump;
7495                       *pump = heuristic4;
7496                     }
7497                   }
7498                 }
7499                 int returnCode = CbcClpUnitTest(model_, dirMiplib, extra2, stuff);
7500                 babModel_ = NULL;
7501                 return returnCode;
7502               } else {
7503                 abort(); // can't get here
7504                 //strengthenedModel = babModel_->strengthenedModel();
7505               }
7506               currentBranchModel = NULL;
7507 #ifndef CBC_OTHER_SOLVER
7508               osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
7509               if (debugFile == "createAfterPre" && babModel_->bestSolution()) {
7510                 lpSolver = osiclp->getModelPtr();
7511                 //move best solution (should be there -- but ..)
7512                 int n = lpSolver->getNumCols();
7513                 memcpy(lpSolver->primalColumnSolution(), babModel_->bestSolution(), n * sizeof(double));
7514                 saveSolution(osiclp->getModelPtr(), "debug.file");
7515               }
7516 #endif
7517               statistics_cut_time = 0.0;
7518               if (!noPrinting_) {
7519                 // Print more statistics
7520                 sprintf(generalPrint, "Cuts at root node changed objective from %g to %g",
7521                   babModel_->getContinuousObjective(), babModel_->rootObjectiveAfterCuts());
7522                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
7523                   << generalPrint
7524                   << CoinMessageEol;
7525 
7526                 numberGenerators = babModel_->numberCutGenerators();
7527                 // can get here twice!
7528                 if (statistics_number_cuts != NULL)
7529                   delete[] statistics_number_cuts;
7530                 statistics_number_cuts = new int[numberGenerators];
7531 
7532                 if (statistics_name_generators != NULL)
7533                   delete[] statistics_name_generators;
7534                 statistics_name_generators = new const char *[numberGenerators];
7535 
7536                 statistics_number_generators = numberGenerators;
7537 
7538                 char timing[30];
7539                 for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
7540                   CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator);
7541                   statistics_name_generators[iGenerator] = generator->cutGeneratorName();
7542                   statistics_number_cuts[iGenerator] = generator->numberCutsInTotal();
7543                   sprintf(generalPrint, "%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts",
7544                     generator->cutGeneratorName(),
7545                     generator->numberTimesEntered(),
7546                     generator->numberCutsInTotal() + generator->numberColumnCuts(),
7547                     generator->numberCutsActive());
7548                   if (generator->timing()) {
7549                     sprintf(timing, " (%.3f seconds)", generator->timeInCutGenerator());
7550                     strcat(generalPrint, timing);
7551                     statistics_cut_time += generator->timeInCutGenerator();
7552                   }
7553                   CglStored *stored = dynamic_cast< CglStored * >(generator->generator());
7554                   if (stored && !generator->numberCutsInTotal())
7555                     continue;
7556 #ifndef CLP_INVESTIGATE
7557                   CglImplication *implication = dynamic_cast< CglImplication * >(generator->generator());
7558                   if (implication && !generator->numberCutsInTotal())
7559                     continue;
7560 #endif
7561                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
7562                     << generalPrint
7563                     << CoinMessageEol;
7564                 }
7565 #ifdef COIN_DEVELOP
7566                 printf("%d solutions found by heuristics\n",
7567                   babModel_->getNumberHeuristicSolutions());
7568                 // Not really generator but I am feeling lazy
7569                 for (iGenerator = 0; iGenerator < babModel_->numberHeuristics(); iGenerator++) {
7570                   CbcHeuristic *heuristic = babModel_->heuristic(iGenerator);
7571                   if (heuristic->numRuns()) {
7572                     // Need to bring others inline
7573                     sprintf(generalPrint, "%s was tried %d times out of %d and created %d solutions\n",
7574                       heuristic->heuristicName(),
7575                       heuristic->numRuns(),
7576                       heuristic->numCouldRun(),
7577                       heuristic->numberSolutionsFound());
7578                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
7579                       << generalPrint
7580                       << CoinMessageEol;
7581                   }
7582                 }
7583 #endif
7584               }
7585               // adjust time to allow for children on some systems
7586               time2 = CoinCpuTime() + CoinCpuTimeJustChildren();
7587               totalTime += time2 - time1;
7588               // For best solution
7589               double *bestSolution = NULL;
7590               // Say in integer
7591               if (babModel_->status()) {
7592                 // treat as stopped
7593                 integerStatus = 3;
7594               } else {
7595                 if (babModel_->isProvenOptimal()) {
7596                   integerStatus = 0;
7597                 } else if (!babModel_->bestSolution()) {
7598                   // infeasible
7599                   integerStatus = 6;
7600                   delete saveSolver;
7601                   saveSolver = NULL;
7602                 }
7603               }
7604               if (babModel_->getMinimizationObjValue() < 1.0e50 && type == CBC_PARAM_ACTION_BAB) {
7605                 // post process
7606                 int n;
7607                 if (preProcess) {
7608                   n = saveSolver->getNumCols();
7609                   bestSolution = new double[n];
7610 #ifndef CBC_OTHER_SOLVER
7611                   OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
7612 #else
7613                   OsiCpxSolverInterface *clpSolver = dynamic_cast< OsiCpxSolverInterface * >(babModel_->solver());
7614 #endif
7615                   // Save bounds on processed model
7616                   const int *originalColumns = process.originalColumns();
7617                   int numberColumns2 = clpSolver->getNumCols();
7618                   double *lower2 = new double[n];
7619                   double *upper2 = new double[n];
7620                   for (int i = 0; i < n; i++) {
7621                     lower2[i] = COIN_DBL_MAX;
7622                     upper2[i] = -COIN_DBL_MAX;
7623                   }
7624                   const double *columnLower = clpSolver->getColLower();
7625                   const double *columnUpper = clpSolver->getColUpper();
7626                   for (int i = 0; i < numberColumns2; i++) {
7627                     int jColumn = originalColumns[i];
7628                     if (jColumn < n) {
7629                       lower2[jColumn] = columnLower[i];
7630                       upper2[jColumn] = columnUpper[i];
7631                     }
7632                   }
7633 #ifndef CBC_OTHER_SOLVER
7634                   ClpSimplex *lpSolver = clpSolver->getModelPtr();
7635                   lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound)
7636 #endif
7637                   // put back any saved solutions
7638                   putBackOtherSolutions(babModel_, &model_, &process);
7639                   process.postProcess(*babModel_->solver());
7640 #ifdef COIN_DEVELOP
7641                   if (model_.bestSolution() && fabs(model_.getMinimizationObjValue() - babModel_->getMinimizationObjValue()) < 1.0e-8) {
7642                     const double *b1 = model_.bestSolution();
7643                     const double *b2 = saveSolver->getColSolution();
7644                     const double *columnLower = saveSolver->getColLower();
7645                     const double *columnUpper = saveSolver->getColUpper();
7646                     for (int i = 0; i < n; i++) {
7647                       if (fabs(b1[i] - b2[i]) > 1.0e-7) {
7648                         printf("%d %g %g %g %g\n", i, b1[i], b2[i],
7649                           columnLower[i], columnUpper[i]);
7650                       }
7651                     }
7652                   }
7653 #endif
7654                   bool tightenB = false;
7655                   {
7656                     int n = babModel_->numberObjects();
7657                     for (int i = 0; i < n; i++) {
7658                       const OsiObject *obj = babModel_->object(i);
7659                       if (!dynamic_cast< const CbcSimpleInteger * >(obj)) {
7660                         tightenB = true;
7661                         break;
7662                       }
7663                     }
7664                   }
7665                   // Solution now back in saveSolver
7666                   // Double check bounds
7667                   columnLower = saveSolver->getColLower();
7668                   columnUpper = saveSolver->getColUpper();
7669                   int numberChanged = 0;
7670                   for (int i = 0; i < n; i++) {
7671                     if (!saveSolver->isInteger(i) && !tightenB)
7672                       continue;
7673                     if (lower2[i] != COIN_DBL_MAX) {
7674                       if (lower2[i] != columnLower[i] || upper2[i] != columnUpper[i]) {
7675                         if (lower2[i] < columnLower[i] || upper2[i] > columnUpper[i]) {
7676 #ifdef COIN_DEVELOP
7677                           printf("odd bounds tighter");
7678                           printf("%d bab bounds %g %g now %g %g\n",
7679                             i, lower2[i], upper2[i], columnLower[i],
7680                             columnUpper[i]);
7681 #endif
7682                         } else {
7683 #ifdef COIN_DEVELOP
7684                           printf("%d bab bounds %g %g now %g %g\n",
7685                             i, lower2[i], upper2[i], columnLower[i],
7686                             columnUpper[i]);
7687 #endif
7688                           numberChanged++;
7689                           saveSolver->setColLower(i, lower2[i]);
7690                           saveSolver->setColUpper(i, upper2[i]);
7691                         }
7692                       }
7693                     }
7694                   }
7695 #ifdef JJF_ZERO
7696                   // See if sos so we can fix
7697                   OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver);
7698                   if (osiclp && osiclp->numberSOS()) {
7699                     // SOS
7700                     numberSOS = osiclp->numberSOS();
7701                     const CoinSet *setInfo = osiclp->setInfo();
7702                     int i;
7703                     for (i = 0; i < numberSOS; i++) {
7704                       int type = setInfo[i].setType();
7705                       int n = setInfo[i].numberEntries();
7706                       const int *which = setInfo[i].which();
7707                       int first = -1;
7708                       int last = -1;
7709                       for (int j = 0; j < n; j++) {
7710                         int iColumn = which[j];
7711                         if (fabs(solution[iColumn]) > 1.0e-7) {
7712                           last = j;
7713                           if (first < 0)
7714                             first = j;
7715                         }
7716                       }
7717                       assert(last - first < type);
7718                       for (int j = 0; j < n; j++) {
7719                         if (j < first || j > last) {
7720                           int iColumn = which[j];
7721                           saveSolver->setColLower(iColumn, 0.0);
7722                           saveSolver->setColUpper(iColumn, 0.0);
7723                         }
7724                       }
7725                     }
7726                   }
7727 #endif
7728                   delete[] lower2;
7729                   delete[] upper2;
7730                   if (numberChanged) {
7731                     sprintf(generalPrint, "%d bounds tightened after postprocessing\n",
7732                       numberChanged);
7733                     generalMessageHandler->message(CLP_GENERAL, generalMessages)
7734                       << generalPrint
7735                       << CoinMessageEol;
7736                   }
7737                   saveSolver->resolve();
7738                   if (!saveSolver->isProvenOptimal()) {
7739                     // try all slack
7740                     CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart());
7741                     saveSolver->setWarmStart(basis);
7742                     delete basis;
7743                     saveSolver->initialSolve();
7744 #ifdef COIN_DEVELOP
7745                     saveSolver->writeMps("inf2");
7746 #endif
7747                     OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver);
7748                     if (osiclp)
7749                       osiclp->getModelPtr()->checkUnscaledSolution();
7750                   }
7751 
7752                   //assert(saveSolver->isProvenOptimal());
7753 #ifndef CBC_OTHER_SOLVER
7754                   // and original solver
7755                   originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
7756                   assert(n >= originalSolver->getNumCols());
7757                   n = originalSolver->getNumCols();
7758                   originalSolver->setColLower(saveSolver->getColLower());
7759                   originalSolver->setColUpper(saveSolver->getColUpper());
7760                   // basis
7761                   CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart());
7762                   originalSolver->setBasis(*basis);
7763                   delete basis;
7764                   originalSolver->resolve();
7765                   if (!originalSolver->isProvenOptimal()) {
7766                     // try all slack
7767                     CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart());
7768                     originalSolver->setBasis(*basis);
7769                     delete basis;
7770                     originalSolver->initialSolve();
7771                     OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(originalSolver);
7772                     if (osiclp)
7773                       osiclp->getModelPtr()->checkUnscaledSolution();
7774                   }
7775                   //assert(originalSolver->isProvenOptimal());
7776 #endif
7777                   babModel_->assignSolver(saveSolver);
7778                   memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double));
7779                 } else {
7780                   n = babModel_->solver()->getNumCols();
7781                   bestSolution = new double[n];
7782                   memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double));
7783                 }
7784                 if (returnMode == 1 && model_.numberSavedSolutions() < 2) {
7785                   model_.deleteSolutions();
7786                   model_.setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue());
7787                 }
7788                 babModel_->deleteSolutions();
7789                 babModel_->setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue());
7790 #ifndef CBC_OTHER_SOLVER
7791                 // and put back in very original solver
7792                 {
7793                   ClpSimplex *original = originalSolver->getModelPtr();
7794                   double *lower = original->columnLower();
7795                   double *upper = original->columnUpper();
7796                   double *solution = original->primalColumnSolution();
7797                   int n = original->numberColumns();
7798                   //assert (!n||n==babModel_->solver()->getNumCols());
7799                   for (int i = 0; i < n; i++) {
7800                     solution[i] = bestSolution[i];
7801                     if (originalSolver->isInteger(i)) {
7802                       lower[i] = solution[i];
7803                       upper[i] = solution[i];
7804                     }
7805                   }
7806                   // basis
7807                   CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart());
7808                   originalSolver->setBasis(*basis);
7809                   delete basis;
7810                   originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
7811 		  originalSolver->setHintParam(OsiDoPresolveInResolve, true, OsiHintTry);
7812                   originalSolver->resolve();
7813                   if (!originalSolver->isProvenOptimal()) {
7814                     // try all slack
7815                     CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart());
7816                     originalSolver->setBasis(*basis);
7817                     delete basis;
7818                     originalSolver->initialSolve();
7819                     OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(originalSolver);
7820                     if (osiclp)
7821                       osiclp->getModelPtr()->checkUnscaledSolution();
7822 #ifdef CLP_INVESTIGATE
7823                     if (!originalSolver->isProvenOptimal()) {
7824                       if (saveSolver) {
7825                         printf("saveSolver and originalSolver matrices saved\n");
7826                         saveSolver->writeMps("infA");
7827                       } else {
7828                         printf("originalSolver matrix saved\n");
7829                         originalSolver->writeMps("infB");
7830                       }
7831                     }
7832 #endif
7833                   }
7834                   //assert(originalSolver->isProvenOptimal());
7835                 }
7836 #endif
7837                 checkSOS(babModel_, babModel_->solver());
7838               } else if (model_.bestSolution() && type == CBC_PARAM_ACTION_BAB && model_.getMinimizationObjValue() < 1.0e50 && preProcess) {
7839                 sprintf(generalPrint, "Restoring heuristic best solution of %g", model_.getMinimizationObjValue());
7840                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
7841                   << generalPrint
7842                   << CoinMessageEol;
7843                 int n = saveSolver->getNumCols();
7844                 bestSolution = new double[n];
7845                 // Put solution now back in saveSolver
7846                 saveSolver->setColSolution(model_.bestSolution());
7847                 babModel_->assignSolver(saveSolver);
7848                 saveSolver = NULL;
7849                 babModel_->setMinimizationObjValue(model_.getMinimizationObjValue());
7850                 memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double));
7851 #ifndef CBC_OTHER_SOLVER
7852                 // and put back in very original solver
7853                 {
7854                   ClpSimplex *original = originalSolver->getModelPtr();
7855                   double *lower = original->columnLower();
7856                   double *upper = original->columnUpper();
7857                   double *solution = original->primalColumnSolution();
7858                   int n = original->numberColumns();
7859                   //assert (!n||n==babModel_->solver()->getNumCols());
7860                   for (int i = 0; i < n; i++) {
7861                     solution[i] = bestSolution[i];
7862                     if (originalSolver->isInteger(i)) {
7863                       lower[i] = solution[i];
7864                       upper[i] = solution[i];
7865                     }
7866                   }
7867                   // basis
7868                   CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart());
7869                   originalSolver->setBasis(*basis);
7870                   delete basis;
7871                 }
7872 #endif
7873               }
7874 #ifndef CBC_OTHER_SOLVER
7875               //if (type==CBC_PARAM_ACTION_STRENGTHEN&&strengthenedModel)
7876               //clpSolver = dynamic_cast< OsiClpSolverInterface*> (strengthenedModel);
7877 #ifdef COIN_HAS_ASL
7878               else if (statusUserFunction_[0])
7879                 clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
7880 #endif
7881               lpSolver = clpSolver->getModelPtr();
7882               if (numberChanged) {
7883                 for (int i = 0; i < numberChanged; i++) {
7884                   int iColumn = changed[i];
7885                   clpSolver->setContinuous(iColumn);
7886                 }
7887                 delete[] changed;
7888               }
7889 #endif
7890               if (type == CBC_PARAM_ACTION_BAB) {
7891 #ifndef CBC_OTHER_SOLVER
7892                 //move best solution (should be there -- but ..)
7893                 int n = lpSolver->getNumCols();
7894                 if (bestSolution) {
7895                   memcpy(lpSolver->primalColumnSolution(), bestSolution, n * sizeof(double));
7896                   // now see what that does to row solution
7897                   int numberRows = lpSolver->numberRows();
7898                   double *rowSolution = lpSolver->primalRowSolution();
7899                   memset(rowSolution, 0, numberRows * sizeof(double));
7900                   lpSolver->clpMatrix()->times(1.0, bestSolution, rowSolution);
7901                   lpSolver->setObjectiveValue(babModel_->getObjValue());
7902                 }
7903                 if (debugFile == "create" && bestSolution) {
7904                   saveSolution(lpSolver, "debug.file");
7905                 }
7906 #else
7907                 if (bestSolution) {
7908                   model_.solver()->setColSolution(bestSolution);
7909                 }
7910 #endif
7911                 delete saveSolver;
7912                 delete[] bestSolution;
7913                 std::string statusName[] = { "", "Stopped on ", "Run abandoned", "", "", "User ctrl-c" };
7914                 std::string minor[] = { "Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "Problem proven infeasible" };
7915                 int iStat = babModel_->status();
7916                 int iStat2 = babModel_->secondaryStatus();
7917                 if (!iStat && !iStat2 && !bestSolution)
7918                   iStat2 = 8;
7919                 if (!iStat && iStat2 == 1 && bestSolution)
7920                   iStat2 = 0; // solution and search completed
7921                 statistics_seconds = time2 - time1;
7922                 statistics_sys_seconds = CoinSysTime();
7923                 statistics_elapsed_seconds = CoinWallclockTime();
7924                 statistics_obj = babModel_->getObjValue();
7925                 statistics_continuous = babModel_->getContinuousObjective();
7926                 statistics_tighter = babModel_->rootObjectiveAfterCuts();
7927                 statistics_nodes = babModel_->getNodeCount();
7928                 statistics_iterations = babModel_->getIterationCount();
7929                 ;
7930                 statistics_result = statusName[iStat];
7931                 ;
7932                 if (!noPrinting_) {
7933                   sprintf(generalPrint, "\nResult - %s%s\n",
7934                     statusName[iStat].c_str(),
7935                     minor[iStat2].c_str());
7936                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
7937                     << generalPrint
7938                     << CoinMessageEol;
7939                   if (babModel_->bestSolution()) {
7940                     sprintf(generalPrint,
7941                       "Objective value:                %.8f\n",
7942                       babModel_->getObjValue());
7943                   } else {
7944                     sprintf(generalPrint,
7945                       "No feasible solution found\n");
7946                   }
7947                   if (iStat2 >= 2 && iStat2 <= 6) {
7948                     bool minimizing = babModel_->solver()->getObjSense() > 0.0;
7949                     sprintf(generalPrint + strlen(generalPrint),
7950                       "%s bound:                    %.3f\n",
7951                       minimizing ? "Lower" : "Upper",
7952                       babModel_->getBestPossibleObjValue());
7953                     if (babModel_->bestSolution()) {
7954                       sprintf(generalPrint + strlen(generalPrint),
7955                         "Gap:                            %.2f\n",
7956                         (babModel_->getObjValue() - babModel_->getBestPossibleObjValue()) / fabs(babModel_->getBestPossibleObjValue()));
7957                     }
7958                   }
7959                   sprintf(generalPrint + strlen(generalPrint),
7960                     "Enumerated nodes:               %d\n",
7961                     babModel_->getNodeCount());
7962                   sprintf(generalPrint + strlen(generalPrint),
7963                     "Total iterations:               %d\n",
7964                     babModel_->getIterationCount());
7965 #if CBC_QUIET == 0
7966                   sprintf(generalPrint + strlen(generalPrint),
7967                     "Time (CPU seconds):             %.2f\n",
7968                     CoinCpuTime() - time1);
7969                   sprintf(generalPrint + strlen(generalPrint),
7970                     "Time (Wallclock seconds):       %.2f\n",
7971                     CoinGetTimeOfDay() - time1Elapsed);
7972 #endif
7973                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
7974                     << generalPrint
7975                     << CoinMessageEol;
7976                 }
7977                 int returnCode = 0;
7978                 if (callBack != NULL)
7979                   returnCode = callBack(babModel_, 5);
7980                 if (returnCode) {
7981                   // exit if user wants
7982                   model_.moveInfo(*babModel_);
7983                   delete babModel_;
7984                   babModel_ = NULL;
7985                   return returnCode;
7986                 }
7987 #ifdef COIN_HAS_ASL
7988                 if (statusUserFunction_[0]) {
7989                   clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
7990                   lpSolver = clpSolver->getModelPtr();
7991                   double value = babModel_->getObjValue() * lpSolver->getObjSense();
7992                   char buf[300];
7993                   int pos = 0;
7994                   if (iStat == 0) {
7995                     if (babModel_->getObjValue() < 1.0e40) {
7996                       pos += sprintf(buf + pos, "optimal,");
7997                     } else {
7998                       // infeasible
7999                       iStat = 1;
8000                       pos += sprintf(buf + pos, "infeasible,");
8001                     }
8002                   } else if (iStat == 1) {
8003                     if (iStat2 != 6)
8004                       iStat = 3;
8005                     else
8006                       iStat = 4;
8007                     pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str());
8008                   } else if (iStat == 2) {
8009                     iStat = 7;
8010                     pos += sprintf(buf + pos, "stopped on difficulties,");
8011                   } else if (iStat == 5) {
8012                     iStat = 3;
8013                     pos += sprintf(buf + pos, "stopped on ctrl-c,");
8014                   } else {
8015                     pos += sprintf(buf + pos, "status unknown,");
8016                     iStat = 6;
8017                   }
8018                   info.problemStatus = iStat;
8019                   info.objValue = value;
8020                   if (babModel_->getObjValue() < 1.0e40) {
8021                     int precision = ampl_obj_prec();
8022                     if (precision > 0)
8023                       pos += sprintf(buf + pos, " objective %.*g", precision,
8024                         value);
8025                     else
8026                       pos += sprintf(buf + pos, " objective %g", value);
8027                   }
8028                   sprintf(buf + pos, "\n%d nodes, %d iterations, %g seconds",
8029                     babModel_->getNodeCount(),
8030                     babModel_->getIterationCount(),
8031                     totalTime);
8032                   if (bestSolution) {
8033                     free(info.primalSolution);
8034                     if (!numberKnapsack) {
8035                       info.primalSolution = (double *)malloc(n * sizeof(double));
8036                       CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution);
8037                       int numberRows = lpSolver->numberRows();
8038                       free(info.dualSolution);
8039                       info.dualSolution = (double *)malloc(numberRows * sizeof(double));
8040                       CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution);
8041                     } else {
8042                       // expanded knapsack
8043                       info.dualSolution = NULL;
8044                       int numberColumns = saveCoinModel.numberColumns();
8045                       info.primalSolution = (double *)malloc(numberColumns * sizeof(double));
8046                       // Fills in original solution (coinModel length)
8047                       afterKnapsack(saveTightenedModel, whichColumn, knapsackStart,
8048                         knapsackRow, numberKnapsack,
8049                         lpSolver->primalColumnSolution(), info.primalSolution, 1);
8050                     }
8051                   } else {
8052                     info.primalSolution = NULL;
8053                     info.dualSolution = NULL;
8054                   }
8055                   // put buffer into info
8056                   strcpy(info.buffer, buf);
8057                 }
8058 #endif
8059               } else {
8060                 sprintf(generalPrint, "Model strengthened - now has %d rows",
8061                   clpSolver->getNumRows());
8062                 printGeneralMessage(model_, generalPrint);
8063               }
8064               time1 = time2;
8065 #ifdef COIN_HAS_ASL
8066               if (statusUserFunction_[0]) {
8067                 // keep if going to be destroyed
8068                 OsiSolverInterface *solver = babModel_->solver();
8069                 OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
8070                 ClpSimplex *lpSolver2 = clpSolver->getModelPtr();
8071                 if (lpSolver == lpSolver2)
8072                   babModel_->setModelOwnsSolver(false);
8073               }
8074 #endif
8075               //delete babModel_;
8076               //babModel_=NULL;
8077             } else {
8078               sprintf(generalPrint, "** Current model not valid");
8079               printGeneralMessage(model_, generalPrint);
8080             }
8081             break;
8082           case CLP_PARAM_ACTION_IMPORT: {
8083 #ifdef COIN_HAS_ASL
8084             if (!statusUserFunction_[0]) {
8085 #endif
8086               free(priorities);
8087               priorities = NULL;
8088               free(branchDirection);
8089               branchDirection = NULL;
8090               free(pseudoDown);
8091               pseudoDown = NULL;
8092               free(pseudoUp);
8093               pseudoUp = NULL;
8094               free(solutionIn);
8095               solutionIn = NULL;
8096               free(prioritiesIn);
8097               prioritiesIn = NULL;
8098               free(sosStart);
8099               sosStart = NULL;
8100               free(sosIndices);
8101               sosIndices = NULL;
8102               free(sosType);
8103               sosType = NULL;
8104               free(sosReference);
8105               sosReference = NULL;
8106               free(cut);
8107               cut = NULL;
8108               free(sosPriority);
8109               sosPriority = NULL;
8110 #ifdef COIN_HAS_ASL
8111             }
8112 #endif
8113             //delete babModel_;
8114             //babModel_=NULL;
8115             // get next field
8116             field = CoinReadGetString(argc, argv);
8117             if (field == "$") {
8118               field = parameters_[iParam].stringValue();
8119             } else if (field == "EOL") {
8120               parameters_[iParam].printString();
8121               break;
8122             } else {
8123               parameters_[iParam].setStringValue(field);
8124             }
8125             std::string fileName;
8126             bool canOpen = false;
8127             // See if gmpl file
8128             int gmpl = 0;
8129             std::string gmplData;
8130             if (field == "-" || field == "stdin") {
8131               // stdin
8132               canOpen = true;
8133               fileName = "-";
8134             } else if (field == "-lp" || field == "stdin_lp") {
8135               // stdin
8136               canOpen = true;
8137               fileName = "-";
8138               gmpl = -1; //.lp format
8139             } else {
8140               // See if .lp
8141               {
8142                 const char *c_name = field.c_str();
8143                 size_t length = strlen(c_name);
8144                 if ((length > 3 && !strncmp(c_name + length - 3, ".lp", 3)) || (length > 6 && !strncmp(c_name + length - 6, ".lp.gz", 6)) || (length > 7 && !strncmp(c_name + length - 7, ".lp.bz2", 7)))
8145                   gmpl = -1; // .lp
8146               }
8147               bool absolutePath;
8148               if (dirsep == '/') {
8149                 // non Windows (or cygwin)
8150                 absolutePath = (field[0] == '/');
8151               } else {
8152                 //Windows (non cycgwin)
8153                 absolutePath = (field[0] == '\\');
8154                 // but allow for :
8155                 if (strchr(field.c_str(), ':'))
8156                   absolutePath = true;
8157               }
8158               if (absolutePath) {
8159                 fileName = field;
8160                 size_t length = field.size();
8161                 size_t percent = field.find('%');
8162                 if (percent < length && percent > 0) {
8163                   gmpl = 1;
8164                   fileName = field.substr(0, percent);
8165                   gmplData = field.substr(percent + 1);
8166                   if (percent < length - 1)
8167                     gmpl = 2; // two files
8168                   printf("GMPL model file %s and data file %s\n",
8169                     fileName.c_str(), gmplData.c_str());
8170                 }
8171               } else if (field[0] == '~') {
8172                 char *environVar = getenv("HOME");
8173                 if (environVar) {
8174                   std::string home(environVar);
8175                   field = field.erase(0, 1);
8176                   fileName = home + field;
8177                 } else {
8178                   fileName = field;
8179                 }
8180               } else {
8181                 fileName = directory + field;
8182                 // See if gmpl (model & data) - or even lp file
8183                 size_t length = field.size();
8184                 size_t percent = field.find('%');
8185                 if (percent < length && percent > 0) {
8186                   gmpl = 1;
8187                   fileName = directory + field.substr(0, percent);
8188                   gmplData = directory + field.substr(percent + 1);
8189                   if (percent < length - 1)
8190                     gmpl = 2; // two files
8191                   printf("GMPL model file %s and data file %s\n",
8192                     fileName.c_str(), gmplData.c_str());
8193                 }
8194               }
8195               std::string name = fileName;
8196               if (fileCoinReadable(name)) {
8197                 // can open - lets go for it
8198                 canOpen = true;
8199                 if (gmpl == 2) {
8200                   FILE *fp;
8201                   fp = fopen(gmplData.c_str(), "r");
8202                   if (fp) {
8203                     fclose(fp);
8204                   } else {
8205                     canOpen = false;
8206                     sprintf(generalPrint, "Unable to open file %s", gmplData.c_str());
8207                     printGeneralMessage(model_, generalPrint);
8208                   }
8209                 }
8210               } else {
8211                 sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
8212                 printGeneralMessage(model_, generalPrint);
8213               }
8214             }
8215             if (canOpen) {
8216               int status;
8217               numberLotSizing = 0;
8218               delete[] lotsize;
8219 #ifndef CBC_OTHER_SOLVER
8220               ClpSimplex *lpSolver = clpSolver->getModelPtr();
8221               if (!gmpl) {
8222                 status = clpSolver->readMps(fileName.c_str(),
8223                   keepImportNames != 0,
8224                   allowImportErrors != 0);
8225               } else if (gmpl > 0) {
8226                 status = lpSolver->readGMPL(fileName.c_str(),
8227                   (gmpl == 2) ? gmplData.c_str() : NULL,
8228                   keepImportNames != 0);
8229               } else {
8230 #ifdef KILL_ZERO_READLP
8231                 status = clpSolver->readLp(fileName.c_str(), lpSolver->getSmallElementValue());
8232 #else
8233                 status = clpSolver->readLp(fileName.c_str(), 1.0e-12);
8234 #endif
8235               }
8236 #else
8237               status = clpSolver->readMps(fileName.c_str(), "");
8238 #endif
8239               if (!status || (status > 0 && allowImportErrors)) {
8240 #ifndef CBC_OTHER_SOLVER
8241                 if (keepImportNames) {
8242                   lengthName = lpSolver->lengthNames();
8243                   rowNames = *(lpSolver->rowNames());
8244                   columnNames = *(lpSolver->columnNames());
8245                 } else {
8246                   lengthName = 0;
8247                 }
8248                 goodModel = true;
8249                 // sets to all slack (not necessary?)
8250                 lpSolver->createStatus();
8251                 // See if sos
8252                 if (clpSolver->numberSOS()) {
8253                   // SOS
8254                   numberSOS = clpSolver->numberSOS();
8255                   const CoinSet *setInfo = clpSolver->setInfo();
8256                   sosStart = reinterpret_cast< int * >(malloc((numberSOS + 1) * sizeof(int)));
8257                   sosType = reinterpret_cast< char * >(malloc(numberSOS * sizeof(char)));
8258                   const double *lower = clpSolver->getColLower();
8259                   const double *upper = clpSolver->getColUpper();
8260                   int i;
8261                   int nTotal = 0;
8262                   sosStart[0] = 0;
8263                   for (i = 0; i < numberSOS; i++) {
8264                     int type = setInfo[i].setType();
8265                     int n = setInfo[i].numberEntries();
8266                     sosType[i] = static_cast< char >(type);
8267                     nTotal += n;
8268                     sosStart[i + 1] = nTotal;
8269                   }
8270                   sosIndices = reinterpret_cast< int * >(malloc(nTotal * sizeof(int)));
8271                   sosReference = reinterpret_cast< double * >(malloc(nTotal * sizeof(double)));
8272                   for (i = 0; i < numberSOS; i++) {
8273                     int n = setInfo[i].numberEntries();
8274                     const int *which = setInfo[i].which();
8275                     const double *weights = setInfo[i].weights();
8276                     int base = sosStart[i];
8277                     for (int j = 0; j < n; j++) {
8278                       int k = which[j];
8279                       // don't allow free
8280                       if (upper[k] > 1.0e15)
8281                         clpSolver->setColUpper(k, 1.0e15);
8282                       if (lower[k] < -1.0e15)
8283                         clpSolver->setColLower(k, -1.0e15);
8284                       sosIndices[j + base] = k;
8285                       sosReference[j + base] = weights ? weights[j] : static_cast< double >(j);
8286                     }
8287                   }
8288                 }
8289                 // make sure integer
8290                 // also deal with semi-continuous
8291                 int numberColumns = lpSolver->numberColumns();
8292                 int i;
8293                 for (i = 0; i < numberColumns; i++) {
8294                   if (clpSolver->integerType(i) > 2)
8295                     break;
8296                   if (lpSolver->isInteger(i))
8297                     clpSolver->setInteger(i);
8298                 }
8299                 if (i < numberColumns) {
8300                   // semi-continuous
8301                   clpSolver->setSpecialOptions(clpSolver->specialOptions() | 8388608);
8302                   int iStart = i;
8303                   for (i = iStart; i < numberColumns; i++) {
8304                     if (clpSolver->integerType(i) > 2)
8305                       numberLotSizing++;
8306                   }
8307                   lotsize = new lotStruct[numberLotSizing];
8308                   numberLotSizing = 0;
8309                   const double *lower = clpSolver->getColLower();
8310                   const double *upper = clpSolver->getColUpper();
8311                   for (i = iStart; i < numberColumns; i++) {
8312                     if (clpSolver->integerType(i) > 2) {
8313                       int iType = clpSolver->integerType(i) - 3;
8314                       if (!iType)
8315                         clpSolver->setContinuous(i);
8316                       else
8317                         clpSolver->setInteger(i);
8318                       lotsize[numberLotSizing].column = i;
8319                       lotsize[numberLotSizing].high = upper[i];
8320                       if (lower[i]) {
8321                         lotsize[numberLotSizing++].low = lower[i];
8322                         clpSolver->setColLower(i, 0.0);
8323                       } else {
8324                         lotsize[numberLotSizing++].low = 1.0;
8325                       }
8326                     }
8327                   }
8328                 }
8329 #else
8330                 lengthName = 0;
8331                 goodModel = true;
8332 #endif
8333                 time2 = CoinCpuTime();
8334                 totalTime += time2 - time1;
8335                 time1 = time2;
8336                 // Go to canned file if just input file
8337                 if (CbcOrClpRead_mode == 2 && argc == 2) {
8338                   // only if ends .mps
8339                   char *find = const_cast< char * >(strstr(fileName.c_str(), ".mps"));
8340                   if (find && find[4] == '\0') {
8341                     find[1] = 'p';
8342                     find[2] = 'a';
8343                     find[3] = 'r';
8344                     FILE *fp = fopen(fileName.c_str(), "r");
8345                     if (fp) {
8346                       CbcOrClpReadCommand = fp; // Read from that file
8347                       CbcOrClpRead_mode = -1;
8348                     }
8349                   }
8350                 }
8351               } else {
8352                 // errors
8353                 sprintf(generalPrint, "There were %d errors on input", status);
8354                 printGeneralMessage(model_, generalPrint);
8355               }
8356             }
8357           } break;
8358           case CLP_PARAM_ACTION_MODELIN:
8359 #ifndef CBC_OTHER_SOLVER
8360 #ifdef COIN_HAS_LINK
8361           {
8362             // get next field
8363             field = CoinReadGetString(argc, argv);
8364             if (field == "$") {
8365               field = parameters_[iParam].stringValue();
8366             } else if (field == "EOL") {
8367               parameters_[iParam].printString();
8368               break;
8369             } else {
8370               parameters_[iParam].setStringValue(field);
8371             }
8372             std::string fileName;
8373             bool canOpen = false;
8374             if (field == "-") {
8375               // stdin
8376               canOpen = true;
8377               fileName = "-";
8378             } else {
8379               bool absolutePath;
8380               if (dirsep == '/') {
8381                 // non Windows (or cygwin)
8382                 absolutePath = (field[0] == '/');
8383               } else {
8384                 //Windows (non cycgwin)
8385                 absolutePath = (field[0] == '\\');
8386                 // but allow for :
8387                 if (strchr(field.c_str(), ':'))
8388                   absolutePath = true;
8389               }
8390               if (absolutePath) {
8391                 fileName = field;
8392               } else if (field[0] == '~') {
8393                 char *environVar = getenv("HOME");
8394                 if (environVar) {
8395                   std::string home(environVar);
8396                   field = field.erase(0, 1);
8397                   fileName = home + field;
8398                 } else {
8399                   fileName = field;
8400                 }
8401               } else {
8402                 fileName = directory + field;
8403               }
8404               FILE *fp = fopen(fileName.c_str(), "r");
8405               if (fp) {
8406                 // can open - lets go for it
8407                 fclose(fp);
8408                 canOpen = true;
8409               } else {
8410                 sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
8411                 printGeneralMessage(model_, generalPrint);
8412               }
8413             }
8414             if (canOpen) {
8415               CoinModel coinModel(fileName.c_str(), 2);
8416               // load from coin model
8417               OsiSolverLink solver1;
8418               OsiSolverInterface *solver2 = solver1.clone();
8419               model_.assignSolver(solver2, false);
8420               OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver());
8421               assert(si != NULL);
8422               si->setDefaultMeshSize(0.001);
8423               // need some relative granularity
8424               si->setDefaultBound(100.0);
8425               double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue();
8426               if (dextra3)
8427                 si->setDefaultMeshSize(dextra3);
8428               si->setDefaultBound(100.0);
8429               si->setIntegerPriority(1000);
8430               si->setBiLinearPriority(10000);
8431               CoinModel *model2 = &coinModel;
8432               si->load(*model2);
8433               // redo
8434               solver = model_.solver();
8435               clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
8436               lpSolver = clpSolver->getModelPtr();
8437               clpSolver->messageHandler()->setLogLevel(0);
8438               testOsiParameters = 0;
8439               complicatedInteger = 2;
8440             }
8441           }
8442 #endif
8443 #endif
8444           break;
8445           case CLP_PARAM_ACTION_EXPORT:
8446             if (goodModel) {
8447               // get next field
8448               field = CoinReadGetString(argc, argv);
8449               if (field == "$") {
8450                 field = parameters_[iParam].stringValue();
8451               } else if (field == "EOL") {
8452                 parameters_[iParam].printString();
8453                 break;
8454               } else {
8455                 parameters_[iParam].setStringValue(field);
8456               }
8457               std::string fileName;
8458               bool canOpen = false;
8459               if (field[0] == '/' || field[0] == '\\') {
8460                 fileName = field;
8461               } else if (field[0] == '~') {
8462                 char *environVar = getenv("HOME");
8463                 if (environVar) {
8464                   std::string home(environVar);
8465                   field = field.erase(0, 1);
8466                   fileName = home + field;
8467                 } else {
8468                   fileName = field;
8469                 }
8470               } else {
8471                 fileName = directory + field;
8472               }
8473               FILE *fp = fopen(fileName.c_str(), "w");
8474               if (fp) {
8475                 // can open - lets go for it
8476                 fclose(fp);
8477                 canOpen = true;
8478               } else {
8479                 sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
8480                 printGeneralMessage(model_, generalPrint);
8481               }
8482               if (canOpen) {
8483                 // If presolve on then save presolved
8484                 bool deleteModel2 = false;
8485                 ClpSimplex *model2 = lpSolver;
8486                 if (dualize && dualize < 3) {
8487                   model2 = static_cast< ClpSimplexOther * >(model2)->dualOfModel();
8488                   sprintf(generalPrint, "Dual of model has %d rows and %d columns",
8489                     model2->numberRows(), model2->numberColumns());
8490                   generalMessageHandler->message(CLP_GENERAL, generalMessages)
8491                     << generalPrint
8492                     << CoinMessageEol;
8493                   model2->setOptimizationDirection(1.0);
8494                 }
8495 #ifndef CBC_OTHER_SOLVER
8496 #ifdef COIN_HAS_ASL
8497                 if (info.numberSos && doSOS && statusUserFunction_[0]) {
8498                   // SOS
8499                   numberSOS = info.numberSos;
8500                   sosStart = info.sosStart;
8501                   sosIndices = info.sosIndices;
8502                   sosReference = info.sosReference;
8503                   clpSolver->setSOSData(numberSOS, info.sosType, sosStart, sosIndices, sosReference);
8504                 }
8505 #endif
8506                 numberSOS = clpSolver->numberSOS();
8507                 if (numberSOS || lotsize)
8508                   preSolve = false;
8509 #endif
8510                 if (preSolve) {
8511                   ClpPresolve pinfo;
8512                   int presolveOptions2 = presolveOptions & ~0x40000000;
8513                   if ((presolveOptions2 & 0xffff) != 0)
8514                     pinfo.setPresolveActions(presolveOptions2);
8515                   if ((printOptions & 1) != 0)
8516                     pinfo.statistics();
8517                   double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue();
8518                   model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance,
8519                     true, preSolve);
8520                   if (model2) {
8521                     printf("Saving presolved model on %s\n",
8522                       fileName.c_str());
8523                     deleteModel2 = true;
8524                   } else {
8525                     printf("Presolved model looks infeasible - saving original on %s\n",
8526                       fileName.c_str());
8527                     deleteModel2 = false;
8528                     model2 = lpSolver;
8529                   }
8530                   // see if extension lp
8531                   bool writeLp = false;
8532                   {
8533                     int lengthName = strlen(fileName.c_str());
8534                     if (lengthName > 3 && !strcmp(fileName.c_str() + lengthName - 3, ".lp"))
8535                       writeLp = true;
8536                   }
8537                   if (!writeLp) {
8538                     model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1));
8539                   } else {
8540                     FILE *fp = fopen(fileName.c_str(), "w");
8541                     assert(fp);
8542                     OsiClpSolverInterface solver(model2);
8543                     solver.writeLp(fp, 1.0e-12);
8544                   }
8545                   if (deleteModel2)
8546                     delete model2;
8547                 } else {
8548                   printf("Saving model on %s\n",
8549                     fileName.c_str());
8550 #ifdef COIN_HAS_LINK
8551                   OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(clpSolver);
8552                   if (!linkSolver || !linkSolver->quadraticModel()) {
8553 #endif
8554                     // Convert names
8555                     int iRow;
8556                     int numberRows = model2->numberRows();
8557                     int iColumn;
8558                     int numberColumns = model2->numberColumns();
8559 
8560                     char **rowNames = NULL;
8561                     char **columnNames = NULL;
8562                     if (model2->lengthNames()) {
8563                       rowNames = new char *[numberRows];
8564                       for (iRow = 0; iRow < numberRows; iRow++) {
8565                         rowNames[iRow] = CoinStrdup(model2->rowName(iRow).c_str());
8566                       }
8567 
8568                       columnNames = new char *[numberColumns];
8569                       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
8570                         columnNames[iColumn] = CoinStrdup(model2->columnName(iColumn).c_str());
8571                       }
8572                     }
8573                     // see if extension lp
8574                     bool writeLp = false;
8575                     {
8576                       int lengthName = strlen(fileName.c_str());
8577                       if (lengthName > 3 && !strcmp(fileName.c_str() + lengthName - 3, ".lp"))
8578                         writeLp = true;
8579                     }
8580                     if (lotsize) {
8581                       for (int i = 0; i < numberLotSizing; i++) {
8582                         int iColumn = lotsize[i].column;
8583                         double low = lotsize[i].low;
8584                         if (low != 1.0)
8585                           clpSolver->setColLower(iColumn, low);
8586                         int type;
8587                         if (clpSolver->isInteger(iColumn))
8588                           type = 4;
8589                         else
8590                           type = 3;
8591                         clpSolver->setColumnType(iColumn, type);
8592                       }
8593                     }
8594                     if (!writeLp) {
8595                       remove(fileName.c_str());
8596                       //model_.addSOSEtcToSolver();
8597                       clpSolver->writeMpsNative(fileName.c_str(), const_cast< const char ** >(rowNames), const_cast< const char ** >(columnNames),
8598                         (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1));
8599                     } else {
8600                       FILE *fp = fopen(fileName.c_str(), "w");
8601                       assert(fp);
8602                       clpSolver->writeLp(fp, 1.0e-12);
8603                     }
8604                     if (rowNames) {
8605                       for (iRow = 0; iRow < numberRows; iRow++) {
8606                         free(rowNames[iRow]);
8607                       }
8608                       delete[] rowNames;
8609                       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
8610                         free(columnNames[iColumn]);
8611                       }
8612                       delete[] columnNames;
8613                     }
8614                     if (lotsize) {
8615                       for (int i = 0; i < numberLotSizing; i++) {
8616                         int iColumn = lotsize[i].column;
8617                         int itype = clpSolver->integerType(iColumn);
8618                         clpSolver->setColLower(iColumn, 0.0);
8619                         if (itype == 3)
8620                           clpSolver->setContinuous(iColumn);
8621                         else
8622                           clpSolver->setInteger(iColumn);
8623                       }
8624                     }
8625 #ifdef COIN_HAS_LINK
8626                   } else {
8627                     linkSolver->quadraticModel()->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1));
8628                   }
8629 #endif
8630                 }
8631                 time2 = CoinCpuTime();
8632                 totalTime += time2 - time1;
8633                 time1 = time2;
8634               }
8635             } else {
8636               sprintf(generalPrint, "** Current model not valid");
8637               printGeneralMessage(model_, generalPrint);
8638             }
8639             break;
8640           case CLP_PARAM_ACTION_BASISIN:
8641             if (goodModel) {
8642               // get next field
8643               field = CoinReadGetString(argc, argv);
8644               if (field == "$") {
8645                 field = parameters_[iParam].stringValue();
8646               } else if (field == "EOL") {
8647                 parameters_[iParam].printString();
8648                 break;
8649               } else {
8650                 parameters_[iParam].setStringValue(field);
8651               }
8652               std::string fileName;
8653               bool canOpen = false;
8654               if (field == "-") {
8655                 // stdin
8656                 canOpen = true;
8657                 fileName = "-";
8658               } else {
8659                 if (field[0] == '/' || field[0] == '\\') {
8660                   fileName = field;
8661                 } else if (field[0] == '~') {
8662                   char *environVar = getenv("HOME");
8663                   if (environVar) {
8664                     std::string home(environVar);
8665                     field = field.erase(0, 1);
8666                     fileName = home + field;
8667                   } else {
8668                     fileName = field;
8669                   }
8670                 } else {
8671                   fileName = directory + field;
8672                 }
8673                 FILE *fp = fopen(fileName.c_str(), "r");
8674                 if (fp) {
8675                   // can open - lets go for it
8676                   fclose(fp);
8677                   canOpen = true;
8678                 } else {
8679                   sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
8680                   printGeneralMessage(model_, generalPrint);
8681                 }
8682               }
8683               if (canOpen) {
8684 #ifndef CBC_OTHER_SOLVER
8685                 int values = lpSolver->readBasis(fileName.c_str());
8686                 if (values == 0)
8687                   basisHasValues = -1;
8688                 else
8689                   basisHasValues = 1;
8690                 assert(lpSolver == clpSolver->getModelPtr());
8691                 clpSolver->setWarmStart(NULL);
8692 #endif
8693               }
8694             } else {
8695               sprintf(generalPrint, "** Current model not valid");
8696               printGeneralMessage(model_, generalPrint);
8697             }
8698             break;
8699           case CBC_PARAM_ACTION_PRIORITYIN:
8700             if (goodModel) {
8701               // get next field
8702               field = CoinReadGetString(argc, argv);
8703               if (field == "$") {
8704                 field = parameters_[iParam].stringValue();
8705               } else if (field == "EOL") {
8706                 parameters_[iParam].printString();
8707                 break;
8708               } else {
8709                 parameters_[iParam].setStringValue(field);
8710               }
8711               std::string fileName;
8712               if (field[0] == '/' || field[0] == '\\') {
8713                 fileName = field;
8714               } else if (field[0] == '~') {
8715                 char *environVar = getenv("HOME");
8716                 if (environVar) {
8717                   std::string home(environVar);
8718                   field = field.erase(0, 1);
8719                   fileName = home + field;
8720                 } else {
8721                   fileName = field;
8722                 }
8723               } else {
8724                 fileName = directory + field;
8725               }
8726               FILE *fp = fopen(fileName.c_str(), "r");
8727               if (fp) {
8728                 // can open - lets go for it
8729                 std::string headings[] = { "name", "number", "direction", "priority", "up", "down",
8730                   "solution", "priin" };
8731                 int got[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
8732                 int order[8];
8733                 bool useMasks = false;
8734                 if (strstr(fileName.c_str(), "mask_")) {
8735                   // look more closely
8736                   const char *name = fileName.c_str();
8737                   int length = strlen(name);
8738                   for (int i = length - 1; i >= 0; i--) {
8739                     if (name[i] == dirsep) {
8740                       name += i + 1;
8741                       break;
8742                     }
8743                   }
8744                   useMasks = !strncmp(name, "mask_", 5);
8745                 }
8746                 assert(sizeof(got) == sizeof(order));
8747                 int nAcross = 0;
8748                 char line[1000];
8749                 int numberColumns = lpSolver->numberColumns();
8750                 if (!fgets(line, 1000, fp)) {
8751                   std::cout << "Odd file " << fileName << std::endl;
8752                 } else {
8753                   char *pos = line;
8754                   char *put = line;
8755                   while (*pos >= ' ' && *pos != '\n') {
8756                     if (*pos != ' ' && *pos != '\t') {
8757                       *put = static_cast< char >(tolower(*pos));
8758                       put++;
8759                     }
8760                     pos++;
8761                   }
8762                   *put = '\0';
8763                   pos = line;
8764                   int i;
8765                   bool good = true;
8766                   while (pos) {
8767                     char *comma = strchr(pos, ',');
8768                     if (comma)
8769                       *comma = '\0';
8770                     for (i = 0; i < static_cast< int >(sizeof(got) / sizeof(int)); i++) {
8771                       if (headings[i] == pos) {
8772                         if (got[i] < 0) {
8773                           order[nAcross] = i;
8774                           got[i] = nAcross++;
8775                         } else {
8776                           // duplicate
8777                           good = false;
8778                         }
8779                         break;
8780                       }
8781                     }
8782                     if (i == static_cast< int >(sizeof(got) / sizeof(int)))
8783                       good = false;
8784                     if (comma) {
8785                       *comma = ',';
8786                       pos = comma + 1;
8787                     } else {
8788                       break;
8789                     }
8790                   }
8791                   if (got[0] < 0 && got[1] < 0)
8792                     good = false;
8793                   if (got[0] >= 0 && got[1] >= 0)
8794                     good = false;
8795                   if (got[0] >= 0 && !lpSolver->lengthNames())
8796                     good = false;
8797                   int numberFields = 99;
8798                   if (good && (strstr(fileName.c_str(), ".mst") || strstr(fileName.c_str(), ".MST") || strstr(fileName.c_str(), ".csv"))) {
8799                     numberFields = 0;
8800                     for (i = 2; i < static_cast< int >(sizeof(got) / sizeof(int)); i++) {
8801                       if (got[i] >= 0)
8802                         numberFields++;
8803                     }
8804                     if (!numberFields) {
8805                       // Like Cplex format
8806                       order[nAcross] = 6;
8807                       got[6] = nAcross++;
8808                     }
8809                   }
8810                   if (good) {
8811                     char **columnNames = new char *[numberColumns];
8812                     //pseudoDown = NULL;
8813                     //pseudoUp = NULL;
8814                     //branchDirection = NULL;
8815                     //if (got[5]!=-1)
8816                     pseudoDown = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double)));
8817                     //if (got[4]!=-1)
8818                     pseudoUp = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double)));
8819                     //if (got[2]!=-1)
8820                     branchDirection = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int)));
8821                     priorities = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int)));
8822                     free(solutionIn);
8823                     solutionIn = NULL;
8824                     free(prioritiesIn);
8825                     prioritiesIn = NULL;
8826                     int iColumn;
8827                     if (got[6] >= 0) {
8828                       solutionIn = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double)));
8829                       for (iColumn = 0; iColumn < numberColumns; iColumn++)
8830                         solutionIn[iColumn] = -COIN_DBL_MAX;
8831                     }
8832                     if (got[7] >= 0 || !numberFields) {
8833                       prioritiesIn = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int)));
8834                       for (iColumn = 0; iColumn < numberColumns; iColumn++)
8835                         prioritiesIn[iColumn] = 10000;
8836                     }
8837                     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
8838                       columnNames[iColumn] = CoinStrdup(lpSolver->columnName(iColumn).c_str());
8839                       //if (got[5]!=-1)
8840                       pseudoDown[iColumn] = 0.0;
8841                       //if (got[4]!=-1)
8842                       pseudoUp[iColumn] = 0.0;
8843                       //if (got[2]!=-1)
8844                       branchDirection[iColumn] = 0;
8845                       priorities[iColumn] = useMasks ? -123456789 : 0;
8846                     }
8847                     int nBadPseudo = 0;
8848                     int nBadDir = 0;
8849                     int nBadPri = 0;
8850                     int nBadName = 0;
8851                     int nBadLine = 0;
8852                     int nLine = 0;
8853                     iColumn = -1;
8854                     int lowestPriority = -COIN_INT_MAX;
8855                     bool needCard = true;
8856                     while (!needCard || fgets(line, 1000, fp)) {
8857                       if (!strncmp(line, "ENDATA", 6) || !strncmp(line, "endata", 6))
8858                         break;
8859                       nLine++;
8860                       if (!useMasks)
8861                         iColumn = -1;
8862                       else
8863                         needCard = false;
8864                       double up = 0.0;
8865                       double down = 0.0;
8866                       int pri = 0;
8867                       int dir = 0;
8868                       double solValue = COIN_DBL_MAX;
8869                       int priValue = 1000000;
8870                       char *pos = line;
8871                       char *put = line;
8872                       if (!numberFields) {
8873                         // put in ,
8874                         for (i = 4; i < 100; i++) {
8875                           if (line[i] == ' ' || line[i] == '\t') {
8876                             line[i] = ',';
8877                             break;
8878                           }
8879                         }
8880                       }
8881                       while (*pos >= ' ' && *pos != '\n') {
8882                         if (*pos != ' ' && *pos != '\t') {
8883                           *put = *pos;
8884                           put++;
8885                         }
8886                         pos++;
8887                       }
8888                       *put = '\0';
8889                       pos = line;
8890                       for (int i = 0; i < nAcross; i++) {
8891                         char *comma = strchr(pos, ',');
8892                         if (comma) {
8893                           *comma = '\0';
8894                         } else if (i < nAcross - 1) {
8895                           nBadLine++;
8896                           break;
8897                         }
8898                         switch (order[i]) {
8899                           // name
8900                         case 0:
8901                           iColumn++;
8902                           for (; iColumn < numberColumns; iColumn++) {
8903                             if (priorities[iColumn] != -123456789) {
8904                               if (!strcmp(columnNames[iColumn], pos))
8905                                 break;
8906                             } else {
8907                               // mask (at present ? and trailing *)
8908                               const char *name = columnNames[iColumn];
8909                               int length = strlen(name);
8910                               int lengthMask = strlen(pos);
8911                               bool asterisk = pos[lengthMask - 1] == '*';
8912                               if (asterisk)
8913                                 length = lengthMask - 1;
8914                               int i;
8915                               for (i = 0; i < length; i++) {
8916                                 if (name[i] != pos[i]) {
8917                                   if (pos[i] != '?')
8918                                     break;
8919                                 }
8920                               }
8921                               if (i == length)
8922                                 break;
8923                             }
8924                           }
8925                           if (iColumn == numberColumns) {
8926                             iColumn = -1;
8927                             needCard = true;
8928                           }
8929                           break;
8930                           // number
8931                         case 1:
8932                           iColumn = atoi(pos);
8933                           if (iColumn < 0 || iColumn >= numberColumns)
8934                             iColumn = -1;
8935                           break;
8936                           // direction
8937                         case 2:
8938                           if (*pos == 'D')
8939                             dir = -1;
8940                           else if (*pos == 'U')
8941                             dir = 1;
8942                           else if (*pos == 'N')
8943                             dir = 0;
8944                           else if (*pos == '1' && *(pos + 1) == '\0')
8945                             dir = 1;
8946                           else if (*pos == '0' && *(pos + 1) == '\0')
8947                             dir = 0;
8948                           else if (*pos == '1' && *(pos + 1) == '1' && *(pos + 2) == '\0')
8949                             dir = -1;
8950                           else
8951                             dir = -2; // bad
8952                           break;
8953                           // priority
8954                         case 3:
8955                           pri = atoi(pos);
8956                           lowestPriority = CoinMax(lowestPriority, pri);
8957                           break;
8958                           // up
8959                         case 4:
8960                           up = atof(pos);
8961                           break;
8962                           // down
8963                         case 5:
8964                           down = atof(pos);
8965                           break;
8966                           // sol value
8967                         case 6:
8968                           solValue = atof(pos);
8969                           break;
8970                           // priority in value
8971                         case 7:
8972                           priValue = atoi(pos);
8973                           break;
8974                         }
8975                         if (comma) {
8976                           *comma = ',';
8977                           pos = comma + 1;
8978                         }
8979                       }
8980                       if (iColumn >= 0) {
8981                         if (down < 0.0) {
8982                           nBadPseudo++;
8983                           down = 0.0;
8984                         }
8985                         if (up < 0.0) {
8986                           nBadPseudo++;
8987                           up = 0.0;
8988                         }
8989                         if (!up)
8990                           up = down;
8991                         if (!down)
8992                           down = up;
8993                         if (dir < -1 || dir > 1) {
8994                           nBadDir++;
8995                           dir = 0;
8996                         }
8997                         if (pri < 0) {
8998                           nBadPri++;
8999                           pri = 0;
9000                         }
9001                         //if (got[5]!=-1)
9002                         pseudoDown[iColumn] = down;
9003                         //if (got[4]!=-1)
9004                         pseudoUp[iColumn] = up;
9005                         //if (got[2]!=-1)
9006                         branchDirection[iColumn] = dir;
9007                         priorities[iColumn] = pri;
9008                         if (solValue != COIN_DBL_MAX) {
9009                           assert(solutionIn);
9010                           solutionIn[iColumn] = solValue;
9011                         }
9012                         if (priValue != 1000000) {
9013                           assert(prioritiesIn);
9014                           prioritiesIn[iColumn] = priValue;
9015                         }
9016                       } else if (!useMasks) {
9017                         nBadName++;
9018                       }
9019                     }
9020                     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
9021                       if (priorities[iColumn] == -123456789)
9022                         priorities[iColumn] = lowestPriority + 1;
9023                     }
9024                     if (!noPrinting_) {
9025                       printf("%d fields and %d records", nAcross, nLine);
9026                       if (nBadPseudo)
9027                         printf(" %d bad pseudo costs", nBadPseudo);
9028                       if (nBadDir)
9029                         printf(" %d bad directions", nBadDir);
9030                       if (nBadPri)
9031                         printf(" %d bad priorities", nBadPri);
9032                       if (nBadName)
9033                         printf(" ** %d records did not match on name/sequence", nBadName);
9034                       printf("\n");
9035                     }
9036                     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
9037                       free(columnNames[iColumn]);
9038                     }
9039                     delete[] columnNames;
9040                   } else {
9041                     std::cout << "Duplicate or unknown keyword - or name/number fields wrong" << line << std::endl;
9042                   }
9043                 }
9044                 fclose(fp);
9045               } else {
9046                 sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
9047                 printGeneralMessage(model_, generalPrint);
9048               }
9049             } else {
9050               sprintf(generalPrint, "** Current model not valid");
9051               printGeneralMessage(model_, generalPrint);
9052             }
9053             break;
9054           case CBC_PARAM_ACTION_MIPSTART:
9055             if (goodModel) {
9056               // get next field
9057               field = CoinReadGetString(argc, argv);
9058               if (field == "$") {
9059                 field = parameters_[iParam].stringValue();
9060               } else if (field == "EOL") {
9061                 parameters_[iParam].printString();
9062                 break;
9063               } else {
9064                 parameters_[iParam].setStringValue(field);
9065               }
9066               std::string fileName;
9067               if (field[0] == '/' || field[0] == '\\') {
9068                 fileName = field;
9069               } else if (field[0] == '~') {
9070                 char *environVar = getenv("HOME");
9071                 if (environVar) {
9072                   std::string home(environVar);
9073                   field = field.erase(0, 1);
9074                   fileName = home + field;
9075                 } else {
9076                   fileName = field;
9077                 }
9078               } else {
9079                 fileName = directory + field;
9080               }
9081               sprintf(generalPrint, "opening mipstart file %s.", fileName.c_str());
9082               generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol;
9083               double msObj;
9084               readMIPStart(&model_, fileName.c_str(), mipStart, msObj);
9085               // copy to before preprocess if has .before.
9086               if (strstr(fileName.c_str(), ".before.")) {
9087                 mipStartBefore = mipStart;
9088                 sprintf(generalPrint, "file %s will be used before preprocessing.", fileName.c_str());
9089                 generalMessageHandler->message(CLP_GENERAL, generalMessages)
9090                   << generalPrint
9091                   << CoinMessageEol;
9092               }
9093             } else {
9094               sprintf(generalPrint, "** Current model not valid");
9095               printGeneralMessage(model_, generalPrint);
9096             }
9097             break;
9098           case CLP_PARAM_ACTION_DEBUG:
9099             if (goodModel) {
9100               delete[] debugValues;
9101               debugValues = NULL;
9102               // get next field
9103               field = CoinReadGetString(argc, argv);
9104               if (field == "$") {
9105                 field = parameters_[iParam].stringValue();
9106               } else if (field == "EOL") {
9107                 parameters_[iParam].printString();
9108                 break;
9109               } else {
9110                 parameters_[iParam].setStringValue(field);
9111                 debugFile = field;
9112                 if (debugFile == "create" || debugFile == "createAfterPre") {
9113                   printf("Will create a debug file so this run should be a good one\n");
9114                   break;
9115                 }
9116               }
9117               std::string fileName;
9118               if (field[0] == '/' || field[0] == '\\') {
9119                 fileName = field;
9120               } else if (field[0] == '~') {
9121                 char *environVar = getenv("HOME");
9122                 if (environVar) {
9123                   std::string home(environVar);
9124                   field = field.erase(0, 1);
9125                   fileName = home + field;
9126                 } else {
9127                   fileName = field;
9128                 }
9129               } else {
9130                 fileName = directory + field;
9131               }
9132               FILE *fp = fopen(fileName.c_str(), "rb");
9133               if (fp) {
9134                 // can open - lets go for it
9135                 int numRows;
9136                 double obj;
9137                 size_t nRead;
9138                 nRead = fread(&numRows, sizeof(int), 1, fp);
9139                 if (nRead != 1)
9140                   throw("Error in fread");
9141                 nRead = fread(&numberDebugValues, sizeof(int), 1, fp);
9142                 if (nRead != 1)
9143                   throw("Error in fread");
9144                 nRead = fread(&obj, sizeof(double), 1, fp);
9145                 if (nRead != 1)
9146                   throw("Error in fread");
9147                 debugValues = new double[numberDebugValues + numRows];
9148                 nRead = fread(debugValues, sizeof(double), numRows, fp);
9149                 if (nRead != static_cast< size_t >(numRows))
9150                   throw("Error in fread");
9151                 nRead = fread(debugValues, sizeof(double), numRows, fp);
9152                 if (nRead != static_cast< size_t >(numRows))
9153                   throw("Error in fread");
9154                 nRead = fread(debugValues, sizeof(double), numberDebugValues, fp);
9155                 if (nRead != static_cast< size_t >(numberDebugValues))
9156                   throw("Error in fread");
9157                 printf("%d doubles read into debugValues\n", numberDebugValues);
9158 #ifdef CGL_WRITEMPS
9159                 debugSolution = debugValues;
9160                 debugNumberColumns = numberDebugValues;
9161 #endif
9162                 if (numberDebugValues < 200) {
9163                   for (int i = 0; i < numberDebugValues; i++) {
9164                     if (clpSolver->isInteger(i) && debugValues[i])
9165                       printf("%d %g\n", i, debugValues[i]);
9166                   }
9167                 }
9168                 fclose(fp);
9169               } else {
9170                 sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
9171                 printGeneralMessage(model_, generalPrint);
9172               }
9173             } else {
9174               sprintf(generalPrint, "** Current model not valid");
9175               printGeneralMessage(model_, generalPrint);
9176             }
9177             break;
9178           case CLP_PARAM_ACTION_PRINTMASK:
9179             // get next field
9180             {
9181               std::string name = CoinReadGetString(argc, argv);
9182               if (name != "EOL") {
9183                 parameters_[iParam].setStringValue(name);
9184                 printMask = name;
9185               } else {
9186                 parameters_[iParam].printString();
9187               }
9188             }
9189             break;
9190           case CLP_PARAM_ACTION_BASISOUT:
9191             if (goodModel) {
9192               // get next field
9193               field = CoinReadGetString(argc, argv);
9194               if (field == "$") {
9195                 field = parameters_[iParam].stringValue();
9196               } else if (field == "EOL") {
9197                 parameters_[iParam].printString();
9198                 break;
9199               } else {
9200                 parameters_[iParam].setStringValue(field);
9201               }
9202               std::string fileName;
9203               bool canOpen = false;
9204               if (field[0] == '/' || field[0] == '\\') {
9205                 fileName = field;
9206               } else if (field[0] == '~') {
9207                 char *environVar = getenv("HOME");
9208                 if (environVar) {
9209                   std::string home(environVar);
9210                   field = field.erase(0, 1);
9211                   fileName = home + field;
9212                 } else {
9213                   fileName = field;
9214                 }
9215               } else {
9216                 fileName = directory + field;
9217               }
9218               FILE *fp = fopen(fileName.c_str(), "w");
9219               if (fp) {
9220                 // can open - lets go for it
9221                 fclose(fp);
9222                 canOpen = true;
9223               } else {
9224                 sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
9225                 printGeneralMessage(model_, generalPrint);
9226               }
9227               if (canOpen) {
9228                 ClpSimplex *model2 = lpSolver;
9229                 model2->writeBasis(fileName.c_str(), outputFormat > 1, outputFormat - 2);
9230                 time2 = CoinCpuTime();
9231                 totalTime += time2 - time1;
9232                 time1 = time2;
9233               }
9234             } else {
9235               sprintf(generalPrint, "** Current model not valid");
9236               printGeneralMessage(model_, generalPrint);
9237             }
9238             break;
9239           case CLP_PARAM_ACTION_SAVE: {
9240             // get next field
9241             field = CoinReadGetString(argc, argv);
9242             if (field == "$") {
9243               field = parameters_[iParam].stringValue();
9244             } else if (field == "EOL") {
9245               parameters_[iParam].printString();
9246               break;
9247             } else {
9248               parameters_[iParam].setStringValue(field);
9249             }
9250             std::string fileName;
9251             bool canOpen = false;
9252             if (field[0] == '/' || field[0] == '\\') {
9253               fileName = field;
9254             } else if (field[0] == '~') {
9255               char *environVar = getenv("HOME");
9256               if (environVar) {
9257                 std::string home(environVar);
9258                 field = field.erase(0, 1);
9259                 fileName = home + field;
9260               } else {
9261                 fileName = field;
9262               }
9263             } else {
9264               fileName = directory + field;
9265             }
9266             FILE *fp = fopen(fileName.c_str(), "wb");
9267             if (fp) {
9268               // can open - lets go for it
9269               fclose(fp);
9270               canOpen = true;
9271             } else {
9272               sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
9273               printGeneralMessage(model_, generalPrint);
9274             }
9275             if (canOpen) {
9276               int status;
9277               // If presolve on then save presolved
9278               bool deleteModel2 = false;
9279               ClpSimplex *model2 = lpSolver;
9280               if (preSolve) {
9281                 ClpPresolve pinfo;
9282                 double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue();
9283                 model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance,
9284                   false, preSolve);
9285                 if (model2) {
9286                   printf("Saving presolved model on %s\n",
9287                     fileName.c_str());
9288                   deleteModel2 = true;
9289                 } else {
9290                   printf("Presolved model looks infeasible - saving original on %s\n",
9291                     fileName.c_str());
9292                   deleteModel2 = false;
9293                   model2 = lpSolver;
9294                 }
9295               } else {
9296                 printf("Saving model on %s\n",
9297                   fileName.c_str());
9298               }
9299               status = model2->saveModel(fileName.c_str());
9300               if (deleteModel2)
9301                 delete model2;
9302               if (!status) {
9303                 goodModel = true;
9304                 time2 = CoinCpuTime();
9305                 totalTime += time2 - time1;
9306                 time1 = time2;
9307               } else {
9308                 // errors
9309                 sprintf(generalPrint, "There were errors on output");
9310                 printGeneralMessage(model_, generalPrint);
9311               }
9312             }
9313           } break;
9314           case CLP_PARAM_ACTION_RESTORE: {
9315             // get next field
9316             field = CoinReadGetString(argc, argv);
9317             if (field == "$") {
9318               field = parameters_[iParam].stringValue();
9319             } else if (field == "EOL") {
9320               parameters_[iParam].printString();
9321               break;
9322             } else {
9323               parameters_[iParam].setStringValue(field);
9324             }
9325             std::string fileName;
9326             bool canOpen = false;
9327             if (field[0] == '/' || field[0] == '\\') {
9328               fileName = field;
9329             } else if (field[0] == '~') {
9330               char *environVar = getenv("HOME");
9331               if (environVar) {
9332                 std::string home(environVar);
9333                 field = field.erase(0, 1);
9334                 fileName = home + field;
9335               } else {
9336                 fileName = field;
9337               }
9338             } else {
9339               fileName = directory + field;
9340             }
9341             FILE *fp = fopen(fileName.c_str(), "rb");
9342             if (fp) {
9343               // can open - lets go for it
9344               fclose(fp);
9345               canOpen = true;
9346             } else {
9347               sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
9348               printGeneralMessage(model_, generalPrint);
9349             }
9350             if (canOpen) {
9351               int status = lpSolver->restoreModel(fileName.c_str());
9352               if (!status) {
9353                 goodModel = true;
9354                 time2 = CoinCpuTime();
9355                 totalTime += time2 - time1;
9356                 time1 = time2;
9357               } else {
9358                 // errors
9359                 sprintf(generalPrint, "There were errors on input");
9360                 printGeneralMessage(model_, generalPrint);
9361               }
9362             }
9363           } break;
9364           case CLP_PARAM_ACTION_MAXIMIZE:
9365             lpSolver->setOptimizationDirection(-1);
9366             break;
9367           case CLP_PARAM_ACTION_MINIMIZE:
9368             lpSolver->setOptimizationDirection(1);
9369             break;
9370           case CLP_PARAM_ACTION_ALLSLACK:
9371             lpSolver->allSlackBasis(true);
9372             break;
9373           case CLP_PARAM_ACTION_REVERSE:
9374             if (goodModel) {
9375               int iColumn;
9376               int numberColumns = lpSolver->numberColumns();
9377               double *dualColumnSolution = lpSolver->dualColumnSolution();
9378               ClpObjective *obj = lpSolver->objectiveAsObject();
9379               assert(dynamic_cast< ClpLinearObjective * >(obj));
9380               double offset;
9381               double *objective = obj->gradient(NULL, NULL, offset, true);
9382               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
9383                 dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
9384                 objective[iColumn] = -objective[iColumn];
9385               }
9386               int iRow;
9387               int numberRows = lpSolver->numberRows();
9388               double *dualRowSolution = lpSolver->dualRowSolution();
9389               for (iRow = 0; iRow < numberRows; iRow++)
9390                 dualRowSolution[iRow] = dualRowSolution[iRow];
9391             }
9392             break;
9393           case CLP_PARAM_ACTION_DIRECTORY: {
9394             std::string name = CoinReadGetString(argc, argv);
9395             if (name != "EOL") {
9396               size_t length = name.length();
9397               if (length > 0 && name[length - 1] == dirsep) {
9398                 directory = name;
9399               } else {
9400                 directory = name + dirsep;
9401               }
9402               parameters_[iParam].setStringValue(directory);
9403             } else {
9404               parameters_[iParam].printString();
9405             }
9406           } break;
9407           case CLP_PARAM_ACTION_DIRSAMPLE: {
9408             std::string name = CoinReadGetString(argc, argv);
9409             if (name != "EOL") {
9410               size_t length = name.length();
9411               if (length > 0 && name[length - 1] == dirsep) {
9412                 dirSample = name;
9413               } else {
9414                 dirSample = name + dirsep;
9415               }
9416               parameters_[iParam].setStringValue(dirSample);
9417             } else {
9418               parameters_[iParam].printString();
9419             }
9420           } break;
9421           case CLP_PARAM_ACTION_DIRNETLIB: {
9422             std::string name = CoinReadGetString(argc, argv);
9423             if (name != "EOL") {
9424               size_t length = name.length();
9425               if (length > 0 && name[length - 1] == dirsep) {
9426                 dirNetlib = name;
9427               } else {
9428                 dirNetlib = name + dirsep;
9429               }
9430               parameters_[iParam].setStringValue(dirNetlib);
9431             } else {
9432               parameters_[iParam].printString();
9433             }
9434           } break;
9435           case CBC_PARAM_ACTION_DIRMIPLIB: {
9436             std::string name = CoinReadGetString(argc, argv);
9437             if (name != "EOL") {
9438               size_t length = name.length();
9439               if (length > 0 && name[length - 1] == dirsep) {
9440                 dirMiplib = name;
9441               } else {
9442                 dirMiplib = name + dirsep;
9443               }
9444               parameters_[iParam].setStringValue(dirMiplib);
9445             } else {
9446               parameters_[iParam].printString();
9447             }
9448           } break;
9449           case CLP_PARAM_ACTION_STDIN:
9450             CbcOrClpRead_mode = -1;
9451             break;
9452           case CLP_PARAM_ACTION_NETLIB_DUAL:
9453           case CLP_PARAM_ACTION_NETLIB_EITHER:
9454           case CLP_PARAM_ACTION_NETLIB_BARRIER:
9455           case CLP_PARAM_ACTION_NETLIB_PRIMAL:
9456           case CLP_PARAM_ACTION_NETLIB_TUNE: {
9457             printf("unit test is now only from clp - does same thing\n");
9458             //return(22);
9459           } break;
9460           case CLP_PARAM_ACTION_UNITTEST: {
9461             CbcClpUnitTest(model_, dirSample, -2, NULL);
9462           } break;
9463           case CLP_PARAM_ACTION_FAKEBOUND:
9464             if (goodModel) {
9465               // get bound
9466               double value = CoinReadGetDoubleField(argc, argv, &valid);
9467               if (!valid) {
9468                 sprintf(generalPrint, "Setting %s to DEBUG %g", parameters_[iParam].name().c_str(), value);
9469                 printGeneralMessage(model_, generalPrint);
9470                 int iRow;
9471                 int numberRows = lpSolver->numberRows();
9472                 double *rowLower = lpSolver->rowLower();
9473                 double *rowUpper = lpSolver->rowUpper();
9474                 for (iRow = 0; iRow < numberRows; iRow++) {
9475                   // leave free ones for now
9476                   if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) {
9477                     rowLower[iRow] = CoinMax(rowLower[iRow], -value);
9478                     rowUpper[iRow] = CoinMin(rowUpper[iRow], value);
9479                   }
9480                 }
9481                 int iColumn;
9482                 int numberColumns = lpSolver->numberColumns();
9483                 double *columnLower = lpSolver->columnLower();
9484                 double *columnUpper = lpSolver->columnUpper();
9485                 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
9486                   // leave free ones for now
9487                   if (columnLower[iColumn] > -1.0e20 || columnUpper[iColumn] < 1.0e20) {
9488                     columnLower[iColumn] = CoinMax(columnLower[iColumn], -value);
9489                     columnUpper[iColumn] = CoinMin(columnUpper[iColumn], value);
9490                   }
9491                 }
9492               } else if (valid == 1) {
9493                 abort();
9494               } else {
9495                 std::cout << "enter value for " << parameters_[iParam].name() << std::endl;
9496               }
9497             }
9498             break;
9499           case CLP_PARAM_ACTION_REALLY_SCALE:
9500             if (goodModel) {
9501               ClpSimplex newModel(*lpSolver,
9502                 lpSolver->scalingFlag());
9503               printf("model really really scaled\n");
9504               *lpSolver = newModel;
9505             }
9506             break;
9507           case CLP_PARAM_ACTION_USERCLP:
9508 #ifdef USER_HAS_FAKE_CLP
9509             // Replace the sample code by whatever you want
9510             if (goodModel) {
9511               // Way of using an existing piece of code
9512               OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
9513               ClpSimplex *lpSolver = clpSolver->getModelPtr();
9514               // set time from integer model
9515               double timeToGo = model_.getMaximumSeconds();
9516               lpSolver->setMaximumSeconds(timeToGo);
9517               int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue();
9518               fakeMain2(*lpSolver, *clpSolver, extra1);
9519               lpSolver = clpSolver->getModelPtr();
9520 #ifdef COIN_HAS_ASL
9521               // My actual usage has objective only in clpSolver
9522               //double objectiveValue=clpSolver->getObjValue();
9523               //int iStat = lpSolver->status();
9524               //int iStat2 = lpSolver->secondaryStatus();
9525 #endif
9526             }
9527 #endif
9528             break;
9529           case CBC_PARAM_ACTION_USERCBC:
9530 #ifdef USER_HAS_FAKE_CBC
9531             // Replace the sample code by whatever you want
9532             if (goodModel) {
9533               // Way of using an existing piece of code
9534               OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
9535               ClpSimplex *lpSolver = clpSolver->getModelPtr();
9536               // set time from integer model
9537               double timeToGo = model_.getMaximumSeconds();
9538               lpSolver->setMaximumSeconds(timeToGo);
9539               fakeMain(*lpSolver, *clpSolver, model);
9540 #ifdef COIN_HAS_ASL
9541               // My actual usage has objective only in clpSolver
9542               double objectiveValue = clpSolver->getObjValue();
9543               int iStat = lpSolver->status();
9544               int iStat2 = lpSolver->secondaryStatus();
9545 #endif
9546               // make sure solution back in correct place
9547               clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
9548               lpSolver = clpSolver->getModelPtr();
9549 #ifdef COIN_HAS_ASL
9550               if (statusUserFunction_[0]) {
9551                 int n = clpSolver->getNumCols();
9552                 double value = objectiveValue * lpSolver->getObjSense();
9553                 char buf[300];
9554                 int pos = 0;
9555                 std::string minor[] = { "", "", "gap", "nodes", "time", "", "solutions", "user ctrl-c" };
9556                 if (iStat == 0) {
9557                   if (objectiveValue < 1.0e40) {
9558                     pos += sprintf(buf + pos, "optimal,");
9559                   } else {
9560                     // infeasible
9561                     iStat = 1;
9562                     pos += sprintf(buf + pos, "infeasible,");
9563                   }
9564                 } else if (iStat == 1) {
9565                   if (iStat2 != 6)
9566                     iStat = 3;
9567                   else
9568                     iStat = 4;
9569                   pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str());
9570                 } else if (iStat == 2) {
9571                   iStat = 7;
9572                   pos += sprintf(buf + pos, "stopped on difficulties,");
9573                 } else if (iStat == 5) {
9574                   iStat = 3;
9575                   pos += sprintf(buf + pos, "stopped on ctrl-c,");
9576                 } else if (iStat == 6) {
9577                   // bab infeasible
9578                   pos += sprintf(buf + pos, "integer infeasible,");
9579                   iStat = 1;
9580                 } else {
9581                   pos += sprintf(buf + pos, "status unknown,");
9582                   iStat = 6;
9583                 }
9584                 info.problemStatus = iStat;
9585                 info.objValue = value;
9586                 if (objectiveValue < 1.0e40)
9587                   pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
9588                     value);
9589                 sprintf(buf + pos, "\n%d nodes, %d iterations",
9590                   model_.getNodeCount(),
9591                   model_.getIterationCount());
9592                 if (objectiveValue < 1.0e50) {
9593                   free(info.primalSolution);
9594                   info.primalSolution = (double *)malloc(n * sizeof(double));
9595                   CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution);
9596                   int numberRows = lpSolver->numberRows();
9597                   free(info.dualSolution);
9598                   info.dualSolution = (double *)malloc(numberRows * sizeof(double));
9599                   CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution);
9600                 } else {
9601                   info.primalSolution = NULL;
9602                   info.dualSolution = NULL;
9603                 }
9604                 // put buffer into info
9605                 strcpy(info.buffer, buf);
9606               }
9607 #endif
9608             }
9609 #endif
9610             break;
9611           case CLP_PARAM_ACTION_HELP:
9612             std::cout << "Cbc version " << CBC_VERSION
9613                       << ", build " << __DATE__ << std::endl;
9614             std::cout << "Non default values:-" << std::endl;
9615             std::cout << "Perturbation " << lpSolver->perturbation() << " (default 100)"
9616                       << std::endl;
9617             CoinReadPrintit(
9618               "Presolve being done with 5 passes\n\
9619 Dual steepest edge steep/partial on matrix shape and factorization density\n\
9620 Clpnnnn taken out of messages\n\
9621 If Factorization frequency default then done on size of matrix\n\n\
9622 (-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
9623 You can switch to interactive mode at any time so\n\
9624 clp watson.mps -scaling off -primalsimplex\nis the same as\n\
9625 clp watson.mps -\nscaling off\nprimalsimplex");
9626             break;
9627           case CLP_PARAM_ACTION_CSVSTATISTICS: {
9628             // get next field
9629             field = CoinReadGetString(argc, argv);
9630             if (field == "$") {
9631               field = parameters_[iParam].stringValue();
9632             } else if (field == "EOL") {
9633               parameters_[iParam].printString();
9634               break;
9635             } else {
9636               parameters_[iParam].setStringValue(field);
9637             }
9638             std::string fileName;
9639             if (field[0] == '/' || field[0] == '\\') {
9640               fileName = field;
9641             } else if (field[0] == '~') {
9642               char *environVar = getenv("HOME");
9643               if (environVar) {
9644                 std::string home(environVar);
9645                 field = field.erase(0, 1);
9646                 fileName = home + field;
9647               } else {
9648                 fileName = field;
9649               }
9650             } else {
9651               fileName = directory + field;
9652             }
9653             int state = 0;
9654             char buffer[1000];
9655             FILE *fp = fopen(fileName.c_str(), "r");
9656             if (fp) {
9657               // file already there
9658               state = 1;
9659               char *getBuffer = fgets(buffer, 1000, fp);
9660               if (getBuffer) {
9661                 // assume header there
9662                 state = 2;
9663               }
9664               fclose(fp);
9665             }
9666             fp = fopen(fileName.c_str(), "a");
9667             if (fp) {
9668               // can open - lets go for it
9669               // first header if needed
9670               if (state != 2) {
9671                 fprintf(fp, "Name,result,time,sys,elapsed,objective,continuous,tightened,cut_time,nodes,iterations,rows,columns,processed_rows,processed_columns");
9672                 for (int i = 0; i < statistics_number_generators; i++)
9673                   fprintf(fp, ",%s", statistics_name_generators[i]);
9674                 fprintf(fp, ",runtime_options");
9675                 fprintf(fp, "\n");
9676               }
9677               strcpy(buffer, argv[1]);
9678               char *slash = buffer;
9679               for (int i = 0; i < static_cast< int >(strlen(buffer)); i++) {
9680                 if (buffer[i] == '/' || buffer[i] == '\\')
9681                   slash = buffer + i + 1;
9682               }
9683               fprintf(fp, "%s,%s,%.2f,%.2f,%.2f,%.16g,%g,%g,%.2f,%d,%d,%d,%d,%d,%d",
9684                 slash, statistics_result.c_str(), statistics_seconds,
9685                 statistics_sys_seconds, statistics_elapsed_seconds,
9686                 statistics_obj,
9687                 statistics_continuous, statistics_tighter, statistics_cut_time, statistics_nodes,
9688                 statistics_iterations, statistics_nrows, statistics_ncols,
9689                 statistics_nprocessedrows, statistics_nprocessedcols);
9690               for (int i = 0; i < statistics_number_generators; i++)
9691                 fprintf(fp, ",%d", statistics_number_cuts != NULL ? statistics_number_cuts[i] : 0);
9692               fprintf(fp, ",");
9693               for (int i = 1; i < argc; i++) {
9694                 if (strstr(argv[i], ".gz") || strstr(argv[i], ".mps"))
9695                   continue;
9696                 if (!argv[i] || !strncmp(argv[i], "-csv", 4))
9697                   break;
9698                 fprintf(fp, "%s ", argv[i]);
9699               }
9700               fprintf(fp, "\n");
9701               fclose(fp);
9702             } else {
9703               sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
9704               printGeneralMessage(model_, generalPrint);
9705             }
9706           } break;
9707           case CLP_PARAM_ACTION_SOLUTION:
9708           case CLP_PARAM_ACTION_NEXTBESTSOLUTION:
9709           case CLP_PARAM_ACTION_GMPL_SOLUTION:
9710             if (goodModel) {
9711               ClpSimplex *saveLpSolver = NULL;
9712               // get next field
9713               field = CoinReadGetString(argc, argv);
9714               bool append = false;
9715               if (field == "append$") {
9716                 field = "$";
9717                 append = true;
9718               }
9719               if (field == "$") {
9720                 field = parameters_[iParam].stringValue();
9721               } else if (field == "EOL") {
9722                 parameters_[iParam].printString();
9723                 break;
9724               } else {
9725                 parameters_[iParam].setStringValue(field);
9726               }
9727               std::string fileName;
9728               FILE *fp = NULL;
9729               if (field == "-" || field == "EOL" || field == "stdout") {
9730                 // stdout
9731                 fp = stdout;
9732               } else if (field == "stderr") {
9733                 // stderr
9734                 fp = stderr;
9735               } else {
9736                 bool absolutePath;
9737                 if (dirsep == '/') {
9738                   // non Windows (or cygwin)
9739                   absolutePath = (field[0] == '/');
9740                 } else {
9741                   //Windows (non cycgwin)
9742                   absolutePath = (field[0] == '\\');
9743                   // but allow for :
9744                   if (strchr(field.c_str(), ':'))
9745                     absolutePath = true;
9746                 }
9747                 if (absolutePath) {
9748                   fileName = field;
9749                 } else if (field[0] == '~') {
9750                   char *environVar = getenv("HOME");
9751                   if (environVar) {
9752                     std::string home(environVar);
9753                     field = field.erase(0, 1);
9754                     fileName = home + field;
9755                   } else {
9756                     fileName = field;
9757                   }
9758                 } else {
9759                   fileName = directory + field;
9760                 }
9761                 if (!append)
9762                   fp = fopen(fileName.c_str(), "w");
9763                 else
9764                   fp = fopen(fileName.c_str(), "a");
9765               }
9766               if (fp) {
9767 #ifndef CBC_OTHER_SOLVER
9768                 // See if Glpk
9769                 if (type == CLP_PARAM_ACTION_GMPL_SOLUTION) {
9770                   int numberRows = lpSolver->getNumRows();
9771 		  int numberColumns = lpSolver->getNumCols();
9772                   int numberGlpkRows = numberRows + 1;
9773 #ifdef COIN_HAS_GLPK
9774                   if (cbc_glp_prob) {
9775                     // from gmpl
9776                     numberGlpkRows = glp_get_num_rows(cbc_glp_prob);
9777                     if (numberGlpkRows != numberRows)
9778                       printf("Mismatch - cbc %d rows, glpk %d\n",
9779                         numberRows, numberGlpkRows);
9780                   }
9781 #endif
9782                   fprintf(fp, "%d %d\n", numberGlpkRows,
9783                     numberColumns);
9784                   int iStat = lpSolver->status();
9785                   int iStat2 = GLP_UNDEF;
9786                   bool integerProblem = false;
9787                   if (integerStatus >= 0) {
9788                     iStat = integerStatus;
9789                     integerProblem = true;
9790                   }
9791                   if (iStat == 0) {
9792                     // optimal
9793                     if (integerProblem)
9794                       iStat2 = GLP_OPT;
9795                     else
9796                       iStat2 = GLP_FEAS;
9797                   } else if (iStat == 1) {
9798                     // infeasible
9799                     iStat2 = GLP_NOFEAS;
9800                   } else if (iStat == 2) {
9801                     // unbounded
9802                     // leave as 1
9803                   } else if (iStat >= 3 && iStat <= 5) {
9804                     if (babModel_ && !babModel_->bestSolution())
9805                       iStat2 = GLP_NOFEAS;
9806                     else
9807                       iStat2 = GLP_FEAS;
9808                   } else if (iStat == 6) {
9809                     // bab infeasible
9810                     iStat2 = GLP_NOFEAS;
9811                   }
9812                   lpSolver->computeObjectiveValue(false);
9813                   double objValue = clpSolver->getObjValue();
9814                   if (integerProblem)
9815                     fprintf(fp, "%d %g\n", iStat2, objValue);
9816                   else
9817                     fprintf(fp, "%d 2 %g\n", iStat2, objValue);
9818                   if (numberGlpkRows > numberRows) {
9819                     // objective as row
9820                     if (integerProblem) {
9821                       fprintf(fp, "%g\n", objValue);
9822                     } else {
9823                       fprintf(fp, "4 %g 1.0\n", objValue);
9824                     }
9825                   }
9826                   int lookup[6] = { 4, 1, 3, 2, 4, 5 };
9827                   const double *primalRowSolution = lpSolver->primalRowSolution();
9828                   const double *dualRowSolution = lpSolver->dualRowSolution();
9829                   for (int i = 0; i < numberRows; i++) {
9830                     if (integerProblem) {
9831                       fprintf(fp, "%g\n", primalRowSolution[i]);
9832                     } else {
9833                       fprintf(fp, "%d %g %g\n", lookup[lpSolver->getRowStatus(i)],
9834                         primalRowSolution[i], dualRowSolution[i]);
9835                     }
9836                   }
9837                   const double *primalColumnSolution = lpSolver->primalColumnSolution();
9838                   const double *dualColumnSolution = lpSolver->dualColumnSolution();
9839                   for (int i = 0; i < numberColumns; i++) {
9840                     if (integerProblem) {
9841                       fprintf(fp, "%g\n", primalColumnSolution[i]);
9842                     } else {
9843                       fprintf(fp, "%d %g %g\n", lookup[lpSolver->getColumnStatus(i)],
9844                         primalColumnSolution[i], dualColumnSolution[i]);
9845                     }
9846                   }
9847                   fclose(fp);
9848 #ifdef COIN_HAS_GLPK
9849                   if (cbc_glp_prob) {
9850                     if (integerProblem) {
9851                       glp_read_mip(cbc_glp_prob, fileName.c_str());
9852                       glp_mpl_postsolve(cbc_glp_tran,
9853                         cbc_glp_prob,
9854                         GLP_MIP);
9855                     } else {
9856                       glp_read_sol(cbc_glp_prob, fileName.c_str());
9857                       glp_mpl_postsolve(cbc_glp_tran,
9858                         cbc_glp_prob,
9859                         GLP_SOL);
9860                     }
9861                     // free up as much as possible
9862                     glp_free(cbc_glp_prob);
9863                     glp_mpl_free_wksp(cbc_glp_tran);
9864                     cbc_glp_prob = NULL;
9865                     cbc_glp_tran = NULL;
9866                     //gmp_free_mem();
9867                     /* check that no memory blocks are still allocated */
9868                     glp_free_env();
9869                   }
9870 #endif
9871                   break;
9872                 }
9873                 if (printMode < 5) {
9874                   if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) {
9875                     // save
9876                     const double *nextBestSolution = model_.savedSolution(1);
9877                     if (!nextBestSolution) {
9878                       sprintf(generalPrint, "All alternative solutions printed");
9879                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
9880                         << generalPrint
9881                         << CoinMessageEol;
9882                       break;
9883                     } else {
9884                       sprintf(generalPrint, "Alternative solution - %d remaining", model_.numberSavedSolutions() - 2);
9885                       generalMessageHandler->message(CLP_GENERAL, generalMessages)
9886                         << generalPrint
9887                         << CoinMessageEol;
9888                     }
9889                     saveLpSolver = lpSolver;
9890                     assert(clpSolver->getModelPtr() == saveLpSolver);
9891                     lpSolver = new ClpSimplex(*saveLpSolver);
9892 #ifndef NDEBUG
9893                     ClpSimplex *oldSimplex = clpSolver->swapModelPtr(lpSolver);
9894                     assert(oldSimplex == saveLpSolver);
9895 #else
9896                     clpSolver->swapModelPtr(lpSolver);
9897 #endif
9898                     double *solution = lpSolver->primalColumnSolution();
9899                     double *lower = lpSolver->columnLower();
9900                     double *upper = lpSolver->columnUpper();
9901                     int numberColumns = lpSolver->numberColumns();
9902                     memcpy(solution, nextBestSolution, numberColumns * sizeof(double));
9903                     model_.deleteSavedSolution(1);
9904                     for (int i = 0; i < numberColumns; i++) {
9905                       if (clpSolver->isInteger(i)) {
9906                         double value = floor(solution[i] + 0.5);
9907                         lower[i] = value;
9908                         upper[i] = value;
9909                       }
9910                     }
9911                     lpSolver->allSlackBasis();
9912                     lpSolver->initialSolve();
9913                   }
9914                   // Write solution header (suggested by Luigi Poderico)
9915                   // Refresh solver
9916                   lpSolver = clpSolver->getModelPtr();
9917                   lpSolver->computeObjectiveValue(false);
9918                   double objValue = lpSolver->getObjValue();
9919                   int iStat = lpSolver->status();
9920                   int iStat2 = -1;
9921                   if (integerStatus >= 0) {
9922                     iStat = integerStatus;
9923                     iStat2 = babModel_->secondaryStatus();
9924                   }
9925                   if (iStat == 0) {
9926                     fprintf(fp, "Optimal");
9927                     if (iStat2 == 2) {
9928                       fprintf(fp, " (within gap tolerance)");
9929                     }
9930                   } else if (iStat == 1) {
9931                     // infeasible
9932                     fprintf(fp, "Infeasible");
9933                   } else if (iStat == 2) {
9934                     // unbounded
9935                     fprintf(fp, "Unbounded");
9936                   } else if (iStat >= 3 && iStat <= 5) {
9937                     if (iStat == 3) {
9938                       if (iStat2 == 4) {
9939                         fprintf(fp, "Stopped on time");
9940                       } else {
9941                         fprintf(fp, "Stopped on iterations");
9942                       }
9943                     } else if (iStat == 4) {
9944                       fprintf(fp, "Stopped on difficulties");
9945                     } else {
9946                       fprintf(fp, "Stopped on ctrl-c");
9947                     }
9948                     if (babModel_ && !babModel_->bestSolution())
9949                       fprintf(fp, " (no integer solution - continuous used)");
9950                   } else if (iStat == 6) {
9951                     // bab infeasible
9952                     fprintf(fp, "Integer infeasible");
9953                   } else {
9954                     fprintf(fp, "Status unknown");
9955                   }
9956                   fprintf(fp, " - objective value %.8f\n", objValue);
9957                 }
9958 #endif
9959                 // make fancy later on
9960                 int iRow;
9961                 int numberRows = clpSolver->getNumRows();
9962                 const double *dualRowSolution = clpSolver->getRowPrice();
9963                 const double *primalRowSolution = clpSolver->getRowActivity();
9964                 const double *rowLower = clpSolver->getRowLower();
9965                 const double *rowUpper = clpSolver->getRowUpper();
9966                 double primalTolerance;
9967                 clpSolver->getDblParam(OsiPrimalTolerance, primalTolerance);
9968                 size_t lengthPrint = static_cast< size_t >(CoinMax(lengthName, 8));
9969                 bool doMask = (printMask != "" && lengthName);
9970                 int *maskStarts = NULL;
9971                 int maxMasks = 0;
9972                 char **masks = NULL;
9973                 if (doMask) {
9974                   int nAst = 0;
9975                   const char *pMask2 = printMask.c_str();
9976                   char pMask[100];
9977                   size_t iChar;
9978                   size_t lengthMask = strlen(pMask2);
9979                   assert(lengthMask < 100);
9980                   if (*pMask2 == '"') {
9981                     if (pMask2[lengthMask - 1] != '"') {
9982                       printf("mismatched \" in mask %s\n", pMask2);
9983                       break;
9984                     } else {
9985                       strcpy(pMask, pMask2 + 1);
9986                       *strchr(pMask, '"') = '\0';
9987                     }
9988                   } else if (*pMask2 == '\'') {
9989                     if (pMask2[lengthMask - 1] != '\'') {
9990                       printf("mismatched ' in mask %s\n", pMask2);
9991                       break;
9992                     } else {
9993                       strcpy(pMask, pMask2 + 1);
9994                       *strchr(pMask, '\'') = '\0';
9995                     }
9996                   } else {
9997                     strcpy(pMask, pMask2);
9998                   }
9999                   if (lengthMask > static_cast< size_t >(lengthName)) {
10000                     printf("mask %s too long - skipping\n", pMask);
10001                     break;
10002                   }
10003                   maxMasks = 1;
10004                   for (iChar = 0; iChar < lengthMask; iChar++) {
10005                     if (pMask[iChar] == '*') {
10006                       nAst++;
10007                       maxMasks *= (lengthName + 1);
10008                     }
10009                   }
10010                   int nEntries = 1;
10011                   maskStarts = new int[lengthName + 2];
10012                   masks = new char *[maxMasks];
10013                   char **newMasks = new char *[maxMasks];
10014                   int i;
10015                   for (i = 0; i < maxMasks; i++) {
10016                     masks[i] = new char[lengthName + 1];
10017                     newMasks[i] = new char[lengthName + 1];
10018                   }
10019                   strcpy(masks[0], pMask);
10020                   for (int iAst = 0; iAst < nAst; iAst++) {
10021                     int nOldEntries = nEntries;
10022                     nEntries = 0;
10023                     for (int iEntry = 0; iEntry < nOldEntries; iEntry++) {
10024                       char *oldMask = masks[iEntry];
10025                       char *ast = strchr(oldMask, '*');
10026                       assert(ast);
10027                       size_t length = strlen(oldMask) - 1;
10028                       size_t nBefore = ast - oldMask;
10029                       size_t nAfter = length - nBefore;
10030                       // and add null
10031                       nAfter++;
10032                       for (int i = 0; i <= lengthName - static_cast< int >(length); i++) {
10033                         char *maskOut = newMasks[nEntries];
10034                         memcpy(maskOut, oldMask, nBefore);
10035                         for (int k = 0; k < i; k++)
10036                           maskOut[k + nBefore] = '?';
10037                         memcpy(maskOut + nBefore + i, ast + 1, nAfter);
10038                         nEntries++;
10039                         assert(nEntries <= maxMasks);
10040                       }
10041                     }
10042                     char **temp = masks;
10043                     masks = newMasks;
10044                     newMasks = temp;
10045                   }
10046                   // Now extend and sort
10047                   int *sort = new int[nEntries];
10048                   for (i = 0; i < nEntries; i++) {
10049                     char *maskThis = masks[i];
10050                     size_t length = strlen(maskThis);
10051                     while (length > 0 && maskThis[length - 1] == ' ')
10052                       length--;
10053                     maskThis[length] = '\0';
10054                     sort[i] = static_cast< int >(length);
10055                   }
10056                   CoinSort_2(sort, sort + nEntries, masks);
10057                   int lastLength = -1;
10058                   for (i = 0; i < nEntries; i++) {
10059                     int length = sort[i];
10060                     while (length > lastLength)
10061                       maskStarts[++lastLength] = i;
10062                   }
10063                   maskStarts[++lastLength] = nEntries;
10064                   delete[] sort;
10065                   for (i = 0; i < maxMasks; i++)
10066                     delete[] newMasks[i];
10067                   delete[] newMasks;
10068                 }
10069                 if (printMode > 5 && printMode < 12) {
10070                   ClpSimplex *solver = clpSolver->getModelPtr();
10071 		  int numberColumns = numberPrintingColumns(clpSolver);
10072                   //int numberColumns = solver->numberColumns();
10073                   // column length unless rhs ranging
10074                   int number = numberColumns;
10075                   if (lpSolver->status()) {
10076                     fprintf(fp, "**** Results not valid when LP not optimal\n");
10077                     number = 0;
10078                   }
10079                   switch (printMode) {
10080                     // bound ranging
10081                   case 6:
10082                     fprintf(fp, "Bound ranging");
10083                     break;
10084                     // rhs ranging
10085                   case 7:
10086                     fprintf(fp, "Rhs ranging");
10087                     if (!lpSolver->status())
10088                       number = numberRows;
10089                     break;
10090                     // objective ranging
10091                   case 8:
10092                     fprintf(fp, "Objective ranging");
10093                     break;
10094                   }
10095                   if (lengthName)
10096                     fprintf(fp, ",name");
10097                   fprintf(fp, ",increase,variable,decrease,variable\n");
10098                   int *which = new int[number];
10099                   if (printMode != 7) {
10100                     if (!doMask) {
10101                       for (int i = 0; i < number; i++)
10102                         which[i] = i;
10103                     } else {
10104                       int n = 0;
10105                       for (int i = 0; i < number; i++) {
10106                         if (maskMatches(maskStarts, masks, columnNames[i]))
10107                           which[n++] = i;
10108                       }
10109                       if (n) {
10110                         number = n;
10111                       } else {
10112                         printf("No names match - doing all\n");
10113                         for (int i = 0; i < number; i++)
10114                           which[i] = i;
10115                       }
10116                     }
10117                   } else {
10118                     if (!doMask) {
10119                       for (int i = 0; i < number; i++)
10120                         which[i] = i + numberColumns;
10121                     } else {
10122                       int n = 0;
10123                       for (int i = 0; i < number; i++) {
10124                         if (maskMatches(maskStarts, masks, rowNames[i]))
10125                           which[n++] = i + numberColumns;
10126                       }
10127                       if (n) {
10128                         number = n;
10129                       } else {
10130                         printf("No names match - doing all\n");
10131                         for (int i = 0; i < number; i++)
10132                           which[i] = i + numberColumns;
10133                       }
10134                     }
10135                   }
10136                   double *valueIncrease = new double[number];
10137                   int *sequenceIncrease = new int[number];
10138                   double *valueDecrease = new double[number];
10139                   int *sequenceDecrease = new int[number];
10140                   switch (printMode) {
10141                     // bound or rhs ranging
10142                   case 6:
10143                   case 7:
10144                     solver->primalRanging(numberRows,
10145                       which, valueIncrease, sequenceIncrease,
10146                       valueDecrease, sequenceDecrease);
10147                     break;
10148                     // objective ranging
10149                   case 8:
10150                     solver->dualRanging(number,
10151                       which, valueIncrease, sequenceIncrease,
10152                       valueDecrease, sequenceDecrease);
10153                     break;
10154                   }
10155                   for (int i = 0; i < number; i++) {
10156                     int iWhich = which[i];
10157                     fprintf(fp, "%d,", (iWhich < numberColumns) ? iWhich : iWhich - numberColumns);
10158                     if (lengthName) {
10159                       const char *name = (printMode == 7) ? rowNames[iWhich - numberColumns].c_str() : columnNames[iWhich].c_str();
10160                       fprintf(fp, "%s,", name);
10161                     }
10162                     if (valueIncrease[i] < 1.0e30) {
10163                       fprintf(fp, "%.10g,", valueIncrease[i]);
10164                       int outSequence = sequenceIncrease[i];
10165                       if (outSequence < numberColumns) {
10166                         if (lengthName)
10167                           fprintf(fp, "%s,", columnNames[outSequence].c_str());
10168                         else
10169                           fprintf(fp, "C%7.7d,", outSequence);
10170                       } else {
10171                         outSequence -= numberColumns;
10172                         if (lengthName)
10173                           fprintf(fp, "%s,", rowNames[outSequence].c_str());
10174                         else
10175                           fprintf(fp, "R%7.7d,", outSequence);
10176                       }
10177                     } else {
10178                       fprintf(fp, "1.0e100,,");
10179                     }
10180                     if (valueDecrease[i] < 1.0e30) {
10181                       fprintf(fp, "%.10g,", valueDecrease[i]);
10182                       int outSequence = sequenceDecrease[i];
10183                       if (outSequence < numberColumns) {
10184                         if (lengthName)
10185                           fprintf(fp, "%s", columnNames[outSequence].c_str());
10186                         else
10187                           fprintf(fp, "C%7.7d", outSequence);
10188                       } else {
10189                         outSequence -= numberColumns;
10190                         if (lengthName)
10191                           fprintf(fp, "%s", rowNames[outSequence].c_str());
10192                         else
10193                           fprintf(fp, "R%7.7d", outSequence);
10194                       }
10195                     } else {
10196                       fprintf(fp, "1.0e100,");
10197                     }
10198                     fprintf(fp, "\n");
10199                   }
10200                   if (fp != stdout)
10201                     fclose(fp);
10202                   delete[] which;
10203                   delete[] valueIncrease;
10204                   delete[] sequenceIncrease;
10205                   delete[] valueDecrease;
10206                   delete[] sequenceDecrease;
10207                   if (masks) {
10208                     delete[] maskStarts;
10209                     for (int i = 0; i < maxMasks; i++)
10210                       delete[] masks[i];
10211                     delete[] masks;
10212                   }
10213                   break;
10214                 }
10215                 char printFormat[50];
10216                 sprintf(printFormat, " %s         %s\n",
10217                   CLP_QUOTE(CLP_OUTPUT_FORMAT),
10218                   CLP_QUOTE(CLP_OUTPUT_FORMAT));
10219                 if (printMode > 2 && printMode < 5) {
10220                   for (iRow = 0; iRow < numberRows; iRow++) {
10221                     int type = printMode - 3;
10222                     if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance || primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) {
10223                       fprintf(fp, "** ");
10224                       type = 2;
10225                     } else if (fabs(primalRowSolution[iRow]) > 1.0e-8) {
10226                       type = 1;
10227                     } else if (numberRows < 50) {
10228                       type = 3;
10229                     }
10230                     if (doMask && !maskMatches(maskStarts, masks, rowNames[iRow]))
10231                       type = 0;
10232                     if (type) {
10233                       fprintf(fp, "%7d ", iRow);
10234                       if (lengthName) {
10235                         const char *name = rowNames[iRow].c_str();
10236                         size_t n = strlen(name);
10237                         size_t i;
10238                         for (i = 0; i < n; i++)
10239                           fprintf(fp, "%c", name[i]);
10240                         for (; i < lengthPrint; i++)
10241                           fprintf(fp, " ");
10242                       }
10243                       fprintf(fp, printFormat, primalRowSolution[iRow],
10244                         dualRowSolution[iRow]);
10245                     }
10246                   }
10247                 }
10248                 int iColumn;
10249                 int numberColumns = numberPrintingColumns(clpSolver);
10250                 const double *dualColumnSolution = clpSolver->getReducedCost();
10251                 const double *primalColumnSolution = clpSolver->getColSolution();
10252                 const double *columnLower = clpSolver->getColLower();
10253                 const double *columnUpper = clpSolver->getColUpper();
10254                 if (printMode != 2 && printMode < 12) {
10255                   if (printMode == 5) {
10256                     if (lengthName)
10257                       fprintf(fp, "name");
10258                     else
10259                       fprintf(fp, "number");
10260                     fprintf(fp, ",solution\n");
10261                   }
10262                   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
10263                     int type = (printMode > 3) ? 1 : 0;
10264                     if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) {
10265                       fprintf(fp, "** ");
10266                       type = 2;
10267                     } else if (fabs(primalColumnSolution[iColumn]) > 1.0e-8) {
10268                       type = 1;
10269                     } else if (numberColumns < 50) {
10270                       type = 3;
10271                     }
10272                     // see if integer
10273                     if ((!clpSolver->isInteger(iColumn) || fabs(primalColumnSolution[iColumn]) < 1.0e-8)
10274                       && printMode == 1)
10275                       type = 0;
10276                     if (doMask && !maskMatches(maskStarts, masks, columnNames[iColumn]))
10277                       type = 0;
10278                     if (type) {
10279                       if (printMode != 5) {
10280                         fprintf(fp, "%7d ", iColumn);
10281                         if (lengthName) {
10282                           const char *name = columnNames[iColumn].c_str();
10283                           size_t n = strlen(name);
10284                           size_t i;
10285                           for (i = 0; i < n; i++)
10286                             fprintf(fp, "%c", name[i]);
10287                           for (; i < lengthPrint; i++)
10288                             fprintf(fp, " ");
10289                         }
10290                         fprintf(fp, printFormat,
10291                           primalColumnSolution[iColumn],
10292                           dualColumnSolution[iColumn]);
10293                       } else {
10294                         char temp[100];
10295                         if (lengthName) {
10296                           const char *name = columnNames[iColumn].c_str();
10297                           for (int i = 0; i < lengthName; i++)
10298                             temp[i] = name[i];
10299                           temp[lengthName] = '\0';
10300                         } else {
10301                           sprintf(temp, "%7d", iColumn);
10302                         }
10303                         sprintf(temp + strlen(temp), ", %15.8g",
10304                           primalColumnSolution[iColumn]);
10305                         size_t n = strlen(temp);
10306                         size_t k = 0;
10307                         for (size_t i = 0; i < n + 1; i++) {
10308                           if (temp[i] != ' ')
10309                             temp[k++] = temp[i];
10310                         }
10311                         fprintf(fp, "%s\n", temp);
10312                       }
10313                     }
10314                   }
10315                   if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) {
10316                     if (saveLpSolver) {
10317                       clpSolver->swapModelPtr(saveLpSolver);
10318                       delete lpSolver;
10319                       lpSolver = saveLpSolver;
10320                       saveLpSolver = NULL;
10321                     }
10322                   }
10323                 } else if (printMode==2){
10324                   // special format suitable for OsiRowCutDebugger
10325                   int n = 0;
10326                   bool comma = false;
10327                   bool newLine = false;
10328                   fprintf(fp, "\tint intIndicesV[]={\n");
10329                   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
10330                     if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) {
10331                       if (comma)
10332                         fprintf(fp, ",");
10333                       if (newLine)
10334                         fprintf(fp, "\n");
10335                       fprintf(fp, "%d ", iColumn);
10336                       comma = true;
10337                       newLine = false;
10338                       n++;
10339                       if (n == 10) {
10340                         n = 0;
10341                         newLine = true;
10342                       }
10343                     }
10344                   }
10345                   fprintf(fp, "};\n");
10346                   n = 0;
10347                   comma = false;
10348                   newLine = false;
10349                   fprintf(fp, "\tdouble intSolnV[]={\n");
10350                   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
10351                     if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) {
10352                       if (comma)
10353                         fprintf(fp, ",");
10354                       if (newLine)
10355                         fprintf(fp, "\n");
10356                       int value = static_cast< int >(primalColumnSolution[iColumn] + 0.5);
10357                       fprintf(fp, "%d. ", value);
10358                       comma = true;
10359                       newLine = false;
10360                       n++;
10361                       if (n == 10) {
10362                         n = 0;
10363                         newLine = true;
10364                       }
10365                     }
10366                   }
10367                   fprintf(fp, "};\n");
10368 		} else {
10369 		  // Make up a fake bounds section
10370 		  char outputValue[24];
10371                   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
10372 		    if (printMode==13||model_.solver()->isInteger(iColumn)) {
10373 		      fprintf(fp," FX BOUND001  ");
10374 		      const char *name = columnNames[iColumn].c_str();
10375 		      size_t n = strlen(name);
10376 		      size_t i;
10377 		      for (i = 0; i < n; i++)
10378 			fprintf(fp, "%c", name[i]);
10379 		      for (; i < lengthPrint; i++)
10380 			fprintf(fp, " ");
10381 		      CoinConvertDouble(5,2,primalColumnSolution[iColumn],
10382 					outputValue);
10383 		      fprintf(fp,"  %s\n",outputValue);
10384 		    } else {
10385 		      fprintf(fp," LO BOUND001  ");
10386 		      const char *name = columnNames[iColumn].c_str();
10387 		      size_t n = strlen(name);
10388 		      size_t i;
10389 		      for (i = 0; i < n; i++)
10390 			fprintf(fp, "%c", name[i]);
10391 		      for (; i < lengthPrint; i++)
10392 			fprintf(fp, " ");
10393 		      CoinConvertDouble(5,2,CoinMax(-1.0e30,columnLower[iColumn]),
10394 					outputValue);
10395 		      fprintf(fp,"  %s\n",outputValue);
10396 		      fprintf(fp," UP BOUND001  ");
10397 		      for (i = 0; i < n; i++)
10398 			fprintf(fp, "%c", name[i]);
10399 		      for (; i < lengthPrint; i++)
10400 			fprintf(fp, " ");
10401 		      CoinConvertDouble(5,2,CoinMin(1.0e30,columnUpper[iColumn]),
10402 					outputValue);
10403 		      fprintf(fp,"  %s\n",outputValue);
10404 		    }
10405 		  }
10406                   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
10407                     if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) {
10408 		      fprintf(fp," FX BOUND002  ");
10409 		      const char *name = columnNames[iColumn].c_str();
10410 		      size_t n = strlen(name);
10411 		      size_t i;
10412 		      for (i = 0; i < n; i++)
10413 			fprintf(fp, "%c", name[i]);
10414 		      for (; i < lengthPrint; i++)
10415 			fprintf(fp, " ");
10416 		      CoinConvertDouble(5,2,primalColumnSolution[iColumn],
10417 					outputValue);
10418 		      fprintf(fp,"  %s\n",outputValue);
10419 		    }
10420 		  }
10421                 }
10422                 if (fp != stdout)
10423                   fclose(fp);
10424                 if (masks) {
10425                   delete[] maskStarts;
10426                   for (int i = 0; i < maxMasks; i++)
10427                     delete[] masks[i];
10428                   delete[] masks;
10429                 }
10430               } else {
10431                 sprintf(generalPrint, "Unable to open file %s", fileName.c_str());
10432                 printGeneralMessage(model_, generalPrint);
10433               }
10434             } else {
10435               sprintf(generalPrint, "** Current model not valid");
10436               printGeneralMessage(model_, generalPrint);
10437             }
10438             break;
10439           case CLP_PARAM_ACTION_SAVESOL:
10440             if (goodModel) {
10441               // get next field
10442               field = CoinReadGetString(argc, argv);
10443               if (field == "$") {
10444                 field = parameters_[iParam].stringValue();
10445               } else if (field == "EOL") {
10446                 parameters_[iParam].printString();
10447                 break;
10448               } else {
10449                 parameters_[iParam].setStringValue(field);
10450               }
10451               std::string fileName;
10452               if (field[0] == '/' || field[0] == '\\') {
10453                 fileName = field;
10454               } else if (field[0] == '~') {
10455                 char *environVar = getenv("HOME");
10456                 if (environVar) {
10457                   std::string home(environVar);
10458                   field = field.erase(0, 1);
10459                   fileName = home + field;
10460                 } else {
10461                   fileName = field;
10462                 }
10463               } else {
10464                 fileName = directory + field;
10465               }
10466               saveSolution(lpSolver, fileName);
10467             } else {
10468               sprintf(generalPrint, "** Current model not valid");
10469               printGeneralMessage(model_, generalPrint);
10470             }
10471             break;
10472           case CLP_PARAM_ACTION_DUMMY:
10473             break;
10474           case CLP_PARAM_ACTION_ENVIRONMENT:
10475             CbcOrClpEnvironmentIndex = 0;
10476             break;
10477           case CLP_PARAM_ACTION_PARAMETRICS:
10478             if (goodModel) {
10479               // get next field
10480               field = CoinReadGetString(argc, argv);
10481               if (field == "$") {
10482                 field = parameters_[iParam].stringValue();
10483               } else if (field == "EOL") {
10484                 parameters_[iParam].printString();
10485                 break;
10486               } else {
10487                 parameters_[iParam].setStringValue(field);
10488               }
10489               std::string fileName;
10490               //bool canOpen = false;
10491               if (field[0] == '/' || field[0] == '\\') {
10492                 fileName = field;
10493               } else if (field[0] == '~') {
10494                 char *environVar = getenv("HOME");
10495                 if (environVar) {
10496                   std::string home(environVar);
10497                   field = field.erase(0, 1);
10498                   fileName = home + field;
10499                 } else {
10500                   fileName = field;
10501                 }
10502               } else {
10503                 fileName = directory + field;
10504               }
10505               static_cast< ClpSimplexOther * >(lpSolver)->parametrics(fileName.c_str());
10506               time2 = CoinCpuTime();
10507               totalTime += time2 - time1;
10508               time1 = time2;
10509             } else {
10510               sprintf(generalPrint, "** Current model not valid");
10511               printGeneralMessage(model_, generalPrint);
10512             }
10513             break;
10514           case CLP_PARAM_ACTION_GUESS:
10515             if (goodModel && model_.solver()) {
10516               delete[] alternativeEnvironment;
10517               OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
10518               assert(clpSolver);
10519               lpSolver = clpSolver->getModelPtr();
10520               assert(lpSolver);
10521               ClpSimplexOther *model2 = static_cast< ClpSimplexOther * >(lpSolver);
10522               alternativeEnvironment = model2->guess(1);
10523               if (alternativeEnvironment)
10524                 CbcOrClpEnvironmentIndex = 0;
10525               else
10526                 std::cout << "** Guess unable to generate commands" << std::endl;
10527             } else {
10528               std::cout << "** Guess needs a valid model" << std::endl;
10529             }
10530             break;
10531           default:
10532             abort();
10533           }
10534         }
10535       } else if (!numberMatches) {
10536         std::cout << "No match for " << field << " - ? for list of commands"
10537                   << std::endl;
10538       } else if (numberMatches == 1) {
10539         if (!numberQuery) {
10540           std::cout << "Short match for " << field << " - completion: ";
10541           std::cout << parameters_[firstMatch].matchName() << std::endl;
10542         } else if (numberQuery) {
10543           std::cout << parameters_[firstMatch].matchName() << " : ";
10544           std::cout << parameters_[firstMatch].shortHelp() << std::endl;
10545           if (numberQuery >= 2)
10546             parameters_[firstMatch].printLongHelp();
10547         }
10548       } else {
10549         if (!numberQuery)
10550           std::cout << "Multiple matches for " << field << " - possible completions:"
10551                     << std::endl;
10552         else
10553           std::cout << "Completions of " << field << ":" << std::endl;
10554         for (iParam = 0; iParam < (int)parameters_.size(); iParam++) {
10555           int match = parameters_[iParam].matches(field);
10556           if (match && parameters_[iParam].displayThis()) {
10557             std::cout << parameters_[iParam].matchName();
10558             if (numberQuery >= 2)
10559               std::cout << " : " << parameters_[iParam].shortHelp();
10560             std::cout << std::endl;
10561           }
10562         }
10563       }
10564     }
10565     delete coinModel;
10566   }
10567 #if CBC_QUIET == 0
10568   sprintf(generalPrint,
10569     "Total time (CPU seconds):       %.2f   (Wallclock seconds):       %.2f\n",
10570     CoinCpuTime() - time0,
10571     CoinGetTimeOfDay() - time0Elapsed);
10572   generalMessageHandler->message(CLP_GENERAL, generalMessages)
10573     << generalPrint
10574     << CoinMessageEol;
10575 #endif
10576 #ifdef COIN_HAS_GLPK
10577   if (cbc_glp_prob) {
10578     // free up as much as possible
10579     glp_free(cbc_glp_prob);
10580     glp_mpl_free_wksp(cbc_glp_tran);
10581     glp_free_env();
10582     cbc_glp_prob = NULL;
10583     cbc_glp_tran = NULL;
10584   }
10585 #endif
10586   delete[] lotsize;
10587   if (statistics_number_cuts != NULL)
10588     delete[] statistics_number_cuts;
10589 
10590   if (statistics_name_generators != NULL)
10591     delete[] statistics_name_generators;
10592     // By now all memory should be freed
10593 #ifdef DMALLOC
10594     //dmalloc_log_unfreed();
10595     //dmalloc_shutdown();
10596 #endif
10597   if (babModel_) {
10598     model_.moveInfo(*babModel_);
10599 #ifndef CBC_OTHER_SOLVER
10600     OsiClpSolverInterface *clpSolver0 = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver());
10601     ClpSimplex *lpSolver0 = clpSolver0->getModelPtr();
10602     OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver());
10603     ClpSimplex *lpSolver = clpSolver->getModelPtr();
10604     if (lpSolver0 != lpSolver && lpSolver != originalSolver->getModelPtr())
10605       lpSolver->moveInfo(*lpSolver0);
10606       //babModel_->setModelOwnsSolver(false);
10607 #endif
10608   }
10609 #ifdef CBC_SIG_TRAP
10610   // On Sun sometimes seems to be error - try and get round it
10611   CoinSighandler_t saveSignal = SIG_DFL;
10612   // register signal handler
10613   saveSignal = signal(SIGSEGV, signal_handler_error);
10614   // to force failure!babModel_->setNumberObjects(20000);
10615   if (!sigsetjmp(cbc_seg_buffer, 1)) {
10616 #endif
10617     delete babModel_;
10618 #ifdef CBC_SIG_TRAP
10619   } else {
10620     std::cerr << "delete babModel_ failed" << std::endl;
10621   }
10622 #endif
10623   babModel_ = NULL;
10624   model_.solver()->setWarmStart(NULL);
10625   //sprintf(generalPrint, "Total time %.2f", CoinCpuTime() - time0);
10626   //generalMessageHandler->message(CLP_GENERAL, generalMessages)
10627   //<< generalPrint
10628   //<< CoinMessageEol;
10629   return 0;
10630 }
10631 
CbcMain(int argc,const char * argv[],CbcModel & model)10632 int CbcMain(int argc, const char *argv[],
10633   CbcModel &model)
10634 {
10635   CbcSolverUsefulData cbcData;
10636   cbcData.noPrinting_ = false;
10637   CbcMain0(model, cbcData);
10638   return CbcMain1(argc, argv, model, dummyCallBack, cbcData);
10639 }
10640 
CbcMain0(CbcModel & model)10641 void CbcMain0(CbcModel &model)
10642 {
10643   CbcSolverUsefulData solverData;
10644   CbcMain0(model, solverData);
10645 }
CbcMain0(CbcModel & model,CbcSolverUsefulData & parameterData)10646 void CbcMain0(CbcModel &model,
10647   CbcSolverUsefulData &parameterData)
10648 {
10649   std::vector< CbcOrClpParam > &parameters = parameterData.parameters_;
10650 #ifndef CBC_OTHER_SOLVER
10651   OsiClpSolverInterface *originalSolver = dynamic_cast< OsiClpSolverInterface * >(model.solver());
10652 #elif CBC_OTHER_SOLVER == 1
10653   OsiCpxSolverInterface *originalSolver = dynamic_cast< OsiCpxSolverInterface * >(model.solver());
10654   // Dummy solvers
10655   OsiClpSolverInterface dummySolver;
10656   ClpSimplex *lpSolver = dummySolver.getModelPtr();
10657   OsiCpxSolverInterface *clpSolver = originalSolver;
10658 #endif
10659   assert(originalSolver);
10660   CoinMessageHandler *generalMessageHandler = originalSolver->messageHandler();
10661   generalMessageHandler->setPrefix(true);
10662 #ifndef CBC_OTHER_SOLVER
10663   OsiSolverInterface *solver = model.solver();
10664   OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
10665   ClpSimplex *lpSolver = clpSolver->getModelPtr();
10666   lpSolver->setPerturbation(50);
10667   lpSolver->messageHandler()->setPrefix(false);
10668 #endif
10669   //establishParams(numberParameters, parameters) ;
10670   const char dirsep = CoinFindDirSeparator();
10671   std::string directory;
10672   std::string dirSample;
10673   std::string dirNetlib;
10674   std::string dirMiplib;
10675   if (dirsep == '/') {
10676     directory = "./";
10677     dirSample = "../../Data/Sample/";
10678     dirNetlib = "../../Data/Netlib/";
10679     dirMiplib = "../../Data/miplib3/";
10680   } else {
10681     directory = ".\\";
10682     dirSample = "..\\..\\..\\..\\Data\\Sample\\";
10683     dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
10684     dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
10685   }
10686   std::string defaultDirectory = directory;
10687   std::string importFile = "";
10688   std::string exportFile = "default.mps";
10689   std::string importBasisFile = "";
10690   std::string importPriorityFile = "";
10691   std::string debugFile = "";
10692   std::string printMask = "";
10693   std::string exportBasisFile = "default.bas";
10694   std::string saveFile = "default.prob";
10695   std::string restoreFile = "default.prob";
10696   std::string solutionFile = "stdout";
10697   std::string solutionSaveFile = "solution.file";
10698   int doIdiot = -1;
10699   int outputFormat = 2;
10700   int substitution = 3;
10701   int dualize = 3;
10702   int preSolve = 5;
10703   int doSprint = -1;
10704   int testOsiParameters = -1;
10705   parameters[whichParam(CLP_PARAM_ACTION_BASISIN, parameters)].setStringValue(importBasisFile);
10706   parameters[whichParam(CBC_PARAM_ACTION_PRIORITYIN, parameters)].setStringValue(importPriorityFile);
10707   parameters[whichParam(CLP_PARAM_ACTION_BASISOUT, parameters)].setStringValue(exportBasisFile);
10708   parameters[whichParam(CLP_PARAM_ACTION_DEBUG, parameters)].setStringValue(debugFile);
10709   parameters[whichParam(CLP_PARAM_ACTION_PRINTMASK, parameters)].setStringValue(printMask);
10710   parameters[whichParam(CLP_PARAM_ACTION_DIRECTORY, parameters)].setStringValue(directory);
10711   parameters[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, parameters)].setStringValue(dirSample);
10712   parameters[whichParam(CLP_PARAM_ACTION_DIRNETLIB, parameters)].setStringValue(dirNetlib);
10713   parameters[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, parameters)].setStringValue(dirMiplib);
10714   parameters[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters)].setDoubleValue(lpSolver->dualBound());
10715   parameters[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters)].setDoubleValue(lpSolver->dualTolerance());
10716   parameters[whichParam(CLP_PARAM_ACTION_EXPORT, parameters)].setStringValue(exportFile);
10717   parameters[whichParam(CLP_PARAM_INT_IDIOT, parameters)].setIntValue(doIdiot);
10718   parameters[whichParam(CLP_PARAM_ACTION_IMPORT, parameters)].setStringValue(importFile);
10719   parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters)].setDoubleValue(1.0e-8);
10720   int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters);
10721   int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters);
10722   parameters[slog].setIntValue(1);
10723   clpSolver->messageHandler()->setLogLevel(1);
10724   model.messageHandler()->setLogLevel(1);
10725   lpSolver->setLogLevel(1);
10726   parameters[log].setIntValue(1);
10727   parameters[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters)].setIntValue(lpSolver->factorizationFrequency());
10728   parameters[whichParam(CLP_PARAM_INT_MAXITERATION, parameters)].setIntValue(lpSolver->maximumIterations());
10729   parameters[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, parameters)].setIntValue(outputFormat);
10730   parameters[whichParam(CLP_PARAM_INT_PRESOLVEPASS, parameters)].setIntValue(preSolve);
10731   parameters[whichParam(CLP_PARAM_INT_PERTVALUE, parameters)].setIntValue(lpSolver->perturbation());
10732   parameters[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters)].setDoubleValue(lpSolver->primalTolerance());
10733   parameters[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters)].setDoubleValue(lpSolver->infeasibilityCost());
10734   parameters[whichParam(CLP_PARAM_ACTION_RESTORE, parameters)].setStringValue(restoreFile);
10735   parameters[whichParam(CLP_PARAM_ACTION_SAVE, parameters)].setStringValue(saveFile);
10736   //parameters[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters,parameters)].setDoubleValue(1.0e8);
10737   parameters[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, parameters)].setDoubleValue(1.0e8);
10738   parameters[whichParam(CLP_PARAM_ACTION_SOLUTION, parameters)].setStringValue(solutionFile);
10739   parameters[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, parameters)].setStringValue(solutionFile);
10740   parameters[whichParam(CLP_PARAM_ACTION_SAVESOL, parameters)].setStringValue(solutionSaveFile);
10741   parameters[whichParam(CLP_PARAM_INT_SPRINT, parameters)].setIntValue(doSprint);
10742   parameters[whichParam(CLP_PARAM_INT_SUBSTITUTION, parameters)].setIntValue(substitution);
10743   parameters[whichParam(CLP_PARAM_INT_DUALIZE, parameters)].setIntValue(dualize);
10744   model.setNumberBeforeTrust(10);
10745   parameters[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters)].setIntValue(5);
10746   parameters[whichParam(CBC_PARAM_INT_MAXNODES, parameters)].setIntValue(model.getMaximumNodes());
10747   model.setNumberStrong(5);
10748   parameters[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters)].setIntValue(model.numberStrong());
10749   parameters[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcInfeasibilityWeight));
10750   parameters[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcIntegerTolerance));
10751   parameters[whichParam(CBC_PARAM_DBL_INCREMENT, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcCutoffIncrement));
10752   parameters[whichParam(CBC_PARAM_INT_TESTOSI, parameters)].setIntValue(testOsiParameters);
10753   parameters[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters)].setIntValue(1003);
10754   initialPumpTune = 1003;
10755 #ifdef CBC_THREAD
10756   parameters[whichParam(CBC_PARAM_INT_THREADS, parameters)].setIntValue(0);
10757 #endif
10758   // Set up likely cut generators and defaults
10759   parameters[whichParam(CBC_PARAM_STR_PREPROCESS, parameters)].setCurrentOption("sos");
10760   parameters[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters)].setIntValue(1057);
10761   parameters[whichParam(CBC_PARAM_INT_CUTPASSINTREE, parameters)].setIntValue(1);
10762   parameters[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters)].setIntValue(-1);
10763   parameters[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters)].setIntValue(100);
10764   parameters[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters)].setCurrentOption("on");
10765   parameters[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters)].setCurrentOption("on");
10766   parameters[whichParam(CBC_PARAM_STR_NODESTRATEGY, parameters)].setCurrentOption("fewest");
10767   parameters[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters)].setCurrentOption("ifmove");
10768   parameters[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters)].setCurrentOption("ifmove");
10769   parameters[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters)].setCurrentOption("ifmove");
10770   parameters[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters)].setCurrentOption("ifmove");
10771   parameters[whichParam(CBC_PARAM_STR_REDSPLITCUTS, parameters)].setCurrentOption("off");
10772   parameters[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, parameters)].setCurrentOption("off");
10773   parameters[whichParam(CBC_PARAM_STR_GMICUTS, parameters)].setCurrentOption("off");
10774   parameters[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters)].setCurrentOption("ifmove");
10775   parameters[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters)].setCurrentOption("ifmove");
10776   parameters[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters)].setCurrentOption("ifmove");
10777   parameters[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters)].setCurrentOption("root");
10778   parameters[whichParam(CBC_PARAM_STR_LANDPCUTS, parameters)].setCurrentOption("off");
10779   parameters[whichParam(CBC_PARAM_STR_RESIDCUTS, parameters)].setCurrentOption("off");
10780   parameters[whichParam(CBC_PARAM_STR_ROUNDING, parameters)].setCurrentOption("on");
10781   parameters[whichParam(CBC_PARAM_STR_FPUMP, parameters)].setCurrentOption("on");
10782   parameters[whichParam(CBC_PARAM_STR_GREEDY, parameters)].setCurrentOption("on");
10783   parameters[whichParam(CBC_PARAM_STR_COMBINE, parameters)].setCurrentOption("off");
10784   parameters[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters)].setCurrentOption("off");
10785   parameters[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters)].setCurrentOption("off");
10786   parameters[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters)].setCurrentOption("off");
10787   parameters[whichParam(CBC_PARAM_STR_RANDROUND, parameters)].setCurrentOption("off");
10788   parameters[whichParam(CBC_PARAM_STR_NAIVE, parameters)].setCurrentOption("off");
10789   parameters[whichParam(CBC_PARAM_STR_RINS, parameters)].setCurrentOption("off");
10790   parameters[whichParam(CBC_PARAM_STR_DINS, parameters)].setCurrentOption("off");
10791   parameters[whichParam(CBC_PARAM_STR_RENS, parameters)].setCurrentOption("off");
10792   parameters[whichParam(CBC_PARAM_STR_LOCALTREE, parameters)].setCurrentOption("off");
10793   parameters[whichParam(CBC_PARAM_STR_COSTSTRATEGY, parameters)].setCurrentOption("off");
10794 }
10795 
10796 /*
10797   Routines to print statistics.
10798 */
breakdown(const char * name,int numberLook,const double * region)10799 static void breakdown(const char *name, int numberLook, const double *region)
10800 {
10801   double range[] = {
10802     -COIN_DBL_MAX,
10803     -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, -1.0e2, -1.0e1,
10804     -1.0,
10805     -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15,
10806     0.0,
10807     1.0e-15, 1.0e-11, 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1,
10808     1.0,
10809     1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, 1.0e15,
10810     COIN_DBL_MAX
10811   };
10812   int nRanges = static_cast< int >(sizeof(range) / sizeof(double));
10813   int *number = new int[nRanges];
10814   memset(number, 0, nRanges * sizeof(int));
10815   int *numberExact = new int[nRanges];
10816   memset(numberExact, 0, nRanges * sizeof(int));
10817   int i;
10818   for (i = 0; i < numberLook; i++) {
10819     double value = region[i];
10820     for (int j = 0; j < nRanges; j++) {
10821       if (value == range[j]) {
10822         numberExact[j]++;
10823         break;
10824       } else if (value < range[j]) {
10825         number[j]++;
10826         break;
10827       }
10828     }
10829   }
10830   printf("\n%s has %d entries\n", name, numberLook);
10831   for (i = 0; i < nRanges; i++) {
10832     if (number[i])
10833       printf("%d between %g and %g", number[i], range[i - 1], range[i]);
10834     if (numberExact[i]) {
10835       if (number[i])
10836         printf(", ");
10837       printf("%d exactly at %g", numberExact[i], range[i]);
10838     }
10839     if (number[i] + numberExact[i])
10840       printf("\n");
10841   }
10842   delete[] number;
10843   delete[] numberExact;
10844 }
sortOnOther(int * column,const CoinBigIndex * rowStart,int * order,int * other,int nRow,int nInRow,int where)10845 static void sortOnOther(int *column,
10846   const CoinBigIndex *rowStart,
10847   int *order,
10848   int *other,
10849   int nRow,
10850   int nInRow,
10851   int where)
10852 {
10853   if (nRow < 2 || where >= nInRow)
10854     return;
10855   // do initial sort
10856   int kRow;
10857   int iRow;
10858   for (kRow = 0; kRow < nRow; kRow++) {
10859     iRow = order[kRow];
10860     other[kRow] = column[rowStart[iRow] + where];
10861   }
10862   CoinSort_2(other, other + nRow, order);
10863   int first = 0;
10864   iRow = order[0];
10865   int firstC = column[rowStart[iRow] + where];
10866   kRow = 1;
10867   while (kRow < nRow) {
10868     int lastC = 9999999;
10869     ;
10870     for (; kRow < nRow + 1; kRow++) {
10871       if (kRow < nRow) {
10872         iRow = order[kRow];
10873         lastC = column[rowStart[iRow] + where];
10874       } else {
10875         lastC = 9999999;
10876       }
10877       if (lastC > firstC)
10878         break;
10879     }
10880     // sort
10881     sortOnOther(column, rowStart, order + first, other, kRow - first,
10882       nInRow, where + 1);
10883     firstC = lastC;
10884     first = kRow;
10885   }
10886 }
statistics(ClpSimplex * originalModel,ClpSimplex * model)10887 static void statistics(ClpSimplex *originalModel, ClpSimplex *model)
10888 {
10889   int numberColumns = originalModel->numberColumns();
10890   const char *integerInformation = originalModel->integerInformation();
10891   const double *columnLower = originalModel->columnLower();
10892   const double *columnUpper = originalModel->columnUpper();
10893   int numberIntegers = 0;
10894   int numberBinary = 0;
10895   int iRow, iColumn;
10896   if (integerInformation) {
10897     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
10898       if (integerInformation[iColumn]) {
10899         if (columnUpper[iColumn] > columnLower[iColumn]) {
10900           numberIntegers++;
10901           if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1)
10902             numberBinary++;
10903         }
10904       }
10905     }
10906     printf("Original problem has %d integers (%d of which binary)\n",
10907       numberIntegers, numberBinary);
10908   }
10909   numberColumns = model->numberColumns();
10910   int numberRows = model->numberRows();
10911   columnLower = model->columnLower();
10912   columnUpper = model->columnUpper();
10913   const double *rowLower = model->rowLower();
10914   const double *rowUpper = model->rowUpper();
10915   const double *objective = model->objective();
10916   if (model->integerInformation()) {
10917     const char *integerInformation = model->integerInformation();
10918     int numberIntegers = 0;
10919     int numberBinary = 0;
10920     double *obj = new double[numberColumns];
10921     int *which = new int[numberColumns];
10922     for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
10923       if (columnUpper[iColumn] > columnLower[iColumn]) {
10924         if (integerInformation[iColumn]) {
10925           numberIntegers++;
10926           if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1)
10927             numberBinary++;
10928         }
10929       }
10930     }
10931     if (numberColumns != originalModel->numberColumns())
10932       printf("Presolved problem has %d integers (%d of which binary)\n",
10933         numberIntegers, numberBinary);
10934     for (int ifInt = 0; ifInt < 2; ifInt++) {
10935       for (int ifAbs = 0; ifAbs < 2; ifAbs++) {
10936         int numberSort = 0;
10937         int numberZero = 0;
10938         int numberDifferentObj = 0;
10939         for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
10940           if (columnUpper[iColumn] > columnLower[iColumn]) {
10941             if (!ifInt || integerInformation[iColumn]) {
10942               obj[numberSort] = (ifAbs) ? fabs(objective[iColumn]) : objective[iColumn];
10943               which[numberSort++] = iColumn;
10944               if (!objective[iColumn])
10945                 numberZero++;
10946             }
10947           }
10948         }
10949         CoinSort_2(obj, obj + numberSort, which);
10950         double last = obj[0];
10951         for (int jColumn = 1; jColumn < numberSort; jColumn++) {
10952           if (fabs(obj[jColumn] - last) > 1.0e-12) {
10953             numberDifferentObj++;
10954             last = obj[jColumn];
10955           }
10956         }
10957         numberDifferentObj++;
10958         printf("==== ");
10959         if (ifInt)
10960           printf("for integers ");
10961         if (!ifAbs)
10962           printf("%d zero objective ", numberZero);
10963         else
10964           printf("absolute objective values ");
10965         printf("%d different\n", numberDifferentObj);
10966         bool saveModel = false;
10967         int target = model->logLevel();
10968         if (target > 10000) {
10969           if (ifInt && !ifAbs)
10970             saveModel = true;
10971           target -= 10000;
10972         }
10973 
10974         if (target <= 100)
10975           target = 12;
10976         else
10977           target -= 100;
10978         if (numberDifferentObj < target) {
10979           int iLast = 0;
10980           double last = obj[0];
10981           for (int jColumn = 1; jColumn < numberSort; jColumn++) {
10982             if (fabs(obj[jColumn] - last) > 1.0e-12) {
10983               printf("%d variables have objective of %g\n",
10984                 jColumn - iLast, last);
10985               iLast = jColumn;
10986               last = obj[jColumn];
10987             }
10988           }
10989           printf("%d variables have objective of %g\n",
10990             numberSort - iLast, last);
10991           if (saveModel) {
10992             int spaceNeeded = numberSort + numberDifferentObj;
10993             CoinBigIndex *columnAddDummy = new CoinBigIndex[numberDifferentObj + 1];
10994             int *columnAdd = new int[spaceNeeded];
10995             double *elementAdd = new double[spaceNeeded];
10996             CoinBigIndex *rowAdd = new CoinBigIndex[2 * numberDifferentObj + 1];
10997             int *newIsInteger = reinterpret_cast< int * >(rowAdd + numberDifferentObj + 1);
10998             double *objectiveNew = new double[3 * numberDifferentObj];
10999             double *lowerNew = objectiveNew + numberDifferentObj;
11000             double *upperNew = lowerNew + numberDifferentObj;
11001             memset(columnAddDummy, 0,
11002               (numberDifferentObj + 1) * sizeof(CoinBigIndex));
11003             ClpSimplex tempModel = *model;
11004             int iLast = 0;
11005             double last = obj[0];
11006             numberDifferentObj = 0;
11007             int numberElements = 0;
11008             rowAdd[0] = 0;
11009             double *objective = tempModel.objective();
11010             for (int jColumn = 1; jColumn < numberSort + 1; jColumn++) {
11011               if (jColumn == numberSort || fabs(obj[jColumn] - last) > 1.0e-12) {
11012                 // not if just one
11013                 if (jColumn - iLast > 1) {
11014                   bool allInteger = integerInformation != NULL;
11015                   int iColumn = which[iLast];
11016                   objectiveNew[numberDifferentObj] = objective[iColumn];
11017                   double lower = 0.0;
11018                   double upper = 0.0;
11019                   for (int kColumn = iLast; kColumn < jColumn; kColumn++) {
11020                     iColumn = which[kColumn];
11021                     objective[iColumn] = 0.0;
11022                     double lowerValue = columnLower[iColumn];
11023                     double upperValue = columnUpper[iColumn];
11024                     double elementValue = -1.0;
11025                     if (objectiveNew[numberDifferentObj] * objective[iColumn] < 0.0) {
11026                       lowerValue = -columnUpper[iColumn];
11027                       upperValue = -columnLower[iColumn];
11028                       elementValue = 1.0;
11029                     }
11030                     columnAdd[numberElements] = iColumn;
11031                     elementAdd[numberElements++] = elementValue;
11032                     if (integerInformation && !integerInformation[iColumn])
11033                       allInteger = false;
11034                     if (lower != -COIN_DBL_MAX) {
11035                       if (lowerValue != -COIN_DBL_MAX)
11036                         lower += lowerValue;
11037                       else
11038                         lower = -COIN_DBL_MAX;
11039                     }
11040                     if (upper != COIN_DBL_MAX) {
11041                       if (upperValue != COIN_DBL_MAX)
11042                         upper += upperValue;
11043                       else
11044                         upper = COIN_DBL_MAX;
11045                     }
11046                   }
11047                   columnAdd[numberElements] = numberColumns + numberDifferentObj;
11048                   elementAdd[numberElements++] = 1.0;
11049                   newIsInteger[numberDifferentObj] = (allInteger) ? 1 : 0;
11050                   lowerNew[numberDifferentObj] = lower;
11051                   upperNew[numberDifferentObj] = upper;
11052                   numberDifferentObj++;
11053                   rowAdd[numberDifferentObj] = numberElements;
11054                 }
11055                 iLast = jColumn;
11056                 last = obj[jColumn];
11057               }
11058             }
11059             // add columns
11060             tempModel.addColumns(numberDifferentObj, lowerNew, upperNew,
11061               objectiveNew,
11062               columnAddDummy, NULL, NULL);
11063             // add constraints and make integer if all integer in group
11064             for (int iObj = 0; iObj < numberDifferentObj; iObj++) {
11065               lowerNew[iObj] = 0.0;
11066               upperNew[iObj] = 0.0;
11067               if (newIsInteger[iObj])
11068                 tempModel.setInteger(numberColumns + iObj);
11069             }
11070             tempModel.addRows(numberDifferentObj, lowerNew, upperNew,
11071               rowAdd, columnAdd, elementAdd);
11072             delete[] columnAdd;
11073             delete[] columnAddDummy;
11074             delete[] elementAdd;
11075             delete[] rowAdd;
11076             delete[] objectiveNew;
11077             // save
11078             std::string tempName = model->problemName();
11079             if (ifInt)
11080               tempName += "_int";
11081             if (ifAbs)
11082               tempName += "_abs";
11083             tempName += ".mps";
11084             tempModel.writeMps(tempName.c_str());
11085           }
11086         }
11087       }
11088     }
11089     delete[] which;
11090     delete[] obj;
11091     printf("===== end objective counts\n");
11092   }
11093   CoinPackedMatrix *matrix = model->matrix();
11094   CoinBigIndex numberElements = matrix->getNumElements();
11095   const int *columnLength = matrix->getVectorLengths();
11096   //const CoinBigIndex * columnStart = matrix->getVectorStarts();
11097   const double *elementByColumn = matrix->getElements();
11098   int *number = new int[numberRows + 1];
11099   memset(number, 0, (numberRows + 1) * sizeof(int));
11100   int numberObjSingletons = 0;
11101   /* cType
11102         0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up,
11103         8 0/1
11104      */
11105   int cType[9];
11106   std::string cName[] = { "0.0->inf,", "0.0->up,", "lo->inf,", "lo->up,", "free,", "fixed,", "-inf->0.0,",
11107     "-inf->up,", "0.0->1.0" };
11108   int nObjective = 0;
11109   memset(cType, 0, sizeof(cType));
11110   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11111     int length = columnLength[iColumn];
11112     if (length == 1 && objective[iColumn])
11113       numberObjSingletons++;
11114     number[length]++;
11115     if (objective[iColumn])
11116       nObjective++;
11117     if (columnLower[iColumn] > -1.0e20) {
11118       if (columnLower[iColumn] == 0.0) {
11119         if (columnUpper[iColumn] > 1.0e20)
11120           cType[0]++;
11121         else if (columnUpper[iColumn] == 1.0)
11122           cType[8]++;
11123         else if (columnUpper[iColumn] == 0.0)
11124           cType[5]++;
11125         else
11126           cType[1]++;
11127       } else {
11128         if (columnUpper[iColumn] > 1.0e20)
11129           cType[2]++;
11130         else if (columnUpper[iColumn] == columnLower[iColumn])
11131           cType[5]++;
11132         else
11133           cType[3]++;
11134       }
11135     } else {
11136       if (columnUpper[iColumn] > 1.0e20)
11137         cType[4]++;
11138       else if (columnUpper[iColumn] == 0.0)
11139         cType[6]++;
11140       else
11141         cType[7]++;
11142     }
11143   }
11144   /* rType
11145         0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other,
11146         7 L 0,  8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free
11147      */
11148   int rType[13];
11149   std::string rName[] = { "E 0.0,", "E 1.0,", "E -1.0,", "E other,", "G 0.0,", "G 1.0,", "G other,",
11150     "L 0.0,", "L 1.0,", "L other,", "Range 0.0->1.0,", "Range other,", "Free" };
11151   memset(rType, 0, sizeof(rType));
11152   for (iRow = 0; iRow < numberRows; iRow++) {
11153     if (rowLower[iRow] > -1.0e20) {
11154       if (rowLower[iRow] == 0.0) {
11155         if (rowUpper[iRow] > 1.0e20)
11156           rType[4]++;
11157         else if (rowUpper[iRow] == 1.0)
11158           rType[10]++;
11159         else if (rowUpper[iRow] == 0.0)
11160           rType[0]++;
11161         else
11162           rType[11]++;
11163       } else if (rowLower[iRow] == 1.0) {
11164         if (rowUpper[iRow] > 1.0e20)
11165           rType[5]++;
11166         else if (rowUpper[iRow] == rowLower[iRow])
11167           rType[1]++;
11168         else
11169           rType[11]++;
11170       } else if (rowLower[iRow] == -1.0) {
11171         if (rowUpper[iRow] > 1.0e20)
11172           rType[6]++;
11173         else if (rowUpper[iRow] == rowLower[iRow])
11174           rType[2]++;
11175         else
11176           rType[11]++;
11177       } else {
11178         if (rowUpper[iRow] > 1.0e20)
11179           rType[6]++;
11180         else if (rowUpper[iRow] == rowLower[iRow])
11181           rType[3]++;
11182         else
11183           rType[11]++;
11184       }
11185     } else {
11186       if (rowUpper[iRow] > 1.0e20)
11187         rType[12]++;
11188       else if (rowUpper[iRow] == 0.0)
11189         rType[7]++;
11190       else if (rowUpper[iRow] == 1.0)
11191         rType[8]++;
11192       else
11193         rType[9]++;
11194     }
11195   }
11196   // Basic statistics
11197   printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n",
11198     numberRows, numberColumns, nObjective, numberElements);
11199   if (number[0] + number[1]) {
11200     printf("There are ");
11201     if (numberObjSingletons)
11202       printf("%d singletons with objective ", numberObjSingletons);
11203     int numberNoObj = number[1] - numberObjSingletons;
11204     if (numberNoObj)
11205       printf("%d singletons with no objective ", numberNoObj);
11206     if (number[0])
11207       printf("** %d columns have no entries", number[0]);
11208     printf("\n");
11209   }
11210   printf("Column breakdown:\n");
11211   int k;
11212   for (k = 0; k < static_cast< int >(sizeof(cType) / sizeof(int)); k++) {
11213     printf("%d of type %s ", cType[k], cName[k].c_str());
11214     if (((k + 1) % 3) == 0)
11215       printf("\n");
11216   }
11217   if ((k % 3) != 0)
11218     printf("\n");
11219   printf("Row breakdown:\n");
11220   for (k = 0; k < static_cast< int >(sizeof(rType) / sizeof(int)); k++) {
11221     printf("%d of type %s ", rType[k], rName[k].c_str());
11222     if (((k + 1) % 3) == 0)
11223       printf("\n");
11224   }
11225   if ((k % 3) != 0)
11226     printf("\n");
11227     //#define SYM
11228 #ifndef SYM
11229   if (model->logLevel() < 2)
11230     return;
11231 #endif
11232   int kMax = model->logLevel() > 3 ? 1000000 : 10;
11233   k = 0;
11234   for (iRow = 1; iRow <= numberRows; iRow++) {
11235     if (number[iRow]) {
11236       k++;
11237       printf("%d columns have %d entries\n", number[iRow], iRow);
11238       if (k == kMax)
11239         break;
11240     }
11241   }
11242   if (k < numberRows) {
11243     int kk = k;
11244     k = 0;
11245     for (iRow = numberRows; iRow >= 1; iRow--) {
11246       if (number[iRow]) {
11247         k++;
11248         if (k == kMax)
11249           break;
11250       }
11251     }
11252     if (k > kk) {
11253       printf("\n    .........\n\n");
11254       iRow = k;
11255       k = 0;
11256       for (; iRow < numberRows; iRow++) {
11257         if (number[iRow]) {
11258           k++;
11259           printf("%d columns have %d entries\n", number[iRow], iRow);
11260           if (k == kMax)
11261             break;
11262         }
11263       }
11264     }
11265   }
11266   delete[] number;
11267   printf("\n\n");
11268   if (model->logLevel() == 63
11269 #ifdef SYM
11270     || true
11271 #endif
11272   ) {
11273     // get column copy
11274     CoinPackedMatrix columnCopy = *matrix;
11275     const int *columnLength = columnCopy.getVectorLengths();
11276     number = new int[numberRows + 1];
11277     memset(number, 0, (numberRows + 1) * sizeof(int));
11278     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11279       int length = columnLength[iColumn];
11280       number[length]++;
11281     }
11282     k = 0;
11283     for (iRow = 1; iRow <= numberRows; iRow++) {
11284       if (number[iRow]) {
11285         k++;
11286       }
11287     }
11288     int *row = columnCopy.getMutableIndices();
11289     const CoinBigIndex *columnStart = columnCopy.getVectorStarts();
11290     double *element = columnCopy.getMutableElements();
11291     int *order = new int[numberColumns];
11292     int *other = new int[numberColumns];
11293     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11294       int length = columnLength[iColumn];
11295       order[iColumn] = iColumn;
11296       other[iColumn] = length;
11297       CoinBigIndex start = columnStart[iColumn];
11298       CoinSort_2(row + start, row + start + length, element + start);
11299     }
11300     CoinSort_2(other, other + numberColumns, order);
11301     int jColumn = number[0] + number[1];
11302     for (iRow = 2; iRow <= numberRows; iRow++) {
11303       if (number[iRow]) {
11304         printf("XX %d columns have %d entries\n", number[iRow], iRow);
11305         int kColumn = jColumn + number[iRow];
11306         sortOnOther(row, columnStart,
11307           order + jColumn, other, number[iRow], iRow, 0);
11308         // Now print etc
11309         if (iRow < 500000) {
11310           for (int lColumn = jColumn; lColumn < kColumn; lColumn++) {
11311             iColumn = order[lColumn];
11312             CoinBigIndex start = columnStart[iColumn];
11313             if (model->logLevel() == 63) {
11314               printf("column %d %g <= ", iColumn, columnLower[iColumn]);
11315               for (CoinBigIndex i = start; i < start + iRow; i++)
11316                 printf("( %d, %g) ", row[i], element[i]);
11317               printf("<= %g\n", columnUpper[iColumn]);
11318             }
11319           }
11320         }
11321         jColumn = kColumn;
11322       }
11323     }
11324     delete[] order;
11325     delete[] other;
11326     delete[] number;
11327   }
11328   // get row copy
11329   CoinPackedMatrix rowCopy = *matrix;
11330   rowCopy.reverseOrdering();
11331   const int *rowLength = rowCopy.getVectorLengths();
11332   number = new int[numberColumns + 1];
11333   memset(number, 0, (numberColumns + 1) * sizeof(int));
11334   if (model->logLevel() > 3) {
11335     // get column copy
11336     CoinPackedMatrix columnCopy = *matrix;
11337     const int *columnLength = columnCopy.getVectorLengths();
11338     const int *row = columnCopy.getIndices();
11339     const CoinBigIndex *columnStart = columnCopy.getVectorStarts();
11340     const double *element = columnCopy.getElements();
11341     const double *elementByRow = rowCopy.getElements();
11342     const CoinBigIndex *rowStart = rowCopy.getVectorStarts();
11343     const int *column = rowCopy.getIndices();
11344     int nPossibleZeroCost = 0;
11345     int nPossibleNonzeroCost = 0;
11346     for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
11347       int length = columnLength[iColumn];
11348       if (columnLower[iColumn] < -1.0e30 && columnUpper[iColumn] > 1.0e30) {
11349         if (length == 1) {
11350           printf("Singleton free %d - cost %g\n", iColumn, objective[iColumn]);
11351         } else if (length == 2) {
11352           int iRow0 = row[columnStart[iColumn]];
11353           int iRow1 = row[columnStart[iColumn] + 1];
11354           double element0 = element[columnStart[iColumn]];
11355           double element1 = element[columnStart[iColumn] + 1];
11356           int n0 = rowLength[iRow0];
11357           int n1 = rowLength[iRow1];
11358           printf("Doubleton free %d - cost %g - %g in %srow with %d entries and %g in %srow with %d entries\n",
11359             iColumn, objective[iColumn], element0, (rowLower[iRow0] == rowUpper[iRow0]) ? "==" : "", n0,
11360             element1, (rowLower[iRow1] == rowUpper[iRow1]) ? "==" : "", n1);
11361         }
11362       }
11363       if (length == 1) {
11364         int iRow = row[columnStart[iColumn]];
11365         double value = COIN_DBL_MAX;
11366         for (CoinBigIndex i = rowStart[iRow]; i < rowStart[iRow] + rowLength[iRow]; i++) {
11367           int jColumn = column[i];
11368           if (jColumn != iColumn) {
11369             if (value != elementByRow[i]) {
11370               if (value == COIN_DBL_MAX) {
11371                 value = elementByRow[i];
11372               } else {
11373                 value = -COIN_DBL_MAX;
11374                 break;
11375               }
11376             }
11377           }
11378         }
11379         if (!objective[iColumn]) {
11380           if (model->logLevel() > 4)
11381             printf("Singleton %d with no objective in row with %d elements - rhs %g,%g\n", iColumn, rowLength[iRow], rowLower[iRow], rowUpper[iRow]);
11382           nPossibleZeroCost++;
11383         } else if (value != -COIN_DBL_MAX) {
11384           if (model->logLevel() > 4)
11385             printf("Singleton %d (%s) with objective in row %d (%s) with %d equal elements - rhs %g,%g\n", iColumn, model->getColumnName(iColumn).c_str(),
11386               iRow, model->getRowName(iRow).c_str(),
11387               rowLength[iRow], rowLower[iRow], rowUpper[iRow]);
11388           nPossibleNonzeroCost++;
11389         }
11390       }
11391     }
11392     if (nPossibleZeroCost || nPossibleNonzeroCost)
11393       printf("%d singletons with zero cost, %d with valid cost\n",
11394         nPossibleZeroCost, nPossibleNonzeroCost);
11395     // look for DW
11396     int *blockStart = new int[2 * (numberRows + numberColumns) + 1 + numberRows];
11397     int *columnBlock = blockStart + numberRows;
11398     int *nextColumn = columnBlock + numberColumns;
11399     int *blockCount = nextColumn + numberColumns;
11400     int *blockEls = blockCount + numberRows + 1;
11401     int direction[2] = { -1, 1 };
11402     int bestBreak = -1;
11403     double bestValue = 0.0;
11404     int iPass = 0;
11405     int halfway = (numberRows + 1) / 2;
11406     int firstMaster = -1;
11407     int lastMaster = -2;
11408     while (iPass < 2) {
11409       int increment = direction[iPass];
11410       int start = increment > 0 ? 0 : numberRows - 1;
11411       int stop = increment > 0 ? numberRows : -1;
11412       int numberBlocks = 0;
11413       int thisBestBreak = -1;
11414       double thisBestValue = COIN_DBL_MAX;
11415       int numberRowsDone = 0;
11416       int numberMarkedColumns = 0;
11417       int maximumBlockSize = 0;
11418       for (int i = 0; i < numberRows + 2 * numberColumns; i++)
11419         blockStart[i] = -1;
11420       for (int i = 0; i < numberRows + 1; i++)
11421         blockCount[i] = 0;
11422       for (int iRow = start; iRow != stop; iRow += increment) {
11423         int iBlock = -1;
11424         for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
11425           int iColumn = column[j];
11426           int whichColumnBlock = columnBlock[iColumn];
11427           if (whichColumnBlock >= 0) {
11428             // column marked
11429             if (iBlock < 0) {
11430               // put row in that block
11431               iBlock = whichColumnBlock;
11432             } else if (iBlock != whichColumnBlock) {
11433               // merge
11434               blockCount[iBlock] += blockCount[whichColumnBlock];
11435               blockCount[whichColumnBlock] = 0;
11436               int jColumn = blockStart[whichColumnBlock];
11437               while (jColumn >= 0) {
11438                 columnBlock[jColumn] = iBlock;
11439                 iColumn = jColumn;
11440                 jColumn = nextColumn[jColumn];
11441               }
11442               nextColumn[iColumn] = blockStart[iBlock];
11443               blockStart[iBlock] = blockStart[whichColumnBlock];
11444               blockStart[whichColumnBlock] = -1;
11445             }
11446           }
11447         }
11448         int n = numberMarkedColumns;
11449         if (iBlock < 0) {
11450           //new block
11451           if (rowLength[iRow]) {
11452             numberBlocks++;
11453             iBlock = numberBlocks;
11454             int jColumn = column[rowStart[iRow]];
11455             columnBlock[jColumn] = iBlock;
11456             blockStart[iBlock] = jColumn;
11457             numberMarkedColumns++;
11458             for (CoinBigIndex j = rowStart[iRow] + 1; j < rowStart[iRow] + rowLength[iRow]; j++) {
11459               int iColumn = column[j];
11460               columnBlock[iColumn] = iBlock;
11461               numberMarkedColumns++;
11462               nextColumn[jColumn] = iColumn;
11463               jColumn = iColumn;
11464             }
11465             blockCount[iBlock] = numberMarkedColumns - n;
11466           } else {
11467             // empty
11468             iBlock = numberRows;
11469           }
11470         } else {
11471           // put in existing block
11472           int jColumn = blockStart[iBlock];
11473           for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
11474             int iColumn = column[j];
11475             assert(columnBlock[iColumn] < 0 || columnBlock[iColumn] == iBlock);
11476             if (columnBlock[iColumn] < 0) {
11477               columnBlock[iColumn] = iBlock;
11478               numberMarkedColumns++;
11479               nextColumn[iColumn] = jColumn;
11480               jColumn = iColumn;
11481             }
11482           }
11483           blockStart[iBlock] = jColumn;
11484           blockCount[iBlock] += numberMarkedColumns - n;
11485         }
11486         maximumBlockSize = CoinMax(maximumBlockSize, blockCount[iBlock]);
11487         numberRowsDone++;
11488         if (thisBestValue * numberRowsDone > maximumBlockSize && numberRowsDone > halfway) {
11489           thisBestBreak = iRow;
11490           thisBestValue = static_cast< double >(maximumBlockSize) / static_cast< double >(numberRowsDone);
11491         }
11492       }
11493       if (thisBestBreak == stop)
11494         thisBestValue = COIN_DBL_MAX;
11495       iPass++;
11496       if (iPass == 1) {
11497         bestBreak = thisBestBreak;
11498         bestValue = thisBestValue;
11499       } else {
11500         if (bestValue < thisBestValue) {
11501           firstMaster = 0;
11502           lastMaster = bestBreak;
11503         } else {
11504           firstMaster = thisBestBreak; // ? +1
11505           lastMaster = numberRows;
11506         }
11507       }
11508     }
11509     if (firstMaster < lastMaster) {
11510       printf("%d master rows %d <= < %d\n", lastMaster - firstMaster,
11511         firstMaster, lastMaster);
11512       for (int i = 0; i < numberRows + 2 * numberColumns; i++)
11513         blockStart[i] = -1;
11514       for (int i = firstMaster; i < lastMaster; i++)
11515         blockStart[i] = -2;
11516       int firstRow = 0;
11517       int numberBlocks = -1;
11518       while (true) {
11519         for (; firstRow < numberRows; firstRow++) {
11520           if (blockStart[firstRow] == -1)
11521             break;
11522         }
11523         if (firstRow == numberRows)
11524           break;
11525         int nRows = 0;
11526         numberBlocks++;
11527         int numberStack = 1;
11528         blockCount[0] = firstRow;
11529         while (numberStack) {
11530           int iRow = blockCount[--numberStack];
11531           for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
11532             int iColumn = column[j];
11533             int iBlock = columnBlock[iColumn];
11534             if (iBlock < 0) {
11535               columnBlock[iColumn] = numberBlocks;
11536               for (CoinBigIndex k = columnStart[iColumn];
11537                    k < columnStart[iColumn] + columnLength[iColumn]; k++) {
11538                 int jRow = row[k];
11539                 int rowBlock = blockStart[jRow];
11540                 if (rowBlock == -1) {
11541                   nRows++;
11542                   blockStart[jRow] = numberBlocks;
11543                   blockCount[numberStack++] = jRow;
11544                 }
11545               }
11546             }
11547           }
11548         }
11549         if (!nRows) {
11550           // empty!!
11551           numberBlocks--;
11552         }
11553         firstRow++;
11554       }
11555       // adjust
11556       numberBlocks++;
11557       for (int i = 0; i < numberBlocks; i++) {
11558         blockCount[i] = 0;
11559         nextColumn[i] = 0;
11560       }
11561       int numberEmpty = 0;
11562       int numberMaster = 0;
11563       memset(blockEls, 0, numberBlocks * sizeof(int));
11564       for (int iRow = 0; iRow < numberRows; iRow++) {
11565         int iBlock = blockStart[iRow];
11566         if (iBlock >= 0) {
11567           blockCount[iBlock]++;
11568           blockEls[iBlock] += rowLength[iRow];
11569         } else {
11570           if (iBlock == -2)
11571             numberMaster++;
11572           else
11573             numberEmpty++;
11574         }
11575       }
11576       int numberEmptyColumns = 0;
11577       int numberMasterColumns = 0;
11578       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
11579         int iBlock = columnBlock[iColumn];
11580         if (iBlock >= 0) {
11581           nextColumn[iBlock]++;
11582         } else {
11583           if (columnLength[iColumn])
11584             numberMasterColumns++;
11585           else
11586             numberEmptyColumns++;
11587         }
11588       }
11589       int largestRows = 0;
11590       int largestColumns = 0;
11591       for (int i = 0; i < numberBlocks; i++) {
11592         if (blockCount[i] + nextColumn[i] > largestRows + largestColumns) {
11593           largestRows = blockCount[i];
11594           largestColumns = nextColumn[i];
11595         }
11596       }
11597       bool useful = true;
11598       if (numberMaster > halfway || largestRows * 3 > numberRows)
11599         useful = false;
11600       printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of %d, %d master columns (%d empty) out of %d\n",
11601         useful ? "**Useful" : "NoGood",
11602         numberBlocks, largestRows, largestColumns, numberMaster, numberEmpty, numberRows,
11603         numberMasterColumns, numberEmptyColumns, numberColumns);
11604       FILE *fp = NULL;
11605       bool justIntegers = true;
11606       bool oneFile = true;
11607       int logLevel = model->logLevel();
11608       if (logLevel > 19) {
11609         logLevel -= 2;
11610         oneFile = true;
11611         fp = fopen("fake.bnd", "w");
11612       }
11613       if (logLevel == 19)
11614         justIntegers = false;
11615       for (int i = 0; i < numberBlocks; i++)
11616         printf("Block %d has %d rows and %d columns (%d elements)\n",
11617           i, blockCount[i], nextColumn[i], blockEls[i]);
11618       if (logLevel >= 17 && logLevel <= 21) {
11619         int *whichRows = new int[numberRows + numberColumns];
11620         int *whichColumns = whichRows + numberRows;
11621         char name[20];
11622         for (int iBlock = 0; iBlock < numberBlocks; iBlock++) {
11623           sprintf(name, "block%d.mps", iBlock);
11624           int nRows = 0;
11625           for (int iRow = 0; iRow < numberRows; iRow++) {
11626             if (blockStart[iRow] == iBlock)
11627               whichRows[nRows++] = iRow;
11628           }
11629           int nColumns = 0;
11630           for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
11631             if (columnBlock[iColumn] == iBlock)
11632               whichColumns[nColumns++] = iColumn;
11633           }
11634           ClpSimplex subset(model, nRows, whichRows, nColumns, whichColumns);
11635           for (int jRow = 0; jRow < nRows; jRow++) {
11636             int iRow = whichRows[jRow];
11637             std::string name = model->getRowName(iRow);
11638             subset.setRowName(jRow, name);
11639           }
11640           int nInteger = 0;
11641           for (int jColumn = 0; jColumn < nColumns; jColumn++) {
11642             int iColumn = whichColumns[jColumn];
11643             if (model->isInteger(iColumn)) {
11644               subset.setInteger(jColumn);
11645               nInteger++;
11646             }
11647             std::string name = model->getColumnName(iColumn);
11648             subset.setColumnName(jColumn, name);
11649           }
11650           if (logLevel == 17) {
11651             subset.writeMps(name, 0, 1);
11652           } else if (nInteger) {
11653             OsiClpSolverInterface subset2(&subset);
11654             CbcModel smallModel(subset2);
11655             smallModel.branchAndBound();
11656             const double *solution = smallModel.bestSolution();
11657             if (solution) {
11658               if (!oneFile) {
11659                 sprintf(name, "block%d.bnd", iBlock);
11660                 fp = fopen(name, "w");
11661                 assert(fp);
11662               }
11663               fprintf(fp, "BBB objective %g for block %d\n",
11664                 smallModel.getObjValue(), iBlock);
11665               for (int jColumn = 0; jColumn < nColumns; jColumn++) {
11666                 if (subset.isInteger(jColumn) || !justIntegers)
11667                   fprintf(fp, " FX BOUND1    %.8s  %g\n",
11668                     subset.getColumnName(jColumn).c_str(),
11669                     solution[jColumn]);
11670               }
11671               if (!oneFile)
11672                 fclose(fp);
11673             } else {
11674               printf("***** Problem is infeasible\n");
11675               abort();
11676             }
11677           }
11678         }
11679         if (oneFile)
11680           fclose(fp);
11681         delete[] whichRows;
11682       }
11683     }
11684     delete[] blockStart;
11685   }
11686   for (iRow = 0; iRow < numberRows; iRow++) {
11687     int length = rowLength[iRow];
11688     number[length]++;
11689   }
11690   if (number[0])
11691     printf("** %d rows have no entries\n", number[0]);
11692   k = 0;
11693   for (iColumn = 1; iColumn <= numberColumns; iColumn++) {
11694     if (number[iColumn]) {
11695       k++;
11696       printf("%d rows have %d entries\n", number[iColumn], iColumn);
11697       if (k == kMax)
11698         break;
11699     }
11700   }
11701   if (k < numberColumns) {
11702     int kk = k;
11703     k = 0;
11704     for (iColumn = numberColumns; iColumn >= 1; iColumn--) {
11705       if (number[iColumn]) {
11706         k++;
11707         if (k == kMax)
11708           break;
11709       }
11710     }
11711     if (k > kk) {
11712       printf("\n    .........\n\n");
11713       iColumn = k;
11714       k = 0;
11715       for (; iColumn < numberColumns; iColumn++) {
11716         if (number[iColumn]) {
11717           k++;
11718           printf("%d rows have %d entries\n", number[iColumn], iColumn);
11719           if (k == kMax)
11720             break;
11721         }
11722       }
11723     }
11724   }
11725   if (model->logLevel() == 63
11726 #ifdef SYM
11727     || true
11728 #endif
11729   ) {
11730     int *column = rowCopy.getMutableIndices();
11731     const CoinBigIndex *rowStart = rowCopy.getVectorStarts();
11732     double *element = rowCopy.getMutableElements();
11733     int *order = new int[numberRows];
11734     int *other = new int[numberRows];
11735     for (iRow = 0; iRow < numberRows; iRow++) {
11736       int length = rowLength[iRow];
11737       order[iRow] = iRow;
11738       other[iRow] = length;
11739       CoinBigIndex start = rowStart[iRow];
11740       CoinSort_2(column + start, column + start + length, element + start);
11741     }
11742     CoinSort_2(other, other + numberRows, order);
11743     int jRow = number[0] + number[1];
11744     double *weight = new double[numberRows];
11745     double *randomColumn = new double[numberColumns + 1];
11746     double *randomRow = new double[numberRows + 1];
11747     int *sortRow = new int[numberRows];
11748     int *possibleRow = new int[numberRows];
11749     int *backRow = new int[numberRows];
11750     int *stackRow = new int[numberRows];
11751     int *sortColumn = new int[numberColumns];
11752     int *possibleColumn = new int[numberColumns];
11753     int *backColumn = new int[numberColumns];
11754     int *backColumn2 = new int[numberColumns];
11755     int *mapRow = new int[numberRows];
11756     int *mapColumn = new int[numberColumns];
11757     int *stackColumn = new int[numberColumns];
11758     double randomLower = CoinDrand48();
11759     double randomUpper = CoinDrand48();
11760     double randomInteger = CoinDrand48();
11761     CoinBigIndex *startAdd = new CoinBigIndex[numberRows + 1];
11762     int *columnAdd = new int[2 * numberElements];
11763     double *elementAdd = new double[2 * numberElements];
11764     int nAddRows = 0;
11765     startAdd[0] = 0;
11766     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11767       randomColumn[iColumn] = CoinDrand48();
11768       backColumn2[iColumn] = -1;
11769     }
11770     for (iColumn = 2; iColumn <= numberColumns; iColumn++) {
11771       if (number[iColumn]) {
11772         printf("XX %d rows have %d entries\n", number[iColumn], iColumn);
11773         int kRow = jRow + number[iColumn];
11774         sortOnOther(column, rowStart,
11775           order + jRow, other, number[iColumn], iColumn, 0);
11776         // Now print etc
11777         if (iColumn < 500000) {
11778           int nLook = 0;
11779           for (int lRow = jRow; lRow < kRow; lRow++) {
11780             iRow = order[lRow];
11781             CoinBigIndex start = rowStart[iRow];
11782             if (model->logLevel() == 63) {
11783               printf("row %d %g <= ", iRow, rowLower[iRow]);
11784               for (CoinBigIndex i = start; i < start + iColumn; i++)
11785                 printf("( %d, %g) ", column[i], element[i]);
11786               printf("<= %g\n", rowUpper[iRow]);
11787             }
11788             int first = column[start];
11789             double sum = 0.0;
11790             for (CoinBigIndex i = start; i < start + iColumn; i++) {
11791               int jColumn = column[i];
11792               double value = element[i];
11793               jColumn -= first;
11794               assert(jColumn >= 0);
11795               sum += value * randomColumn[jColumn];
11796             }
11797             if (rowLower[iRow] > -1.0e30 && rowLower[iRow])
11798               sum += rowLower[iRow] * randomLower;
11799             else if (!rowLower[iRow])
11800               sum += 1.234567e-7 * randomLower;
11801             if (rowUpper[iRow] < 1.0e30 && rowUpper[iRow])
11802               sum += rowUpper[iRow] * randomUpper;
11803             else if (!rowUpper[iRow])
11804               sum += 1.234567e-7 * randomUpper;
11805             sortRow[nLook] = iRow;
11806             randomRow[nLook++] = sum;
11807             // best way is to number unique elements and bounds and use
11808             if (fabs(sum) > 1.0e4)
11809               sum *= 1.0e-6;
11810             weight[iRow] = sum;
11811           }
11812           assert(nLook <= numberRows);
11813           CoinSort_2(randomRow, randomRow + nLook, sortRow);
11814           randomRow[nLook] = COIN_DBL_MAX;
11815           double last = -COIN_DBL_MAX;
11816           int iLast = -1;
11817           for (int iLook = 0; iLook < nLook + 1; iLook++) {
11818             if (randomRow[iLook] > last) {
11819               if (iLast >= 0) {
11820                 int n = iLook - iLast;
11821                 if (n > 1) {
11822                   //printf("%d rows possible?\n",n);
11823                 }
11824               }
11825               iLast = iLook;
11826               last = randomRow[iLook];
11827             }
11828           }
11829         }
11830         jRow = kRow;
11831       }
11832     }
11833     CoinPackedMatrix columnCopy = *matrix;
11834     const int *columnLength = columnCopy.getVectorLengths();
11835     const int *row = columnCopy.getIndices();
11836     const CoinBigIndex *columnStart = columnCopy.getVectorStarts();
11837     const double *elementByColumn = columnCopy.getElements();
11838     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11839       int length = columnLength[iColumn];
11840       CoinBigIndex start = columnStart[iColumn];
11841       double sum = objective[iColumn];
11842       if (columnLower[iColumn] > -1.0e30 && columnLower[iColumn])
11843         sum += columnLower[iColumn] * randomLower;
11844       else if (!columnLower[iColumn])
11845         sum += 1.234567e-7 * randomLower;
11846       if (columnUpper[iColumn] < 1.0e30 && columnUpper[iColumn])
11847         sum += columnUpper[iColumn] * randomUpper;
11848       else if (!columnUpper[iColumn])
11849         sum += 1.234567e-7 * randomUpper;
11850       if (model->isInteger(iColumn))
11851         sum += 9.87654321e-6 * randomInteger;
11852       for (CoinBigIndex i = start; i < start + length; i++) {
11853         int iRow = row[i];
11854         sum += elementByColumn[i] * weight[iRow];
11855       }
11856       sortColumn[iColumn] = iColumn;
11857       randomColumn[iColumn] = sum;
11858     }
11859     {
11860       CoinSort_2(randomColumn, randomColumn + numberColumns, sortColumn);
11861       for (iColumn = 0; iColumn < numberColumns; iColumn++) {
11862         int i = sortColumn[iColumn];
11863         backColumn[i] = iColumn;
11864       }
11865       randomColumn[numberColumns] = COIN_DBL_MAX;
11866       double last = -COIN_DBL_MAX;
11867       int iLast = -1;
11868       for (int iLook = 0; iLook < numberColumns + 1; iLook++) {
11869         if (randomColumn[iLook] > last) {
11870           if (iLast >= 0) {
11871             int n = iLook - iLast;
11872             if (n > 1) {
11873               //printf("%d columns possible?\n",n);
11874             }
11875             for (int i = iLast; i < iLook; i++) {
11876               possibleColumn[sortColumn[i]] = n;
11877             }
11878           }
11879           iLast = iLook;
11880           last = randomColumn[iLook];
11881         }
11882       }
11883       for (iRow = 0; iRow < numberRows; iRow++) {
11884         CoinBigIndex start = rowStart[iRow];
11885         double sum = 0.0;
11886         int length = rowLength[iRow];
11887         for (CoinBigIndex i = start; i < start + length; i++) {
11888           int jColumn = column[i];
11889           double value = element[i];
11890           jColumn = backColumn[jColumn];
11891           sum += value * randomColumn[jColumn];
11892           //if (iColumn==23089||iRow==23729)
11893           //printf("row %d cola %d colb %d value %g rand %g sum %g\n",
11894           //   iRow,jColumn,column[i],value,randomColumn[jColumn],sum);
11895         }
11896         sortRow[iRow] = iRow;
11897         randomRow[iRow] = weight[iRow];
11898         randomRow[iRow] = sum;
11899       }
11900       CoinSort_2(randomRow, randomRow + numberRows, sortRow);
11901       for (iRow = 0; iRow < numberRows; iRow++) {
11902         int i = sortRow[iRow];
11903         backRow[i] = iRow;
11904       }
11905       randomRow[numberRows] = COIN_DBL_MAX;
11906       last = -COIN_DBL_MAX;
11907       iLast = -1;
11908       // Do backward indices from order
11909       for (iRow = 0; iRow < numberRows; iRow++) {
11910         other[order[iRow]] = iRow;
11911       }
11912       for (int iLook = 0; iLook < numberRows + 1; iLook++) {
11913         if (randomRow[iLook] > last) {
11914           if (iLast >= 0) {
11915             int n = iLook - iLast;
11916             if (n > 1) {
11917               //printf("%d rows possible?\n",n);
11918               // Within group sort as for original "order"
11919               for (int i = iLast; i < iLook; i++) {
11920                 int jRow = sortRow[i];
11921                 order[i] = other[jRow];
11922               }
11923               CoinSort_2(order + iLast, order + iLook, sortRow + iLast);
11924             }
11925             for (int i = iLast; i < iLook; i++) {
11926               possibleRow[sortRow[i]] = n;
11927             }
11928           }
11929           iLast = iLook;
11930           last = randomRow[iLook];
11931         }
11932       }
11933       // Temp out
11934       for (int iLook = 0; iLook < numberRows - 1000000; iLook++) {
11935         iRow = sortRow[iLook];
11936         CoinBigIndex start = rowStart[iRow];
11937         int length = rowLength[iRow];
11938         int numberPossible = possibleRow[iRow];
11939         for (CoinBigIndex i = start; i < start + length; i++) {
11940           int jColumn = column[i];
11941           if (possibleColumn[jColumn] != numberPossible)
11942             numberPossible = -1;
11943         }
11944         int n = numberPossible;
11945         if (numberPossible > 1) {
11946           //printf("pppppossible %d\n",numberPossible);
11947           for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) {
11948             int jRow = sortRow[jLook];
11949             CoinBigIndex start2 = rowStart[jRow];
11950             assert(numberPossible == possibleRow[jRow]);
11951             assert(length == rowLength[jRow]);
11952             for (CoinBigIndex i = start2; i < start2 + length; i++) {
11953               int jColumn = column[i];
11954               if (possibleColumn[jColumn] != numberPossible)
11955                 numberPossible = -1;
11956             }
11957           }
11958           if (numberPossible < 2) {
11959             // switch off
11960             for (int jLook = iLook; jLook < iLook + n; jLook++)
11961               possibleRow[sortRow[jLook]] = -1;
11962           }
11963           // skip rest
11964           iLook += n - 1;
11965         } else {
11966           possibleRow[iRow] = -1;
11967         }
11968       }
11969       for (int iLook = 0; iLook < numberRows; iLook++) {
11970         iRow = sortRow[iLook];
11971         int numberPossible = possibleRow[iRow];
11972         // Only if any integers
11973         int numberIntegers = 0;
11974         CoinBigIndex start = rowStart[iRow];
11975         int length = rowLength[iRow];
11976         for (CoinBigIndex i = start; i < start + length; i++) {
11977           int jColumn = column[i];
11978           if (model->isInteger(jColumn))
11979             numberIntegers++;
11980         }
11981         if (numberPossible > 1 && !numberIntegers) {
11982           //printf("possible %d - but no integers\n",numberPossible);
11983         }
11984         if (numberPossible > 1 && (numberIntegers || false)) {
11985           //
11986           printf("possible %d - %d integers\n", numberPossible, numberIntegers);
11987           int lastLook = iLook;
11988           int nMapRow = -1;
11989           for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) {
11990             // stop if too many failures
11991             if (jLook > iLook + 10 && nMapRow < 0)
11992               break;
11993             // Create identity mapping
11994             int i;
11995             for (i = 0; i < numberRows; i++)
11996               mapRow[i] = i;
11997             for (i = 0; i < numberColumns; i++)
11998               mapColumn[i] = i;
11999             int offset = jLook - iLook;
12000             int nStackC = 0;
12001             // build up row and column mapping
12002             int nStackR = 1;
12003             stackRow[0] = iLook;
12004             bool good = true;
12005             while (nStackR) {
12006               nStackR--;
12007               int look1 = stackRow[nStackR];
12008               int look2 = look1 + offset;
12009               assert(randomRow[look1] == randomRow[look2]);
12010               int row1 = sortRow[look1];
12011               int row2 = sortRow[look2];
12012               assert(mapRow[row1] == row1);
12013               assert(mapRow[row2] == row2);
12014               mapRow[row1] = row2;
12015               mapRow[row2] = row1;
12016               CoinBigIndex start1 = rowStart[row1];
12017               CoinBigIndex offset2 = rowStart[row2] - start1;
12018               int length = rowLength[row1];
12019               assert(length == rowLength[row2]);
12020               for (CoinBigIndex i = start1; i < start1 + length; i++) {
12021                 int jColumn1 = column[i];
12022                 int jColumn2 = column[i + offset2];
12023                 if (randomColumn[backColumn[jColumn1]] != randomColumn[backColumn[jColumn2]]) {
12024                   good = false;
12025                   break;
12026                 }
12027                 if (mapColumn[jColumn1] == jColumn1) {
12028                   // not touched
12029                   assert(mapColumn[jColumn2] == jColumn2);
12030                   if (jColumn1 != jColumn2) {
12031                     // Put on stack
12032                     mapColumn[jColumn1] = jColumn2;
12033                     mapColumn[jColumn2] = jColumn1;
12034                     stackColumn[nStackC++] = jColumn1;
12035                   }
12036                 } else {
12037                   if (mapColumn[jColumn1] != jColumn2 || mapColumn[jColumn2] != jColumn1) {
12038                     // bad
12039                     good = false;
12040                     printf("bad col\n");
12041                     break;
12042                   }
12043                 }
12044               }
12045               if (!good)
12046                 break;
12047               while (nStackC) {
12048                 nStackC--;
12049                 int iColumn = stackColumn[nStackC];
12050                 int iColumn2 = mapColumn[iColumn];
12051                 assert(iColumn != iColumn2);
12052                 int length = columnLength[iColumn];
12053                 assert(length == columnLength[iColumn2]);
12054                 CoinBigIndex start = columnStart[iColumn];
12055                 CoinBigIndex offset2 = columnStart[iColumn2] - start;
12056                 for (CoinBigIndex i = start; i < start + length; i++) {
12057                   int iRow = row[i];
12058                   int iRow2 = row[i + offset2];
12059                   if (mapRow[iRow] == iRow) {
12060                     // First (but be careful)
12061                     if (iRow != iRow2) {
12062                       //mapRow[iRow]=iRow2;
12063                       //mapRow[iRow2]=iRow;
12064                       int iBack = backRow[iRow];
12065                       int iBack2 = backRow[iRow2];
12066                       if (randomRow[iBack] == randomRow[iBack2] && iBack2 - iBack == offset) {
12067                         stackRow[nStackR++] = iBack;
12068                       } else {
12069                         //printf("randomRow diff - weights %g %g\n",
12070                         //     weight[iRow],weight[iRow2]);
12071                         // bad
12072                         good = false;
12073                         break;
12074                       }
12075                     }
12076                   } else {
12077                     if (mapRow[iRow] != iRow2 || mapRow[iRow2] != iRow) {
12078                       // bad
12079                       good = false;
12080                       printf("bad row\n");
12081                       break;
12082                     }
12083                   }
12084                 }
12085                 if (!good)
12086                   break;
12087               }
12088             }
12089             // then check OK
12090             if (good) {
12091               for (iRow = 0; iRow < numberRows; iRow++) {
12092                 CoinBigIndex start = rowStart[iRow];
12093                 int length = rowLength[iRow];
12094                 if (mapRow[iRow] == iRow) {
12095                   for (CoinBigIndex i = start; i < start + length; i++) {
12096                     int jColumn = column[i];
12097                     backColumn2[jColumn] = static_cast< int >(i - start);
12098                   }
12099                   for (CoinBigIndex i = start; i < start + length; i++) {
12100                     int jColumn = column[i];
12101                     if (mapColumn[jColumn] != jColumn) {
12102                       int jColumn2 = mapColumn[jColumn];
12103                       CoinBigIndex i2 = backColumn2[jColumn2];
12104                       if (i2 < 0) {
12105                         good = false;
12106                       } else if (element[i] != element[i2 + start]) {
12107                         good = false;
12108                       }
12109                     }
12110                   }
12111                   for (CoinBigIndex i = start; i < start + length; i++) {
12112                     int jColumn = column[i];
12113                     backColumn2[jColumn] = -1;
12114                   }
12115                 } else {
12116                   int row2 = mapRow[iRow];
12117                   assert(iRow = mapRow[row2]);
12118                   if (rowLower[iRow] != rowLower[row2] || rowLower[row2] != rowLower[iRow])
12119                     good = false;
12120                   CoinBigIndex offset2 = rowStart[row2] - start;
12121                   for (CoinBigIndex i = start; i < start + length; i++) {
12122                     int jColumn = column[i];
12123                     double value = element[i];
12124                     int jColumn2 = column[i + offset2];
12125                     double value2 = element[i + offset2];
12126                     if (value != value2 || mapColumn[jColumn] != jColumn2 || mapColumn[jColumn2] != jColumn)
12127                       good = false;
12128                   }
12129                 }
12130               }
12131               if (good) {
12132                 // check rim
12133                 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
12134                   if (mapColumn[iColumn] != iColumn) {
12135                     int iColumn2 = mapColumn[iColumn];
12136                     if (objective[iColumn] != objective[iColumn2])
12137                       good = false;
12138                     if (columnLower[iColumn] != columnLower[iColumn2])
12139                       good = false;
12140                     if (columnUpper[iColumn] != columnUpper[iColumn2])
12141                       good = false;
12142                     if (model->isInteger(iColumn) != model->isInteger(iColumn2))
12143                       good = false;
12144                   }
12145                 }
12146               }
12147               if (good) {
12148                 // temp
12149                 if (nMapRow < 0) {
12150                   //const double * solution = model->primalColumnSolution();
12151                   // find mapped
12152                   int nMapColumn = 0;
12153                   for (int i = 0; i < numberColumns; i++) {
12154                     if (mapColumn[i] > i)
12155                       nMapColumn++;
12156                   }
12157                   nMapRow = 0;
12158                   int kRow = -1;
12159                   for (int i = 0; i < numberRows; i++) {
12160                     if (mapRow[i] > i) {
12161                       nMapRow++;
12162                       kRow = i;
12163                     }
12164                   }
12165                   printf("%d columns, %d rows\n", nMapColumn, nMapRow);
12166                   if (nMapRow == 1) {
12167                     CoinBigIndex start = rowStart[kRow];
12168                     int length = rowLength[kRow];
12169                     printf("%g <= ", rowLower[kRow]);
12170                     for (CoinBigIndex i = start; i < start + length; i++) {
12171                       int jColumn = column[i];
12172                       if (mapColumn[jColumn] != jColumn)
12173                         printf("* ");
12174                       printf("%d,%g ", jColumn, element[i]);
12175                     }
12176                     printf("<= %g\n", rowUpper[kRow]);
12177                   }
12178                 }
12179                 // temp
12180                 int row1 = sortRow[lastLook];
12181                 int row2 = sortRow[jLook];
12182                 lastLook = jLook;
12183                 CoinBigIndex start1 = rowStart[row1];
12184                 CoinBigIndex offset2 = rowStart[row2] - start1;
12185                 int length = rowLength[row1];
12186                 assert(length == rowLength[row2]);
12187                 CoinBigIndex put = startAdd[nAddRows];
12188                 double multiplier = length < 11 ? 2.0 : 1.125;
12189                 double value = 1.0;
12190                 for (CoinBigIndex i = start1; i < start1 + length; i++) {
12191                   int jColumn1 = column[i];
12192                   int jColumn2 = column[i + offset2];
12193                   columnAdd[put] = jColumn1;
12194                   elementAdd[put++] = value;
12195                   columnAdd[put] = jColumn2;
12196                   elementAdd[put++] = -value;
12197                   value *= multiplier;
12198                 }
12199                 nAddRows++;
12200                 startAdd[nAddRows] = put;
12201               } else {
12202                 printf("ouch - did not check out as good\n");
12203               }
12204             }
12205           }
12206           // skip rest
12207           iLook += numberPossible - 1;
12208         }
12209       }
12210     }
12211     if (nAddRows) {
12212       double *lower = new double[nAddRows];
12213       double *upper = new double[nAddRows];
12214       int i;
12215       //const double * solution = model->primalColumnSolution();
12216       for (i = 0; i < nAddRows; i++) {
12217         lower[i] = 0.0;
12218         upper[i] = COIN_DBL_MAX;
12219       }
12220       printf("Adding %d rows with %d elements\n", nAddRows,
12221         startAdd[nAddRows]);
12222       //ClpSimplex newModel(*model);
12223       //newModel.addRows(nAddRows,lower,upper,startAdd,columnAdd,elementAdd);
12224       //newModel.writeMps("modified.mps");
12225       delete[] lower;
12226       delete[] upper;
12227     }
12228     delete[] startAdd;
12229     delete[] columnAdd;
12230     delete[] elementAdd;
12231     delete[] order;
12232     delete[] other;
12233     delete[] randomColumn;
12234     delete[] weight;
12235     delete[] randomRow;
12236     delete[] sortRow;
12237     delete[] backRow;
12238     delete[] possibleRow;
12239     delete[] sortColumn;
12240     delete[] backColumn;
12241     delete[] backColumn2;
12242     delete[] possibleColumn;
12243     delete[] mapRow;
12244     delete[] mapColumn;
12245     delete[] stackRow;
12246     delete[] stackColumn;
12247   }
12248   delete[] number;
12249   // Now do breakdown of ranges
12250   breakdown("Elements", static_cast< int >(numberElements), elementByColumn);
12251   breakdown("RowLower", numberRows, rowLower);
12252   breakdown("RowUpper", numberRows, rowUpper);
12253   breakdown("ColumnLower", numberColumns, columnLower);
12254   breakdown("ColumnUpper", numberColumns, columnUpper);
12255   breakdown("Objective", numberColumns, objective);
12256 }
12257 
maskMatches(const int * starts,char ** masks,std::string & check)12258 static bool maskMatches(const int *starts, char **masks,
12259   std::string &check)
12260 {
12261   // back to char as I am old fashioned
12262   const char *checkC = check.c_str();
12263   size_t length = strlen(checkC);
12264   while (length > 0 && checkC[length - 1] == ' ')
12265     length--;
12266   for (int i = starts[length]; i < starts[length + 1]; i++) {
12267     char *thisMask = masks[i];
12268     size_t k;
12269     for (k = 0; k < length; k++) {
12270       if (thisMask[k] != '?' && thisMask[k] != checkC[k])
12271         break;
12272     }
12273     if (k == length)
12274       return true;
12275   }
12276   return false;
12277 }
12278 
clean(char * temp)12279 static void clean(char *temp)
12280 {
12281   char *put = temp;
12282   while (*put >= ' ')
12283     put++;
12284   *put = '\0';
12285 }
12286 
generateCode(CbcModel *,const char * fileName,int type,int preProcess)12287 static void generateCode(CbcModel * /*model*/, const char *fileName, int type, int preProcess)
12288 {
12289   // options on code generation
12290   bool sizecode = (type & 4) != 0;
12291   type &= 3;
12292   FILE *fp = fopen(fileName, "r");
12293   assert(fp);
12294   int numberLines = 0;
12295 #define MAXLINES 5000
12296 #define MAXONELINE 200
12297   char line[MAXLINES][MAXONELINE];
12298   strcpy(line[numberLines++], "0#if defined(_MSC_VER)");
12299   strcpy(line[numberLines++], "0// Turn off compiler warning about long names");
12300   strcpy(line[numberLines++], "0#  pragma warning(disable:4786)");
12301   strcpy(line[numberLines++], "0#endif\n");
12302   strcpy(line[numberLines++], "0#include <cassert>");
12303   strcpy(line[numberLines++], "0#include <iomanip>");
12304   strcpy(line[numberLines++], "0#include \"OsiClpSolverInterface.hpp\"");
12305   strcpy(line[numberLines++], "0#include \"CbcModel.hpp\"");
12306   strcpy(line[numberLines++], "0#include \"CbcCutGenerator.hpp\"");
12307   strcpy(line[numberLines++], "0#include \"CbcStrategy.hpp\"");
12308   strcpy(line[numberLines++], "0#include \"CglPreProcess.hpp\"");
12309   strcpy(line[numberLines++], "0#include \"CoinTime.hpp\"");
12310   if (preProcess > 0)
12311     strcpy(line[numberLines++], "0#include \"CglProbing.hpp\""); // possibly redundant
12312   // To allow generated 5's to be just before branchAndBound - do rest here
12313   strcpy(line[numberLines++], "5  cbcModel->initialSolve();");
12314   strcpy(line[numberLines++], "5  if (clpModel->tightenPrimalBounds()!=0) {");
12315   strcpy(line[numberLines++], "5    std::cout<<\"Problem is infeasible - tightenPrimalBounds!\"<<std::endl;");
12316   strcpy(line[numberLines++], "5    exit(1);");
12317   strcpy(line[numberLines++], "5  }");
12318   strcpy(line[numberLines++], "5  clpModel->dual();  // clean up");
12319   if (sizecode) {
12320     // override some settings
12321     strcpy(line[numberLines++], "5  // compute some things using problem size");
12322     strcpy(line[numberLines++], "5  cbcModel->setMinimumDrop(CoinMin(5.0e-2,");
12323     strcpy(line[numberLines++], "5       fabs(cbcModel->getMinimizationObjValue())*1.0e-3+1.0e-4));");
12324     strcpy(line[numberLines++], "5  if (cbcModel->getNumCols()<500)");
12325     strcpy(line[numberLines++], "5    cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible");
12326     strcpy(line[numberLines++], "5  else if (cbcModel->getNumCols()<5000)");
12327     strcpy(line[numberLines++], "5    cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop");
12328     strcpy(line[numberLines++], "5  else");
12329     strcpy(line[numberLines++], "5    cbcModel->setMaximumCutPassesAtRoot(20);");
12330     strcpy(line[numberLines++], "5  cbcModel->setMaximumCutPasses(1);");
12331   }
12332   if (preProcess <= 0) {
12333     // no preprocessing or strategy
12334     if (preProcess) {
12335       strcpy(line[numberLines++], "5  // Preprocessing using CbcStrategy");
12336       strcpy(line[numberLines++], "5  CbcStrategyDefault strategy(1,5,5);");
12337       strcpy(line[numberLines++], "5  strategy.setupPreProcessing(1);");
12338       strcpy(line[numberLines++], "5  cbcModel->setStrategy(strategy);");
12339     }
12340   } else {
12341     int translate[] = { 9999, 0, 0, -1, 2, 3, -2 };
12342     strcpy(line[numberLines++], "5  // Hand coded preprocessing");
12343     strcpy(line[numberLines++], "5  CglPreProcess process;");
12344     strcpy(line[numberLines++], "5  OsiSolverInterface * saveSolver=cbcModel->solver()->clone();");
12345     strcpy(line[numberLines++], "5  // Tell solver we are in Branch and Cut");
12346     strcpy(line[numberLines++], "5  saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;");
12347     strcpy(line[numberLines++], "5  // Default set of cut generators");
12348     strcpy(line[numberLines++], "5  CglProbing generator1;");
12349     strcpy(line[numberLines++], "5  generator1.setUsingObjective(1);");
12350     strcpy(line[numberLines++], "5  generator1.setMaxPass(3);");
12351     strcpy(line[numberLines++], "5  generator1.setMaxProbeRoot(saveSolver->getNumCols());");
12352     strcpy(line[numberLines++], "5  generator1.setMaxElements(100);");
12353     strcpy(line[numberLines++], "5  generator1.setMaxLookRoot(50);");
12354     strcpy(line[numberLines++], "5  generator1.setRowCuts(3);");
12355     strcpy(line[numberLines++], "5  // Add in generators");
12356     strcpy(line[numberLines++], "5  process.addCutGenerator(&generator1);");
12357     strcpy(line[numberLines++], "5  process.messageHandler()->setLogLevel(cbcModel->logLevel());");
12358     strcpy(line[numberLines++], "5  OsiSolverInterface * solver2 = ");
12359     sprintf(line[numberLines++], "5    process.preProcessNonDefault(*saveSolver,%d,10);", translate[preProcess]);
12360     strcpy(line[numberLines++], "5  // Tell solver we are not in Branch and Cut");
12361     strcpy(line[numberLines++], "5  saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;");
12362     strcpy(line[numberLines++], "5  if (solver2)");
12363     strcpy(line[numberLines++], "5    solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;");
12364     strcpy(line[numberLines++], "5  if (!solver2) {");
12365     strcpy(line[numberLines++], "5    std::cout<<\"Pre-processing says infeasible!\"<<std::endl;");
12366     strcpy(line[numberLines++], "5    exit(1);");
12367     strcpy(line[numberLines++], "5  } else {");
12368     strcpy(line[numberLines++], "5    std::cout<<\"processed model has \"<<solver2->getNumRows()");
12369     strcpy(line[numberLines++], "5	     <<\" rows, \"<<solver2->getNumCols()");
12370     strcpy(line[numberLines++], "5	     <<\" columns and \"<<solver2->getNumElements()");
12371     strcpy(line[numberLines++], "5	     <<\" elements\"<<solver2->getNumElements()<<std::endl;");
12372     strcpy(line[numberLines++], "5  }");
12373     strcpy(line[numberLines++], "5  // we have to keep solver2 so pass clone");
12374     strcpy(line[numberLines++], "5  solver2 = solver2->clone();");
12375     strcpy(line[numberLines++], "5  cbcModel->assignSolver(solver2);");
12376     strcpy(line[numberLines++], "5  cbcModel->initialSolve();");
12377   }
12378   while (fgets(line[numberLines], MAXONELINE, fp)) {
12379     assert(numberLines < MAXLINES);
12380     clean(line[numberLines]);
12381     numberLines++;
12382   }
12383   fclose(fp);
12384   strcpy(line[numberLines++], "0\nint main (int argc, const char *argv[])\n{");
12385   strcpy(line[numberLines++], "0  OsiClpSolverInterface solver1;");
12386   strcpy(line[numberLines++], "0  int status=1;");
12387   strcpy(line[numberLines++], "0  if (argc<2)");
12388   strcpy(line[numberLines++], "0    std::cout<<\"Please give file name\"<<std::endl;");
12389   strcpy(line[numberLines++], "0  else");
12390   strcpy(line[numberLines++], "0    status=solver1.readMps(argv[1],\"\");");
12391   strcpy(line[numberLines++], "0  if (status) {");
12392   strcpy(line[numberLines++], "0    std::cout<<\"Bad readMps \"<<argv[1]<<std::endl;");
12393   strcpy(line[numberLines++], "0    exit(1);");
12394   strcpy(line[numberLines++], "0  }\n");
12395   strcpy(line[numberLines++], "0  double time1 = CoinCpuTime();");
12396   strcpy(line[numberLines++], "0  CbcModel model(solver1);");
12397   strcpy(line[numberLines++], "0  // Now do requested saves and modifications");
12398   strcpy(line[numberLines++], "0  CbcModel * cbcModel = & model;");
12399   strcpy(line[numberLines++], "0  OsiSolverInterface * osiModel = model.solver();");
12400   strcpy(line[numberLines++], "0  OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel);");
12401   strcpy(line[numberLines++], "0  ClpSimplex * clpModel = osiclpModel->getModelPtr();");
12402   // add in comments about messages
12403   strcpy(line[numberLines++], "3  // You can save some time by switching off message building");
12404   strcpy(line[numberLines++], "3  // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);");
12405   // add in actual solve
12406   strcpy(line[numberLines++], "5  cbcModel->branchAndBound();");
12407   strcpy(line[numberLines++], "8  std::cout<<argv[1]<<\" took \"<<CoinCpuTime()-time1<<\" seconds, \"");
12408   strcpy(line[numberLines++], "8	   <<cbcModel->getNodeCount()<<\" nodes with objective \"");
12409   strcpy(line[numberLines++], "8	   <<cbcModel->getObjValue()");
12410   strcpy(line[numberLines++], "8	   <<(!cbcModel->status() ? \" Finished\" : \" Not finished\")");
12411   strcpy(line[numberLines++], "8	   <<std::endl;");
12412   strcpy(line[numberLines++], "5  // For best solution");
12413   strcpy(line[numberLines++], "5  int numberColumns = solver1.getNumCols();");
12414   strcpy(line[numberLines++], "5  if (cbcModel->getMinimizationObjValue()<1.0e50) {");
12415   if (preProcess > 0) {
12416     strcpy(line[numberLines++], "5    // post process");
12417     strcpy(line[numberLines++], "5    process.postProcess(*cbcModel->solver());");
12418     strcpy(line[numberLines++], "5    // Solution now back in saveSolver");
12419     strcpy(line[numberLines++], "5    cbcModel->assignSolver(saveSolver);");
12420     strcpy(line[numberLines++], "5    memcpy(cbcModel->bestSolution(),cbcModel->solver()->getColSolution(),");
12421     strcpy(line[numberLines++], "5	   numberColumns*sizeof(double));");
12422   }
12423   strcpy(line[numberLines++], "5    // put back in original solver");
12424   strcpy(line[numberLines++], "5    solver1.setColSolution(cbcModel->bestSolution());");
12425   strcpy(line[numberLines++], "5    const double * solution = solver1.getColSolution();");
12426   strcpy(line[numberLines++], "8  \n  // Now you would use solution etc etc\n");
12427   strcpy(line[numberLines++], "5");
12428   strcpy(line[numberLines++], "5    // Get names from solver1 (as OsiSolverInterface may lose)");
12429   strcpy(line[numberLines++], "5    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();");
12430   strcpy(line[numberLines++], "5    ");
12431   strcpy(line[numberLines++], "5    int iColumn;");
12432   strcpy(line[numberLines++], "5    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);");
12433   strcpy(line[numberLines++], "5    ");
12434   strcpy(line[numberLines++], "5    std::cout<<\"--------------------------------------\"<<std::endl;");
12435   strcpy(line[numberLines++], "5    for (iColumn=0;iColumn<numberColumns;iColumn++) {");
12436   strcpy(line[numberLines++], "5      double value=solution[iColumn];");
12437   strcpy(line[numberLines++], "5      if (fabs(value)>1.0e-7&&solver1.isInteger(iColumn)) ");
12438   strcpy(line[numberLines++], "5	std::cout<<std::setw(6)<<iColumn<<\" \"");
12439   strcpy(line[numberLines++], "5                 <<columnNames[iColumn]<<\" \"");
12440   strcpy(line[numberLines++], "5                 <<value<<std::endl;");
12441   strcpy(line[numberLines++], "5    }");
12442   strcpy(line[numberLines++], "5    std::cout<<\"--------------------------------------\"<<std::endl;");
12443   strcpy(line[numberLines++], "5  ");
12444   strcpy(line[numberLines++], "5    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);");
12445   strcpy(line[numberLines++], "5  }");
12446   strcpy(line[numberLines++], "8  return 0;\n}");
12447   fp = fopen(fileName, "w");
12448   assert(fp);
12449 
12450   int wanted[9];
12451   memset(wanted, 0, sizeof(wanted));
12452   wanted[0] = wanted[3] = wanted[5] = wanted[8] = 1;
12453   if (type > 0)
12454     wanted[1] = wanted[6] = 1;
12455   if (type > 1)
12456     wanted[2] = wanted[4] = wanted[7] = 1;
12457   std::string header[9] = { "", "Save values", "Redundant save of default values", "Set changed values",
12458     "Redundant set default values", "Solve", "Restore values", "Redundant restore values", "Finish up" };
12459   for (int iType = 0; iType < 9; iType++) {
12460     if (!wanted[iType])
12461       continue;
12462     int n = 0;
12463     int iLine;
12464     for (iLine = 0; iLine < numberLines; iLine++) {
12465       if (line[iLine][0] == '0' + iType) {
12466         if (!n && header[iType] != "")
12467           fprintf(fp, "\n  // %s\n\n", header[iType].c_str());
12468         n++;
12469         // skip save and clp as cloned
12470         if (!strstr(line[iLine], "save") || (!strstr(line[iLine], "clpMo") && !strstr(line[iLine], "_Osi")))
12471           fprintf(fp, "%s\n", line[iLine] + 1);
12472       }
12473     }
12474   }
12475   fclose(fp);
12476   printf("C++ file written to %s\n", fileName);
12477 }
12478 // Print a general message
printGeneralMessage(CbcModel & model,const char * message)12479 static void printGeneralMessage(CbcModel &model, const char *message)
12480 {
12481 #ifndef DISALLOW_PRINTING
12482   model.messageHandler()->message(CBC_FPUMP1, model.messages())
12483     << message
12484     << CoinMessageEol;
12485 #endif
12486 }
12487 #ifdef COIN_HAS_NTY
12488 #include "CbcSymmetry.hpp"
12489 // returns number of constraints added
nautiedConstraints(CbcModel & model,int maxPass)12490 static int nautiedConstraints(CbcModel &model, int maxPass)
12491 {
12492   bool changed = true;
12493   int numberAdded = 0;
12494   int numberPasses = 0;
12495   int changeType = 0; //(more2&(128|256))>>7;
12496   OsiSolverInterface *solverOriginal = model.solver();
12497 #define REALLY_CHANGE
12498 #ifdef REALLY_CHANGE
12499   OsiSolverInterface *solver = solverOriginal;
12500 #else
12501   int numberOriginalRows = solverOriginal->getNumRows();
12502   OsiSolverInterface *solver = solverOriginal->clone();
12503 #endif
12504   while (changed) {
12505     changed = false;
12506     CbcSymmetry symmetryInfo;
12507     //symmetryInfo.setModel(&model);
12508     // for now strong is just on counts - use user option
12509     //int maxN=5000000;
12510     //OsiSolverInterface * solver = model.solver();
12511     symmetryInfo.setupSymmetry(&model);
12512     int numberGenerators = symmetryInfo.statsOrbits(&model, 0);
12513     if (numberGenerators) {
12514       //symmetryInfo.Print_Orbits();
12515       int numberUsefulOrbits = symmetryInfo.numberUsefulOrbits();
12516       if (numberUsefulOrbits) {
12517         symmetryInfo.Compute_Symmetry();
12518         symmetryInfo.fillOrbits(/*true*/);
12519         const int *orbits = symmetryInfo.whichOrbit();
12520         int numberUsefulOrbits = symmetryInfo.numberUsefulOrbits();
12521         int *counts = new int[numberUsefulOrbits];
12522         memset(counts, 0, numberUsefulOrbits * sizeof(int));
12523         int numberColumns = solver->getNumCols();
12524         int numberUseful = 0;
12525         if (changeType == 1) {
12526           // just 0-1
12527           for (int i = 0; i < numberColumns; i++) {
12528             int iOrbit = orbits[i];
12529             if (iOrbit >= 0) {
12530               if (solver->isBinary(i)) {
12531                 counts[iOrbit]++;
12532                 numberUseful++;
12533               }
12534             }
12535           }
12536         } else if (changeType == 2) {
12537           // just integer
12538           for (int i = 0; i < numberColumns; i++) {
12539             int iOrbit = orbits[i];
12540             if (iOrbit >= 0) {
12541               if (solver->isInteger(i)) {
12542                 counts[iOrbit]++;
12543                 numberUseful++;
12544               }
12545             }
12546           }
12547         } else {
12548           // all
12549           for (int i = 0; i < numberColumns; i++) {
12550             int iOrbit = orbits[i];
12551             if (iOrbit >= 0) {
12552               counts[iOrbit]++;
12553               numberUseful++;
12554             }
12555           }
12556         }
12557         int iOrbit = -1;
12558 #define LONGEST 0
12559 #if LONGEST
12560         // choose longest
12561         int maxOrbit = 0;
12562         for (int i = 0; i < numberUsefulOrbits; i++) {
12563           if (counts[i] > maxOrbit) {
12564             maxOrbit = counts[i];
12565             iOrbit = i;
12566           }
12567         }
12568 #else
12569         // choose closest to 2
12570         int minOrbit = numberColumns + 1;
12571         for (int i = 0; i < numberUsefulOrbits; i++) {
12572           if (counts[i] > 1 && counts[i] < minOrbit) {
12573             minOrbit = counts[i];
12574             iOrbit = i;
12575           }
12576         }
12577 #endif
12578         delete[] counts;
12579         if (!numberUseful)
12580           break;
12581         // take largest
12582         const double *solution = solver->getColSolution();
12583         double *size = new double[numberColumns];
12584         int *which = new int[numberColumns];
12585         int nIn = 0;
12586         for (int i = 0; i < numberColumns; i++) {
12587           if (orbits[i] == iOrbit) {
12588             size[nIn] = -solution[i];
12589             which[nIn++] = i;
12590           }
12591         }
12592         if (nIn > 1) {
12593           //printf("Using orbit length %d\n",nIn);
12594           CoinSort_2(size, size + nIn, which);
12595           size[0] = 1.0;
12596           size[1] = -1.0;
12597 #if LONGEST == 0
12598           solver->addRow(2, which, size, 0.0, COIN_DBL_MAX);
12599           numberAdded++;
12600 #elif LONGEST == 1
12601           for (int i = 0; i < nIn - 1; i++) {
12602             solver->addRow(2, which + i, size, 0.0, COIN_DBL_MAX);
12603             numberAdded++;
12604           }
12605 #else
12606           for (int i = 0; i < nIn - 1; i++) {
12607             solver->addRow(2, which, size, 0.0, COIN_DBL_MAX);
12608             which[1] = which[2 + i];
12609             numberAdded++;
12610           }
12611 #endif
12612           numberPasses++;
12613           if (numberPasses < maxPass)
12614             changed = true;
12615         }
12616         delete[] size;
12617         delete[] which;
12618       }
12619     }
12620   }
12621   if (numberAdded) {
12622     char general[100];
12623     if (numberPasses < maxPass)
12624       sprintf(general, "%d constraints added in %d passes", numberAdded,
12625         numberPasses);
12626     else
12627       sprintf(general, "%d constraints added in %d passes (maximum) - must be better way", numberAdded,
12628         numberPasses);
12629     model.messageHandler()->message(CBC_GENERAL,
12630       model.messages())
12631       << general << CoinMessageEol;
12632 #ifdef SAVE_NAUTY
12633     OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
12634     ClpSimplex *lpSolver = clpSolver->getModelPtr();
12635     char name[100];
12636     strcpy(name, lpSolver->problemName().c_str());
12637     strcat(name, "_nauty");
12638     printf("saving model on %s\n", name);
12639     solver->writeMps(name);
12640 #endif
12641   }
12642 #ifndef REALLY_CHANGE
12643   CbcRowCuts *globalCuts = model.globalCuts();
12644   int numberRows = solver->getNumRows();
12645   if (numberRows > numberOriginalRows) {
12646     const CoinPackedMatrix *rowCopy = solver->getMatrixByRow();
12647     const int *column = rowCopy->getIndices();
12648     const int *rowLength = rowCopy->getVectorLengths();
12649     const CoinBigIndex *rowStart = rowCopy->getVectorStarts();
12650     const double *elements = rowCopy->getElements();
12651     const double *rowLower = solver->getRowLower();
12652     const double *rowUpper = solver->getRowUpper();
12653     for (int iRow = numberOriginalRows; iRow < numberRows; iRow++) {
12654       OsiRowCut rc;
12655       rc.setLb(rowLower[iRow]);
12656       rc.setUb(rowUpper[iRow]);
12657       CoinBigIndex start = rowStart[iRow];
12658       rc.setRow(rowLength[iRow], column + start, elements + start, false);
12659       globalCuts->addCutIfNotDuplicate(rc);
12660     }
12661   }
12662   delete solver;
12663 #endif
12664   return numberAdded;
12665 }
12666 #endif
12667 /*
12668   Version 1.00.00 November 16 2005.
12669   This is to stop me (JJF) messing about too much.
12670   Tuning changes should be noted here.
12671   The testing next version may be activated by CBC_NEXT_VERSION
12672   This applies to OsiClp, Clp etc
12673   Version 1.00.01 November 24 2005
12674   Added several classes for advanced users.  This can't affect code (if you don't use it)
12675   Made some tiny changes (for N way branching) which should not change anything.
12676   CbcNWay object class - for N way branching this also allows use of CbcConsequence class.
12677   CbcBranchAllDifferent object class - for branching on general integer variables
12678   to stop them having same value so branches are x >= y+1 and x <= y-1.
12679   Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly)
12680   and CglStored which just has a list of cuts which can be activated.
12681   Modified preprocess option to SOS
12682   Version 1.00.02 December 9 2005
12683   Added use of CbcStrategy to do clean preprocessing
12684   Added use of referenceSolver for cleaner repetition of Cbc
12685   Version 1.01.00 February 2 2006
12686   Added first try at Ampl interface
12687   Version 1.04 June 2007
12688   Goes parallel
12689   Version 2.00 September 2007
12690   Improvements to feaspump
12691   Source code changes so up to 2.0
12692 */
12693 
12694 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
12695 */
12696