source: trunk/Clp/src/CbcOrClpParam.cpp @ 2473

Last change on this file since 2473 was 2473, checked in by stefan, 2 months ago

revert r2472 and extend temp array in CoinReadPrintit?

  • and add assert
  • fixes #230
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 149.8 KB
Line 
1/* $Id: CbcOrClpParam.cpp 2473 2019-05-23 10:30:13Z 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
32static char coin_prompt[] = "Coin:";
33#else
34static 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
50static bool doPrinting = true;
51static std::string afterEquals = "";
52static 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
58int coinFlushBufferFlag = 0;
59#endif
60void setCbcOrClpPrinting(bool yesNo)
61{
62  doPrinting = yesNo;
63}
64//#############################################################################
65// Constructors / Destructor / Assignment
66//#############################################################################
67
68//-------------------------------------------------------------------
69// Default Constructor
70//-------------------------------------------------------------------
71CbcOrClpParam::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
95CbcOrClpParam::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}
119CbcOrClpParam::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
144CbcOrClpParam::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
171CbcOrClpParam::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//-------------------------------------------------------------------
199CbcOrClpParam::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//-------------------------------------------------------------------
226CbcOrClpParam::~CbcOrClpParam()
227{
228}
229
230//----------------------------------------------------------------
231// Assignment operator
232//-------------------------------------------------------------------
233CbcOrClpParam &
234CbcOrClpParam::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}
260void 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
274void 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*/
284int 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*/
293int 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
310int 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)
318void CbcOrClpParam::append(std::string keyWord)
319{
320  definedKeyWords_.push_back(keyWord);
321}
322
323int 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
345std::string
346CbcOrClpParam::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)
355int 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
424void 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
447void 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}
457void 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
483void 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
499int 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
508const char *
509CbcOrClpParam::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
539int 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
548const char *
549CbcOrClpParam::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}
597double
598CbcOrClpParam::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}
639int 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
648const char *
649CbcOrClpParam::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}
711int 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
756int 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
766double
767CbcOrClpParam::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}
783int 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
792const char *
793CbcOrClpParam::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}
815int 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}
828int 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
837const char *
838CbcOrClpParam::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}
893double
894CbcOrClpParam::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}
929int 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
938const char *
939CbcOrClpParam::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}
1013int 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
1064void 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
1075void 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
1089const char *
1090CbcOrClpParam::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
1120const char *
1121CbcOrClpParam::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}
1148void 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}
1156const char *
1157CbcOrClpParam::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}
1172void 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}
1180const char *
1181CbcOrClpParam::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}
1196void CbcOrClpParam::setStringValue(std::string value)
1197{
1198  stringValue_ = value;
1199}
1200static char line[1000];
1201static char *where = NULL;
1202extern int CbcOrClpRead_mode;
1203int CbcOrClpEnvironmentIndex = -1;
1204// Alternative to environment
1205char *alternativeEnvironment = NULL;
1206static 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}
1254extern FILE *CbcOrClpReadCommand;
1255// Simple read stuff
1256std::string
1257CoinReadNextField()
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
1319std::string
1320CoinReadGetCommand(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}
1377std::string
1378CoinReadGetString(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
1408int 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}
1447double
1448CoinReadGetDoubleField(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*/
1491void 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?) \
1524and 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 \
1535are 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 \
1541best 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 \
1546value, 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 \
1556basis 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 \
1586corrector algorithm.  You may want to link in an alternative \
1587ordering and factorization.  It will also solve models \
1588with 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.  \
1628First just try with default settings and look carefully at the log file.  Did cuts help?  Did they take too long?  \
1629Look at output to see which cuts were effective and then do some tuning.  You will see that the \
1630options for cuts are off, on, root and ifmove, forceon.  Off is \
1631obvious. " CUTS_LONGHELP " For probing, forceonbut just does fixing probing in tree - not strengthening etc.  \
1632If pre-processing reduced the size of the \
1633problem or strengthened many coefficients then it is probably wise to leave it on.  Switch off heuristics \
1634which did not provide solutions.  The other major area to look at is the search.  Hopefully good solutions \
1635were obtained fairly early in the search so the important point is to select the best variable to branch on.  \
1636See whether strong branching did a good job - or did it just take a lot of iterations.  Adjust the strongBranching \
1637and trustPseudoCosts parameters.  If cuts did a good job, then you may wish to \
1638have 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.  \
1699The native ordering and factorization is not state of the art, although acceptable.  \
1700You may want to link in one from another source.  See Makefile.locations for some \
1701possibilities.");
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 \
1731using variables which have appeared in one or more solutions. \
1732It 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 \
1745fixing variables which have the same value in two or more solutions. \
1746It 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 \
1789then you can!  If this is on, then Cbc will get to the root node and then \
1790hand over to Cplex.  If heuristics find a solution this can be significantly \
1791quicker.  You will probably want to switch off Cbc's cuts as Cplex thinks \
1792they are genuine constraints.  It is also probable that you want to switch \
1793off preprocessing, although for difficult problems it is worth trying \
1794both.");
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 \
1803you to generate user_driver.cpp which approximates the code.  \
18040 gives simplest driver, 1 generates saves and restores, 2 \
1805generates saves and restores even for variables at default value. \
18064 bit in cbc generates size dependent code rather than computed values.  \
1807This is now deprecated as you can call stand-alone solver - see \
1808Cbc/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 \
1849of the solver for quadratic programs it may be a good idea to switch off crossover for this case (and maybe \
1850presolve 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. \
1878Any value >0 says that all cuts <= this length can be generated both at \
1879root node and in tree. 0 says to use some dynamic lengths.  If value >=10,000,000 \
1880then the length in tree is value%10000000 - so 10000100 means unlimited length \
1881at 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.  \
1891CBC also updates this value whenever it obtains a solution to the value of \
1892the 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\
1916If set to create it will create a file called debug.file  after search.\n\n\
1917The idea is that if you suspect a bad cut generator \
1918you can do a good run with debug set to 'create' and then switch on the cuts you suspect and \
1919re-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 \
1929Dantzig 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 \
1953means 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 \
1955this 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.  \
1956The 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\
1996You 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 \
2066and 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. \
2082One 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. \
2146Only those heuristics with 'both' or 'before' set will run.  \
2147Doing 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 \
2154gap 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.\
2199The 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 \
2206no 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 \
2211to 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 \
2212correct 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 \
2261e.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. \
22770 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. \
22880 is normal strong branching. \
22891, 2, 4, and 6 does strong branching on all fractional variables if \
2290at the root node (1), \
2291at depth less than modifier (2), \
2292objective equals best possible (4), or \
2293at depth less than modifier and objective equals best possible (6). \
229411, 12, 14, and 16 are like 1, 2, 4, and 6, respecitively, but do strong branching on all integer (incl. non-fractional) variables. \
2295Values >= 100 are used to specify a depth limit (value/100), otherwise 5 is used. \
2296If 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'.  \
2309It 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!! \
2338The bottom digit is a strategy when to used shadow price stuff e.g. 3 \
2339means use until a solution is found.  The next two digits say what sort \
2340of 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 \
2366other 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 \
2369other choices are a dense one, OSL's, or one designed for small problems. \
2370However if at Aboca then the default is CoinAbcFactorization and other choices are \
2371a 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 \
2391and uses a sequence of LPs to try and get an integer feasible solution. \
2392Some 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 \
2398reduced 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 \
2402before 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. \
2424If 0 then just tries to set as best solution \
2425If >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 \
2434about are fixed and if the preprocessed model is smaller than this fraction of the original problem, \
2435a 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, \
2484they are now more fashionable as LP solvers are more robust and they interact well \
2485with other cuts.  They will almost always give cuts (although in this executable \
2486they are limited as to number of variables in cut).  However the cuts may be dense \
2487so 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 \
2512directory given by 'directory'.  A name of '$' will use the previous value for the \
2513name.  This is initialized to 'stdout' (this defaults to ordinary solution if stdout). \
2514If 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 \
2521setting 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 \
2540you 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. \
2551Other values are for the feasibility pump - \
25522 says do exact number of passes given, \
25534 only applies if an initial cutoff has been given and says relax after 50 passes, \
2554while 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'.  \
2584If '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 \
2590much 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 \
2596all objective coefficients are multiples of 0.01 and only integer variables have entries in \
2597the 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 \
2603to 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 \
2607expected 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 \
2620no 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.  \
2634This 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' \
2679by Matteo Fischetti & Domenico Salvagnin.  This simplification \
2680just uses original constraints while modifying objective using other cuts. \
2681So you don't use messy constraints generated by Gomory etc. \
2682A variant is to allow non messy cuts e.g. clique cuts. \
2683So 'only' does this while 'clean' also allows integral valued cuts.  \
2684'End' is recommended and waits until other cuts have finished before it \
2685does a few passes. \
2686The 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\
2754You 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 \
2760refactorizations",
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 \
2769stopping",
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 \
2784but 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.  \
2799This 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\
2808This should only be necessary if you have previously set maximization \
2809You 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\
2851but 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("\
2866The MIPStart allows one to enter an initial integer feasible solution \
2867to CBC. Values of the main decision variables which are active (have \
2868non-zero values) in this solution are specified in a text  file. The \
2869text file format used is the same of the solutions saved by CBC, but \
2870not all fields are required to be filled. First line may contain the \
2871solution status and will be ignored, remaining lines contain column \
2872indexes, names and values as in this example:\n\
2873\n\
2874Stopped 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\
2881Column indexes are also ignored since pre-processing can change them. \
2882There is no need to include values for continuous or integer auxiliary \
2883variables, since they can be computed based on main decision variables. \
2884Starting CBC with an integer feasible solution can dramatically improve \
2885its performance: several MIP heuristics (e.g. RINS) rely on having at \
2886least one feasible solution available and can start immediately if the \
2887user provides one. Feasibility Pump (FP) is a heuristic which tries to \
2888overcome the problem of taking too long to find feasible solution (or \
2889not finding at all), but it not always succeeds. If you provide one \
2890starting solution you will probably save some time by disabling FP. \
2891\n\n\
2892Knowledge specific to your problem can be considered to write an \
2893external module to quickly produce an initial feasible solution - some \
2894alternatives are the implementation of simple greedy heuristics or the \
2895solution (by CBC for example) of a simpler model created just to find \
2896a feasible solution. \
2897\n\n\
2898Silly options added.  If filename ends .low then integers not mentioned \
2899are set low - also .high, .lowcheap, .highcheap, .lowexpensive, .highexpensive \
2900where .lowexpensive sets costed ones to make expensive others low. Also if \
2901filename starts empty. then no file is read at all - just actions done. \
2902\n\n\
2903Question and suggestions regarding MIPStart can be directed to\n\
2904haroldo.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. \
2940The solvers do not interact with each other.  However if extra passes are specified \
2941then cuts are collected and used in later passes - so there is interaction there. \
2942Some parts of this implementation have their origin in idea of \
2943Andrea 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.\
2965The 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.\
2973The 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.\
2982The 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.\
2990The 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 \
2998works best.  I know this is cheating but it also stresses the code better by doing a \
2999mixture of stuff.  The best algorithm was chosen on a Linux ThinkPad using native cholesky \
3000with 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 \
3010specialized 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 \
3039be selected first (the up-down choice will carry on after a first solution has been bound). \
3040The 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. \
3048This 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. \
3073Value '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...\
3083Setting 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 \
3102values, 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 \
3111and 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. \
3114File is in modified csv format - a line ROWS will be followed by rows data \
3115while a line COLUMNS will be followed by column data.  The last line \
3116should be ENDATA. The ROWS line must exist and is in the format \
3117ROWS, inital theta, final theta, interval theta, n where n is 0 to get \
3118CLPI0062 message at interval or at each change of theta \
3119and 1 to get CLPI0063 message at each iteration.  If interval theta is 0.0 \
3120or >= final theta then no interval reporting.  n may be missed out when it is \
3121taken as 0.  If there is Row data then \
3122there is a headings line with allowed headings - name, number, \
3123lower(rhs change), upper(rhs change), rhs(change).  Either the lower and upper \
3124fields should be given or the rhs field. \
3125The optional COLUMNS line is followed by a headings line with allowed \
3126headings - name, number, objective(change), lower(change), upper(change). \
3127 Exactly one of name and number must be given for either section and \
3128missing 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 \
3140stop if the drop in the objective function value is small) if the problem has less than 5000 columns, and 20 passes otherwise. \
3141A 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.  \
3251Option 'on' will normally do 5 passes, while using 'more' will do 10.  If the problem is very large one can \
3252let 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 \
3272it 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 \
3287infeasible 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 \
3328no 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 \
3338costs 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 \
3355select incoming variables to try and avoid degenerate moves. \
3356Variables not in the promising set have their infeasibility weight multiplied by psi, \
3357so 0.01 would mean that if there were any promising variables, then they would always be chosen, \
3358while 1.0 effectively switches the algorithm off. \
3359There are two ways of switching this feature on.  One way is to set psi to a positive value and then \
3360the Positive Edge criterion will be used for both primal and dual simplex.  The other way is to select PEsteepest \
3361in dualpivot choice (for example), then the absolute value of psi is used. \
3362Code donated by Jeremy Omer.  See \
3363Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR's CLP; \
3364Omer, 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\
3386integer - nonzero integer column variables\n\
3387special - in format suitable for OsiRowCutDebugger\n\
3388rows - nonzero column variables and row activities\n\
3389all - all column variables and row activities.\n\
3390\nFor non-integer problems 'integer' and 'special' act like 'normal'.  \
3391Also 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. \
3402This 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. \
3414File 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). \
3453The idea is to define a sub-MIP without additional constraints but with a modified objective function intended to attract the search \
3454in the proximity of the incumbent. \
3455The approach works well for 0-1 MIPs whose solution landscape is not too irregular (meaning the there is reasonable probability of \
3456finding an improved solution by flipping a small number of binary variables), in particular when it is applied to the first heuristic solutions \
3457found 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 \
3476when 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. \
3491If accumulate is on then after a major pass, variables which have not moved \
3492are 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 \
3542best 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 \
3547of the objective value at the root node then the search will terminate.  See 'allowableGap' for a \
3548way 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). \
3606This version is by Giacomo Nannicini based on Francois Margot's version. \
3607Standard setting only uses rows in tableau <= 256, long uses all. \
3608These cuts may be expensive to generate. \
3609See 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 \
3708and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \
3709activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \
3710If 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 \
3775sequential 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 \
3805this 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. \
3894Use 0 for easy problems, 1 is default, 2 is aggressive. \
38951 uses Gomory cuts with a tolerance of 0.01 at the root node, \
3896does a possible restart after 100 nodes if many variables could be fixed, \
3897activates a diving and RINS heuristic, and makes the feasibility pump \
3898more 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 \
3908will 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 \
3918of unsatisfied variables to try minimal up and down branches on.  Then the most effective one is chosen. \
3919If a variable is branched on many times then the previous average up and down costs may be used - \
3920see 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 \
3949to use one or two more than number of cpus available.  If 100+n then n threads and \
3950search is repeatable (maybe be somewhat slower), \
3951if 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 \
3958activity 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 \
3988trust 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 \
3999If bb and bb>0 then this is number of minor passes (if unset or 0 then 10) \n \
4000cccc is bit set \n 0 - 1 Heavy probing \n 1 - 2 Make variables integer if possible (if obj value)\n \
40012 - 4 As above but even if zero objective value\n \
40027 - 128 Try and create cliques\n 8 - 256 If all +1 try hard for dominated rows\n \
400310 - 1024 Use a larger feasibility tolerance in presolve\n \
400411 - 2048 Try probing before creating cliques\n \
400512 - 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.  \
4036Look 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.  \
4045Look for USERCBC in main driver and modify sample code. \
4046It 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.  \
4056Uses avx2 or avx512 instructions. Uses different storage for matrix - can be \
4057of benefit without instruction set on some problems.  \
4058Being 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 \
4115whose 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 \
4119if 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
4125int 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*/
4139void 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
4231void 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*/
Note: See TracBrowser for help on using the repository browser.