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

Last change on this file since 2463 was 2463, checked in by stefan, 7 weeks ago

increase max value for bab timelimit (cbc)

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