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

Last change on this file since 2466 was 2466, checked in by stefan, 8 weeks ago

revise some option help texts

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 148.9 KB
Line 
1/* $Id: CbcOrClpParam.cpp 2466 2019-05-02 05:39:00Z 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, 1.0e20, 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, 1.0e100, CBC_PARAM_DBL_ARTIFICIALCOST, 1);
1563    p.setDoubleValue(0.0);
1564    p.setLonghelp(
1565      "0.0 off - otherwise variables with costs >= this are treated as artificials 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 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 quadratic it may be a good idea to switch off crossover for quadratic (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, 999999, 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      -1.0e100, 1.0e100, 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", "Whether to use 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 BAB",
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      -1.0e100, 1.0e100, 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      -1.0e100, 1.0e100, 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      -1.0e100, 1.0e100, 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.  Last digit is ignored \
2065and used for extra options - \
2066         \n\t1-3 allow fixing of satisfied integers (but not at bound) \
2067         \n\t1 switch off above for that dive if goes infeasible \
2068         \n\t2 switch off above permanently if 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, 1.0e12, 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 \n\
2287\n\t0 - normal\n\
2288\n\twhen to do all fractional\n\
2289\n\t1 - root node\n\
2290\n\t2 - depth less than modifier\n\
2291\n\t4 - if objective == best possible\n\
2292\n\t6 - as 2+4\n\
2293\n\twhen to do all including satisfied\n\
2294\n\t10 - root node etc.\n\
2295\n\tIf >=100 then do when depth <= strategy/100 (otherwise 5)");
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      -1.0e20, 1.0e20, 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 feasibility pump, variables which have not moved \
2433about are fixed and if the preprocessed model is small enough a few nodes \
2434of branch and bound are done on reduced problem.  Small problem has to be \
2435less than this fraction of original.");
2436    parameters.push_back(p);
2437  }
2438#endif
2439  {
2440    CbcOrClpParam p("gamma!(Delta)", "Whether to regularize barrier",
2441      "off", CLP_PARAM_STR_GAMMA, 7, 1);
2442    p.append("on");
2443    p.append("gamma");
2444    p.append("delta");
2445    p.append("onstrong");
2446    p.append("gammastrong");
2447    p.append("deltastrong");
2448    parameters.push_back(p);
2449  }
2450#endif
2451#ifdef COIN_HAS_CBC
2452  {
2453    CbcOrClpParam p("GMI!Cuts", "Whether to use alternative Gomory cuts",
2454      "off", CBC_PARAM_STR_GMICUTS);
2455
2456    p.append("on");
2457    p.append("root");
2458    p.append("ifmove");
2459    p.append("forceOn");
2460    p.append("endonly");
2461    p.append("long");
2462    p.append("longroot");
2463    p.append("longifmove");
2464    p.append("forceLongOn");
2465    p.append("longendonly");
2466    p.setLonghelp(CUTS_LONGHELP
2467      " This version is by Giacomo Nannicini and may be more robust than gomoryCuts.");
2468    parameters.push_back(p);
2469  }
2470  {
2471    CbcOrClpParam p("gomory!Cuts", "Whether to use Gomory cuts",
2472      "off", CBC_PARAM_STR_GOMORYCUTS);
2473
2474    p.append("on");
2475    p.append("root");
2476    p.append("ifmove");
2477    p.append("forceOn");
2478    p.append("onglobal");
2479    p.append("forceandglobal");
2480    p.append("forceLongOn");
2481    p.append("long");
2482    p.setLonghelp(
2483      "The original cuts - beware of imitations!  Having gone out of favor, \
2484they are now more fashionable as LP solvers are more robust and they interact well \
2485with other cuts.  They will almost always give cuts (although in this executable \
2486they are limited as to number of variables in cut).  However the cuts may be dense \
2487so it is worth experimenting (Long allows any length). "
2488    CUTS_LONGHELP
2489    " Reference: https://github.com/coin-or/Cgl/wiki/CglGomory");
2490    parameters.push_back(p);
2491  }
2492  {
2493    CbcOrClpParam p("greedy!Heuristic", "Whether to use a greedy heuristic",
2494      "off", CBC_PARAM_STR_GREEDY);
2495
2496    p.append("on");
2497    p.append("both");
2498    p.append("before");
2499    //p.append("root");
2500    p.setLonghelp(
2501      "This heuristic tries to obtain a feasible solution by just fixing a percentage of variables and then try a small branch and cut run. "
2502      HEURISTICS_LONGHELP);
2503    parameters.push_back(p);
2504  }
2505#endif
2506  {
2507    CbcOrClpParam p("gsolu!tion", "Puts glpk solution to file",
2508      CLP_PARAM_ACTION_GMPL_SOLUTION);
2509
2510    p.setLonghelp(
2511      "Will write a glpk solution file to the given file name.  It will use the default \
2512directory given by 'directory'.  A name of '$' will use the previous value for the \
2513name.  This is initialized to 'stdout' (this defaults to ordinary solution if stdout). \
2514If problem created from gmpl model - will do any reports.");
2515    parameters.push_back(p);
2516  }
2517  {
2518    CbcOrClpParam p("guess", "Guesses at good parameters", CLP_PARAM_ACTION_GUESS, 7);
2519    p.setLonghelp(
2520    "This looks at model statistics and does an initial solve \
2521setting some parameters which may help you to think of possibilities.");
2522    parameters.push_back(p);
2523  }
2524#ifdef COIN_HAS_CBC
2525  {
2526    CbcOrClpParam p("heur!isticsOnOff", "Switches most primal heuristics on or off",
2527      "off", CBC_PARAM_STR_HEURISTICSTRATEGY);
2528    p.append("on");
2529    p.setLonghelp(
2530      "This option can be used to switch on or off all heuristics that search for feasible solutions,\
2531      except for the local tree search, as it dramatically alters the search.\
2532      Then individual heuristics can be turned off or on.");
2533    parameters.push_back(p);
2534  }
2535  {
2536    CbcOrClpParam p("help", "Print out version, non-standard options and some help",
2537      CLP_PARAM_ACTION_HELP, 3);
2538    p.setLonghelp(
2539      "This prints out some help to get user started.  If you have printed this then \
2540you should be past that stage:-)");
2541    parameters.push_back(p);
2542  }
2543#endif
2544#ifdef COIN_HAS_CBC
2545  {
2546    CbcOrClpParam p("hOp!tions", "Heuristic options",
2547      -9999999, 9999999, CBC_PARAM_INT_HOPTIONS, 1);
2548    p.setIntValue(0);
2549    p.setLonghelp(
2550      "1 says stop heuristic immediately allowable gap reached. \
2551Others are for feasibility pump - \
25522 says do exact number of passes given, \
25534 only applies if initial cutoff given and says relax after 50 passes, \
2554while 8 will adapt cutoff rhs after first solution if it looks as if code is stalling.");
2555    parameters.push_back(p);
2556  }
2557  {
2558    CbcOrClpParam p("hot!StartMaxIts", "Maximum iterations on hot start",
2559      0, COIN_INT_MAX, CBC_PARAM_INT_MAXHOTITS);
2560    parameters.push_back(p);
2561  }
2562#endif
2563#ifdef COIN_HAS_CLP
2564  {
2565    CbcOrClpParam p("idiot!Crash", "Whether to try idiot crash",
2566      -1, 99999999, CLP_PARAM_INT_IDIOT);
2567
2568    p.setLonghelp(
2569      "This is a type of 'crash' which works well on some homogeneous problems.\
2570 It works best on problems with unit elements and rhs but will do something to any \
2571 model.  It should only be used before the primal simplex algorithm.  It can be set to -1 when the code \
2572 decides for itself whether to use it, 0 to switch off, or n > 0 to do n passes.");
2573    parameters.push_back(p);
2574  }
2575#endif
2576  {
2577    CbcOrClpParam p("import", "Import model from mps file",
2578      CLP_PARAM_ACTION_IMPORT, 3);
2579    p.setLonghelp(
2580      "This will read an MPS format file from the given file name.  It will use the default\
2581 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
2582 is initialized to '', i.e. it must be set.  If you have libgz then it can read compressed\
2583 files 'xxxxxxxx.gz' or 'xxxxxxxx.bz2'.  \
2584If 'keepnames' is off, then names are dropped -> Rnnnnnnn and Cnnnnnnn.");
2585    parameters.push_back(p);
2586  }
2587#ifdef COIN_HAS_CBC
2588  {
2589    CbcOrClpParam p("inc!rement", "A valid solution must be at least this \
2590much better than last integer solution",
2591      -1.0e20, 1.0e20, CBC_PARAM_DBL_INCREMENT);
2592
2593    p.setLonghelp(
2594      "Whenever a solution is found the bound on the objective value for new solutions is set to the\
2595      objective function of the found solution (in a minimization sense) plus this.  If it is not set then CBC will try and work one out, e.g. if \
2596all objective coefficients are multiples of 0.01 and only integer variables have entries in \
2597the objective function, then the increment can be set to 0.01.  Be careful if setting this to a negative value!");
2598
2599    parameters.push_back(p);
2600  }
2601  {
2602    CbcOrClpParam p("inf!easibilityWeight", "Each integer infeasibility is expected \
2603to cost this much",
2604      0.0, 1.0e20, CBC_PARAM_DBL_INFEASIBILITYWEIGHT, 1);
2605    p.setLonghelp(
2606      "A primitive way of deciding which node to explore next.  Satisfying each integer infeasibility is \
2607expected to cost this much.");
2608    parameters.push_back(p);
2609  }
2610  {
2611    CbcOrClpParam p("initialS!olve", "Solve to continuous",
2612      CLP_PARAM_ACTION_SOLVECONTINUOUS);
2613
2614    p.setLonghelp(
2615      "This just solves the problem to continuous - without adding any cuts");
2616    parameters.push_back(p);
2617  }
2618  {
2619    CbcOrClpParam p("integerT!olerance", "For a feasible solution \
2620no integer variable may be more than this away from an integer value",
2621      1.0e-20, 0.5, CBC_PARAM_DBL_INTEGERTOLERANCE);
2622    p.setLonghelp(
2623      "Beware of setting this smaller than the primal feasibility tolerance.");
2624    parameters.push_back(p);
2625  }
2626#endif
2627#ifdef COIN_HAS_CLP
2628  {
2629    CbcOrClpParam p("keepN!ames", "Whether to keep names from import",
2630      "on", CLP_PARAM_STR_KEEPNAMES);
2631    p.append("off");
2632    p.setLonghelp(
2633      "It saves space to get rid of names so if you need to you can set this to off.  \
2634This needs to be set before the import of model - so -keepnames off -import xxxxx.mps.");
2635    parameters.push_back(p);
2636  }
2637  {
2638    CbcOrClpParam p("KKT", "Whether to use KKT factorization",
2639      "off", CLP_PARAM_STR_KKT, 7, 1);
2640    p.append("on");
2641    parameters.push_back(p);
2642  }
2643#endif
2644#ifdef COIN_HAS_CBC
2645  {
2646    CbcOrClpParam p("knapsack!Cuts", "Whether to use Knapsack cuts",
2647      "off", CBC_PARAM_STR_KNAPSACKCUTS);
2648
2649    p.append("on");
2650    p.append("root");
2651    p.append("ifmove");
2652    p.append("forceOn");
2653    p.append("onglobal");
2654    p.append("forceandglobal");
2655    p.setLonghelp(CUTS_LONGHELP
2656      " Reference: https://github.com/coin-or/Cgl/wiki/CglKnapsackCover");
2657    parameters.push_back(p);
2658  }
2659  {
2660    CbcOrClpParam p("lagomory!Cuts", "Whether to use Lagrangean Gomory cuts",
2661      "off", CBC_PARAM_STR_LAGOMORYCUTS);
2662    p.append("endonlyroot");
2663    p.append("endcleanroot");
2664    p.append("root");
2665    p.append("endonly");
2666    p.append("endclean");
2667    p.append("endboth");
2668    p.append("onlyaswell");
2669    p.append("cleanaswell");
2670    p.append("bothaswell");
2671    p.append("onlyinstead");
2672    p.append("cleaninstead");
2673    p.append("bothinstead");
2674    p.append("onlyaswellroot");
2675    p.append("cleanaswellroot");
2676    p.append("bothaswellroot");
2677    p.setLonghelp(
2678      "This is a gross simplification of 'A Relax-and-Cut Framework for Gomory's Mixed-Integer Cuts' \
2679by Matteo Fischetti & Domenico Salvagnin.  This simplification \
2680just uses original constraints while modifying objective using other cuts. \
2681So you don't use messy constraints generated by Gomory etc. \
2682A variant is to allow non messy cuts e.g. clique cuts. \
2683So 'only' does this while clean also allows integral valued cuts.  \
2684'End' is recommended which waits until other cuts have finished and then \
2685does a few passes. \
2686The length options for gomory cuts are used.");
2687    parameters.push_back(p);
2688  }
2689  {
2690    CbcOrClpParam p("latwomir!Cuts", "Whether to use Lagrangean TwoMir cuts",
2691      "off", CBC_PARAM_STR_LATWOMIRCUTS);
2692
2693    p.append("endonlyroot");
2694    p.append("endcleanroot");
2695    p.append("endbothroot");
2696    p.append("endonly");
2697    p.append("endclean");
2698    p.append("endboth");
2699    p.append("onlyaswell");
2700    p.append("cleanaswell");
2701    p.append("bothaswell");
2702    p.append("onlyinstead");
2703    p.append("cleaninstead");
2704    p.append("bothinstead");
2705    p.setLonghelp(
2706      "This is a lagrangean relaxation for TwoMir cuts.  See \
2707  lagomoryCuts for description of options.");
2708    parameters.push_back(p);
2709  }
2710  {
2711    CbcOrClpParam p("lift!AndProjectCuts", "Whether to use Lift and Project cuts",
2712      "off", CBC_PARAM_STR_LANDPCUTS);
2713
2714    p.append("on");
2715    p.append("root");
2716    p.append("ifmove");
2717    p.append("forceOn");
2718    p.setLonghelp(
2719      "These cuts may be expensive to compute. "
2720      CUTS_LONGHELP
2721      " Reference: https://github.com/coin-or/Cgl/wiki/CglLandP");
2722    parameters.push_back(p);
2723  }
2724  {
2725    CbcOrClpParam p("local!TreeSearch", "Whether to use local tree search when a solution is found",
2726      "off", CBC_PARAM_STR_LOCALTREE);
2727    p.append("on");
2728    p.setLonghelp(
2729      "The heuristic is from Fischetti and Lodi and is not really a heuristic although it can be used as one \
2730(with limited functionality).  It is not switched on when heuristics are switched on.");
2731    parameters.push_back(p);
2732  }
2733#endif
2734  {
2735#ifndef COIN_HAS_CBC
2736    CbcOrClpParam p("log!Level", "Level of detail in Solver output",
2737      -1, 999999, CLP_PARAM_INT_SOLVERLOGLEVEL);
2738    parameters.push_back(p);
2739#else
2740    CbcOrClpParam p("log!Level", "Level of detail in Coin branch and Cut output",
2741      -63, 63, CLP_PARAM_INT_LOGLEVEL);
2742    p.setIntValue(1);
2743#endif
2744    p.setLonghelp(
2745      "If 0 then there should be no output in normal circumstances.  1 is probably the best\
2746 value for most uses, while 2 and 3 give more information.");
2747    parameters.push_back(p);
2748  }
2749  {
2750    CbcOrClpParam p("max!imize", "Set optimization direction to maximize",
2751      CLP_PARAM_ACTION_MAXIMIZE, 7);
2752    p.setLonghelp(
2753      "The default is minimize - use 'maximize' for maximization.\n\
2754You can also use the parameters 'direction maximize'.");
2755    parameters.push_back(p);
2756  }
2757#ifdef COIN_HAS_CLP
2758  {
2759    CbcOrClpParam p("maxF!actor", "Maximum number of iterations between \
2760refactorizations",
2761      1, 999999, CLP_PARAM_INT_MAXFACTOR);
2762    p.setLonghelp(
2763      "If this is left at its default value of 200 then CLP will guess a\
2764 value to use.  CLP may decide to re-factorize earlier for accuracy.");
2765    parameters.push_back(p);
2766  }
2767  {
2768    CbcOrClpParam p("maxIt!erations", "Maximum number of iterations before \
2769stopping",
2770      0, 2147483647, CLP_PARAM_INT_MAXITERATION);
2771    p.setLonghelp(
2772      "This can be used for testing purposes.  The corresponding library call\n\
2773      \tsetMaximumIterations(value)\n can be useful.  If the code stops on\
2774 seconds or by an interrupt this will be treated as stopping on maximum iterations.  This is ignored in branchAndCut - use maxN!odes.");
2775    parameters.push_back(p);
2776  }
2777#endif
2778#ifdef COIN_HAS_CBC
2779  {
2780    CbcOrClpParam p("maxN!odes", "Maximum number of nodes to do",
2781      -1, 2147483647, CBC_PARAM_INT_MAXNODES);
2782    p.setLonghelp(
2783      "This is a repeatable way to limit search.  Normally using time is easier \
2784but then the results may not be repeatable.");
2785    parameters.push_back(p);
2786  }
2787  {
2788    CbcOrClpParam p("maxSaved!Solutions", "Maximum number of solutions to save",
2789      0, 2147483647, CBC_PARAM_INT_MAXSAVEDSOLS);
2790    p.setLonghelp(
2791      "Number of solutions to save.");
2792    parameters.push_back(p);
2793  }
2794  {
2795    CbcOrClpParam p("maxSo!lutions", "Maximum number of feasible solutions to get",
2796      1, 2147483647, CBC_PARAM_INT_MAXSOLS);
2797    p.setLonghelp(
2798      "You may want to stop after (say) two solutions or an hour.  \
2799This is checked every node in tree, so it is possible to get more solutions from heuristics.");
2800    parameters.push_back(p);
2801  }
2802#endif
2803  {
2804    CbcOrClpParam p("min!imize", "Set optimization direction to minimize",
2805      CLP_PARAM_ACTION_MINIMIZE, 7);
2806    p.setLonghelp(
2807      "The default is minimize - use 'maximize' for maximization.\n\
2808This should only be necessary if you have previously set maximization \
2809You can also use the parameters 'direction minimize'.");
2810    parameters.push_back(p);
2811  }
2812#ifdef COIN_HAS_CBC
2813  {
2814    CbcOrClpParam p("mipO!ptions", "Dubious options for mip",
2815      0, COIN_INT_MAX, CBC_PARAM_INT_MIPOPTIONS, 0);
2816    p.setIntValue(1057);
2817    parameters.push_back(p);
2818  }
2819  {
2820    CbcOrClpParam p("more!MipOptions", "More dubious options for mip",
2821      -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0);
2822    parameters.push_back(p);
2823  }
2824  {
2825    CbcOrClpParam p("more2!MipOptions", "More more dubious options for mip",
2826      -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMOREMIPOPTIONS, 0);
2827    p.setIntValue(0);
2828    parameters.push_back(p);
2829  }
2830  {
2831    CbcOrClpParam p("mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts",
2832      "off", CBC_PARAM_STR_MIXEDCUTS);
2833
2834    p.append("on");
2835    p.append("root");
2836    p.append("ifmove");
2837    p.append("forceOn");
2838    p.append("onglobal");
2839    p.setLonghelp(CUTS_LONGHELP
2840      " Reference: https://github.com/coin-or/Cgl/wiki/CglMixedIntegerRounding2");
2841    parameters.push_back(p);
2842  }
2843#endif
2844  {
2845    CbcOrClpParam p("mess!ages", "Controls if Clpnnnn is printed",
2846      "off", CLP_PARAM_STR_MESSAGES);
2847
2848    p.append("on");
2849    p.setLonghelp("The default behavior is to put out messages such as:\n\
2850   Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
2851but this program turns this off to make it look more friendly.  It can be useful\
2852 to turn them back on if you want to be able to 'grep' for particular messages or if\
2853 you intend to override the behavior of a particular message.  This only affects Clp not Cbc.");
2854    parameters.push_back(p);
2855  }
2856  {
2857    CbcOrClpParam p("miplib", "Do some of miplib test set",
2858      CBC_PARAM_ACTION_MIPLIB, 3, 1);
2859    parameters.push_back(p);
2860  }
2861#ifdef COIN_HAS_CBC
2862  {
2863    CbcOrClpParam p("mips!tart", "reads an initial feasible solution from file",
2864      CBC_PARAM_ACTION_MIPSTART);
2865    p.setLonghelp("\
2866The MIPStart allows one to enter an initial integer feasible solution \
2867to CBC. Values of the main decision variables which are active (have \
2868non-zero values) in this solution are specified in a text  file. The \
2869text file format used is the same of the solutions saved by CBC, but \
2870not all fields are required to be filled. First line may contain the \
2871solution status and will be ignored, remaining lines contain column \
2872indexes, names and values as in this example:\n\
2873\n\
2874Stopped on iterations - objective value 57597.00000000\n\
2875      0  x(1,1,2,2)               1 \n\
2876      1  x(3,1,3,2)               1 \n\
2877      5  v(5,1)                   2 \n\
2878      33 x(8,1,5,2)               1 \n\
2879      ...\n\
2880\n\
2881Column indexes are also ignored since pre-processing can change them. \
2882There is no need to include values for continuous or integer auxiliary \
2883variables, since they can be computed based on main decision variables. \
2884Starting CBC with an integer feasible solution can dramatically improve \
2885its performance: several MIP heuristics (e.g. RINS) rely on having at \
2886least one feasible solution available and can start immediately if the \
2887user provides one. Feasibility Pump (FP) is a heuristic which tries to \
2888overcome the problem of taking too long to find feasible solution (or \
2889not finding at all), but it not always succeeds. If you provide one \
2890starting solution you will probably save some time by disabling FP. \
2891\n\n\
2892Knowledge specific to your problem can be considered to write an \
2893external module to quickly produce an initial feasible solution - some \
2894alternatives are the implementation of simple greedy heuristics or the \
2895solution (by CBC for example) of a simpler model created just to find \
2896a feasible solution. \
2897\n\n\
2898Silly options added.  If filename ends .low then integers not mentioned \
2899are set low - also .high, .lowcheap, .highcheap, .lowexpensive, .highexpensive \
2900where .lowexpensive sets costed ones to make expensive others low. Also if \
2901filename starts empty. then no file is read at all - just actions done. \
2902\n\n\
2903Question and suggestions regarding MIPStart can be directed to\n\
2904haroldo.santos@gmail.com. ");
2905    parameters.push_back(p);
2906  }
2907#endif
2908  {
2909    CbcOrClpParam p("moreS!pecialOptions", "Yet more dubious options for Simplex - see ClpSimplex.hpp",
2910      0, COIN_INT_MAX, CLP_PARAM_INT_MORESPECIALOPTIONS, 0);
2911    parameters.push_back(p);
2912  }
2913#ifdef COIN_HAS_CBC
2914  {
2915    CbcOrClpParam p("moreT!une", "Yet more dubious ideas for feasibility pump",
2916      0, 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0);
2917
2918    p.setLonghelp(
2919      "Yet more ideas for Feasibility Pump \n\
2920\t/100000 == 1 use box constraints and original obj in cleanup\n\
2921\t/1000 == 1 Pump will run twice if no solution found\n\
2922\t/1000 == 2 Pump will only run after root cuts if no solution found\n\
2923\t/1000 >10 as above but even if solution found\n\
2924\t/100 == 1,3.. exact 1.0 for objective values\n\
2925\t/100 == 2,3.. allow more iterations per pass\n\
2926\t n fix if value of variable same for last n iterations.");
2927    p.setIntValue(0);
2928    parameters.push_back(p);
2929  }
2930  {
2931    CbcOrClpParam p("multiple!RootPasses", "Do multiple root passes to collect cuts and solutions",
2932      0, 100000000, CBC_PARAM_INT_MULTIPLEROOTS, 0);
2933    p.setIntValue(0);
2934    p.setLonghelp(
2935      "Solve (in parallel, if enabled) the root phase this number of times, \
2936      each with its own different seed, and collect all solutions and cuts generated. \
2937      The actual format is aabbcc where aa is the number of extra passes; \
2938      if bb is non zero, then it is number of threads to use (otherwise uses threads setting); \
2939      and cc is the number of times to do root phase. \
2940The solvers do not interact with each other.  However if extra passes are specified \
2941then cuts are collected and used in later passes - so there is interaction there. \
2942Some parts of this implementation have their origin in idea of \
2943Andrea Lodi, Matteo Fischetti, Michele Monaci, Domenico Salvagnin, and Andrea Tramontani.");
2944    parameters.push_back(p);
2945  }
2946  {
2947    CbcOrClpParam p("naive!Heuristics", "Whether to try some stupid heuristic",
2948      "off", CBC_PARAM_STR_NAIVE, 7, 1);
2949
2950    p.append("on");
2951    p.append("both");
2952    p.append("before");
2953    p.setLonghelp(
2954      "This is naive heuristics which, e.g., fix all integers with costs to zero!. "
2955      HEURISTICS_LONGHELP);
2956    parameters.push_back(p);
2957  }
2958#endif
2959#ifdef COIN_HAS_CLP
2960  {
2961    CbcOrClpParam p("netlib", "Solve entire netlib test set",
2962      CLP_PARAM_ACTION_NETLIB_EITHER, 3, 1);
2963    p.setLonghelp(
2964      "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\
2965The user can set options before e.g. clp -presolve off -netlib");
2966    parameters.push_back(p);
2967  }
2968  {
2969    CbcOrClpParam p("netlibB!arrier", "Solve entire netlib test set with barrier",
2970      CLP_PARAM_ACTION_NETLIB_BARRIER, 3, 1);
2971    p.setLonghelp(
2972      "This exercises the unit test for clp and then solves the netlib test set using barrier.\
2973The user can set options before e.g. clp -kkt on -netlib");
2974    parameters.push_back(p);
2975  }
2976  {
2977    CbcOrClpParam p("netlibD!ual", "Solve entire netlib test set (dual)",
2978      CLP_PARAM_ACTION_NETLIB_DUAL, 3, 1);
2979
2980    p.setLonghelp(
2981      "This exercises the unit test for clp and then solves the netlib test set using dual.\
2982The user can set options before e.g. clp -presolve off -netlib");
2983    parameters.push_back(p);
2984  }
2985  {
2986    CbcOrClpParam p("netlibP!rimal", "Solve entire netlib test set (primal)",
2987      CLP_PARAM_ACTION_NETLIB_PRIMAL, 3, 1);
2988    p.setLonghelp(
2989      "This exercises the unit test for clp and then solves the netlib test set using primal.\
2990The user can set options before e.g. clp -presolve off -netlibp");
2991    parameters.push_back(p);
2992  }
2993  {
2994    CbcOrClpParam p("netlibT!une", "Solve entire netlib test set with 'best' algorithm",
2995      CLP_PARAM_ACTION_NETLIB_TUNE, 3, 1);
2996    p.setLonghelp(
2997      "This exercises the unit test for clp and then solves the netlib test set using whatever \
2998works best.  I know this is cheating but it also stresses the code better by doing a \
2999mixture of stuff.  The best algorithm was chosen on a Linux ThinkPad using native cholesky \
3000with University of Florida ordering.");
3001    parameters.push_back(p);
3002  }
3003  {
3004    CbcOrClpParam p("network", "Tries to make network matrix",
3005      CLP_PARAM_ACTION_NETWORK, 7, 0);
3006    p.setLonghelp(
3007      "Clp will go faster if the matrix can be converted to a network.  The matrix\
3008 operations may be a bit faster with more efficient storage, but the main advantage\
3009 comes from using a network factorization.  It will probably not be as fast as a \
3010specialized network code.");
3011    parameters.push_back(p);
3012  }
3013#ifdef COIN_HAS_CBC
3014  {
3015    CbcOrClpParam p("nextB!estSolution", "Prints next best saved solution to file",
3016      CLP_PARAM_ACTION_NEXTBESTSOLUTION);
3017
3018    p.setLonghelp(
3019      "To write best solution, just use solution.  This prints next best (if exists) \
3020 and then deletes it. \
3021 This will write a primitive solution file to the given file name.  It will use the default\
3022 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3023 is initialized to 'stdout'.  The amount of output can be varied using printi!ngOptions or printMask.");
3024    parameters.push_back(p);
3025  }
3026  {
3027    CbcOrClpParam p("node!Strategy", "What strategy to use to select the next node from the branch and cut tree",
3028      "hybrid", CBC_PARAM_STR_NODESTRATEGY);
3029    p.append("fewest");
3030    p.append("depth");
3031    p.append("upfewest");
3032    p.append("downfewest");
3033    p.append("updepth");
3034    p.append("downdepth");
3035    p.setLonghelp(
3036      "Normally before a feasible solution is found, CBC will choose a node with fewest infeasibilities. \
3037  Alternatively, one may choose tree-depth as the criterion. This requires the minimal amount of memory, but may take a long time to find the best solution.\
3038  Additionally, one may specify whether up or down branches must \
3039be selected first (the up-down choice will carry on after a first solution has been bound). \
3040The default choice 'hybrid' does breadth first on small depth nodes and then switches to 'fewest'.");
3041    parameters.push_back(p);
3042  }
3043  {
3044    CbcOrClpParam p("numberA!nalyze", "Number of analysis iterations",
3045      -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0);
3046    p.setLonghelp(
3047      "This says how many iterations to spend at root node analyzing problem. \
3048This is a first try and will hopefully become more sophisticated.");
3049    parameters.push_back(p);
3050  }
3051#endif
3052  {
3053    CbcOrClpParam p("objective!Scale", "Scale factor to apply to objective",
3054      -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE, 1);
3055    p.setLonghelp(
3056      "If the objective function has some very large values, you may wish to scale them\
3057 internally by this amount.  It can also be set by autoscale.  It is applied after scaling.  You are unlikely to need this.");
3058    p.setDoubleValue(1.0);
3059    parameters.push_back(p);
3060  }
3061#endif
3062#ifdef COIN_HAS_CBC
3063#ifdef COIN_HAS_NTY
3064  {
3065    CbcOrClpParam p("Orbit!alBranching", "Whether to try orbital branching",
3066      "off", CBC_PARAM_STR_ORBITAL);
3067    p.append("on");
3068    p.append("strong");
3069    p.append("force");
3070    p.append("simple");
3071    p.setLonghelp(
3072      "This switches on Orbital branching. \
3073On just adds orbital, strong tries extra fixing in strong branching");
3074    parameters.push_back(p);
3075  }
3076#endif
3077  {
3078    CbcOrClpParam p("PrepN!ames", "If column names will be kept in pre-processed model",
3079      "off", CBC_PARAM_STR_PREPROCNAMES);
3080    p.append("on");
3081    p.setLonghelp(
3082      "Normally the preprocessed model has column names replaced by new names C0000...\
3083Setting this option to on keeps original names in variables which still exist in the preprocessed problem");
3084    parameters.push_back(p);
3085  }
3086
3087  {
3088    CbcOrClpParam p("outDup!licates", "takes duplicate rows etc out of integer model",
3089      CLP_PARAM_ACTION_OUTDUPROWS, 7, 0);
3090    parameters.push_back(p);
3091  }
3092#endif
3093  {
3094    CbcOrClpParam p("output!Format", "Which output format to use",
3095      1, 6, CLP_PARAM_INT_OUTPUTFORMAT);
3096    p.setLonghelp(
3097      "Normally export will be done using normal representation for numbers and two values\
3098 per line.  You may want to do just one per line (for grep or suchlike) and you may wish\
3099 to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
3100 otherwise odd values gives one value per line, even two.  Values 1,2 give normal format, 3,4\
3101 gives greater precision, while 5,6 give IEEE values.  When used for exporting a basis 1 does not save \
3102values, 2 saves values, 3 with greater accuracy and 4 in IEEE.");
3103    parameters.push_back(p);
3104  }
3105#ifdef COIN_HAS_CLP
3106  {
3107    CbcOrClpParam p("para!metrics", "Import data from file and do parametrics",
3108      CLP_PARAM_ACTION_PARAMETRICS, 3);
3109    p.setLonghelp(
3110      "This will read a file with parametric data from the given file name \
3111and then do parametrics.  It will use the default\
3112 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3113 is initialized to '', i.e. it must be set.  This can not read from compressed files. \
3114File is in modified csv format - a line ROWS will be followed by rows data \
3115while a line COLUMNS will be followed by column data.  The last line \
3116should be ENDATA. The ROWS line must exist and is in the format \
3117ROWS, inital theta, final theta, interval theta, n where n is 0 to get \
3118CLPI0062 message at interval or at each change of theta \
3119and 1 to get CLPI0063 message at each iteration.  If interval theta is 0.0 \
3120or >= final theta then no interval reporting.  n may be missed out when it is \
3121taken as 0.  If there is Row data then \
3122there is a headings line with allowed headings - name, number, \
3123lower(rhs change), upper(rhs change), rhs(change).  Either the lower and upper \
3124fields should be given or the rhs field. \
3125The optional COLUMNS line is followed by a headings line with allowed \
3126headings - name, number, objective(change), lower(change), upper(change). \
3127 Exactly one of name and number must be given for either section and \
3128missing ones have value 0.0.");
3129    parameters.push_back(p);
3130  }
3131#endif
3132#ifdef COIN_HAS_CBC
3133  {
3134    CbcOrClpParam p("passC!uts", "Number of rounds that cut generators are applied in the root node",
3135      -9999999, 9999999, CBC_PARAM_INT_CUTPASS);
3136
3137    p.setIntValue(20);
3138    p.setLonghelp(
3139      "The default is to do 100 passes if the problem has less than 500 columns, 100 passes (but \
3140stop if the drop in the objective function value is small) if the problem has less than 5000 columns, and 20 passes otherwise. \
3141A negative value -n means that n passes are also applied if the objective does not drop.");
3142    parameters.push_back(p);
3143  }
3144  {
3145    CbcOrClpParam p("passF!easibilityPump", "How many passes to do in the Feasibility Pump heuristic",
3146      0, 10000, CBC_PARAM_INT_FPUMPITS);
3147    p.setIntValue(20);
3148    parameters.push_back(p);
3149  }
3150#endif
3151#ifdef COIN_HAS_CLP
3152  {
3153    CbcOrClpParam p("passP!resolve", "How many passes in presolve",
3154      -200, 100, CLP_PARAM_INT_PRESOLVEPASS, 1);
3155    p.setLonghelp(
3156      "Normally Presolve does 10 passes but you may want to do less to make it\
3157 more lightweight or do more if improvements are still being made.  As Presolve will return\
3158 if nothing is being taken out, you should not normally need to use this fine tuning.");
3159    parameters.push_back(p);
3160  }
3161#endif
3162#ifdef COIN_HAS_CBC
3163  {
3164    CbcOrClpParam p("passT!reeCuts", "Number of rounds that cut generators are applied in the tree",
3165      -9999999, 9999999, CBC_PARAM_INT_CUTPASSINTREE);
3166    p.setIntValue(1);
3167    p.setLonghelp("The default is to do one pass. A negative value -n means that n passes are also applied if the objective does not drop.");
3168    parameters.push_back(p);
3169  }
3170#endif
3171#ifdef COIN_HAS_CLP
3172  {
3173    CbcOrClpParam p("pertV!alue", "Method of perturbation",
3174      -5000, 102, CLP_PARAM_INT_PERTVALUE, 1);
3175    parameters.push_back(p);
3176  }
3177  {
3178    CbcOrClpParam p("perturb!ation", "Whether to perturb the problem",
3179      "on", CLP_PARAM_STR_PERTURBATION);
3180    p.append("off");
3181    p.setLonghelp(
3182      "Perturbation helps to stop cycling, but CLP uses other measures for this.\
3183  However, large problems and especially ones with unit elements and unit right hand sides or costs\
3184 benefit from perturbation.  Normally CLP tries to be intelligent, but one can switch this off.");
3185  // The Clp library has this off by default.  This program has it on by default.
3186    parameters.push_back(p);
3187  }
3188  {
3189    CbcOrClpParam p("PFI", "Whether to use Product Form of Inverse in simplex",
3190      "off", CLP_PARAM_STR_PFI, 7, 0);
3191    p.append("on");
3192    p.setLonghelp(
3193      "By default clp uses Forrest-Tomlin L-U update.  If you are masochistic you can switch it off.");
3194    parameters.push_back(p);
3195  }
3196#endif
3197#ifdef COIN_HAS_CBC
3198  {
3199    CbcOrClpParam p("pivotAndC!omplement", "Whether to try Pivot and Complement heuristic",
3200      "off", CBC_PARAM_STR_PIVOTANDCOMPLEMENT);
3201
3202    p.append("on");
3203    p.append("both");
3204    p.append("before");
3205    p.setLonghelp(HEURISTICS_LONGHELP);
3206    parameters.push_back(p);
3207  }
3208  {
3209    CbcOrClpParam p("pivotAndF!ix", "Whether to try Pivot and Fix heuristic",
3210      "off", CBC_PARAM_STR_PIVOTANDFIX);
3211    p.append("on");
3212    p.append("both");
3213    p.append("before");
3214    p.setLonghelp(HEURISTICS_LONGHELP);
3215    parameters.push_back(p);
3216  }
3217#endif
3218#ifdef COIN_HAS_CLP
3219  {
3220    CbcOrClpParam p("plus!Minus", "Tries to make +- 1 matrix",
3221      CLP_PARAM_ACTION_PLUSMINUS, 7, 0);
3222    p.setLonghelp(
3223      "Clp will go slightly faster if the matrix can be converted so that the elements are\
3224 not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
3225 see if it can convert the problem so you should not need to use this.");
3226    parameters.push_back(p);
3227  }
3228  {
3229    CbcOrClpParam p("pO!ptions", "Dubious print options",
3230      0, COIN_INT_MAX, CLP_PARAM_INT_PRINTOPTIONS, 1);
3231    p.setIntValue(0);
3232    p.setLonghelp(
3233      "If this is > 0 then presolve will give more information and branch and cut will give statistics");
3234    parameters.push_back(p);
3235  }
3236  {
3237    CbcOrClpParam p("preO!pt", "Presolve options",
3238      0, COIN_INT_MAX, CLP_PARAM_INT_PRESOLVEOPTIONS, 0);
3239    parameters.push_back(p);
3240  }
3241#endif
3242  {
3243    CbcOrClpParam p("presolve", "Whether to presolve problem",
3244      "on", CLP_PARAM_STR_PRESOLVE);
3245    p.append("off");
3246    p.append("more");
3247    p.append("file");
3248    p.setLonghelp("Presolve analyzes the model to find such things as redundant equations, equations\
3249 which fix some variables, equations which can be transformed into bounds, etc.  For the\
3250 initial solve of any problem this is worth doing unless one knows that it will have no effect.  \
3251Option 'on' will normally do 5 passes, while using 'more' will do 10.  If the problem is very large one can \
3252let CLP write the original problem to file by using 'file'.");
3253    parameters.push_back(p);
3254  }
3255#ifdef COIN_HAS_CBC
3256  {
3257    CbcOrClpParam p("preprocess", "Whether to use integer preprocessing",
3258      "off", CBC_PARAM_STR_PREPROCESS);
3259
3260    p.append("on");
3261    p.append("save");
3262    p.append("equal");
3263    p.append("sos");
3264    p.append("trysos");
3265    p.append("equalall");
3266    p.append("strategy");
3267    p.append("aggregate");
3268    p.append("forcesos");
3269    p.append("stop!aftersaving");
3270    p.setLonghelp(
3271      "This tries to reduce size of model in a similar way to presolve and \
3272it also tries to strengthen the model - this can be very useful and is worth trying. \
3273 Value 'save' saves the presolved problem to a file presolved.mps.\
3274 Value 'equal' will turn inequality-cliques into equalities.\
3275 Value 'sos' lets CBC search for rows with upper bound 1 and where all nonzero coefficients are 1 and creates special ordered sets if the sets are not overlapping and all integer variables (except for at most one) are in the sets.\
3276 Value 'trysos' is same as 'sos', but allows any number of integer variables outside of sets.\
3277 Value 'equalall' lets CBC turn all valid inequalities into equalities by adding integer slack variables."); // Value 'strategy' is as on but uses CbcStrategy.
3278    parameters.push_back(p);
3279  }
3280#endif
3281#ifdef COIN_HAS_CLP
3282  {
3283    CbcOrClpParam p("preT!olerance", "Tolerance to use in presolve",
3284      1.0e-20, 1.0e12, CLP_PARAM_DBL_PRESOLVETOLERANCE);
3285    p.setLonghelp(
3286      "One may want to increase this tolerance if presolve says the problem is \
3287infeasible and one has awkward numbers and is sure that the problem is really feasible.");
3288    parameters.push_back(p);
3289  }
3290  {
3291    CbcOrClpParam p("primalP!ivot", "Primal pivot choice algorithm",
3292      "auto!matic", CLP_PARAM_STR_PRIMALPIVOT, 7, 1);
3293
3294    p.append("exa!ct");
3295    p.append("dant!zig");
3296    p.append("part!ial");
3297    p.append("steep!est");
3298    p.append("change");
3299    p.append("sprint");
3300    p.append("PEsteep!est");
3301    p.append("PEdantzig");
3302    p.setLonghelp(
3303      "The Dantzig method is simple but its use is deprecated.  Exact devex is the method of choice and there\
3304 are two variants which keep all weights updated but only scan a subset each iteration.\
3305 Partial switches this on while 'change' initially does 'dantzig' until the factorization\
3306 becomes denser.  This is still a work in progress.\
3307 The PE variants add the Positive Edge criterion.\
3308 This selects incoming variables to try to avoid degenerate moves. \
3309 See also Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR's CLP;\
3310 Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex.");
3311
3312    parameters.push_back(p);
3313  }
3314  {
3315    CbcOrClpParam p("primalS!implex", "Do primal simplex algorithm",
3316      CLP_PARAM_ACTION_PRIMALSIMPLEX);
3317
3318    p.setLonghelp(
3319      "This command solves the continuous relaxation of the current model using the primal algorithm.\
3320  The default is to use exact devex.\
3321 The time and iterations may be affected by settings such as presolve, scaling, crash\
3322 and also by column selection  method, infeasibility weight and dual and primal tolerances.");
3323    parameters.push_back(p);
3324  }
3325#endif
3326  {
3327    CbcOrClpParam p("primalT!olerance", "For a feasible solution \
3328no primal infeasibility, i.e., constraint violation, may exceed this value",
3329      1.0e-20, 1.0e12, CLP_PARAM_DBL_PRIMALTOLERANCE);
3330    p.setLonghelp(
3331      "Normally the default tolerance is fine, but one may want to increase it a\
3332 bit if the primal simplex algorithm seems to be having a hard time.");
3333    parameters.push_back(p);
3334  }
3335#ifdef COIN_HAS_CLP
3336  {
3337    CbcOrClpParam p("primalW!eight", "Initially algorithm acts as if it \
3338costs this much to be infeasible",
3339      1.0e-20, 1.0e20, CLP_PARAM_DBL_PRIMALWEIGHT);
3340    p.setLonghelp(
3341      "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
3342 algorithm where you first get feasible then optimal.  So Clp is minimizing this weight times\
3343 the sum of primal infeasibilities plus the true objective function (in minimization sense).\
3344  Too high a value may mean more iterations, while too low a bound means\
3345 the code may go all the way and then have to increase the weight in order to get feasible.\
3346  OSL had a heuristic to\
3347 adjust bounds, maybe we need that here.");
3348    parameters.push_back(p);
3349  }
3350  {
3351    CbcOrClpParam p("psi", "Two-dimension pricing factor for Positive edge",
3352      -1.1, 1.1, CLP_PARAM_DBL_PSI);
3353
3354    p.setDoubleValue(-0.5);
3355    p.setLonghelp(
3356      "The Positive Edge criterion has been added to \
3357select incoming variables to try and avoid degenerate moves. \
3358Variables not in promising set have their infeasibility weight multiplied by psi \
3359so 0.01 would mean that if there were any promising variables, then they would always be chosen, \
3360while 1.0 effectively switches algorithm off. \
3361There are two ways of switching on this feature.  One way is to set psi positive and then \
3362the Positive Edge criterion will be used for Primal and Dual.  The other way is to select pesteep \
3363in dualpivot choice (for example), then the absolute value of psi is used - default 0.5. \
3364Until this settles down it is only implemented in clp. \
3365Code donated by Jeremy Omer.  See \
3366Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR’s CLP. and \
3367Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex.");
3368    parameters.push_back(p);
3369  }
3370#endif
3371  {
3372    CbcOrClpParam p("printi!ngOptions", "Print options",
3373      "normal", CLP_PARAM_STR_INTPRINT, 3);
3374    p.append("integer");
3375    p.append("special");
3376    p.append("rows");
3377    p.append("all");
3378    p.append("csv");
3379    p.append("bound!ranging");
3380    p.append("rhs!ranging");
3381    p.append("objective!ranging");
3382    p.append("stats");
3383    p.append("boundsint");
3384    p.append("boundsall");
3385    p.append("fixint");
3386    p.append("fixall");
3387    p.setLonghelp(
3388      "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\
3389integer - nonzero integer column variables\n\
3390special - in format suitable for OsiRowCutDebugger\n\
3391rows - nonzero column variables and row activities\n\
3392all - all column variables and row activities.\n\
3393\nFor non-integer problems 'integer' and 'special' act like 'normal'.  \
3394Also see printMask for controlling output.");
3395    parameters.push_back(p);
3396  }
3397  {
3398    CbcOrClpParam p("printM!ask", "Control printing of solution on a  mask",
3399      CLP_PARAM_ACTION_PRINTMASK, 3);
3400
3401    p.setLonghelp(
3402      "If set then only those names which match mask are printed in a solution. \
3403'?' matches any character and '*' matches any set of characters. \
3404 The default is '' i.e. unset so all variables are printed. \
3405This is only active if model has names.");
3406    parameters.push_back(p);
3407  }
3408
3409#ifdef COIN_HAS_CBC
3410  {
3411    CbcOrClpParam p("prio!rityIn", "Import priorities etc from file",
3412      CBC_PARAM_ACTION_PRIORITYIN, 3);
3413    p.setLonghelp(
3414      "This will read a file with priorities from the given file name.  It will use the default\
3415 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3416 is initialized to '', i.e. it must be set.  This can not read from compressed files. \
3417File is in csv format with allowed headings - name, number, priority, direction, up, down, solution.  Exactly one of\
3418 name and number must be given.");
3419    parameters.push_back(p);
3420  }
3421
3422  {
3423    CbcOrClpParam p("probing!Cuts", "Whether to use Probing cuts",
3424      "off", CBC_PARAM_STR_PROBINGCUTS);
3425    p.append("on");
3426    p.append("root");
3427    p.append("ifmove");
3428    p.append("forceOn");
3429    p.append("onglobal");
3430    p.append("forceonglobal");
3431    p.append("forceOnBut");
3432    p.append("forceOnStrong");
3433    p.append("forceOnButStrong");
3434    p.append("strongRoot");
3435    p.setLonghelp(CUTS_LONGHELP
3436      " Value 'forceOnBut' turns on probing and forces CBC to do probing at every node, but does only probing, not strengthening etc. \
3437    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. \
3438    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. \
3439    Reference: https://github.com/coin-or/Cgl/wiki/CglProbing");
3440    parameters.push_back(p);
3441  }
3442  {
3443    CbcOrClpParam p("proximity!Search", "Whether to do proximity search heuristic",
3444      "off", CBC_PARAM_STR_PROXIMITY);
3445
3446    p.append("on");
3447    p.append("both");
3448    p.append("before");
3449    p.append("10");
3450    p.append("100");
3451    p.append("300");
3452    // but allow numbers after this (returning 1)
3453    p.setFakeKeyWord(1);
3454    p.setLonghelp(
3455      "This heuristic looks for a solution close to the incumbent solution (Fischetti and Monaci, 2012). \
3456The idea is to define a sub-MIP without additional constraints but with a modified objective function intended to attract the search \
3457in the proximity of the incumbent. \
3458The approach works well for 0-1 MIPs whose solution landscape is not too irregular (meaning the there is reasonable probability of \
3459finding an improved solution by flipping a small number of binary variables), in particular when it is applied to the first heuristic solutions \
3460found at the root node. "
3461      HEURISTICS_LONGHELP); // Can also set different maxNode settings by plusnnnn (and are 'on'(on==30)).
3462    parameters.push_back(p);
3463  }
3464  {
3465    CbcOrClpParam p("pumpC!utoff", "Fake cutoff for use in feasibility pump",
3466      -1.0e100, 1.0e100, CBC_PARAM_DBL_FAKECUTOFF);
3467    p.setDoubleValue(0.0);
3468    p.setLonghelp(
3469      "0.0 off - otherwise add a constraint forcing objective below this value\
3470 in feasibility pump");
3471    parameters.push_back(p);
3472  }
3473  {
3474    CbcOrClpParam p("pumpI!ncrement", "Fake increment for use in feasibility pump",
3475      -1.0e100, 1.0e100, CBC_PARAM_DBL_FAKEINCREMENT, 1);
3476    p.setDoubleValue(0.0);
3477    p.setLonghelp(
3478      "0.0 off - otherwise use as absolute increment to cutoff \
3479when solution found in feasibility pump");
3480    parameters.push_back(p);
3481  }
3482  {
3483    CbcOrClpParam p("pumpT!une", "Dubious ideas for feasibility pump",
3484      0, 100000000, CBC_PARAM_INT_FPUMPTUNE);
3485    p.setIntValue(1003);
3486    p.setLonghelp(
3487      "This fine tunes Feasibility Pump \n\
3488\t>=10000000 use as objective weight switch\n\
3489\t>=1000000 use as accumulate switch\n\
3490\t>=1000 use index+1 as number of large loops\n\
3491\t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\
3492\t%100 == 10,20 affects how each solve is done\n\
3493\t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \
3494If accumulate is on then after a major pass, variables which have not moved \
3495are fixed and a small branch and bound is tried.");
3496    p.setIntValue(0);
3497    parameters.push_back(p);
3498  }
3499#endif
3500  {
3501    CbcOrClpParam p("quit", "Stops clp execution",
3502      CLP_PARAM_ACTION_EXIT);
3503    p.setLonghelp(
3504      "This stops the execution of Clp, end, exit, quit and stop are synonyms");
3505
3506    parameters.push_back(p);
3507  }
3508#ifdef COIN_HAS_CBC
3509  {
3510    CbcOrClpParam p("randomC!bcSeed", "Random seed for Cbc",
3511      -1, COIN_INT_MAX, CBC_PARAM_INT_RANDOMSEED);
3512
3513    p.setLonghelp(
3514      "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. "
3515      "The special value of 0 lets Cbc use the time of the day for the initial seed.");
3516    p.setIntValue(-1);
3517    parameters.push_back(p);
3518  }
3519  {
3520    CbcOrClpParam p("randomi!zedRounding", "Whether to try randomized rounding heuristic",
3521      "off", CBC_PARAM_STR_RANDROUND);
3522    p.append("on");
3523    p.append("both");
3524    p.append("before");
3525    p.setLonghelp(HEURISTICS_LONGHELP);
3526    parameters.push_back(p);
3527  }
3528#endif
3529#ifdef COIN_HAS_CLP
3530  {
3531    CbcOrClpParam p("randomS!eed", "Random seed for Clp",
3532      0, COIN_INT_MAX, CLP_PARAM_INT_RANDOMSEED);
3533
3534    p.setLonghelp(
3535      "Initialization of the random seed for pseudo-random numbers used to break ties in degenerate problems. "
3536      "This may yield a different continuous optimum and, in the context of Cbc, different cuts and heuristic solutions. "
3537      "The special value of 0 lets CLP use the time of the day for the initial seed.");
3538    p.setIntValue(1234567);
3539    parameters.push_back(p);
3540  }
3541#endif
3542#ifdef COIN_HAS_CBC
3543  {
3544    CbcOrClpParam p("ratio!Gap", "Stop when gap between best possible and \
3545best known is less than this fraction of larger of two",
3546      0.0, 1.0e20, CBC_PARAM_DBL_GAPRATIO);
3547    p.setDoubleValue(0.0);
3548    p.setLonghelp(
3549      "If the gap between the best known solution and the best possible solution is less than this fraction \
3550of the objective value at the root node then the search will terminate.  See 'allowableGap' for a \
3551way of using absolute value rather than fraction.");
3552    parameters.push_back(p);
3553  }
3554#endif
3555  {
3556    CbcOrClpParam p("restoreS!olution", "reads solution from file",
3557      CLP_PARAM_ACTION_RESTORESOL);
3558
3559    p.setLonghelp(
3560      "This will read a binary solution file from the given file name.  It will use the default\
3561 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3562 is initialized to 'solution.file'.  This reads in a file from saveSolution");
3563    parameters.push_back(p);
3564  }
3565#ifdef COIN_HAS_CBC
3566  {
3567    CbcOrClpParam p("readSt!ored", "Import stored cuts from file",
3568      CLP_PARAM_ACTION_STOREDFILE, 3, 0);
3569    parameters.push_back(p);
3570  }
3571#endif
3572#ifdef COIN_HAS_CLP
3573  {
3574    CbcOrClpParam p("reallyO!bjectiveScale", "Scale factor to apply to objective in place",
3575      -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE2, 0);
3576    p.setLonghelp("You can set this to -1.0 to test maximization or other to stress code");
3577    p.setDoubleValue(1.0);
3578    parameters.push_back(p);
3579  }
3580  {
3581    CbcOrClpParam p("reallyS!cale", "Scales model in place",
3582      CLP_PARAM_ACTION_REALLY_SCALE, 7, 0);
3583    parameters.push_back(p);
3584  }
3585#endif
3586#ifdef COIN_HAS_CBC
3587  {
3588    CbcOrClpParam p("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts",
3589      "off", CBC_PARAM_STR_REDSPLITCUTS);
3590
3591    p.append("on");
3592    p.append("root");
3593    p.append("ifmove");
3594    p.append("forceOn");
3595    p.setLonghelp(
3596      "These cuts may be expensive to generate. "
3597      CUTS_LONGHELP
3598      " Reference: https://github.com/coin-or/Cgl/wiki/CglRedSplit");
3599    parameters.push_back(p);
3600  }
3601  {
3602    CbcOrClpParam p("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2",
3603      "off", CBC_PARAM_STR_REDSPLIT2CUTS);
3604    p.append("on");
3605    p.append("root");
3606    p.append("longOn");
3607    p.append("longRoot");
3608    p.setLonghelp("This switches on reduce and split  cuts (either at root or in entire tree). \
3609This version is by Giacomo Nannicini based on Francois Margot's version. \
3610Standard setting only uses rows in tableau <= 256, long uses all. \
3611These cuts may be expensive to generate. \
3612See option cuts for more information on the possible values.");
3613    parameters.push_back(p);
3614  }
3615  {
3616    CbcOrClpParam p("residual!CapacityCuts", "Whether to use Residual Capacity cuts",
3617      "off", CBC_PARAM_STR_RESIDCUTS);
3618    p.append("on");
3619    p.append("root");
3620    p.append("ifmove");
3621    p.append("forceOn");
3622    p.setLonghelp(CUTS_LONGHELP
3623      " Reference: https://github.com/coin-or/Cgl/wiki/CglResidualCapacity");
3624
3625    parameters.push_back(p);
3626  }
3627#endif
3628#ifdef COIN_HAS_CLP
3629  {
3630    CbcOrClpParam p("restore!Model", "Restore model from binary file",
3631      CLP_PARAM_ACTION_RESTORE, 7, 1);
3632    p.setLonghelp(
3633      "This reads data save by saveModel from the given file.  It will use the default\
3634 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3635 is initialized to 'default.prob'.");
3636
3637    parameters.push_back(p);
3638  }
3639  {
3640    CbcOrClpParam p("reverse", "Reverses sign of objective",
3641      CLP_PARAM_ACTION_REVERSE, 7, 0);
3642    p.setLonghelp(
3643      "Useful for testing if maximization works correctly");
3644    parameters.push_back(p);
3645  }
3646  {
3647    CbcOrClpParam p("rhs!Scale", "Scale factor to apply to rhs and bounds",
3648      -1.0e20, 1.0e20, CLP_PARAM_DBL_RHSSCALE, 0);
3649    p.setLonghelp(
3650      "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
3651 internally by this amount.  It can also be set by autoscale.  This should not be needed.");
3652    p.setDoubleValue(1.0);
3653    parameters.push_back(p);
3654  }
3655#endif
3656#ifdef COIN_HAS_CBC
3657  {
3658    CbcOrClpParam p("Rens", "Whether to try Relaxation Enforced Neighborhood Search",
3659      "off", CBC_PARAM_STR_RENS);
3660    p.append("on");
3661    p.append("both");
3662    p.append("before");
3663    p.append("200");
3664    p.append("1000");
3665    p.append("10000");
3666    p.append("dj");
3667    p.append("djbefore");
3668    p.append("usesolution");
3669    p.setLonghelp(HEURISTICS_LONGHELP
3670      " Value 'on' just does 50 nodes. 200, 1000, and 10000 does that many nodes.");
3671    parameters.push_back(p);
3672  }
3673  {
3674    CbcOrClpParam p("Rins", "Whether to try Relaxed Induced Neighborhood Search",
3675      "off", CBC_PARAM_STR_RINS);
3676    p.append("on");
3677    p.append("both");
3678    p.append("before");
3679    p.append("often");
3680    p.setLonghelp(HEURISTICS_LONGHELP);
3681    parameters.push_back(p);
3682  }
3683  {
3684    CbcOrClpParam p("round!ingHeuristic", "Whether to use simple (but effective) Rounding heuristic",
3685      "off", CBC_PARAM_STR_ROUNDING);
3686    p.append("on");
3687    p.append("both");
3688    p.append("before");
3689    p.setLonghelp(HEURISTICS_LONGHELP);
3690    parameters.push_back(p);
3691  }
3692#endif
3693  {
3694    CbcOrClpParam p("saveM!odel", "Save model to binary file",
3695      CLP_PARAM_ACTION_SAVE, 7, 1);
3696    p.setLonghelp(
3697      "This will save the problem to the given file name for future use\
3698 by restoreModel.  It will use the default\
3699 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3700 is initialized to 'default.prob'.");
3701    parameters.push_back(p);
3702  }
3703  {
3704    CbcOrClpParam p("saveS!olution", "saves solution to file",
3705      CLP_PARAM_ACTION_SAVESOL);
3706
3707    p.setLonghelp(
3708      "This will write a binary solution file to the given file name.  It will use the default\
3709 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3710 is initialized to 'solution.file'.  To read the file use fread(int) twice to pick up number of rows \
3711and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \
3712activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \
3713If name contains '_fix_read_' then does not write but reads and will fix all variables");
3714    parameters.push_back(p);
3715  }
3716  {
3717    CbcOrClpParam p("scal!ing", "Whether to scale problem",
3718      "off", CLP_PARAM_STR_SCALING);
3719    p.append("equi!librium");
3720    p.append("geo!metric");
3721    p.append("auto!matic");
3722    p.append("dynamic");
3723    p.append("rows!only");
3724    p.setLonghelp(
3725      "Scaling can help in solving problems which might otherwise fail because of lack of\
3726 accuracy.  It can also reduce the number of iterations.  It is not applied if the range\
3727 of elements is small.  When the solution is evaluated in the unscaled problem, it is possible that small primal and/or\
3728 dual infeasibilities occur. "
3729 "Option 'equilibrium' uses the largest element for scaling. "
3730 "Option 'geometric' uses the squareroot of the product of largest and smallest element. "
3731 "Option 'auto' let CLP choose a method that gives the best ratio of the largest element to the smallest one.");
3732    p.setCurrentOption(3); // say auto
3733    parameters.push_back(p);
3734  }
3735#ifndef COIN_HAS_CBC
3736  {
3737    CbcOrClpParam p("sec!onds", "Maximum seconds",
3738      -1.0, 1.0e12, CLP_PARAM_DBL_TIMELIMIT);
3739
3740    p.setLonghelp("After this many seconds clp will act as if maximum iterations had been reached \
3741(if value >=0).");
3742    parameters.push_back(p);
3743  }
3744#else
3745  {
3746    CbcOrClpParam p("sec!onds", "maximum seconds",
3747      -1.0, 1.0e100, CBC_PARAM_DBL_TIMELIMIT_BAB);
3748    p.setLonghelp(
3749      "After this many seconds coin solver will act as if maximum nodes had been reached.");
3750    parameters.push_back(p);
3751  }
3752#endif
3753  {
3754    CbcOrClpParam p("sleep", "for debug",
3755      CLP_PARAM_ACTION_DUMMY, 7, 0);
3756
3757    p.setLonghelp(
3758      "If passed to solver fom ampl, then ampl will wait so that you can copy .nl file for debug.");
3759    parameters.push_back(p);
3760  }
3761#ifdef COIN_HAS_CBC
3762  {
3763    CbcOrClpParam p("slow!cutpasses", "Maximum number of rounds for slower cut generators",
3764      -1, COIN_INT_MAX, CBC_PARAM_INT_MAX_SLOW_CUTS);
3765    p.setLonghelp(
3766      "Some cut generators are fairly slow - this limits the number of times they are tried.\
3767      The cut generators identified as 'may be slow' at present are Lift and project cuts and both versions of Reduce and Split cuts.");
3768    p.setIntValue(10);
3769    parameters.push_back(p);
3770  }
3771#endif
3772#ifdef COIN_HAS_CLP
3773  {
3774    CbcOrClpParam p("slp!Value", "Number of slp passes before primal",
3775      -50000, 50000, CLP_PARAM_INT_SLPVALUE, 1);
3776    p.setLonghelp(
3777      "If you are solving a quadratic problem using primal then it may be helpful to do some \
3778sequential Lps to get a good approximate solution.");
3779    parameters.push_back(p);
3780  }
3781#if CLP_MULTIPLE_FACTORIZATIONS > 0
3782  {
3783    CbcOrClpParam p("small!Factorization", "Whether to use small factorization",
3784      -1, 10000, CBC_PARAM_INT_SMALLFACT, 1);
3785    p.setLonghelp(
3786      "If processed problem <= this use small factorization");
3787    p.setIntValue(-1);
3788    parameters.push_back(p);
3789  }
3790#endif
3791#endif
3792  {
3793    CbcOrClpParam p("solu!tion", "Prints solution to file",
3794      CLP_PARAM_ACTION_SOLUTION);
3795    p.setLonghelp(
3796      "This will write a primitive solution file to the given file name.  It will use the default\
3797 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3798 is initialized to 'stdout'.  The amount of output can be varied using printi!ngOptions or printMask.");
3799    parameters.push_back(p);
3800  }
3801#ifdef COIN_HAS_CLP
3802#ifdef COIN_HAS_CBC
3803  {
3804    CbcOrClpParam p("solv!e", "Solve problem",
3805      CBC_PARAM_ACTION_BAB);
3806         p.setLonghelp(
3807          "If there are no integer variables then this just solves LP.  If there are integer variables \
3808this does branch and cut." );
3809         parameters.push_back( p );
3810  }
3811  {
3812    CbcOrClpParam p("sosO!ptions", "Whether to use SOS from AMPL",  "off", CBC_PARAM_STR_SOS);
3813    p.append("on");
3814    p.setCurrentOption("on");
3815         p.setLonghelp(
3816          "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\
3817 be turned off - this does so." );
3818         parameters.push_back( p );
3819  }
3820  {
3821    CbcOrClpParam p("slog!Level", "Level of detail in (LP) Solver output", -1, 63, CLP_PARAM_INT_SOLVERLOGLEVEL);
3822    p.setLonghelp(
3823      "If 0 then there should be no output in normal circumstances.  1 is probably the best\
3824 value for most uses, while 2 and 3 give more information.  This parameter is only used inside MIP - for Clp use 'log'");
3825    parameters.push_back(p);
3826  }
3827  {
3828     // Due to James Howey
3829     CbcOrClpParam p("sosP!rioritize", "How to deal with SOS priorities",
3830       "off", CBC_PARAM_STR_SOSPRIORITIZE);
3831     p.append("high");
3832     p.append("low");
3833     p.append("orderhigh");
3834     p.append("orderlow");
3835     p.setLonghelp(
3836       "This sets priorities for SOS.  The first two just set priority \
3837    relative to integers.  Orderhigh gives first set highest priority and integers \
3838    a low priority.  Orderlow gives integers high priority then SOS in order.");
3839    parameters.push_back(p);
3840  }
3841#else
3842  // allow solve as synonym for possible dual
3843  {
3844    CbcOrClpParam p("solv!e", "Solve problem using dual simplex (probably)",
3845      CLP_PARAM_ACTION_EITHERSIMPLEX);
3846    p.setLonghelp(
3847      "Just so can use solve for clp as well as in cbc");
3848    parameters.push_back(p);
3849  }
3850#endif
3851#endif
3852#ifdef COIN_HAS_CLP
3853  {
3854    CbcOrClpParam p("spars!eFactor", "Whether factorization treated as sparse",
3855      "on", CLP_PARAM_STR_SPARSEFACTOR, 7, 0);
3856    p.append("off");
3857    parameters.push_back(p);
3858  }
3859  {
3860    CbcOrClpParam p("special!Options", "Dubious options for Simplex - see ClpSimplex.hpp",
3861      0, COIN_INT_MAX, CLP_PARAM_INT_SPECIALOPTIONS, 0);
3862    parameters.push_back(p);
3863  }
3864  {
3865    CbcOrClpParam p("sprint!Crash", "Whether to try sprint crash",
3866      -1, 5000000, CLP_PARAM_INT_SPRINT);
3867    p.setLonghelp(
3868      "For long and thin problems this method may solve a series of small problems\
3869 created by taking a subset of the columns.  The idea as 'Sprint' was introduced by J. Forrest after\
3870 an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
3871  CPLEX calls it 'sifting'.  -1 lets CLP automatically choose the number of passes, 0 is off, n is number of passes");
3872    parameters.push_back(p);
3873  }
3874  {
3875    CbcOrClpParam p("stat!istics", "Print some statistics",
3876      CLP_PARAM_ACTION_STATISTICS);
3877    p.setLonghelp(
3878      "This command prints some statistics for the current model.\
3879 If log level >1 then more is printed.\
3880 These are for presolved model if presolve on (and unscaled).");
3881    parameters.push_back(p);
3882  }
3883#endif
3884  {
3885    CbcOrClpParam p("stop", "Stops clp execution",
3886      CLP_PARAM_ACTION_EXIT);
3887    p.setLonghelp(
3888      "This stops the execution of Clp, end, exit, quit and stop are synonyms");
3889    parameters.push_back(p);
3890  }
3891#ifdef COIN_HAS_CBC
3892  {
3893    CbcOrClpParam p("strat!egy", "Switches on groups of features",
3894      0, 2, CBC_PARAM_INT_STRATEGY);
3895    p.setLonghelp(
3896      "This turns on newer features. \
3897Use 0 for easy problems, 1 is default, 2 is aggressive. \
38981 uses Gomory cuts with a tolerance of 0.01 at the root node, \
3899does a possible restart after 100 nodes if many variables could be fixed, \
3900activates a diving and RINS heuristic, and makes the feasibility pump \
3901more aggressive."); // This does not apply to unit tests (where 'experiment' may have similar effects
3902    p.setIntValue(1);
3903    parameters.push_back(p);
3904  }
3905#ifdef CBC_KEEP_DEPRECATED
3906  {
3907    CbcOrClpParam p("strengthen", "Create strengthened problem",
3908      CBC_PARAM_ACTION_STRENGTHEN, 3);
3909    p.setLonghelp(
3910      "This creates a new problem by applying the root node cuts.  All tight constraints \
3911will be in resulting problem");
3912    parameters.push_back(p);
3913  }
3914#endif
3915  {
3916    CbcOrClpParam p("strong!Branching", "Number of variables to look at in strong branching",
3917      0, COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING);
3918    p.setIntValue(20);
3919    p.setLonghelp(
3920      "In order to decide which variable to branch on, the code will choose up to this number \
3921of unsatisfied variables to try minimal up and down branches on.  Then the most effective one is chosen. \
3922If a variable is branched on many times then the previous average up and down costs may be used - \
3923see also option trustPseudoCosts.");
3924    parameters.push_back(p);
3925  }
3926#endif
3927#ifdef COIN_HAS_CLP
3928  {
3929    CbcOrClpParam p("subs!titution", "How long a column to substitute for in presolve",
3930      0, 10000, CLP_PARAM_INT_SUBSTITUTION, 0);
3931    p.setLonghelp(
3932      "Normally Presolve gets rid of 'free' variables when there are no more than 3 \
3933 variables in column.  If you increase this the number of rows may decrease but number of \
3934 elements may increase.");
3935    parameters.push_back(p);
3936  }
3937#endif
3938#ifdef COIN_HAS_CBC
3939  {
3940    CbcOrClpParam p("testO!si", "Test OsiObject stuff",
3941      -1, COIN_INT_MAX, CBC_PARAM_INT_TESTOSI, 0);
3942    parameters.push_back(p);
3943  }
3944#endif
3945#ifdef CBC_THREAD
3946  {
3947    CbcOrClpParam p("thread!s", "Number of threads to try and use",
3948      -100, 100000, CBC_PARAM_INT_THREADS, 1);
3949    p.setIntValue(0);
3950    p.setLonghelp(
3951      "To use multiple threads, set threads to number wanted.  It may be better \
3952to use one or two more than number of cpus available.  If 100+n then n threads and \
3953search is repeatable (maybe be somewhat slower), \
3954if 200+n use threads for root cuts, 400+n threads used in sub-trees.");
3955    parameters.push_back(p);
3956  }
3957#endif
3958#ifdef COIN_HAS_CBC
3959  {
3960    CbcOrClpParam p("tighten!Factor", "Tighten bounds using this times largest \
3961activity at continuous solution",
3962      1.0e-3, 1.0e20, CBC_PARAM_DBL_TIGHTENFACTOR, 0);
3963    p.setLonghelp(
3964      "This sleazy trick can help on some problems.");
3965    parameters.push_back(p);
3966  }
3967
3968#endif
3969#ifdef COIN_HAS_CLP
3970  {
3971    CbcOrClpParam p("tightLP", "Poor person's preSolve for now",
3972      CLP_PARAM_ACTION_TIGHTEN, 7, 0);
3973    parameters.push_back(p);
3974  }
3975#endif
3976  {
3977    CbcOrClpParam p("timeM!ode", "Whether to use CPU or elapsed time",
3978      "cpu", CLP_PARAM_STR_TIME_MODE);
3979    p.append("elapsed");
3980    p.setLonghelp(
3981      "cpu uses CPU time for stopping, while elapsed uses elapsed time. \
3982(On Windows, elapsed time is always used).");
3983    parameters.push_back(p);
3984  }
3985#ifdef COIN_HAS_CBC
3986  {
3987    CbcOrClpParam p("trust!PseudoCosts", "Number of branches before we trust pseudocosts",
3988      -3, 2000000000, CBC_PARAM_INT_NUMBERBEFORE);
3989    p.setLonghelp(
3990      "Using strong branching computes pseudo-costs.  This parameter determines after how many branches for a variable we just \
3991trust the pseudo costs and do not do any more strong branching.");
3992    p.setIntValue(10);
3993    parameters.push_back(p);
3994  }
3995#endif
3996#ifdef COIN_HAS_CBC
3997  {
3998    CbcOrClpParam p("tune!PreProcess", "Dubious tuning parameters",
3999      0, 2000000000, CLP_PARAM_INT_PROCESSTUNE, 1);
4000    p.setLonghelp(
4001      "Format aabbcccc - \n If aa then this is number of major passes (i.e. with presolve) \n \
4002If bb and bb>0 then this is number of minor passes (if unset or 0 then 10) \n \
4003cccc is bit set \n 0 - 1 Heavy probing \n 1 - 2 Make variables integer if possible (if obj value)\n \
40042 - 4 As above but even if zero objective value\n \
40057 - 128 Try and create cliques\n 8 - 256 If all +1 try hard for dominated rows\n \
400610 - 1024 Use a larger feasibility tolerance in presolve\n \
400711 - 2048 Try probing before creating cliques\n \
400812 - 4096 Switch off duplicate column checking for integers \n \n \
4009     Now aa 99 has special meaning i.e. just one simple presolve.");
4010    parameters.push_back(p);
4011  }
4012  {
4013    CbcOrClpParam p("two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts",
4014      "off", CBC_PARAM_STR_TWOMIRCUTS);
4015    p.append("on");
4016    p.append("root");
4017    p.append("ifmove");
4018    p.append("forceOn");
4019    p.append("onglobal");
4020    p.append("forceandglobal");
4021    p.append("forceLongOn");
4022    p.setLonghelp(CUTS_LONGHELP
4023      " Reference: https://github.com/coin-or/Cgl/wiki/CglTwomir");
4024    parameters.push_back(p);
4025  }
4026#endif
4027  {
4028    CbcOrClpParam p("unitTest", "Do unit test",
4029      CLP_PARAM_ACTION_UNITTEST, 3, 1);
4030    p.setLonghelp(
4031      "This exercises the unit test for clp");
4032    parameters.push_back(p);
4033  }
4034  {
4035    CbcOrClpParam p("userClp", "Hand coded Clp stuff",
4036      CLP_PARAM_ACTION_USERCLP, 0, 0);
4037    p.setLonghelp(
4038      "There are times e.g. when using AMPL interface when you may wish to do something unusual.  \
4039Look for USERCLP in main driver and modify sample code.");
4040    parameters.push_back(p);
4041  }
4042#ifdef COIN_HAS_CBC
4043  {
4044    CbcOrClpParam p("userCbc", "Hand coded Cbc stuff",
4045      CBC_PARAM_ACTION_USERCBC, 0, 0);
4046    p.setLonghelp(
4047      "There are times e.g. when using AMPL interface when you may wish to do something unusual.  \
4048Look for USERCBC in main driver and modify sample code. \
4049It is possible you can get same effect by using example driver4.cpp.");
4050    parameters.push_back(p);
4051  }
4052#endif
4053#ifdef COIN_AVX2
4054  {
4055    CbcOrClpParam p("vector!Mode", "Try and use vector instructions",
4056      0, 11, CLP_PARAM_INT_VECTOR_MODE);
4057    p.setLonghelp(
4058      "At present only for Intel architectures - but could be extended.  \
4059Uses avx2 or avx512 instructions. Uses different storage for matrix - can be \
4060of benefit without instruction set on some problems.  \
4061Being lazy I have used 10 to switch on a pool matrix (11 may come later)");
4062    p.setIntValue(0);
4063    parameters.push_back(p);
4064  }
4065#endif
4066#ifdef COIN_HAS_CBC
4067  {
4068    CbcOrClpParam p("Vnd!VariableNeighborhoodSearch", "Whether to try Variable Neighborhood Search",
4069      "off", CBC_PARAM_STR_VND);
4070    p.append("on");
4071    p.append("both");
4072    p.append("before");
4073    p.append("intree");
4074    p.setLonghelp(HEURISTICS_LONGHELP);
4075    parameters.push_back(p);
4076  }
4077#endif
4078  {
4079    CbcOrClpParam p("vector", "Whether to use vector? Form of matrix in simplex",
4080      "off", CLP_PARAM_STR_VECTOR, 7, 0);
4081    p.append("on");
4082    p.setLonghelp(
4083      "If this is on ClpPackedMatrix uses extra column copy in odd format.");
4084    parameters.push_back(p);
4085  }
4086  {
4087    CbcOrClpParam p("verbose", "Switches on longer help on single ?",
4088      0, 31, CLP_PARAM_INT_VERBOSE, 0);
4089    p.setLonghelp(
4090      "Set to 1 to get short help with ? list, 2 to get long help, 3 for both.  (add 4 to just get ampl ones).");
4091    p.setIntValue(0);
4092    parameters.push_back(p);
4093  }
4094#ifdef COIN_HAS_CBC
4095  {
4096    CbcOrClpParam p("vub!heuristic", "Type of VUB heuristic",
4097      -2, 20, CBC_PARAM_INT_VUBTRY, 0);
4098    p.setLonghelp(
4099      "This heuristic tries and fix some integer variables.");
4100    p.setIntValue(-1);
4101    parameters.push_back(p);
4102  }
4103  {
4104    CbcOrClpParam p("zero!HalfCuts", "Whether to use zero half cuts",
4105      "off", CBC_PARAM_STR_ZEROHALFCUTS);
4106    p.append("on");
4107    p.append("root");
4108    p.append("ifmove");
4109    p.append("forceOn");
4110    p.append("onglobal");
4111    p.setLonghelp(CUTS_LONGHELP
4112      " This implementation was written by Alberto Caprara.");
4113    parameters.push_back(p);
4114  }
4115#endif
4116  {
4117    CbcOrClpParam p("zeroT!olerance", "Kill all coefficients \
4118whose absolute value is less than this value",
4119      1.0e-100, 1.0e-5, CLP_PARAM_DBL_ZEROTOLERANCE);
4120    p.setLonghelp(
4121      "This applies to reading mps files (and also lp files \
4122if KILL_ZERO_READLP defined)");
4123    p.setDoubleValue(1.0e-20);
4124    parameters.push_back(p);
4125  }
4126}
4127// Given a parameter type - returns its number in list
4128int whichParam(const CbcOrClpParameterType &name,
4129  const std::vector< CbcOrClpParam > &parameters)
4130{
4131  for (int i = 0; i < (int)parameters.size(); i++) {
4132    if (parameters[i].type() == name)
4133      return i;
4134  }
4135  return std::numeric_limits< int >::max(); // should not arrive here
4136}
4137#ifdef COIN_HAS_CLP
4138/* Restore a solution from file.
4139   mode 0 normal, 1 swap rows and columns and primal and dual
4140   if 2 set then also change signs
4141*/
4142void restoreSolution(ClpSimplex *lpSolver, std::string fileName, int mode)
4143{
4144  FILE *fp = fopen(fileName.c_str(), "rb");
4145  if (fp) {
4146    int numberRows = lpSolver->numberRows();
4147    int numberColumns = lpSolver->numberColumns();
4148    int numberRowsFile;
4149    int numberColumnsFile;
4150    double objectiveValue;
4151    size_t nRead;
4152    nRead = fread(&numberRowsFile, sizeof(int), 1, fp);
4153    if (nRead != 1)
4154      throw("Error in fread");
4155    nRead = fread(&numberColumnsFile, sizeof(int), 1, fp);
4156    if (nRead != 1)
4157      throw("Error in fread");
4158    nRead = fread(&objectiveValue, sizeof(double), 1, fp);
4159    if (nRead != 1)
4160      throw("Error in fread");
4161    double *dualRowSolution = lpSolver->dualRowSolution();
4162    double *primalRowSolution = lpSolver->primalRowSolution();
4163    double *dualColumnSolution = lpSolver->dualColumnSolution();
4164    double *primalColumnSolution = lpSolver->primalColumnSolution();
4165    if (mode) {
4166      // swap
4167      int k = numberRows;
4168      numberRows = numberColumns;
4169      numberColumns = k;
4170      double *temp;
4171      temp = dualRowSolution;
4172      dualRowSolution = primalColumnSolution;
4173      primalColumnSolution = temp;
4174      temp = dualColumnSolution;
4175      dualColumnSolution = primalRowSolution;
4176      primalRowSolution = temp;
4177    }
4178    if (numberRows > numberRowsFile || numberColumns > numberColumnsFile) {
4179      std::cout << "Mismatch on rows and/or columns - giving up" << std::endl;
4180    } else {
4181      lpSolver->setObjectiveValue(objectiveValue);
4182      if (numberRows == numberRowsFile && numberColumns == numberColumnsFile) {
4183        nRead = fread(primalRowSolution, sizeof(double), numberRows, fp);
4184        if (nRead != static_cast< size_t >(numberRows))
4185          throw("Error in fread");
4186        nRead = fread(dualRowSolution, sizeof(double), numberRows, fp);
4187        if (nRead != static_cast< size_t >(numberRows))
4188          throw("Error in fread");
4189        nRead = fread(primalColumnSolution, sizeof(double), numberColumns, fp);
4190        if (nRead != static_cast< size_t >(numberColumns))
4191          throw("Error in fread");
4192        nRead = fread(dualColumnSolution, sizeof(double), numberColumns, fp);
4193        if (nRead != static_cast< size_t >(numberColumns))
4194          throw("Error in fread");
4195      } else {
4196        std::cout << "Mismatch on rows and/or columns - truncating" << std::endl;
4197        double *temp = new double[CoinMax(numberRowsFile, numberColumnsFile)];
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, primalRowSolution);
4202        nRead = fread(temp, sizeof(double), numberRowsFile, fp);
4203        if (nRead != static_cast< size_t >(numberRowsFile))
4204          throw("Error in fread");
4205        CoinMemcpyN(temp, numberRows, dualRowSolution);
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, primalColumnSolution);
4210        nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
4211        if (nRead != static_cast< size_t >(numberColumnsFile))
4212          throw("Error in fread");
4213        CoinMemcpyN(temp, numberColumns, dualColumnSolution);
4214        delete[] temp;
4215      }
4216      if (mode == 3) {
4217        int i;
4218        for (i = 0; i < numberRows; i++) {
4219          primalRowSolution[i] = -primalRowSolution[i];
4220          dualRowSolution[i] = -dualRowSolution[i];
4221        }
4222        for (i = 0; i < numberColumns; i++) {
4223          primalColumnSolution[i] = -primalColumnSolution[i];
4224          dualColumnSolution[i] = -dualColumnSolution[i];
4225        }
4226      }
4227    }
4228    fclose(fp);
4229  } else {
4230    std::cout << "Unable to open file " << fileName << std::endl;
4231  }
4232}
4233// Dump a solution to file
4234void saveSolution(const ClpSimplex *lpSolver, std::string fileName)
4235{
4236  if (strstr(fileName.c_str(), "_fix_read_")) {
4237    FILE *fp = fopen(fileName.c_str(), "rb");
4238    if (fp) {
4239      ClpSimplex *solver = const_cast< ClpSimplex * >(lpSolver);
4240      restoreSolution(solver, fileName, 0);
4241      // fix all
4242      int logLevel = solver->logLevel();
4243      int iColumn;
4244      int numberColumns = solver->numberColumns();
4245      double *primalColumnSolution = solver->primalColumnSolution();
4246      double *columnLower = solver->columnLower();
4247      double *columnUpper = solver->columnUpper();
4248      for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4249        double value = primalColumnSolution[iColumn];
4250        if (value > columnUpper[iColumn]) {
4251          if (value > columnUpper[iColumn] + 1.0e-6 && logLevel > 1)
4252            printf("%d value of %g - bounds %g %g\n",
4253              iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
4254          value = columnUpper[iColumn];
4255        } else if (value < columnLower[iColumn]) {
4256          if (value < columnLower[iColumn] - 1.0e-6 && logLevel > 1)
4257            printf("%d value of %g - bounds %g %g\n",
4258              iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
4259          value = columnLower[iColumn];
4260        }
4261        columnLower[iColumn] = value;
4262        columnUpper[iColumn] = value;
4263      }
4264      return;
4265    }
4266  }
4267  FILE *fp = fopen(fileName.c_str(), "wb");
4268  if (fp) {
4269    int numberRows = lpSolver->numberRows();
4270    int numberColumns = lpSolver->numberColumns();
4271    double objectiveValue = lpSolver->objectiveValue();
4272    size_t nWrite;
4273    nWrite = fwrite(&numberRows, sizeof(int), 1, fp);
4274    if (nWrite != 1)
4275      throw("Error in fwrite");
4276    nWrite = fwrite(&numberColumns, sizeof(int), 1, fp);
4277    if (nWrite != 1)
4278      throw("Error in fwrite");
4279    nWrite = fwrite(&objectiveValue, sizeof(double), 1, fp);
4280    if (nWrite != 1)
4281      throw("Error in fwrite");
4282    double *dualRowSolution = lpSolver->dualRowSolution();
4283    double *primalRowSolution = lpSolver->primalRowSolution();
4284    nWrite = fwrite(primalRowSolution, sizeof(double), numberRows, fp);
4285    if (nWrite != static_cast< size_t >(numberRows))
4286      throw("Error in fwrite");
4287    nWrite = fwrite(dualRowSolution, sizeof(double), numberRows, fp);
4288    if (nWrite != static_cast< size_t >(numberRows))
4289      throw("Error in fwrite");
4290    double *dualColumnSolution = lpSolver->dualColumnSolution();
4291    double *primalColumnSolution = lpSolver->primalColumnSolution();
4292    nWrite = fwrite(primalColumnSolution, sizeof(double), numberColumns, fp);
4293    if (nWrite != static_cast< size_t >(numberColumns))
4294      throw("Error in fwrite");
4295    nWrite = fwrite(dualColumnSolution, sizeof(double), numberColumns, fp);
4296    if (nWrite != static_cast< size_t >(numberColumns))
4297      throw("Error in fwrite");
4298    fclose(fp);
4299  } else {
4300    std::cout << "Unable to open file " << fileName << std::endl;
4301  }
4302}
4303#endif
4304
4305/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
4306*/
Note: See TracBrowser for help on using the repository browser.