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

Last change on this file since 2389 was 2389, checked in by unxusr, 3 months ago

store Cbc and Clp parameters in a vector to simplify code

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