1 /* $Id: CbcOrClpParam.cpp 2476 2019-06-13 14:49:27Z stefan $ */
2 // Copyright (C) 2002, 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 #include "CoinPragma.hpp"
7 #include "CoinTime.hpp"
8 #include "CbcOrClpParam.hpp"
9
10 #include <string>
11 #include <iostream>
12 #include <cassert>
13
14 #ifdef COIN_HAS_CBC
15 #ifdef COIN_HAS_CLP
16 #include "OsiClpSolverInterface.hpp"
17 #include "ClpSimplex.hpp"
18 #endif
19 #include "CbcModel.hpp"
20 #endif
21 #include "CoinHelperFunctions.hpp"
22 #ifdef COIN_HAS_CLP
23 #include "ClpSimplex.hpp"
24 #include "ClpFactorization.hpp"
25 #endif
26 #ifdef COIN_HAS_READLINE
27 #include <readline/readline.h>
28 #include <readline/history.h>
29 #endif
30 #ifdef COIN_HAS_CBC
31 // from CoinSolve
32 static char coin_prompt[] = "Coin:";
33 #else
34 static char coin_prompt[] = "Clp:";
35 #endif
36 #ifdef CLP_CILK
37 #ifndef CBC_THREAD
38 #define CBC_THREAD
39 #endif
40 #endif
41 #if defined(COIN_HAS_WSMP) && !defined(USE_EKKWSSMP)
42 #ifndef CBC_THREAD
43 #define CBC_THREAD
44 #endif
45 #endif
46 #include "ClpConfig.h"
47 #ifdef CLP_HAS_ABC
48 #include "AbcCommon.hpp"
49 #endif
50 static bool doPrinting = true;
51 static std::string afterEquals = "";
52 static char printArray[250];
53 #if COIN_INT_MAX == 0
54 #undef COIN_INT_MAX
55 #define COIN_INT_MAX 2147483647
56 #endif
57 #if FLUSH_PRINT_BUFFER > 2
58 int coinFlushBufferFlag = 0;
59 #endif
setCbcOrClpPrinting(bool yesNo)60 void setCbcOrClpPrinting(bool yesNo)
61 {
62 doPrinting = yesNo;
63 }
64 //#############################################################################
65 // Constructors / Destructor / Assignment
66 //#############################################################################
67
68 //-------------------------------------------------------------------
69 // Default Constructor
70 //-------------------------------------------------------------------
CbcOrClpParam()71 CbcOrClpParam::CbcOrClpParam()
72 : type_(CBC_PARAM_NOTUSED_INVALID)
73 , lowerDoubleValue_(0.0)
74 , upperDoubleValue_(0.0)
75 , lowerIntValue_(0)
76 , upperIntValue_(0)
77 , lengthName_(0)
78 , lengthMatch_(0)
79 , definedKeyWords_()
80 , name_()
81 , shortHelp_()
82 , longHelp_()
83 , action_(CBC_PARAM_NOTUSED_INVALID)
84 , currentKeyWord_(-1)
85 , display_(0)
86 , intValue_(-1)
87 , doubleValue_(-1.0)
88 , stringValue_("")
89 , whereUsed_(7)
90 , fakeKeyWord_(-1)
91 , fakeValue_(0)
92 {
93 }
94 // Other constructors
CbcOrClpParam(std::string name,std::string help,double lower,double upper,CbcOrClpParameterType type,int display)95 CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
96 double lower, double upper, CbcOrClpParameterType type,
97 int display)
98 : type_(type)
99 , lowerIntValue_(0)
100 , upperIntValue_(0)
101 , definedKeyWords_()
102 , name_(name)
103 , shortHelp_(help)
104 , longHelp_()
105 , action_(type)
106 , currentKeyWord_(-1)
107 , display_(display)
108 , intValue_(-1)
109 , doubleValue_(-1.0)
110 , stringValue_("")
111 , whereUsed_(7)
112 , fakeKeyWord_(-1)
113 , fakeValue_(0)
114 {
115 lowerDoubleValue_ = lower;
116 upperDoubleValue_ = upper;
117 gutsOfConstructor();
118 }
CbcOrClpParam(std::string name,std::string help,int lower,int upper,CbcOrClpParameterType type,int display)119 CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
120 int lower, int upper, CbcOrClpParameterType type,
121 int display)
122 : type_(type)
123 , lowerDoubleValue_(0.0)
124 , upperDoubleValue_(0.0)
125 , definedKeyWords_()
126 , name_(name)
127 , shortHelp_(help)
128 , longHelp_()
129 , action_(type)
130 , currentKeyWord_(-1)
131 , display_(display)
132 , intValue_(-1)
133 , doubleValue_(-1.0)
134 , stringValue_("")
135 , whereUsed_(7)
136 , fakeKeyWord_(-1)
137 , fakeValue_(0)
138 {
139 gutsOfConstructor();
140 lowerIntValue_ = lower;
141 upperIntValue_ = upper;
142 }
143 // Other strings will be added by append
CbcOrClpParam(std::string name,std::string help,std::string firstValue,CbcOrClpParameterType type,int whereUsed,int display)144 CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
145 std::string firstValue,
146 CbcOrClpParameterType type, int whereUsed,
147 int display)
148 : type_(type)
149 , lowerDoubleValue_(0.0)
150 , upperDoubleValue_(0.0)
151 , lowerIntValue_(0)
152 , upperIntValue_(0)
153 , definedKeyWords_()
154 , name_(name)
155 , shortHelp_(help)
156 , longHelp_()
157 , action_(type)
158 , currentKeyWord_(0)
159 , display_(display)
160 , intValue_(-1)
161 , doubleValue_(-1.0)
162 , stringValue_("")
163 , whereUsed_(whereUsed)
164 , fakeKeyWord_(-1)
165 , fakeValue_(0)
166 {
167 gutsOfConstructor();
168 definedKeyWords_.push_back(firstValue);
169 }
170 // Action
CbcOrClpParam(std::string name,std::string help,CbcOrClpParameterType type,int whereUsed,int display)171 CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
172 CbcOrClpParameterType type, int whereUsed,
173 int display)
174 : type_(type)
175 , lowerDoubleValue_(0.0)
176 , upperDoubleValue_(0.0)
177 , lowerIntValue_(0)
178 , upperIntValue_(0)
179 , definedKeyWords_()
180 , name_(name)
181 , shortHelp_(help)
182 , longHelp_()
183 , action_(type)
184 , currentKeyWord_(-1)
185 , display_(display)
186 , intValue_(-1)
187 , doubleValue_(-1.0)
188 , stringValue_("")
189 , fakeKeyWord_(-1)
190 , fakeValue_(0)
191 {
192 whereUsed_ = whereUsed;
193 gutsOfConstructor();
194 }
195
196 //-------------------------------------------------------------------
197 // Copy constructor
198 //-------------------------------------------------------------------
CbcOrClpParam(const CbcOrClpParam & rhs)199 CbcOrClpParam::CbcOrClpParam(const CbcOrClpParam &rhs)
200 {
201 type_ = rhs.type_;
202 lowerDoubleValue_ = rhs.lowerDoubleValue_;
203 upperDoubleValue_ = rhs.upperDoubleValue_;
204 lowerIntValue_ = rhs.lowerIntValue_;
205 upperIntValue_ = rhs.upperIntValue_;
206 lengthName_ = rhs.lengthName_;
207 lengthMatch_ = rhs.lengthMatch_;
208 definedKeyWords_ = rhs.definedKeyWords_;
209 name_ = rhs.name_;
210 shortHelp_ = rhs.shortHelp_;
211 longHelp_ = rhs.longHelp_;
212 action_ = rhs.action_;
213 currentKeyWord_ = rhs.currentKeyWord_;
214 display_ = rhs.display_;
215 intValue_ = rhs.intValue_;
216 doubleValue_ = rhs.doubleValue_;
217 stringValue_ = rhs.stringValue_;
218 whereUsed_ = rhs.whereUsed_;
219 fakeKeyWord_ = rhs.fakeKeyWord_;
220 fakeValue_ = rhs.fakeValue_;
221 }
222
223 //-------------------------------------------------------------------
224 // Destructor
225 //-------------------------------------------------------------------
~CbcOrClpParam()226 CbcOrClpParam::~CbcOrClpParam()
227 {
228 }
229
230 //----------------------------------------------------------------
231 // Assignment operator
232 //-------------------------------------------------------------------
233 CbcOrClpParam &
operator =(const CbcOrClpParam & rhs)234 CbcOrClpParam::operator=(const CbcOrClpParam &rhs)
235 {
236 if (this != &rhs) {
237 type_ = rhs.type_;
238 lowerDoubleValue_ = rhs.lowerDoubleValue_;
239 upperDoubleValue_ = rhs.upperDoubleValue_;
240 lowerIntValue_ = rhs.lowerIntValue_;
241 upperIntValue_ = rhs.upperIntValue_;
242 lengthName_ = rhs.lengthName_;
243 lengthMatch_ = rhs.lengthMatch_;
244 definedKeyWords_ = rhs.definedKeyWords_;
245 name_ = rhs.name_;
246 shortHelp_ = rhs.shortHelp_;
247 longHelp_ = rhs.longHelp_;
248 action_ = rhs.action_;
249 currentKeyWord_ = rhs.currentKeyWord_;
250 display_ = rhs.display_;
251 intValue_ = rhs.intValue_;
252 doubleValue_ = rhs.doubleValue_;
253 stringValue_ = rhs.stringValue_;
254 whereUsed_ = rhs.whereUsed_;
255 fakeKeyWord_ = rhs.fakeKeyWord_;
256 fakeValue_ = rhs.fakeValue_;
257 }
258 return *this;
259 }
gutsOfConstructor()260 void CbcOrClpParam::gutsOfConstructor()
261 {
262 std::string::size_type shriekPos = name_.find('!');
263 lengthName_ = static_cast< unsigned int >(name_.length());
264 if (shriekPos == std::string::npos) {
265 //does not contain '!'
266 lengthMatch_ = lengthName_;
267 } else {
268 lengthMatch_ = static_cast< unsigned int >(shriekPos);
269 name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1);
270 lengthName_--;
271 }
272 }
273 // Sets value of fake keyword to current size of keywords
setFakeKeyWord(int fakeValue)274 void CbcOrClpParam::setFakeKeyWord(int fakeValue)
275 {
276 fakeKeyWord_ = static_cast< int >(definedKeyWords_.size());
277 assert(fakeKeyWord_ > 0);
278 fakeValue_ = fakeValue;
279 assert(fakeValue_ >= 0);
280 }
281 /* Returns current parameter option position
282 but if fake keyword returns fakeValue_
283 */
currentOptionAsInteger() const284 int CbcOrClpParam::currentOptionAsInteger() const
285 {
286 int fakeInteger;
287 return currentOptionAsInteger(fakeInteger);
288 }
289 /* Returns current parameter option position
290 but if fake keyword returns fakeValue_ and sets
291 fakeInteger to value
292 */
currentOptionAsInteger(int & fakeInteger) const293 int CbcOrClpParam::currentOptionAsInteger(int &fakeInteger) const
294 {
295 fakeInteger = -COIN_INT_MAX;
296 if (fakeKeyWord_ < 0) {
297 return currentKeyWord_;
298 } else if (currentKeyWord_ >= 0 && currentKeyWord_ < fakeKeyWord_) {
299 return currentKeyWord_;
300 } else {
301 // fake
302 if (currentKeyWord_ < 0)
303 fakeInteger = currentKeyWord_ + 1000;
304 else
305 fakeInteger = currentKeyWord_ - 1000;
306 return fakeValue_;
307 }
308 }
309 // Returns length of name for printing
lengthMatchName() const310 int CbcOrClpParam::lengthMatchName() const
311 {
312 if (lengthName_ == lengthMatch_)
313 return lengthName_;
314 else
315 return lengthName_ + 2;
316 }
317 // Insert string (only valid for keywords)
append(std::string keyWord)318 void CbcOrClpParam::append(std::string keyWord)
319 {
320 definedKeyWords_.push_back(keyWord);
321 }
322
matches(std::string input) const323 int CbcOrClpParam::matches(std::string input) const
324 {
325 // look up strings to do more elegantly
326 if (input.length() > lengthName_) {
327 return 0;
328 } else {
329 unsigned int i;
330 for (i = 0; i < input.length(); i++) {
331 if (tolower(name_[i]) != tolower(input[i]))
332 break;
333 }
334 if (i < input.length()) {
335 return 0;
336 } else if (i >= lengthMatch_) {
337 return 1;
338 } else {
339 // matched but too short
340 return 2;
341 }
342 }
343 }
344 // Returns name which could match
345 std::string
matchName() const346 CbcOrClpParam::matchName() const
347 {
348 if (lengthMatch_ == lengthName_)
349 return name_;
350 else
351 return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + ")";
352 }
353
354 // Returns parameter option which matches (-1 if none)
parameterOption(std::string check) const355 int CbcOrClpParam::parameterOption(std::string check) const
356 {
357 int numberItems = static_cast< int >(definedKeyWords_.size());
358 if (!numberItems) {
359 return -1;
360 } else {
361 int whichItem = 0;
362 unsigned int it;
363 for (it = 0; it < definedKeyWords_.size(); it++) {
364 std::string thisOne = definedKeyWords_[it];
365 std::string::size_type shriekPos = thisOne.find('!');
366 size_t length1 = thisOne.length();
367 size_t length2 = length1;
368 if (shriekPos != std::string::npos) {
369 //contains '!'
370 length2 = shriekPos;
371 thisOne = thisOne.substr(0, shriekPos) + thisOne.substr(shriekPos + 1);
372 length1 = thisOne.length();
373 }
374 if (check.length() <= length1 && length2 <= check.length()) {
375 unsigned int i;
376 for (i = 0; i < check.length(); i++) {
377 if (tolower(thisOne[i]) != tolower(check[i]))
378 break;
379 }
380 if (i < check.length()) {
381 whichItem++;
382 } else if (i >= length2) {
383 break;
384 }
385 } else {
386 whichItem++;
387 }
388 }
389 if (whichItem < numberItems) {
390 return whichItem;
391 } else {
392 if (fakeKeyWord_ <= 0)
393 return -1;
394 // allow plus or minus
395 int n;
396 if (check.substr(0, 4) == "plus" || check.substr(0, 4) == "PLUS") {
397 n = 4;
398 } else if (check.substr(0, 5) == "minus" || check.substr(0, 5) == "MINUS") {
399 n = 5;
400 } else {
401 return -1;
402 }
403 int value = 0;
404 std::string field = check.substr(n);
405 if (field != "EOL") {
406 const char *start = field.c_str();
407 char *endPointer = NULL;
408 // check valid
409 value = static_cast< int >(strtol(start, &endPointer, 10));
410 if (*endPointer != '\0') {
411 return -1;
412 }
413 if (n == 4)
414 return value + 1000;
415 else
416 return -value - 1000;
417 } else {
418 return -1;
419 }
420 }
421 }
422 }
423 // Prints parameter options
printOptions() const424 void CbcOrClpParam::printOptions() const
425 {
426 std::cout << "<Possible options for " << name_ << " are:";
427 unsigned int it;
428 for (it = 0; it < definedKeyWords_.size(); it++) {
429 std::string thisOne = definedKeyWords_[it];
430 std::string::size_type shriekPos = thisOne.find('!');
431 if (shriekPos != std::string::npos) {
432 //contains '!'
433 thisOne = thisOne.substr(0, shriekPos) + "(" + thisOne.substr(shriekPos + 1) + ")";
434 }
435 std::cout << " " << thisOne;
436 }
437 assert(currentKeyWord_ >= 0 && currentKeyWord_ < static_cast< int >(definedKeyWords_.size()));
438 std::string current = definedKeyWords_[currentKeyWord_];
439 std::string::size_type shriekPos = current.find('!');
440 if (shriekPos != std::string::npos) {
441 //contains '!'
442 current = current.substr(0, shriekPos) + "(" + current.substr(shriekPos + 1) + ")";
443 }
444 std::cout << ";\n\tcurrent " << current << ">" << std::endl;
445 }
446 // Print action and string
printString() const447 void CbcOrClpParam::printString() const
448 {
449 if (name_ == "directory")
450 std::cout << "Current working directory is " << stringValue_ << std::endl;
451 else if (name_.substr(0, 6) == "printM")
452 std::cout << "Current value of printMask is " << stringValue_ << std::endl;
453 else
454 std::cout << "Current default (if $ as parameter) for " << name_
455 << " is " << stringValue_ << std::endl;
456 }
CoinReadPrintit(const char * input)457 void CoinReadPrintit(const char *input)
458 {
459 int length = static_cast< int >(strlen(input));
460 assert(length <= 1000);
461 char temp[1001];
462 int i;
463 int n = 0;
464 for (i = 0; i < length; i++) {
465 if (input[i] == '\n') {
466 temp[n] = '\0';
467 std::cout << temp << std::endl;
468 n = 0;
469 } else if (n >= 65 && input[i] == ' ') {
470 temp[n] = '\0';
471 std::cout << temp << std::endl;
472 n = 0;
473 } else if (n || input[i] != ' ') {
474 temp[n++] = input[i];
475 }
476 }
477 if (n) {
478 temp[n] = '\0';
479 std::cout << temp << std::endl;
480 }
481 }
482 // Print Long help
printLongHelp() const483 void CbcOrClpParam::printLongHelp() const
484 {
485 if (type_ >= 1 && type_ < 600) {
486 CoinReadPrintit(longHelp_.c_str());
487 if (type_ < CLP_PARAM_INT_SOLVERLOGLEVEL) {
488 printf("<Range of values is %g to %g;\n\tcurrent %g>\n", lowerDoubleValue_, upperDoubleValue_, doubleValue_);
489 assert(upperDoubleValue_ > lowerDoubleValue_);
490 } else if (type_ < CLP_PARAM_STR_DIRECTION) {
491 printf("<Range of values is %d to %d;\n\tcurrent %d>\n", lowerIntValue_, upperIntValue_, intValue_);
492 assert(upperIntValue_ > lowerIntValue_);
493 } else if (type_ < CLP_PARAM_ACTION_DIRECTORY) {
494 printOptions();
495 }
496 }
497 }
498 #ifdef COIN_HAS_CBC
setDoubleParameter(OsiSolverInterface * model,double value)499 int CbcOrClpParam::setDoubleParameter(OsiSolverInterface *model, double value)
500 {
501 int returnCode;
502 setDoubleParameterWithMessage(model, value, returnCode);
503 if (doPrinting && strlen(printArray))
504 std::cout << printArray << std::endl;
505 return returnCode;
506 }
507 // Sets double parameter and returns printable string and error code
508 const char *
setDoubleParameterWithMessage(OsiSolverInterface * model,double value,int & returnCode)509 CbcOrClpParam::setDoubleParameterWithMessage(OsiSolverInterface *model, double value, int &returnCode)
510 {
511 if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
512 sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
513 value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
514 std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl;
515 returnCode = 1;
516 } else {
517 double oldValue = doubleValue_;
518 doubleValue_ = value;
519 switch (type_) {
520 case CLP_PARAM_DBL_DUALTOLERANCE:
521 model->getDblParam(OsiDualTolerance, oldValue);
522 model->setDblParam(OsiDualTolerance, value);
523 break;
524 case CLP_PARAM_DBL_PRIMALTOLERANCE:
525 model->getDblParam(OsiPrimalTolerance, oldValue);
526 model->setDblParam(OsiPrimalTolerance, value);
527 break;
528 default:
529 break;
530 }
531 sprintf(printArray, "%s was changed from %g to %g",
532 name_.c_str(), oldValue, value);
533 returnCode = 0;
534 }
535 return printArray;
536 }
537 #endif
538 #ifdef COIN_HAS_CLP
setDoubleParameter(ClpSimplex * model,double value)539 int CbcOrClpParam::setDoubleParameter(ClpSimplex *model, double value)
540 {
541 int returnCode;
542 setDoubleParameterWithMessage(model, value, returnCode);
543 if (doPrinting && strlen(printArray))
544 std::cout << printArray << std::endl;
545 return returnCode;
546 }
547 // Sets int parameter and returns printable string and error code
548 const char *
setDoubleParameterWithMessage(ClpSimplex * model,double value,int & returnCode)549 CbcOrClpParam::setDoubleParameterWithMessage(ClpSimplex *model, double value, int &returnCode)
550 {
551 double oldValue = doubleValue_;
552 if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
553 sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
554 value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
555 returnCode = 1;
556 } else {
557 sprintf(printArray, "%s was changed from %g to %g",
558 name_.c_str(), oldValue, value);
559 returnCode = 0;
560 doubleValue_ = value;
561 switch (type_) {
562 case CLP_PARAM_DBL_DUALTOLERANCE:
563 model->setDualTolerance(value);
564 break;
565 case CLP_PARAM_DBL_PRIMALTOLERANCE:
566 model->setPrimalTolerance(value);
567 break;
568 case CLP_PARAM_DBL_ZEROTOLERANCE:
569 model->setSmallElementValue(value);
570 break;
571 case CLP_PARAM_DBL_DUALBOUND:
572 model->setDualBound(value);
573 break;
574 case CLP_PARAM_DBL_PRIMALWEIGHT:
575 model->setInfeasibilityCost(value);
576 break;
577 #ifndef COIN_HAS_CBC
578 case CLP_PARAM_DBL_TIMELIMIT:
579 model->setMaximumSeconds(value);
580 break;
581 #endif
582 case CLP_PARAM_DBL_OBJSCALE:
583 model->setObjectiveScale(value);
584 break;
585 case CLP_PARAM_DBL_RHSSCALE:
586 model->setRhsScale(value);
587 break;
588 case CLP_PARAM_DBL_PRESOLVETOLERANCE:
589 model->setDblParam(ClpPresolveTolerance, value);
590 break;
591 default:
592 break;
593 }
594 }
595 return printArray;
596 }
597 double
doubleParameter(ClpSimplex * model) const598 CbcOrClpParam::doubleParameter(ClpSimplex *model) const
599 {
600 double value;
601 switch (type_) {
602 #ifndef COIN_HAS_CBC
603 case CLP_PARAM_DBL_DUALTOLERANCE:
604 value = model->dualTolerance();
605 break;
606 case CLP_PARAM_DBL_PRIMALTOLERANCE:
607 value = model->primalTolerance();
608 break;
609 #endif
610 case CLP_PARAM_DBL_ZEROTOLERANCE:
611 value = model->getSmallElementValue();
612 break;
613 case CLP_PARAM_DBL_DUALBOUND:
614 value = model->dualBound();
615 break;
616 case CLP_PARAM_DBL_PRIMALWEIGHT:
617 value = model->infeasibilityCost();
618 break;
619 #ifndef COIN_HAS_CBC
620 case CLP_PARAM_DBL_TIMELIMIT:
621 value = model->maximumSeconds();
622 break;
623 #endif
624 case CLP_PARAM_DBL_OBJSCALE:
625 value = model->objectiveScale();
626 break;
627 case CLP_PARAM_DBL_RHSSCALE:
628 value = model->rhsScale();
629 break;
630 case CLP_PARAM_DBL_PRESOLVETOLERANCE:
631 value = model->presolveTolerance();
632 break;
633 default:
634 value = doubleValue_;
635 break;
636 }
637 return value;
638 }
setIntParameter(ClpSimplex * model,int value)639 int CbcOrClpParam::setIntParameter(ClpSimplex *model, int value)
640 {
641 int returnCode;
642 setIntParameterWithMessage(model, value, returnCode);
643 if (doPrinting && strlen(printArray))
644 std::cout << printArray << std::endl;
645 return returnCode;
646 }
647 // Sets int parameter and returns printable string and error code
648 const char *
setIntParameterWithMessage(ClpSimplex * model,int value,int & returnCode)649 CbcOrClpParam::setIntParameterWithMessage(ClpSimplex *model, int value, int &returnCode)
650 {
651 int oldValue = intValue_;
652 if (value < lowerIntValue_ || value > upperIntValue_) {
653 sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
654 value, name_.c_str(), lowerIntValue_, upperIntValue_);
655 returnCode = 1;
656 } else {
657 intValue_ = value;
658 sprintf(printArray, "%s was changed from %d to %d",
659 name_.c_str(), oldValue, value);
660 returnCode = 0;
661 switch (type_) {
662 case CLP_PARAM_INT_SOLVERLOGLEVEL:
663 model->setLogLevel(value);
664 if (value > 2)
665 model->factorization()->messageLevel(8);
666 else
667 model->factorization()->messageLevel(0);
668 break;
669 case CLP_PARAM_INT_MAXFACTOR:
670 model->factorization()->maximumPivots(value);
671 break;
672 case CLP_PARAM_INT_PERTVALUE:
673 model->setPerturbation(value);
674 break;
675 case CLP_PARAM_INT_MAXITERATION:
676 model->setMaximumIterations(value);
677 break;
678 case CLP_PARAM_INT_SPECIALOPTIONS:
679 model->setSpecialOptions(value);
680 break;
681 case CLP_PARAM_INT_RANDOMSEED: {
682 if (value == 0) {
683 double time = fabs(CoinGetTimeOfDay());
684 while (time >= COIN_INT_MAX)
685 time *= 0.5;
686 value = static_cast< int >(time);
687 sprintf(printArray, "using time of day %s was changed from %d to %d",
688 name_.c_str(), oldValue, value);
689 }
690 model->setRandomSeed(value);
691 } break;
692 case CLP_PARAM_INT_MORESPECIALOPTIONS:
693 model->setMoreSpecialOptions(value);
694 break;
695 case CLP_PARAM_INT_VECTOR_MODE:
696 model->setVectorMode(value);
697 break;
698 #ifndef COIN_HAS_CBC
699 #ifdef CBC_THREAD
700 case CBC_PARAM_INT_THREADS:
701 model->setNumberThreads(value);
702 break;
703 #endif
704 #endif
705 default:
706 break;
707 }
708 }
709 return printArray;
710 }
intParameter(ClpSimplex * model) const711 int CbcOrClpParam::intParameter(ClpSimplex *model) const
712 {
713 int value;
714 switch (type_) {
715 #ifndef COIN_HAS_CBC
716 case CLP_PARAM_INT_SOLVERLOGLEVEL:
717 value = model->logLevel();
718 break;
719 #endif
720 case CLP_PARAM_INT_MAXFACTOR:
721 value = model->factorization()->maximumPivots();
722 break;
723 break;
724 case CLP_PARAM_INT_PERTVALUE:
725 value = model->perturbation();
726 break;
727 case CLP_PARAM_INT_MAXITERATION:
728 value = model->maximumIterations();
729 break;
730 case CLP_PARAM_INT_SPECIALOPTIONS:
731 value = model->specialOptions();
732 break;
733 case CLP_PARAM_INT_RANDOMSEED:
734 value = model->randomNumberGenerator()->getSeed();
735 break;
736 case CLP_PARAM_INT_MORESPECIALOPTIONS:
737 value = model->moreSpecialOptions();
738 break;
739 case CLP_PARAM_INT_VECTOR_MODE:
740 value = model->vectorMode();
741 break;
742 #ifndef COIN_HAS_CBC
743 #ifdef CBC_THREAD
744 case CBC_PARAM_INT_THREADS:
745 value = model->numberThreads();
746 break;
747 #endif
748 #endif
749 default:
750 value = intValue_;
751 break;
752 }
753 return value;
754 }
755 #endif
checkDoubleParameter(double value) const756 int CbcOrClpParam::checkDoubleParameter(double value) const
757 {
758 if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
759 std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl;
760 return 1;
761 } else {
762 return 0;
763 }
764 }
765 #ifdef COIN_HAS_CBC
766 double
doubleParameter(OsiSolverInterface * model) const767 CbcOrClpParam::doubleParameter(OsiSolverInterface *model) const
768 {
769 double value = 0.0;
770 switch (type_) {
771 case CLP_PARAM_DBL_DUALTOLERANCE:
772 model->getDblParam(OsiDualTolerance, value);
773 break;
774 case CLP_PARAM_DBL_PRIMALTOLERANCE:
775 model->getDblParam(OsiPrimalTolerance, value);
776 break;
777 default:
778 return doubleValue_;
779 break;
780 }
781 return value;
782 }
setIntParameter(OsiSolverInterface * model,int value)783 int CbcOrClpParam::setIntParameter(OsiSolverInterface *model, int value)
784 {
785 int returnCode;
786 setIntParameterWithMessage(model, value, returnCode);
787 if (doPrinting && strlen(printArray))
788 std::cout << printArray << std::endl;
789 return returnCode;
790 }
791 // Sets int parameter and returns printable string and error code
792 const char *
setIntParameterWithMessage(OsiSolverInterface * model,int value,int & returnCode)793 CbcOrClpParam::setIntParameterWithMessage(OsiSolverInterface *model, int value, int &returnCode)
794 {
795 if (value < lowerIntValue_ || value > upperIntValue_) {
796 sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
797 value, name_.c_str(), lowerIntValue_, upperIntValue_);
798 returnCode = 1;
799 } else {
800 int oldValue = intValue_;
801 intValue_ = oldValue;
802 switch (type_) {
803 case CLP_PARAM_INT_SOLVERLOGLEVEL:
804 model->messageHandler()->setLogLevel(value);
805 break;
806 default:
807 break;
808 }
809 sprintf(printArray, "%s was changed from %d to %d",
810 name_.c_str(), oldValue, value);
811 returnCode = 0;
812 }
813 return printArray;
814 }
intParameter(OsiSolverInterface * model) const815 int CbcOrClpParam::intParameter(OsiSolverInterface *model) const
816 {
817 int value = 0;
818 switch (type_) {
819 case CLP_PARAM_INT_SOLVERLOGLEVEL:
820 value = model->messageHandler()->logLevel();
821 break;
822 default:
823 value = intValue_;
824 break;
825 }
826 return value;
827 }
setDoubleParameter(CbcModel & model,double value)828 int CbcOrClpParam::setDoubleParameter(CbcModel &model, double value)
829 {
830 int returnCode = 0;
831 setDoubleParameterWithMessage(model, value, returnCode);
832 if (doPrinting && strlen(printArray))
833 std::cout << printArray << std::endl;
834 return returnCode;
835 }
836 // Sets double parameter and returns printable string and error code
837 const char *
setDoubleParameterWithMessage(CbcModel & model,double value,int & returnCode)838 CbcOrClpParam::setDoubleParameterWithMessage(CbcModel &model, double value, int &returnCode)
839 {
840 if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
841 sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
842 value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
843 returnCode = 1;
844 } else {
845 double oldValue = doubleValue_;
846 doubleValue_ = value;
847 switch (type_) {
848 case CBC_PARAM_DBL_INFEASIBILITYWEIGHT:
849 oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight);
850 model.setDblParam(CbcModel::CbcInfeasibilityWeight, value);
851 break;
852 case CBC_PARAM_DBL_INTEGERTOLERANCE:
853 oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance);
854 model.setDblParam(CbcModel::CbcIntegerTolerance, value);
855 break;
856 case CBC_PARAM_DBL_INCREMENT:
857 oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement);
858 model.setDblParam(CbcModel::CbcCutoffIncrement, value);
859 case CBC_PARAM_DBL_ALLOWABLEGAP:
860 oldValue = model.getDblParam(CbcModel::CbcAllowableGap);
861 model.setDblParam(CbcModel::CbcAllowableGap, value);
862 break;
863 case CBC_PARAM_DBL_GAPRATIO:
864 oldValue = model.getDblParam(CbcModel::CbcAllowableFractionGap);
865 model.setDblParam(CbcModel::CbcAllowableFractionGap, value);
866 break;
867 case CBC_PARAM_DBL_CUTOFF:
868 oldValue = model.getCutoff();
869 model.setCutoff(value);
870 break;
871 case CBC_PARAM_DBL_TIMELIMIT_BAB:
872 oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds);
873 {
874 //OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model.solver());
875 //ClpSimplex * lpSolver = clpSolver->getModelPtr();
876 //lpSolver->setMaximumSeconds(value);
877 model.setDblParam(CbcModel::CbcMaximumSeconds, value);
878 }
879 break;
880 case CLP_PARAM_DBL_DUALTOLERANCE:
881 case CLP_PARAM_DBL_PRIMALTOLERANCE:
882 setDoubleParameter(model.solver(), value);
883 return 0; // to avoid message
884 default:
885 break;
886 }
887 sprintf(printArray, "%s was changed from %g to %g",
888 name_.c_str(), oldValue, value);
889 returnCode = 0;
890 }
891 return printArray;
892 }
893 double
doubleParameter(CbcModel & model) const894 CbcOrClpParam::doubleParameter(CbcModel &model) const
895 {
896 double value;
897 switch (type_) {
898 case CBC_PARAM_DBL_INFEASIBILITYWEIGHT:
899 value = model.getDblParam(CbcModel::CbcInfeasibilityWeight);
900 break;
901 case CBC_PARAM_DBL_INTEGERTOLERANCE:
902 value = model.getDblParam(CbcModel::CbcIntegerTolerance);
903 break;
904 case CBC_PARAM_DBL_INCREMENT:
905 value = model.getDblParam(CbcModel::CbcCutoffIncrement);
906 break;
907 case CBC_PARAM_DBL_ALLOWABLEGAP:
908 value = model.getDblParam(CbcModel::CbcAllowableGap);
909 break;
910 case CBC_PARAM_DBL_GAPRATIO:
911 value = model.getDblParam(CbcModel::CbcAllowableFractionGap);
912 break;
913 case CBC_PARAM_DBL_CUTOFF:
914 value = model.getCutoff();
915 break;
916 case CBC_PARAM_DBL_TIMELIMIT_BAB:
917 value = model.getDblParam(CbcModel::CbcMaximumSeconds);
918 break;
919 case CLP_PARAM_DBL_DUALTOLERANCE:
920 case CLP_PARAM_DBL_PRIMALTOLERANCE:
921 value = doubleParameter(model.solver());
922 break;
923 default:
924 value = doubleValue_;
925 break;
926 }
927 return value;
928 }
setIntParameter(CbcModel & model,int value)929 int CbcOrClpParam::setIntParameter(CbcModel &model, int value)
930 {
931 int returnCode;
932 setIntParameterWithMessage(model, value, returnCode);
933 if (doPrinting && strlen(printArray))
934 std::cout << printArray << std::endl;
935 return returnCode;
936 }
937 // Sets int parameter and returns printable string and error code
938 const char *
setIntParameterWithMessage(CbcModel & model,int value,int & returnCode)939 CbcOrClpParam::setIntParameterWithMessage(CbcModel &model, int value, int &returnCode)
940 {
941 if (value < lowerIntValue_ || value > upperIntValue_) {
942 sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
943 value, name_.c_str(), lowerIntValue_, upperIntValue_);
944 returnCode = 1;
945 } else {
946 printArray[0] = '\0';
947 if (value == intValue_)
948 return printArray;
949 int oldValue = intValue_;
950 intValue_ = value;
951 switch (type_) {
952 case CLP_PARAM_INT_LOGLEVEL:
953 oldValue = model.messageHandler()->logLevel();
954 model.messageHandler()->setLogLevel(CoinAbs(value));
955 break;
956 case CLP_PARAM_INT_SOLVERLOGLEVEL:
957 oldValue = model.solver()->messageHandler()->logLevel();
958 model.solver()->messageHandler()->setLogLevel(value);
959 break;
960 case CBC_PARAM_INT_MAXNODES:
961 oldValue = model.getIntParam(CbcModel::CbcMaxNumNode);
962 model.setIntParam(CbcModel::CbcMaxNumNode, value);
963 break;
964 case CBC_PARAM_INT_MAXSOLS:
965 oldValue = model.getIntParam(CbcModel::CbcMaxNumSol);
966 model.setIntParam(CbcModel::CbcMaxNumSol, value);
967 break;
968 case CBC_PARAM_INT_MAXSAVEDSOLS:
969 oldValue = model.maximumSavedSolutions();
970 model.setMaximumSavedSolutions(value);
971 break;
972 case CBC_PARAM_INT_STRONGBRANCHING:
973 oldValue = model.numberStrong();
974 model.setNumberStrong(value);
975 break;
976 case CBC_PARAM_INT_NUMBERBEFORE:
977 oldValue = model.numberBeforeTrust();
978 model.setNumberBeforeTrust(value);
979 break;
980 case CBC_PARAM_INT_NUMBERANALYZE:
981 oldValue = model.numberAnalyzeIterations();
982 model.setNumberAnalyzeIterations(value);
983 break;
984 case CBC_PARAM_INT_CUTPASSINTREE:
985 oldValue = model.getMaximumCutPasses();
986 model.setMaximumCutPasses(value);
987 break;
988 case CBC_PARAM_INT_CUTPASS:
989 oldValue = model.getMaximumCutPassesAtRoot();
990 model.setMaximumCutPassesAtRoot(value);
991 break;
992 #ifdef COIN_HAS_CBC
993 #ifdef CBC_THREAD
994 case CBC_PARAM_INT_THREADS:
995 oldValue = model.getNumberThreads();
996 model.setNumberThreads(value);
997 break;
998 #endif
999 case CBC_PARAM_INT_RANDOMSEED:
1000 oldValue = model.getRandomSeed();
1001 model.setRandomSeed(value);
1002 break;
1003 #endif
1004 default:
1005 break;
1006 }
1007 sprintf(printArray, "%s was changed from %d to %d",
1008 name_.c_str(), oldValue, value);
1009 returnCode = 0;
1010 }
1011 return printArray;
1012 }
intParameter(CbcModel & model) const1013 int CbcOrClpParam::intParameter(CbcModel &model) const
1014 {
1015 int value;
1016 switch (type_) {
1017 case CLP_PARAM_INT_LOGLEVEL:
1018 value = model.messageHandler()->logLevel();
1019 break;
1020 case CLP_PARAM_INT_SOLVERLOGLEVEL:
1021 value = model.solver()->messageHandler()->logLevel();
1022 break;
1023 case CBC_PARAM_INT_MAXNODES:
1024 value = model.getIntParam(CbcModel::CbcMaxNumNode);
1025 break;
1026 case CBC_PARAM_INT_MAXSOLS:
1027 value = model.getIntParam(CbcModel::CbcMaxNumSol);
1028 break;
1029 case CBC_PARAM_INT_MAXSAVEDSOLS:
1030 value = model.maximumSavedSolutions();
1031 break;
1032 case CBC_PARAM_INT_STRONGBRANCHING:
1033 value = model.numberStrong();
1034 break;
1035 case CBC_PARAM_INT_NUMBERBEFORE:
1036 value = model.numberBeforeTrust();
1037 break;
1038 case CBC_PARAM_INT_NUMBERANALYZE:
1039 value = model.numberAnalyzeIterations();
1040 break;
1041 case CBC_PARAM_INT_CUTPASSINTREE:
1042 value = model.getMaximumCutPasses();
1043 break;
1044 case CBC_PARAM_INT_CUTPASS:
1045 value = model.getMaximumCutPassesAtRoot();
1046 break;
1047 #ifdef COIN_HAS_CBC
1048 #ifdef CBC_THREAD
1049 case CBC_PARAM_INT_THREADS:
1050 value = model.getNumberThreads();
1051 #endif
1052 case CBC_PARAM_INT_RANDOMSEED:
1053 value = model.getRandomSeed();
1054 break;
1055 #endif
1056 default:
1057 value = intValue_;
1058 break;
1059 }
1060 return value;
1061 }
1062 #endif
1063 // Sets current parameter option using string
setCurrentOption(const std::string value)1064 void CbcOrClpParam::setCurrentOption(const std::string value)
1065 {
1066 int action = parameterOption(value);
1067 if (action >= 0)
1068 currentKeyWord_ = action;
1069 #if FLUSH_PRINT_BUFFER > 2
1070 if (name_ == "bufferedMode")
1071 coinFlushBufferFlag = action;
1072 #endif
1073 }
1074 // Sets current parameter option
setCurrentOption(int value,bool printIt)1075 void CbcOrClpParam::setCurrentOption(int value, bool printIt)
1076 {
1077 if (printIt && value != currentKeyWord_)
1078 std::cout << "Option for " << name_ << " changed from "
1079 << definedKeyWords_[currentKeyWord_] << " to "
1080 << definedKeyWords_[value] << std::endl;
1081
1082 #if FLUSH_PRINT_BUFFER > 2
1083 if (name_ == "bufferedMode")
1084 coinFlushBufferFlag = value;
1085 #endif
1086 currentKeyWord_ = value;
1087 }
1088 // Sets current parameter option and returns printable string
1089 const char *
setCurrentOptionWithMessage(int value)1090 CbcOrClpParam::setCurrentOptionWithMessage(int value)
1091 {
1092 if (value != currentKeyWord_) {
1093 char current[100];
1094 char newString[100];
1095 if (currentKeyWord_ >= 0 && (fakeKeyWord_ <= 0 || currentKeyWord_ < fakeKeyWord_))
1096 strcpy(current, definedKeyWords_[currentKeyWord_].c_str());
1097 else if (currentKeyWord_ < 0)
1098 sprintf(current, "minus%d", -currentKeyWord_ - 1000);
1099 else
1100 sprintf(current, "plus%d", currentKeyWord_ - 1000);
1101 if (value >= 0 && (fakeKeyWord_ <= 0 || value < fakeKeyWord_))
1102 strcpy(newString, definedKeyWords_[value].c_str());
1103 else if (value < 0)
1104 sprintf(newString, "minus%d", -value - 1000);
1105 else
1106 sprintf(newString, "plus%d", value - 1000);
1107 sprintf(printArray, "Option for %s changed from %s to %s",
1108 name_.c_str(), current, newString);
1109 #if FLUSH_PRINT_BUFFER > 2
1110 if (name_ == "bufferedMode")
1111 coinFlushBufferFlag = value;
1112 #endif
1113 currentKeyWord_ = value;
1114 } else {
1115 printArray[0] = '\0';
1116 }
1117 return printArray;
1118 }
1119 // Sets current parameter option using string with message
1120 const char *
setCurrentOptionWithMessage(const std::string value)1121 CbcOrClpParam::setCurrentOptionWithMessage(const std::string value)
1122 {
1123 int action = parameterOption(value);
1124 char current[100];
1125 printArray[0] = '\0';
1126 if (action >= 0) {
1127 #if FLUSH_PRINT_BUFFER > 2
1128 if (name_ == "bufferedMode")
1129 coinFlushBufferFlag = action;
1130 #endif
1131 if (action == currentKeyWord_)
1132 return NULL;
1133 if (currentKeyWord_ >= 0 && (fakeKeyWord_ <= 0 || currentKeyWord_ < fakeKeyWord_))
1134 strcpy(current, definedKeyWords_[currentKeyWord_].c_str());
1135 else if (currentKeyWord_ < 0)
1136 sprintf(current, "minus%d", -currentKeyWord_ - 1000);
1137 else
1138 sprintf(current, "plus%d", currentKeyWord_ - 1000);
1139 sprintf(printArray, "Option for %s changed from %s to %s",
1140 name_.c_str(), current, value.c_str());
1141 currentKeyWord_ = action;
1142 } else {
1143 sprintf(printArray, "Option for %s given illegal value %s",
1144 name_.c_str(), value.c_str());
1145 }
1146 return printArray;
1147 }
setIntValue(int value)1148 void CbcOrClpParam::setIntValue(int value)
1149 {
1150 if (value < lowerIntValue_ || value > upperIntValue_) {
1151 std::cout << value << " was provided for " << name_ << " - valid range is " << lowerIntValue_ << " to " << upperIntValue_ << std::endl;
1152 } else {
1153 intValue_ = value;
1154 }
1155 }
1156 const char *
setIntValueWithMessage(int value)1157 CbcOrClpParam::setIntValueWithMessage(int value)
1158 {
1159 printArray[0] = '\0';
1160 if (value < lowerIntValue_ || value > upperIntValue_) {
1161 sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
1162 value, name_.c_str(), lowerIntValue_, upperIntValue_);
1163 } else {
1164 if (value == intValue_)
1165 return NULL;
1166 sprintf(printArray, "%s was changed from %d to %d",
1167 name_.c_str(), intValue_, value);
1168 intValue_ = value;
1169 }
1170 return printArray;
1171 }
setDoubleValue(double value)1172 void CbcOrClpParam::setDoubleValue(double value)
1173 {
1174 if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
1175 std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl;
1176 } else {
1177 doubleValue_ = value;
1178 }
1179 }
1180 const char *
setDoubleValueWithMessage(double value)1181 CbcOrClpParam::setDoubleValueWithMessage(double value)
1182 {
1183 printArray[0] = '\0';
1184 if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
1185 sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
1186 value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
1187 } else {
1188 if (value == doubleValue_)
1189 return NULL;
1190 sprintf(printArray, "%s was changed from %g to %g",
1191 name_.c_str(), doubleValue_, value);
1192 doubleValue_ = value;
1193 }
1194 return printArray;
1195 }
setStringValue(std::string value)1196 void CbcOrClpParam::setStringValue(std::string value)
1197 {
1198 stringValue_ = value;
1199 }
1200 static char line[1000];
1201 static char *where = NULL;
1202 extern int CbcOrClpRead_mode;
1203 int CbcOrClpEnvironmentIndex = -1;
1204 // Alternative to environment
1205 char *alternativeEnvironment = NULL;
fillEnv()1206 static size_t fillEnv()
1207 {
1208 #if defined(_MSC_VER) || defined(__MSVCRT__)
1209 return 0;
1210 #else
1211 // Don't think it will work on Windows
1212 char *environ;
1213 if (!alternativeEnvironment)
1214 environ = getenv("CBC_CLP_ENVIRONMENT");
1215 else
1216 environ = alternativeEnvironment;
1217 size_t length = 0;
1218 if (environ) {
1219 length = strlen(environ);
1220 if (CbcOrClpEnvironmentIndex < static_cast< int >(length)) {
1221 // find next non blank
1222 char *whereEnv = environ + CbcOrClpEnvironmentIndex;
1223 // munch white space
1224 while (*whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ')
1225 whereEnv++;
1226 // copy
1227 char *put = line;
1228 while (*whereEnv != '\0') {
1229 if (*whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ') {
1230 break;
1231 }
1232 *put = *whereEnv;
1233 put++;
1234 assert(put - line < 1000);
1235 whereEnv++;
1236 }
1237 CbcOrClpEnvironmentIndex = static_cast< int >(whereEnv - environ);
1238 *put = '\0';
1239 length = strlen(line);
1240 } else {
1241 length = 0;
1242 }
1243 }
1244 if (!length) {
1245 CbcOrClpEnvironmentIndex = -1;
1246 if (alternativeEnvironment) {
1247 delete[] alternativeEnvironment;
1248 alternativeEnvironment = NULL;
1249 }
1250 }
1251 return length;
1252 #endif
1253 }
1254 extern FILE *CbcOrClpReadCommand;
1255 // Simple read stuff
1256 std::string
CoinReadNextField()1257 CoinReadNextField()
1258 {
1259 std::string field;
1260 if (!where) {
1261 // need new line
1262 #ifdef COIN_HAS_READLINE
1263 if (CbcOrClpReadCommand == stdin) {
1264 // Get a line from the user.
1265 where = readline(coin_prompt);
1266
1267 // If the line has any text in it, save it on the history.
1268 if (where) {
1269 if (*where)
1270 add_history(where);
1271 strcpy(line, where);
1272 free(where);
1273 }
1274 } else {
1275 where = fgets(line, 1000, CbcOrClpReadCommand);
1276 }
1277 #else
1278 if (CbcOrClpReadCommand == stdin) {
1279 fputs(coin_prompt, stdout);
1280 fflush(stdout);
1281 }
1282 where = fgets(line, 1000, CbcOrClpReadCommand);
1283 #endif
1284 if (!where)
1285 return field; // EOF
1286 where = line;
1287 // clean image
1288 char *lastNonBlank = line - 1;
1289 while (*where != '\0') {
1290 if (*where != '\t' && *where < ' ') {
1291 break;
1292 } else if (*where != '\t' && *where != ' ') {
1293 lastNonBlank = where;
1294 }
1295 where++;
1296 }
1297 where = line;
1298 *(lastNonBlank + 1) = '\0';
1299 }
1300 // munch white space
1301 while (*where == ' ' || *where == '\t')
1302 where++;
1303 char *saveWhere = where;
1304 while (*where != ' ' && *where != '\t' && *where != '\0')
1305 where++;
1306 if (where != saveWhere) {
1307 char save = *where;
1308 *where = '\0';
1309 //convert to string
1310 field = saveWhere;
1311 *where = save;
1312 } else {
1313 where = NULL;
1314 field = "EOL";
1315 }
1316 return field;
1317 }
1318
1319 std::string
CoinReadGetCommand(int argc,const char * argv[])1320 CoinReadGetCommand(int argc, const char *argv[])
1321 {
1322 std::string field = "EOL";
1323 // say no =
1324 afterEquals = "";
1325 while (field == "EOL") {
1326 if (CbcOrClpRead_mode > 0) {
1327 if ((CbcOrClpRead_mode < argc && argv[CbcOrClpRead_mode]) || CbcOrClpEnvironmentIndex >= 0) {
1328 if (CbcOrClpEnvironmentIndex < 0) {
1329 field = argv[CbcOrClpRead_mode++];
1330 } else {
1331 if (fillEnv()) {
1332 field = line;
1333 } else {
1334 // not there
1335 continue;
1336 }
1337 }
1338 if (field == "-") {
1339 std::cout << "Switching to line mode" << std::endl;
1340 CbcOrClpRead_mode = -1;
1341 field = CoinReadNextField();
1342 } else if (field[0] != '-') {
1343 if (CbcOrClpRead_mode != 2) {
1344 // now allow std::cout<<"skipping non-command "<<field<<std::endl;
1345 // field="EOL"; // skip
1346 } else if (CbcOrClpEnvironmentIndex < 0) {
1347 // special dispensation - taken as -import name
1348 CbcOrClpRead_mode--;
1349 field = "import";
1350 }
1351 } else {
1352 if (field != "--") {
1353 // take off -
1354 field = field.substr(1);
1355 } else {
1356 // special dispensation - taken as -import --
1357 CbcOrClpRead_mode--;
1358 field = "import";
1359 }
1360 }
1361 } else {
1362 field = "";
1363 }
1364 } else {
1365 field = CoinReadNextField();
1366 }
1367 }
1368 // if = then modify and save
1369 std::string::size_type found = field.find('=');
1370 if (found != std::string::npos) {
1371 afterEquals = field.substr(found + 1);
1372 field = field.substr(0, found);
1373 }
1374 //std::cout<<field<<std::endl;
1375 return field;
1376 }
1377 std::string
CoinReadGetString(int argc,const char * argv[])1378 CoinReadGetString(int argc, const char *argv[])
1379 {
1380 std::string field = "EOL";
1381 if (afterEquals == "") {
1382 if (CbcOrClpRead_mode > 0) {
1383 if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
1384 if (CbcOrClpEnvironmentIndex < 0) {
1385 if (argv[CbcOrClpRead_mode][0] != '-') {
1386 field = argv[CbcOrClpRead_mode++];
1387 } else if (!strcmp(argv[CbcOrClpRead_mode], "--")) {
1388 CbcOrClpRead_mode++;
1389 // -- means import from stdin
1390 field = "-";
1391 }
1392 } else {
1393 fillEnv();
1394 field = line;
1395 }
1396 }
1397 } else {
1398 field = CoinReadNextField();
1399 }
1400 } else {
1401 field = afterEquals;
1402 afterEquals = "";
1403 }
1404 //std::cout<<field<<std::endl;
1405 return field;
1406 }
1407 // valid 0 - okay, 1 bad, 2 not there
CoinReadGetIntField(int argc,const char * argv[],int * valid)1408 int CoinReadGetIntField(int argc, const char *argv[], int *valid)
1409 {
1410 std::string field = "EOL";
1411 if (afterEquals == "") {
1412 if (CbcOrClpRead_mode > 0) {
1413 if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
1414 if (CbcOrClpEnvironmentIndex < 0) {
1415 // may be negative value so do not check for -
1416 field = argv[CbcOrClpRead_mode++];
1417 } else {
1418 fillEnv();
1419 field = line;
1420 }
1421 }
1422 } else {
1423 field = CoinReadNextField();
1424 }
1425 } else {
1426 field = afterEquals;
1427 afterEquals = "";
1428 }
1429 long int value = 0;
1430 //std::cout<<field<<std::endl;
1431 if (field != "EOL") {
1432 const char *start = field.c_str();
1433 char *endPointer = NULL;
1434 // check valid
1435 value = strtol(start, &endPointer, 10);
1436 if (*endPointer == '\0') {
1437 *valid = 0;
1438 } else {
1439 *valid = 1;
1440 std::cout << "String of " << field;
1441 }
1442 } else {
1443 *valid = 2;
1444 }
1445 return static_cast< int >(value);
1446 }
1447 double
CoinReadGetDoubleField(int argc,const char * argv[],int * valid)1448 CoinReadGetDoubleField(int argc, const char *argv[], int *valid)
1449 {
1450 std::string field = "EOL";
1451 if (afterEquals == "") {
1452 if (CbcOrClpRead_mode > 0) {
1453 if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
1454 if (CbcOrClpEnvironmentIndex < 0) {
1455 // may be negative value so do not check for -
1456 field = argv[CbcOrClpRead_mode++];
1457 } else {
1458 fillEnv();
1459 field = line;
1460 }
1461 }
1462 } else {
1463 field = CoinReadNextField();
1464 }
1465 } else {
1466 field = afterEquals;
1467 afterEquals = "";
1468 }
1469 double value = 0.0;
1470 //std::cout<<field<<std::endl;
1471 if (field != "EOL") {
1472 const char *start = field.c_str();
1473 char *endPointer = NULL;
1474 // check valid
1475 value = strtod(start, &endPointer);
1476 if (*endPointer == '\0') {
1477 *valid = 0;
1478 } else {
1479 *valid = 1;
1480 std::cout << "String of " << field;
1481 }
1482 } else {
1483 *valid = 2;
1484 }
1485 return value;
1486 }
1487 /*
1488 Subroutine to establish the cbc parameter array. See the description of
1489 class CbcOrClpParam for details. Pulled from C..Main() for clarity.
1490 */
establishParams(std::vector<CbcOrClpParam> & parameters)1491 void establishParams(std::vector< CbcOrClpParam > ¶meters)
1492 {
1493 parameters.clear();
1494 parameters.push_back(CbcOrClpParam("?", "For help", CBC_PARAM_GENERALQUERY, 7, 0));
1495 parameters.push_back(CbcOrClpParam("???", "For help", CBC_PARAM_FULLGENERALQUERY, 7, 0));
1496 parameters.push_back(CbcOrClpParam("-", "From stdin", CLP_PARAM_ACTION_STDIN, 3, 0));
1497
1498 // some help strings that repeat for many options
1499 #define CUTS_LONGHELP \
1500 "Value 'on' enables the cut generator and CBC will try it in the branch and cut tree (see cutDepth on how to fine tune the behavior). " \
1501 "Value 'root' lets CBC run the cut generator generate only at the root node. " \
1502 "Value 'ifmove' lets CBC use the cut generator in the tree if it looks as if it is doing some good and moves the objective value. " \
1503 "Value 'forceon' turns on the cut generator and forces CBC to use it at every node."
1504 #define HEURISTICS_LONGHELP \
1505 "Value 'on' means to use the heuristic in each node of the tree, i.e. after preprocessing. " \
1506 "Value 'before' means use the heuristic only if option doHeuristics is used. " \
1507 "Value 'both' means to use the heuristic if option doHeuristics is used and during solve."
1508
1509 #if defined(ABC_INHERIT) || ABOCA_LITE
1510 CbcOrClpParam paramAboca("abc", "Whether to visit Aboca", "off", CLP_PARAM_STR_ABCWANTED, 7, 0);
1511 paramAboca.append("one");
1512 paramAboca.append("two");
1513 paramAboca.append("three");
1514 paramAboca.append("four");
1515 paramAboca.append("five");
1516 paramAboca.append("six");
1517 paramAboca.append("seven");
1518 paramAboca.append("eight");
1519 paramAboca.append("on");
1520 paramAboca.append("decide");
1521 paramAboca.setFakeKeyWord(10);
1522 paramAboca.setLonghelp(
1523 "Decide whether to use A Basic Optimization Code (Accelerated?) \
1524 and whether to try going parallel!");
1525 parameters.push_back(paramAboca);
1526 #endif
1527 {
1528 CbcOrClpParam p("allC!ommands", "Whether to print less used commands",
1529 "no", CLP_PARAM_STR_ALLCOMMANDS);
1530
1531 p.append("more");
1532 p.append("all");
1533 p.setLonghelp(
1534 "For the sake of your sanity, only the more useful and simple commands \
1535 are printed out on ?.");
1536 parameters.push_back(p);
1537 }
1538 #ifdef COIN_HAS_CBC
1539 {
1540 CbcOrClpParam p("allow!ableGap", "Stop when gap between best possible and \
1541 best less than this",
1542 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ALLOWABLEGAP);
1543 p.setDoubleValue(0.0);
1544 p.setLonghelp(
1545 "If the gap between best known solution and the best possible solution is less than this \
1546 value, then the search will be terminated. Also see ratioGap.");
1547 parameters.push_back(p);
1548 }
1549 #endif
1550 #ifdef COIN_HAS_CLP
1551 {
1552 CbcOrClpParam p("allS!lack", "Set basis back to all slack and reset solution",
1553 CLP_PARAM_ACTION_ALLSLACK, 3);
1554 p.setLonghelp(
1555 "Mainly useful for tuning purposes. Normally the first dual or primal will be using an all slack \
1556 basis anyway.");
1557 parameters.push_back(p);
1558 }
1559 #endif
1560 #ifdef COIN_HAS_CBC
1561 {
1562 CbcOrClpParam p("artif!icialCost", "Costs >= this treated as artificials in feasibility pump",
1563 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ARTIFICIALCOST, 1);
1564 p.setDoubleValue(0.0);
1565 p.setLonghelp(
1566 "A value of 0.0 means off. Otherwise, variables with costs >= this are treated as artificial variables and fixed to lower bound in feasibility pump.");
1567 parameters.push_back(p);
1568 }
1569 #endif
1570 #ifdef COIN_HAS_CLP
1571 {
1572 CbcOrClpParam p("auto!Scale", "Whether to scale objective, rhs and bounds of problem if they look odd",
1573 "off", CLP_PARAM_STR_AUTOSCALE, 7, 0);
1574 p.append("on");
1575 p.setLonghelp(
1576 "If you think you may get odd objective values or large equality rows etc then\
1577 it may be worth setting this true. It is still experimental and you may prefer\
1578 to use objective!Scale and rhs!Scale.");
1579 parameters.push_back(p);
1580 }
1581 {
1582 CbcOrClpParam p("barr!ier", "Solve using primal dual predictor corrector algorithm",
1583 CLP_PARAM_ACTION_BARRIER);
1584 p.setLonghelp(
1585 "This command solves the current model using the primal dual predictor \
1586 corrector algorithm. You may want to link in an alternative \
1587 ordering and factorization. It will also solve models \
1588 with quadratic objectives.");
1589 parameters.push_back(p);
1590 }
1591 {
1592 CbcOrClpParam p("basisI!n", "Import basis from bas file",
1593 CLP_PARAM_ACTION_BASISIN, 3);
1594 p.setLonghelp(
1595 "This will read an MPS format basis file from the given file name. It will use the default\
1596 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
1597 is initialized to '', i.e. it must be set. If you have libz then it can read compressed\
1598 files 'xxxxxxxx.gz' or xxxxxxxx.bz2.");
1599 parameters.push_back(p);
1600 }
1601 {
1602 CbcOrClpParam p("basisO!ut", "Export basis as bas file",
1603 CLP_PARAM_ACTION_BASISOUT);
1604
1605 p.setLonghelp(
1606 "This will write an MPS format basis file to the given file name. It will use the default\
1607 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
1608 is initialized to 'default.bas'.");
1609 parameters.push_back(p);
1610 }
1611 {
1612 CbcOrClpParam p("biasLU", "Whether factorization biased towards U",
1613 "UU", CLP_PARAM_STR_BIASLU, 2, 0);
1614
1615 p.append("UX");
1616 p.append("LX");
1617 p.append("LL");
1618 p.setCurrentOption("LX");
1619 parameters.push_back(p);
1620 }
1621 #endif
1622 #ifdef COIN_HAS_CBC
1623 {
1624 CbcOrClpParam p("branch!AndCut", "Do Branch and Cut",
1625 CBC_PARAM_ACTION_BAB);
1626 p.setLonghelp(
1627 "This does branch and cut. There are many parameters which can affect the performance. \
1628 First just try with default settings and look carefully at the log file. Did cuts help? Did they take too long? \
1629 Look at output to see which cuts were effective and then do some tuning. You will see that the \
1630 options for cuts are off, on, root and ifmove, forceon. Off is \
1631 obvious. " CUTS_LONGHELP " For probing, forceonbut just does fixing probing in tree - not strengthening etc. \
1632 If pre-processing reduced the size of the \
1633 problem or strengthened many coefficients then it is probably wise to leave it on. Switch off heuristics \
1634 which did not provide solutions. The other major area to look at is the search. Hopefully good solutions \
1635 were obtained fairly early in the search so the important point is to select the best variable to branch on. \
1636 See whether strong branching did a good job - or did it just take a lot of iterations. Adjust the strongBranching \
1637 and trustPseudoCosts parameters. If cuts did a good job, then you may wish to \
1638 have more rounds of cuts - see passC!uts and passT!ree.");
1639 parameters.push_back(p);
1640 }
1641 #endif
1642 {
1643 CbcOrClpParam p("bscale", "Whether to scale in barrier (and ordering speed)",
1644 "off", CLP_PARAM_STR_BARRIERSCALE, 7, 0);
1645 p.append("on");
1646 p.append("off1");
1647 p.append("on1");
1648 p.append("off2");
1649 p.append("on2");
1650 parameters.push_back(p);
1651 }
1652 #if FLUSH_PRINT_BUFFER > 2
1653 {
1654 CbcOrClpParam p("buff!eredMode", "Whether to flush print buffer",
1655 "on", CLP_PARAM_STR_BUFFER_MODE);
1656
1657 p.append("off");
1658 p.setLonghelp(
1659 "Default is on, off switches on unbuffered output");
1660 p.setIntValue(0);
1661 parameters.push_back(p);
1662 }
1663 #endif
1664 {
1665 CbcOrClpParam p("chol!esky", "Which cholesky algorithm",
1666 "native", CLP_PARAM_STR_CHOLESKY, 7);
1667
1668 p.append("dense");
1669 //#ifdef FOREIGN_BARRIER
1670 #ifdef COIN_HAS_WSMP
1671 p.append("fudge!Long");
1672 p.append("wssmp");
1673 #else
1674 p.append("fudge!Long_dummy");
1675 p.append("wssmp_dummy");
1676 #endif
1677 #if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK)
1678 p.append("Uni!versityOfFlorida");
1679 #else
1680 p.append("Uni!versityOfFlorida_dummy");
1681 #endif
1682 #ifdef TAUCS_BARRIER
1683 p.append("Taucs");
1684 #else
1685 p.append("Taucs_dummy");
1686 #endif
1687 #ifdef COIN_HAS_MUMPS
1688 p.append("Mumps");
1689 #else
1690 p.append("Mumps_dummy");
1691 #endif
1692 #ifdef PARDISO_BARRIER
1693 p.append("Pardiso");
1694 #else
1695 p.append("Pardiso_dummy");
1696 #endif
1697 p.setLonghelp(
1698 "For a barrier code to be effective it needs a good Cholesky ordering and factorization. \
1699 The native ordering and factorization is not state of the art, although acceptable. \
1700 You may want to link in one from another source. See Makefile.locations for some \
1701 possibilities.");
1702
1703 parameters.push_back(p);
1704 }
1705 #ifdef COIN_HAS_CBC
1706 {
1707 CbcOrClpParam p("clique!Cuts", "Whether to use Clique cuts",
1708 "off", CBC_PARAM_STR_CLIQUECUTS);
1709 p.append("on");
1710 p.append("root");
1711 p.append("ifmove");
1712 p.append("forceOn");
1713 p.append("onglobal");
1714 p.setLonghelp(CUTS_LONGHELP
1715 " Reference: https://github.com/coin-or/Cgl/wiki/CglClique");
1716
1717 parameters.push_back(p);
1718 }
1719 {
1720 CbcOrClpParam p("combine!Solutions", "Whether to use combine solution heuristic",
1721 "off", CBC_PARAM_STR_COMBINE);
1722
1723 p.append("on");
1724 p.append("both");
1725 p.append("before");
1726 p.append("onquick");
1727 p.append("bothquick");
1728 p.append("beforequick");
1729 p.setLonghelp(
1730 "This heuristic does branch and cut on given problem by just \
1731 using variables which have appeared in one or more solutions. \
1732 It is obviously only tried after two or more solutions have been found. "
1733 HEURISTICS_LONGHELP);
1734
1735 parameters.push_back(p);
1736 }
1737 {
1738 CbcOrClpParam p("combine2!Solutions", "Whether to use crossover solution heuristic",
1739 "off", CBC_PARAM_STR_CROSSOVER2);
1740 p.append("on");
1741 p.append("both");
1742 p.append("before");
1743 p.setLonghelp(
1744 "This heuristic does branch and cut on the problem given by \
1745 fixing variables which have the same value in two or more solutions. \
1746 It obviously only tries after two or more solutions. "
1747 HEURISTICS_LONGHELP);
1748 parameters.push_back(p);
1749 }
1750 {
1751 CbcOrClpParam p("constraint!fromCutoff", "Whether to use cutoff as constraint",
1752 "off", CBC_PARAM_STR_CUTOFF_CONSTRAINT);
1753
1754 p.append("on");
1755 p.append("variable");
1756 p.append("forcevariable");
1757 p.append("conflict");
1758 p.setLonghelp(
1759 "For some problems, cut generators and general branching work better if the problem would be infeasible if the cost is too high. "
1760 "If this option is enabled, the objective function is added as a constraint which right hand side is set to the current cutoff value (objective value of best known solution)");
1761 parameters.push_back(p);
1762 }
1763 {
1764 CbcOrClpParam p("cost!Strategy", "How to use costs for branching priorities",
1765 "off", CBC_PARAM_STR_COSTSTRATEGY);
1766
1767 p.append("pri!orities");
1768 p.append("column!Order?");
1769 p.append("01f!irst?");
1770 p.append("01l!ast?");
1771 p.append("length!?");
1772 p.append("singletons");
1773 p.append("nonzero");
1774 p.append("general!Force?");
1775 p.setLonghelp(
1776 "Value 'priorities' assigns highest priority to variables with largest absolute cost. This primitive strategy can be surprisingly effective. "
1777 "Value 'columnorder' assigns the priorities 1, 2, 3, ... with respect to the column ordering. "
1778 "Value '01first' ('01last') assignes two sets of priorities such that binary variables get high (low) priority. "
1779 "Value 'length' assigns high priority to variables that occur in many equations. ");
1780
1781 parameters.push_back(p);
1782 }
1783 {
1784 CbcOrClpParam p("cplex!Use", "Whether to use Cplex!",
1785 "off", CBC_PARAM_STR_CPX);
1786 p.append("on");
1787 p.setLonghelp(
1788 " If the user has Cplex, but wants to use some of Cbc's heuristics \
1789 then you can! If this is on, then Cbc will get to the root node and then \
1790 hand over to Cplex. If heuristics find a solution this can be significantly \
1791 quicker. You will probably want to switch off Cbc's cuts as Cplex thinks \
1792 they are genuine constraints. It is also probable that you want to switch \
1793 off preprocessing, although for difficult problems it is worth trying \
1794 both.");
1795 parameters.push_back(p);
1796 }
1797 #endif
1798 {
1799 CbcOrClpParam p("cpp!Generate", "Generates C++ code",
1800 -1, 50000, CLP_PARAM_INT_CPP, 1);
1801 p.setLonghelp(
1802 "Once you like what the stand-alone solver does then this allows \
1803 you to generate user_driver.cpp which approximates the code. \
1804 0 gives simplest driver, 1 generates saves and restores, 2 \
1805 generates saves and restores even for variables at default value. \
1806 4 bit in cbc generates size dependent code rather than computed values. \
1807 This is now deprecated as you can call stand-alone solver - see \
1808 Cbc/examples/driver4.cpp.");
1809 parameters.push_back(p);
1810 }
1811 #ifdef COIN_HAS_CLP
1812 {
1813 CbcOrClpParam p("crash", "Whether to create basis for problem",
1814 "off", CLP_PARAM_STR_CRASH);
1815
1816 p.append("on");
1817 p.append("so!low_halim");
1818 p.append("lots");
1819 #ifdef CLP_INHERIT_MODE
1820 p.append("dual");
1821 p.append("dw");
1822 p.append("idiot");
1823 #else
1824 p.append("idiot1");
1825 p.append("idiot2");
1826 p.append("idiot3");
1827 p.append("idiot4");
1828 p.append("idiot5");
1829 p.append("idiot6");
1830 p.append("idiot7");
1831 #endif
1832 p.setLonghelp(
1833 "If crash is set to 'on' and there is an all slack basis then Clp will flip or put structural\
1834 variables into the basis with the aim of getting dual feasible. On average, dual simplex seems to perform\
1835 better without it and there are alternative types of 'crash' for primal simplex, e.g. 'idiot' or 'sprint'. \
1836 A variant due to Solow and Halim which is as 'on' but just flips is also available.");
1837
1838 parameters.push_back(p);
1839 }
1840 {
1841 CbcOrClpParam p("cross!over", "Whether to get a basic solution with the simplex algorithm after the barrier algorithm finished",
1842 "on", CLP_PARAM_STR_CROSSOVER);
1843 p.append("off");
1844 p.append("maybe");
1845 p.append("presolve");
1846 p.setLonghelp(
1847 "Interior point algorithms do not obtain a basic solution.\
1848 This option will crossover to a basic solution suitable for ranging or branch and cut. With the current state \
1849 of the solver for quadratic programs it may be a good idea to switch off crossover for this case (and maybe \
1850 presolve as well) - the option 'maybe' does this.");
1851 parameters.push_back(p);
1852 }
1853 #endif
1854 #ifdef COIN_HAS_CBC
1855 {
1856 CbcOrClpParam p("csv!Statistics", "Create one line of statistics",
1857 CLP_PARAM_ACTION_CSVSTATISTICS, 2, 1);
1858 p.setLonghelp(
1859 "This appends statistics to given file name. It will use the default\
1860 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
1861 is initialized to '', i.e. it must be set. Adds header if file empty or does not exist.");
1862 parameters.push_back(p);
1863 }
1864 {
1865 CbcOrClpParam p("cutD!epth", "Depth in tree at which to do cuts",
1866 -1, COIN_INT_MAX, CBC_PARAM_INT_CUTDEPTH);
1867 p.setLonghelp(
1868 "Cut generators may be off, on, on only at the root node, or on if they look useful. \
1869 Setting this option to a positive value K let CBC call a cutgenerator on a node whenever the depth in the tree is a multiple of K. \
1870 The default of -1 lets CBC decide.");
1871 p.setIntValue(-1);
1872 parameters.push_back(p);
1873 }
1874 {
1875 CbcOrClpParam p("cutL!ength", "Length of a cut",
1876 -1, COIN_INT_MAX, CBC_PARAM_INT_CUTLENGTH);
1877 p.setLonghelp("At present this only applies to Gomory cuts. -1 (default) leaves as is. \
1878 Any value >0 says that all cuts <= this length can be generated both at \
1879 root node and in tree. 0 says to use some dynamic lengths. If value >=10,000,000 \
1880 then the length in tree is value%10000000 - so 10000100 means unlimited length \
1881 at root and 100 in tree.");
1882 p.setIntValue(-1);
1883 parameters.push_back(p);
1884 }
1885 {
1886 CbcOrClpParam p("cuto!ff", "Bound on the objective value for all solutions",
1887 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_CUTOFF);
1888 p.setDoubleValue(1.0e50);
1889 p.setLonghelp(
1890 "All solutions must have a better objective value (in a minimization sense) than the value of this option. \
1891 CBC also updates this value whenever it obtains a solution to the value of \
1892 the objective function of the solution minus the cutoff increment.");
1893 parameters.push_back(p);
1894 }
1895 {
1896 CbcOrClpParam p("cuts!OnOff", "Switches all cut generators on or off",
1897 "off", CBC_PARAM_STR_CUTSSTRATEGY);
1898 p.append("on");
1899 p.append("root");
1900 p.append("ifmove");
1901 p.append("forceOn");
1902 p.setLonghelp(
1903 "This can be used to switch on or off all cut generators (apart from Reduce and Split). "
1904 "Then one can turn individual ones off or on. "
1905 CUTS_LONGHELP);
1906 parameters.push_back(p);
1907 }
1908 {
1909 CbcOrClpParam p("debug!In", "read valid solution from file",
1910 CLP_PARAM_ACTION_DEBUG, 7, 1);
1911
1912 p.setLonghelp(
1913 "This will read a solution file from the given file name. It will use the default\
1914 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
1915 is initialized to '', i.e. it must be set.\n\n\
1916 If set to create it will create a file called debug.file after search.\n\n\
1917 The idea is that if you suspect a bad cut generator \
1918 you can do a good run with debug set to 'create' and then switch on the cuts you suspect and \
1919 re-run with debug set to 'debug.file' The create case has same effect as saveSolution.");
1920 parameters.push_back(p);
1921 }
1922 #endif
1923 #ifdef COIN_HAS_CLP
1924 {
1925 CbcOrClpParam p("decomp!ose", "Whether to try decomposition",
1926 -COIN_INT_MAX, COIN_INT_MAX, CLP_PARAM_INT_DECOMPOSE_BLOCKS, 1);
1927 p.setLonghelp(
1928 "0 - off, 1 choose blocks >1 use as blocks \
1929 Dantzig Wolfe if primal, Benders if dual \
1930 - uses sprint pass for number of passes");
1931 p.setIntValue(0);
1932 parameters.push_back(p);
1933 }
1934 #if CLP_MULTIPLE_FACTORIZATIONS > 0
1935 {
1936 CbcOrClpParam p("dense!Threshold", "Threshold for using dense factorization",
1937 -1, 10000, CBC_PARAM_INT_DENSE, 1);
1938 p.setLonghelp(
1939 "If processed problem <= this use dense factorization");
1940 p.setIntValue(-1);
1941 parameters.push_back(p);
1942 }
1943 #endif
1944 #endif
1945 #ifdef COIN_HAS_CBC
1946 {
1947 CbcOrClpParam p("depth!MiniBab", "Depth at which to try mini branch-and-bound",
1948 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_DEPTHMINIBAB);
1949
1950 p.setIntValue(-1);
1951 p.setLonghelp(
1952 "Rather a complicated parameter but can be useful. -1 means off for large problems but on as if -12 for problems where rows+columns<500, -2 \
1953 means use Cplex if it is linked in. Otherwise if negative then go into depth first complete search fast branch and bound when depth>= -value-2 \
1954 (so -3 will use this at depth>=1). This mode is only switched on after 500 nodes. If you really want to switch it off for small problems then set \
1955 this to -999. If >=0 the value doesn't matter very much. The code will do approximately 100 nodes of fast branch and bound every now and then at depth>=5. \
1956 The actual logic is too twisted to describe here.");
1957 parameters.push_back(p);
1958 }
1959 {
1960 CbcOrClpParam p("dextra3", "Extra double parameter 3",
1961 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA3, 0);
1962 p.setDoubleValue(0.0);
1963 parameters.push_back(p);
1964 }
1965 {
1966 CbcOrClpParam p("dextra4", "Extra double parameter 4",
1967 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA4, 0);
1968 p.setDoubleValue(0.0);
1969 parameters.push_back(p);
1970 }
1971 {
1972 CbcOrClpParam p("dextra4", "Extra double parameter 5",
1973 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA5, 0);
1974 p.setDoubleValue(0.0);
1975 parameters.push_back(p);
1976 }
1977 {
1978 CbcOrClpParam p("Dins", "Whether to try Distance Induced Neighborhood Search",
1979 "off", CBC_PARAM_STR_DINS);
1980
1981 p.append("on");
1982 p.append("both");
1983 p.append("before");
1984 p.append("often");
1985 p.setLonghelp(HEURISTICS_LONGHELP);
1986 parameters.push_back(p);
1987 }
1988 #endif
1989 {
1990 CbcOrClpParam p("direction", "Minimize or Maximize",
1991 "min!imize", CLP_PARAM_STR_DIRECTION);
1992 p.append("max!imize");
1993 p.append("zero");
1994 p.setLonghelp(
1995 "The default is minimize - use 'direction maximize' for maximization.\n\
1996 You can also use the parameters 'maximize' or 'minimize'.");
1997 parameters.push_back(p);
1998 }
1999 {
2000 CbcOrClpParam p("directory", "Set Default directory for import etc.",
2001 CLP_PARAM_ACTION_DIRECTORY);
2002 p.setLonghelp(
2003 "This sets the directory which import, export, saveModel, restoreModel etc will use.\
2004 It is initialized to './'");
2005 parameters.push_back(p);
2006 }
2007 {
2008 CbcOrClpParam p("dirSample", "Set directory where the COIN-OR sample problems are.",
2009 CLP_PARAM_ACTION_DIRSAMPLE, 7, 1);
2010
2011 p.setLonghelp(
2012 "This sets the directory where the COIN-OR sample problems reside. It is\
2013 used only when -unitTest is passed to clp. clp will pick up the test problems\
2014 from this directory.\
2015 It is initialized to '../../Data/Sample'");
2016 parameters.push_back(p);
2017 }
2018 {
2019 CbcOrClpParam p("dirNetlib", "Set directory where the netlib problems are.",
2020 CLP_PARAM_ACTION_DIRNETLIB, 7, 1);
2021
2022 p.setLonghelp(
2023 "This sets the directory where the netlib problems reside. One can get\
2024 the netlib problems from COIN-OR or from the main netlib site. This\
2025 parameter is used only when -netlib is passed to clp. clp will pick up the\
2026 netlib problems from this directory. If clp is built without zlib support\
2027 then the problems must be uncompressed.\
2028 It is initialized to '../../Data/Netlib'");
2029 parameters.push_back(p);
2030 }
2031 {
2032 CbcOrClpParam p("dirMiplib", "Set directory where the miplib 2003 problems are.",
2033 CBC_PARAM_ACTION_DIRMIPLIB, 7, 1);
2034
2035 p.setLonghelp(
2036 "This sets the directory where the miplib 2003 problems reside. One can\
2037 get the miplib problems from COIN-OR or from the main miplib site. This\
2038 parameter is used only when -miplib is passed to cbc. cbc will pick up the\
2039 miplib problems from this directory. If cbc is built without zlib support\
2040 then the problems must be uncompressed.\
2041 It is initialized to '../../Data/miplib3'");
2042 parameters.push_back(p);
2043 }
2044 #ifdef COIN_HAS_CBC
2045 {
2046 CbcOrClpParam p("diveO!pt", "Diving options",
2047 -1, 200000, CBC_PARAM_INT_DIVEOPT, 1);
2048 p.setLonghelp(
2049 "If >2 && <20 then modify diving options - \
2050 \n\t3 only at root and if no solution, \
2051 \n\t4 only at root and if this heuristic has not got solution, \
2052 \n\t5 decay only if no solution, \
2053 \n\t6 if depth <3 or decay, \
2054 \n\t7 run up to 2 times if solution found 4 otherwise, \
2055 \n\t>10 All only at root (DivingC normal as value-10), \
2056 \n\t>20 All with value-20).");
2057 p.setIntValue(-1);
2058 parameters.push_back(p);
2059 }
2060 {
2061 CbcOrClpParam p("diveS!olves", "Diving solve option",
2062 -1, 200000, CBC_PARAM_INT_DIVEOPTSOLVES, 1);
2063
2064 p.setLonghelp(
2065 "If >0 then do up to this many solves. However, the last digit is ignored \
2066 and used for extra options: \
2067 1-3 enables fixing of satisfied integer variables (but not at bound), \
2068 where 1 switches this off for that dive if the dive goes infeasible, \
2069 and 2 switches it off permanently if the dive goes infeasible.");
2070 p.setIntValue(100);
2071 parameters.push_back(p);
2072 }
2073 {
2074 CbcOrClpParam p("DivingS!ome", "Whether to try Diving heuristics",
2075 "off", CBC_PARAM_STR_DIVINGS);
2076
2077 p.append("on");
2078 p.append("both");
2079 p.append("before");
2080 p.setLonghelp(
2081 "This switches on a random diving heuristic at various times. \
2082 One may prefer to individually turn diving heuristics on or off. "
2083 HEURISTICS_LONGHELP);
2084 // C - Coefficient, F - Fractional, G - Guided, L - LineSearch, P - PseudoCost, V - VectorLength.
2085 parameters.push_back(p);
2086 }
2087 {
2088 CbcOrClpParam p("DivingC!oefficient", "Whether to try Coefficient diving heuristic",
2089 "off", CBC_PARAM_STR_DIVINGC);
2090 p.append("on");
2091 p.append("both");
2092 p.append("before");
2093 p.setLonghelp(HEURISTICS_LONGHELP);
2094 parameters.push_back(p);
2095 }
2096 {
2097 CbcOrClpParam p("DivingF!ractional", "Whether to try Fractional diving heuristic",
2098 "off", CBC_PARAM_STR_DIVINGF);
2099 p.append("on");
2100 p.append("both");
2101 p.append("before");
2102 p.setLonghelp(HEURISTICS_LONGHELP);
2103 parameters.push_back(p);
2104 }
2105 {
2106 CbcOrClpParam p("DivingG!uided", "Whether to try Guided diving heuristic",
2107 "off", CBC_PARAM_STR_DIVINGG);
2108 p.append("on");
2109 p.append("both");
2110 p.append("before");
2111 p.setLonghelp(HEURISTICS_LONGHELP);
2112 parameters.push_back(p);
2113 }
2114 {
2115 CbcOrClpParam p("DivingL!ineSearch", "Whether to try Linesearch diving heuristic",
2116 "off", CBC_PARAM_STR_DIVINGL);
2117 p.append("on");
2118 p.append("both");
2119 p.append("before");
2120 p.setLonghelp(HEURISTICS_LONGHELP);
2121 parameters.push_back(p);
2122 }
2123 {
2124 CbcOrClpParam p("DivingP!seudoCost", "Whether to try Pseudocost diving heuristic",
2125 "off", CBC_PARAM_STR_DIVINGP);
2126 p.append("on");
2127 p.append("both");
2128 p.append("before");
2129 p.setLonghelp(HEURISTICS_LONGHELP);
2130 parameters.push_back(p);
2131 }
2132 {
2133 CbcOrClpParam p("DivingV!ectorLength", "Whether to try Vectorlength diving heuristic",
2134 "off", CBC_PARAM_STR_DIVINGV);
2135 p.append("on");
2136 p.append("both");
2137 p.append("before");
2138 p.setLonghelp(HEURISTICS_LONGHELP);
2139 parameters.push_back(p);
2140 }
2141 {
2142 CbcOrClpParam p("doH!euristic", "Do heuristics before any preprocessing",
2143 CBC_PARAM_ACTION_DOHEURISTIC, 3);
2144 p.setLonghelp(
2145 "Normally heuristics are done in branch and bound. It may be useful to do them outside. \
2146 Only those heuristics with 'both' or 'before' set will run. \
2147 Doing this may also set cutoff, which can help with preprocessing.");
2148 parameters.push_back(p);
2149 }
2150 #endif
2151 #ifdef COIN_HAS_CLP
2152 {
2153 CbcOrClpParam p("dualB!ound", "Initially algorithm acts as if no \
2154 gap between bounds exceeds this value",
2155 1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALBOUND);
2156 p.setLonghelp(
2157 "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\
2158 algorithm where you first get feasible then optimal. If a problem has both upper and\
2159 lower bounds then it is trivial to get dual feasible by setting non basic variables\
2160 to correct bound. If the gap between the upper and lower bounds of a variable is more\
2161 than the value of dualBound Clp introduces fake bounds so that it can make the problem\
2162 dual feasible. This has the same effect as a composite objective function in the\
2163 primal algorithm. Too high a value may mean more iterations, while too low a bound means\
2164 the code may go all the way and then have to increase the bounds. OSL had a heuristic to\
2165 adjust bounds, maybe we need that here.");
2166
2167 parameters.push_back(p);
2168 }
2169 {
2170 CbcOrClpParam p("dualize", "Solves dual reformulation",
2171 0, 4, CLP_PARAM_INT_DUALIZE, 1);
2172 p.setLonghelp(
2173 "Don't even think about it.");
2174
2175 parameters.push_back(p);
2176 }
2177 {
2178 CbcOrClpParam p("dualP!ivot", "Dual pivot choice algorithm",
2179 "auto!matic", CLP_PARAM_STR_DUALPIVOT, 7, 1);
2180 p.append("dant!zig");
2181 p.append("partial");
2182 p.append("steep!est");
2183 p.append("PEsteep!est");
2184 p.append("PEdantzig");
2185 p.setLonghelp(
2186 "The Dantzig method is simple but its use is deprecated. Steepest is the method of choice and there\
2187 are two variants which keep all weights updated but only scan a subset each iteration.\
2188 Partial switches this on while automatic decides at each iteration based on information\
2189 about the factorization.\
2190 The PE variants add the Positive Edge criterion. \
2191 This selects incoming variables to try to avoid degenerate moves. See also option psi.");
2192 parameters.push_back(p);
2193 }
2194 {
2195 CbcOrClpParam p("dualS!implex", "Do dual simplex algorithm",
2196 CLP_PARAM_ACTION_DUALSIMPLEX);
2197 p.setLonghelp(
2198 "This command solves the continuous relaxation of the current model using the dual steepest edge algorithm.\
2199 The time and iterations may be affected by settings such as presolve, scaling, crash\
2200 and also by dual pivot method, fake bound on variables and dual and primal tolerances.");
2201 parameters.push_back(p);
2202 }
2203 #endif
2204 {
2205 CbcOrClpParam p("dualT!olerance", "For an optimal solution \
2206 no dual infeasibility may exceed this value",
2207 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_DUALTOLERANCE);
2208 p.setLonghelp(
2209 "Normally the default tolerance is fine, but one may want to increase it a\
2210 bit if the dual simplex algorithm seems to be having a hard time. One method which can be faster is \
2211 to use a large tolerance e.g. 1.0e-4 and the dual simplex algorithm and then to clean up the problem using the primal simplex algorithm with the \
2212 correct tolerance (remembering to switch off presolve for this final short clean up phase).");
2213 parameters.push_back(p);
2214 }
2215 #ifdef COIN_HAS_CBC
2216 {
2217 CbcOrClpParam p("dw!Heuristic", "Whether to try Dantzig Wolfe heuristic",
2218 "off", CBC_PARAM_STR_DW);
2219 p.append("on");
2220 p.append("both");
2221 p.append("before");
2222 p.setLonghelp(
2223 "This heuristic is very very compute intensive. It tries to find a Dantzig Wolfe structure and use that."
2224 HEURISTICS_LONGHELP);
2225 parameters.push_back(p);
2226 }
2227 #endif
2228 #ifdef COIN_HAS_CLP
2229 {
2230 CbcOrClpParam p("either!Simplex", "Do dual or primal simplex algorithm",
2231 CLP_PARAM_ACTION_EITHERSIMPLEX);
2232 p.setLonghelp(
2233 "This command solves the continuous relaxation of the current model using the dual or primal algorithm,\
2234 based on a dubious analysis of model.");
2235 parameters.push_back(p);
2236 }
2237 #endif
2238 {
2239 CbcOrClpParam p("end", "Stops clp execution",
2240 CLP_PARAM_ACTION_EXIT);
2241 p.setLonghelp(
2242 "This stops execution ; end, exit, quit and stop are synonyms");
2243 parameters.push_back(p);
2244 }
2245 {
2246 CbcOrClpParam p("environ!ment", "Read commands from environment",
2247 CLP_PARAM_ACTION_ENVIRONMENT, 7, 0);
2248 p.setLonghelp(
2249 "This starts reading from environment variable CBC_CLP_ENVIRONMENT.");
2250 parameters.push_back(p);
2251 }
2252 {
2253 CbcOrClpParam p("error!sAllowed", "Whether to allow import errors",
2254 "off", CLP_PARAM_STR_ERRORSALLOWED, 3);
2255
2256 p.append("on");
2257 p.setLonghelp(
2258 "The default is not to use any model which had errors when reading the mps file.\
2259 Setting this to 'on' will allow all errors from which the code can recover\
2260 simply by ignoring the error. There are some errors from which the code can not recover \
2261 e.g. no ENDATA. This has to be set before import i.e. -errorsAllowed on -import xxxxxx.mps.");
2262 parameters.push_back(p);
2263 }
2264 {
2265 CbcOrClpParam p("exit", "Stops clp execution",
2266 CLP_PARAM_ACTION_EXIT);
2267 p.setLonghelp(
2268 "This stops the execution of Clp, end, exit, quit and stop are synonyms");
2269 parameters.push_back(p);
2270 }
2271 #ifdef COIN_HAS_CBC
2272 {
2273 CbcOrClpParam p("exper!iment", "Whether to use testing features",
2274 -1, 200000, CBC_PARAM_INT_EXPERIMENT, 0);
2275 p.setLonghelp(
2276 "Defines how adventurous you want to be in using new ideas. \
2277 0 then no new ideas, 1 fairly sensible, 2 a bit dubious, 3 you are on your own!");
2278
2279 p.setIntValue(0);
2280 parameters.push_back(p);
2281 }
2282 {
2283 CbcOrClpParam p("expensive!Strong", "Whether to do even more strong branching",
2284 0, COIN_INT_MAX, CBC_PARAM_INT_STRONG_STRATEGY, 0);
2285
2286 p.setLonghelp(
2287 "Strategy for extra strong branching. \
2288 0 is normal strong branching. \
2289 1, 2, 4, and 6 does strong branching on all fractional variables if \
2290 at the root node (1), \
2291 at depth less than modifier (2), \
2292 objective equals best possible (4), or \
2293 at depth less than modifier and objective equals best possible (6). \
2294 11, 12, 14, and 16 are like 1, 2, 4, and 6, respecitively, but do strong branching on all integer (incl. non-fractional) variables. \
2295 Values >= 100 are used to specify a depth limit (value/100), otherwise 5 is used. \
2296 If the values >= 100, then above rules are applied to value%100.");
2297 p.setIntValue(0);
2298 parameters.push_back(p);
2299 }
2300 #endif
2301 {
2302 CbcOrClpParam p("export", "Export model as mps file",
2303 CLP_PARAM_ACTION_EXPORT);
2304
2305 p.setLonghelp(
2306 "This will write an MPS format file to the given file name. It will use the default\
2307 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
2308 is initialized to 'default.mps'. \
2309 It can be useful to get rid of the original names and go over to using Rnnnnnnn and Cnnnnnnn. This can be done by setting 'keepnames' off before importing mps file.");
2310 parameters.push_back(p);
2311 }
2312 #ifdef COIN_HAS_CBC
2313 {
2314 CbcOrClpParam p("extra1", "Extra integer parameter 1",
2315 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA1, 0);
2316 p.setIntValue(-1);
2317 parameters.push_back(p);
2318 }
2319 {
2320 CbcOrClpParam p("extra2", "Extra integer parameter 2",
2321 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA2, 0);
2322 p.setIntValue(-1);
2323 parameters.push_back(p);
2324 }
2325 {
2326 CbcOrClpParam p("extra3", "Extra integer parameter 3",
2327 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA3, 0);
2328 p.setIntValue(-1);
2329 parameters.push_back(p);
2330 }
2331 {
2332 CbcOrClpParam p("extra4", "Extra integer parameter 4",
2333 -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA4, 0);
2334
2335 p.setIntValue(-1);
2336 p.setLonghelp(
2337 "This switches on yet more special options!! \
2338 The bottom digit is a strategy when to used shadow price stuff e.g. 3 \
2339 means use until a solution is found. The next two digits say what sort \
2340 of dual information to use. After that it goes back to powers of 2 so -\n\
2341 \n\t1000 - switches on experimental hotstart\n\
2342 \n\t2,4,6000 - switches on experimental methods of stopping cuts\n\
2343 \n\t8000 - increase minimum drop gradually\n\
2344 \n\t16000 - switches on alternate gomory criterion");
2345 parameters.push_back(p);
2346 }
2347 {
2348 CbcOrClpParam p("extraV!ariables", "Allow creation of extra integer variables",
2349 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA_VARIABLES, 0);
2350 p.setIntValue(0);
2351 p.setLonghelp(
2352 "Switches on a trivial re-formulation that introduces extra integer variables to group together variables with same cost.");
2353 parameters.push_back(p);
2354 }
2355 #endif
2356 #ifdef COIN_HAS_CLP
2357 {
2358 CbcOrClpParam p("fact!orization", "Which factorization to use",
2359 "normal", CLP_PARAM_STR_FACTORIZATION);
2360 p.append("dense");
2361 p.append("simple");
2362 p.append("osl");
2363 p.setLonghelp(
2364 #ifndef ABC_INHERIT
2365 "The default is to use the normal CoinFactorization, but \
2366 other choices are a dense one, OSL's, or one designed for small problems."
2367 #else
2368 "Normally the default is to use the normal CoinFactorization, but \
2369 other choices are a dense one, OSL's, or one designed for small problems. \
2370 However if at Aboca then the default is CoinAbcFactorization and other choices are \
2371 a dense one, one designed for small problems or if enabled a long factorization."
2372 #endif
2373 );
2374 parameters.push_back(p);
2375 }
2376 {
2377 CbcOrClpParam p("fakeB!ound", "All bounds <= this value - DEBUG",
2378 1.0, 1.0e15, CLP_PARAM_ACTION_FAKEBOUND, 0);
2379 parameters.push_back(p);
2380 }
2381 #ifdef COIN_HAS_CBC
2382 {
2383 CbcOrClpParam p("feas!ibilityPump", "Whether to try the Feasibility Pump heuristic",
2384 "off", CBC_PARAM_STR_FPUMP);
2385
2386 p.append("on");
2387 p.append("both");
2388 p.append("before");
2389 p.setLonghelp(
2390 "This heuristic is due to Fischetti, Glover, and Lodi \
2391 and uses a sequence of LPs to try and get an integer feasible solution. \
2392 Some fine tuning is available by options passFeasibilityPump and pumpTune. "
2393 HEURISTICS_LONGHELP);
2394 parameters.push_back(p);
2395 }
2396 {
2397 CbcOrClpParam p("fix!OnDj", "Try heuristic based on fixing variables with \
2398 reduced costs greater than this",
2399 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DJFIX, 1);
2400 p.setLonghelp(
2401 "If this is set integer variables with reduced costs greater than this will be fixed \
2402 before branch and bound - use with extreme caution!");
2403 parameters.push_back(p);
2404 }
2405 {
2406 CbcOrClpParam p("flow!CoverCuts", "Whether to use Flow Cover cuts",
2407 "off", CBC_PARAM_STR_FLOWCUTS);
2408 p.append("on");
2409 p.append("root");
2410 p.append("ifmove");
2411 p.append("forceOn");
2412 p.append("onglobal");
2413 p.setFakeKeyWord(3);
2414 p.setLonghelp(CUTS_LONGHELP
2415 " Reference: https://github.com/coin-or/Cgl/wiki/CglFlowCover"); // Can also enter testing values by plusnn (==ifmove)
2416 parameters.push_back(p);
2417 }
2418 {
2419 CbcOrClpParam p("force!Solution", "Whether to use given solution as crash for BAB",
2420 -1, 20000000, CLP_PARAM_INT_USESOLUTION);
2421 p.setIntValue(-1);
2422 p.setLonghelp(
2423 "-1 off. If 1 then tries to branch to solution given by AMPL or priorities file. \
2424 If 0 then just tries to set as best solution \
2425 If >1 then also does that many nodes on fixed problem.");
2426 parameters.push_back(p);
2427 }
2428 {
2429 CbcOrClpParam p("fraction!forBAB", "Fraction in feasibility pump",
2430 1.0e-5, 1.1, CBC_PARAM_DBL_SMALLBAB, 1);
2431 p.setDoubleValue(0.5);
2432 p.setLonghelp(
2433 "After a pass in the feasibility pump, variables which have not moved \
2434 about are fixed and if the preprocessed model is smaller than this fraction of the original problem, \
2435 a few nodes of branch and bound are done on the reduced problem.");
2436 parameters.push_back(p);
2437 }
2438 #endif
2439 {
2440 CbcOrClpParam p("gamma!(Delta)", "Whether to regularize barrier",
2441 "off", CLP_PARAM_STR_GAMMA, 7, 1);
2442 p.append("on");
2443 p.append("gamma");
2444 p.append("delta");
2445 p.append("onstrong");
2446 p.append("gammastrong");
2447 p.append("deltastrong");
2448 parameters.push_back(p);
2449 }
2450 #endif
2451 #ifdef COIN_HAS_CBC
2452 {
2453 CbcOrClpParam p("GMI!Cuts", "Whether to use alternative Gomory cuts",
2454 "off", CBC_PARAM_STR_GMICUTS);
2455
2456 p.append("on");
2457 p.append("root");
2458 p.append("ifmove");
2459 p.append("forceOn");
2460 p.append("endonly");
2461 p.append("long");
2462 p.append("longroot");
2463 p.append("longifmove");
2464 p.append("forceLongOn");
2465 p.append("longendonly");
2466 p.setLonghelp(CUTS_LONGHELP
2467 " This version is by Giacomo Nannicini and may be more robust than gomoryCuts.");
2468 parameters.push_back(p);
2469 }
2470 {
2471 CbcOrClpParam p("gomory!Cuts", "Whether to use Gomory cuts",
2472 "off", CBC_PARAM_STR_GOMORYCUTS);
2473
2474 p.append("on");
2475 p.append("root");
2476 p.append("ifmove");
2477 p.append("forceOn");
2478 p.append("onglobal");
2479 p.append("forceandglobal");
2480 p.append("forceLongOn");
2481 p.append("long");
2482 p.setLonghelp(
2483 "The original cuts - beware of imitations! Having gone out of favor, \
2484 they are now more fashionable as LP solvers are more robust and they interact well \
2485 with other cuts. They will almost always give cuts (although in this executable \
2486 they are limited as to number of variables in cut). However the cuts may be dense \
2487 so it is worth experimenting (Long allows any length). "
2488 CUTS_LONGHELP
2489 " Reference: https://github.com/coin-or/Cgl/wiki/CglGomory");
2490 parameters.push_back(p);
2491 }
2492 {
2493 CbcOrClpParam p("greedy!Heuristic", "Whether to use a greedy heuristic",
2494 "off", CBC_PARAM_STR_GREEDY);
2495
2496 p.append("on");
2497 p.append("both");
2498 p.append("before");
2499 //p.append("root");
2500 p.setLonghelp(
2501 "This heuristic tries to obtain a feasible solution by just fixing a percentage of variables and then try a small branch and cut run. "
2502 HEURISTICS_LONGHELP);
2503 parameters.push_back(p);
2504 }
2505 #endif
2506 {
2507 CbcOrClpParam p("gsolu!tion", "Puts glpk solution to file",
2508 CLP_PARAM_ACTION_GMPL_SOLUTION);
2509
2510 p.setLonghelp(
2511 "Will write a glpk solution file to the given file name. It will use the default \
2512 directory given by 'directory'. A name of '$' will use the previous value for the \
2513 name. This is initialized to 'stdout' (this defaults to ordinary solution if stdout). \
2514 If problem created from gmpl model - will do any reports.");
2515 parameters.push_back(p);
2516 }
2517 {
2518 CbcOrClpParam p("guess", "Guesses at good parameters", CLP_PARAM_ACTION_GUESS, 7);
2519 p.setLonghelp(
2520 "This looks at model statistics and does an initial solve \
2521 setting some parameters which may help you to think of possibilities.");
2522 parameters.push_back(p);
2523 }
2524 #ifdef COIN_HAS_CBC
2525 {
2526 CbcOrClpParam p("heur!isticsOnOff", "Switches most primal heuristics on or off",
2527 "off", CBC_PARAM_STR_HEURISTICSTRATEGY);
2528 p.append("on");
2529 p.setLonghelp(
2530 "This option can be used to switch on or off all heuristics that search for feasible solutions,\
2531 except for the local tree search, as it dramatically alters the search.\
2532 Then individual heuristics can be turned off or on.");
2533 parameters.push_back(p);
2534 }
2535 {
2536 CbcOrClpParam p("help", "Print out version, non-standard options and some help",
2537 CLP_PARAM_ACTION_HELP, 3);
2538 p.setLonghelp(
2539 "This prints out some help to get user started. If you have printed this then \
2540 you should be past that stage:-)");
2541 parameters.push_back(p);
2542 }
2543 #endif
2544 #ifdef COIN_HAS_CBC
2545 {
2546 CbcOrClpParam p("hOp!tions", "Heuristic options",
2547 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_HOPTIONS, 1);
2548 p.setIntValue(0);
2549 p.setLonghelp(
2550 "Value 1 stops heuristics immediately if the allowable gap has been reached. \
2551 Other values are for the feasibility pump - \
2552 2 says do exact number of passes given, \
2553 4 only applies if an initial cutoff has been given and says relax after 50 passes, \
2554 while 8 will adapt the cutoff rhs after the first solution if it looks as if the code is stalling.");
2555 parameters.push_back(p);
2556 }
2557 {
2558 CbcOrClpParam p("hot!StartMaxIts", "Maximum iterations on hot start",
2559 0, COIN_INT_MAX, CBC_PARAM_INT_MAXHOTITS);
2560 parameters.push_back(p);
2561 }
2562 #endif
2563 #ifdef COIN_HAS_CLP
2564 {
2565 CbcOrClpParam p("idiot!Crash", "Whether to try idiot crash",
2566 -1, COIN_INT_MAX, CLP_PARAM_INT_IDIOT);
2567
2568 p.setLonghelp(
2569 "This is a type of 'crash' which works well on some homogeneous problems.\
2570 It works best on problems with unit elements and rhs but will do something to any \
2571 model. It should only be used before the primal simplex algorithm. It can be set to -1 when the code \
2572 decides for itself whether to use it, 0 to switch off, or n > 0 to do n passes.");
2573 parameters.push_back(p);
2574 }
2575 #endif
2576 {
2577 CbcOrClpParam p("import", "Import model from mps file",
2578 CLP_PARAM_ACTION_IMPORT, 3);
2579 p.setLonghelp(
2580 "This will read an MPS format file from the given file name. It will use the default\
2581 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
2582 is initialized to '', i.e. it must be set. If you have libgz then it can read compressed\
2583 files 'xxxxxxxx.gz' or 'xxxxxxxx.bz2'. \
2584 If 'keepnames' is off, then names are dropped -> Rnnnnnnn and Cnnnnnnn.");
2585 parameters.push_back(p);
2586 }
2587 #ifdef COIN_HAS_CBC
2588 {
2589 CbcOrClpParam p("inc!rement", "A valid solution must be at least this \
2590 much better than last integer solution",
2591 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_INCREMENT);
2592
2593 p.setLonghelp(
2594 "Whenever a solution is found the bound on the objective value for new solutions is set to the\
2595 objective function of the found solution (in a minimization sense) plus this. If it is not set then CBC will try and work one out, e.g. if \
2596 all objective coefficients are multiples of 0.01 and only integer variables have entries in \
2597 the objective function, then the increment can be set to 0.01. Be careful if setting this to a negative value!");
2598
2599 parameters.push_back(p);
2600 }
2601 {
2602 CbcOrClpParam p("inf!easibilityWeight", "Each integer infeasibility is expected \
2603 to cost this much",
2604 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_INFEASIBILITYWEIGHT, 1);
2605 p.setLonghelp(
2606 "A primitive way of deciding which node to explore next. Satisfying each integer infeasibility is \
2607 expected to cost this much.");
2608 parameters.push_back(p);
2609 }
2610 {
2611 CbcOrClpParam p("initialS!olve", "Solve to continuous",
2612 CLP_PARAM_ACTION_SOLVECONTINUOUS);
2613
2614 p.setLonghelp(
2615 "This just solves the problem to continuous - without adding any cuts");
2616 parameters.push_back(p);
2617 }
2618 {
2619 CbcOrClpParam p("integerT!olerance", "For a feasible solution \
2620 no integer variable may be more than this away from an integer value",
2621 1.0e-20, 0.5, CBC_PARAM_DBL_INTEGERTOLERANCE);
2622 p.setLonghelp(
2623 "Beware of setting this smaller than the primal feasibility tolerance.");
2624 parameters.push_back(p);
2625 }
2626 #endif
2627 #ifdef COIN_HAS_CLP
2628 {
2629 CbcOrClpParam p("keepN!ames", "Whether to keep names from import",
2630 "on", CLP_PARAM_STR_KEEPNAMES);
2631 p.append("off");
2632 p.setLonghelp(
2633 "It saves space to get rid of names so if you need to you can set this to off. \
2634 This needs to be set before the import of model - so -keepnames off -import xxxxx.mps.");
2635 parameters.push_back(p);
2636 }
2637 {
2638 CbcOrClpParam p("KKT", "Whether to use KKT factorization in barrier",
2639 "off", CLP_PARAM_STR_KKT, 7, 1);
2640 p.append("on");
2641 parameters.push_back(p);
2642 }
2643 #endif
2644 #ifdef COIN_HAS_CBC
2645 {
2646 CbcOrClpParam p("knapsack!Cuts", "Whether to use Knapsack cuts",
2647 "off", CBC_PARAM_STR_KNAPSACKCUTS);
2648
2649 p.append("on");
2650 p.append("root");
2651 p.append("ifmove");
2652 p.append("forceOn");
2653 p.append("onglobal");
2654 p.append("forceandglobal");
2655 p.setLonghelp(CUTS_LONGHELP
2656 " Reference: https://github.com/coin-or/Cgl/wiki/CglKnapsackCover");
2657 parameters.push_back(p);
2658 }
2659 {
2660 CbcOrClpParam p("lagomory!Cuts", "Whether to use Lagrangean Gomory cuts",
2661 "off", CBC_PARAM_STR_LAGOMORYCUTS);
2662 p.append("endonlyroot");
2663 p.append("endcleanroot");
2664 p.append("root");
2665 p.append("endonly");
2666 p.append("endclean");
2667 p.append("endboth");
2668 p.append("onlyaswell");
2669 p.append("cleanaswell");
2670 p.append("bothaswell");
2671 p.append("onlyinstead");
2672 p.append("cleaninstead");
2673 p.append("bothinstead");
2674 p.append("onlyaswellroot");
2675 p.append("cleanaswellroot");
2676 p.append("bothaswellroot");
2677 p.setLonghelp(
2678 "This is a gross simplification of 'A Relax-and-Cut Framework for Gomory's Mixed-Integer Cuts' \
2679 by Matteo Fischetti & Domenico Salvagnin. This simplification \
2680 just uses original constraints while modifying objective using other cuts. \
2681 So you don't use messy constraints generated by Gomory etc. \
2682 A variant is to allow non messy cuts e.g. clique cuts. \
2683 So 'only' does this while 'clean' also allows integral valued cuts. \
2684 'End' is recommended and waits until other cuts have finished before it \
2685 does a few passes. \
2686 The length options for gomory cuts are used.");
2687 parameters.push_back(p);
2688 }
2689 {
2690 CbcOrClpParam p("latwomir!Cuts", "Whether to use Lagrangean TwoMir cuts",
2691 "off", CBC_PARAM_STR_LATWOMIRCUTS);
2692
2693 p.append("endonlyroot");
2694 p.append("endcleanroot");
2695 p.append("endbothroot");
2696 p.append("endonly");
2697 p.append("endclean");
2698 p.append("endboth");
2699 p.append("onlyaswell");
2700 p.append("cleanaswell");
2701 p.append("bothaswell");
2702 p.append("onlyinstead");
2703 p.append("cleaninstead");
2704 p.append("bothinstead");
2705 p.setLonghelp(
2706 "This is a Lagrangean relaxation for TwoMir cuts. See \
2707 lagomoryCuts for description of options.");
2708 parameters.push_back(p);
2709 }
2710 {
2711 CbcOrClpParam p("lift!AndProjectCuts", "Whether to use Lift and Project cuts",
2712 "off", CBC_PARAM_STR_LANDPCUTS);
2713
2714 p.append("on");
2715 p.append("root");
2716 p.append("ifmove");
2717 p.append("forceOn");
2718 p.setLonghelp(
2719 "These cuts may be expensive to compute. "
2720 CUTS_LONGHELP
2721 " Reference: https://github.com/coin-or/Cgl/wiki/CglLandP");
2722 parameters.push_back(p);
2723 }
2724 {
2725 CbcOrClpParam p("local!TreeSearch", "Whether to use local tree search when a solution is found",
2726 "off", CBC_PARAM_STR_LOCALTREE);
2727 p.append("on");
2728 p.setLonghelp(
2729 "The heuristic is from Fischetti and Lodi and is not really a heuristic although it can be used as one \
2730 (with limited functionality). It is not switched on when heuristics are switched on.");
2731 parameters.push_back(p);
2732 }
2733 #endif
2734 {
2735 #ifndef COIN_HAS_CBC
2736 CbcOrClpParam p("log!Level", "Level of detail in Solver output",
2737 -1, COIN_INT_MAX, CLP_PARAM_INT_SOLVERLOGLEVEL);
2738 parameters.push_back(p);
2739 #else
2740 CbcOrClpParam p("log!Level", "Level of detail in Coin branch and Cut output",
2741 -63, 63, CLP_PARAM_INT_LOGLEVEL);
2742 p.setIntValue(1);
2743 #endif
2744 p.setLonghelp(
2745 "If 0 then there should be no output in normal circumstances. 1 is probably the best\
2746 value for most uses, while 2 and 3 give more information.");
2747 parameters.push_back(p);
2748 }
2749 {
2750 CbcOrClpParam p("max!imize", "Set optimization direction to maximize",
2751 CLP_PARAM_ACTION_MAXIMIZE, 7);
2752 p.setLonghelp(
2753 "The default is minimize - use 'maximize' for maximization.\n\
2754 You can also use the parameters 'direction maximize'.");
2755 parameters.push_back(p);
2756 }
2757 #ifdef COIN_HAS_CLP
2758 {
2759 CbcOrClpParam p("maxF!actor", "Maximum number of iterations between \
2760 refactorizations",
2761 1, COIN_INT_MAX, CLP_PARAM_INT_MAXFACTOR);
2762 p.setLonghelp(
2763 "If this is left at its default value of 200 then CLP will guess a\
2764 value to use. CLP may decide to re-factorize earlier for accuracy.");
2765 parameters.push_back(p);
2766 }
2767 {
2768 CbcOrClpParam p("maxIt!erations", "Maximum number of iterations before \
2769 stopping",
2770 0, COIN_INT_MAX, CLP_PARAM_INT_MAXITERATION);
2771 p.setLonghelp(
2772 "This can be used for testing purposes. The corresponding library call\n\
2773 \tsetMaximumIterations(value)\n can be useful. If the code stops on\
2774 seconds or by an interrupt this will be treated as stopping on maximum iterations. This is ignored in branchAndCut - use maxN!odes.");
2775 parameters.push_back(p);
2776 }
2777 #endif
2778 #ifdef COIN_HAS_CBC
2779 {
2780 CbcOrClpParam p("maxN!odes", "Maximum number of nodes to do",
2781 -1, COIN_INT_MAX, CBC_PARAM_INT_MAXNODES);
2782 p.setLonghelp(
2783 "This is a repeatable way to limit search. Normally using time is easier \
2784 but then the results may not be repeatable.");
2785 parameters.push_back(p);
2786 }
2787 {
2788 CbcOrClpParam p("maxSaved!Solutions", "Maximum number of solutions to save",
2789 0, COIN_INT_MAX, CBC_PARAM_INT_MAXSAVEDSOLS);
2790 p.setLonghelp(
2791 "Number of solutions to save.");
2792 parameters.push_back(p);
2793 }
2794 {
2795 CbcOrClpParam p("maxSo!lutions", "Maximum number of feasible solutions to get",
2796 1, COIN_INT_MAX, CBC_PARAM_INT_MAXSOLS);
2797 p.setLonghelp(
2798 "You may want to stop after (say) two solutions or an hour. \
2799 This is checked every node in tree, so it is possible to get more solutions from heuristics.");
2800 parameters.push_back(p);
2801 }
2802 #endif
2803 {
2804 CbcOrClpParam p("min!imize", "Set optimization direction to minimize",
2805 CLP_PARAM_ACTION_MINIMIZE, 7);
2806 p.setLonghelp(
2807 "The default is minimize - use 'maximize' for maximization.\n\
2808 This should only be necessary if you have previously set maximization \
2809 You can also use the parameters 'direction minimize'.");
2810 parameters.push_back(p);
2811 }
2812 #ifdef COIN_HAS_CBC
2813 {
2814 CbcOrClpParam p("mipO!ptions", "Dubious options for mip",
2815 0, COIN_INT_MAX, CBC_PARAM_INT_MIPOPTIONS, 0);
2816 p.setIntValue(1057);
2817 parameters.push_back(p);
2818 }
2819 {
2820 CbcOrClpParam p("more!MipOptions", "More dubious options for mip",
2821 -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0);
2822 parameters.push_back(p);
2823 }
2824 {
2825 CbcOrClpParam p("more2!MipOptions", "More more dubious options for mip",
2826 -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMOREMIPOPTIONS, 0);
2827 p.setIntValue(0);
2828 parameters.push_back(p);
2829 }
2830 {
2831 CbcOrClpParam p("mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts",
2832 "off", CBC_PARAM_STR_MIXEDCUTS);
2833
2834 p.append("on");
2835 p.append("root");
2836 p.append("ifmove");
2837 p.append("forceOn");
2838 p.append("onglobal");
2839 p.setLonghelp(CUTS_LONGHELP
2840 " Reference: https://github.com/coin-or/Cgl/wiki/CglMixedIntegerRounding2");
2841 parameters.push_back(p);
2842 }
2843 #endif
2844 {
2845 CbcOrClpParam p("mess!ages", "Controls if Clpnnnn is printed",
2846 "off", CLP_PARAM_STR_MESSAGES);
2847
2848 p.append("on");
2849 p.setLonghelp("The default behavior is to put out messages such as:\n\
2850 Clp0005 2261 Objective 109.024 Primal infeas 944413 (758)\n\
2851 but this program turns this off to make it look more friendly. It can be useful\
2852 to turn them back on if you want to be able to 'grep' for particular messages or if\
2853 you intend to override the behavior of a particular message. This only affects Clp not Cbc.");
2854 parameters.push_back(p);
2855 }
2856 {
2857 CbcOrClpParam p("miplib", "Do some of miplib test set",
2858 CBC_PARAM_ACTION_MIPLIB, 3, 1);
2859 parameters.push_back(p);
2860 }
2861 #ifdef COIN_HAS_CBC
2862 {
2863 CbcOrClpParam p("mips!tart", "reads an initial feasible solution from file",
2864 CBC_PARAM_ACTION_MIPSTART);
2865 p.setLonghelp("\
2866 The MIPStart allows one to enter an initial integer feasible solution \
2867 to CBC. Values of the main decision variables which are active (have \
2868 non-zero values) in this solution are specified in a text file. The \
2869 text file format used is the same of the solutions saved by CBC, but \
2870 not all fields are required to be filled. First line may contain the \
2871 solution status and will be ignored, remaining lines contain column \
2872 indexes, names and values as in this example:\n\
2873 \n\
2874 Stopped on iterations - objective value 57597.00000000\n\
2875 0 x(1,1,2,2) 1 \n\
2876 1 x(3,1,3,2) 1 \n\
2877 5 v(5,1) 2 \n\
2878 33 x(8,1,5,2) 1 \n\
2879 ...\n\
2880 \n\
2881 Column indexes are also ignored since pre-processing can change them. \
2882 There is no need to include values for continuous or integer auxiliary \
2883 variables, since they can be computed based on main decision variables. \
2884 Starting CBC with an integer feasible solution can dramatically improve \
2885 its performance: several MIP heuristics (e.g. RINS) rely on having at \
2886 least one feasible solution available and can start immediately if the \
2887 user provides one. Feasibility Pump (FP) is a heuristic which tries to \
2888 overcome the problem of taking too long to find feasible solution (or \
2889 not finding at all), but it not always succeeds. If you provide one \
2890 starting solution you will probably save some time by disabling FP. \
2891 \n\n\
2892 Knowledge specific to your problem can be considered to write an \
2893 external module to quickly produce an initial feasible solution - some \
2894 alternatives are the implementation of simple greedy heuristics or the \
2895 solution (by CBC for example) of a simpler model created just to find \
2896 a feasible solution. \
2897 \n\n\
2898 Silly options added. If filename ends .low then integers not mentioned \
2899 are set low - also .high, .lowcheap, .highcheap, .lowexpensive, .highexpensive \
2900 where .lowexpensive sets costed ones to make expensive others low. Also if \
2901 filename starts empty. then no file is read at all - just actions done. \
2902 \n\n\
2903 Question and suggestions regarding MIPStart can be directed to\n\
2904 haroldo.santos@gmail.com. ");
2905 parameters.push_back(p);
2906 }
2907 #endif
2908 {
2909 CbcOrClpParam p("moreS!pecialOptions", "Yet more dubious options for Simplex - see ClpSimplex.hpp",
2910 0, COIN_INT_MAX, CLP_PARAM_INT_MORESPECIALOPTIONS, 0);
2911 parameters.push_back(p);
2912 }
2913 #ifdef COIN_HAS_CBC
2914 {
2915 CbcOrClpParam p("moreT!une", "Yet more dubious ideas for feasibility pump",
2916 0, 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0);
2917
2918 p.setLonghelp(
2919 "Yet more ideas for Feasibility Pump \n\
2920 \t/100000 == 1 use box constraints and original obj in cleanup\n\
2921 \t/1000 == 1 Pump will run twice if no solution found\n\
2922 \t/1000 == 2 Pump will only run after root cuts if no solution found\n\
2923 \t/1000 >10 as above but even if solution found\n\
2924 \t/100 == 1,3.. exact 1.0 for objective values\n\
2925 \t/100 == 2,3.. allow more iterations per pass\n\
2926 \t n fix if value of variable same for last n iterations.");
2927 p.setIntValue(0);
2928 parameters.push_back(p);
2929 }
2930 {
2931 CbcOrClpParam p("multiple!RootPasses", "Do multiple root passes to collect cuts and solutions",
2932 0, COIN_INT_MAX, CBC_PARAM_INT_MULTIPLEROOTS, 0);
2933 p.setIntValue(0);
2934 p.setLonghelp(
2935 "Solve (in parallel, if enabled) the root phase this number of times, \
2936 each with its own different seed, and collect all solutions and cuts generated. \
2937 The actual format is aabbcc where aa is the number of extra passes; \
2938 if bb is non zero, then it is number of threads to use (otherwise uses threads setting); \
2939 and cc is the number of times to do root phase. \
2940 The solvers do not interact with each other. However if extra passes are specified \
2941 then cuts are collected and used in later passes - so there is interaction there. \
2942 Some parts of this implementation have their origin in idea of \
2943 Andrea Lodi, Matteo Fischetti, Michele Monaci, Domenico Salvagnin, and Andrea Tramontani.");
2944 parameters.push_back(p);
2945 }
2946 {
2947 CbcOrClpParam p("naive!Heuristics", "Whether to try some stupid heuristic",
2948 "off", CBC_PARAM_STR_NAIVE, 7, 1);
2949
2950 p.append("on");
2951 p.append("both");
2952 p.append("before");
2953 p.setLonghelp(
2954 "This is naive heuristics which, e.g., fix all integers with costs to zero!. "
2955 HEURISTICS_LONGHELP);
2956 parameters.push_back(p);
2957 }
2958 #endif
2959 #ifdef COIN_HAS_CLP
2960 {
2961 CbcOrClpParam p("netlib", "Solve entire netlib test set",
2962 CLP_PARAM_ACTION_NETLIB_EITHER, 3, 1);
2963 p.setLonghelp(
2964 "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\
2965 The user can set options before e.g. clp -presolve off -netlib");
2966 parameters.push_back(p);
2967 }
2968 {
2969 CbcOrClpParam p("netlibB!arrier", "Solve entire netlib test set with barrier",
2970 CLP_PARAM_ACTION_NETLIB_BARRIER, 3, 1);
2971 p.setLonghelp(
2972 "This exercises the unit test for clp and then solves the netlib test set using barrier.\
2973 The user can set options before e.g. clp -kkt on -netlib");
2974 parameters.push_back(p);
2975 }
2976 {
2977 CbcOrClpParam p("netlibD!ual", "Solve entire netlib test set (dual)",
2978 CLP_PARAM_ACTION_NETLIB_DUAL, 3, 1);
2979
2980 p.setLonghelp(
2981 "This exercises the unit test for clp and then solves the netlib test set using dual.\
2982 The user can set options before e.g. clp -presolve off -netlib");
2983 parameters.push_back(p);
2984 }
2985 {
2986 CbcOrClpParam p("netlibP!rimal", "Solve entire netlib test set (primal)",
2987 CLP_PARAM_ACTION_NETLIB_PRIMAL, 3, 1);
2988 p.setLonghelp(
2989 "This exercises the unit test for clp and then solves the netlib test set using primal.\
2990 The user can set options before e.g. clp -presolve off -netlibp");
2991 parameters.push_back(p);
2992 }
2993 {
2994 CbcOrClpParam p("netlibT!une", "Solve entire netlib test set with 'best' algorithm",
2995 CLP_PARAM_ACTION_NETLIB_TUNE, 3, 1);
2996 p.setLonghelp(
2997 "This exercises the unit test for clp and then solves the netlib test set using whatever \
2998 works best. I know this is cheating but it also stresses the code better by doing a \
2999 mixture of stuff. The best algorithm was chosen on a Linux ThinkPad using native cholesky \
3000 with University of Florida ordering.");
3001 parameters.push_back(p);
3002 }
3003 {
3004 CbcOrClpParam p("network", "Tries to make network matrix",
3005 CLP_PARAM_ACTION_NETWORK, 7, 0);
3006 p.setLonghelp(
3007 "Clp will go faster if the matrix can be converted to a network. The matrix\
3008 operations may be a bit faster with more efficient storage, but the main advantage\
3009 comes from using a network factorization. It will probably not be as fast as a \
3010 specialized network code.");
3011 parameters.push_back(p);
3012 }
3013 #ifdef COIN_HAS_CBC
3014 {
3015 CbcOrClpParam p("nextB!estSolution", "Prints next best saved solution to file",
3016 CLP_PARAM_ACTION_NEXTBESTSOLUTION);
3017
3018 p.setLonghelp(
3019 "To write best solution, just use solution. This prints next best (if exists) \
3020 and then deletes it. \
3021 This will write a primitive solution file to the given file name. It will use the default\
3022 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3023 is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask.");
3024 parameters.push_back(p);
3025 }
3026 {
3027 CbcOrClpParam p("node!Strategy", "What strategy to use to select the next node from the branch and cut tree",
3028 "hybrid", CBC_PARAM_STR_NODESTRATEGY);
3029 p.append("fewest");
3030 p.append("depth");
3031 p.append("upfewest");
3032 p.append("downfewest");
3033 p.append("updepth");
3034 p.append("downdepth");
3035 p.setLonghelp(
3036 "Normally before a feasible solution is found, CBC will choose a node with fewest infeasibilities. \
3037 Alternatively, one may choose tree-depth as the criterion. This requires the minimal amount of memory, but may take a long time to find the best solution.\
3038 Additionally, one may specify whether up or down branches must \
3039 be selected first (the up-down choice will carry on after a first solution has been bound). \
3040 The default choice 'hybrid' does breadth first on small depth nodes and then switches to 'fewest'.");
3041 parameters.push_back(p);
3042 }
3043 {
3044 CbcOrClpParam p("numberA!nalyze", "Number of analysis iterations",
3045 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0);
3046 p.setLonghelp(
3047 "This says how many iterations to spend at root node analyzing problem. \
3048 This is a first try and will hopefully become more sophisticated.");
3049 parameters.push_back(p);
3050 }
3051 #endif
3052 {
3053 CbcOrClpParam p("objective!Scale", "Scale factor to apply to objective",
3054 -COIN_DBL_MAX, COIN_DBL_MAX, CLP_PARAM_DBL_OBJSCALE, 1);
3055 p.setLonghelp(
3056 "If the objective function has some very large values, you may wish to scale them\
3057 internally by this amount. It can also be set by autoscale. It is applied after scaling. You are unlikely to need this.");
3058 p.setDoubleValue(1.0);
3059 parameters.push_back(p);
3060 }
3061 #endif
3062 #ifdef COIN_HAS_CBC
3063 #ifdef COIN_HAS_NTY
3064 {
3065 CbcOrClpParam p("Orbit!alBranching", "Whether to try orbital branching",
3066 "off", CBC_PARAM_STR_ORBITAL);
3067 p.append("on");
3068 p.append("strong");
3069 p.append("force");
3070 p.append("simple");
3071 p.setLonghelp(
3072 "This switches on Orbital branching. \
3073 Value 'on' just adds orbital, 'strong' tries extra fixing in strong branching.");
3074 parameters.push_back(p);
3075 }
3076 #endif
3077 {
3078 CbcOrClpParam p("PrepN!ames", "If column names will be kept in pre-processed model",
3079 "off", CBC_PARAM_STR_PREPROCNAMES);
3080 p.append("on");
3081 p.setLonghelp(
3082 "Normally the preprocessed model has column names replaced by new names C0000...\
3083 Setting this option to on keeps original names in variables which still exist in the preprocessed problem");
3084 parameters.push_back(p);
3085 }
3086
3087 {
3088 CbcOrClpParam p("outDup!licates", "takes duplicate rows etc out of integer model",
3089 CLP_PARAM_ACTION_OUTDUPROWS, 7, 0);
3090 parameters.push_back(p);
3091 }
3092 #endif
3093 {
3094 CbcOrClpParam p("output!Format", "Which output format to use",
3095 1, 6, CLP_PARAM_INT_OUTPUTFORMAT);
3096 p.setLonghelp(
3097 "Normally export will be done using normal representation for numbers and two values\
3098 per line. You may want to do just one per line (for grep or suchlike) and you may wish\
3099 to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
3100 otherwise odd values gives one value per line, even two. Values 1,2 give normal format, 3,4\
3101 gives greater precision, while 5,6 give IEEE values. When used for exporting a basis 1 does not save \
3102 values, 2 saves values, 3 with greater accuracy and 4 in IEEE.");
3103 parameters.push_back(p);
3104 }
3105 #ifdef COIN_HAS_CLP
3106 {
3107 CbcOrClpParam p("para!metrics", "Import data from file and do parametrics",
3108 CLP_PARAM_ACTION_PARAMETRICS, 3);
3109 p.setLonghelp(
3110 "This will read a file with parametric data from the given file name \
3111 and then do parametrics. It will use the default\
3112 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3113 is initialized to '', i.e. it must be set. This can not read from compressed files. \
3114 File is in modified csv format - a line ROWS will be followed by rows data \
3115 while a line COLUMNS will be followed by column data. The last line \
3116 should be ENDATA. The ROWS line must exist and is in the format \
3117 ROWS, inital theta, final theta, interval theta, n where n is 0 to get \
3118 CLPI0062 message at interval or at each change of theta \
3119 and 1 to get CLPI0063 message at each iteration. If interval theta is 0.0 \
3120 or >= final theta then no interval reporting. n may be missed out when it is \
3121 taken as 0. If there is Row data then \
3122 there is a headings line with allowed headings - name, number, \
3123 lower(rhs change), upper(rhs change), rhs(change). Either the lower and upper \
3124 fields should be given or the rhs field. \
3125 The optional COLUMNS line is followed by a headings line with allowed \
3126 headings - name, number, objective(change), lower(change), upper(change). \
3127 Exactly one of name and number must be given for either section and \
3128 missing ones have value 0.0.");
3129 parameters.push_back(p);
3130 }
3131 #endif
3132 #ifdef COIN_HAS_CBC
3133 {
3134 CbcOrClpParam p("passC!uts", "Number of rounds that cut generators are applied in the root node",
3135 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_CUTPASS);
3136
3137 p.setIntValue(20);
3138 p.setLonghelp(
3139 "The default is to do 100 passes if the problem has less than 500 columns, 100 passes (but \
3140 stop if the drop in the objective function value is small) if the problem has less than 5000 columns, and 20 passes otherwise. \
3141 A negative value -n means that n passes are also applied if the objective does not drop.");
3142 parameters.push_back(p);
3143 }
3144 {
3145 CbcOrClpParam p("passF!easibilityPump", "How many passes to do in the Feasibility Pump heuristic",
3146 0, 10000, CBC_PARAM_INT_FPUMPITS);
3147 p.setIntValue(20);
3148 parameters.push_back(p);
3149 }
3150 #endif
3151 #ifdef COIN_HAS_CLP
3152 {
3153 CbcOrClpParam p("passP!resolve", "How many passes in presolve",
3154 -200, 100, CLP_PARAM_INT_PRESOLVEPASS, 1);
3155 p.setLonghelp(
3156 "Normally Presolve does 10 passes but you may want to do less to make it\
3157 more lightweight or do more if improvements are still being made. As Presolve will return\
3158 if nothing is being taken out, you should not normally need to use this fine tuning.");
3159 parameters.push_back(p);
3160 }
3161 #endif
3162 #ifdef COIN_HAS_CBC
3163 {
3164 CbcOrClpParam p("passT!reeCuts", "Number of rounds that cut generators are applied in the tree",
3165 -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_CUTPASSINTREE);
3166 p.setIntValue(1);
3167 p.setLonghelp("The default is to do one pass. A negative value -n means that n passes are also applied if the objective does not drop.");
3168 parameters.push_back(p);
3169 }
3170 #endif
3171 #ifdef COIN_HAS_CLP
3172 {
3173 CbcOrClpParam p("pertV!alue", "Method of perturbation",
3174 -5000, 102, CLP_PARAM_INT_PERTVALUE, 1);
3175 parameters.push_back(p);
3176 }
3177 {
3178 CbcOrClpParam p("perturb!ation", "Whether to perturb the problem",
3179 "on", CLP_PARAM_STR_PERTURBATION);
3180 p.append("off");
3181 p.setLonghelp(
3182 "Perturbation helps to stop cycling, but CLP uses other measures for this.\
3183 However, large problems and especially ones with unit elements and unit right hand sides or costs\
3184 benefit from perturbation. Normally CLP tries to be intelligent, but one can switch this off.");
3185 // The Clp library has this off by default. This program has it on by default.
3186 parameters.push_back(p);
3187 }
3188 {
3189 CbcOrClpParam p("PFI", "Whether to use Product Form of Inverse in simplex",
3190 "off", CLP_PARAM_STR_PFI, 7, 0);
3191 p.append("on");
3192 p.setLonghelp(
3193 "By default clp uses Forrest-Tomlin L-U update. If you are masochistic you can switch it off.");
3194 parameters.push_back(p);
3195 }
3196 #endif
3197 #ifdef COIN_HAS_CBC
3198 {
3199 CbcOrClpParam p("pivotAndC!omplement", "Whether to try Pivot and Complement heuristic",
3200 "off", CBC_PARAM_STR_PIVOTANDCOMPLEMENT);
3201
3202 p.append("on");
3203 p.append("both");
3204 p.append("before");
3205 p.setLonghelp(HEURISTICS_LONGHELP);
3206 parameters.push_back(p);
3207 }
3208 {
3209 CbcOrClpParam p("pivotAndF!ix", "Whether to try Pivot and Fix heuristic",
3210 "off", CBC_PARAM_STR_PIVOTANDFIX);
3211 p.append("on");
3212 p.append("both");
3213 p.append("before");
3214 p.setLonghelp(HEURISTICS_LONGHELP);
3215 parameters.push_back(p);
3216 }
3217 #endif
3218 #ifdef COIN_HAS_CLP
3219 {
3220 CbcOrClpParam p("plus!Minus", "Tries to make +- 1 matrix",
3221 CLP_PARAM_ACTION_PLUSMINUS, 7, 0);
3222 p.setLonghelp(
3223 "Clp will go slightly faster if the matrix can be converted so that the elements are\
3224 not stored and are known to be unit. The main advantage is memory use. Clp may automatically\
3225 see if it can convert the problem so you should not need to use this.");
3226 parameters.push_back(p);
3227 }
3228 {
3229 CbcOrClpParam p("pO!ptions", "Dubious print options",
3230 0, COIN_INT_MAX, CLP_PARAM_INT_PRINTOPTIONS, 1);
3231 p.setIntValue(0);
3232 p.setLonghelp(
3233 "If this is > 0 then presolve will give more information and branch and cut will give statistics");
3234 parameters.push_back(p);
3235 }
3236 {
3237 CbcOrClpParam p("preO!pt", "Presolve options",
3238 0, COIN_INT_MAX, CLP_PARAM_INT_PRESOLVEOPTIONS, 0);
3239 parameters.push_back(p);
3240 }
3241 #endif
3242 {
3243 CbcOrClpParam p("presolve", "Whether to presolve problem",
3244 "on", CLP_PARAM_STR_PRESOLVE);
3245 p.append("off");
3246 p.append("more");
3247 p.append("file");
3248 p.setLonghelp("Presolve analyzes the model to find such things as redundant equations, equations\
3249 which fix some variables, equations which can be transformed into bounds, etc. For the\
3250 initial solve of any problem this is worth doing unless one knows that it will have no effect. \
3251 Option 'on' will normally do 5 passes, while using 'more' will do 10. If the problem is very large one can \
3252 let CLP write the original problem to file by using 'file'.");
3253 parameters.push_back(p);
3254 }
3255 #ifdef COIN_HAS_CBC
3256 {
3257 CbcOrClpParam p("preprocess", "Whether to use integer preprocessing",
3258 "off", CBC_PARAM_STR_PREPROCESS);
3259
3260 p.append("on");
3261 p.append("save");
3262 p.append("equal");
3263 p.append("sos");
3264 p.append("trysos");
3265 p.append("equalall");
3266 p.append("strategy");
3267 p.append("aggregate");
3268 p.append("forcesos");
3269 p.append("stop!aftersaving");
3270 p.setLonghelp(
3271 "This tries to reduce size of model in a similar way to presolve and \
3272 it also tries to strengthen the model - this can be very useful and is worth trying. \
3273 Value 'save' saves the presolved problem to a file presolved.mps.\
3274 Value 'equal' will turn inequality-cliques into equalities.\
3275 Value 'sos' lets CBC search for rows with upper bound 1 and where all nonzero coefficients are 1 and creates special ordered sets if the sets are not overlapping and all integer variables (except for at most one) are in the sets.\
3276 Value 'trysos' is same as 'sos', but allows any number of integer variables outside of sets.\
3277 Value 'equalall' lets CBC turn all valid inequalities into equalities by adding integer slack variables."); // Value 'strategy' is as on but uses CbcStrategy.
3278 parameters.push_back(p);
3279 }
3280 #endif
3281 #ifdef COIN_HAS_CLP
3282 {
3283 CbcOrClpParam p("preT!olerance", "Tolerance to use in presolve",
3284 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_PRESOLVETOLERANCE);
3285 p.setLonghelp(
3286 "One may want to increase this tolerance if presolve says the problem is \
3287 infeasible and one has awkward numbers and is sure that the problem is really feasible.");
3288 parameters.push_back(p);
3289 }
3290 {
3291 CbcOrClpParam p("primalP!ivot", "Primal pivot choice algorithm",
3292 "auto!matic", CLP_PARAM_STR_PRIMALPIVOT, 7, 1);
3293
3294 p.append("exa!ct");
3295 p.append("dant!zig");
3296 p.append("part!ial");
3297 p.append("steep!est");
3298 p.append("change");
3299 p.append("sprint");
3300 p.append("PEsteep!est");
3301 p.append("PEdantzig");
3302 p.setLonghelp(
3303 "The Dantzig method is simple but its use is deprecated. Exact devex is the method of choice and there\
3304 are two variants which keep all weights updated but only scan a subset each iteration.\
3305 Partial switches this on while 'change' initially does 'dantzig' until the factorization\
3306 becomes denser. This is still a work in progress.\
3307 The PE variants add the Positive Edge criterion.\
3308 This selects incoming variables to try to avoid degenerate moves. \
3309 See also Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR's CLP;\
3310 Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex.");
3311
3312 parameters.push_back(p);
3313 }
3314 {
3315 CbcOrClpParam p("primalS!implex", "Do primal simplex algorithm",
3316 CLP_PARAM_ACTION_PRIMALSIMPLEX);
3317
3318 p.setLonghelp(
3319 "This command solves the continuous relaxation of the current model using the primal algorithm.\
3320 The default is to use exact devex.\
3321 The time and iterations may be affected by settings such as presolve, scaling, crash\
3322 and also by column selection method, infeasibility weight and dual and primal tolerances.");
3323 parameters.push_back(p);
3324 }
3325 #endif
3326 {
3327 CbcOrClpParam p("primalT!olerance", "For a feasible solution \
3328 no primal infeasibility, i.e., constraint violation, may exceed this value",
3329 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_PRIMALTOLERANCE);
3330 p.setLonghelp(
3331 "Normally the default tolerance is fine, but one may want to increase it a\
3332 bit if the primal simplex algorithm seems to be having a hard time.");
3333 parameters.push_back(p);
3334 }
3335 #ifdef COIN_HAS_CLP
3336 {
3337 CbcOrClpParam p("primalW!eight", "Initially algorithm acts as if it \
3338 costs this much to be infeasible",
3339 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_PRIMALWEIGHT);
3340 p.setLonghelp(
3341 "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
3342 algorithm where you first get feasible then optimal. So Clp is minimizing this weight times\
3343 the sum of primal infeasibilities plus the true objective function (in minimization sense).\
3344 Too high a value may mean more iterations, while too low a value means\
3345 the algorithm may iterate into the wrong directory for long and then has to increase the weight in order to get feasible."); // OSL had a heuristic to adjust bounds, maybe we need that here.
3346 parameters.push_back(p);
3347 }
3348 {
3349 CbcOrClpParam p("psi", "Two-dimension pricing factor for Positive Edge criterion",
3350 -1.1, 1.1, CLP_PARAM_DBL_PSI);
3351
3352 p.setDoubleValue(-0.5);
3353 p.setLonghelp(
3354 "The Positive Edge criterion has been added to \
3355 select incoming variables to try and avoid degenerate moves. \
3356 Variables not in the promising set have their infeasibility weight multiplied by psi, \
3357 so 0.01 would mean that if there were any promising variables, then they would always be chosen, \
3358 while 1.0 effectively switches the algorithm off. \
3359 There are two ways of switching this feature on. One way is to set psi to a positive value and then \
3360 the Positive Edge criterion will be used for both primal and dual simplex. The other way is to select PEsteepest \
3361 in dualpivot choice (for example), then the absolute value of psi is used. \
3362 Code donated by Jeremy Omer. See \
3363 Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR's CLP; \
3364 Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex."); // Until this settles down it is only implemented in CLP.
3365 parameters.push_back(p);
3366 }
3367 #endif
3368 {
3369 CbcOrClpParam p("printi!ngOptions", "Print options",
3370 "normal", CLP_PARAM_STR_INTPRINT, 3);
3371 p.append("integer");
3372 p.append("special");
3373 p.append("rows");
3374 p.append("all");
3375 p.append("csv");
3376 p.append("bound!ranging");
3377 p.append("rhs!ranging");
3378 p.append("objective!ranging");
3379 p.append("stats");
3380 p.append("boundsint");
3381 p.append("boundsall");
3382 p.append("fixint");
3383 p.append("fixall");
3384 p.setLonghelp(
3385 "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\
3386 integer - nonzero integer column variables\n\
3387 special - in format suitable for OsiRowCutDebugger\n\
3388 rows - nonzero column variables and row activities\n\
3389 all - all column variables and row activities.\n\
3390 \nFor non-integer problems 'integer' and 'special' act like 'normal'. \
3391 Also see printMask for controlling output.");
3392 parameters.push_back(p);
3393 }
3394 {
3395 CbcOrClpParam p("printM!ask", "Control printing of solution on a mask",
3396 CLP_PARAM_ACTION_PRINTMASK, 3);
3397
3398 p.setLonghelp(
3399 "If set then only those names which match mask are printed in a solution. \
3400 '?' matches any character and '*' matches any set of characters. \
3401 The default is '' i.e. unset so all variables are printed. \
3402 This is only active if model has names.");
3403 parameters.push_back(p);
3404 }
3405
3406 #ifdef COIN_HAS_CBC
3407 {
3408 CbcOrClpParam p("prio!rityIn", "Import priorities etc from file",
3409 CBC_PARAM_ACTION_PRIORITYIN, 3);
3410 p.setLonghelp(
3411 "This will read a file with priorities from the given file name. It will use the default\
3412 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3413 is initialized to '', i.e. it must be set. This can not read from compressed files. \
3414 File is in csv format with allowed headings - name, number, priority, direction, up, down, solution. Exactly one of\
3415 name and number must be given.");
3416 parameters.push_back(p);
3417 }
3418
3419 {
3420 CbcOrClpParam p("probing!Cuts", "Whether to use Probing cuts",
3421 "off", CBC_PARAM_STR_PROBINGCUTS);
3422 p.append("on");
3423 p.append("root");
3424 p.append("ifmove");
3425 p.append("forceOn");
3426 p.append("onglobal");
3427 p.append("forceonglobal");
3428 p.append("forceOnBut");
3429 p.append("forceOnStrong");
3430 p.append("forceOnButStrong");
3431 p.append("strongRoot");
3432 p.setLonghelp(CUTS_LONGHELP
3433 " Value 'forceOnBut' turns on probing and forces CBC to do probing at every node, but does only probing, not strengthening etc. \
3434 Value 'strong' forces CBC to strongly do probing at every node, that is, also when CBC would usually turn it off because it hasn't found something. \
3435 Value 'forceonbutstrong' is like 'forceonstrong', but does only probing (column fixing) and turns off row strengthening, so the matrix will not change inside the branch and bound. \
3436 Reference: https://github.com/coin-or/Cgl/wiki/CglProbing");
3437 parameters.push_back(p);
3438 }
3439 {
3440 CbcOrClpParam p("proximity!Search", "Whether to do proximity search heuristic",
3441 "off", CBC_PARAM_STR_PROXIMITY);
3442
3443 p.append("on");
3444 p.append("both");
3445 p.append("before");
3446 p.append("10");
3447 p.append("100");
3448 p.append("300");
3449 // but allow numbers after this (returning 1)
3450 p.setFakeKeyWord(1);
3451 p.setLonghelp(
3452 "This heuristic looks for a solution close to the incumbent solution (Fischetti and Monaci, 2012). \
3453 The idea is to define a sub-MIP without additional constraints but with a modified objective function intended to attract the search \
3454 in the proximity of the incumbent. \
3455 The approach works well for 0-1 MIPs whose solution landscape is not too irregular (meaning the there is reasonable probability of \
3456 finding an improved solution by flipping a small number of binary variables), in particular when it is applied to the first heuristic solutions \
3457 found at the root node. "
3458 HEURISTICS_LONGHELP); // Can also set different maxNode settings by plusnnnn (and are 'on'(on==30)).
3459 parameters.push_back(p);
3460 }
3461 {
3462 CbcOrClpParam p("pumpC!utoff", "Fake cutoff for use in feasibility pump",
3463 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKECUTOFF);
3464 p.setDoubleValue(0.0);
3465 p.setLonghelp(
3466 "A value of 0.0 means off. Otherwise, add a constraint forcing objective below this value\
3467 in feasibility pump");
3468 parameters.push_back(p);
3469 }
3470 {
3471 CbcOrClpParam p("pumpI!ncrement", "Fake increment for use in feasibility pump",
3472 -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKEINCREMENT, 1);
3473 p.setDoubleValue(0.0);
3474 p.setLonghelp(
3475 "A value of 0.0 means off. Otherwise use as absolute increment to cutoff \
3476 when solution found in feasibility pump");
3477 parameters.push_back(p);
3478 }
3479 {
3480 CbcOrClpParam p("pumpT!une", "Dubious ideas for feasibility pump",
3481 0, 100000000, CBC_PARAM_INT_FPUMPTUNE);
3482 p.setIntValue(1003);
3483 p.setLonghelp(
3484 "This fine tunes Feasibility Pump \n\
3485 \t>=10000000 use as objective weight switch\n\
3486 \t>=1000000 use as accumulate switch\n\
3487 \t>=1000 use index+1 as number of large loops\n\
3488 \t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\
3489 \t%100 == 10,20 affects how each solve is done\n\
3490 \t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \
3491 If accumulate is on then after a major pass, variables which have not moved \
3492 are fixed and a small branch and bound is tried.");
3493 p.setIntValue(0);
3494 parameters.push_back(p);
3495 }
3496 #endif
3497 {
3498 CbcOrClpParam p("quit", "Stops clp execution",
3499 CLP_PARAM_ACTION_EXIT);
3500 p.setLonghelp(
3501 "This stops the execution of Clp, end, exit, quit and stop are synonyms");
3502
3503 parameters.push_back(p);
3504 }
3505 #ifdef COIN_HAS_CBC
3506 {
3507 CbcOrClpParam p("randomC!bcSeed", "Random seed for Cbc",
3508 -1, COIN_INT_MAX, CBC_PARAM_INT_RANDOMSEED);
3509
3510 p.setLonghelp(
3511 "Allows initialization of the random seed for pseudo-random numbers used in heuristics such as the Feasibility Pump to decide whether to round up or down. "
3512 "The special value of 0 lets Cbc use the time of the day for the initial seed.");
3513 p.setIntValue(-1);
3514 parameters.push_back(p);
3515 }
3516 {
3517 CbcOrClpParam p("randomi!zedRounding", "Whether to try randomized rounding heuristic",
3518 "off", CBC_PARAM_STR_RANDROUND);
3519 p.append("on");
3520 p.append("both");
3521 p.append("before");
3522 p.setLonghelp(HEURISTICS_LONGHELP);
3523 parameters.push_back(p);
3524 }
3525 #endif
3526 #ifdef COIN_HAS_CLP
3527 {
3528 CbcOrClpParam p("randomS!eed", "Random seed for Clp",
3529 0, COIN_INT_MAX, CLP_PARAM_INT_RANDOMSEED);
3530
3531 p.setLonghelp(
3532 "Initialization of the random seed for pseudo-random numbers used to break ties in degenerate problems. "
3533 "This may yield a different continuous optimum and, in the context of Cbc, different cuts and heuristic solutions. "
3534 "The special value of 0 lets CLP use the time of the day for the initial seed.");
3535 p.setIntValue(1234567);
3536 parameters.push_back(p);
3537 }
3538 #endif
3539 #ifdef COIN_HAS_CBC
3540 {
3541 CbcOrClpParam p("ratio!Gap", "Stop when gap between best possible and \
3542 best known is less than this fraction of larger of two",
3543 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_GAPRATIO);
3544 p.setDoubleValue(0.0);
3545 p.setLonghelp(
3546 "If the gap between the best known solution and the best possible solution is less than this fraction \
3547 of the objective value at the root node then the search will terminate. See 'allowableGap' for a \
3548 way of using absolute value rather than fraction.");
3549 parameters.push_back(p);
3550 }
3551 #endif
3552 {
3553 CbcOrClpParam p("restoreS!olution", "reads solution from file",
3554 CLP_PARAM_ACTION_RESTORESOL);
3555
3556 p.setLonghelp(
3557 "This will read a binary solution file from the given file name. It will use the default\
3558 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3559 is initialized to 'solution.file'. This reads in a file from saveSolution");
3560 parameters.push_back(p);
3561 }
3562 #ifdef COIN_HAS_CBC
3563 {
3564 CbcOrClpParam p("readSt!ored", "Import stored cuts from file",
3565 CLP_PARAM_ACTION_STOREDFILE, 3, 0);
3566 parameters.push_back(p);
3567 }
3568 #endif
3569 #ifdef COIN_HAS_CLP
3570 {
3571 CbcOrClpParam p("reallyO!bjectiveScale", "Scale factor to apply to objective in place",
3572 -COIN_DBL_MAX, COIN_DBL_MAX, CLP_PARAM_DBL_OBJSCALE2, 0);
3573 p.setLonghelp("You can set this to -1.0 to test maximization or other to stress code");
3574 p.setDoubleValue(1.0);
3575 parameters.push_back(p);
3576 }
3577 {
3578 CbcOrClpParam p("reallyS!cale", "Scales model in place",
3579 CLP_PARAM_ACTION_REALLY_SCALE, 7, 0);
3580 parameters.push_back(p);
3581 }
3582 #endif
3583 #ifdef COIN_HAS_CBC
3584 {
3585 CbcOrClpParam p("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts",
3586 "off", CBC_PARAM_STR_REDSPLITCUTS);
3587
3588 p.append("on");
3589 p.append("root");
3590 p.append("ifmove");
3591 p.append("forceOn");
3592 p.setLonghelp(
3593 "These cuts may be expensive to generate. "
3594 CUTS_LONGHELP
3595 " Reference: https://github.com/coin-or/Cgl/wiki/CglRedSplit");
3596 parameters.push_back(p);
3597 }
3598 {
3599 CbcOrClpParam p("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2",
3600 "off", CBC_PARAM_STR_REDSPLIT2CUTS);
3601 p.append("on");
3602 p.append("root");
3603 p.append("longOn");
3604 p.append("longRoot");
3605 p.setLonghelp("This switches on reduce and split cuts (either at root or in entire tree). \
3606 This version is by Giacomo Nannicini based on Francois Margot's version. \
3607 Standard setting only uses rows in tableau <= 256, long uses all. \
3608 These cuts may be expensive to generate. \
3609 See option cuts for more information on the possible values.");
3610 parameters.push_back(p);
3611 }
3612 {
3613 CbcOrClpParam p("residual!CapacityCuts", "Whether to use Residual Capacity cuts",
3614 "off", CBC_PARAM_STR_RESIDCUTS);
3615 p.append("on");
3616 p.append("root");
3617 p.append("ifmove");
3618 p.append("forceOn");
3619 p.setLonghelp(CUTS_LONGHELP
3620 " Reference: https://github.com/coin-or/Cgl/wiki/CglResidualCapacity");
3621
3622 parameters.push_back(p);
3623 }
3624 #endif
3625 #ifdef COIN_HAS_CLP
3626 {
3627 CbcOrClpParam p("restore!Model", "Restore model from binary file",
3628 CLP_PARAM_ACTION_RESTORE, 7, 1);
3629 p.setLonghelp(
3630 "This reads data save by saveModel from the given file. It will use the default\
3631 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3632 is initialized to 'default.prob'.");
3633
3634 parameters.push_back(p);
3635 }
3636 {
3637 CbcOrClpParam p("reverse", "Reverses sign of objective",
3638 CLP_PARAM_ACTION_REVERSE, 7, 0);
3639 p.setLonghelp(
3640 "Useful for testing if maximization works correctly");
3641 parameters.push_back(p);
3642 }
3643 {
3644 CbcOrClpParam p("rhs!Scale", "Scale factor to apply to rhs and bounds",
3645 -COIN_DBL_MAX, COIN_DBL_MAX, CLP_PARAM_DBL_RHSSCALE, 0);
3646 p.setLonghelp(
3647 "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
3648 internally by this amount. It can also be set by autoscale. This should not be needed.");
3649 p.setDoubleValue(1.0);
3650 parameters.push_back(p);
3651 }
3652 #endif
3653 #ifdef COIN_HAS_CBC
3654 {
3655 CbcOrClpParam p("Rens", "Whether to try Relaxation Enforced Neighborhood Search",
3656 "off", CBC_PARAM_STR_RENS);
3657 p.append("on");
3658 p.append("both");
3659 p.append("before");
3660 p.append("200");
3661 p.append("1000");
3662 p.append("10000");
3663 p.append("dj");
3664 p.append("djbefore");
3665 p.append("usesolution");
3666 p.setLonghelp(HEURISTICS_LONGHELP
3667 " Value 'on' just does 50 nodes. 200, 1000, and 10000 does that many nodes.");
3668 parameters.push_back(p);
3669 }
3670 {
3671 CbcOrClpParam p("Rins", "Whether to try Relaxed Induced Neighborhood Search",
3672 "off", CBC_PARAM_STR_RINS);
3673 p.append("on");
3674 p.append("both");
3675 p.append("before");
3676 p.append("often");
3677 p.setLonghelp(HEURISTICS_LONGHELP);
3678 parameters.push_back(p);
3679 }
3680 {
3681 CbcOrClpParam p("round!ingHeuristic", "Whether to use simple (but effective) Rounding heuristic",
3682 "off", CBC_PARAM_STR_ROUNDING);
3683 p.append("on");
3684 p.append("both");
3685 p.append("before");
3686 p.setLonghelp(HEURISTICS_LONGHELP);
3687 parameters.push_back(p);
3688 }
3689 #endif
3690 {
3691 CbcOrClpParam p("saveM!odel", "Save model to binary file",
3692 CLP_PARAM_ACTION_SAVE, 7, 1);
3693 p.setLonghelp(
3694 "This will save the problem to the given file name for future use\
3695 by restoreModel. It will use the default\
3696 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3697 is initialized to 'default.prob'.");
3698 parameters.push_back(p);
3699 }
3700 {
3701 CbcOrClpParam p("saveS!olution", "saves solution to file",
3702 CLP_PARAM_ACTION_SAVESOL);
3703
3704 p.setLonghelp(
3705 "This will write a binary solution file to the given file name. It will use the default\
3706 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3707 is initialized to 'solution.file'. To read the file use fread(int) twice to pick up number of rows \
3708 and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \
3709 activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \
3710 If name contains '_fix_read_' then does not write but reads and will fix all variables");
3711 parameters.push_back(p);
3712 }
3713 {
3714 CbcOrClpParam p("scal!ing", "Whether to scale problem",
3715 "off", CLP_PARAM_STR_SCALING);
3716 p.append("equi!librium");
3717 p.append("geo!metric");
3718 p.append("auto!matic");
3719 p.append("dynamic");
3720 p.append("rows!only");
3721 p.setLonghelp(
3722 "Scaling can help in solving problems which might otherwise fail because of lack of\
3723 accuracy. It can also reduce the number of iterations. It is not applied if the range\
3724 of elements is small. When the solution is evaluated in the unscaled problem, it is possible that small primal and/or\
3725 dual infeasibilities occur. "
3726 "Option 'equilibrium' uses the largest element for scaling. "
3727 "Option 'geometric' uses the squareroot of the product of largest and smallest element. "
3728 "Option 'auto' let CLP choose a method that gives the best ratio of the largest element to the smallest one.");
3729 p.setCurrentOption(3); // say auto
3730 parameters.push_back(p);
3731 }
3732 #ifndef COIN_HAS_CBC
3733 {
3734 CbcOrClpParam p("sec!onds", "Maximum seconds",
3735 -1.0, COIN_DBL_MAX, CLP_PARAM_DBL_TIMELIMIT);
3736
3737 p.setLonghelp("After this many seconds clp will act as if maximum iterations had been reached \
3738 (if value >=0).");
3739 parameters.push_back(p);
3740 }
3741 #else
3742 {
3743 CbcOrClpParam p("sec!onds", "maximum seconds",
3744 -1.0, COIN_DBL_MAX, CBC_PARAM_DBL_TIMELIMIT_BAB);
3745 p.setLonghelp(
3746 "After this many seconds coin solver will act as if maximum nodes had been reached.");
3747 parameters.push_back(p);
3748 }
3749 #endif
3750 {
3751 CbcOrClpParam p("sleep", "for debug",
3752 CLP_PARAM_ACTION_DUMMY, 7, 0);
3753
3754 p.setLonghelp(
3755 "If passed to solver fom ampl, then ampl will wait so that you can copy .nl file for debug.");
3756 parameters.push_back(p);
3757 }
3758 #ifdef COIN_HAS_CBC
3759 {
3760 CbcOrClpParam p("slow!cutpasses", "Maximum number of rounds for slower cut generators",
3761 -1, COIN_INT_MAX, CBC_PARAM_INT_MAX_SLOW_CUTS);
3762 p.setLonghelp(
3763 "Some cut generators are fairly slow - this limits the number of times they are tried.\
3764 The cut generators identified as 'may be slow' at present are Lift and project cuts and both versions of Reduce and Split cuts.");
3765 p.setIntValue(10);
3766 parameters.push_back(p);
3767 }
3768 #endif
3769 #ifdef COIN_HAS_CLP
3770 {
3771 CbcOrClpParam p("slp!Value", "Number of slp passes before primal",
3772 -50000, 50000, CLP_PARAM_INT_SLPVALUE, 1);
3773 p.setLonghelp(
3774 "If you are solving a quadratic problem using primal then it may be helpful to do some \
3775 sequential Lps to get a good approximate solution.");
3776 parameters.push_back(p);
3777 }
3778 #if CLP_MULTIPLE_FACTORIZATIONS > 0
3779 {
3780 CbcOrClpParam p("small!Factorization", "Threshold for using small factorization",
3781 -1, 10000, CBC_PARAM_INT_SMALLFACT, 1);
3782 p.setLonghelp(
3783 "If processed problem <= this use small factorization");
3784 p.setIntValue(-1);
3785 parameters.push_back(p);
3786 }
3787 #endif
3788 #endif
3789 {
3790 CbcOrClpParam p("solu!tion", "Prints solution to file",
3791 CLP_PARAM_ACTION_SOLUTION);
3792 p.setLonghelp(
3793 "This will write a primitive solution file to the given file name. It will use the default\
3794 directory given by 'directory'. A name of '$' will use the previous value for the name. This\
3795 is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask.");
3796 parameters.push_back(p);
3797 }
3798 #ifdef COIN_HAS_CLP
3799 #ifdef COIN_HAS_CBC
3800 {
3801 CbcOrClpParam p("solv!e", "Solve problem",
3802 CBC_PARAM_ACTION_BAB);
3803 p.setLonghelp(
3804 "If there are no integer variables then this just solves LP. If there are integer variables \
3805 this does branch and cut." );
3806 parameters.push_back( p );
3807 }
3808 {
3809 CbcOrClpParam p("sosO!ptions", "Whether to use SOS from AMPL", "off", CBC_PARAM_STR_SOS);
3810 p.append("on");
3811 p.setCurrentOption("on");
3812 p.setLonghelp(
3813 "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\
3814 be turned off - this does so." );
3815 parameters.push_back( p );
3816 }
3817 {
3818 CbcOrClpParam p("slog!Level", "Level of detail in (LP) Solver output", -1, 63, CLP_PARAM_INT_SOLVERLOGLEVEL);
3819 p.setLonghelp(
3820 "If 0 then there should be no output in normal circumstances. 1 is probably the best\
3821 value for most uses, while 2 and 3 give more information. This parameter is only used inside MIP - for Clp use 'log'");
3822 parameters.push_back(p);
3823 }
3824 {
3825 // Due to James Howey
3826 CbcOrClpParam p("sosP!rioritize", "How to deal with SOS priorities",
3827 "off", CBC_PARAM_STR_SOSPRIORITIZE);
3828 p.append("high");
3829 p.append("low");
3830 p.append("orderhigh");
3831 p.append("orderlow");
3832 p.setLonghelp(
3833 "This sets priorities for SOS. Values 'high' and 'low' just set a priority \
3834 relative to the for integer variables. Value 'orderhigh' gives first highest priority to the first SOS and integer variables \
3835 a low priority. Value 'orderlow' gives integer variables a high priority then SOS in order.");
3836 parameters.push_back(p);
3837 }
3838 #else
3839 // allow solve as synonym for possible dual
3840 {
3841 CbcOrClpParam p("solv!e", "Solve problem using dual simplex (probably)",
3842 CLP_PARAM_ACTION_EITHERSIMPLEX);
3843 p.setLonghelp(
3844 "Just so can use solve for clp as well as in cbc");
3845 parameters.push_back(p);
3846 }
3847 #endif
3848 #endif
3849 #ifdef COIN_HAS_CLP
3850 {
3851 CbcOrClpParam p("spars!eFactor", "Whether factorization treated as sparse",
3852 "on", CLP_PARAM_STR_SPARSEFACTOR, 7, 0);
3853 p.append("off");
3854 parameters.push_back(p);
3855 }
3856 {
3857 CbcOrClpParam p("special!Options", "Dubious options for Simplex - see ClpSimplex.hpp",
3858 0, COIN_INT_MAX, CLP_PARAM_INT_SPECIALOPTIONS, 0);
3859 parameters.push_back(p);
3860 }
3861 {
3862 CbcOrClpParam p("sprint!Crash", "Whether to try sprint crash",
3863 -1, COIN_INT_MAX, CLP_PARAM_INT_SPRINT);
3864 p.setLonghelp(
3865 "For long and thin problems this method may solve a series of small problems\
3866 created by taking a subset of the columns. The idea as 'Sprint' was introduced by J. Forrest after\
3867 an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
3868 CPLEX calls it 'sifting'. -1 lets CLP automatically choose the number of passes, 0 is off, n is number of passes");
3869 parameters.push_back(p);
3870 }
3871 {
3872 CbcOrClpParam p("stat!istics", "Print some statistics",
3873 CLP_PARAM_ACTION_STATISTICS);
3874 p.setLonghelp(
3875 "This command prints some statistics for the current model.\
3876 If log level >1 then more is printed.\
3877 These are for presolved model if presolve on (and unscaled).");
3878 parameters.push_back(p);
3879 }
3880 #endif
3881 {
3882 CbcOrClpParam p("stop", "Stops clp execution",
3883 CLP_PARAM_ACTION_EXIT);
3884 p.setLonghelp(
3885 "This stops the execution of Clp, end, exit, quit and stop are synonyms");
3886 parameters.push_back(p);
3887 }
3888 #ifdef COIN_HAS_CBC
3889 {
3890 CbcOrClpParam p("strat!egy", "Switches on groups of features",
3891 0, 2, CBC_PARAM_INT_STRATEGY);
3892 p.setLonghelp(
3893 "This turns on newer features. \
3894 Use 0 for easy problems, 1 is default, 2 is aggressive. \
3895 1 uses Gomory cuts with a tolerance of 0.01 at the root node, \
3896 does a possible restart after 100 nodes if many variables could be fixed, \
3897 activates a diving and RINS heuristic, and makes the feasibility pump \
3898 more aggressive."); // This does not apply to unit tests (where 'experiment' may have similar effects
3899 p.setIntValue(1);
3900 parameters.push_back(p);
3901 }
3902 #ifdef CBC_KEEP_DEPRECATED
3903 {
3904 CbcOrClpParam p("strengthen", "Create strengthened problem",
3905 CBC_PARAM_ACTION_STRENGTHEN, 3);
3906 p.setLonghelp(
3907 "This creates a new problem by applying the root node cuts. All tight constraints \
3908 will be in resulting problem");
3909 parameters.push_back(p);
3910 }
3911 #endif
3912 {
3913 CbcOrClpParam p("strong!Branching", "Number of variables to look at in strong branching",
3914 0, COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING);
3915 p.setIntValue(20);
3916 p.setLonghelp(
3917 "In order to decide which variable to branch on, the code will choose up to this number \
3918 of unsatisfied variables to try minimal up and down branches on. Then the most effective one is chosen. \
3919 If a variable is branched on many times then the previous average up and down costs may be used - \
3920 see also option trustPseudoCosts.");
3921 parameters.push_back(p);
3922 }
3923 #endif
3924 #ifdef COIN_HAS_CLP
3925 {
3926 CbcOrClpParam p("subs!titution", "How long a column to substitute for in presolve",
3927 0, 10000, CLP_PARAM_INT_SUBSTITUTION, 0);
3928 p.setLonghelp(
3929 "Normally Presolve gets rid of 'free' variables when there are no more than 3 \
3930 coefficients in a row. If you increase this, the number of rows may decrease but the number of \
3931 coefficients may increase.");
3932 parameters.push_back(p);
3933 }
3934 #endif
3935 #ifdef COIN_HAS_CBC
3936 {
3937 CbcOrClpParam p("testO!si", "Test OsiObject stuff",
3938 -1, COIN_INT_MAX, CBC_PARAM_INT_TESTOSI, 0);
3939 parameters.push_back(p);
3940 }
3941 #endif
3942 #ifdef CBC_THREAD
3943 {
3944 CbcOrClpParam p("thread!s", "Number of threads to try and use",
3945 -100, 100000, CBC_PARAM_INT_THREADS, 1);
3946 p.setIntValue(0);
3947 p.setLonghelp(
3948 "To use multiple threads, set threads to number wanted. It may be better \
3949 to use one or two more than number of cpus available. If 100+n then n threads and \
3950 search is repeatable (maybe be somewhat slower), \
3951 if 200+n use threads for root cuts, 400+n threads used in sub-trees.");
3952 parameters.push_back(p);
3953 }
3954 #endif
3955 #ifdef COIN_HAS_CBC
3956 {
3957 CbcOrClpParam p("tighten!Factor", "Tighten bounds using this times largest \
3958 activity at continuous solution",
3959 1.0e-3, COIN_DBL_MAX, CBC_PARAM_DBL_TIGHTENFACTOR, 0);
3960 p.setLonghelp(
3961 "This sleazy trick can help on some problems.");
3962 parameters.push_back(p);
3963 }
3964
3965 #endif
3966 #ifdef COIN_HAS_CLP
3967 {
3968 CbcOrClpParam p("tightLP", "Poor person's preSolve for now",
3969 CLP_PARAM_ACTION_TIGHTEN, 7, 0);
3970 parameters.push_back(p);
3971 }
3972 #endif
3973 {
3974 CbcOrClpParam p("timeM!ode", "Whether to use CPU or elapsed time",
3975 "cpu", CLP_PARAM_STR_TIME_MODE);
3976 p.append("elapsed");
3977 p.setLonghelp(
3978 "cpu uses CPU time for stopping, while elapsed uses elapsed time. \
3979 (On Windows, elapsed time is always used).");
3980 parameters.push_back(p);
3981 }
3982 #ifdef COIN_HAS_CBC
3983 {
3984 CbcOrClpParam p("trust!PseudoCosts", "Number of branches before we trust pseudocosts",
3985 -3, COIN_INT_MAX, CBC_PARAM_INT_NUMBERBEFORE);
3986 p.setLonghelp(
3987 "Using strong branching computes pseudo-costs. This parameter determines after how many branches for a variable we just \
3988 trust the pseudo costs and do not do any more strong branching.");
3989 p.setIntValue(10);
3990 parameters.push_back(p);
3991 }
3992 #endif
3993 #ifdef COIN_HAS_CBC
3994 {
3995 CbcOrClpParam p("tune!PreProcess", "Dubious tuning parameters for preprocessing",
3996 0, COIN_INT_MAX, CLP_PARAM_INT_PROCESSTUNE, 1);
3997 p.setLonghelp(
3998 "Format aabbcccc - \n If aa then this is number of major passes (i.e. with presolve) \n \
3999 If bb and bb>0 then this is number of minor passes (if unset or 0 then 10) \n \
4000 cccc is bit set \n 0 - 1 Heavy probing \n 1 - 2 Make variables integer if possible (if obj value)\n \
4001 2 - 4 As above but even if zero objective value\n \
4002 7 - 128 Try and create cliques\n 8 - 256 If all +1 try hard for dominated rows\n \
4003 10 - 1024 Use a larger feasibility tolerance in presolve\n \
4004 11 - 2048 Try probing before creating cliques\n \
4005 12 - 4096 Switch off duplicate column checking for integers \n \n \
4006 Now aa 99 has special meaning i.e. just one simple presolve.");
4007 parameters.push_back(p);
4008 }
4009 {
4010 CbcOrClpParam p("two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts",
4011 "off", CBC_PARAM_STR_TWOMIRCUTS);
4012 p.append("on");
4013 p.append("root");
4014 p.append("ifmove");
4015 p.append("forceOn");
4016 p.append("onglobal");
4017 p.append("forceandglobal");
4018 p.append("forceLongOn");
4019 p.setLonghelp(CUTS_LONGHELP
4020 " Reference: https://github.com/coin-or/Cgl/wiki/CglTwomir");
4021 parameters.push_back(p);
4022 }
4023 #endif
4024 {
4025 CbcOrClpParam p("unitTest", "Do unit test",
4026 CLP_PARAM_ACTION_UNITTEST, 3, 1);
4027 p.setLonghelp(
4028 "This exercises the unit test for clp");
4029 parameters.push_back(p);
4030 }
4031 {
4032 CbcOrClpParam p("userClp", "Hand coded Clp stuff",
4033 CLP_PARAM_ACTION_USERCLP, 0, 0);
4034 p.setLonghelp(
4035 "There are times e.g. when using AMPL interface when you may wish to do something unusual. \
4036 Look for USERCLP in main driver and modify sample code.");
4037 parameters.push_back(p);
4038 }
4039 #ifdef COIN_HAS_CBC
4040 {
4041 CbcOrClpParam p("userCbc", "Hand coded Cbc stuff",
4042 CBC_PARAM_ACTION_USERCBC, 0, 0);
4043 p.setLonghelp(
4044 "There are times e.g. when using AMPL interface when you may wish to do something unusual. \
4045 Look for USERCBC in main driver and modify sample code. \
4046 It is possible you can get same effect by using example driver4.cpp.");
4047 parameters.push_back(p);
4048 }
4049 #endif
4050 #ifdef COIN_AVX2
4051 {
4052 CbcOrClpParam p("vector!Mode", "Try and use vector instructions",
4053 0, 11, CLP_PARAM_INT_VECTOR_MODE);
4054 p.setLonghelp(
4055 "At present only for Intel architectures - but could be extended. \
4056 Uses avx2 or avx512 instructions. Uses different storage for matrix - can be \
4057 of benefit without instruction set on some problems. \
4058 Being lazy I have used 10 to switch on a pool matrix (11 may come later)");
4059 p.setIntValue(0);
4060 parameters.push_back(p);
4061 }
4062 #endif
4063 #ifdef COIN_HAS_CBC
4064 {
4065 CbcOrClpParam p("Vnd!VariableNeighborhoodSearch", "Whether to try Variable Neighborhood Search",
4066 "off", CBC_PARAM_STR_VND);
4067 p.append("on");
4068 p.append("both");
4069 p.append("before");
4070 p.append("intree");
4071 p.setLonghelp(HEURISTICS_LONGHELP);
4072 parameters.push_back(p);
4073 }
4074 #endif
4075 {
4076 CbcOrClpParam p("vector", "Whether to use vector? Form of matrix in simplex",
4077 "off", CLP_PARAM_STR_VECTOR, 7, 0);
4078 p.append("on");
4079 p.setLonghelp(
4080 "If this is on ClpPackedMatrix uses extra column copy in odd format.");
4081 parameters.push_back(p);
4082 }
4083 {
4084 CbcOrClpParam p("verbose", "Switches on longer help on single ?",
4085 0, 31, CLP_PARAM_INT_VERBOSE, 0);
4086 p.setLonghelp(
4087 "Set to 1 to get short help with ? list, 2 to get long help, 3 for both. (add 4 to just get ampl ones).");
4088 p.setIntValue(0);
4089 parameters.push_back(p);
4090 }
4091 #ifdef COIN_HAS_CBC
4092 {
4093 CbcOrClpParam p("vub!heuristic", "Type of VUB heuristic",
4094 -2, 20, CBC_PARAM_INT_VUBTRY, 0);
4095 p.setLonghelp(
4096 "This heuristic tries and fix some integer variables.");
4097 p.setIntValue(-1);
4098 parameters.push_back(p);
4099 }
4100 {
4101 CbcOrClpParam p("zero!HalfCuts", "Whether to use zero half cuts",
4102 "off", CBC_PARAM_STR_ZEROHALFCUTS);
4103 p.append("on");
4104 p.append("root");
4105 p.append("ifmove");
4106 p.append("forceOn");
4107 p.append("onglobal");
4108 p.setLonghelp(CUTS_LONGHELP
4109 " This implementation was written by Alberto Caprara.");
4110 parameters.push_back(p);
4111 }
4112 #endif
4113 {
4114 CbcOrClpParam p("zeroT!olerance", "Kill all coefficients \
4115 whose absolute value is less than this value",
4116 1.0e-100, 1.0e-5, CLP_PARAM_DBL_ZEROTOLERANCE);
4117 p.setLonghelp(
4118 "This applies to reading mps files (and also lp files \
4119 if KILL_ZERO_READLP defined)");
4120 p.setDoubleValue(1.0e-20);
4121 parameters.push_back(p);
4122 }
4123 }
4124 // Given a parameter type - returns its number in list
whichParam(const CbcOrClpParameterType & name,const std::vector<CbcOrClpParam> & parameters)4125 int whichParam(const CbcOrClpParameterType &name,
4126 const std::vector< CbcOrClpParam > ¶meters)
4127 {
4128 for (int i = 0; i < (int)parameters.size(); i++) {
4129 if (parameters[i].type() == name)
4130 return i;
4131 }
4132 return std::numeric_limits< int >::max(); // should not arrive here
4133 }
4134 #ifdef COIN_HAS_CLP
4135 /* Restore a solution from file.
4136 mode 0 normal, 1 swap rows and columns and primal and dual
4137 if 2 set then also change signs
4138 */
restoreSolution(ClpSimplex * lpSolver,std::string fileName,int mode)4139 void restoreSolution(ClpSimplex *lpSolver, std::string fileName, int mode)
4140 {
4141 FILE *fp = fopen(fileName.c_str(), "rb");
4142 if (fp) {
4143 int numberRows = lpSolver->numberRows();
4144 int numberColumns = lpSolver->numberColumns();
4145 int numberRowsFile;
4146 int numberColumnsFile;
4147 double objectiveValue;
4148 size_t nRead;
4149 nRead = fread(&numberRowsFile, sizeof(int), 1, fp);
4150 if (nRead != 1)
4151 throw("Error in fread");
4152 nRead = fread(&numberColumnsFile, sizeof(int), 1, fp);
4153 if (nRead != 1)
4154 throw("Error in fread");
4155 nRead = fread(&objectiveValue, sizeof(double), 1, fp);
4156 if (nRead != 1)
4157 throw("Error in fread");
4158 double *dualRowSolution = lpSolver->dualRowSolution();
4159 double *primalRowSolution = lpSolver->primalRowSolution();
4160 double *dualColumnSolution = lpSolver->dualColumnSolution();
4161 double *primalColumnSolution = lpSolver->primalColumnSolution();
4162 if (mode) {
4163 // swap
4164 int k = numberRows;
4165 numberRows = numberColumns;
4166 numberColumns = k;
4167 double *temp;
4168 temp = dualRowSolution;
4169 dualRowSolution = primalColumnSolution;
4170 primalColumnSolution = temp;
4171 temp = dualColumnSolution;
4172 dualColumnSolution = primalRowSolution;
4173 primalRowSolution = temp;
4174 }
4175 if (numberRows > numberRowsFile || numberColumns > numberColumnsFile) {
4176 std::cout << "Mismatch on rows and/or columns - giving up" << std::endl;
4177 } else {
4178 lpSolver->setObjectiveValue(objectiveValue);
4179 if (numberRows == numberRowsFile && numberColumns == numberColumnsFile) {
4180 nRead = fread(primalRowSolution, sizeof(double), numberRows, fp);
4181 if (nRead != static_cast< size_t >(numberRows))
4182 throw("Error in fread");
4183 nRead = fread(dualRowSolution, sizeof(double), numberRows, fp);
4184 if (nRead != static_cast< size_t >(numberRows))
4185 throw("Error in fread");
4186 nRead = fread(primalColumnSolution, sizeof(double), numberColumns, fp);
4187 if (nRead != static_cast< size_t >(numberColumns))
4188 throw("Error in fread");
4189 nRead = fread(dualColumnSolution, sizeof(double), numberColumns, fp);
4190 if (nRead != static_cast< size_t >(numberColumns))
4191 throw("Error in fread");
4192 } else {
4193 std::cout << "Mismatch on rows and/or columns - truncating" << std::endl;
4194 double *temp = new double[CoinMax(numberRowsFile, numberColumnsFile)];
4195 nRead = fread(temp, sizeof(double), numberRowsFile, fp);
4196 if (nRead != static_cast< size_t >(numberRowsFile))
4197 throw("Error in fread");
4198 CoinMemcpyN(temp, numberRows, primalRowSolution);
4199 nRead = fread(temp, sizeof(double), numberRowsFile, fp);
4200 if (nRead != static_cast< size_t >(numberRowsFile))
4201 throw("Error in fread");
4202 CoinMemcpyN(temp, numberRows, dualRowSolution);
4203 nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
4204 if (nRead != static_cast< size_t >(numberColumnsFile))
4205 throw("Error in fread");
4206 CoinMemcpyN(temp, numberColumns, primalColumnSolution);
4207 nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
4208 if (nRead != static_cast< size_t >(numberColumnsFile))
4209 throw("Error in fread");
4210 CoinMemcpyN(temp, numberColumns, dualColumnSolution);
4211 delete[] temp;
4212 }
4213 if (mode == 3) {
4214 int i;
4215 for (i = 0; i < numberRows; i++) {
4216 primalRowSolution[i] = -primalRowSolution[i];
4217 dualRowSolution[i] = -dualRowSolution[i];
4218 }
4219 for (i = 0; i < numberColumns; i++) {
4220 primalColumnSolution[i] = -primalColumnSolution[i];
4221 dualColumnSolution[i] = -dualColumnSolution[i];
4222 }
4223 }
4224 }
4225 fclose(fp);
4226 } else {
4227 std::cout << "Unable to open file " << fileName << std::endl;
4228 }
4229 }
4230 // Dump a solution to file
saveSolution(const ClpSimplex * lpSolver,std::string fileName)4231 void saveSolution(const ClpSimplex *lpSolver, std::string fileName)
4232 {
4233 if (strstr(fileName.c_str(), "_fix_read_")) {
4234 FILE *fp = fopen(fileName.c_str(), "rb");
4235 if (fp) {
4236 ClpSimplex *solver = const_cast< ClpSimplex * >(lpSolver);
4237 restoreSolution(solver, fileName, 0);
4238 // fix all
4239 int logLevel = solver->logLevel();
4240 int iColumn;
4241 int numberColumns = solver->numberColumns();
4242 double *primalColumnSolution = solver->primalColumnSolution();
4243 double *columnLower = solver->columnLower();
4244 double *columnUpper = solver->columnUpper();
4245 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4246 double value = primalColumnSolution[iColumn];
4247 if (value > columnUpper[iColumn]) {
4248 if (value > columnUpper[iColumn] + 1.0e-6 && logLevel > 1)
4249 printf("%d value of %g - bounds %g %g\n",
4250 iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
4251 value = columnUpper[iColumn];
4252 } else if (value < columnLower[iColumn]) {
4253 if (value < columnLower[iColumn] - 1.0e-6 && logLevel > 1)
4254 printf("%d value of %g - bounds %g %g\n",
4255 iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
4256 value = columnLower[iColumn];
4257 }
4258 columnLower[iColumn] = value;
4259 columnUpper[iColumn] = value;
4260 }
4261 return;
4262 }
4263 }
4264 FILE *fp = fopen(fileName.c_str(), "wb");
4265 if (fp) {
4266 int numberRows = lpSolver->numberRows();
4267 int numberColumns = lpSolver->numberColumns();
4268 double objectiveValue = lpSolver->objectiveValue();
4269 size_t nWrite;
4270 nWrite = fwrite(&numberRows, sizeof(int), 1, fp);
4271 if (nWrite != 1)
4272 throw("Error in fwrite");
4273 nWrite = fwrite(&numberColumns, sizeof(int), 1, fp);
4274 if (nWrite != 1)
4275 throw("Error in fwrite");
4276 nWrite = fwrite(&objectiveValue, sizeof(double), 1, fp);
4277 if (nWrite != 1)
4278 throw("Error in fwrite");
4279 double *dualRowSolution = lpSolver->dualRowSolution();
4280 double *primalRowSolution = lpSolver->primalRowSolution();
4281 nWrite = fwrite(primalRowSolution, sizeof(double), numberRows, fp);
4282 if (nWrite != static_cast< size_t >(numberRows))
4283 throw("Error in fwrite");
4284 nWrite = fwrite(dualRowSolution, sizeof(double), numberRows, fp);
4285 if (nWrite != static_cast< size_t >(numberRows))
4286 throw("Error in fwrite");
4287 double *dualColumnSolution = lpSolver->dualColumnSolution();
4288 double *primalColumnSolution = lpSolver->primalColumnSolution();
4289 nWrite = fwrite(primalColumnSolution, sizeof(double), numberColumns, fp);
4290 if (nWrite != static_cast< size_t >(numberColumns))
4291 throw("Error in fwrite");
4292 nWrite = fwrite(dualColumnSolution, sizeof(double), numberColumns, fp);
4293 if (nWrite != static_cast< size_t >(numberColumns))
4294 throw("Error in fwrite");
4295 fclose(fp);
4296 } else {
4297 std::cout << "Unable to open file " << fileName << std::endl;
4298 }
4299 }
4300 #endif
4301
4302 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
4303 */
4304