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

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

fix getting clp-presolve-tolerance

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