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 ¶meterData);
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 ¶meterData)
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 ¶meterData)
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 ¶meters = 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 ¶meters = 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 ¶meterData)
10648 {
10649 std::vector< CbcOrClpParam > ¶meters = 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