source: stable/1.17/Clp/src/CbcOrClpParam.cpp @ 2449

Last change on this file since 2449 was 2449, checked in by stefan, 3 months ago

sync with trunk

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 145.8 KB
Line 
1/* $Id: CbcOrClpParam.cpp 2449 2019-04-08 03:34:28Z stefan $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include "CoinPragma.hpp"
7#include "CoinTime.hpp"
8#include "CbcOrClpParam.hpp"
9
10#include <string>
11#include <iostream>
12#include <cassert>
13
14#ifdef COIN_HAS_CBC
15#ifdef COIN_HAS_CLP
16#include "OsiClpSolverInterface.hpp"
17#include "ClpSimplex.hpp"
18#endif
19#include "CbcModel.hpp"
20#endif
21#include "CoinHelperFunctions.hpp"
22#ifdef COIN_HAS_CLP
23#include "ClpSimplex.hpp"
24#include "ClpFactorization.hpp"
25#endif
26#ifdef COIN_HAS_READLINE
27#include <readline/readline.h>
28#include <readline/history.h>
29#endif
30#ifdef COIN_HAS_CBC
31// from CoinSolve
32static char coin_prompt[] = "Coin:";
33#else
34static char coin_prompt[] = "Clp:";
35#endif
36#ifdef CLP_CILK
37#ifndef CBC_THREAD
38#define CBC_THREAD
39#endif
40#endif
41#if defined(COIN_HAS_WSMP) && !defined(USE_EKKWSSMP)
42#ifndef CBC_THREAD
43#define CBC_THREAD
44#endif
45#endif
46#include "ClpConfig.h"
47#ifdef CLP_HAS_ABC
48#include "AbcCommon.hpp"
49#endif
50static bool doPrinting = true;
51static std::string afterEquals = "";
52static char printArray[200];
53#if COIN_INT_MAX == 0
54#undef COIN_INT_MAX
55#define COIN_INT_MAX 2147483647
56#endif
57#if FLUSH_PRINT_BUFFER > 2
58int coinFlushBufferFlag = 0;
59#endif
60void setCbcOrClpPrinting(bool yesNo)
61{
62  doPrinting = yesNo;
63}
64//#############################################################################
65// Constructors / Destructor / Assignment
66//#############################################################################
67
68//-------------------------------------------------------------------
69// Default Constructor
70//-------------------------------------------------------------------
71CbcOrClpParam::CbcOrClpParam()
72  : type_(CBC_PARAM_NOTUSED_INVALID)
73  , lowerDoubleValue_(0.0)
74  , upperDoubleValue_(0.0)
75  , lowerIntValue_(0)
76  , upperIntValue_(0)
77  , lengthName_(0)
78  , lengthMatch_(0)
79  , definedKeyWords_()
80  , name_()
81  , shortHelp_()
82  , longHelp_()
83  , action_(CBC_PARAM_NOTUSED_INVALID)
84  , currentKeyWord_(-1)
85  , display_(0)
86  , intValue_(-1)
87  , doubleValue_(-1.0)
88  , stringValue_("")
89  , whereUsed_(7)
90  , fakeKeyWord_(-1)
91  , fakeValue_(0)
92{
93}
94// Other constructors
95CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
96  double lower, double upper, CbcOrClpParameterType type,
97  int display)
98  : type_(type)
99  , lowerIntValue_(0)
100  , upperIntValue_(0)
101  , definedKeyWords_()
102  , name_(name)
103  , shortHelp_(help)
104  , longHelp_()
105  , action_(type)
106  , currentKeyWord_(-1)
107  , display_(display)
108  , intValue_(-1)
109  , doubleValue_(-1.0)
110  , stringValue_("")
111  , whereUsed_(7)
112  , fakeKeyWord_(-1)
113  , fakeValue_(0)
114{
115  lowerDoubleValue_ = lower;
116  upperDoubleValue_ = upper;
117  gutsOfConstructor();
118}
119CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
120  int lower, int upper, CbcOrClpParameterType type,
121  int display)
122  : type_(type)
123  , lowerDoubleValue_(0.0)
124  , upperDoubleValue_(0.0)
125  , definedKeyWords_()
126  , name_(name)
127  , shortHelp_(help)
128  , longHelp_()
129  , action_(type)
130  , currentKeyWord_(-1)
131  , display_(display)
132  , intValue_(-1)
133  , doubleValue_(-1.0)
134  , stringValue_("")
135  , whereUsed_(7)
136  , fakeKeyWord_(-1)
137  , fakeValue_(0)
138{
139  gutsOfConstructor();
140  lowerIntValue_ = lower;
141  upperIntValue_ = upper;
142}
143// Other strings will be added by append
144CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
145  std::string firstValue,
146  CbcOrClpParameterType type, int whereUsed,
147  int display)
148  : type_(type)
149  , lowerDoubleValue_(0.0)
150  , upperDoubleValue_(0.0)
151  , lowerIntValue_(0)
152  , upperIntValue_(0)
153  , definedKeyWords_()
154  , name_(name)
155  , shortHelp_(help)
156  , longHelp_()
157  , action_(type)
158  , currentKeyWord_(0)
159  , display_(display)
160  , intValue_(-1)
161  , doubleValue_(-1.0)
162  , stringValue_("")
163  , whereUsed_(whereUsed)
164  , fakeKeyWord_(-1)
165  , fakeValue_(0)
166{
167  gutsOfConstructor();
168  definedKeyWords_.push_back(firstValue);
169}
170// Action
171CbcOrClpParam::CbcOrClpParam(std::string name, std::string help,
172  CbcOrClpParameterType type, int whereUsed,
173  int display)
174  : type_(type)
175  , lowerDoubleValue_(0.0)
176  , upperDoubleValue_(0.0)
177  , lowerIntValue_(0)
178  , upperIntValue_(0)
179  , definedKeyWords_()
180  , name_(name)
181  , shortHelp_(help)
182  , longHelp_()
183  , action_(type)
184  , currentKeyWord_(-1)
185  , display_(display)
186  , intValue_(-1)
187  , doubleValue_(-1.0)
188  , stringValue_("")
189  , fakeKeyWord_(-1)
190  , fakeValue_(0)
191{
192  whereUsed_ = whereUsed;
193  gutsOfConstructor();
194}
195
196//-------------------------------------------------------------------
197// Copy constructor
198//-------------------------------------------------------------------
199CbcOrClpParam::CbcOrClpParam(const CbcOrClpParam &rhs)
200{
201  type_ = rhs.type_;
202  lowerDoubleValue_ = rhs.lowerDoubleValue_;
203  upperDoubleValue_ = rhs.upperDoubleValue_;
204  lowerIntValue_ = rhs.lowerIntValue_;
205  upperIntValue_ = rhs.upperIntValue_;
206  lengthName_ = rhs.lengthName_;
207  lengthMatch_ = rhs.lengthMatch_;
208  definedKeyWords_ = rhs.definedKeyWords_;
209  name_ = rhs.name_;
210  shortHelp_ = rhs.shortHelp_;
211  longHelp_ = rhs.longHelp_;
212  action_ = rhs.action_;
213  currentKeyWord_ = rhs.currentKeyWord_;
214  display_ = rhs.display_;
215  intValue_ = rhs.intValue_;
216  doubleValue_ = rhs.doubleValue_;
217  stringValue_ = rhs.stringValue_;
218  whereUsed_ = rhs.whereUsed_;
219  fakeKeyWord_ = rhs.fakeKeyWord_;
220  fakeValue_ = rhs.fakeValue_;
221}
222
223//-------------------------------------------------------------------
224// Destructor
225//-------------------------------------------------------------------
226CbcOrClpParam::~CbcOrClpParam()
227{
228}
229
230//----------------------------------------------------------------
231// Assignment operator
232//-------------------------------------------------------------------
233CbcOrClpParam &
234CbcOrClpParam::operator=(const CbcOrClpParam &rhs)
235{
236  if (this != &rhs) {
237    type_ = rhs.type_;
238    lowerDoubleValue_ = rhs.lowerDoubleValue_;
239    upperDoubleValue_ = rhs.upperDoubleValue_;
240    lowerIntValue_ = rhs.lowerIntValue_;
241    upperIntValue_ = rhs.upperIntValue_;
242    lengthName_ = rhs.lengthName_;
243    lengthMatch_ = rhs.lengthMatch_;
244    definedKeyWords_ = rhs.definedKeyWords_;
245    name_ = rhs.name_;
246    shortHelp_ = rhs.shortHelp_;
247    longHelp_ = rhs.longHelp_;
248    action_ = rhs.action_;
249    currentKeyWord_ = rhs.currentKeyWord_;
250    display_ = rhs.display_;
251    intValue_ = rhs.intValue_;
252    doubleValue_ = rhs.doubleValue_;
253    stringValue_ = rhs.stringValue_;
254    whereUsed_ = rhs.whereUsed_;
255    fakeKeyWord_ = rhs.fakeKeyWord_;
256    fakeValue_ = rhs.fakeValue_;
257  }
258  return *this;
259}
260void CbcOrClpParam::gutsOfConstructor()
261{
262  std::string::size_type shriekPos = name_.find('!');
263  lengthName_ = static_cast< unsigned int >(name_.length());
264  if (shriekPos == std::string::npos) {
265    //does not contain '!'
266    lengthMatch_ = lengthName_;
267  } else {
268    lengthMatch_ = static_cast< unsigned int >(shriekPos);
269    name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1);
270    lengthName_--;
271  }
272}
273// Sets value of fake keyword to current size of keywords
274void CbcOrClpParam::setFakeKeyWord(int fakeValue)
275{
276  fakeKeyWord_ = static_cast< int >(definedKeyWords_.size());
277  assert(fakeKeyWord_ > 0);
278  fakeValue_ = fakeValue;
279  assert(fakeValue_ >= 0);
280}
281/* Returns current parameter option position
282   but if fake keyword returns fakeValue_
283*/
284int CbcOrClpParam::currentOptionAsInteger() const
285{
286  int fakeInteger;
287  return currentOptionAsInteger(fakeInteger);
288}
289/* Returns current parameter option position
290   but if fake keyword returns fakeValue_ and sets
291   fakeInteger to value
292*/
293int CbcOrClpParam::currentOptionAsInteger(int &fakeInteger) const
294{
295  fakeInteger = -COIN_INT_MAX;
296  if (fakeKeyWord_ < 0) {
297    return currentKeyWord_;
298  } else if (currentKeyWord_ >= 0 && currentKeyWord_ < fakeKeyWord_) {
299    return currentKeyWord_;
300  } else {
301    // fake
302    if (currentKeyWord_ < 0)
303      fakeInteger = currentKeyWord_ + 1000;
304    else
305      fakeInteger = currentKeyWord_ - 1000;
306    return fakeValue_;
307  }
308}
309// Returns length of name for printing
310int CbcOrClpParam::lengthMatchName() const
311{
312  if (lengthName_ == lengthMatch_)
313    return lengthName_;
314  else
315    return lengthName_ + 2;
316}
317// Insert string (only valid for keywords)
318void CbcOrClpParam::append(std::string keyWord)
319{
320  definedKeyWords_.push_back(keyWord);
321}
322
323int CbcOrClpParam::matches(std::string input) const
324{
325  // look up strings to do more elegantly
326  if (input.length() > lengthName_) {
327    return 0;
328  } else {
329    unsigned int i;
330    for (i = 0; i < input.length(); i++) {
331      if (tolower(name_[i]) != tolower(input[i]))
332        break;
333    }
334    if (i < input.length()) {
335      return 0;
336    } else if (i >= lengthMatch_) {
337      return 1;
338    } else {
339      // matched but too short
340      return 2;
341    }
342  }
343}
344// Returns name which could match
345std::string
346CbcOrClpParam::matchName() const
347{
348  if (lengthMatch_ == lengthName_)
349    return name_;
350  else
351    return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + ")";
352}
353
354// Returns parameter option which matches (-1 if none)
355int CbcOrClpParam::parameterOption(std::string check) const
356{
357  int numberItems = static_cast< int >(definedKeyWords_.size());
358  if (!numberItems) {
359    return -1;
360  } else {
361    int whichItem = 0;
362    unsigned int it;
363    for (it = 0; it < definedKeyWords_.size(); it++) {
364      std::string thisOne = definedKeyWords_[it];
365      std::string::size_type shriekPos = thisOne.find('!');
366      size_t length1 = thisOne.length();
367      size_t length2 = length1;
368      if (shriekPos != std::string::npos) {
369        //contains '!'
370        length2 = shriekPos;
371        thisOne = thisOne.substr(0, shriekPos) + thisOne.substr(shriekPos + 1);
372        length1 = thisOne.length();
373      }
374      if (check.length() <= length1 && length2 <= check.length()) {
375        unsigned int i;
376        for (i = 0; i < check.length(); i++) {
377          if (tolower(thisOne[i]) != tolower(check[i]))
378            break;
379        }
380        if (i < check.length()) {
381          whichItem++;
382        } else if (i >= length2) {
383          break;
384        }
385      } else {
386        whichItem++;
387      }
388    }
389    if (whichItem < numberItems) {
390      return whichItem;
391    } else {
392      if (fakeKeyWord_ <= 0)
393        return -1;
394      // allow plus or minus
395      int n;
396      if (check.substr(0, 4) == "plus" || check.substr(0, 4) == "PLUS") {
397        n = 4;
398      } else if (check.substr(0, 5) == "minus" || check.substr(0, 5) == "MINUS") {
399        n = 5;
400      } else {
401        return -1;
402      }
403      int value = 0;
404      std::string field = check.substr(n);
405      if (field != "EOL") {
406        const char *start = field.c_str();
407        char *endPointer = NULL;
408        // check valid
409        value = static_cast< int >(strtol(start, &endPointer, 10));
410        if (*endPointer != '\0') {
411          return -1;
412        }
413        if (n == 4)
414          return value + 1000;
415        else
416          return -value - 1000;
417      } else {
418        return -1;
419      }
420    }
421  }
422}
423// Prints parameter options
424void CbcOrClpParam::printOptions() const
425{
426  std::cout << "<Possible options for " << name_ << " are:";
427  unsigned int it;
428  for (it = 0; it < definedKeyWords_.size(); it++) {
429    std::string thisOne = definedKeyWords_[it];
430    std::string::size_type shriekPos = thisOne.find('!');
431    if (shriekPos != std::string::npos) {
432      //contains '!'
433      thisOne = thisOne.substr(0, shriekPos) + "(" + thisOne.substr(shriekPos + 1) + ")";
434    }
435    std::cout << " " << thisOne;
436  }
437  assert(currentKeyWord_ >= 0 && currentKeyWord_ < static_cast< int >(definedKeyWords_.size()));
438  std::string current = definedKeyWords_[currentKeyWord_];
439  std::string::size_type shriekPos = current.find('!');
440  if (shriekPos != std::string::npos) {
441    //contains '!'
442    current = current.substr(0, shriekPos) + "(" + current.substr(shriekPos + 1) + ")";
443  }
444  std::cout << ";\n\tcurrent  " << current << ">" << std::endl;
445}
446// Print action and string
447void CbcOrClpParam::printString() const
448{
449  if (name_ == "directory")
450    std::cout << "Current working directory is " << stringValue_ << std::endl;
451  else if (name_.substr(0, 6) == "printM")
452    std::cout << "Current value of printMask is " << stringValue_ << std::endl;
453  else
454    std::cout << "Current default (if $ as parameter) for " << name_
455              << " is " << stringValue_ << std::endl;
456}
457void CoinReadPrintit(const char *input)
458{
459  int length = static_cast< int >(strlen(input));
460  char temp[101];
461  int i;
462  int n = 0;
463  for (i = 0; i < length; i++) {
464    if (input[i] == '\n') {
465      temp[n] = '\0';
466      std::cout << temp << std::endl;
467      n = 0;
468    } else if (n >= 65 && input[i] == ' ') {
469      temp[n] = '\0';
470      std::cout << temp << std::endl;
471      n = 0;
472    } else if (n || input[i] != ' ') {
473      temp[n++] = input[i];
474    }
475  }
476  if (n) {
477    temp[n] = '\0';
478    std::cout << temp << std::endl;
479  }
480}
481// Print Long help
482void CbcOrClpParam::printLongHelp() const
483{
484  if (type_ >= 1 && type_ < 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    p.setIntValue(1057);
2819    parameters.push_back(p);
2820  }
2821  {
2822    CbcOrClpParam p("more!MipOptions", "More dubious options for mip",
2823      -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0);
2824    parameters.push_back(p);
2825  }
2826  {
2827    CbcOrClpParam p("more2!MipOptions", "More more dubious options for mip",
2828      -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMOREMIPOPTIONS, 0);
2829    p.setIntValue(0);
2830    parameters.push_back(p);
2831  }
2832  {
2833    CbcOrClpParam p("mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts",
2834      "off", CBC_PARAM_STR_MIXEDCUTS);
2835
2836    p.append("on");
2837    p.append("root");
2838    p.append("ifmove");
2839    p.append("forceOn");
2840    p.append("onglobal");
2841    p.setLonghelp(
2842      "This switches on mixed integer rounding cuts (either at root or in entire tree) \
2843See branchAndCut for information on options.");
2844    parameters.push_back(p);
2845  }
2846#endif
2847  {
2848    CbcOrClpParam p("mess!ages", "Controls if Clpnnnn is printed",
2849      "off", CLP_PARAM_STR_MESSAGES);
2850
2851    p.append("on");
2852    p.setLonghelp("The default behavior is to put out messages such as:\n\
2853   Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
2854but this program turns this off to make it look more friendly.  It can be useful\
2855 to turn them back on if you want to be able to 'grep' for particular messages or if\
2856 you intend to override the behavior of a particular message.  This only affects Clp not Cbc.");
2857    parameters.push_back(p);
2858  }
2859  {
2860    CbcOrClpParam p("miplib", "Do some of miplib test set",
2861      CBC_PARAM_ACTION_MIPLIB, 3, 1);
2862    parameters.push_back(p);
2863  }
2864#ifdef COIN_HAS_CBC
2865  {
2866    CbcOrClpParam p("mips!tart", "reads an initial feasible solution from file",
2867      CBC_PARAM_ACTION_MIPSTART);
2868    p.setLonghelp("\
2869The MIPStart allows one to enter an initial integer feasible solution \
2870to CBC. Values of the main decision variables which are active (have \
2871non-zero values) in this solution are specified in a text  file. The \
2872text file format used is the same of the solutions saved by CBC, but \
2873not all fields are required to be filled. First line may contain the \
2874solution status and will be ignored, remaining lines contain column \
2875indexes, names and values as in this example:\n\
2876\n\
2877Stopped on iterations - objective value 57597.00000000\n\
2878      0  x(1,1,2,2)               1 \n\
2879      1  x(3,1,3,2)               1 \n\
2880      5  v(5,1)                   2 \n\
2881      33 x(8,1,5,2)               1 \n\
2882      ...\n\
2883\n\
2884Column indexes are also ignored since pre-processing can change them. \
2885There is no need to include values for continuous or integer auxiliary \
2886variables, since they can be computed based on main decision variables. \
2887Starting CBC with an integer feasible solution can dramatically improve \
2888its performance: several MIP heuristics (e.g. RINS) rely on having at \
2889least one feasible solution available and can start immediately if the \
2890user provides one. Feasibility Pump (FP) is a heuristic which tries to \
2891overcome the problem of taking too long to find feasible solution (or \
2892not finding at all), but it not always succeeds. If you provide one \
2893starting solution you will probably save some time by disabling FP. \
2894\n\n\
2895Knowledge specific to your problem can be considered to write an \
2896external module to quickly produce an initial feasible solution - some \
2897alternatives are the implementation of simple greedy heuristics or the \
2898solution (by CBC for example) of a simpler model created just to find \
2899a feasible solution. \
2900\n\n\
2901Question and suggestions regarding MIPStart can be directed to\n\
2902haroldo.santos@gmail.com. ");
2903    parameters.push_back(p);
2904  }
2905#endif
2906  {
2907    CbcOrClpParam p("moreS!pecialOptions", "Yet more dubious options for Simplex - see ClpSimplex.hpp",
2908      0, COIN_INT_MAX, CLP_PARAM_INT_MORESPECIALOPTIONS, 0);
2909    parameters.push_back(p);
2910  }
2911#ifdef COIN_HAS_CBC
2912  {
2913    CbcOrClpParam p("moreT!une", "Yet more dubious ideas for feasibility pump",
2914      0, 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0);
2915
2916    p.setLonghelp(
2917      "Yet more ideas for Feasibility Pump \n\
2918\t/100000 == 1 use box constraints and original obj in cleanup\n\
2919\t/1000 == 1 Pump will run twice if no solution found\n\
2920\t/1000 == 2 Pump will only run after root cuts if no solution found\n\
2921\t/1000 >10 as above but even if solution found\n\
2922\t/100 == 1,3.. exact 1.0 for objective values\n\
2923\t/100 == 2,3.. allow more iterations per pass\n\
2924\t n fix if value of variable same for last n iterations.");
2925    p.setIntValue(0);
2926    parameters.push_back(p);
2927  }
2928  {
2929    CbcOrClpParam p("multiple!RootPasses", "Do multiple root passes to collect cuts and solutions",
2930      0, 100000000, CBC_PARAM_INT_MULTIPLEROOTS, 0);
2931    p.setIntValue(0);
2932    p.setLonghelp(
2933      "Do (in parallel if threads enabled) the root phase this number of times \
2934 and collect all solutions and cuts generated.  The actual format is aabbcc \
2935where aa is number of extra passes, if bb is non zero \
2936then it is number of threads to use (otherwise uses threads setting) and \
2937cc is number of times to do root phase.  Yet another one from the Italian idea factory \
2938(This time - Andrea Lodi , Matteo Fischetti , Michele Monaci , Domenico Salvagnin , \
2939and Andrea Tramontani). \
2940The solvers do not interact with each other.  However if extra passes are specified \
2941then cuts are collected and used in later passes - so there is interaction there.");
2942    parameters.push_back(p);
2943  }
2944  {
2945    CbcOrClpParam p("naive!Heuristics", "Whether to try some stupid heuristic",
2946      "off", CBC_PARAM_STR_NAIVE, 7, 1);
2947
2948    p.append("on");
2949    p.append("both");
2950    p.append("before");
2951    p.setLonghelp(
2952      "Really silly stuff e.g. fix all integers with costs to zero!. \
2953Doh option does heuristic before preprocessing");
2954    parameters.push_back(p);
2955  }
2956#endif
2957#ifdef COIN_HAS_CLP
2958  {
2959    CbcOrClpParam p("netlib", "Solve entire netlib test set",
2960      CLP_PARAM_ACTION_NETLIB_EITHER, 3, 1);
2961    p.setLonghelp(
2962      "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\
2963The user can set options before e.g. clp -presolve off -netlib");
2964    parameters.push_back(p);
2965  }
2966  {
2967    CbcOrClpParam p("netlibB!arrier", "Solve entire netlib test set with barrier",
2968      CLP_PARAM_ACTION_NETLIB_BARRIER, 3, 1);
2969    p.setLonghelp(
2970      "This exercises the unit test for clp and then solves the netlib test set using barrier.\
2971The user can set options before e.g. clp -kkt on -netlib");
2972    parameters.push_back(p);
2973  }
2974  {
2975    CbcOrClpParam p("netlibD!ual", "Solve entire netlib test set (dual)",
2976      CLP_PARAM_ACTION_NETLIB_DUAL, 3, 1);
2977
2978    p.setLonghelp(
2979      "This exercises the unit test for clp and then solves the netlib test set using dual.\
2980The user can set options before e.g. clp -presolve off -netlib");
2981    parameters.push_back(p);
2982  }
2983  {
2984    CbcOrClpParam p("netlibP!rimal", "Solve entire netlib test set (primal)",
2985      CLP_PARAM_ACTION_NETLIB_PRIMAL, 3, 1);
2986    p.setLonghelp(
2987      "This exercises the unit test for clp and then solves the netlib test set using primal.\
2988The user can set options before e.g. clp -presolve off -netlibp");
2989    parameters.push_back(p);
2990  }
2991  {
2992    CbcOrClpParam p("netlibT!une", "Solve entire netlib test set with 'best' algorithm",
2993      CLP_PARAM_ACTION_NETLIB_TUNE, 3, 1);
2994    p.setLonghelp(
2995      "This exercises the unit test for clp and then solves the netlib test set using whatever \
2996works best.  I know this is cheating but it also stresses the code better by doing a \
2997mixture of stuff.  The best algorithm was chosen on a Linux ThinkPad using native cholesky \
2998with University of Florida ordering.");
2999    parameters.push_back(p);
3000  }
3001  {
3002    CbcOrClpParam p("network", "Tries to make network matrix",
3003      CLP_PARAM_ACTION_NETWORK, 7, 0);
3004    p.setLonghelp(
3005      "Clp will go faster if the matrix can be converted to a network.  The matrix\
3006 operations may be a bit faster with more efficient storage, but the main advantage\
3007 comes from using a network factorization.  It will probably not be as fast as a \
3008specialized network code.");
3009    parameters.push_back(p);
3010  }
3011#ifdef COIN_HAS_CBC
3012  {
3013    CbcOrClpParam p("nextB!estSolution", "Prints next best saved solution to file",
3014      CLP_PARAM_ACTION_NEXTBESTSOLUTION);
3015
3016    p.setLonghelp(
3017      "To write best solution, just use solution.  This prints next best (if exists) \
3018 and then deletes it. \
3019 This will write a primitive solution file to the given file name.  It will use the default\
3020 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3021 is initialized to 'stdout'.  The amount of output can be varied using printi!ngOptions or printMask.");
3022    parameters.push_back(p);
3023  }
3024  {
3025    CbcOrClpParam p("node!Strategy", "What strategy to use to select nodes",
3026      "hybrid", CBC_PARAM_STR_NODESTRATEGY);
3027    p.append("fewest");
3028    p.append("depth");
3029    p.append("upfewest");
3030    p.append("downfewest");
3031    p.append("updepth");
3032    p.append("downdepth");
3033    p.setLonghelp(
3034      "Normally before a solution the code will choose node with fewest infeasibilities. \
3035You can choose depth as the criterion.  You can also say if up or down branch must \
3036be done first (the up down choice will carry on after solution). \
3037Default has now been changed to hybrid which is breadth first on small depth nodes then fewest.");
3038    parameters.push_back(p);
3039  }
3040  {
3041    CbcOrClpParam p("numberA!nalyze", "Number of analysis iterations",
3042      -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0);
3043    p.setLonghelp(
3044      "This says how many iterations to spend at root node analyzing problem. \
3045This is a first try and will hopefully become more sophisticated.");
3046    parameters.push_back(p);
3047  }
3048#endif
3049  {
3050    CbcOrClpParam p("objective!Scale", "Scale factor to apply to objective",
3051      -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE, 1);
3052    p.setLonghelp(
3053      "If the objective function has some very large values, you may wish to scale them\
3054 internally by this amount.  It can also be set by autoscale.  It is applied after scaling.  You are unlikely to need this.");
3055    p.setDoubleValue(1.0);
3056    parameters.push_back(p);
3057  }
3058#endif
3059#ifdef COIN_HAS_CBC
3060#ifdef COIN_HAS_NTY
3061  {
3062    CbcOrClpParam p("Orbit!alBranching", "Whether to try orbital branching",
3063      "off", CBC_PARAM_STR_ORBITAL);
3064    p.append("on");
3065    p.append("strong");
3066    p.append("force");
3067    p.append("simple");
3068    p.setLonghelp(
3069      "This switches on Orbital branching. \
3070On just adds orbital, strong tries extra fixing in strong branching");
3071    parameters.push_back(p);
3072  }
3073#endif
3074  {
3075    CbcOrClpParam p("PrepN!ames", "If column names will be kept in pre-processed model",
3076      "off", CBC_PARAM_STR_PREPROCNAMES);
3077    p.append("on");
3078    p.setLonghelp(
3079      "Normally the preprocessed model has column names replaced by new names C0000...\
3080Setting this option to on keeps original names in variables which still exist in the preprocessed problem");
3081    parameters.push_back(p);
3082  }
3083
3084  {
3085    CbcOrClpParam p("outDup!licates", "takes duplicate rows etc out of integer model",
3086      CLP_PARAM_ACTION_OUTDUPROWS, 7, 0);
3087    parameters.push_back(p);
3088  }
3089#endif
3090  {
3091    CbcOrClpParam p("output!Format", "Which output format to use",
3092      1, 6, CLP_PARAM_INT_OUTPUTFORMAT);
3093    p.setLonghelp(
3094      "Normally export will be done using normal representation for numbers and two values\
3095 per line.  You may want to do just one per line (for grep or suchlike) and you may wish\
3096 to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
3097 otherwise odd values gives one value per line, even two.  Values 1,2 give normal format, 3,4\
3098 gives greater precision, while 5,6 give IEEE values.  When used for exporting a basis 1 does not save \
3099values, 2 saves values, 3 with greater accuracy and 4 in IEEE.");
3100    parameters.push_back(p);
3101  }
3102#ifdef COIN_HAS_CLP
3103  {
3104    CbcOrClpParam p("para!metrics", "Import data from file and do parametrics",
3105      CLP_PARAM_ACTION_PARAMETRICS, 3);
3106    p.setLonghelp(
3107      "This will read a file with parametric data from the given file name \
3108and then do parametrics.  It will use the default\
3109 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3110 is initialized to '', i.e. it must be set.  This can not read from compressed files. \
3111File is in modified csv format - a line ROWS will be followed by rows data \
3112while a line COLUMNS will be followed by column data.  The last line \
3113should be ENDATA. The ROWS line must exist and is in the format \
3114ROWS, inital theta, final theta, interval theta, n where n is 0 to get \
3115CLPI0062 message at interval or at each change of theta \
3116and 1 to get CLPI0063 message at each iteration.  If interval theta is 0.0 \
3117or >= final theta then no interval reporting.  n may be missed out when it is \
3118taken as 0.  If there is Row data then \
3119there is a headings line with allowed headings - name, number, \
3120lower(rhs change), upper(rhs change), rhs(change).  Either the lower and upper \
3121fields should be given or the rhs field. \
3122The optional COLUMNS line is followed by a headings line with allowed \
3123headings - name, number, objective(change), lower(change), upper(change). \
3124 Exactly one of name and number must be given for either section and \
3125missing ones have value 0.0.");
3126    parameters.push_back(p);
3127  }
3128#endif
3129#ifdef COIN_HAS_CBC
3130  {
3131    CbcOrClpParam p("passC!uts", "Number of cut passes at root node",
3132      -9999999, 9999999, CBC_PARAM_INT_CUTPASS);
3133
3134    p.setIntValue(20);
3135    p.setLonghelp(
3136      "The default is 100 passes if less than 500 columns, 100 passes (but \
3137stop if drop small if less than 5000 columns, 20 otherwise");
3138    parameters.push_back(p);
3139  }
3140  {
3141    CbcOrClpParam p("passF!easibilityPump", "How many passes in feasibility pump",
3142      0, 10000, CBC_PARAM_INT_FPUMPITS);
3143    p.setLonghelp(
3144      "This fine tunes Feasibility Pump by doing more or fewer passes.");
3145    p.setIntValue(20);
3146    parameters.push_back(p);
3147  }
3148#endif
3149#ifdef COIN_HAS_CLP
3150  {
3151    CbcOrClpParam p("passP!resolve", "How many passes in presolve",
3152      -200, 100, CLP_PARAM_INT_PRESOLVEPASS, 1);
3153    p.setLonghelp(
3154      "Normally Presolve does 10 passes but you may want to do less to make it\
3155 more lightweight or do more if improvements are still being made.  As Presolve will return\
3156 if nothing is being taken out, you should not normally need to use this fine tuning.");
3157    parameters.push_back(p);
3158  }
3159#endif
3160#ifdef COIN_HAS_CBC
3161  {
3162    CbcOrClpParam p("passT!reeCuts", "Number of cut passes in tree",
3163      -9999999, 9999999, CBC_PARAM_INT_CUTPASSINTREE);
3164    p.setIntValue(1);
3165    p.setLonghelp("The default is one pass");
3166    parameters.push_back(p);
3167  }
3168#endif
3169#ifdef COIN_HAS_CLP
3170  {
3171    CbcOrClpParam p("pertV!alue", "Method of perturbation",
3172      -5000, 102, CLP_PARAM_INT_PERTVALUE, 1);
3173    parameters.push_back(p);
3174  }
3175  {
3176    CbcOrClpParam p("perturb!ation", "Whether to perturb problem",
3177      "on", CLP_PARAM_STR_PERTURBATION);
3178    p.append("off");
3179    p.setLonghelp(
3180      "Perturbation helps to stop cycling, but Clp uses other measures for this.\
3181  However large problems and especially ones with unit elements and unit rhs or costs\
3182 benefit from perturbation.  Normally Clp tries to be intelligent, but you can switch this off.\
3183  The Clp library has this off by default.  This program has it on by default.");
3184    parameters.push_back(p);
3185  }
3186  {
3187    CbcOrClpParam p("PFI", "Whether to use Product Form of Inverse in simplex",
3188      "off", CLP_PARAM_STR_PFI, 7, 0);
3189    p.append("on");
3190    p.setLonghelp(
3191      "By default clp uses Forrest-Tomlin L-U update.  If you are masochistic you can switch it off.");
3192    parameters.push_back(p);
3193  }
3194#endif
3195#ifdef COIN_HAS_CBC
3196  {
3197    CbcOrClpParam p("pivotAndC!omplement", "Whether to try Pivot and Complement heuristic",
3198      "off", CBC_PARAM_STR_PIVOTANDCOMPLEMENT);
3199
3200    p.append("on");
3201    p.append("both");
3202    p.append("before");
3203    p.setLonghelp(
3204      "stuff needed. \
3205Doh option does heuristic before preprocessing");
3206    parameters.push_back(p);
3207  }
3208  {
3209    CbcOrClpParam p("pivotAndF!ix", "Whether to try Pivot and Fix heuristic",
3210      "off", CBC_PARAM_STR_PIVOTANDFIX);
3211    p.append("on");
3212    p.append("both");
3213    p.append("before");
3214    p.setLonghelp(
3215      "stuff needed. \
3216Doh option does heuristic before preprocessing");
3217    parameters.push_back(p);
3218  }
3219#endif
3220#ifdef COIN_HAS_CLP
3221  {
3222    CbcOrClpParam p("plus!Minus", "Tries to make +- 1 matrix",
3223      CLP_PARAM_ACTION_PLUSMINUS, 7, 0);
3224    p.setLonghelp(
3225      "Clp will go slightly faster if the matrix can be converted so that the elements are\
3226 not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
3227 see if it can convert the problem so you should not need to use this.");
3228    parameters.push_back(p);
3229  }
3230  {
3231    CbcOrClpParam p("pO!ptions", "Dubious print options",
3232      0, COIN_INT_MAX, CLP_PARAM_INT_PRINTOPTIONS, 1);
3233    p.setIntValue(0);
3234    p.setLonghelp(
3235      "If this is > 0 then presolve will give more information and branch and cut will give statistics");
3236    parameters.push_back(p);
3237  }
3238  {
3239    CbcOrClpParam p("preO!pt", "Presolve options",
3240      0, COIN_INT_MAX, CLP_PARAM_INT_PRESOLVEOPTIONS, 0);
3241    parameters.push_back(p);
3242  }
3243#endif
3244  {
3245    CbcOrClpParam p("presolve", "Whether to presolve problem",
3246      "on", CLP_PARAM_STR_PRESOLVE);
3247    p.append("off");
3248    p.append("more");
3249    p.append("file");
3250    p.setLonghelp("Presolve analyzes the model to find such things as redundant equations, equations\
3251 which fix some variables, equations which can be transformed into bounds etc etc.  For the\
3252 initial solve of any problem this is worth doing unless you know that it will have no effect.  \
3253on will normally do 5 passes while using 'more' will do 10.  If the problem is very large you may need \
3254to write the original to file using 'file'.");
3255    parameters.push_back(p);
3256  }
3257#ifdef COIN_HAS_CBC
3258  {
3259    CbcOrClpParam p("preprocess", "Whether to use integer preprocessing",
3260      "off", CBC_PARAM_STR_PREPROCESS);
3261
3262    p.append("on");
3263    p.append("save");
3264    p.append("equal");
3265    p.append("sos");
3266    p.append("trysos");
3267    p.append("equalall");
3268    p.append("strategy");
3269    p.append("aggregate");
3270    p.append("forcesos");
3271    p.append("stop!aftersaving");
3272    p.setLonghelp(
3273      "This tries to reduce size of model in a similar way to presolve and \
3274it also tries to strengthen the model - this can be very useful and is worth trying. \
3275 Save option saves on file presolved.mps.  equal will turn <= cliques into \
3276==.  sos will create sos sets if all 0-1 in sets (well one extra is allowed) \
3277and no overlaps.  trysos is same but allows any number extra.  equalall will turn all \
3278valid inequalities into equalities with integer slacks.  strategy is as \
3279on but uses CbcStrategy.");
3280    parameters.push_back(p);
3281  }
3282#endif
3283#ifdef COIN_HAS_CLP
3284  {
3285    CbcOrClpParam p("preT!olerance", "Tolerance to use in presolve",
3286      1.0e-20, 1.0e12, CLP_PARAM_DBL_PRESOLVETOLERANCE);
3287    p.setLonghelp(
3288      "The default is 1.0e-8 - you may wish to try 1.0e-7 if presolve says the problem is \
3289infeasible and you have awkward numbers and you are sure the problem is really feasible.");
3290    parameters.push_back(p);
3291  }
3292  {
3293    CbcOrClpParam p("primalP!ivot", "Primal pivot choice algorithm",
3294      "auto!matic", CLP_PARAM_STR_PRIMALPIVOT, 7, 1);
3295
3296    p.append("exa!ct");
3297    p.append("dant!zig");
3298    p.append("part!ial");
3299    p.append("steep!est");
3300    p.append("change");
3301    p.append("sprint");
3302    p.append("PEsteep!est");
3303    p.append("PEdantzig");
3304    p.setLonghelp(
3305      "Clp can use any pivot selection algorithm which the user codes as long as it\
3306 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
3307 to show a simple method but its use is deprecated.  Exact devex is the method of choice and there\
3308 are two variants which keep all weights updated but only scan a subset each iteration.\
3309 Partial switches this on while change initially does dantzig until the factorization\
3310 becomes denser.  This is still a work in progress. \n\
3311** NEWS - the Positive Edge criterion has been added. \
3312This selects incoming variables to try and avoid degenerate moves. Code \
3313donated by Jeremy Omer.  See \
3314Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR’s CLP. and \
3315Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex.");
3316
3317    parameters.push_back(p);
3318  }
3319  {
3320    CbcOrClpParam p("primalS!implex", "Do primal simplex algorithm",
3321      CLP_PARAM_ACTION_PRIMALSIMPLEX);
3322
3323    p.setLonghelp(
3324      "This command solves the continuous relaxation of the current model using the primal algorithm.\
3325  The default is to use exact devex.\
3326 The time and iterations may be affected by settings such as presolve, scaling, crash\
3327 and also by column selection  method, infeasibility weight and dual and primal tolerances.");
3328    parameters.push_back(p);
3329  }
3330#endif
3331  {
3332    CbcOrClpParam p("primalT!olerance", "For an optimal solution \
3333no primal infeasibility may exceed this value",
3334      1.0e-20, 1.0e12, CLP_PARAM_DBL_PRIMALTOLERANCE);
3335    p.setLonghelp(
3336      "Normally the default tolerance is fine, but you may want to increase it a\
3337 bit if a primal run seems to be having a hard time");
3338    parameters.push_back(p);
3339  }
3340#ifdef COIN_HAS_CLP
3341  {
3342    CbcOrClpParam p("primalW!eight", "Initially algorithm acts as if it \
3343costs this much to be infeasible",
3344      1.0e-20, 1.0e20, CLP_PARAM_DBL_PRIMALWEIGHT);
3345    p.setLonghelp(
3346      "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
3347 algorithm where you first get feasible then optimal.  So Clp is minimizing this weight times\
3348 the sum of primal infeasibilities plus the true objective function (in minimization sense).\
3349  Too high a value may mean more iterations, while too low a bound means\
3350 the code may go all the way and then have to increase the weight in order to get feasible.\
3351  OSL had a heuristic to\
3352 adjust bounds, maybe we need that here.");
3353    parameters.push_back(p);
3354  }
3355  {
3356    CbcOrClpParam p("psi", "Two-dimension pricing factor for Positive edge",
3357      -1.1, 1.1, CLP_PARAM_DBL_PSI);
3358
3359    p.setDoubleValue(-0.5);
3360    p.setLonghelp(
3361      "The Positive Edge criterion has been added to \
3362select incoming variables to try and avoid degenerate moves. \
3363Variables not in promising set have their infeasibility weight multiplied by psi \
3364so 0.01 would mean that if there were any promising variables, then they would always be chosen, \
3365while 1.0 effectively switches algorithm off. \
3366There are two ways of switching on this feature.  One way is to set psi positive and then \
3367the Positive Edge criterion will be used for Primal and Dual.  The other way is to select pesteep \
3368in dualpivot choice (for example), then the absolute value of psi is used - default 0.5. \
3369Until this settles down it is only implemented in clp. \
3370Code donated by Jeremy Omer.  See \
3371Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR’s CLP. and \
3372Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex.");
3373    parameters.push_back(p);
3374  }
3375#endif
3376  {
3377    CbcOrClpParam p("printi!ngOptions", "Print options",
3378      "normal", CLP_PARAM_STR_INTPRINT, 3);
3379    p.append("integer");
3380    p.append("special");
3381    p.append("rows");
3382    p.append("all");
3383    p.append("csv");
3384    p.append("bound!ranging");
3385    p.append("rhs!ranging");
3386    p.append("objective!ranging");
3387    p.append("stats");
3388    p.append("boundsint");
3389    p.append("boundsall");
3390    p.append("fixint");
3391    p.append("fixall");
3392    p.setLonghelp(
3393      "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\
3394integer - nonzero integer column variables\n\
3395special - in format suitable for OsiRowCutDebugger\n\
3396rows - nonzero column variables and row activities\n\
3397all - all column variables and row activities.\n\
3398\nFor non-integer problems 'integer' and 'special' act like 'normal'.  \
3399Also see printMask for controlling output.");
3400    parameters.push_back(p);
3401  }
3402  {
3403    CbcOrClpParam p("printM!ask", "Control printing of solution on a  mask",
3404      CLP_PARAM_ACTION_PRINTMASK, 3);
3405
3406    p.setLonghelp(
3407      "If set then only those names which match mask are printed in a solution. \
3408'?' matches any character and '*' matches any set of characters. \
3409 The default is '' i.e. unset so all variables are printed. \
3410This is only active if model has names.");
3411    parameters.push_back(p);
3412  }
3413
3414#ifdef COIN_HAS_CBC
3415  {
3416    CbcOrClpParam p("prio!rityIn", "Import priorities etc from file",
3417      CBC_PARAM_ACTION_PRIORITYIN, 3);
3418    p.setLonghelp(
3419      "This will read a file with priorities from the given file name.  It will use the default\
3420 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3421 is initialized to '', i.e. it must be set.  This can not read from compressed files. \
3422File is in csv format with allowed headings - name, number, priority, direction, up, down, solution.  Exactly one of\
3423 name and number must be given.");
3424    parameters.push_back(p);
3425  }
3426
3427  {
3428    CbcOrClpParam p("probing!Cuts", "Whether to use Probing cuts",
3429      "off", CBC_PARAM_STR_PROBINGCUTS);
3430    p.append("on");
3431    p.append("root");
3432    p.append("ifmove");
3433    p.append("forceOn");
3434    p.append("onglobal");
3435    p.append("forceonglobal");
3436    p.append("forceOnBut");
3437    p.append("forceOnStrong");
3438    p.append("forceOnButStrong");
3439    p.append("strongRoot");
3440    p.setLonghelp(
3441      "This switches on probing cuts (either at root or in entire tree) \
3442    See branchAndCut for information on options. \
3443but strong options do more probing");
3444    parameters.push_back(p);
3445  }
3446  {
3447    CbcOrClpParam p("proximity!Search", "Whether to do proximity search heuristic",
3448      "off", CBC_PARAM_STR_PROXIMITY);
3449
3450    p.append("on");
3451    p.append("both");
3452    p.append("before");
3453    p.append("10");
3454    p.append("100");
3455    p.append("300");
3456    // but allow numbers after this (returning 1)
3457    p.setFakeKeyWord(1);
3458    p.setLonghelp(
3459      "This switches on a heuristic which looks for a solution close \
3460to incumbent solution (Fischetti and Monaci). \
3461See Rounding for meaning of on,both,before. \
3462Can also set different maxNode settings by plusnnnn (and are 'on'(on==30)).");
3463    parameters.push_back(p);
3464  }
3465  {
3466    CbcOrClpParam p("pumpC!utoff", "Fake cutoff for use in feasibility pump",
3467      -1.0e100, 1.0e100, CBC_PARAM_DBL_FAKECUTOFF);
3468    p.setDoubleValue(0.0);
3469    p.setLonghelp(
3470      "0.0 off - otherwise add a constraint forcing objective below this value\
3471 in feasibility pump");
3472    parameters.push_back(p);
3473  }
3474  {
3475    CbcOrClpParam p("pumpI!ncrement", "Fake increment for use in feasibility pump",
3476      -1.0e100, 1.0e100, CBC_PARAM_DBL_FAKEINCREMENT, 1);
3477    p.setDoubleValue(0.0);
3478    p.setLonghelp(
3479      "0.0 off - otherwise use as absolute increment to cutoff \
3480when solution found in feasibility pump");
3481    parameters.push_back(p);
3482  }
3483  {
3484    CbcOrClpParam p("pumpT!une", "Dubious ideas for feasibility pump",
3485      0, 100000000, CBC_PARAM_INT_FPUMPTUNE);
3486    p.setIntValue(1003);
3487    p.setLonghelp(
3488      "This fine tunes Feasibility Pump \n\
3489\t>=10000000 use as objective weight switch\n\
3490\t>=1000000 use as accumulate switch\n\
3491\t>=1000 use index+1 as number of large loops\n\
3492\t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\
3493\t%100 == 10,20 affects how each solve is done\n\
3494\t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \
3495If accumulate is on then after a major pass, variables which have not moved \
3496are fixed and a small branch and bound is tried.");
3497    p.setIntValue(0);
3498    parameters.push_back(p);
3499  }
3500#endif
3501  {
3502    CbcOrClpParam p("quit", "Stops clp execution",
3503      CLP_PARAM_ACTION_EXIT);
3504    p.setLonghelp(
3505      "This stops the execution of Clp, end, exit, quit and stop are synonyms");
3506
3507    parameters.push_back(p);
3508  }
3509#ifdef COIN_HAS_CBC
3510  {
3511    CbcOrClpParam p("randomC!bcSeed", "Random seed for Cbc",
3512      -1, COIN_INT_MAX, CBC_PARAM_INT_RANDOMSEED);
3513
3514    p.setLonghelp(
3515      "This sets a random seed for Cbc \
3516- 0 says use time of day, -1 is as now.");
3517    p.setIntValue(-1);
3518    parameters.push_back(p);
3519  }
3520  {
3521    CbcOrClpParam p("randomi!zedRounding", "Whether to try randomized rounding heuristic",
3522      "off", CBC_PARAM_STR_RANDROUND);
3523    p.append("on");
3524    p.append("both");
3525    p.append("before");
3526    p.setLonghelp(
3527      "stuff needed. \
3528Doh option does heuristic before preprocessing");
3529    parameters.push_back(p);
3530  }
3531#endif
3532#ifdef COIN_HAS_CLP
3533  {
3534    CbcOrClpParam p("randomS!eed", "Random seed for Clp",
3535      0, COIN_INT_MAX, CLP_PARAM_INT_RANDOMSEED);
3536
3537    p.setLonghelp(
3538      "This sets a random seed for Clp \
3539- 0 says use time of day.");
3540    p.setIntValue(1234567);
3541    parameters.push_back(p);
3542  }
3543#endif
3544#ifdef COIN_HAS_CBC
3545  {
3546    CbcOrClpParam p("ratio!Gap", "Stop when gap between best possible and \
3547best less than this fraction of larger of two",
3548      0.0, 1.0e20, CBC_PARAM_DBL_GAPRATIO);
3549    p.setDoubleValue(0.0);
3550    p.setLonghelp(
3551      "If the gap between best solution and best possible solution is less than this fraction \
3552of the objective value at the root node then the search will terminate.  See 'allowableGap' for a \
3553way of using absolute value rather than fraction.");
3554    parameters.push_back(p);
3555  }
3556#endif
3557  {
3558    CbcOrClpParam p("restoreS!olution", "reads solution from file",
3559      CLP_PARAM_ACTION_RESTORESOL);
3560
3561    p.setLonghelp(
3562      "This will read a binary solution file from the given file name.  It will use the default\
3563 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3564 is initialized to 'solution.file'.  This reads in a file from saveSolution");
3565    parameters.push_back(p);
3566  }
3567#ifdef COIN_HAS_CBC
3568  {
3569    CbcOrClpParam p("readSt!ored", "Import stored cuts from file",
3570      CLP_PARAM_ACTION_STOREDFILE, 3, 0);
3571    parameters.push_back(p);
3572  }
3573#endif
3574#ifdef COIN_HAS_CLP
3575  {
3576    CbcOrClpParam p("reallyO!bjectiveScale", "Scale factor to apply to objective in place",
3577      -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE2, 0);
3578    p.setLonghelp("You can set this to -1.0 to test maximization or other to stress code");
3579    p.setDoubleValue(1.0);
3580    parameters.push_back(p);
3581  }
3582  {
3583    CbcOrClpParam p("reallyS!cale", "Scales model in place",
3584      CLP_PARAM_ACTION_REALLY_SCALE, 7, 0);
3585    parameters.push_back(p);
3586  }
3587#endif
3588#ifdef COIN_HAS_CBC
3589  {
3590    CbcOrClpParam p("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts",
3591      "off", CBC_PARAM_STR_REDSPLITCUTS);
3592
3593    p.append("on");
3594    p.append("root");
3595    p.append("ifmove");
3596    p.append("forceOn");
3597    p.setLonghelp(
3598      "This switches on reduce and split  cuts (either at root or in entire tree). \
3599May be slow \
3600See branchAndCut for information on options.");
3601    parameters.push_back(p);
3602  }
3603  {
3604    CbcOrClpParam p("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2",
3605      "off", CBC_PARAM_STR_REDSPLIT2CUTS);
3606    p.append("on");
3607    p.append("root");
3608    p.append("longOn");
3609    p.append("longRoot");
3610    p.setLonghelp("This switches on reduce and split  cuts (either at root or in entire tree) \
3611This version is by Giacomo Nannicini based on Francois Margot's version \
3612Standard setting only uses rows in tableau <=256, long uses all \
3613May be slow \
3614See branchAndCut for information on options.");
3615    parameters.push_back(p);
3616  }
3617  {
3618    CbcOrClpParam p("residual!CapacityCuts", "Whether to use Residual Capacity cuts",
3619      "off", CBC_PARAM_STR_RESIDCUTS);
3620    p.append("on");
3621    p.append("root");
3622    p.append("ifmove");
3623    p.append("forceOn");
3624    p.setLonghelp(
3625      "Residual capacity cuts. \
3626See branchAndCut for information on options.");
3627
3628    parameters.push_back(p);
3629  }
3630#endif
3631#ifdef COIN_HAS_CLP
3632  {
3633    CbcOrClpParam p("restore!Model", "Restore model from binary file",
3634      CLP_PARAM_ACTION_RESTORE, 7, 1);
3635    p.setLonghelp(
3636      "This reads data save by saveModel from the given file.  It will use the default\
3637 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3638 is initialized to 'default.prob'.");
3639
3640    parameters.push_back(p);
3641  }
3642  {
3643    CbcOrClpParam p("reverse", "Reverses sign of objective",
3644      CLP_PARAM_ACTION_REVERSE, 7, 0);
3645    p.setLonghelp(
3646      "Useful for testing if maximization works correctly");
3647    parameters.push_back(p);
3648  }
3649  {
3650    CbcOrClpParam p("rhs!Scale", "Scale factor to apply to rhs and bounds",
3651      -1.0e20, 1.0e20, CLP_PARAM_DBL_RHSSCALE, 0);
3652    p.setLonghelp(
3653      "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
3654 internally by this amount.  It can also be set by autoscale.  This should not be needed.");
3655    p.setDoubleValue(1.0);
3656    parameters.push_back(p);
3657  }
3658#endif
3659#ifdef COIN_HAS_CBC
3660  {
3661    CbcOrClpParam p("Rens", "Whether to try Relaxation Enforced Neighborhood Search",
3662      "off", CBC_PARAM_STR_RENS);
3663    p.append("on");
3664    p.append("both");
3665    p.append("before");
3666    p.append("200");
3667    p.append("1000");
3668    p.append("10000");
3669    p.append("dj");
3670    p.append("djbefore");
3671    p.append("usesolution");
3672    p.setLonghelp(
3673      "This switches on Relaxation enforced neighborhood Search. \
3674on just does 50 nodes \
3675200 or 1000 does that many nodes. \
3676Doh option does heuristic before preprocessing");
3677    parameters.push_back(p);
3678  }
3679  {
3680    CbcOrClpParam p("Rins", "Whether to try Relaxed Induced Neighborhood Search",
3681      "off", CBC_PARAM_STR_RINS);
3682    p.append("on");
3683    p.append("both");
3684    p.append("before");
3685    p.append("often");
3686    p.setLonghelp(
3687      "This switches on Relaxed induced neighborhood Search. \
3688Doh option does heuristic before preprocessing");
3689    parameters.push_back(p);
3690  }
3691  {
3692    CbcOrClpParam p("round!ingHeuristic", "Whether to use Rounding heuristic",
3693      "off", CBC_PARAM_STR_ROUNDING);
3694    p.append("on");
3695    p.append("both");
3696    p.append("before");
3697    p.setLonghelp(
3698      "This switches on a simple (but effective) rounding heuristic at each node of tree.  \
3699On means do in solve i.e. after preprocessing, \
3700Before means do if doHeuristics used, off otherwise, \
3701and both means do if doHeuristics and in solve.");
3702    parameters.push_back(p);
3703  }
3704#endif
3705  {
3706    CbcOrClpParam p("saveM!odel", "Save model to binary file",
3707      CLP_PARAM_ACTION_SAVE, 7, 1);
3708    p.setLonghelp(
3709      "This will save the problem to the given file name for future use\
3710 by restoreModel.  It will use the default\
3711 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3712 is initialized to 'default.prob'.");
3713    parameters.push_back(p);
3714  }
3715  {
3716    CbcOrClpParam p("saveS!olution", "saves solution to file",
3717      CLP_PARAM_ACTION_SAVESOL);
3718
3719    p.setLonghelp(
3720      "This will write a binary solution file to the given file name.  It will use the default\
3721 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3722 is initialized to 'solution.file'.  To read the file use fread(int) twice to pick up number of rows \
3723and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \
3724activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \
3725If name contains '_fix_read_' then does not write but reads and will fix all variables");
3726    parameters.push_back(p);
3727  }
3728  {
3729    CbcOrClpParam p("scal!ing", "Whether to scale problem",
3730      "off", CLP_PARAM_STR_SCALING);
3731    p.append("equi!librium");
3732    p.append("geo!metric");
3733    p.append("auto!matic");
3734    p.append("dynamic");
3735    p.append("rows!only");
3736    p.setLonghelp(
3737      "Scaling can help in solving problems which might otherwise fail because of lack of\
3738 accuracy.  It can also reduce the number of iterations.  It is not applied if the range\
3739 of elements is small.  When unscaled it is possible that there may be small primal and/or\
3740 infeasibilities.");
3741    p.setCurrentOption(3); // say auto
3742    parameters.push_back(p);
3743  }
3744#ifndef COIN_HAS_CBC
3745  {
3746    CbcOrClpParam p("sec!onds", "Maximum seconds",
3747      -1.0, 1.0e12, CLP_PARAM_DBL_TIMELIMIT);
3748
3749    p.setLonghelp("After this many seconds clp will act as if maximum iterations had been reached \
3750(if value >=0).");
3751    parameters.push_back(p);
3752  }
3753#else
3754  {
3755    CbcOrClpParam p("sec!onds", "maximum seconds",
3756      -1.0, 1.0e12, CBC_PARAM_DBL_TIMELIMIT_BAB);
3757    p.setLonghelp(
3758      "After this many seconds coin solver will act as if maximum nodes had been reached.");
3759    parameters.push_back(p);
3760  }
3761#endif
3762  {
3763    CbcOrClpParam p("sleep", "for debug",
3764      CLP_PARAM_ACTION_DUMMY, 7, 0);
3765
3766    p.setLonghelp(
3767      "If passed to solver fom ampl, then ampl will wait so that you can copy .nl file for debug.");
3768    parameters.push_back(p);
3769  }
3770#ifdef COIN_HAS_CBC
3771  {
3772    CbcOrClpParam p("slow!cutpasses", "Maximum number of tries for slower cuts",
3773      -1, COIN_INT_MAX, CBC_PARAM_INT_MAX_SLOW_CUTS);
3774    p.setLonghelp(
3775      "Some cut generators are fairly slow - this limits the number of times they are tried.");
3776    p.setIntValue(10);
3777    parameters.push_back(p);
3778  }
3779#endif
3780#ifdef COIN_HAS_CLP
3781  {
3782    CbcOrClpParam p("slp!Value", "Number of slp passes before primal",
3783      -50000, 50000, CLP_PARAM_INT_SLPVALUE, 1);
3784    p.setLonghelp(
3785      "If you are solving a quadratic problem using primal then it may be helpful to do some \
3786sequential Lps to get a good approximate solution.");
3787    parameters.push_back(p);
3788  }
3789#if CLP_MULTIPLE_FACTORIZATIONS > 0
3790  {
3791    CbcOrClpParam p("small!Factorization", "Whether to use small factorization",
3792      -1, 10000, CBC_PARAM_INT_SMALLFACT, 1);
3793    p.setLonghelp(
3794      "If processed problem <= this use small factorization");
3795    p.setIntValue(-1);
3796    parameters.push_back(p);
3797  }
3798#endif
3799#endif
3800  {
3801    CbcOrClpParam p("solu!tion", "Prints solution to file",
3802      CLP_PARAM_ACTION_SOLUTION);
3803    p.setLonghelp(
3804      "This will write a primitive solution file to the given file name.  It will use the default\
3805 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3806 is initialized to 'stdout'.  The amount of output can be varied using printi!ngOptions or printMask.");
3807    parameters.push_back(p);
3808  }
3809#ifdef COIN_HAS_CLP
3810#ifdef COIN_HAS_CBC
3811  {
3812    CbcOrClpParam p("solv!e", "Solve problem",
3813      CBC_PARAM_ACTION_BAB);
3814         p.setLonghelp(
3815          "If there are no integer variables then this just solves LP.  If there are integer variables \
3816this does branch and cut." );
3817         parameters.push_back( p );
3818  }
3819  {
3820    CbcOrClpParam p("sosO!ptions", "Whether to use SOS from AMPL",  "off", CBC_PARAM_STR_SOS);
3821    p.append("on");
3822    p.setCurrentOption("on");
3823         p.setLonghelp(
3824          "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\
3825 be turned off - this does so." );
3826         parameters.push_back( p );
3827  }
3828  {
3829    CbcOrClpParam p("slog!Level", "Level of detail in (LP) Solver output", -1, 63, CLP_PARAM_INT_SOLVERLOGLEVEL);
3830    p.setLonghelp(
3831      "If 0 then there should be no output in normal circumstances.  1 is probably the best\
3832 value for most uses, while 2 and 3 give more information.  This parameter is only used inside MIP - for Clp use 'log'");
3833    parameters.push_back(p);
3834  }
3835  {
3836     // Due to James Howey
3837     CbcOrClpParam p("sosP!rioritize", "How to deal with SOS priorities",
3838       "off", CBC_PARAM_STR_SOSPRIORITIZE);
3839     p.append("high");
3840     p.append("low");
3841     p.append("orderhigh");
3842     p.append("orderlow");
3843     p.setLonghelp(
3844       "This sets priorities for SOS.  The first two just set priority \
3845    relative to integers.  Orderhigh gives first set highest priority and integers \
3846    a low priority.  Orderlow gives integers high priority then SOS in order.");
3847    parameters.push_back(p);
3848  }
3849#else
3850  // allow solve as synonym for possible dual
3851  {
3852    CbcOrClpParam p("solv!e", "Solve problem using dual simplex (probably)",
3853      CLP_PARAM_ACTION_EITHERSIMPLEX);
3854    p.setLonghelp(
3855      "Just so can use solve for clp as well as in cbc");
3856    parameters.push_back(p);
3857  }
3858#endif
3859#endif
3860#ifdef COIN_HAS_CLP
3861  {
3862    CbcOrClpParam p("spars!eFactor", "Whether factorization treated as sparse",
3863      "on", CLP_PARAM_STR_SPARSEFACTOR, 7, 0);
3864    p.append("off");
3865    parameters.push_back(p);
3866  }
3867  {
3868    CbcOrClpParam p("special!Options", "Dubious options for Simplex - see ClpSimplex.hpp",
3869      0, COIN_INT_MAX, CLP_PARAM_INT_SPECIALOPTIONS, 0);
3870    parameters.push_back(p);
3871  }
3872  {
3873    CbcOrClpParam p("sprint!Crash", "Whether to try sprint crash",
3874      -1, 5000000, CLP_PARAM_INT_SPRINT);
3875    p.setLonghelp(
3876      "For long and thin problems this program may solve a series of small problems\
3877 created by taking a subset of the columns.  I introduced the idea as 'Sprint' after\
3878 an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
3879  Cplex calls it 'sifting'.  -1 is automatic choice, 0 is off, n is number of passes");
3880    parameters.push_back(p);
3881  }
3882  {
3883    CbcOrClpParam p("stat!istics", "Print some statistics",
3884      CLP_PARAM_ACTION_STATISTICS);
3885    p.setLonghelp(
3886      "This command prints some statistics for the current model.\
3887 If log level >1 then more is printed.\
3888 These are for presolved model if presolve on (and unscaled).");
3889    parameters.push_back(p);
3890  }
3891#endif
3892  {
3893    CbcOrClpParam p("stop", "Stops clp execution",
3894      CLP_PARAM_ACTION_EXIT);
3895    p.setLonghelp(
3896      "This stops the execution of Clp, end, exit, quit and stop are synonyms");
3897    parameters.push_back(p);
3898  }
3899#ifdef COIN_HAS_CBC
3900  {
3901    CbcOrClpParam p("strat!egy", "Switches on groups of features",
3902      0, 2, CBC_PARAM_INT_STRATEGY);
3903    p.setLonghelp(
3904      "This turns on newer features. \
3905Use 0 for easy problems, 1 is default, 2 is aggressive. \
39061 uses Gomory cuts using tolerance of 0.01 at root, \
3907does a possible restart after 100 nodes if can fix many \
3908and activates a diving and RINS heuristic and makes feasibility pump \
3909more aggressive. \
3910This does not apply to unit tests (where 'experiment' may have similar effects).");
3911    p.setIntValue(1);
3912    parameters.push_back(p);
3913  }
3914#ifdef CBC_KEEP_DEPRECATED
3915  {
3916    CbcOrClpParam p("strengthen", "Create strengthened problem",
3917      CBC_PARAM_ACTION_STRENGTHEN, 3);
3918    p.setLonghelp(
3919      "This creates a new problem by applying the root node cuts.  All tight constraints \
3920will be in resulting problem");
3921    parameters.push_back(p);
3922  }
3923#endif
3924  {
3925    CbcOrClpParam p("strong!Branching", "Number of variables to look at in strong branching",
3926      0, COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING);
3927    p.setIntValue(20);
3928    p.setLonghelp(
3929      "In order to decide which variable to branch on, the code will choose up to this number \
3930of unsatisfied variables to do mini up and down branches on.  Then the most effective one is chosen. \
3931If a variable is branched on many times then the previous average up and down costs may be used - \
3932see number before trust.");
3933    parameters.push_back(p);
3934  }
3935#endif
3936#ifdef COIN_HAS_CLP
3937  {
3938    CbcOrClpParam p("subs!titution", "How long a column to substitute for in presolve",
3939      0, 10000, CLP_PARAM_INT_SUBSTITUTION, 0);
3940    p.setLonghelp(
3941      "Normally Presolve gets rid of 'free' variables when there are no more than 3 \
3942 variables in column.  If you increase this the number of rows may decrease but number of \
3943 elements may increase.");
3944    parameters.push_back(p);
3945  }
3946#endif
3947#ifdef COIN_HAS_CBC
3948  {
3949    CbcOrClpParam p("testO!si", "Test OsiObject stuff",
3950      -1, COIN_INT_MAX, CBC_PARAM_INT_TESTOSI, 0);
3951    parameters.push_back(p);
3952  }
3953#endif
3954#ifdef CBC_THREAD
3955  {
3956    CbcOrClpParam p("thread!s", "Number of threads to try and use",
3957      -100, 100000, CBC_PARAM_INT_THREADS, 1);
3958    p.setIntValue(0);
3959    p.setLonghelp(
3960      "To use multiple threads, set threads to number wanted.  It may be better \
3961to use one or two more than number of cpus available.  If 100+n then n threads and \
3962search is repeatable (maybe be somewhat slower), \
3963if 200+n use threads for root cuts, 400+n threads used in sub-trees.");
3964    parameters.push_back(p);
3965  }
3966#endif
3967#ifdef COIN_HAS_CBC
3968  {
3969    CbcOrClpParam p("tighten!Factor", "Tighten bounds using this times largest \
3970activity at continuous solution",
3971      1.0e-3, 1.0e20, CBC_PARAM_DBL_TIGHTENFACTOR, 0);
3972    p.setLonghelp(
3973      "This sleazy trick can help on some problems.");
3974    parameters.push_back(p);
3975  }
3976
3977#endif
3978#ifdef COIN_HAS_CLP
3979  {
3980    CbcOrClpParam p("tightLP", "Poor person's preSolve for now",
3981      CLP_PARAM_ACTION_TIGHTEN, 7, 0);
3982    parameters.push_back(p);
3983  }
3984#endif
3985  {
3986    CbcOrClpParam p("timeM!ode", "Whether to use CPU or elapsed time",
3987      "cpu", CLP_PARAM_STR_TIME_MODE);
3988    p.append("elapsed");
3989    p.setLonghelp(
3990      "cpu uses CPU time for stopping, while elapsed uses elapsed time. \
3991(On Windows, elapsed time is always used).");
3992    parameters.push_back(p);
3993  }
3994#ifdef COIN_HAS_CBC
3995  {
3996    CbcOrClpParam p("trust!PseudoCosts", "Number of branches before we trust pseudocosts",
3997      -3, 2000000000, CBC_PARAM_INT_NUMBERBEFORE);
3998    p.setLonghelp(
3999      "Using strong branching computes pseudo-costs.  After this many times for a variable we just \
4000trust the pseudo costs and do not do any more strong branching.");
4001    p.setIntValue(10);
4002    parameters.push_back(p);
4003  }
4004#endif
4005#ifdef COIN_HAS_CBC
4006  {
4007    CbcOrClpParam p("tune!PreProcess", "Dubious tuning parameters",
4008      0, 2000000000, CLP_PARAM_INT_PROCESSTUNE, 1);
4009    p.setLonghelp(
4010      "Format aabbcccc - \n If aa then this is number of major passes (i.e. with presolve) \n \
4011If bb and bb>0 then this is number of minor passes (if unset or 0 then 10) \n \
4012cccc is bit set \n 0 - 1 Heavy probing \n 1 - 2 Make variables integer if possible (if obj value)\n \
40132 - 4 As above but even if zero objective value\n \
40147 - 128 Try and create cliques\n 8 - 256 If all +1 try hard for dominated rows\n \
401510 - 1024 Use a larger feasibility tolerance in presolve\n \
401611 - 2048 Try probing before creating cliques\n \
401712 - 4096 Switch off duplicate column checking for integers \n \n \
4018     Now aa 99 has special meaning i.e. just one simple presolve.");
4019    parameters.push_back(p);
4020  }
4021  {
4022    CbcOrClpParam p("two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts",
4023      "off", CBC_PARAM_STR_TWOMIRCUTS);
4024    p.append("on");
4025    p.append("root");
4026    p.append("ifmove");
4027    p.append("forceOn");
4028    p.append("onglobal");
4029    p.append("forceandglobal");
4030    p.append("forceLongOn");
4031    p.setLonghelp(
4032      "This switches on two phase mixed integer rounding  cuts (either at root or in entire tree) \
4033See branchAndCut for information on options.");
4034    parameters.push_back(p);
4035  }
4036#endif
4037  {
4038    CbcOrClpParam p("unitTest", "Do unit test",
4039      CLP_PARAM_ACTION_UNITTEST, 3, 1);
4040    p.setLonghelp(
4041      "This exercises the unit test for clp");
4042    parameters.push_back(p);
4043  }
4044  {
4045    CbcOrClpParam p("userClp", "Hand coded Clp stuff",
4046      CLP_PARAM_ACTION_USERCLP, 0, 0);
4047    p.setLonghelp(
4048      "There are times e.g. when using AMPL interface when you may wish to do something unusual.  \
4049Look for USERCLP in main driver and modify sample code.");
4050    parameters.push_back(p);
4051  }
4052#ifdef COIN_HAS_CBC
4053  {
4054    CbcOrClpParam p("userCbc", "Hand coded Cbc stuff",
4055      CBC_PARAM_ACTION_USERCBC, 0, 0);
4056    p.setLonghelp(
4057      "There are times e.g. when using AMPL interface when you may wish to do something unusual.  \
4058Look for USERCBC in main driver and modify sample code. \
4059It is possible you can get same effect by using example driver4.cpp.");
4060    parameters.push_back(p);
4061  }
4062#endif
4063#ifdef COIN_AVX2
4064  {
4065    CbcOrClpParam p("vector!Mode", "Try and use vector instructions",
4066      0, 11, CLP_PARAM_INT_VECTOR_MODE);
4067    p.setLonghelp(
4068      "At present only for Intel architectures - but could be extended.  \
4069Uses avx2 or avx512 instructions. Uses different storage for matrix - can be \
4070of benefit without instruction set on some problems.  \
4071Being lazy I have used 10 to switch on a pool matrix (11 may come later)");
4072    p.setIntValue(0);
4073    parameters.push_back(p);
4074  }
4075#endif
4076#ifdef COIN_HAS_CBC
4077  {
4078    CbcOrClpParam p("Vnd!VariableNeighborhoodSearch", "Whether to try Variable Neighborhood Search",
4079      "off", CBC_PARAM_STR_VND);
4080    p.append("on");
4081    p.append("both");
4082    p.append("before");
4083    p.append("intree");
4084    p.setLonghelp(
4085      "This switches on variable neighborhood Search. \
4086Doh option does heuristic before preprocessing");
4087    parameters.push_back(p);
4088  }
4089#endif
4090  {
4091    CbcOrClpParam p("vector", "Whether to use vector? Form of matrix in simplex",
4092      "off", CLP_PARAM_STR_VECTOR, 7, 0);
4093    p.append("on");
4094    p.setLonghelp(
4095      "If this is on ClpPackedMatrix uses extra column copy in odd format.");
4096    parameters.push_back(p);
4097  }
4098  {
4099    CbcOrClpParam p("verbose", "Switches on longer help on single ?",
4100      0, 31, CLP_PARAM_INT_VERBOSE, 0);
4101    p.setLonghelp(
4102      "Set to 1 to get short help with ? list, 2 to get long help, 3 for both.  (add 4 to just get ampl ones).");
4103    p.setIntValue(0);
4104    parameters.push_back(p);
4105  }
4106#ifdef COIN_HAS_CBC
4107  {
4108    CbcOrClpParam p("vub!heuristic", "Type of vub heuristic",
4109      -2, 20, CBC_PARAM_INT_VUBTRY, 0);
4110    p.setLonghelp(
4111      "If set will try and fix some integer variables");
4112    p.setIntValue(-1);
4113    parameters.push_back(p);
4114  }
4115  {
4116    CbcOrClpParam p("zero!HalfCuts", "Whether to use zero half cuts",
4117      "off", CBC_PARAM_STR_ZEROHALFCUTS);
4118    p.append("on");
4119    p.append("root");
4120    p.append("ifmove");
4121    p.append("forceOn");
4122    p.append("onglobal");
4123    p.setLonghelp(
4124      "This switches on zero-half cuts (either at root or in entire tree) \
4125See branchAndCut for information on options.  This implementation was written by \
4126Alberto Caprara.");
4127    parameters.push_back(p);
4128  }
4129#endif
4130  {
4131    CbcOrClpParam p("zeroT!olerance", "Kill all coefficients \
4132whose absolute value is less than this value",
4133      1.0e-100, 1.0e-5, CLP_PARAM_DBL_ZEROTOLERANCE);
4134    p.setLonghelp(
4135      "This applies to reading mps files (and also lp files \
4136if KILL_ZERO_READLP defined)");
4137    p.setDoubleValue(1.0e-20);
4138    parameters.push_back(p);
4139  }
4140}
4141// Given a parameter type - returns its number in list
4142int whichParam(const CbcOrClpParameterType &name,
4143  const std::vector< CbcOrClpParam > &parameters)
4144{
4145  for (int i = 0; i < (int)parameters.size(); i++) {
4146    if (parameters[i].type() == name)
4147      return i;
4148  }
4149  return std::numeric_limits< int >::max(); // should not arrive here
4150}
4151#ifdef COIN_HAS_CLP
4152/* Restore a solution from file.
4153   mode 0 normal, 1 swap rows and columns and primal and dual
4154   if 2 set then also change signs
4155*/
4156void restoreSolution(ClpSimplex *lpSolver, std::string fileName, int mode)
4157{
4158  FILE *fp = fopen(fileName.c_str(), "rb");
4159  if (fp) {
4160    int numberRows = lpSolver->numberRows();
4161    int numberColumns = lpSolver->numberColumns();
4162    int numberRowsFile;
4163    int numberColumnsFile;
4164    double objectiveValue;
4165    size_t nRead;
4166    nRead = fread(&numberRowsFile, sizeof(int), 1, fp);
4167    if (nRead != 1)
4168      throw("Error in fread");
4169    nRead = fread(&numberColumnsFile, sizeof(int), 1, fp);
4170    if (nRead != 1)
4171      throw("Error in fread");
4172    nRead = fread(&objectiveValue, sizeof(double), 1, fp);
4173    if (nRead != 1)
4174      throw("Error in fread");
4175    double *dualRowSolution = lpSolver->dualRowSolution();
4176    double *primalRowSolution = lpSolver->primalRowSolution();
4177    double *dualColumnSolution = lpSolver->dualColumnSolution();
4178    double *primalColumnSolution = lpSolver->primalColumnSolution();
4179    if (mode) {
4180      // swap
4181      int k = numberRows;
4182      numberRows = numberColumns;
4183      numberColumns = k;
4184      double *temp;
4185      temp = dualRowSolution;
4186      dualRowSolution = primalColumnSolution;
4187      primalColumnSolution = temp;
4188      temp = dualColumnSolution;
4189      dualColumnSolution = primalRowSolution;
4190      primalRowSolution = temp;
4191    }
4192    if (numberRows > numberRowsFile || numberColumns > numberColumnsFile) {
4193      std::cout << "Mismatch on rows and/or columns - giving up" << std::endl;
4194    } else {
4195      lpSolver->setObjectiveValue(objectiveValue);
4196      if (numberRows == numberRowsFile && numberColumns == numberColumnsFile) {
4197        nRead = fread(primalRowSolution, sizeof(double), numberRows, fp);
4198        if (nRead != static_cast< size_t >(numberRows))
4199          throw("Error in fread");
4200        nRead = fread(dualRowSolution, sizeof(double), numberRows, fp);
4201        if (nRead != static_cast< size_t >(numberRows))
4202          throw("Error in fread");
4203        nRead = fread(primalColumnSolution, sizeof(double), numberColumns, fp);
4204        if (nRead != static_cast< size_t >(numberColumns))
4205          throw("Error in fread");
4206        nRead = fread(dualColumnSolution, sizeof(double), numberColumns, fp);
4207        if (nRead != static_cast< size_t >(numberColumns))
4208          throw("Error in fread");
4209      } else {
4210        std::cout << "Mismatch on rows and/or columns - truncating" << std::endl;
4211        double *temp = new double[CoinMax(numberRowsFile, numberColumnsFile)];
4212        nRead = fread(temp, sizeof(double), numberRowsFile, fp);
4213        if (nRead != static_cast< size_t >(numberRowsFile))
4214          throw("Error in fread");
4215        CoinMemcpyN(temp, numberRows, primalRowSolution);
4216        nRead = fread(temp, sizeof(double), numberRowsFile, fp);
4217        if (nRead != static_cast< size_t >(numberRowsFile))
4218          throw("Error in fread");
4219        CoinMemcpyN(temp, numberRows, dualRowSolution);
4220        nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
4221        if (nRead != static_cast< size_t >(numberColumnsFile))
4222          throw("Error in fread");
4223        CoinMemcpyN(temp, numberColumns, primalColumnSolution);
4224        nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
4225        if (nRead != static_cast< size_t >(numberColumnsFile))
4226          throw("Error in fread");
4227        CoinMemcpyN(temp, numberColumns, dualColumnSolution);
4228        delete[] temp;
4229      }
4230      if (mode == 3) {
4231        int i;
4232        for (i = 0; i < numberRows; i++) {
4233          primalRowSolution[i] = -primalRowSolution[i];
4234          dualRowSolution[i] = -dualRowSolution[i];
4235        }
4236        for (i = 0; i < numberColumns; i++) {
4237          primalColumnSolution[i] = -primalColumnSolution[i];
4238          dualColumnSolution[i] = -dualColumnSolution[i];
4239        }
4240      }
4241    }
4242    fclose(fp);
4243  } else {
4244    std::cout << "Unable to open file " << fileName << std::endl;
4245  }
4246}
4247// Dump a solution to file
4248void saveSolution(const ClpSimplex *lpSolver, std::string fileName)
4249{
4250  if (strstr(fileName.c_str(), "_fix_read_")) {
4251    FILE *fp = fopen(fileName.c_str(), "rb");
4252    if (fp) {
4253      ClpSimplex *solver = const_cast< ClpSimplex * >(lpSolver);
4254      restoreSolution(solver, fileName, 0);
4255      // fix all
4256      int logLevel = solver->logLevel();
4257      int iColumn;
4258      int numberColumns = solver->numberColumns();
4259      double *primalColumnSolution = solver->primalColumnSolution();
4260      double *columnLower = solver->columnLower();
4261      double *columnUpper = solver->columnUpper();
4262      for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4263        double value = primalColumnSolution[iColumn];
4264        if (value > columnUpper[iColumn]) {
4265          if (value > columnUpper[iColumn] + 1.0e-6 && logLevel > 1)
4266            printf("%d value of %g - bounds %g %g\n",
4267              iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
4268          value = columnUpper[iColumn];
4269        } else if (value < columnLower[iColumn]) {
4270          if (value < columnLower[iColumn] - 1.0e-6 && logLevel > 1)
4271            printf("%d value of %g - bounds %g %g\n",
4272              iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
4273          value = columnLower[iColumn];
4274        }
4275        columnLower[iColumn] = value;
4276        columnUpper[iColumn] = value;
4277      }
4278      return;
4279    }
4280  }
4281  FILE *fp = fopen(fileName.c_str(), "wb");
4282  if (fp) {
4283    int numberRows = lpSolver->numberRows();
4284    int numberColumns = lpSolver->numberColumns();
4285    double objectiveValue = lpSolver->objectiveValue();
4286    size_t nWrite;
4287    nWrite = fwrite(&numberRows, sizeof(int), 1, fp);
4288    if (nWrite != 1)
4289      throw("Error in fwrite");
4290    nWrite = fwrite(&numberColumns, sizeof(int), 1, fp);
4291    if (nWrite != 1)
4292      throw("Error in fwrite");
4293    nWrite = fwrite(&objectiveValue, sizeof(double), 1, fp);
4294    if (nWrite != 1)
4295      throw("Error in fwrite");
4296    double *dualRowSolution = lpSolver->dualRowSolution();
4297    double *primalRowSolution = lpSolver->primalRowSolution();
4298    nWrite = fwrite(primalRowSolution, sizeof(double), numberRows, fp);
4299    if (nWrite != static_cast< size_t >(numberRows))
4300      throw("Error in fwrite");
4301    nWrite = fwrite(dualRowSolution, sizeof(double), numberRows, fp);
4302    if (nWrite != static_cast< size_t >(numberRows))
4303      throw("Error in fwrite");
4304    double *dualColumnSolution = lpSolver->dualColumnSolution();
4305    double *primalColumnSolution = lpSolver->primalColumnSolution();
4306    nWrite = fwrite(primalColumnSolution, sizeof(double), numberColumns, fp);
4307    if (nWrite != static_cast< size_t >(numberColumns))
4308      throw("Error in fwrite");
4309    nWrite = fwrite(dualColumnSolution, sizeof(double), numberColumns, fp);
4310    if (nWrite != static_cast< size_t >(numberColumns))
4311      throw("Error in fwrite");
4312    fclose(fp);
4313  } else {
4314    std::cout << "Unable to open file " << fileName << std::endl;
4315  }
4316}
4317#endif
4318
4319/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
4320*/
Note: See TracBrowser for help on using the repository browser.