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

Last change on this file since 2470 was 2469, checked in by stefan, 6 months ago

more polishing of option descriptions

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