summaryrefslogtreecommitdiff
path: root/thirdparty/linux/include/coin1/CbcOrClpParam.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/linux/include/coin1/CbcOrClpParam.cpp')
-rw-r--r--thirdparty/linux/include/coin1/CbcOrClpParam.cpp4104
1 files changed, 4104 insertions, 0 deletions
diff --git a/thirdparty/linux/include/coin1/CbcOrClpParam.cpp b/thirdparty/linux/include/coin1/CbcOrClpParam.cpp
new file mode 100644
index 0000000..b434fe0
--- /dev/null
+++ b/thirdparty/linux/include/coin1/CbcOrClpParam.cpp
@@ -0,0 +1,4104 @@
+/* $Id: CbcOrClpParam.cpp 2079 2015-01-05 13:11:35Z forrest $ */
+// Copyright (C) 2002, International Business Machines
+// Corporation and others. All Rights Reserved.
+// This code is licensed under the terms of the Eclipse Public License (EPL).
+
+#include "CoinPragma.hpp"
+#include "CoinTime.hpp"
+#include "CbcOrClpParam.hpp"
+
+#include <string>
+#include <iostream>
+#include <cassert>
+
+#ifdef COIN_HAS_CBC
+#ifdef COIN_HAS_CLP
+#include "OsiClpSolverInterface.hpp"
+#include "ClpSimplex.hpp"
+#endif
+#include "CbcModel.hpp"
+#endif
+#include "CoinHelperFunctions.hpp"
+#ifdef COIN_HAS_CLP
+#include "ClpSimplex.hpp"
+#include "ClpFactorization.hpp"
+#endif
+#ifdef COIN_HAS_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+#ifdef COIN_HAS_CBC
+// from CoinSolve
+static char coin_prompt[] = "Coin:";
+#else
+static char coin_prompt[] = "Clp:";
+#endif
+#ifdef CLP_CILK
+#ifndef CBC_THREAD
+#define CBC_THREAD
+#endif
+#endif
+#if defined(COIN_HAS_WSMP) && ! defined(USE_EKKWSSMP)
+#ifndef CBC_THREAD
+#define CBC_THREAD
+#endif
+#endif
+#include "ClpConfig.h"
+#ifdef CLP_HAS_ABC
+#include "AbcCommon.hpp"
+#endif
+static bool doPrinting = true;
+std::string afterEquals = "";
+static char printArray[200];
+#if COIN_INT_MAX==0
+#undef COIN_INT_MAX
+#define COIN_INT_MAX 2147483647
+#endif
+void setCbcOrClpPrinting(bool yesNo)
+{
+ doPrinting = yesNo;
+}
+//#############################################################################
+// Constructors / Destructor / Assignment
+//#############################################################################
+
+//-------------------------------------------------------------------
+// Default Constructor
+//-------------------------------------------------------------------
+CbcOrClpParam::CbcOrClpParam ()
+ : type_(CBC_PARAM_NOTUSED_INVALID),
+ lowerDoubleValue_(0.0),
+ upperDoubleValue_(0.0),
+ lowerIntValue_(0),
+ upperIntValue_(0),
+ lengthName_(0),
+ lengthMatch_(0),
+ definedKeyWords_(),
+ name_(),
+ shortHelp_(),
+ longHelp_(),
+ action_(CBC_PARAM_NOTUSED_INVALID),
+ currentKeyWord_(-1),
+ display_(0),
+ intValue_(-1),
+ doubleValue_(-1.0),
+ stringValue_(""),
+ whereUsed_(7),
+ fakeKeyWord_(-1),
+ fakeValue_(0)
+{
+}
+// Other constructors
+CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
+ double lower, double upper, CbcOrClpParameterType type,
+ int display)
+ : type_(type),
+ lowerIntValue_(0),
+ upperIntValue_(0),
+ definedKeyWords_(),
+ name_(name),
+ shortHelp_(help),
+ longHelp_(),
+ action_(type),
+ currentKeyWord_(-1),
+ display_(display),
+ intValue_(-1),
+ doubleValue_(-1.0),
+ stringValue_(""),
+ whereUsed_(7),
+ fakeKeyWord_(-1),
+ fakeValue_(0)
+{
+ lowerDoubleValue_ = lower;
+ upperDoubleValue_ = upper;
+ gutsOfConstructor();
+}
+CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
+ int lower, int upper, CbcOrClpParameterType type,
+ int display)
+ : type_(type),
+ lowerDoubleValue_(0.0),
+ upperDoubleValue_(0.0),
+ definedKeyWords_(),
+ name_(name),
+ shortHelp_(help),
+ longHelp_(),
+ action_(type),
+ currentKeyWord_(-1),
+ display_(display),
+ intValue_(-1),
+ doubleValue_(-1.0),
+ stringValue_(""),
+ whereUsed_(7),
+ fakeKeyWord_(-1),
+ fakeValue_(0)
+{
+ gutsOfConstructor();
+ lowerIntValue_ = lower;
+ upperIntValue_ = upper;
+}
+// Other strings will be added by append
+CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
+ std::string firstValue,
+ CbcOrClpParameterType type, int whereUsed,
+ int display)
+ : type_(type),
+ lowerDoubleValue_(0.0),
+ upperDoubleValue_(0.0),
+ lowerIntValue_(0),
+ upperIntValue_(0),
+ definedKeyWords_(),
+ name_(name),
+ shortHelp_(help),
+ longHelp_(),
+ action_(type),
+ currentKeyWord_(0),
+ display_(display),
+ intValue_(-1),
+ doubleValue_(-1.0),
+ stringValue_(""),
+ whereUsed_(whereUsed),
+ fakeKeyWord_(-1),
+ fakeValue_(0)
+{
+ gutsOfConstructor();
+ definedKeyWords_.push_back(firstValue);
+}
+// Action
+CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
+ CbcOrClpParameterType type, int whereUsed,
+ int display)
+ : type_(type),
+ lowerDoubleValue_(0.0),
+ upperDoubleValue_(0.0),
+ lowerIntValue_(0),
+ upperIntValue_(0),
+ definedKeyWords_(),
+ name_(name),
+ shortHelp_(help),
+ longHelp_(),
+ action_(type),
+ currentKeyWord_(-1),
+ display_(display),
+ intValue_(-1),
+ doubleValue_(-1.0),
+ stringValue_(""),
+ fakeKeyWord_(-1),
+ fakeValue_(0)
+{
+ whereUsed_ = whereUsed;
+ gutsOfConstructor();
+}
+
+//-------------------------------------------------------------------
+// Copy constructor
+//-------------------------------------------------------------------
+CbcOrClpParam::CbcOrClpParam (const CbcOrClpParam & rhs)
+{
+ type_ = rhs.type_;
+ lowerDoubleValue_ = rhs.lowerDoubleValue_;
+ upperDoubleValue_ = rhs.upperDoubleValue_;
+ lowerIntValue_ = rhs.lowerIntValue_;
+ upperIntValue_ = rhs.upperIntValue_;
+ lengthName_ = rhs.lengthName_;
+ lengthMatch_ = rhs.lengthMatch_;
+ definedKeyWords_ = rhs.definedKeyWords_;
+ name_ = rhs.name_;
+ shortHelp_ = rhs.shortHelp_;
+ longHelp_ = rhs.longHelp_;
+ action_ = rhs.action_;
+ currentKeyWord_ = rhs.currentKeyWord_;
+ display_ = rhs.display_;
+ intValue_ = rhs.intValue_;
+ doubleValue_ = rhs.doubleValue_;
+ stringValue_ = rhs.stringValue_;
+ whereUsed_ = rhs.whereUsed_;
+ fakeKeyWord_ = rhs.fakeKeyWord_;
+ fakeValue_ = rhs.fakeValue_;
+}
+
+//-------------------------------------------------------------------
+// Destructor
+//-------------------------------------------------------------------
+CbcOrClpParam::~CbcOrClpParam ()
+{
+}
+
+//----------------------------------------------------------------
+// Assignment operator
+//-------------------------------------------------------------------
+CbcOrClpParam &
+CbcOrClpParam::operator=(const CbcOrClpParam & rhs)
+{
+ if (this != &rhs) {
+ type_ = rhs.type_;
+ lowerDoubleValue_ = rhs.lowerDoubleValue_;
+ upperDoubleValue_ = rhs.upperDoubleValue_;
+ lowerIntValue_ = rhs.lowerIntValue_;
+ upperIntValue_ = rhs.upperIntValue_;
+ lengthName_ = rhs.lengthName_;
+ lengthMatch_ = rhs.lengthMatch_;
+ definedKeyWords_ = rhs.definedKeyWords_;
+ name_ = rhs.name_;
+ shortHelp_ = rhs.shortHelp_;
+ longHelp_ = rhs.longHelp_;
+ action_ = rhs.action_;
+ currentKeyWord_ = rhs.currentKeyWord_;
+ display_ = rhs.display_;
+ intValue_ = rhs.intValue_;
+ doubleValue_ = rhs.doubleValue_;
+ stringValue_ = rhs.stringValue_;
+ whereUsed_ = rhs.whereUsed_;
+ fakeKeyWord_ = rhs.fakeKeyWord_;
+ fakeValue_ = rhs.fakeValue_;
+ }
+ return *this;
+}
+void
+CbcOrClpParam::gutsOfConstructor()
+{
+ std::string::size_type shriekPos = name_.find('!');
+ lengthName_ = static_cast<unsigned int>(name_.length());
+ if ( shriekPos == std::string::npos ) {
+ //does not contain '!'
+ lengthMatch_ = lengthName_;
+ } else {
+ lengthMatch_ = static_cast<unsigned int>(shriekPos);
+ name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1);
+ lengthName_--;
+ }
+}
+// Sets value of fake keyword to current size of keywords
+void
+CbcOrClpParam::setFakeKeyWord(int fakeValue)
+{
+ fakeKeyWord_ = static_cast<int>(definedKeyWords_.size());
+ assert (fakeKeyWord_>0);
+ fakeValue_ = fakeValue;
+ assert (fakeValue_>=0);
+}
+/* Returns current parameter option position
+ but if fake keyword returns fakeValue_
+*/
+int
+CbcOrClpParam::currentOptionAsInteger ( ) const
+{
+ int fakeInteger;
+ return currentOptionAsInteger(fakeInteger);
+}
+/* Returns current parameter option position
+ but if fake keyword returns fakeValue_ and sets
+ fakeInteger to value
+*/
+int
+CbcOrClpParam::currentOptionAsInteger ( int & fakeInteger ) const
+{
+ fakeInteger=-COIN_INT_MAX;
+ if (fakeKeyWord_<0) {
+ return currentKeyWord_;
+ } else if (currentKeyWord_>=0&&currentKeyWord_<fakeKeyWord_){
+ return currentKeyWord_;
+ } else {
+ // fake
+ if (currentKeyWord_<0)
+ fakeInteger = currentKeyWord_ + 1000;
+ else
+ fakeInteger = currentKeyWord_ - 1000;
+ return fakeValue_;
+ }
+}
+// Returns length of name for printing
+int
+CbcOrClpParam::lengthMatchName ( ) const
+{
+ if (lengthName_ == lengthMatch_)
+ return lengthName_;
+ else
+ return lengthName_ + 2;
+}
+// Insert string (only valid for keywords)
+void
+CbcOrClpParam::append(std::string keyWord)
+{
+ definedKeyWords_.push_back(keyWord);
+}
+
+int
+CbcOrClpParam::matches (std::string input) const
+{
+ // look up strings to do more elegantly
+ if (input.length() > lengthName_) {
+ return 0;
+ } else {
+ unsigned int i;
+ for (i = 0; i < input.length(); i++) {
+ if (tolower(name_[i]) != tolower(input[i]))
+ break;
+ }
+ if (i < input.length()) {
+ return 0;
+ } else if (i >= lengthMatch_) {
+ return 1;
+ } else {
+ // matched but too short
+ return 2;
+ }
+ }
+}
+// Returns name which could match
+std::string
+CbcOrClpParam::matchName ( ) const
+{
+ if (lengthMatch_ == lengthName_)
+ return name_;
+ else
+ return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + ")";
+}
+
+// Returns parameter option which matches (-1 if none)
+int
+CbcOrClpParam::parameterOption ( std::string check ) const
+{
+ int numberItems = static_cast<int>(definedKeyWords_.size());
+ if (!numberItems) {
+ return -1;
+ } else {
+ int whichItem = 0;
+ unsigned int it;
+ for (it = 0; it < definedKeyWords_.size(); it++) {
+ std::string thisOne = definedKeyWords_[it];
+ std::string::size_type shriekPos = thisOne.find('!');
+ size_t length1 = thisOne.length();
+ size_t length2 = length1;
+ if ( shriekPos != std::string::npos ) {
+ //contains '!'
+ length2 = shriekPos;
+ thisOne = thisOne.substr(0, shriekPos) +
+ thisOne.substr(shriekPos + 1);
+ length1 = thisOne.length();
+ }
+ if (check.length() <= length1 && length2 <= check.length()) {
+ unsigned int i;
+ for (i = 0; i < check.length(); i++) {
+ if (tolower(thisOne[i]) != tolower(check[i]))
+ break;
+ }
+ if (i < check.length()) {
+ whichItem++;
+ } else if (i >= length2) {
+ break;
+ }
+ } else {
+ whichItem++;
+ }
+ }
+ if (whichItem < numberItems) {
+ return whichItem;
+ } else {
+ if (fakeKeyWord_<=0)
+ return -1;
+ // allow plus or minus
+ int n;
+ if (check.substr(0,4)=="plus"||check.substr(0,4)=="PLUS") {
+ n = 4;
+ } else if (check.substr(0,5)=="minus"||check.substr(0,5)=="MINUS") {
+ n = 5;
+ } else {
+ return -1;
+ }
+ int value = 0;
+ std::string field=check.substr(n);
+ if (field != "EOL") {
+ const char * start = field.c_str();
+ char * endPointer = NULL;
+ // check valid
+ value = static_cast<int>(strtol(start, &endPointer, 10));
+ if (*endPointer != '\0') {
+ return -1;
+ }
+ if (n==4)
+ return value + 1000;
+ else
+ return -value - 1000;
+ } else {
+ return -1;
+ }
+ }
+ }
+}
+// Prints parameter options
+void
+CbcOrClpParam::printOptions ( ) const
+{
+ std::cout << "<Possible options for " << name_ << " are:";
+ unsigned int it;
+ for (it = 0; it < definedKeyWords_.size(); it++) {
+ std::string thisOne = definedKeyWords_[it];
+ std::string::size_type shriekPos = thisOne.find('!');
+ if ( shriekPos != std::string::npos ) {
+ //contains '!'
+ thisOne = thisOne.substr(0, shriekPos) +
+ "(" + thisOne.substr(shriekPos + 1) + ")";
+ }
+ std::cout << " " << thisOne;
+ }
+ assert (currentKeyWord_ >= 0 && currentKeyWord_ < static_cast<int>(definedKeyWords_.size()));
+ std::string current = definedKeyWords_[currentKeyWord_];
+ std::string::size_type shriekPos = current.find('!');
+ if ( shriekPos != std::string::npos ) {
+ //contains '!'
+ current = current.substr(0, shriekPos) +
+ "(" + current.substr(shriekPos + 1) + ")";
+ }
+ std::cout << ";\n\tcurrent " << current << ">" << std::endl;
+}
+// Print action and string
+void
+CbcOrClpParam::printString() const
+{
+ if (name_ == "directory")
+ std::cout << "Current working directory is " << stringValue_ << std::endl;
+ else if (name_.substr(0, 6) == "printM")
+ std::cout << "Current value of printMask is " << stringValue_ << std::endl;
+ else
+ std::cout << "Current default (if $ as parameter) for " << name_
+ << " is " << stringValue_ << std::endl;
+}
+void CoinReadPrintit(const char * input)
+{
+ int length = static_cast<int>(strlen(input));
+ char temp[101];
+ int i;
+ int n = 0;
+ for (i = 0; i < length; i++) {
+ if (input[i] == '\n') {
+ temp[n] = '\0';
+ std::cout << temp << std::endl;
+ n = 0;
+ } else if (n >= 65 && input[i] == ' ') {
+ temp[n] = '\0';
+ std::cout << temp << std::endl;
+ n = 0;
+ } else if (n || input[i] != ' ') {
+ temp[n++] = input[i];
+ }
+ }
+ if (n) {
+ temp[n] = '\0';
+ std::cout << temp << std::endl;
+ }
+}
+// Print Long help
+void
+CbcOrClpParam::printLongHelp() const
+{
+ if (type_ >= 1 && type_ < 400) {
+ CoinReadPrintit(longHelp_.c_str());
+ if (type_ < CLP_PARAM_INT_SOLVERLOGLEVEL) {
+ printf("<Range of values is %g to %g;\n\tcurrent %g>\n", lowerDoubleValue_, upperDoubleValue_, doubleValue_);
+ assert (upperDoubleValue_ > lowerDoubleValue_);
+ } else if (type_ < CLP_PARAM_STR_DIRECTION) {
+ printf("<Range of values is %d to %d;\n\tcurrent %d>\n", lowerIntValue_, upperIntValue_, intValue_);
+ assert (upperIntValue_ > lowerIntValue_);
+ } else if (type_ < CLP_PARAM_ACTION_DIRECTORY) {
+ printOptions();
+ }
+ }
+}
+#ifdef COIN_HAS_CBC
+int
+CbcOrClpParam::setDoubleParameter (OsiSolverInterface * model, double value)
+{
+ int returnCode;
+ setDoubleParameterWithMessage(model, value, returnCode);
+ if (doPrinting && strlen(printArray))
+ std::cout << printArray << std::endl;
+ return returnCode;
+}
+// Sets double parameter and returns printable string and error code
+const char *
+CbcOrClpParam::setDoubleParameterWithMessage ( OsiSolverInterface * model, double value , int & returnCode)
+{
+ if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
+ sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
+ value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
+ std::cout << value << " was provided for " << name_ <<
+ " - valid range is " << lowerDoubleValue_ << " to " <<
+ upperDoubleValue_ << std::endl;
+ returnCode = 1;
+ } else {
+ double oldValue = doubleValue_;
+ doubleValue_ = value;
+ switch (type_) {
+ case CLP_PARAM_DBL_DUALTOLERANCE:
+ model->getDblParam(OsiDualTolerance, oldValue);
+ model->setDblParam(OsiDualTolerance, value);
+ break;
+ case CLP_PARAM_DBL_PRIMALTOLERANCE:
+ model->getDblParam(OsiPrimalTolerance, oldValue);
+ model->setDblParam(OsiPrimalTolerance, value);
+ break;
+ default:
+ break;
+ }
+ sprintf(printArray, "%s was changed from %g to %g",
+ name_.c_str(), oldValue, value);
+ returnCode = 0;
+ }
+ return printArray;
+}
+#endif
+#ifdef COIN_HAS_CLP
+int
+CbcOrClpParam::setDoubleParameter (ClpSimplex * model, double value)
+{
+ int returnCode;
+ setDoubleParameterWithMessage(model, value, returnCode);
+ if (doPrinting && strlen(printArray))
+ std::cout << printArray << std::endl;
+ return returnCode;
+}
+// Sets int parameter and returns printable string and error code
+const char *
+CbcOrClpParam::setDoubleParameterWithMessage ( ClpSimplex * model, double value , int & returnCode)
+{
+ double oldValue = doubleValue_;
+ if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
+ sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
+ value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
+ returnCode = 1;
+ } else {
+ sprintf(printArray, "%s was changed from %g to %g",
+ name_.c_str(), oldValue, value);
+ returnCode = 0;
+ doubleValue_ = value;
+ switch (type_) {
+ case CLP_PARAM_DBL_DUALTOLERANCE:
+ model->setDualTolerance(value);
+ break;
+ case CLP_PARAM_DBL_PRIMALTOLERANCE:
+ model->setPrimalTolerance(value);
+ break;
+ case CLP_PARAM_DBL_ZEROTOLERANCE:
+ model->setSmallElementValue(value);
+ break;
+ case CLP_PARAM_DBL_DUALBOUND:
+ model->setDualBound(value);
+ break;
+ case CLP_PARAM_DBL_PRIMALWEIGHT:
+ model->setInfeasibilityCost(value);
+ break;
+#ifndef COIN_HAS_CBC
+ case CLP_PARAM_DBL_TIMELIMIT:
+ model->setMaximumSeconds(value);
+ break;
+#endif
+ case CLP_PARAM_DBL_OBJSCALE:
+ model->setObjectiveScale(value);
+ break;
+ case CLP_PARAM_DBL_RHSSCALE:
+ model->setRhsScale(value);
+ break;
+ case CLP_PARAM_DBL_PRESOLVETOLERANCE:
+ model->setDblParam(ClpPresolveTolerance, value);
+ break;
+ default:
+ break;
+ }
+ }
+ return printArray;
+}
+double
+CbcOrClpParam::doubleParameter (ClpSimplex * model) const
+{
+ double value;
+ switch (type_) {
+#ifndef COIN_HAS_CBC
+ case CLP_PARAM_DBL_DUALTOLERANCE:
+ value = model->dualTolerance();
+ break;
+ case CLP_PARAM_DBL_PRIMALTOLERANCE:
+ value = model->primalTolerance();
+ break;
+#endif
+ case CLP_PARAM_DBL_ZEROTOLERANCE:
+ value = model->getSmallElementValue();
+ break;
+ case CLP_PARAM_DBL_DUALBOUND:
+ value = model->dualBound();
+ break;
+ case CLP_PARAM_DBL_PRIMALWEIGHT:
+ value = model->infeasibilityCost();
+ break;
+#ifndef COIN_HAS_CBC
+ case CLP_PARAM_DBL_TIMELIMIT:
+ value = model->maximumSeconds();
+ break;
+#endif
+ case CLP_PARAM_DBL_OBJSCALE:
+ value = model->objectiveScale();
+ break;
+ case CLP_PARAM_DBL_RHSSCALE:
+ value = model->rhsScale();
+ break;
+ default:
+ value = doubleValue_;
+ break;
+ }
+ return value;
+}
+int
+CbcOrClpParam::setIntParameter (ClpSimplex * model, int value)
+{
+ int returnCode;
+ setIntParameterWithMessage(model, value, returnCode);
+ if (doPrinting && strlen(printArray))
+ std::cout << printArray << std::endl;
+ return returnCode;
+}
+// Sets int parameter and returns printable string and error code
+const char *
+CbcOrClpParam::setIntParameterWithMessage ( ClpSimplex * model, int value , int & returnCode)
+{
+ int oldValue = intValue_;
+ if (value < lowerIntValue_ || value > upperIntValue_) {
+ sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
+ value, name_.c_str(), lowerIntValue_, upperIntValue_);
+ returnCode = 1;
+ } else {
+ intValue_ = value;
+ sprintf(printArray, "%s was changed from %d to %d",
+ name_.c_str(), oldValue, value);
+ returnCode = 0;
+ switch (type_) {
+ case CLP_PARAM_INT_SOLVERLOGLEVEL:
+ model->setLogLevel(value);
+ if (value > 2)
+ model->factorization()->messageLevel(8);
+ else
+ model->factorization()->messageLevel(0);
+ break;
+ case CLP_PARAM_INT_MAXFACTOR:
+ model->factorization()->maximumPivots(value);
+ break;
+ case CLP_PARAM_INT_PERTVALUE:
+ model->setPerturbation(value);
+ break;
+ case CLP_PARAM_INT_MAXITERATION:
+ model->setMaximumIterations(value);
+ break;
+ case CLP_PARAM_INT_SPECIALOPTIONS:
+ model->setSpecialOptions(value);
+ break;
+ case CLP_PARAM_INT_RANDOMSEED:
+ {
+ if (value==0) {
+ double time = fabs(CoinGetTimeOfDay());
+ while (time>=COIN_INT_MAX)
+ time *= 0.5;
+ value = static_cast<int>(time);
+ sprintf(printArray, "using time of day %s was changed from %d to %d",
+ name_.c_str(), oldValue, value);
+ }
+ model->setRandomSeed(value);
+ }
+ break;
+ case CLP_PARAM_INT_MORESPECIALOPTIONS:
+ model->setMoreSpecialOptions(value);
+ break;
+#ifndef COIN_HAS_CBC
+#ifdef CBC_THREAD
+ case CBC_PARAM_INT_THREADS:
+ model->setNumberThreads(value);
+ break;
+#endif
+#endif
+ default:
+ break;
+ }
+ }
+ return printArray;
+}
+int
+CbcOrClpParam::intParameter (ClpSimplex * model) const
+{
+ int value;
+ switch (type_) {
+#ifndef COIN_HAS_CBC
+ case CLP_PARAM_INT_SOLVERLOGLEVEL:
+ value = model->logLevel();
+ break;
+#endif
+ case CLP_PARAM_INT_MAXFACTOR:
+ value = model->factorization()->maximumPivots();
+ break;
+ break;
+ case CLP_PARAM_INT_PERTVALUE:
+ value = model->perturbation();
+ break;
+ case CLP_PARAM_INT_MAXITERATION:
+ value = model->maximumIterations();
+ break;
+ case CLP_PARAM_INT_SPECIALOPTIONS:
+ value = model->specialOptions();
+ break;
+ case CLP_PARAM_INT_RANDOMSEED:
+ value = model->randomNumberGenerator()->getSeed();
+ break;
+ case CLP_PARAM_INT_MORESPECIALOPTIONS:
+ value = model->moreSpecialOptions();
+ break;
+#ifndef COIN_HAS_CBC
+#ifdef CBC_THREAD
+ case CBC_PARAM_INT_THREADS:
+ value = model->numberThreads();
+ break;
+#endif
+#endif
+ default:
+ value = intValue_;
+ break;
+ }
+ return value;
+}
+#endif
+int
+CbcOrClpParam::checkDoubleParameter (double value) const
+{
+ if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
+ std::cout << value << " was provided for " << name_ <<
+ " - valid range is " << lowerDoubleValue_ << " to " <<
+ upperDoubleValue_ << std::endl;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+#ifdef COIN_HAS_CBC
+double
+CbcOrClpParam::doubleParameter (OsiSolverInterface *
+#ifndef NDEBUG
+ model
+#endif
+ ) const
+{
+ double value = 0.0;
+ switch (type_) {
+ case CLP_PARAM_DBL_DUALTOLERANCE:
+ assert(model->getDblParam(OsiDualTolerance, value));
+ break;
+ case CLP_PARAM_DBL_PRIMALTOLERANCE:
+ assert(model->getDblParam(OsiPrimalTolerance, value));
+ break;
+ default:
+ return doubleValue_;
+ break;
+ }
+ return value;
+}
+int
+CbcOrClpParam::setIntParameter (OsiSolverInterface * model, int value)
+{
+ int returnCode;
+ setIntParameterWithMessage(model, value, returnCode);
+ if (doPrinting && strlen(printArray))
+ std::cout << printArray << std::endl;
+ return returnCode;
+}
+// Sets int parameter and returns printable string and error code
+const char *
+CbcOrClpParam::setIntParameterWithMessage ( OsiSolverInterface * model, int value , int & returnCode)
+{
+ if (value < lowerIntValue_ || value > upperIntValue_) {
+ sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
+ value, name_.c_str(), lowerIntValue_, upperIntValue_);
+ returnCode = 1;
+ } else {
+ int oldValue = intValue_;
+ intValue_ = oldValue;
+ switch (type_) {
+ case CLP_PARAM_INT_SOLVERLOGLEVEL:
+ model->messageHandler()->setLogLevel(value);
+ break;
+ default:
+ break;
+ }
+ sprintf(printArray, "%s was changed from %d to %d",
+ name_.c_str(), oldValue, value);
+ returnCode = 0;
+ }
+ return printArray;
+}
+int
+CbcOrClpParam::intParameter (OsiSolverInterface * model) const
+{
+ int value = 0;
+ switch (type_) {
+ case CLP_PARAM_INT_SOLVERLOGLEVEL:
+ value = model->messageHandler()->logLevel();
+ break;
+ default:
+ value = intValue_;
+ break;
+ }
+ return value;
+}
+int
+CbcOrClpParam::setDoubleParameter (CbcModel &model, double value)
+{
+ int returnCode=0;
+ setDoubleParameterWithMessage(model, value, returnCode);
+ if (doPrinting && strlen(printArray))
+ std::cout << printArray << std::endl;
+ return returnCode;
+}
+// Sets double parameter and returns printable string and error code
+const char *
+CbcOrClpParam::setDoubleParameterWithMessage ( CbcModel & model, double value , int & returnCode)
+{
+ if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
+ sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
+ value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
+ returnCode = 1;
+ } else {
+ double oldValue = doubleValue_;
+ doubleValue_ = value;
+ switch (type_) {
+ case CBC_PARAM_DBL_INFEASIBILITYWEIGHT:
+ oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight);
+ model.setDblParam(CbcModel::CbcInfeasibilityWeight, value);
+ break;
+ case CBC_PARAM_DBL_INTEGERTOLERANCE:
+ oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance);
+ model.setDblParam(CbcModel::CbcIntegerTolerance, value);
+ break;
+ case CBC_PARAM_DBL_INCREMENT:
+ oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement);
+ model.setDblParam(CbcModel::CbcCutoffIncrement, value);
+ case CBC_PARAM_DBL_ALLOWABLEGAP:
+ oldValue = model.getDblParam(CbcModel::CbcAllowableGap);
+ model.setDblParam(CbcModel::CbcAllowableGap, value);
+ break;
+ case CBC_PARAM_DBL_GAPRATIO:
+ oldValue = model.getDblParam(CbcModel::CbcAllowableFractionGap);
+ model.setDblParam(CbcModel::CbcAllowableFractionGap, value);
+ break;
+ case CBC_PARAM_DBL_CUTOFF:
+ oldValue = model.getCutoff();
+ model.setCutoff(value);
+ break;
+ case CBC_PARAM_DBL_TIMELIMIT_BAB:
+ oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds) ;
+ {
+ //OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model.solver());
+ //ClpSimplex * lpSolver = clpSolver->getModelPtr();
+ //lpSolver->setMaximumSeconds(value);
+ model.setDblParam(CbcModel::CbcMaximumSeconds, value) ;
+ }
+ break ;
+ case CLP_PARAM_DBL_DUALTOLERANCE:
+ case CLP_PARAM_DBL_PRIMALTOLERANCE:
+ setDoubleParameter(model.solver(), value);
+ return 0; // to avoid message
+ default:
+ break;
+ }
+ sprintf(printArray, "%s was changed from %g to %g",
+ name_.c_str(), oldValue, value);
+ returnCode = 0;
+ }
+ return printArray;
+}
+double
+CbcOrClpParam::doubleParameter (CbcModel &model) const
+{
+ double value;
+ switch (type_) {
+ case CBC_PARAM_DBL_INFEASIBILITYWEIGHT:
+ value = model.getDblParam(CbcModel::CbcInfeasibilityWeight);
+ break;
+ case CBC_PARAM_DBL_INTEGERTOLERANCE:
+ value = model.getDblParam(CbcModel::CbcIntegerTolerance);
+ break;
+ case CBC_PARAM_DBL_INCREMENT:
+ value = model.getDblParam(CbcModel::CbcCutoffIncrement);
+ break;
+ case CBC_PARAM_DBL_ALLOWABLEGAP:
+ value = model.getDblParam(CbcModel::CbcAllowableGap);
+ break;
+ case CBC_PARAM_DBL_GAPRATIO:
+ value = model.getDblParam(CbcModel::CbcAllowableFractionGap);
+ break;
+ case CBC_PARAM_DBL_CUTOFF:
+ value = model.getCutoff();
+ break;
+ case CBC_PARAM_DBL_TIMELIMIT_BAB:
+ value = model.getDblParam(CbcModel::CbcMaximumSeconds) ;
+ break ;
+ case CLP_PARAM_DBL_DUALTOLERANCE:
+ case CLP_PARAM_DBL_PRIMALTOLERANCE:
+ value = doubleParameter(model.solver());
+ break;
+ default:
+ value = doubleValue_;
+ break;
+ }
+ return value;
+}
+int
+CbcOrClpParam::setIntParameter (CbcModel &model, int value)
+{
+ int returnCode;
+ setIntParameterWithMessage(model, value, returnCode);
+ if (doPrinting && strlen(printArray))
+ std::cout << printArray << std::endl;
+ return returnCode;
+}
+// Sets int parameter and returns printable string and error code
+const char *
+CbcOrClpParam::setIntParameterWithMessage ( CbcModel & model, int value , int & returnCode)
+{
+ if (value < lowerIntValue_ || value > upperIntValue_) {
+ sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
+ value, name_.c_str(), lowerIntValue_, upperIntValue_);
+ returnCode = 1;
+ } else {
+ printArray[0] = '\0';
+ if (value==intValue_)
+ return printArray;
+ int oldValue = intValue_;
+ intValue_ = value;
+ switch (type_) {
+ case CLP_PARAM_INT_LOGLEVEL:
+ oldValue = model.messageHandler()->logLevel();
+ model.messageHandler()->setLogLevel(CoinAbs(value));
+ break;
+ case CLP_PARAM_INT_SOLVERLOGLEVEL:
+ oldValue = model.solver()->messageHandler()->logLevel();
+ model.solver()->messageHandler()->setLogLevel(value);
+ break;
+ case CBC_PARAM_INT_MAXNODES:
+ oldValue = model.getIntParam(CbcModel::CbcMaxNumNode);
+ model.setIntParam(CbcModel::CbcMaxNumNode, value);
+ break;
+ case CBC_PARAM_INT_MAXSOLS:
+ oldValue = model.getIntParam(CbcModel::CbcMaxNumSol);
+ model.setIntParam(CbcModel::CbcMaxNumSol, value);
+ break;
+ case CBC_PARAM_INT_MAXSAVEDSOLS:
+ oldValue = model.maximumSavedSolutions();
+ model.setMaximumSavedSolutions(value);
+ break;
+ case CBC_PARAM_INT_STRONGBRANCHING:
+ oldValue = model.numberStrong();
+ model.setNumberStrong(value);
+ break;
+ case CBC_PARAM_INT_NUMBERBEFORE:
+ oldValue = model.numberBeforeTrust();
+ model.setNumberBeforeTrust(value);
+ break;
+ case CBC_PARAM_INT_NUMBERANALYZE:
+ oldValue = model.numberAnalyzeIterations();
+ model.setNumberAnalyzeIterations(value);
+ break;
+ case CBC_PARAM_INT_CUTPASSINTREE:
+ oldValue = model.getMaximumCutPasses();
+ model.setMaximumCutPasses(value);
+ break;
+ case CBC_PARAM_INT_CUTPASS:
+ oldValue = model.getMaximumCutPassesAtRoot();
+ model.setMaximumCutPassesAtRoot(value);
+ break;
+#ifdef COIN_HAS_CBC
+#ifdef CBC_THREAD
+ case CBC_PARAM_INT_THREADS:
+ oldValue = model.getNumberThreads();
+ model.setNumberThreads(value);
+ break;
+#endif
+ case CBC_PARAM_INT_RANDOMSEED:
+ oldValue = model.getRandomSeed();
+ model.setRandomSeed(value);
+ break;
+#endif
+ default:
+ break;
+ }
+ sprintf(printArray, "%s was changed from %d to %d",
+ name_.c_str(), oldValue, value);
+ returnCode = 0;
+ }
+ return printArray;
+}
+int
+CbcOrClpParam::intParameter (CbcModel &model) const
+{
+ int value;
+ switch (type_) {
+ case CLP_PARAM_INT_LOGLEVEL:
+ value = model.messageHandler()->logLevel();
+ break;
+ case CLP_PARAM_INT_SOLVERLOGLEVEL:
+ value = model.solver()->messageHandler()->logLevel();
+ break;
+ case CBC_PARAM_INT_MAXNODES:
+ value = model.getIntParam(CbcModel::CbcMaxNumNode);
+ break;
+ case CBC_PARAM_INT_MAXSOLS:
+ value = model.getIntParam(CbcModel::CbcMaxNumSol);
+ break;
+ case CBC_PARAM_INT_MAXSAVEDSOLS:
+ value = model.maximumSavedSolutions();
+ break;
+ case CBC_PARAM_INT_STRONGBRANCHING:
+ value = model.numberStrong();
+ break;
+ case CBC_PARAM_INT_NUMBERBEFORE:
+ value = model.numberBeforeTrust();
+ break;
+ case CBC_PARAM_INT_NUMBERANALYZE:
+ value = model.numberAnalyzeIterations();
+ break;
+ case CBC_PARAM_INT_CUTPASSINTREE:
+ value = model.getMaximumCutPasses();
+ break;
+ case CBC_PARAM_INT_CUTPASS:
+ value = model.getMaximumCutPassesAtRoot();
+ break;
+#ifdef COIN_HAS_CBC
+#ifdef CBC_THREAD
+ case CBC_PARAM_INT_THREADS:
+ value = model.getNumberThreads();
+#endif
+ case CBC_PARAM_INT_RANDOMSEED:
+ value = model.getRandomSeed();
+ break;
+#endif
+ default:
+ value = intValue_;
+ break;
+ }
+ return value;
+}
+#endif
+// Sets current parameter option using string
+void
+CbcOrClpParam::setCurrentOption ( const std::string value )
+{
+ int action = parameterOption(value);
+ if (action >= 0)
+ currentKeyWord_ = action;
+}
+// Sets current parameter option
+void
+CbcOrClpParam::setCurrentOption ( int value , bool printIt)
+{
+ if (printIt && value != currentKeyWord_)
+ std::cout << "Option for " << name_ << " changed from "
+ << definedKeyWords_[currentKeyWord_] << " to "
+ << definedKeyWords_[value] << std::endl;
+
+ currentKeyWord_ = value;
+}
+// Sets current parameter option and returns printable string
+const char *
+CbcOrClpParam::setCurrentOptionWithMessage ( int value )
+{
+ if (value != currentKeyWord_) {
+ char current[100];
+ char newString[100];
+ if (currentKeyWord_>=0&&(fakeKeyWord_<=0||currentKeyWord_<fakeKeyWord_))
+ strcpy(current,definedKeyWords_[currentKeyWord_].c_str());
+ else if (currentKeyWord_<0)
+ sprintf(current,"minus%d",-currentKeyWord_-1000);
+ else
+ sprintf(current,"plus%d",currentKeyWord_-1000);
+ if (value>=0&&(fakeKeyWord_<=0||value<fakeKeyWord_) )
+ strcpy(newString,definedKeyWords_[value].c_str());
+ else if (value<0)
+ sprintf(newString,"minus%d",-value-1000);
+ else
+ sprintf(newString,"plus%d",value-1000);
+ sprintf(printArray, "Option for %s changed from %s to %s",
+ name_.c_str(), current, newString);
+ currentKeyWord_ = value;
+ } else {
+ printArray[0] = '\0';
+ }
+ return printArray;
+}
+// Sets current parameter option using string with message
+const char *
+CbcOrClpParam::setCurrentOptionWithMessage ( const std::string value )
+{
+ int action = parameterOption(value);
+ char current[100];
+ printArray[0] = '\0';
+ if (action >= 0) {
+ if (action == currentKeyWord_)
+ return NULL;
+ if (currentKeyWord_>=0&&(fakeKeyWord_<=0||currentKeyWord_<fakeKeyWord_))
+ strcpy(current,definedKeyWords_[currentKeyWord_].c_str());
+ else if (currentKeyWord_<0)
+ sprintf(current,"minus%d",-currentKeyWord_-1000);
+ else
+ sprintf(current,"plus%d",currentKeyWord_-1000);
+ sprintf(printArray, "Option for %s changed from %s to %s",
+ name_.c_str(), current, value.c_str());
+ currentKeyWord_ = action;
+ } else {
+ sprintf(printArray, "Option for %s given illegal value %s",
+ name_.c_str(), value.c_str());
+ }
+ return printArray;
+}
+void
+CbcOrClpParam::setIntValue ( int value )
+{
+ if (value < lowerIntValue_ || value > upperIntValue_) {
+ std::cout << value << " was provided for " << name_ <<
+ " - valid range is " << lowerIntValue_ << " to " <<
+ upperIntValue_ << std::endl;
+ } else {
+ intValue_ = value;
+ }
+}
+const char *
+CbcOrClpParam::setIntValueWithMessage ( int value )
+{
+ printArray[0] = '\0';
+ if (value < lowerIntValue_ || value > upperIntValue_) {
+ sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
+ value,name_.c_str(),lowerIntValue_,upperIntValue_);
+ } else {
+ if (value==intValue_)
+ return NULL;
+ sprintf(printArray, "%s was changed from %d to %d",
+ name_.c_str(), intValue_, value);
+ intValue_ = value;
+ }
+ return printArray;
+}
+void
+CbcOrClpParam::setDoubleValue ( double value )
+{
+ if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
+ std::cout << value << " was provided for " << name_ <<
+ " - valid range is " << lowerDoubleValue_ << " to " <<
+ upperDoubleValue_ << std::endl;
+ } else {
+ doubleValue_ = value;
+ }
+}
+const char *
+CbcOrClpParam::setDoubleValueWithMessage ( double value )
+{
+ printArray[0] = '\0';
+ if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
+ sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
+ value,name_.c_str(),lowerDoubleValue_,upperDoubleValue_);
+ } else {
+ if (value==doubleValue_)
+ return NULL;
+ sprintf(printArray, "%s was changed from %g to %g",
+ name_.c_str(), doubleValue_, value);
+ doubleValue_ = value;
+ }
+ return printArray;
+}
+void
+CbcOrClpParam::setStringValue ( std::string value )
+{
+ stringValue_ = value;
+}
+static char line[1000];
+static char * where = NULL;
+extern int CbcOrClpRead_mode;
+int CbcOrClpEnvironmentIndex = -1;
+static size_t fillEnv()
+{
+#if defined(_MSC_VER) || defined(__MSVCRT__)
+ return 0;
+#else
+ // Don't think it will work on Windows
+ char * environ = getenv("CBC_CLP_ENVIRONMENT");
+ size_t length = 0;
+ if (environ) {
+ length = strlen(environ);
+ if (CbcOrClpEnvironmentIndex < static_cast<int>(length)) {
+ // find next non blank
+ char * whereEnv = environ + CbcOrClpEnvironmentIndex;
+ // munch white space
+ while (*whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ')
+ whereEnv++;
+ // copy
+ char * put = line;
+ while ( *whereEnv != '\0' ) {
+ if ( *whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ' ) {
+ break;
+ }
+ *put = *whereEnv;
+ put++;
+ assert (put - line < 1000);
+ whereEnv++;
+ }
+ CbcOrClpEnvironmentIndex = static_cast<int>(whereEnv - environ);
+ *put = '\0';
+ length = strlen(line);
+ } else {
+ length = 0;
+ }
+ }
+ if (!length)
+ CbcOrClpEnvironmentIndex = -1;
+ return length;
+#endif
+}
+extern FILE * CbcOrClpReadCommand;
+// Simple read stuff
+std::string
+CoinReadNextField()
+{
+ std::string field;
+ if (!where) {
+ // need new line
+#ifdef COIN_HAS_READLINE
+ if (CbcOrClpReadCommand == stdin) {
+ // Get a line from the user.
+ where = readline (coin_prompt);
+
+ // If the line has any text in it, save it on the history.
+ if (where) {
+ if ( *where)
+ add_history (where);
+ strcpy(line, where);
+ free(where);
+ }
+ } else {
+ where = fgets(line, 1000, CbcOrClpReadCommand);
+ }
+#else
+ if (CbcOrClpReadCommand == stdin) {
+ fputs(coin_prompt,stdout);
+ fflush(stdout);
+ }
+ where = fgets(line, 1000, CbcOrClpReadCommand);
+#endif
+ if (!where)
+ return field; // EOF
+ where = line;
+ // clean image
+ char * lastNonBlank = line - 1;
+ while ( *where != '\0' ) {
+ if ( *where != '\t' && *where < ' ' ) {
+ break;
+ } else if ( *where != '\t' && *where != ' ') {
+ lastNonBlank = where;
+ }
+ where++;
+ }
+ where = line;
+ *(lastNonBlank + 1) = '\0';
+ }
+ // munch white space
+ while (*where == ' ' || *where == '\t')
+ where++;
+ char * saveWhere = where;
+ while (*where != ' ' && *where != '\t' && *where != '\0')
+ where++;
+ if (where != saveWhere) {
+ char save = *where;
+ *where = '\0';
+ //convert to string
+ field = saveWhere;
+ *where = save;
+ } else {
+ where = NULL;
+ field = "EOL";
+ }
+ return field;
+}
+
+std::string
+CoinReadGetCommand(int argc, const char *argv[])
+{
+ std::string field = "EOL";
+ // say no =
+ afterEquals = "";
+ while (field == "EOL") {
+ if (CbcOrClpRead_mode > 0) {
+ if ((CbcOrClpRead_mode < argc && argv[CbcOrClpRead_mode]) ||
+ CbcOrClpEnvironmentIndex >= 0) {
+ if (CbcOrClpEnvironmentIndex < 0) {
+ field = argv[CbcOrClpRead_mode++];
+ } else {
+ if (fillEnv()) {
+ field = line;
+ } else {
+ // not there
+ continue;
+ }
+ }
+ if (field == "-") {
+ std::cout << "Switching to line mode" << std::endl;
+ CbcOrClpRead_mode = -1;
+ field = CoinReadNextField();
+ } else if (field[0] != '-') {
+ if (CbcOrClpRead_mode != 2) {
+ // now allow std::cout<<"skipping non-command "<<field<<std::endl;
+ // field="EOL"; // skip
+ } else if (CbcOrClpEnvironmentIndex < 0) {
+ // special dispensation - taken as -import name
+ CbcOrClpRead_mode--;
+ field = "import";
+ }
+ } else {
+ if (field != "--") {
+ // take off -
+ field = field.substr(1);
+ } else {
+ // special dispensation - taken as -import --
+ CbcOrClpRead_mode--;
+ field = "import";
+ }
+ }
+ } else {
+ field = "";
+ }
+ } else {
+ field = CoinReadNextField();
+ }
+ }
+ // if = then modify and save
+ std::string::size_type found = field.find('=');
+ if (found != std::string::npos) {
+ afterEquals = field.substr(found + 1);
+ field = field.substr(0, found);
+ }
+ //std::cout<<field<<std::endl;
+ return field;
+}
+std::string
+CoinReadGetString(int argc, const char *argv[])
+{
+ std::string field = "EOL";
+ if (afterEquals == "") {
+ if (CbcOrClpRead_mode > 0) {
+ if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
+ if (CbcOrClpEnvironmentIndex < 0) {
+ if (argv[CbcOrClpRead_mode][0] != '-') {
+ field = argv[CbcOrClpRead_mode++];
+ } else if (!strcmp(argv[CbcOrClpRead_mode], "--")) {
+ field = argv[CbcOrClpRead_mode++];
+ // -- means import from stdin
+ field = "-";
+ }
+ } else {
+ fillEnv();
+ field = line;
+ }
+ }
+ } else {
+ field = CoinReadNextField();
+ }
+ } else {
+ field = afterEquals;
+ afterEquals = "";
+ }
+ //std::cout<<field<<std::endl;
+ return field;
+}
+// valid 0 - okay, 1 bad, 2 not there
+int
+CoinReadGetIntField(int argc, const char *argv[], int * valid)
+{
+ std::string field = "EOL";
+ if (afterEquals == "") {
+ if (CbcOrClpRead_mode > 0) {
+ if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
+ if (CbcOrClpEnvironmentIndex < 0) {
+ // may be negative value so do not check for -
+ field = argv[CbcOrClpRead_mode++];
+ } else {
+ fillEnv();
+ field = line;
+ }
+ }
+ } else {
+ field = CoinReadNextField();
+ }
+ } else {
+ field = afterEquals;
+ afterEquals = "";
+ }
+ long int value = 0;
+ //std::cout<<field<<std::endl;
+ if (field != "EOL") {
+ const char * start = field.c_str();
+ char * endPointer = NULL;
+ // check valid
+ value = strtol(start, &endPointer, 10);
+ if (*endPointer == '\0') {
+ *valid = 0;
+ } else {
+ *valid = 1;
+ std::cout << "String of " << field;
+ }
+ } else {
+ *valid = 2;
+ }
+ return static_cast<int>(value);
+}
+double
+CoinReadGetDoubleField(int argc, const char *argv[], int * valid)
+{
+ std::string field = "EOL";
+ if (afterEquals == "") {
+ if (CbcOrClpRead_mode > 0) {
+ if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
+ if (CbcOrClpEnvironmentIndex < 0) {
+ // may be negative value so do not check for -
+ field = argv[CbcOrClpRead_mode++];
+ } else {
+ fillEnv();
+ field = line;
+ }
+ }
+ } else {
+ field = CoinReadNextField();
+ }
+ } else {
+ field = afterEquals;
+ afterEquals = "";
+ }
+ double value = 0.0;
+ //std::cout<<field<<std::endl;
+ if (field != "EOL") {
+ const char * start = field.c_str();
+ char * endPointer = NULL;
+ // check valid
+ value = strtod(start, &endPointer);
+ if (*endPointer == '\0') {
+ *valid = 0;
+ } else {
+ *valid = 1;
+ std::cout << "String of " << field;
+ }
+ } else {
+ *valid = 2;
+ }
+ return value;
+}
+/*
+ Subroutine to establish the cbc parameter array. See the description of
+ class CbcOrClpParam for details. Pulled from C..Main() for clarity.
+*/
+void
+establishParams (int &numberParameters, CbcOrClpParam *const parameters)
+{
+ numberParameters = 0;
+ parameters[numberParameters++] =
+ CbcOrClpParam("?", "For help", CBC_PARAM_GENERALQUERY, 7, 0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("???", "For help", CBC_PARAM_FULLGENERALQUERY, 7, 0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("-", "From stdin",
+ CLP_PARAM_ACTION_STDIN, 3, 0);
+#ifdef ABC_INHERIT
+ parameters[numberParameters++] =
+ CbcOrClpParam("abc", "Whether to visit Aboca",
+ "off", CLP_PARAM_STR_ABCWANTED, 7, 0);
+ parameters[numberParameters-1].append("one");
+ parameters[numberParameters-1].append("two");
+ parameters[numberParameters-1].append("three");
+ parameters[numberParameters-1].append("four");
+ parameters[numberParameters-1].append("five");
+ parameters[numberParameters-1].append("six");
+ parameters[numberParameters-1].append("seven");
+ parameters[numberParameters-1].append("eight");
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("decide");
+ parameters[numberParameters-1].setFakeKeyWord(10);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Decide whether to use A Basic Optimization Code (Accelerated?) \
+and whether to try going parallel!"
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("allC!ommands", "Whether to print less used commands",
+ "no", CLP_PARAM_STR_ALLCOMMANDS);
+ parameters[numberParameters-1].append("more");
+ parameters[numberParameters-1].append("all");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "For the sake of your sanity, only the more useful and simple commands \
+are printed out on ?."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("allow!ableGap", "Stop when gap between best possible and \
+best less than this",
+ 0.0, 1.0e20, CBC_PARAM_DBL_ALLOWABLEGAP);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If the gap between best solution and best possible solution is less than this \
+then the search will be terminated. Also see ratioGap."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("allS!lack", "Set basis back to all slack and reset solution",
+ CLP_PARAM_ACTION_ALLSLACK, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Mainly useful for tuning purposes. Normally the first dual or primal will be using an all slack \
+basis anyway."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("artif!icialCost", "Costs >= this treated as artificials in feasibility pump",
+ 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ARTIFICIALCOST, 1);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "0.0 off - otherwise variables with costs >= this are treated as artificials and fixed to lower bound in feasibility pump"
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("auto!Scale", "Whether to scale objective, rhs and bounds of problem if they look odd",
+ "off", CLP_PARAM_STR_AUTOSCALE, 7, 0);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If you think you may get odd objective values or large equality rows etc then\
+ it may be worth setting this true. It is still experimental and you may prefer\
+ to use objective!Scale and rhs!Scale."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("barr!ier", "Solve using primal dual predictor corrector algorithm",
+ CLP_PARAM_ACTION_BARRIER);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This command solves the current model using the primal dual predictor \
+corrector algorithm. You may want to link in an alternative \
+ordering and factorization. It will also solve models \
+with quadratic objectives."
+
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("basisI!n", "Import basis from bas file",
+ CLP_PARAM_ACTION_BASISIN, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will read an MPS format basis file from the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to '', i.e. it must be set. If you have libz then it can read compressed\
+ files 'xxxxxxxx.gz' or xxxxxxxx.bz2."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("basisO!ut", "Export basis as bas file",
+ CLP_PARAM_ACTION_BASISOUT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will write an MPS format basis file to the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'default.bas'."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("biasLU", "Whether factorization biased towards U",
+ "UU", CLP_PARAM_STR_BIASLU, 2, 0);
+ parameters[numberParameters-1].append("UX");
+ parameters[numberParameters-1].append("LX");
+ parameters[numberParameters-1].append("LL");
+ parameters[numberParameters-1].setCurrentOption("LX");
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("branch!AndCut", "Do Branch and Cut",
+ CBC_PARAM_ACTION_BAB);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This does branch and cut. There are many parameters which can affect the performance. \
+First just try with default settings and look carefully at the log file. Did cuts help? Did they take too long? \
+Look at output to see which cuts were effective and then do some tuning. You will see that the \
+options for cuts are off, on, root and ifmove, forceon. Off is \
+obvious, on means that this cut generator will be tried in the branch and cut tree (you can fine tune using \
+'depth'). Root means just at the root node while 'ifmove' means that cuts will be used in the tree if they \
+look as if they are doing some good and moving the objective value. Forceon is same as on but forces code to use \
+cut generator at every node. For probing forceonbut just does fixing probing in tree - not strengthening etc. \
+If pre-processing reduced the size of the \
+problem or strengthened many coefficients then it is probably wise to leave it on. Switch off heuristics \
+which did not provide solutions. The other major area to look at is the search. Hopefully good solutions \
+were obtained fairly early in the search so the important point is to select the best variable to branch on. \
+See whether strong branching did a good job - or did it just take a lot of iterations. Adjust the strongBranching \
+and trustPseudoCosts parameters. If cuts did a good job, then you may wish to \
+have more rounds of cuts - see passC!uts and passT!ree."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("bscale", "Whether to scale in barrier (and ordering speed)",
+ "off", CLP_PARAM_STR_BARRIERSCALE, 7, 0);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("off1");
+ parameters[numberParameters-1].append("on1");
+ parameters[numberParameters-1].append("off2");
+ parameters[numberParameters-1].append("on2");
+ parameters[numberParameters++] =
+ CbcOrClpParam("chol!esky", "Which cholesky algorithm",
+ "native", CLP_PARAM_STR_CHOLESKY, 7);
+ parameters[numberParameters-1].append("dense");
+ //#ifdef FOREIGN_BARRIER
+#ifdef COIN_HAS_WSMP
+ parameters[numberParameters-1].append("fudge!Long");
+ parameters[numberParameters-1].append("wssmp");
+#else
+ parameters[numberParameters-1].append("fudge!Long_dummy");
+ parameters[numberParameters-1].append("wssmp_dummy");
+#endif
+#if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK)
+ parameters[numberParameters-1].append("Uni!versityOfFlorida");
+#else
+ parameters[numberParameters-1].append("Uni!versityOfFlorida_dummy");
+#endif
+#ifdef TAUCS_BARRIER
+ parameters[numberParameters-1].append("Taucs");
+#else
+ parameters[numberParameters-1].append("Taucs_dummy");
+#endif
+#ifdef COIN_HAS_MUMPS
+ parameters[numberParameters-1].append("Mumps");
+#else
+ parameters[numberParameters-1].append("Mumps_dummy");
+#endif
+ parameters[numberParameters-1].setLonghelp
+ (
+ "For a barrier code to be effective it needs a good Cholesky ordering and factorization. \
+The native ordering and factorization is not state of the art, although acceptable. \
+You may want to link in one from another source. See Makefile.locations for some \
+possibilities."
+ );
+ //#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("clique!Cuts", "Whether to use Clique cuts",
+ "off", CBC_PARAM_STR_CLIQUECUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on clique cuts (either at root or in entire tree) \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("combine!Solutions", "Whether to use combine solution heuristic",
+ "off", CBC_PARAM_STR_COMBINE);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].append("onquick");
+ parameters[numberParameters-1].append("bothquick");
+ parameters[numberParameters-1].append("beforequick");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on a heuristic which does branch and cut on the problem given by just \
+using variables which have appeared in one or more solutions. \
+It obviously only tries after two or more solutions. \
+See Rounding for meaning of on,both,before"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("combine2!Solutions", "Whether to use crossover solution heuristic",
+ "off", CBC_PARAM_STR_CROSSOVER2);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on a heuristic which does branch and cut on the problem given by \
+fixing variables which have same value in two or more solutions. \
+It obviously only tries after two or more solutions. \
+See Rounding for meaning of on,both,before"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("constraint!fromCutoff", "Whether to use cutoff as constraint",
+ "off", CBC_PARAM_STR_CUTOFF_CONSTRAINT);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("variable");
+ parameters[numberParameters-1].append("forcevariable");
+ parameters[numberParameters-1].append("conflict");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This adds the objective as a constraint with best solution as RHS"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("cost!Strategy", "How to use costs as priorities",
+ "off", CBC_PARAM_STR_COSTSTRATEGY);
+ parameters[numberParameters-1].append("pri!orities");
+ parameters[numberParameters-1].append("column!Order?");
+ parameters[numberParameters-1].append("01f!irst?");
+ parameters[numberParameters-1].append("01l!ast?");
+ parameters[numberParameters-1].append("length!?");
+ parameters[numberParameters-1].append("singletons");
+ parameters[numberParameters-1].append("nonzero");
+ parameters[numberParameters-1].append("general!Force?");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This orders the variables in order of their absolute costs - with largest cost ones being branched on \
+first. This primitive strategy can be surprsingly effective. The column order\
+ option is obviously not on costs but easy to code here."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("cplex!Use", "Whether to use Cplex!",
+ "off", CBC_PARAM_STR_CPX);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ " If the user has Cplex, but wants to use some of Cbc's heuristics \
+then you can! If this is on, then Cbc will get to the root node and then \
+hand over to Cplex. If heuristics find a solution this can be significantly \
+quicker. You will probably want to switch off Cbc's cuts as Cplex thinks \
+they are genuine constraints. It is also probable that you want to switch \
+off preprocessing, although for difficult problems it is worth trying \
+both."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("cpp!Generate", "Generates C++ code",
+ -1, 50000, CLP_PARAM_INT_CPP, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Once you like what the stand-alone solver does then this allows \
+you to generate user_driver.cpp which approximates the code. \
+0 gives simplest driver, 1 generates saves and restores, 2 \
+generates saves and restores even for variables at default value. \
+4 bit in cbc generates size dependent code rather than computed values. \
+This is now deprecated as you can call stand-alone solver - see \
+Cbc/examples/driver4.cpp."
+ );
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("crash", "Whether to create basis for problem",
+ "off", CLP_PARAM_STR_CRASH);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("so!low_halim");
+ parameters[numberParameters-1].append("lots");
+#ifdef CLP_INHERIT_MODE
+ parameters[numberParameters-1].append("dual");
+ parameters[numberParameters-1].append("dw");
+ parameters[numberParameters-1].append("idiot");
+#else
+ parameters[numberParameters-1].append("idiot1");
+ parameters[numberParameters-1].append("idiot2");
+ parameters[numberParameters-1].append("idiot3");
+ parameters[numberParameters-1].append("idiot4");
+ parameters[numberParameters-1].append("idiot5");
+ parameters[numberParameters-1].append("idiot6");
+ parameters[numberParameters-1].append("idiot7");
+#endif
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If crash is set on and there is an all slack basis then Clp will flip or put structural\
+ variables into basis with the aim of getting dual feasible. On the whole dual seems to be\
+ better without it and there are alternative types of 'crash' for primal e.g. 'idiot' or 'sprint'. \
+I have also added a variant due to Solow and Halim which is as on but just flip.");
+ parameters[numberParameters++] =
+ CbcOrClpParam("cross!over", "Whether to get a basic solution after barrier",
+ "on", CLP_PARAM_STR_CROSSOVER);
+ parameters[numberParameters-1].append("off");
+ parameters[numberParameters-1].append("maybe");
+ parameters[numberParameters-1].append("presolve");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Interior point algorithms do not obtain a basic solution (and \
+the feasibility criterion is a bit suspect (JJF)). This option will crossover \
+to a basic solution suitable for ranging or branch and cut. With the current state \
+of quadratic it may be a good idea to switch off crossover for quadratic (and maybe \
+presolve as well) - the option maybe does this."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("csv!Statistics", "Create one line of statistics",
+ CLP_PARAM_ACTION_CSVSTATISTICS, 2, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This appends statistics to given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to '', i.e. it must be set. Adds header if file empty or does not exist."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("cutD!epth", "Depth in tree at which to do cuts",
+ -1, 999999, CBC_PARAM_INT_CUTDEPTH);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Cut generators may be - off, on only at root, on if they look possible \
+and on. If they are done every node then that is that, but it may be worth doing them \
+every so often. The original method was every so many nodes but it is more logical \
+to do it whenever depth in tree is a multiple of K. This option does that and defaults \
+to -1 (off -> code decides)."
+ );
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("cutL!ength", "Length of a cut",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_CUTLENGTH);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "At present this only applies to Gomory cuts. -1 (default) leaves as is. \
+Any value >0 says that all cuts <= this length can be generated both at \
+root node and in tree. 0 says to use some dynamic lengths. If value >=10,000,000 \
+then the length in tree is value%10000000 - so 10000100 means unlimited length \
+at root and 100 in tree."
+ );
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("cuto!ff", "All solutions must be better than this",
+ -1.0e60, 1.0e60, CBC_PARAM_DBL_CUTOFF);
+ parameters[numberParameters-1].setDoubleValue(1.0e50);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "All solutions must be better than this value (in a minimization sense). \
+This is also set by code whenever it obtains a solution and is set to value of \
+objective for solution minus cutoff increment."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("cuts!OnOff", "Switches all cuts on or off",
+ "off", CBC_PARAM_STR_CUTSSTRATEGY);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This can be used to switch on or off all cuts (apart from Reduce and Split). Then you can do \
+individual ones off or on \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("debug!In", "read valid solution from file",
+ CLP_PARAM_ACTION_DEBUG, 7, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will read a solution file from the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to '', i.e. it must be set.\n\n\
+If set to create it will create a file called debug.file after search.\n\n\
+The idea is that if you suspect a bad cut generator \
+you can do a good run with debug set to 'create' and then switch on the cuts you suspect and \
+re-run with debug set to 'debug.file' The create case has same effect as saveSolution."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("decomp!ose", "Whether to try decomposition",
+ -COIN_INT_MAX, COIN_INT_MAX, CLP_PARAM_INT_DECOMPOSE_BLOCKS, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "0 - off, 1 choose blocks >1 use as blocks \
+Dantzig Wolfe if primal, Benders if dual \
+- uses sprint pass for number of passes"
+ );
+ parameters[numberParameters-1].setIntValue(0);
+#if CLP_MULTIPLE_FACTORIZATIONS >0
+ parameters[numberParameters++] =
+ CbcOrClpParam("dense!Threshold", "Whether to use dense factorization",
+ -1, 10000, CBC_PARAM_INT_DENSE, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If processed problem <= this use dense factorization"
+ );
+ parameters[numberParameters-1].setIntValue(-1);
+#endif
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("depth!MiniBab", "Depth at which to try mini BAB",
+ -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_DEPTHMINIBAB);
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "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 \
+means 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 (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 this 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. The actual logic is too twisted to describe here."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("dextra3", "Extra double parameter 3",
+ -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA3, 0);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("dextra4", "Extra double parameter 4",
+ -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA4, 0);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("dextra5", "Extra double parameter 5",
+ -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA5, 0);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("Dins", "Whether to try Distance Induced Neighborhood Search",
+ "off", CBC_PARAM_STR_DINS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].append("often");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on Distance induced neighborhood Search. \
+See Rounding for meaning of on,both,before"
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("direction", "Minimize or Maximize",
+ "min!imize", CLP_PARAM_STR_DIRECTION);
+ parameters[numberParameters-1].append("max!imize");
+ parameters[numberParameters-1].append("zero");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The default is minimize - use 'direction maximize' for maximization.\n\
+You can also use the parameters 'maximize' or 'minimize'."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("directory", "Set Default directory for import etc.",
+ CLP_PARAM_ACTION_DIRECTORY);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This sets the directory which import, export, saveModel, restoreModel etc will use.\
+ It is initialized to './'"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("dirSample", "Set directory where the COIN-OR sample problems are.",
+ CLP_PARAM_ACTION_DIRSAMPLE, 7, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This sets the directory where the COIN-OR sample problems reside. It is\
+ used only when -unitTest is passed to clp. clp will pick up the test problems\
+ from this directory.\
+ It is initialized to '../../Data/Sample'"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("dirNetlib", "Set directory where the netlib problems are.",
+ CLP_PARAM_ACTION_DIRNETLIB, 7, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This sets the directory where the netlib problems reside. One can get\
+ the netlib problems from COIN-OR or from the main netlib site. This\
+ parameter is used only when -netlib is passed to clp. clp will pick up the\
+ netlib problems from this directory. If clp is built without zlib support\
+ then the problems must be uncompressed.\
+ It is initialized to '../../Data/Netlib'"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("dirMiplib", "Set directory where the miplib 2003 problems are.",
+ CBC_PARAM_ACTION_DIRMIPLIB, 7, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This sets the directory where the miplib 2003 problems reside. One can\
+ get the miplib problems from COIN-OR or from the main miplib site. This\
+ parameter is used only when -miplib is passed to cbc. cbc will pick up the\
+ miplib problems from this directory. If cbc is built without zlib support\
+ then the problems must be uncompressed.\
+ It is initialized to '../../Data/miplib3'"
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("diveO!pt", "Diving options",
+ -1, 200000, CBC_PARAM_INT_DIVEOPT, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If >2 && <20 then modify diving options - \
+ \n\t3 only at root and if no solution, \
+ \n\t4 only at root and if this heuristic has not got solution, \
+ \n\t5 decay only if no solution, \
+ \n\t6 if depth <3 or decay, \
+ \n\t7 run up to 2 times if solution found 4 otherwise, \
+ \n\t>10 All only at root (DivingC normal as value-10), \
+ \n\t>20 All with value-20)."
+ );
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("diveS!olves", "Diving solve option",
+ -1, 200000, CBC_PARAM_INT_DIVEOPTSOLVES, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If >0 then do up to this many solves. Last digit is ignored \
+and used for extra options - \
+ \n\t1-3 allow fixing of satisfied integers (but not at bound) \
+ \n\t1 switch off above for that dive if goes infeasible \
+ \n\t2 switch off above permanently if goes infeasible"
+ );
+ parameters[numberParameters-1].setIntValue(100);
+ parameters[numberParameters++] =
+ CbcOrClpParam("DivingS!ome", "Whether to try Diving heuristics",
+ "off", CBC_PARAM_STR_DIVINGS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on a random diving heuristic at various times. \
+C - Coefficient, F - Fractional, G - Guided, L - LineSearch, P - PseudoCost, V - VectorLength. \
+You may prefer to use individual on/off \
+See Rounding for meaning of on,both,before"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("DivingC!oefficient", "Whether to try DiveCoefficient",
+ "off", CBC_PARAM_STR_DIVINGC);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters++] =
+ CbcOrClpParam("DivingF!ractional", "Whether to try DiveFractional",
+ "off", CBC_PARAM_STR_DIVINGF);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters++] =
+ CbcOrClpParam("DivingG!uided", "Whether to try DiveGuided",
+ "off", CBC_PARAM_STR_DIVINGG);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters++] =
+ CbcOrClpParam("DivingL!ineSearch", "Whether to try DiveLineSearch",
+ "off", CBC_PARAM_STR_DIVINGL);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters++] =
+ CbcOrClpParam("DivingP!seudoCost", "Whether to try DivePseudoCost",
+ "off", CBC_PARAM_STR_DIVINGP);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters++] =
+ CbcOrClpParam("DivingV!ectorLength", "Whether to try DiveVectorLength",
+ "off", CBC_PARAM_STR_DIVINGV);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters++] =
+ CbcOrClpParam("doH!euristic", "Do heuristics before any preprocessing",
+ CBC_PARAM_ACTION_DOHEURISTIC, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally heuristics are done in branch and bound. It may be useful to do them outside. \
+Only those heuristics with 'both' or 'before' set will run. \
+Doing this may also set cutoff, which can help with preprocessing."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("dualB!ound", "Initially algorithm acts as if no \
+gap between bounds exceeds this value",
+ 1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALBOUND);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\
+ algorithm where you first get feasible then optimal. If a problem has both upper and\
+ lower bounds then it is trivial to get dual feasible by setting non basic variables\
+ to correct bound. If the gap between the upper and lower bounds of a variable is more\
+ than the value of dualBound Clp introduces fake bounds so that it can make the problem\
+ dual feasible. This has the same effect as a composite objective function in the\
+ primal algorithm. Too high a value may mean more iterations, while too low a bound means\
+ the code may go all the way and then have to increase the bounds. OSL had a heuristic to\
+ adjust bounds, maybe we need that here."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("dualize", "Solves dual reformulation",
+ 0, 4, CLP_PARAM_INT_DUALIZE, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Don't even think about it."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("dualP!ivot", "Dual pivot choice algorithm",
+ "auto!matic", CLP_PARAM_STR_DUALPIVOT, 7, 1);
+ parameters[numberParameters-1].append("dant!zig");
+ parameters[numberParameters-1].append("partial");
+ parameters[numberParameters-1].append("steep!est");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Clp can use any pivot selection algorithm which the user codes as long as it\
+ implements the features in the abstract pivot base class. The Dantzig method is implemented\
+ to show a simple method but its use is deprecated. Steepest is the method of choice and there\
+ are two variants which keep all weights updated but only scan a subset each iteration.\
+ Partial switches this on while automatic decides at each iteration based on information\
+ about the factorization."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("dualS!implex", "Do dual simplex algorithm",
+ CLP_PARAM_ACTION_DUALSIMPLEX);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This command solves the continuous relaxation of the current model using the dual steepest edge algorithm.\
+The time and iterations may be affected by settings such as presolve, scaling, crash\
+ and also by dual pivot method, fake bound on variables and dual and primal tolerances."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("dualT!olerance", "For an optimal solution \
+no dual infeasibility may exceed this value",
+ 1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALTOLERANCE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally the default tolerance is fine, but you may want to increase it a\
+ bit if a dual run seems to be having a hard time. One method which can be faster is \
+to use a large tolerance e.g. 1.0e-4 and dual and then clean up problem using primal and the \
+correct tolerance (remembering to switch off presolve for this final short clean up phase)."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("dw!Heuristic", "Whether to try DW heuristic",
+ "off", CBC_PARAM_STR_DW);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "See Rounding for meaning of on,both,before"
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("either!Simplex", "Do dual or primal simplex algorithm",
+ CLP_PARAM_ACTION_EITHERSIMPLEX);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This command solves the continuous relaxation of the current model using the dual or primal algorithm,\
+ based on a dubious analysis of model."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("end", "Stops clp execution",
+ CLP_PARAM_ACTION_EXIT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This stops execution ; end, exit, quit and stop are synonyms"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("environ!ment", "Read commands from environment",
+ CLP_PARAM_ACTION_ENVIRONMENT, 7, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This starts reading from environment variable CBC_CLP_ENVIRONMENT."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("error!sAllowed", "Whether to allow import errors",
+ "off", CLP_PARAM_STR_ERRORSALLOWED, 3);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The default is not to use any model which had errors when reading the mps file.\
+ Setting this to 'on' will allow all errors from which the code can recover\
+ simply by ignoring the error. There are some errors from which the code can not recover \
+e.g. no ENDATA. This has to be set before import i.e. -errorsAllowed on -import xxxxxx.mps."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("exit", "Stops clp execution",
+ CLP_PARAM_ACTION_EXIT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This stops the execution of Clp, end, exit, quit and stop are synonyms"
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("exper!iment", "Whether to use testing features",
+ -1, 200, CBC_PARAM_INT_EXPERIMENT, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Defines how adventurous you want to be in using new ideas. \
+0 then no new ideas, 1 fairly sensible, 2 a bit dubious, 3 you are on your own!"
+ );
+ parameters[numberParameters-1].setIntValue(0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("expensive!Strong", "Whether to do even more strong branching",
+ 0, COIN_INT_MAX, CBC_PARAM_INT_STRONG_STRATEGY, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Strategy for extra strong branching \n\
+\n\t0 - normal\n\
+\n\twhen to do all fractional\n\
+\n\t1 - root node\n\
+\n\t2 - depth less than modifier\n\
+\n\t4 - if objective == best possible\n\
+\n\t6 - as 2+4\n\
+\n\twhen to do all including satisfied\n\
+\n\t10 - root node etc.\n\
+\n\tIf >=100 then do when depth <= strategy/100 (otherwise 5)"
+ );
+ parameters[numberParameters-1].setIntValue(0);
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("export", "Export model as mps file",
+ CLP_PARAM_ACTION_EXPORT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will write an MPS format file to the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'default.mps'. \
+It 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."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("extra1", "Extra integer parameter 1",
+ -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA1, 0);
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("extra2", "Extra integer parameter 2",
+ -100, COIN_INT_MAX, CBC_PARAM_INT_EXTRA2, 0);
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("extra3", "Extra integer parameter 3",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA3, 0);
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("extra4", "Extra integer parameter 4",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA4, 0);
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on yet more special options!! \
+The bottom digit is a strategy when to used shadow price stuff e.g. 3 \
+means use until a solution is found. The next two digits say what sort \
+of dual information to use. After that it goes back to powers of 2 so -\n\
+\n\t1000 - switches on experimental hotstart\n\
+\n\t2,4,6000 - switches on experimental methods of stopping cuts\n\
+\n\t8000 - increase minimum drop gradually\n\
+\n\t16000 - switches on alternate gomory criterion"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("extraV!ariables", "Allow creation of extra integer variables",
+ -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA_VARIABLES, 0);
+ parameters[numberParameters-1].setIntValue(0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on creation of extra integer variables \
+to gather all variables with same cost."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("fact!orization", "Which factorization to use",
+ "normal", CLP_PARAM_STR_FACTORIZATION);
+ parameters[numberParameters-1].append("dense");
+ parameters[numberParameters-1].append("simple");
+ parameters[numberParameters-1].append("osl");
+ parameters[numberParameters-1].setLonghelp
+ (
+#ifndef ABC_INHERIT
+ "The default is to use the normal CoinFactorization, but \
+other choices are a dense one, osl's or one designed for small problems."
+#else
+ "Normally the default is to use the normal CoinFactorization, but \
+other choices are a dense one, osl's or one designed for small problems. \
+However if at Aboca then the default is CoinAbcFactorization and other choices are \
+a dense one, one designed for small problems or if enabled a long factorization."
+#endif
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("fakeB!ound", "All bounds <= this value - DEBUG",
+ 1.0, 1.0e15, CLP_PARAM_ACTION_FAKEBOUND, 0);
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("feas!ibilityPump", "Whether to try Feasibility Pump",
+ "off", CBC_PARAM_STR_FPUMP);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on feasibility pump heuristic at root. This is due to Fischetti, Lodi and Glover \
+and uses a sequence of Lps to try and get an integer feasible solution. \
+Some fine tuning is available by passFeasibilityPump and also pumpTune. \
+See Rounding for meaning of on,both,before"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("fix!OnDj", "Try heuristic based on fixing variables with \
+reduced costs greater than this",
+ -1.0e20, 1.0e20, CBC_PARAM_DBL_DJFIX, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If this is set integer variables with reduced costs greater than this will be fixed \
+before branch and bound - use with extreme caution!"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("flow!CoverCuts", "Whether to use Flow Cover cuts",
+ "off", CBC_PARAM_STR_FLOWCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].setFakeKeyWord(3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on flow cover cuts (either at root or in entire tree) \
+See branchAndCut for information on options. \
+Can also enter testing values by plusnn (==ifmove)"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("force!Solution", "Whether to use given solution as crash for BAB",
+ -1, 20000000, CLP_PARAM_INT_USESOLUTION);
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "-1 off. If 1 then tries to branch to solution given by AMPL or priorities file. \
+If 0 then just tries to set as best solution \
+If >1 then also does that many nodes on fixed problem."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("fraction!forBAB", "Fraction in feasibility pump",
+ 1.0e-5, 1.1, CBC_PARAM_DBL_SMALLBAB, 1);
+ parameters[numberParameters-1].setDoubleValue(0.5);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "After a pass in feasibility pump, variables which have not moved \
+about are fixed and if the preprocessed model is small enough a few nodes \
+of branch and bound are done on reduced problem. Small problem has to be less than this fraction of original."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("gamma!(Delta)", "Whether to regularize barrier",
+ "off", CLP_PARAM_STR_GAMMA, 7, 1);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("gamma");
+ parameters[numberParameters-1].append("delta");
+ parameters[numberParameters-1].append("onstrong");
+ parameters[numberParameters-1].append("gammastrong");
+ parameters[numberParameters-1].append("deltastrong");
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("GMI!Cuts", "Whether to use alternative Gomory cuts",
+ "off", CBC_PARAM_STR_GMICUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("endonly");
+ parameters[numberParameters-1].append("long");
+ parameters[numberParameters-1].append("longroot");
+ parameters[numberParameters-1].append("longifmove");
+ parameters[numberParameters-1].append("forceLongOn");
+ parameters[numberParameters-1].append("longendonly");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on an alternative Gomory cut generator (either at root or in entire tree) \
+This version is by Giacomo Nannicini and may be more robust \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("gomory!Cuts", "Whether to use Gomory cuts",
+ "off", CBC_PARAM_STR_GOMORYCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].append("forceandglobal");
+ parameters[numberParameters-1].append("forceLongOn");
+ parameters[numberParameters-1].append("long");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The original cuts - beware of imitations! Having gone out of favor, they are now more \
+fashionable as LP solvers are more robust and they interact well with other cuts. They will almost always \
+give cuts (although in this executable they are limited as to number of variables in cut). \
+However the cuts may be dense so it is worth experimenting (Long allows any length). \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("greedy!Heuristic", "Whether to use a greedy heuristic",
+ "off", CBC_PARAM_STR_GREEDY);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ //parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Switches on a greedy heuristic which will try and obtain a solution. It may just fix a \
+percentage of variables and then try a small branch and cut run. \
+See Rounding for meaning of on,both,before"
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("gsolu!tion", "Puts glpk solution to file",
+ CLP_PARAM_ACTION_GMPL_SOLUTION);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Will write a glpk solution file to the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'stdout' (this defaults to ordinary solution if stdout). \
+If problem created from gmpl model - will do any reports."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("heur!isticsOnOff", "Switches most heuristics on or off",
+ "off", CBC_PARAM_STR_HEURISTICSTRATEGY);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This can be used to switch on or off all heuristics. Then you can do \
+individual ones off or on. CbcTreeLocal is not included as it dramatically \
+alters search."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("help", "Print out version, non-standard options and some help",
+ CLP_PARAM_ACTION_HELP, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This prints out some help to get user started. If you have printed this then \
+you should be past that stage:-)"
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("hOp!tions", "Heuristic options",
+ -9999999, 9999999, CBC_PARAM_INT_HOPTIONS, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "1 says stop heuristic immediately allowable gap reached. \
+Others are for feasibility pump - \
+2 says do exact number of passes given, \
+4 only applies if initial cutoff given and says relax after 50 passes, \
+while 8 will adapt cutoff rhs after first solution if it looks as if code is stalling."
+ );
+ parameters[numberParameters-1].setIntValue(0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("hot!StartMaxIts", "Maximum iterations on hot start",
+ 0, COIN_INT_MAX, CBC_PARAM_INT_MAXHOTITS);
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("idiot!Crash", "Whether to try idiot crash",
+ -1, 99999999, CLP_PARAM_INT_IDIOT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This is a type of 'crash' which works well on some homogeneous problems.\
+ It works best on problems with unit elements and rhs but will do something to any model. It should only be\
+ used before primal. It can be set to -1 when the code decides for itself whether to use it,\
+ 0 to switch off or n > 0 to do n passes."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("import", "Import model from mps file",
+ CLP_PARAM_ACTION_IMPORT, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will read an MPS format file from the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to '', i.e. it must be set. If you have libgz then it can read compressed\
+ files 'xxxxxxxx.gz' or 'xxxxxxxx.bz2'. \
+If 'keepnames' is off, then names are dropped -> Rnnnnnnn and Cnnnnnnn."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("inc!rement", "A valid solution must be at least this \
+much better than last integer solution",
+ -1.0e20, 1.0e20, CBC_PARAM_DBL_INCREMENT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Whenever a solution is found the bound on solutions is set to solution (in a minimization\
+sense) plus this. If it is not set then the code will try and work one out e.g. if \
+all objective coefficients are multiples of 0.01 and only integer variables have entries in \
+objective then this can be set to 0.01. Be careful if you set this negative!"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("inf!easibilityWeight", "Each integer infeasibility is expected \
+to cost this much",
+ 0.0, 1.0e20, CBC_PARAM_DBL_INFEASIBILITYWEIGHT, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "A primitive way of deciding which node to explore next. Satisfying each integer infeasibility is \
+expected to cost this much."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("initialS!olve", "Solve to continuous",
+ CLP_PARAM_ACTION_SOLVECONTINUOUS);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This just solves the problem to continuous - without adding any cuts"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("integerT!olerance", "For an optimal solution \
+no integer variable may be this away from an integer value",
+ 1.0e-20, 0.5, CBC_PARAM_DBL_INTEGERTOLERANCE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Beware of setting this smaller than the primal tolerance."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("keepN!ames", "Whether to keep names from import",
+ "on", CLP_PARAM_STR_KEEPNAMES);
+ parameters[numberParameters-1].append("off");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "It saves space to get rid of names so if you need to you can set this to off. \
+This needs to be set before the import of model - so -keepnames off -import xxxxx.mps."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("KKT", "Whether to use KKT factorization",
+ "off", CLP_PARAM_STR_KKT, 7, 1);
+ parameters[numberParameters-1].append("on");
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("knapsack!Cuts", "Whether to use Knapsack cuts",
+ "off", CBC_PARAM_STR_KNAPSACKCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].append("forceandglobal");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on knapsack cuts (either at root or in entire tree) \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("lagomory!Cuts", "Whether to use Lagrangean Gomory cuts",
+ "off", CBC_PARAM_STR_LAGOMORYCUTS);
+ parameters[numberParameters-1].append("endonlyroot");
+ parameters[numberParameters-1].append("endcleanroot");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("endonly");
+ parameters[numberParameters-1].append("endclean");
+ parameters[numberParameters-1].append("endboth");
+ parameters[numberParameters-1].append("onlyaswell");
+ parameters[numberParameters-1].append("cleanaswell");
+ parameters[numberParameters-1].append("bothaswell");
+ parameters[numberParameters-1].append("onlyinstead");
+ parameters[numberParameters-1].append("cleaninstead");
+ parameters[numberParameters-1].append("bothinstead");
+ parameters[numberParameters-1].append("onlyaswellroot");
+ parameters[numberParameters-1].append("cleanaswellroot");
+ parameters[numberParameters-1].append("bothaswellroot");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This is a gross simplification of 'A Relax-and-Cut Framework for Gomory's Mixed-Integer Cuts' \
+by Matteo Fischetti & Domenico Salvagnin. This simplification \
+just uses original constraints while modifying objective using other cuts. \
+So you don't use messy constraints generated by Gomory etc. \
+A variant is to allow non messy cuts e.g. clique cuts. \
+So 'only' does this while clean also allows integral valued cuts. \
+'End' is recommended which waits until other cuts have finished and then \
+does a few passes. \
+The length options for gomory cuts are used."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("latwomir!Cuts", "Whether to use Lagrangean TwoMir cuts",
+ "off", CBC_PARAM_STR_LATWOMIRCUTS);
+ parameters[numberParameters-1].append("endonlyroot");
+ parameters[numberParameters-1].append("endcleanroot");
+ parameters[numberParameters-1].append("endbothroot");
+ parameters[numberParameters-1].append("endonly");
+ parameters[numberParameters-1].append("endclean");
+ parameters[numberParameters-1].append("endboth");
+ parameters[numberParameters-1].append("onlyaswell");
+ parameters[numberParameters-1].append("cleanaswell");
+ parameters[numberParameters-1].append("bothaswell");
+ parameters[numberParameters-1].append("onlyinstead");
+ parameters[numberParameters-1].append("cleaninstead");
+ parameters[numberParameters-1].append("bothinstead");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This is a lagrangean relaxation for TwoMir cuts. See \
+lagomoryCuts for description of options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("lift!AndProjectCuts", "Whether to use Lift and Project cuts",
+ "off", CBC_PARAM_STR_LANDPCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Lift and project cuts. \
+May be slow \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("local!TreeSearch", "Whether to use local treesearch",
+ "off", CBC_PARAM_STR_LOCALTREE);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on a local search algorithm when a solution is found. This is from \
+Fischetti and Lodi and is not really a heuristic although it can be used as one. \
+When used from Coin solve it has limited functionality. It is not switched on when \
+heuristics are switched on."
+ );
+#endif
+#ifndef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("log!Level", "Level of detail in Solver output",
+ -1, 999999, CLP_PARAM_INT_SOLVERLOGLEVEL);
+#else
+ parameters[numberParameters++] =
+ CbcOrClpParam("log!Level", "Level of detail in Coin branch and Cut output",
+ -63, 63, CLP_PARAM_INT_LOGLEVEL);
+ parameters[numberParameters-1].setIntValue(1);
+#endif
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If 0 then there should be no output in normal circumstances. 1 is probably the best\
+ value for most uses, while 2 and 3 give more information."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("max!imize", "Set optimization direction to maximize",
+ CLP_PARAM_ACTION_MAXIMIZE, 7);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The default is minimize - use 'maximize' for maximization.\n\
+You can also use the parameters 'direction maximize'."
+ );
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("maxF!actor", "Maximum number of iterations between \
+refactorizations",
+ 1, 999999, CLP_PARAM_INT_MAXFACTOR);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If this is at its initial value of 200 then in this executable clp will guess at a\
+ value to use. Otherwise the user can set a value. The code may decide to re-factorize\
+ earlier for accuracy."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("maxIt!erations", "Maximum number of iterations before \
+stopping",
+ 0, 2147483647, CLP_PARAM_INT_MAXITERATION);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This can be used for testing purposes. The corresponding library call\n\
+ \tsetMaximumIterations(value)\n can be useful. If the code stops on\
+ seconds or by an interrupt this will be treated as stopping on maximum iterations. This is ignored in branchAndCut - use maxN!odes."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("maxN!odes", "Maximum number of nodes to do",
+ -1, 2147483647, CBC_PARAM_INT_MAXNODES);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This is a repeatable way to limit search. Normally using time is easier \
+but then the results may not be repeatable."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("maxSaved!Solutions", "Maximum number of solutions to save",
+ 0, 2147483647, CBC_PARAM_INT_MAXSAVEDSOLS);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Number of solutions to save."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("maxSo!lutions", "Maximum number of solutions to get",
+ 1, 2147483647, CBC_PARAM_INT_MAXSOLS);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "You may want to stop after (say) two solutions or an hour. \
+This is checked every node in tree, so it is possible to get more solutions from heuristics."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("min!imize", "Set optimization direction to minimize",
+ CLP_PARAM_ACTION_MINIMIZE, 7);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The default is minimize - use 'maximize' for maximization.\n\
+This should only be necessary if you have previously set maximization \
+You can also use the parameters 'direction minimize'."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("mipO!ptions", "Dubious options for mip",
+ 0, COIN_INT_MAX, CBC_PARAM_INT_MIPOPTIONS, 0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("more!MipOptions", "More dubious options for mip",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("more2!MipOptions", "More more dubious options for mip",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMOREMIPOPTIONS, 0);
+ parameters[numberParameters-1].setIntValue(0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts",
+ "off", CBC_PARAM_STR_MIXEDCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on mixed integer rounding cuts (either at root or in entire tree) \
+See branchAndCut for information on options."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("mess!ages", "Controls if Clpnnnn is printed",
+ "off", CLP_PARAM_STR_MESSAGES);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ ("The default behavior is to put out messages such as:\n\
+ Clp0005 2261 Objective 109.024 Primal infeas 944413 (758)\n\
+but this program turns this off to make it look more friendly. It can be useful\
+ to turn them back on if you want to be able to 'grep' for particular messages or if\
+ you intend to override the behavior of a particular message. This only affects Clp not Cbc."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("miplib", "Do some of miplib test set",
+ CBC_PARAM_ACTION_MIPLIB, 3, 1);
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("mips!tart", "reads an initial feasible solution from file",
+ CBC_PARAM_ACTION_MIPSTART);
+ parameters[numberParameters-1].setLonghelp
+ ("\
+The MIPStart allows one to enter an initial integer feasible solution \
+to CBC. Values of the main decision variables which are active (have \
+non-zero values) in this solution are specified in a text file. The \
+text file format used is the same of the solutions saved by CBC, but \
+not all fields are required to be filled. First line may contain the \
+solution status and will be ignored, remaining lines contain column \
+indexes, names and values as in this example:\n\
+\n\
+Stopped on iterations - objective value 57597.00000000\n\
+ 0 x(1,1,2,2) 1 \n\
+ 1 x(3,1,3,2) 1 \n\
+ 5 v(5,1) 2 \n\
+ 33 x(8,1,5,2) 1 \n\
+ ...\n\
+\n\
+Column indexes are also ignored since pre-processing can change them. \
+There is no need to include values for continuous or integer auxiliary \
+variables, since they can be computed based on main decision variables. \
+Starting CBC with an integer feasible solution can dramatically improve \
+its performance: several MIP heuristics (e.g. RINS) rely on having at \
+least one feasible solution available and can start immediately if the \
+user provides one. Feasibility Pump (FP) is a heuristic which tries to \
+overcome the problem of taking too long to find feasible solution (or \
+not finding at all), but it not always succeeds. If you provide one \
+starting solution you will probably save some time by disabling FP. \
+\n\n\
+Knowledge specific to your problem can be considered to write an \
+external module to quickly produce an initial feasible solution - some \
+alternatives are the implementation of simple greedy heuristics or the \
+solution (by CBC for example) of a simpler model created just to find \
+a feasible solution. \
+\n\n\
+Question and suggestions regarding MIPStart can be directed to\n\
+haroldo.santos@gmail.com.\
+");
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("moreS!pecialOptions", "Yet more dubious options for Simplex - see ClpSimplex.hpp",
+ 0, COIN_INT_MAX, CLP_PARAM_INT_MORESPECIALOPTIONS, 0);
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("moreT!une", "Yet more dubious ideas for feasibility pump",
+ 0, 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Yet more ideas for Feasibility Pump \n\
+\t/100000 == 1 use box constraints and original obj in cleanup\n\
+\t/1000 == 1 Pump will run twice if no solution found\n\
+\t/1000 == 2 Pump will only run after root cuts if no solution found\n\
+\t/1000 >10 as above but even if solution found\n\
+\t/100 == 1,3.. exact 1.0 for objective values\n\
+\t/100 == 2,3.. allow more iterations per pass\n\
+\t n fix if value of variable same for last n iterations."
+ );
+ parameters[numberParameters-1].setIntValue(0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("multiple!RootPasses", "Do multiple root passes to collect cuts and solutions",
+ 0, 100000000, CBC_PARAM_INT_MULTIPLEROOTS, 0);
+ parameters[numberParameters-1].setIntValue(0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Do (in parallel if threads enabled) the root phase this number of times \
+ and collect all solutions and cuts generated. The actual format is aabbcc \
+where aa is number of extra passes, if bb is non zero \
+then it is number of threads to use (otherwise uses threads setting) and \
+cc is number of times to do root phase. Yet another one from the Italian idea factory \
+(This time - Andrea Lodi , Matteo Fischetti , Michele Monaci , Domenico Salvagnin , \
+and Andrea Tramontani). \
+The solvers do not interact with each other. However if extra passes are specified \
+then cuts are collected and used in later passes - so there is interaction there."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("naive!Heuristics", "Whether to try some stupid heuristic",
+ "off", CBC_PARAM_STR_NAIVE, 7, 1);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Really silly stuff e.g. fix all integers with costs to zero!. \
+Doh option does heuristic before preprocessing" );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("netlib", "Solve entire netlib test set",
+ CLP_PARAM_ACTION_NETLIB_EITHER, 3, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\
+The user can set options before e.g. clp -presolve off -netlib"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("netlibB!arrier", "Solve entire netlib test set with barrier",
+ CLP_PARAM_ACTION_NETLIB_BARRIER, 3, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This exercises the unit test for clp and then solves the netlib test set using barrier.\
+The user can set options before e.g. clp -kkt on -netlib"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("netlibD!ual", "Solve entire netlib test set (dual)",
+ CLP_PARAM_ACTION_NETLIB_DUAL, 3, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This exercises the unit test for clp and then solves the netlib test set using dual.\
+The user can set options before e.g. clp -presolve off -netlib"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("netlibP!rimal", "Solve entire netlib test set (primal)",
+ CLP_PARAM_ACTION_NETLIB_PRIMAL, 3, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This exercises the unit test for clp and then solves the netlib test set using primal.\
+The user can set options before e.g. clp -presolve off -netlibp"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("netlibT!une", "Solve entire netlib test set with 'best' algorithm",
+ CLP_PARAM_ACTION_NETLIB_TUNE, 3, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This exercises the unit test for clp and then solves the netlib test set using whatever \
+works best. I know this is cheating but it also stresses the code better by doing a \
+mixture of stuff. The best algorithm was chosen on a Linux ThinkPad using native cholesky \
+with University of Florida ordering."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("network", "Tries to make network matrix",
+ CLP_PARAM_ACTION_NETWORK, 7, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Clp will go faster if the matrix can be converted to a network. The matrix\
+ operations may be a bit faster with more efficient storage, but the main advantage\
+ comes from using a network factorization. It will probably not be as fast as a \
+specialized network code."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("nextB!estSolution", "Prints next best saved solution to file",
+ CLP_PARAM_ACTION_NEXTBESTSOLUTION);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "To write best solution, just use solution. This prints next best (if exists) \
+ and then deletes it. \
+ This will write a primitive solution file to the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("node!Strategy", "What strategy to use to select nodes",
+ "hybrid", CBC_PARAM_STR_NODESTRATEGY);
+ parameters[numberParameters-1].append("fewest");
+ parameters[numberParameters-1].append("depth");
+ parameters[numberParameters-1].append("upfewest");
+ parameters[numberParameters-1].append("downfewest");
+ parameters[numberParameters-1].append("updepth");
+ parameters[numberParameters-1].append("downdepth");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally before a solution the code will choose node with fewest infeasibilities. \
+You can choose depth as the criterion. You can also say if up or down branch must \
+be done first (the up down choice will carry on after solution). \
+Default has now been changed to hybrid which is breadth first on small depth nodes then fewest."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("numberA!nalyze", "Number of analysis iterations",
+ -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This says how many iterations to spend at root node analyzing problem. \
+This is a first try and will hopefully become more sophisticated."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("objective!Scale", "Scale factor to apply to objective",
+ -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If the objective function has some very large values, you may wish to scale them\
+ internally by this amount. It can also be set by autoscale. It is applied after scaling. You are unlikely to need this."
+ );
+ parameters[numberParameters-1].setDoubleValue(1.0);
+#endif
+#ifdef COIN_HAS_CBC
+#ifdef COIN_HAS_NTY
+ parameters[numberParameters++] =
+ CbcOrClpParam("Orbit!alBranching", "Whether to try orbital branching",
+ "off", CBC_PARAM_STR_ORBITAL);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("strong");
+ parameters[numberParameters-1].append("force");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on Orbital branching. \
+On just adds orbital, strong tries extra fixing in strong branching");
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("outDup!licates", "takes duplicate rows etc out of integer model",
+ CLP_PARAM_ACTION_OUTDUPROWS, 7, 0);
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("output!Format", "Which output format to use",
+ 1, 6, CLP_PARAM_INT_OUTPUTFORMAT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally export will be done using normal representation for numbers and two values\
+ per line. You may want to do just one per line (for grep or suchlike) and you may wish\
+ to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
+ otherwise odd values gives one value per line, even two. Values 1,2 give normal format, 3,4\
+ gives greater precision, while 5,6 give IEEE values. When used for exporting a basis 1 does not save \
+values, 2 saves values, 3 with greater accuracy and 4 in IEEE."
+ );
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("para!metrics", "Import data from file and do parametrics",
+ CLP_PARAM_ACTION_PARAMETRICS, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will read a file with parametric data from the given file name \
+and then do parametrics. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to '', i.e. it must be set. This can not read from compressed files. \
+File is in modified csv format - a line ROWS will be followed by rows data \
+while a line COLUMNS will be followed by column data. The last line \
+should be ENDATA. The ROWS line must exist and is in the format \
+ROWS, inital theta, final theta, interval theta, n where n is 0 to get \
+CLPI0062 message at interval or at each change of theta \
+and 1 to get CLPI0063 message at each iteration. If interval theta is 0.0 \
+or >= final theta then no interval reporting. n may be missed out when it is \
+taken as 0. If there is Row data then \
+there is a headings line with allowed headings - name, number, \
+lower(rhs change), upper(rhs change), rhs(change). Either the lower and upper \
+fields should be given or the rhs field. \
+The optional COLUMNS line is followed by a headings line with allowed \
+headings - name, number, objective(change), lower(change), upper(change). \
+ Exactly one of name and number must be given for either section and \
+missing ones have value 0.0."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("passC!uts", "Number of cut passes at root node",
+ -9999999, 9999999, CBC_PARAM_INT_CUTPASS);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The default is 100 passes if less than 500 columns, 100 passes (but \
+stop if drop small if less than 5000 columns, 20 otherwise"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("passF!easibilityPump", "How many passes in feasibility pump",
+ 0, 10000, CBC_PARAM_INT_FPUMPITS);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This fine tunes Feasibility Pump by doing more or fewer passes."
+ );
+ parameters[numberParameters-1].setIntValue(20);
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("passP!resolve", "How many passes in presolve",
+ -200, 100, CLP_PARAM_INT_PRESOLVEPASS, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally Presolve does 10 passes but you may want to do less to make it\
+ more lightweight or do more if improvements are still being made. As Presolve will return\
+ if nothing is being taken out, you should not normally need to use this fine tuning."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("passT!reeCuts", "Number of cut passes in tree",
+ -9999999, 9999999, CBC_PARAM_INT_CUTPASSINTREE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The default is one pass"
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("pertV!alue", "Method of perturbation",
+ -5000, 102, CLP_PARAM_INT_PERTVALUE, 1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("perturb!ation", "Whether to perturb problem",
+ "on", CLP_PARAM_STR_PERTURBATION);
+ parameters[numberParameters-1].append("off");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Perturbation helps to stop cycling, but Clp uses other measures for this.\
+ However large problems and especially ones with unit elements and unit rhs or costs\
+ benefit from perturbation. Normally Clp tries to be intelligent, but you can switch this off.\
+ The Clp library has this off by default. This program has it on by default."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("PFI", "Whether to use Product Form of Inverse in simplex",
+ "off", CLP_PARAM_STR_PFI, 7, 0);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "By default clp uses Forrest-Tomlin L-U update. If you are masochistic you can switch it off."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("pivotAndC!omplement", "Whether to try Pivot and Complement heuristic",
+ "off", CBC_PARAM_STR_PIVOTANDCOMPLEMENT);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "stuff needed. \
+Doh option does heuristic before preprocessing" );
+ parameters[numberParameters++] =
+ CbcOrClpParam("pivotAndF!ix", "Whether to try Pivot and Fix heuristic",
+ "off", CBC_PARAM_STR_PIVOTANDFIX);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "stuff needed. \
+Doh option does heuristic before preprocessing" );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("plus!Minus", "Tries to make +- 1 matrix",
+ CLP_PARAM_ACTION_PLUSMINUS, 7, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Clp will go slightly faster if the matrix can be converted so that the elements are\
+ not stored and are known to be unit. The main advantage is memory use. Clp may automatically\
+ see if it can convert the problem so you should not need to use this."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("pO!ptions", "Dubious print options",
+ 0, COIN_INT_MAX, CLP_PARAM_INT_PRINTOPTIONS, 1);
+ parameters[numberParameters-1].setIntValue(0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If this is > 0 then presolve will give more information and branch and cut will give statistics"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("preO!pt", "Presolve options",
+ 0, COIN_INT_MAX, CLP_PARAM_INT_PRESOLVEOPTIONS, 0);
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("presolve", "Whether to presolve problem",
+ "on", CLP_PARAM_STR_PRESOLVE);
+ parameters[numberParameters-1].append("off");
+ parameters[numberParameters-1].append("more");
+ parameters[numberParameters-1].append("file");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Presolve analyzes the model to find such things as redundant equations, equations\
+ which fix some variables, equations which can be transformed into bounds etc etc. For the\
+ initial solve of any problem this is worth doing unless you know that it will have no effect. \
+on will normally do 5 passes while using 'more' will do 10. If the problem is very large you may need \
+to write the original to file using 'file'."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("preprocess", "Whether to use integer preprocessing",
+ "off", CBC_PARAM_STR_PREPROCESS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("save");
+ parameters[numberParameters-1].append("equal");
+ parameters[numberParameters-1].append("sos");
+ parameters[numberParameters-1].append("trysos");
+ parameters[numberParameters-1].append("equalall");
+ parameters[numberParameters-1].append("strategy");
+ parameters[numberParameters-1].append("aggregate");
+ parameters[numberParameters-1].append("forcesos");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This tries to reduce size of model in a similar way to presolve and \
+it also tries to strengthen the model - this can be very useful and is worth trying. \
+ Save option saves on file presolved.mps. equal will turn <= cliques into \
+==. sos will create sos sets if all 0-1 in sets (well one extra is allowed) \
+and no overlaps. trysos is same but allows any number extra. equalall will turn all \
+valid inequalities into equalities with integer slacks. strategy is as \
+on but uses CbcStrategy."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("preT!olerance", "Tolerance to use in presolve",
+ 1.0e-20, 1.0e12, CLP_PARAM_DBL_PRESOLVETOLERANCE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The default is 1.0e-8 - you may wish to try 1.0e-7 if presolve says the problem is \
+infeasible and you have awkward numbers and you are sure the problem is really feasible."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("primalP!ivot", "Primal pivot choice algorithm",
+ "auto!matic", CLP_PARAM_STR_PRIMALPIVOT, 7, 1);
+ parameters[numberParameters-1].append("exa!ct");
+ parameters[numberParameters-1].append("dant!zig");
+ parameters[numberParameters-1].append("part!ial");
+ parameters[numberParameters-1].append("steep!est");
+ parameters[numberParameters-1].append("change");
+ parameters[numberParameters-1].append("sprint");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Clp can use any pivot selection algorithm which the user codes as long as it\
+ implements the features in the abstract pivot base class. The Dantzig method is implemented\
+ to show a simple method but its use is deprecated. Exact devex is the method of choice and there\
+ are two variants which keep all weights updated but only scan a subset each iteration.\
+ Partial switches this on while change initially does dantzig until the factorization\
+ becomes denser. This is still a work in progress."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("primalS!implex", "Do primal simplex algorithm",
+ CLP_PARAM_ACTION_PRIMALSIMPLEX);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This command solves the continuous relaxation of the current model using the primal algorithm.\
+ The default is to use exact devex.\
+ The time and iterations may be affected by settings such as presolve, scaling, crash\
+ and also by column selection method, infeasibility weight and dual and primal tolerances."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("primalT!olerance", "For an optimal solution \
+no primal infeasibility may exceed this value",
+ 1.0e-20, 1.0e12, CLP_PARAM_DBL_PRIMALTOLERANCE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally the default tolerance is fine, but you may want to increase it a\
+ bit if a primal run seems to be having a hard time"
+ );
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("primalW!eight", "Initially algorithm acts as if it \
+costs this much to be infeasible",
+ 1.0e-20, 1.0e20, CLP_PARAM_DBL_PRIMALWEIGHT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
+ algorithm where you first get feasible then optimal. So Clp is minimizing this weight times\
+ the sum of primal infeasibilities plus the true objective function (in minimization sense).\
+ Too high a value may mean more iterations, while too low a bound means\
+ the code may go all the way and then have to increase the weight in order to get feasible.\
+ OSL had a heuristic to\
+ adjust bounds, maybe we need that here."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("printi!ngOptions", "Print options",
+ "normal", CLP_PARAM_STR_INTPRINT, 3);
+ parameters[numberParameters-1].append("integer");
+ parameters[numberParameters-1].append("special");
+ parameters[numberParameters-1].append("rows");
+ parameters[numberParameters-1].append("all");
+ parameters[numberParameters-1].append("csv");
+ parameters[numberParameters-1].append("bound!ranging");
+ parameters[numberParameters-1].append("rhs!ranging");
+ parameters[numberParameters-1].append("objective!ranging");
+ parameters[numberParameters-1].append("stats");
+ parameters[numberParameters-1].append("boundsint");
+ parameters[numberParameters-1].append("boundsall");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\
+integer - nonzero integer column variables\n\
+special - in format suitable for OsiRowCutDebugger\n\
+rows - nonzero column variables and row activities\n\
+all - all column variables and row activities.\n\
+\nFor non-integer problems 'integer' and 'special' act like 'normal'. \
+Also see printMask for controlling output."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("printM!ask", "Control printing of solution on a mask",
+ CLP_PARAM_ACTION_PRINTMASK, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If set then only those names which match mask are printed in a solution. \
+'?' matches any character and '*' matches any set of characters. \
+ The default is '' i.e. unset so all variables are printed. \
+This is only active if model has names."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("prio!rityIn", "Import priorities etc from file",
+ CBC_PARAM_ACTION_PRIORITYIN, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will read a file with priorities from the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to '', i.e. it must be set. This can not read from compressed files. \
+File is in csv format with allowed headings - name, number, priority, direction, up, down, solution. Exactly one of\
+ name and number must be given."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("probing!Cuts", "Whether to use Probing cuts",
+ "off", CBC_PARAM_STR_PROBINGCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].append("forceonglobal");
+ parameters[numberParameters-1].append("forceOnBut");
+ parameters[numberParameters-1].append("forceOnStrong");
+ parameters[numberParameters-1].append("forceOnButStrong");
+ parameters[numberParameters-1].append("strongRoot");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on probing cuts (either at root or in entire tree) \
+See branchAndCut for information on options. \
+but strong options do more probing"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("proximity!Search", "Whether to do proximity search heuristic",
+ "off", CBC_PARAM_STR_PROXIMITY);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].append("10");
+ parameters[numberParameters-1].append("100");
+ parameters[numberParameters-1].append("300");
+ // but allow numbers after this (returning 1)
+ parameters[numberParameters-1].setFakeKeyWord(1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on a heuristic which looks for a solution close \
+to incumbent solution (Fischetti and Monaci). \
+See Rounding for meaning of on,both,before. \
+Can also set different maxNode settings by plusnnnn (and are 'on'(on==30))."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("pumpC!utoff", "Fake cutoff for use in feasibility pump",
+ -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKECUTOFF);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "0.0 off - otherwise add a constraint forcing objective below this value\
+ in feasibility pump"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("pumpI!ncrement", "Fake increment for use in feasibility pump",
+ -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKEINCREMENT, 1);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "0.0 off - otherwise use as absolute increment to cutoff \
+when solution found in feasibility pump"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("pumpT!une", "Dubious ideas for feasibility pump",
+ 0, 100000000, CBC_PARAM_INT_FPUMPTUNE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This fine tunes Feasibility Pump \n\
+\t>=10000000 use as objective weight switch\n\
+\t>=1000000 use as accumulate switch\n\
+\t>=1000 use index+1 as number of large loops\n\
+\t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\
+\t%100 == 10,20 affects how each solve is done\n\
+\t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \
+If accumulate is on then after a major pass, variables which have not moved \
+are fixed and a small branch and bound is tried."
+ );
+ parameters[numberParameters-1].setIntValue(0);
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("quit", "Stops clp execution",
+ CLP_PARAM_ACTION_EXIT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This stops the execution of Clp, end, exit, quit and stop are synonyms"
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("randomC!bcSeed", "Random seed for Cbc",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_RANDOMSEED);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This sets a random seed for Cbc \
+- 0 says use time of day, -1 is as now."
+ );
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("randomi!zedRounding", "Whether to try randomized rounding heuristic",
+ "off", CBC_PARAM_STR_RANDROUND);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "stuff needed. \
+Doh option does heuristic before preprocessing" );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("randomS!eed", "Random seed for Clp",
+ 0, COIN_INT_MAX, CLP_PARAM_INT_RANDOMSEED);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This sets a random seed for Clp \
+- 0 says use time of day."
+ );
+ parameters[numberParameters-1].setIntValue(1234567);
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("ratio!Gap", "Stop when gap between best possible and \
+best less than this fraction of larger of two",
+ 0.0, 1.0e20, CBC_PARAM_DBL_GAPRATIO);
+ parameters[numberParameters-1].setDoubleValue(0.0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If the gap between best solution and best possible solution is less than this fraction \
+of the objective value at the root node then the search will terminate. See 'allowableGap' for a \
+way of using absolute value rather than fraction."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("restoreS!olution", "reads solution from file",
+ CLP_PARAM_ACTION_RESTORESOL);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will read a binary solution file from the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'solution.file'. This reads in a file from saveSolution"
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("readSt!ored", "Import stored cuts from file",
+ CLP_PARAM_ACTION_STOREDFILE, 3, 0);
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("reallyO!bjectiveScale", "Scale factor to apply to objective in place",
+ -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE2, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "You can set this to -1.0 to test maximization or other to stress code"
+ );
+ parameters[numberParameters-1].setDoubleValue(1.0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("reallyS!cale", "Scales model in place",
+ CLP_PARAM_ACTION_REALLY_SCALE, 7, 0);
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts",
+ "off", CBC_PARAM_STR_REDSPLITCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on reduce and split cuts (either at root or in entire tree). \
+May be slow \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2",
+ "off", CBC_PARAM_STR_REDSPLIT2CUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("longOn");
+ parameters[numberParameters-1].append("longRoot");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on reduce and split cuts (either at root or in entire tree) \
+This version is by Giacomo Nannicini based on Francois Margot's version \
+Standard setting only uses rows in tableau <=256, long uses all \
+May be slow \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2",
+ "off", CBC_PARAM_STR_REDSPLIT2CUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("longOn");
+ parameters[numberParameters-1].append("longRoot");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on reduce and split cuts (either at root or in entire tree) \
+This version is by Giacomo Nannicini based on Francois Margot's version \
+Standard setting only uses rows in tableau <=256, long uses all \
+See branchAndCut for information on options."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("residual!CapacityCuts", "Whether to use Residual Capacity cuts",
+ "off", CBC_PARAM_STR_RESIDCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Residual capacity cuts. \
+See branchAndCut for information on options."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("restore!Model", "Restore model from binary file",
+ CLP_PARAM_ACTION_RESTORE, 7, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This reads data save by saveModel from the given file. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'default.prob'."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("reverse", "Reverses sign of objective",
+ CLP_PARAM_ACTION_REVERSE, 7, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Useful for testing if maximization works correctly"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("rhs!Scale", "Scale factor to apply to rhs and bounds",
+ -1.0e20, 1.0e20, CLP_PARAM_DBL_RHSSCALE, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
+ internally by this amount. It can also be set by autoscale. This should not be needed."
+ );
+ parameters[numberParameters-1].setDoubleValue(1.0);
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("Rens", "Whether to try Relaxation Enforced Neighborhood Search",
+ "off", CBC_PARAM_STR_RENS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].append("200");
+ parameters[numberParameters-1].append("1000");
+ parameters[numberParameters-1].append("10000");
+ parameters[numberParameters-1].append("dj");
+ parameters[numberParameters-1].append("djbefore");
+ parameters[numberParameters-1].append("usesolution");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on Relaxation enforced neighborhood Search. \
+on just does 50 nodes \
+200 or 1000 does that many nodes. \
+Doh option does heuristic before preprocessing" );
+ parameters[numberParameters++] =
+ CbcOrClpParam("Rins", "Whether to try Relaxed Induced Neighborhood Search",
+ "off", CBC_PARAM_STR_RINS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].append("often");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on Relaxed induced neighborhood Search. \
+Doh option does heuristic before preprocessing" );
+ parameters[numberParameters++] =
+ CbcOrClpParam("round!ingHeuristic", "Whether to use Rounding heuristic",
+ "off", CBC_PARAM_STR_ROUNDING);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on a simple (but effective) rounding heuristic at each node of tree. \
+On means do in solve i.e. after preprocessing, \
+Before means do if doHeuristics used, off otherwise, \
+and both means do if doHeuristics and in solve."
+ );
+
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("saveM!odel", "Save model to binary file",
+ CLP_PARAM_ACTION_SAVE, 7, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will save the problem to the given file name for future use\
+ by restoreModel. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'default.prob'."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("saveS!olution", "saves solution to file",
+ CLP_PARAM_ACTION_SAVESOL);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will write a binary solution file to the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'solution.file'. To read the file use fread(int) twice to pick up number of rows \
+and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \
+activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \
+If name contains '_fix_read_' then does not write but reads and will fix all variables"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("scal!ing", "Whether to scale problem",
+ "off", CLP_PARAM_STR_SCALING);
+ parameters[numberParameters-1].append("equi!librium");
+ parameters[numberParameters-1].append("geo!metric");
+ parameters[numberParameters-1].append("auto!matic");
+ parameters[numberParameters-1].append("dynamic");
+ parameters[numberParameters-1].append("rows!only");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Scaling can help in solving problems which might otherwise fail because of lack of\
+ accuracy. It can also reduce the number of iterations. It is not applied if the range\
+ of elements is small. When unscaled it is possible that there may be small primal and/or\
+ infeasibilities."
+ );
+ parameters[numberParameters-1].setCurrentOption(3); // say auto
+#ifndef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("sec!onds", "Maximum seconds",
+ -1.0, 1.0e12, CLP_PARAM_DBL_TIMELIMIT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "After this many seconds clp will act as if maximum iterations had been reached \
+(if value >=0)."
+ );
+#else
+ parameters[numberParameters++] =
+ CbcOrClpParam("sec!onds", "maximum seconds",
+ -1.0, 1.0e12, CBC_PARAM_DBL_TIMELIMIT_BAB);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "After this many seconds coin solver will act as if maximum nodes had been reached."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("sleep", "for debug",
+ CLP_PARAM_ACTION_DUMMY, 7, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If passed to solver fom ampl, then ampl will wait so that you can copy .nl file for debug."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("slow!cutpasses", "Maximum number of tries for slower cuts",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_MAX_SLOW_CUTS);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Some cut generators are fairly slow - this limits the number of times they are tried."
+ );
+ parameters[numberParameters-1].setIntValue(10);
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("slp!Value", "Number of slp passes before primal",
+ -50000, 50000, CLP_PARAM_INT_SLPVALUE, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If you are solving a quadratic problem using primal then it may be helpful to do some \
+sequential Lps to get a good approximate solution."
+ );
+#if CLP_MULTIPLE_FACTORIZATIONS > 0
+ parameters[numberParameters++] =
+ CbcOrClpParam("small!Factorization", "Whether to use small factorization",
+ -1, 10000, CBC_PARAM_INT_SMALLFACT, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If processed problem <= this use small factorization"
+ );
+ parameters[numberParameters-1].setIntValue(-1);
+#endif
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("solu!tion", "Prints solution to file",
+ CLP_PARAM_ACTION_SOLUTION);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This will write a primitive solution file to the given file name. It will use the default\
+ directory given by 'directory'. A name of '$' will use the previous value for the name. This\
+ is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask."
+ );
+#ifdef COIN_HAS_CLP
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("solv!e", "Solve problem",
+ CBC_PARAM_ACTION_BAB);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If there are no integer variables then this just solves LP. If there are integer variables \
+this does branch and cut."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("sos!Options", "Whether to use SOS from AMPL",
+ "off", CBC_PARAM_STR_SOS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setCurrentOption("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\
+ be turned off - this does so."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("slog!Level", "Level of detail in (LP) Solver output",
+ -1, 63, CLP_PARAM_INT_SOLVERLOGLEVEL);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If 0 then there should be no output in normal circumstances. 1 is probably the best\
+ value for most uses, while 2 and 3 give more information. This parameter is only used inside MIP - for Clp use 'log'"
+ );
+#else
+ // allow solve as synonym for possible dual
+ parameters[numberParameters++] =
+ CbcOrClpParam("solv!e", "Solve problem using dual simplex (probably)",
+ CLP_PARAM_ACTION_EITHERSIMPLEX);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Just so can use solve for clp as well as in cbc"
+ );
+#endif
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("spars!eFactor", "Whether factorization treated as sparse",
+ "on", CLP_PARAM_STR_SPARSEFACTOR, 7, 0);
+ parameters[numberParameters-1].append("off");
+ parameters[numberParameters++] =
+ CbcOrClpParam("special!Options", "Dubious options for Simplex - see ClpSimplex.hpp",
+ 0, COIN_INT_MAX, CLP_PARAM_INT_SPECIALOPTIONS, 0);
+ parameters[numberParameters++] =
+ CbcOrClpParam("sprint!Crash", "Whether to try sprint crash",
+ -1, 5000000, CLP_PARAM_INT_SPRINT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "For long and thin problems this program may solve a series of small problems\
+ created by taking a subset of the columns. I introduced the idea as 'Sprint' after\
+ an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
+ Cplex calls it 'sifting'. -1 is automatic choice, 0 is off, n is number of passes"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("stat!istics", "Print some statistics",
+ CLP_PARAM_ACTION_STATISTICS);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This command prints some statistics for the current model.\
+ If log level >1 then more is printed.\
+ These are for presolved model if presolve on (and unscaled)."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("stop", "Stops clp execution",
+ CLP_PARAM_ACTION_EXIT);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This stops the execution of Clp, end, exit, quit and stop are synonyms"
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("strat!egy", "Switches on groups of features",
+ 0, 2, CBC_PARAM_INT_STRATEGY);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This turns on newer features. \
+Use 0 for easy problems, 1 is default, 2 is aggressive. \
+1 uses Gomory cuts using tolerance of 0.01 at root, \
+does a possible restart after 100 nodes if can fix many \
+and activates a diving and RINS heuristic and makes feasibility pump \
+more aggressive. \
+This does not apply to unit tests (where 'experiment' may have similar effects)."
+ );
+ parameters[numberParameters-1].setIntValue(1);
+#ifdef CBC_KEEP_DEPRECATED
+ parameters[numberParameters++] =
+ CbcOrClpParam("strengthen", "Create strengthened problem",
+ CBC_PARAM_ACTION_STRENGTHEN, 3);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This creates a new problem by applying the root node cuts. All tight constraints \
+will be in resulting problem"
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("strong!Branching", "Number of variables to look at in strong branching",
+ 0, COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "In order to decide which variable to branch on, the code will choose up to this number \
+of unsatisfied variables to do mini up and down branches on. Then the most effective one is chosen. \
+If a variable is branched on many times then the previous average up and down costs may be used - \
+see number before trust."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("subs!titution", "How long a column to substitute for in presolve",
+ 0, 10000, CLP_PARAM_INT_SUBSTITUTION, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Normally Presolve gets rid of 'free' variables when there are no more than 3 \
+ variables in column. If you increase this the number of rows may decrease but number of \
+ elements may increase."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("testO!si", "Test OsiObject stuff",
+ -1, COIN_INT_MAX, CBC_PARAM_INT_TESTOSI, 0);
+#endif
+#ifdef CBC_THREAD
+ parameters[numberParameters++] =
+ CbcOrClpParam("thread!s", "Number of threads to try and use",
+ -100, 100000, CBC_PARAM_INT_THREADS, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "To use multiple threads, set threads to number wanted. It may be better \
+to use one or two more than number of cpus available. If 100+n then n threads and \
+search is repeatable (maybe be somewhat slower), \
+if 200+n use threads for root cuts, 400+n threads used in sub-trees."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("tighten!Factor", "Tighten bounds using this times largest \
+activity at continuous solution",
+ 1.0e-3, 1.0e20, CBC_PARAM_DBL_TIGHTENFACTOR, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This sleazy trick can help on some problems."
+ );
+#endif
+#ifdef COIN_HAS_CLP
+ parameters[numberParameters++] =
+ CbcOrClpParam("tightLP", "Poor person's preSolve for now",
+ CLP_PARAM_ACTION_TIGHTEN, 7, 0);
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("timeM!ode", "Whether to use CPU or elapsed time",
+ "cpu", CLP_PARAM_STR_TIME_MODE);
+ parameters[numberParameters-1].append("elapsed");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "cpu uses CPU time for stopping, while elapsed uses elapsed time. \
+(On Windows, elapsed time is always used)."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("trust!PseudoCosts", "Number of branches before we trust pseudocosts",
+ -3, 2000000000, CBC_PARAM_INT_NUMBERBEFORE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Using strong branching computes pseudo-costs. After this many times for a variable we just \
+trust the pseudo costs and do not do any more strong branching."
+ );
+#endif
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("tune!PreProcess", "Dubious tuning parameters",
+ 0, 2000000000, CLP_PARAM_INT_PROCESSTUNE, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Format aabbcccc - \n If aa then this is number of major passes (i.e. with presolve) \n \
+If bb and bb>0 then this is number of minor passes (if unset or 0 then 10) \n \
+cccc is bit set \n 0 - 1 Heavy probing \n 1 - 2 Make variables integer if possible (if obj value)\n \
+2 - 4 As above but even if zero objective value\n \
+7 - 128 Try and create cliques\n 8 - 256 If all +1 try hard for dominated rows\n \
+10 - 1024 Use a larger feasibility tolerance in presolve\n \
+11 - 2048 Try probing before creating cliques"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts",
+ "off", CBC_PARAM_STR_TWOMIRCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].append("forceandglobal");
+ parameters[numberParameters-1].append("forceLongOn");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on two phase mixed integer rounding cuts (either at root or in entire tree) \
+See branchAndCut for information on options."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("unitTest", "Do unit test",
+ CLP_PARAM_ACTION_UNITTEST, 3, 1);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This exercises the unit test for clp"
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("userClp", "Hand coded Clp stuff",
+ CLP_PARAM_ACTION_USERCLP, 0, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "There are times e.g. when using AMPL interface when you may wish to do something unusual. \
+Look for USERCLP in main driver and modify sample code."
+ );
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("userCbc", "Hand coded Cbc stuff",
+ CBC_PARAM_ACTION_USERCBC, 0, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "There are times e.g. when using AMPL interface when you may wish to do something unusual. \
+Look for USERCBC in main driver and modify sample code. \
+It is possible you can get same effect by using example driver4.cpp."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("Vnd!VariableNeighborhoodSearch", "Whether to try Variable Neighborhood Search",
+ "off", CBC_PARAM_STR_VND);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("both");
+ parameters[numberParameters-1].append("before");
+ parameters[numberParameters-1].append("intree");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on variable neighborhood Search. \
+Doh option does heuristic before preprocessing" );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("vector", "Whether to use vector? Form of matrix in simplex",
+ "off", CLP_PARAM_STR_VECTOR, 7, 0);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If this is on ClpPackedMatrix uses extra column copy in odd format."
+ );
+ parameters[numberParameters++] =
+ CbcOrClpParam("verbose", "Switches on longer help on single ?",
+ 0, 31, CLP_PARAM_INT_VERBOSE, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "Set to 1 to get short help with ? list, 2 to get long help, 3 for both. (add 4 to just get ampl ones)."
+ );
+ parameters[numberParameters-1].setIntValue(0);
+#ifdef COIN_HAS_CBC
+ parameters[numberParameters++] =
+ CbcOrClpParam("vub!heuristic", "Type of vub heuristic",
+ -2, 20, CBC_PARAM_INT_VUBTRY, 0);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "If set will try and fix some integer variables"
+ );
+ parameters[numberParameters-1].setIntValue(-1);
+ parameters[numberParameters++] =
+ CbcOrClpParam("zero!HalfCuts", "Whether to use zero half cuts",
+ "off", CBC_PARAM_STR_ZEROHALFCUTS);
+ parameters[numberParameters-1].append("on");
+ parameters[numberParameters-1].append("root");
+ parameters[numberParameters-1].append("ifmove");
+ parameters[numberParameters-1].append("forceOn");
+ parameters[numberParameters-1].append("onglobal");
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This switches on zero-half cuts (either at root or in entire tree) \
+See branchAndCut for information on options. This implementation was written by \
+Alberto Caprara."
+ );
+#endif
+ parameters[numberParameters++] =
+ CbcOrClpParam("zeroT!olerance", "Kill all coefficients \
+whose absolute value is less than this value",
+ 1.0e-100, 1.0e-5, CLP_PARAM_DBL_ZEROTOLERANCE);
+ parameters[numberParameters-1].setLonghelp
+ (
+ "This applies to reading mps files (and also lp files \
+if KILL_ZERO_READLP defined)"
+ );
+ parameters[numberParameters-1].setDoubleValue(1.0e-20);
+ assert(numberParameters < CBCMAXPARAMETERS);
+}
+// Given a parameter type - returns its number in list
+int whichParam (CbcOrClpParameterType name,
+ int numberParameters, CbcOrClpParam *const parameters)
+{
+ int i;
+ for (i = 0; i < numberParameters; i++) {
+ if (parameters[i].type() == name)
+ break;
+ }
+ assert (i < numberParameters);
+ return i;
+}
+#ifdef COIN_HAS_CLP
+/* Restore a solution from file.
+ mode 0 normal, 1 swap rows and columns and primal and dual
+ if 2 set then also change signs
+*/
+void restoreSolution(ClpSimplex * lpSolver, std::string fileName, int mode)
+{
+ FILE * fp = fopen(fileName.c_str(), "rb");
+ if (fp) {
+ int numberRows = lpSolver->numberRows();
+ int numberColumns = lpSolver->numberColumns();
+ int numberRowsFile;
+ int numberColumnsFile;
+ double objectiveValue;
+ size_t nRead;
+ nRead = fread(&numberRowsFile, sizeof(int), 1, fp);
+ if (nRead != 1)
+ throw("Error in fread");
+ nRead = fread(&numberColumnsFile, sizeof(int), 1, fp);
+ if (nRead != 1)
+ throw("Error in fread");
+ nRead = fread(&objectiveValue, sizeof(double), 1, fp);
+ if (nRead != 1)
+ throw("Error in fread");
+ double * dualRowSolution = lpSolver->dualRowSolution();
+ double * primalRowSolution = lpSolver->primalRowSolution();
+ double * dualColumnSolution = lpSolver->dualColumnSolution();
+ double * primalColumnSolution = lpSolver->primalColumnSolution();
+ if (mode) {
+ // swap
+ int k = numberRows;
+ numberRows = numberColumns;
+ numberColumns = k;
+ double * temp;
+ temp = dualRowSolution;
+ dualRowSolution = primalColumnSolution;
+ primalColumnSolution = temp;
+ temp = dualColumnSolution;
+ dualColumnSolution = primalRowSolution;
+ primalRowSolution = temp;
+ }
+ if (numberRows > numberRowsFile || numberColumns > numberColumnsFile) {
+ std::cout << "Mismatch on rows and/or columns - giving up" << std::endl;
+ } else {
+ lpSolver->setObjectiveValue(objectiveValue);
+ if (numberRows == numberRowsFile && numberColumns == numberColumnsFile) {
+ nRead = fread(primalRowSolution, sizeof(double), numberRows, fp);
+ if (nRead != static_cast<size_t>(numberRows))
+ throw("Error in fread");
+ nRead = fread(dualRowSolution, sizeof(double), numberRows, fp);
+ if (nRead != static_cast<size_t>(numberRows))
+ throw("Error in fread");
+ nRead = fread(primalColumnSolution, sizeof(double), numberColumns, fp);
+ if (nRead != static_cast<size_t>(numberColumns))
+ throw("Error in fread");
+ nRead = fread(dualColumnSolution, sizeof(double), numberColumns, fp);
+ if (nRead != static_cast<size_t>(numberColumns))
+ throw("Error in fread");
+ } else {
+ std::cout << "Mismatch on rows and/or columns - truncating" << std::endl;
+ double * temp = new double [CoinMax(numberRowsFile, numberColumnsFile)];
+ nRead = fread(temp, sizeof(double), numberRowsFile, fp);
+ if (nRead != static_cast<size_t>(numberRowsFile))
+ throw("Error in fread");
+ CoinMemcpyN(temp, numberRows, primalRowSolution);
+ nRead = fread(temp, sizeof(double), numberRowsFile, fp);
+ if (nRead != static_cast<size_t>(numberRowsFile))
+ throw("Error in fread");
+ CoinMemcpyN(temp, numberRows, dualRowSolution);
+ nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
+ if (nRead != static_cast<size_t>(numberColumnsFile))
+ throw("Error in fread");
+ CoinMemcpyN(temp, numberColumns, primalColumnSolution);
+ nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
+ if (nRead != static_cast<size_t>(numberColumnsFile))
+ throw("Error in fread");
+ CoinMemcpyN(temp, numberColumns, dualColumnSolution);
+ delete [] temp;
+ }
+ if (mode == 3) {
+ int i;
+ for (i = 0; i < numberRows; i++) {
+ primalRowSolution[i] = -primalRowSolution[i];
+ dualRowSolution[i] = -dualRowSolution[i];
+ }
+ for (i = 0; i < numberColumns; i++) {
+ primalColumnSolution[i] = -primalColumnSolution[i];
+ dualColumnSolution[i] = -dualColumnSolution[i];
+ }
+ }
+ }
+ fclose(fp);
+ } else {
+ std::cout << "Unable to open file " << fileName << std::endl;
+ }
+}
+// Dump a solution to file
+void saveSolution(const ClpSimplex * lpSolver, std::string fileName)
+{
+ if (strstr(fileName.c_str(), "_fix_read_")) {
+ FILE * fp = fopen(fileName.c_str(), "rb");
+ if (fp) {
+ ClpSimplex * solver = const_cast<ClpSimplex *>(lpSolver);
+ restoreSolution(solver, fileName, 0);
+ // fix all
+ int logLevel = solver->logLevel();
+ int iColumn;
+ int numberColumns = solver->numberColumns();
+ double * primalColumnSolution =
+ solver->primalColumnSolution();
+ double * columnLower = solver->columnLower();
+ double * columnUpper = solver->columnUpper();
+ for (iColumn = 0; iColumn < numberColumns; iColumn++) {
+ double value = primalColumnSolution[iColumn];
+ if (value > columnUpper[iColumn]) {
+ if (value > columnUpper[iColumn] + 1.0e-6 && logLevel > 1)
+ printf("%d value of %g - bounds %g %g\n",
+ iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
+ value = columnUpper[iColumn];
+ } else if (value < columnLower[iColumn]) {
+ if (value < columnLower[iColumn] - 1.0e-6 && logLevel > 1)
+ printf("%d value of %g - bounds %g %g\n",
+ iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
+ value = columnLower[iColumn];
+ }
+ columnLower[iColumn] = value;
+ columnUpper[iColumn] = value;
+ }
+ return;
+ }
+ }
+ FILE * fp = fopen(fileName.c_str(), "wb");
+ if (fp) {
+ int numberRows = lpSolver->numberRows();
+ int numberColumns = lpSolver->numberColumns();
+ double objectiveValue = lpSolver->objectiveValue();
+ size_t nWrite;
+ nWrite = fwrite(&numberRows, sizeof(int), 1, fp);
+ if (nWrite != 1)
+ throw("Error in fwrite");
+ nWrite = fwrite(&numberColumns, sizeof(int), 1, fp);
+ if (nWrite != 1)
+ throw("Error in fwrite");
+ nWrite = fwrite(&objectiveValue, sizeof(double), 1, fp);
+ if (nWrite != 1)
+ throw("Error in fwrite");
+ double * dualRowSolution = lpSolver->dualRowSolution();
+ double * primalRowSolution = lpSolver->primalRowSolution();
+ nWrite = fwrite(primalRowSolution, sizeof(double), numberRows, fp);
+ if (nWrite != static_cast<size_t>(numberRows))
+ throw("Error in fwrite");
+ nWrite = fwrite(dualRowSolution, sizeof(double), numberRows, fp);
+ if (nWrite != static_cast<size_t>(numberRows))
+ throw("Error in fwrite");
+ double * dualColumnSolution = lpSolver->dualColumnSolution();
+ double * primalColumnSolution = lpSolver->primalColumnSolution();
+ nWrite = fwrite(primalColumnSolution, sizeof(double), numberColumns, fp);
+ if (nWrite != static_cast<size_t>(numberColumns))
+ throw("Error in fwrite");
+ nWrite = fwrite(dualColumnSolution, sizeof(double), numberColumns, fp);
+ if (nWrite != static_cast<size_t>(numberColumns))
+ throw("Error in fwrite");
+ fclose(fp);
+ } else {
+ std::cout << "Unable to open file " << fileName << std::endl;
+ }
+}
+#endif