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 > &parameters)
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 > &parameters)
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