diff options
author | Harpreet | 2015-08-27 02:32:30 +0530 |
---|---|---|
committer | Harpreet | 2015-08-27 02:32:30 +0530 |
commit | f9afc284ce324fa3c13606ad90895beec507c249 (patch) | |
tree | a1680fec3342c4eb00b73cd056ff9fad519c5877 /thirdparty/linux/include | |
download | FOSSEE-Optimization-toolbox-f9afc284ce324fa3c13606ad90895beec507c249.tar.gz FOSSEE-Optimization-toolbox-f9afc284ce324fa3c13606ad90895beec507c249.tar.bz2 FOSSEE-Optimization-toolbox-f9afc284ce324fa3c13606ad90895beec507c249.zip |
Master File
Diffstat (limited to 'thirdparty/linux/include')
156 files changed, 57030 insertions, 0 deletions
diff --git a/thirdparty/linux/include/coin/CbcOrClpParam.cpp b/thirdparty/linux/include/coin/CbcOrClpParam.cpp new file mode 100644 index 0000000..b434fe0 --- /dev/null +++ b/thirdparty/linux/include/coin/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&¤tKeyWord_<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 diff --git a/thirdparty/linux/include/coin/CbcOrClpParam.hpp b/thirdparty/linux/include/coin/CbcOrClpParam.hpp new file mode 100644 index 0000000..d76d966 --- /dev/null +++ b/thirdparty/linux/include/coin/CbcOrClpParam.hpp @@ -0,0 +1,531 @@ + +/* $Id: CbcOrClpParam.hpp 2070 2014-11-18 11:12:54Z 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). + +#ifdef USE_CBCCONFIG +# include "CbcConfig.h" +#else +# include "ClpConfig.h" +#endif + +#ifndef CbcOrClpParam_H +#define CbcOrClpParam_H +/** + This has parameter handling stuff which can be shared between Cbc and Clp (and Dylp etc). + + This (and .cpp) should be copied so that it is the same in Cbc/Test and Clp/Test. + I know this is not elegant but it seems simplest. + + It uses COIN_HAS_CBC for parameters wanted by CBC + It uses COIN_HAS_CLP for parameters wanted by CLP (or CBC using CLP) + It could use COIN_HAS_DYLP for parameters wanted by DYLP + It could use COIN_HAS_DYLP_OR_CLP for parameters wanted by DYLP or CLP etc etc + + */ +class OsiSolverInterface; +class CbcModel; +class ClpSimplex; +/*! \brief Parameter codes + + Parameter type ranges are allocated as follows + <ul> + <li> 1 -- 100 double parameters + <li> 101 -- 200 integer parameters + <li> 201 -- 250 string parameters + <li> 251 -- 300 cuts etc(string but broken out for clarity) + <li> 301 -- 400 `actions' + </ul> + + `Actions' do not necessarily invoke an immediate action; it's just that they + don't fit neatly into the parameters array. + + This coding scheme is in flux. +*/ + +enum CbcOrClpParameterType + +{ + CBC_PARAM_GENERALQUERY = -100, + CBC_PARAM_FULLGENERALQUERY, + + CLP_PARAM_DBL_PRIMALTOLERANCE = 1, + CLP_PARAM_DBL_DUALTOLERANCE, + CLP_PARAM_DBL_TIMELIMIT, + CLP_PARAM_DBL_DUALBOUND, + CLP_PARAM_DBL_PRIMALWEIGHT, + CLP_PARAM_DBL_OBJSCALE, + CLP_PARAM_DBL_RHSSCALE, + CLP_PARAM_DBL_ZEROTOLERANCE, + + CBC_PARAM_DBL_INFEASIBILITYWEIGHT = 51, + CBC_PARAM_DBL_CUTOFF, + CBC_PARAM_DBL_INTEGERTOLERANCE, + CBC_PARAM_DBL_INCREMENT, + CBC_PARAM_DBL_ALLOWABLEGAP, + CBC_PARAM_DBL_TIMELIMIT_BAB, + CBC_PARAM_DBL_GAPRATIO, + + CBC_PARAM_DBL_DJFIX = 81, + CBC_PARAM_DBL_TIGHTENFACTOR, + CLP_PARAM_DBL_PRESOLVETOLERANCE, + CLP_PARAM_DBL_OBJSCALE2, + CBC_PARAM_DBL_FAKEINCREMENT, + CBC_PARAM_DBL_FAKECUTOFF, + CBC_PARAM_DBL_ARTIFICIALCOST, + CBC_PARAM_DBL_DEXTRA3, + CBC_PARAM_DBL_SMALLBAB, + CBC_PARAM_DBL_DEXTRA4, + CBC_PARAM_DBL_DEXTRA5, + + CLP_PARAM_INT_SOLVERLOGLEVEL = 101, +#ifndef COIN_HAS_CBC + CLP_PARAM_INT_LOGLEVEL = 101, +#endif + CLP_PARAM_INT_MAXFACTOR, + CLP_PARAM_INT_PERTVALUE, + CLP_PARAM_INT_MAXITERATION, + CLP_PARAM_INT_PRESOLVEPASS, + CLP_PARAM_INT_IDIOT, + CLP_PARAM_INT_SPRINT, + CLP_PARAM_INT_OUTPUTFORMAT, + CLP_PARAM_INT_SLPVALUE, + CLP_PARAM_INT_PRESOLVEOPTIONS, + CLP_PARAM_INT_PRINTOPTIONS, + CLP_PARAM_INT_SPECIALOPTIONS, + CLP_PARAM_INT_SUBSTITUTION, + CLP_PARAM_INT_DUALIZE, + CLP_PARAM_INT_VERBOSE, + CLP_PARAM_INT_CPP, + CLP_PARAM_INT_PROCESSTUNE, + CLP_PARAM_INT_USESOLUTION, + CLP_PARAM_INT_RANDOMSEED, + CLP_PARAM_INT_MORESPECIALOPTIONS, + CLP_PARAM_INT_DECOMPOSE_BLOCKS, + + CBC_PARAM_INT_STRONGBRANCHING = 151, + CBC_PARAM_INT_CUTDEPTH, + CBC_PARAM_INT_MAXNODES, + CBC_PARAM_INT_NUMBERBEFORE, + CBC_PARAM_INT_NUMBERANALYZE, + CBC_PARAM_INT_MIPOPTIONS, + CBC_PARAM_INT_MOREMIPOPTIONS, + CBC_PARAM_INT_MAXHOTITS, + CBC_PARAM_INT_FPUMPITS, + CBC_PARAM_INT_MAXSOLS, + CBC_PARAM_INT_FPUMPTUNE, + CBC_PARAM_INT_TESTOSI, + CBC_PARAM_INT_EXTRA1, + CBC_PARAM_INT_EXTRA2, + CBC_PARAM_INT_EXTRA3, + CBC_PARAM_INT_EXTRA4, + CBC_PARAM_INT_DEPTHMINIBAB, + CBC_PARAM_INT_CUTPASSINTREE, + CBC_PARAM_INT_THREADS, + CBC_PARAM_INT_CUTPASS, + CBC_PARAM_INT_VUBTRY, + CBC_PARAM_INT_DENSE, + CBC_PARAM_INT_EXPERIMENT, + CBC_PARAM_INT_DIVEOPT, + CBC_PARAM_INT_DIVEOPTSOLVES, + CBC_PARAM_INT_STRATEGY, + CBC_PARAM_INT_SMALLFACT, + CBC_PARAM_INT_HOPTIONS, + CBC_PARAM_INT_CUTLENGTH, + CBC_PARAM_INT_FPUMPTUNE2, +#ifdef COIN_HAS_CBC + CLP_PARAM_INT_LOGLEVEL , +#endif + CBC_PARAM_INT_MAXSAVEDSOLS, + CBC_PARAM_INT_RANDOMSEED, + CBC_PARAM_INT_MULTIPLEROOTS, + CBC_PARAM_INT_STRONG_STRATEGY, + CBC_PARAM_INT_EXTRA_VARIABLES, + CBC_PARAM_INT_MAX_SLOW_CUTS, + CBC_PARAM_INT_MOREMOREMIPOPTIONS, + + CLP_PARAM_STR_DIRECTION = 201, + CLP_PARAM_STR_DUALPIVOT, + CLP_PARAM_STR_SCALING, + CLP_PARAM_STR_ERRORSALLOWED, + CLP_PARAM_STR_KEEPNAMES, + CLP_PARAM_STR_SPARSEFACTOR, + CLP_PARAM_STR_PRIMALPIVOT, + CLP_PARAM_STR_PRESOLVE, + CLP_PARAM_STR_CRASH, + CLP_PARAM_STR_BIASLU, + CLP_PARAM_STR_PERTURBATION, + CLP_PARAM_STR_MESSAGES, + CLP_PARAM_STR_AUTOSCALE, + CLP_PARAM_STR_CHOLESKY, + CLP_PARAM_STR_KKT, + CLP_PARAM_STR_BARRIERSCALE, + CLP_PARAM_STR_GAMMA, + CLP_PARAM_STR_CROSSOVER, + CLP_PARAM_STR_PFI, + CLP_PARAM_STR_INTPRINT, + CLP_PARAM_STR_VECTOR, + CLP_PARAM_STR_FACTORIZATION, + CLP_PARAM_STR_ALLCOMMANDS, + CLP_PARAM_STR_TIME_MODE, + CLP_PARAM_STR_ABCWANTED, + + CBC_PARAM_STR_NODESTRATEGY = 251, + CBC_PARAM_STR_BRANCHSTRATEGY, + CBC_PARAM_STR_CUTSSTRATEGY, + CBC_PARAM_STR_HEURISTICSTRATEGY, + CBC_PARAM_STR_GOMORYCUTS, + CBC_PARAM_STR_PROBINGCUTS, + CBC_PARAM_STR_KNAPSACKCUTS, + CBC_PARAM_STR_REDSPLITCUTS, + CBC_PARAM_STR_ROUNDING, + CBC_PARAM_STR_SOLVER, + CBC_PARAM_STR_CLIQUECUTS, + CBC_PARAM_STR_COSTSTRATEGY, + CBC_PARAM_STR_FLOWCUTS, + CBC_PARAM_STR_MIXEDCUTS, + CBC_PARAM_STR_TWOMIRCUTS, + CBC_PARAM_STR_PREPROCESS, + CBC_PARAM_STR_FPUMP, + CBC_PARAM_STR_GREEDY, + CBC_PARAM_STR_COMBINE, + CBC_PARAM_STR_PROXIMITY, + CBC_PARAM_STR_LOCALTREE, + CBC_PARAM_STR_SOS, + CBC_PARAM_STR_LANDPCUTS, + CBC_PARAM_STR_RINS, + CBC_PARAM_STR_RESIDCUTS, + CBC_PARAM_STR_RENS, + CBC_PARAM_STR_DIVINGS, + CBC_PARAM_STR_DIVINGC, + CBC_PARAM_STR_DIVINGF, + CBC_PARAM_STR_DIVINGG, + CBC_PARAM_STR_DIVINGL, + CBC_PARAM_STR_DIVINGP, + CBC_PARAM_STR_DIVINGV, + CBC_PARAM_STR_DINS, + CBC_PARAM_STR_PIVOTANDFIX, + CBC_PARAM_STR_RANDROUND, + CBC_PARAM_STR_NAIVE, + CBC_PARAM_STR_ZEROHALFCUTS, + CBC_PARAM_STR_CPX, + CBC_PARAM_STR_CROSSOVER2, + CBC_PARAM_STR_PIVOTANDCOMPLEMENT, + CBC_PARAM_STR_VND, + CBC_PARAM_STR_LAGOMORYCUTS, + CBC_PARAM_STR_LATWOMIRCUTS, + CBC_PARAM_STR_REDSPLIT2CUTS, + CBC_PARAM_STR_GMICUTS, + CBC_PARAM_STR_CUTOFF_CONSTRAINT, + CBC_PARAM_STR_DW, + CBC_PARAM_STR_ORBITAL, + + CLP_PARAM_ACTION_DIRECTORY = 301, + CLP_PARAM_ACTION_DIRSAMPLE, + CLP_PARAM_ACTION_DIRNETLIB, + CBC_PARAM_ACTION_DIRMIPLIB, + CLP_PARAM_ACTION_IMPORT, + CLP_PARAM_ACTION_EXPORT, + CLP_PARAM_ACTION_RESTORE, + CLP_PARAM_ACTION_SAVE, + CLP_PARAM_ACTION_DUALSIMPLEX, + CLP_PARAM_ACTION_PRIMALSIMPLEX, + CLP_PARAM_ACTION_EITHERSIMPLEX, + CLP_PARAM_ACTION_MAXIMIZE, + CLP_PARAM_ACTION_MINIMIZE, + CLP_PARAM_ACTION_EXIT, + CLP_PARAM_ACTION_STDIN, + CLP_PARAM_ACTION_UNITTEST, + CLP_PARAM_ACTION_NETLIB_EITHER, + CLP_PARAM_ACTION_NETLIB_DUAL, + CLP_PARAM_ACTION_NETLIB_PRIMAL, + CLP_PARAM_ACTION_SOLUTION, + CLP_PARAM_ACTION_SAVESOL, + CLP_PARAM_ACTION_TIGHTEN, + CLP_PARAM_ACTION_FAKEBOUND, + CLP_PARAM_ACTION_HELP, + CLP_PARAM_ACTION_PLUSMINUS, + CLP_PARAM_ACTION_NETWORK, + CLP_PARAM_ACTION_ALLSLACK, + CLP_PARAM_ACTION_REVERSE, + CLP_PARAM_ACTION_BARRIER, + CLP_PARAM_ACTION_NETLIB_BARRIER, + CLP_PARAM_ACTION_NETLIB_TUNE, + CLP_PARAM_ACTION_REALLY_SCALE, + CLP_PARAM_ACTION_BASISIN, + CLP_PARAM_ACTION_BASISOUT, + CLP_PARAM_ACTION_SOLVECONTINUOUS, + CLP_PARAM_ACTION_CLEARCUTS, + CLP_PARAM_ACTION_VERSION, + CLP_PARAM_ACTION_STATISTICS, + CLP_PARAM_ACTION_DEBUG, + CLP_PARAM_ACTION_DUMMY, + CLP_PARAM_ACTION_PRINTMASK, + CLP_PARAM_ACTION_OUTDUPROWS, + CLP_PARAM_ACTION_USERCLP, + CLP_PARAM_ACTION_MODELIN, + CLP_PARAM_ACTION_CSVSTATISTICS, + CLP_PARAM_ACTION_STOREDFILE, + CLP_PARAM_ACTION_ENVIRONMENT, + CLP_PARAM_ACTION_PARAMETRICS, + CLP_PARAM_ACTION_GMPL_SOLUTION, + CLP_PARAM_ACTION_RESTORESOL, + + CBC_PARAM_ACTION_BAB = 361, + CBC_PARAM_ACTION_MIPLIB, + CBC_PARAM_ACTION_STRENGTHEN, + CBC_PARAM_ACTION_PRIORITYIN, + CBC_PARAM_ACTION_MIPSTART, + CBC_PARAM_ACTION_USERCBC, + CBC_PARAM_ACTION_DOHEURISTIC, + CLP_PARAM_ACTION_NEXTBESTSOLUTION, + + CBC_PARAM_NOTUSED_OSLSTUFF = 401, + CBC_PARAM_NOTUSED_CBCSTUFF, + + CBC_PARAM_NOTUSED_INVALID = 1000 +} ; +#include <vector> +#include <string> + +/// Very simple class for setting parameters + +class CbcOrClpParam { +public: + /**@name Constructor and destructor */ + //@{ + /// Constructors + CbcOrClpParam ( ); + CbcOrClpParam (std::string name, std::string help, + double lower, double upper, CbcOrClpParameterType type, int display = 2); + CbcOrClpParam (std::string name, std::string help, + int lower, int upper, CbcOrClpParameterType type, int display = 2); + // Other strings will be added by insert + CbcOrClpParam (std::string name, std::string help, std::string firstValue, + CbcOrClpParameterType type, int whereUsed = 7, int display = 2); + // Action + CbcOrClpParam (std::string name, std::string help, + CbcOrClpParameterType type, int whereUsed = 7, int display = 2); + /// Copy constructor. + CbcOrClpParam(const CbcOrClpParam &); + /// Assignment operator. This copies the data + CbcOrClpParam & operator=(const CbcOrClpParam & rhs); + /// Destructor + ~CbcOrClpParam ( ); + //@} + + /**@name stuff */ + //@{ + /// Insert string (only valid for keywords) + void append(std::string keyWord); + /// Adds one help line + void addHelp(std::string keyWord); + /// Returns name + inline std::string name( ) const { + return name_; + } + /// Returns short help + inline std::string shortHelp( ) const { + return shortHelp_; + } + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(CbcModel & model, double value) ; + /// Sets double parameter and returns printable string and error code + const char * setDoubleParameterWithMessage ( CbcModel & model, double value , int & returnCode); + /// Gets a double parameter + double doubleParameter(CbcModel & model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(CbcModel & model, int value) ; + /// Sets int parameter and returns printable string and error code + const char * setIntParameterWithMessage ( CbcModel & model, int value , int & returnCode); + /// Gets a int parameter + int intParameter(CbcModel & model) const; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(ClpSimplex * model, double value) ; + /// Gets a double parameter + double doubleParameter(ClpSimplex * model) const; + /// Sets double parameter and returns printable string and error code + const char * setDoubleParameterWithMessage ( ClpSimplex * model, double value , int & returnCode); + /// Sets a int parameter (nonzero code if error) + int setIntParameter(ClpSimplex * model, int value) ; + /// Sets int parameter and returns printable string and error code + const char * setIntParameterWithMessage ( ClpSimplex * model, int value , int & returnCode); + /// Gets a int parameter + int intParameter(ClpSimplex * model) const; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(OsiSolverInterface * model, double value) ; + /// Sets double parameter and returns printable string and error code + const char * setDoubleParameterWithMessage ( OsiSolverInterface * model, double value , int & returnCode); + /// Gets a double parameter + double doubleParameter(OsiSolverInterface * model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(OsiSolverInterface * model, int value) ; + /// Sets int parameter and returns printable string and error code + const char * setIntParameterWithMessage ( OsiSolverInterface * model, int value , int & returnCode); + /// Gets a int parameter + int intParameter(OsiSolverInterface * model) const; + /// Checks a double parameter (nonzero code if error) + int checkDoubleParameter(double value) const; + /// Returns name which could match + std::string matchName ( ) const; + /// Returns length of name for ptinting + int lengthMatchName ( ) const; + /// Returns parameter option which matches (-1 if none) + int parameterOption ( std::string check ) const; + /// Prints parameter options + void printOptions ( ) const; + /// Returns current parameter option + inline std::string currentOption ( ) const { + return definedKeyWords_[currentKeyWord_]; + } + /// Sets current parameter option + void setCurrentOption ( int value , bool printIt = false); + /// Sets current parameter option and returns printable string + const char * setCurrentOptionWithMessage ( int value ); + /// Sets current parameter option using string + void setCurrentOption (const std::string value ); + /// Sets current parameter option using string with message + const char * setCurrentOptionWithMessage (const std::string value ); + /// Returns current parameter option position + int currentOptionAsInteger ( ) const ; + /** Returns current parameter option position + but if fake keyword returns a fake value and sets + fakeInteger to true value. If not fake then fakeInteger is -COIN_INT_MAX + */ + int currentOptionAsInteger ( int & fakeInteger ) const; + /// Sets int value + void setIntValue ( int value ); + /// Sets int value with message + const char * setIntValueWithMessage ( int value ); + inline int intValue () const { + return intValue_; + } + /// Sets double value + void setDoubleValue ( double value ); + /// Sets double value with message + const char * setDoubleValueWithMessage ( double value ); + inline double doubleValue () const { + return doubleValue_; + } + /// Sets string value + void setStringValue ( std::string value ); + inline std::string stringValue () const { + return stringValue_; + } + /// Returns 1 if matches minimum, 2 if matches less, 0 if not matched + int matches (std::string input) const; + /// type + inline CbcOrClpParameterType type() const { + return type_; + } + /// whether to display + inline int displayThis() const { + return display_; + } + /// Set Long help + inline void setLonghelp(const std::string help) { + longHelp_ = help; + } + /// Print Long help + void printLongHelp() const; + /// Print action and string + void printString() const; + /** 7 if used everywhere, + 1 - used by clp + 2 - used by cbc + 4 - used by ampl + */ + inline int whereUsed() const { + return whereUsed_; + } + /// Gets value of fake keyword + inline int fakeKeyWord() const + { return fakeKeyWord_;} + /// Sets value of fake keyword + inline void setFakeKeyWord(int value, int fakeValue) + { fakeKeyWord_ = value; fakeValue_ = fakeValue;} + /// Sets value of fake keyword to current size of keywords + void setFakeKeyWord(int fakeValue); + +private: + /// gutsOfConstructor + void gutsOfConstructor(); + //@} +////////////////// data ////////////////// +private: + + /**@name data + We might as well throw all type data in - could derive? + */ + //@{ + // Type see CbcOrClpParameterType + CbcOrClpParameterType type_; + /// If double == okay + double lowerDoubleValue_; + double upperDoubleValue_; + /// If int == okay + int lowerIntValue_; + int upperIntValue_; + // Length of name + unsigned int lengthName_; + // Minimum match + unsigned int lengthMatch_; + /// set of valid strings + std::vector<std::string> definedKeyWords_; + /// Name + std::string name_; + /// Short help + std::string shortHelp_; + /// Long help + std::string longHelp_; + /// Action + CbcOrClpParameterType action_; + /// Current keyWord (if a keyword parameter) + int currentKeyWord_; + /// Display on ? + int display_; + /// Integer parameter - current value + int intValue_; + /// Double parameter - current value + double doubleValue_; + /// String parameter - current value + std::string stringValue_; + /** 7 if used everywhere, + 1 - used by clp + 2 - used by cbc + 4 - used by ampl + */ + int whereUsed_; + /** If >=0 then integers allowed as a fake keyword + So minusnnnn would got to -nnnn in currentKeyword_ + and plusnnnn would go to fakeKeyword_+nnnn + */ + int fakeKeyWord_; + /// Return this as main value if an integer + int fakeValue_; + //@} +}; +/// Simple read stuff +std::string CoinReadNextField(); + +std::string CoinReadGetCommand(int argc, const char *argv[]); +std::string CoinReadGetString(int argc, const char *argv[]); +// valid 0 - okay, 1 bad, 2 not there +int CoinReadGetIntField(int argc, const char *argv[], int * valid); +double CoinReadGetDoubleField(int argc, const char *argv[], int * valid); +void CoinReadPrintit(const char * input); +void setCbcOrClpPrinting(bool yesNo); +#define CBCMAXPARAMETERS 250 +/* + 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); +// Given a parameter type - returns its number in list +int whichParam (CbcOrClpParameterType name, + int numberParameters, CbcOrClpParam *const parameters); +// Dump/restore a solution to file +void saveSolution(const ClpSimplex * lpSolver, std::string fileName); +void restoreSolution(ClpSimplex * lpSolver, std::string fileName, int mode); +#endif /* CbcOrClpParam_H */ diff --git a/thirdparty/linux/include/coin/Cgl012cut.hpp b/thirdparty/linux/include/coin/Cgl012cut.hpp new file mode 100644 index 0000000..2814b0a --- /dev/null +++ b/thirdparty/linux/include/coin/Cgl012cut.hpp @@ -0,0 +1,464 @@ +// $Id: Cgl012cut.hpp 1149 2013-10-21 18:23:53Z tkr $ +// Copyright (C) 2010, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/** @file 012cut.h Include file for C coded 0-1/2 separator */ +#ifndef CGL012CUT +#define CGL012CUT +#include <cstdio> +#include <cstdlib> +#include <cmath> + +#define CGL_NEW_SHORT +#ifndef CGL_NEW_SHORT +typedef /* arc */ + struct arc_st +{ + int len; /* length of the arc */ + struct node_st *head; /* head node */ +} + arc; + +typedef /* node */ + struct node_st +{ + arc *first; /* first outgoing arc */ + int dist; /* tentative shortest path length */ + struct node_st *parent; /* parent pointer */ + struct node_st *next; /* next node in queue */ + struct node_st *prev; /* previous node in queue */ + int status; /* status of node */ + int temp; /* for temporary labels */ + int index; /* index of the node in the graph */ +} node; +#endif +typedef struct +{ + int length; // Length of arc + int to; // To node +} cgl_arc; + +typedef struct +{ + cgl_arc * firstArc; // First outgoing arc + int parentNode; // Parent node in shortest path + int index; // Which node I am + int distanceBack; // Distance back to source +} cgl_node; + +typedef struct +{ + int nnodes; // Number of nodes in graph + int narcs; // Number of arcs in graph + cgl_node * nodes; + cgl_arc * arcs; +} cgl_graph; +/* #define PRINT */ +/* #define PRINT_CUTS */ +#define REDUCTION + +typedef struct { +int mr; /* number of rows in the ILP matrix */ +int mc; /* number of columns in the ILP matrix */ +int mnz; /* number of nonzero's in the ILP matrix */ +int *mtbeg; /* starting position of each row in arrays mtind and mtval */ +int *mtcnt; /* number of entries of each row in arrays mtind and mtval */ +int *mtind; /* column indices of the nonzero entries of the ILP matrix */ +int *mtval; /* values of the nonzero entries of the ILP matrix */ +int *vlb; /* lower bounds on the variables */ +int *vub; /* upper bounds on the variables */ +int *mrhs; /* right hand sides of the constraints */ +char *msense; /* senses of the constraints: 'L', 'G' or 'E' */ +const double *xstar; /* current optimal solution of the LP relaxation */ +} ilp; + +typedef struct { +int mr; /* number of rows in the parity ILP matrix */ +int mc; /* number of columns in the parity ILP matrix */ +int mnz; /* number of 1's in the parity ILP matrix */ +int *mtbeg; /* starting position of each row in arrays mtind and mtval */ +int *mtcnt; /* number of entries of each row in arrays mtind and mtval */ +int *mtind; /* column indices of the 1's of the parity ILP matrix */ +short int *mrhs; /* right hand side parity of the constraints */ +double *xstar; /* current optimal solution of the LP relaxation */ +double *slack; /* slack of the constraints w.r.t. xstar */ +short int *row_to_delete; /* flag for marking rows not to be considered */ +short int *col_to_delete; /* flag for marking columns not to be considered */ +int *gcd; /* greatest common divisor of each row in the input ILP matrix */ +short int *possible_weak; /* possible weakening types of each column */ +short int *type_even_weak; /* type of even weakening of each column + (lower or upper bound weakening) */ +short int *type_odd_weak; /* type of odd weakening of each column + (lower or upper bound weakening) */ +double *loss_even_weak; /* loss for the even weakening of each column */ +double *loss_odd_weak; /* loss for the odd weakening of each column */ +double *min_loss_by_weak; /* minimum loss for the weakening of each column */ +} parity_ilp; + +typedef struct { +int nweak; /* number of variables weakened */ +int *var; /* list of variables weakened */ +short int *type; /* type of weakening (lower or upper bound weakening) */ +} info_weak; + +typedef struct { +int endpoint1, endpoint2; /* endpoints of the edge */ +double weight; /* edge weight */ +short int parity; /* edge parity (even or odd) */ +int constr; /* constraint associated with the edge */ +info_weak *weak; /* weakening information */ +} edge; + +typedef struct { +int nnodes; /* number of nodes */ +int nedges; /* number of edges */ +int *nodes; /* indexes of the ILP columns corresponding to the nodes */ +int *ind; /* indexes of the nodes corresponding to the ILP columns */ +edge **even_adj_list; /* pointers to the even edges */ +edge **odd_adj_list; /* pointers to the odd edges */ +} separation_graph; + +#ifndef CGL_NEW_SHORT +typedef struct { +int nnodes; /* number of nodes */ +int narcs; /* number of arcs */ +node *nodes; /* array of the nodes - see "types_db.h" */ +arc *arcs; /* array of the arcs - see "types_db.h" */ +} auxiliary_graph; +#else +typedef struct { +int nnodes; /* number of nodes */ +int narcs; /* number of arcs */ +cgl_node *nodes; /* array of the nodes - see "types_db.h" */ +cgl_arc *arcs; /* array of the arcs - see "types_db.h" */ +} auxiliary_graph; +#endif + +typedef struct { +long dist; /* distance from/to root */ +int pred; /* index of the predecessor */ +} short_path_node; + +typedef struct { +double weight; /* overall weight of the cycle */ +int length; /* number of edges in the cycle */ +edge **edge_list; /* list of edges in the cycle */ +} cycle; + +typedef struct { +int cnum; /* overall number of cycles */ +cycle **list; /* pointers to the cycles in the list */ +} cycle_list; + +typedef struct { +int n_of_constr; /* number of constraints combined to get the cut */ +int *constr_list; /* list of the constraints combined */ +short int *in_constr_list; /* flag saying whether a given constraint is + in the list of constraints of the cut (IN) + or not (OUT) */ +int cnzcnt; /* overall number of nonzero's in the cut */ +int *cind; /* column indices of the nonzero entries of the cut */ +int *cval; /* values of the nonzero entries of the cut */ +int crhs; /* right hand side of the cut */ +char csense; /* sense of the cut: 'L', 'G' or 'E' */ +double violation; /* violation of the cut w.r.t. the current LP solution */ +} cut; + +typedef struct { +int cnum; /* overall number of cuts */ +cut **list; /* pointers to the cuts in the list */ +} cut_list; + +typedef struct { +int n_of_constr; /* number of constraints combined to get the cut */ +int *constr_list; /* list of the constraints combined */ +int code; /* identifier of the cut */ +int n_it_violated; /* number of consecutive iterations (starting from the + last and going backward) in which the cut was + violated by the LP solution */ +int it_found; /* iteration in which the cut was separated */ +double score; /* score of the cut, used to choose wich cut should be + added to the current LP (if any) */ +} pool_cut; + +typedef struct { +int cnum; /* overall number of cuts */ +pool_cut **list; /* pointers to the cuts in the list */ +int *ncod; /* number of cuts with a given code in the pool */ +} pool_cut_list; + +typedef struct { +int *ccoef; /* coefficients of the cut */ +int crhs; /* right hand side of the cut */ +int pool_index; /* index of the cut in the pool */ +double score; /* cut score (to be maximized) */ +} select_cut; + +typedef struct { +int n_it_zero; /* number of consecutive iterations (starting from the + last and going backward) in which each variable took + the value 0 in the LP solution */ +} log_var; +/** 012Cut Generator Class + + This class is to make Cgl01cut thread safe etc +*/ + +class Cgl012Cut { + +public: + + /**@name Generate Cuts */ + //@{ +int sep_012_cut( +/* + INPUT parameters: +*/ +int mr, /* number of rows in the ILP matrix */ +int mc, /* number of columns in the ILP matrix */ +int mnz, /* number of nonzero's in the ILP matrix */ +int *mtbeg, /* starting position of each row in arrays mtind and mtval */ +int *mtcnt, /* number of entries of each row in arrays mtind and mtval */ +int *mtind, /* column indices of the nonzero entries of the ILP matrix */ +int *mtval, /* values of the nonzero entries of the ILP matrix */ +int *vlb, /* lower bounds on the variables */ +int *vub, /* upper bounds on the variables */ +int *mrhs, /* right hand sides of the constraints */ +char *msense, /* senses of the constraints: 'L', 'G' or 'E' */ +const double *xstar, /* current optimal solution of the LP relaxation */ +bool aggressive, /* flag asking whether as many cuts as possible are + required on output (TRUE) or not (FALSE) */ +/* + OUTPUT parameters (the memory for the vectors is allocated INTERNALLY + by the procedure: if some memory is already allocated, it is FREED): +*/ +int *cnum, /* number of violated 0-1/2 cuts identified by the procedure */ +int *cnzcnt, /* overall number of nonzero's in the cuts */ +int **cbeg, /* starting position of each cut in arrays cind and cval */ +int **ccnt, /* number of entries of each cut in arrays cind and cval */ +int **cind, /* column indices of the nonzero entries of the cuts */ +int **cval, /* values of the nonzero entries of the cuts */ +int **crhs, /* right hand sides of the cuts */ +char **csense /* senses of the cuts: 'L', 'G' or 'E' */ +/* + NOTE that all the numerical input/output vectors are INTEGER (with + the exception of xstar), since the procedure is intended to work + with pure ILP's, and that the ILP matrix has to be given on input + in ROW format. +*/ + ); +void ilp_load( + int mr, /* number of rows in the ILP matrix */ + int mc, /* number of columns in the ILP matrix */ + int mnz, /* number of nonzero's in the ILP matrix */ + int *mtbeg, /* starting position of each row in arrays mtind and mtval */ + int *mtcnt, /* number of entries of each row in arrays mtind and mtval */ + int *mtind, /* column indices of the nonzero entries of the ILP matrix */ + int *mtval, /* values of the nonzero entries of the ILP matrix */ + int *vlb, /* lower bounds on the variables */ + int *vub, /* upper bounds on the variables */ + int *mrhs, /* right hand sides of the constraints */ + char *msense /* senses of the constraints: 'L', 'G' or 'E' */ + ); +void free_ilp(); +/* alloc_parity_ilp: allocate the memory for the parity ILP data structure */ + +void alloc_parity_ilp( + int mr, /* number of rows in the ILP matrix */ + int mc, /* number of columns in the ILP matrix */ + int mnz /* number of nonzero's in the ILP matrix */ + ); +void free_parity_ilp(); + void initialize_log_var(); +/* free_log_var */ + void free_log_var(); +private: +/* best_weakening: find the best upper/lower bound weakening of a set + of variables */ + +int best_weakening( + int n_to_weak, /* number of variables to weaken */ +int *vars_to_weak, /* indices of the variables to weaken */ +short int original_parity, /* original parity of the constraint to weaken */ +double original_slack, /* original slack of the constraint to weaken */ +double *best_even_slack, /* best possible slack of a weakened constraint + with even right-hand-side */ +double *best_odd_slack, /* best possible slack of a weakened constraint + with odd right-hand-side */ +info_weak **info_even_weak, /* weakening information about the best possible + even weakened constraint */ +info_weak **info_odd_weak, /* weakening information about the best possible + odd weakened constraint */ +short int only_odd, /* flag which tells whether only an odd weakening is of + interest (TRUE) or both weakenings are (FALSE) */ +short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); + +/* best_cut: find the coefficients, the rhs and the violation of the + best possible cut that can be obtained by weakening a given set of + coefficients to even and a rhs to odd, dividing by 2 and rounding */ + +short int best_cut( + int *ccoef, /* vector of the coefficients */ + int *crhs, /* pointer to rhs value */ + double *violation, /* violation of the cut */ + short int update, /* TRUE/FALSE: if TRUE, the new ccoef and crhs are + given on output */ + short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); +/* get_cut: extract a hopefully violated cut from an odd cycle of the + separation graph */ + +cut *get_cut( + cycle *s_cyc /* shortest odd cycles identified in the separation graph */ + ); + +/* update_log_var: update the log information for the problem variables */ + void update_log_var(); + +/* basic_separation: try to identify violated 0-1/2 cuts by using the + original procedure described in Caprara and Fischetti's MP paper */ + + cut_list *basic_separation(); + +/* score_by_moving: compute the score of the best cut obtainable from + the current local search solution by inserting/deleting a constraint */ + +double score_by_moving( + int i, /* constraint to be moved */ + short int itype, /* type of move - ADD or DEL */ + double thresh /* minimum value of an interesting score */ + ); +/* modify_current: update the current local search solution by inserting/ + deleting a constraint */ + +void modify_current( + int i, /* constraint to be moved */ + short int itype /* type of move - ADD or DEL */ + ); + +/* best neighbour: find the cut to be added/deleted from the current + solution among those allowed by the tabu rules */ + + short int best_neighbour(cut_list *out_cuts /* list of the violated cuts found */); + +/* add_tight_constraint: initialize the current cut by adding a tight + constraint to it */ + + void add_tight_constraint(); + +/* tabu_012: try to identify violated 0-1/2 cuts by a simple tabu search + procedure adapted from that used by Battiti and Protasi for finding + large cliques */ + + cut_list *tabu_012(); +/* initialize: initialize the data structures for local search */ + + void initialize(); +/* restart: perform a restart of the search - IMPORTANT: in the current + implementation vector last_moved is not cleared at restart */ + + void restart(short int failure /* flag forcing the restart if some trouble occurred */); + void print_constr(int i /* constraint to be printed */); + void print_parity_ilp(); + +/* get_parity_ilp: construct an internal data structure containing all the + information which can be useful for 0-1/2 cut separation */ + + void get_parity_ilp(); +/* initialize_sep_graph: allocate and initialize the data structure + to contain the information associated with a separation graph */ + + separation_graph *initialize_sep_graph(); + void print_cut(cut *v_cut); +/* get_ori_cut_coef: get the coefficients of a cut, before dividing by 2 and + rounding, starting from the list of the constraints combined to get + the cut */ + +short int get_ori_cut_coef( + int n_of_constr, /* number of constraints combined */ + int *constr_list, /* list of the constraints combined */ + int *ccoef, /* cut left hand side coefficients */ + int *crhs, /* cut right hand side */ + short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); +/* define_cut: construct a cut data structure from a vector of + coefficients and a right-hand-side */ + +cut *define_cut( + int *ccoef, /* coefficients of the cut */ + int crhs /* right hand side of the cut */ + ); + +/* cut_score: define the score of a (violated) cut */ + +double cut_score( + int *ccoef, /* cut left hand side coefficients */ + int crhs, /* cut right hand side */ + double viol, /* cut violation */ + short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); +/* get_current_cut: return a cut data type with the information about + the current cut of the search procedure */ + + cut *get_current_cut(); +/* print_cur_cut: display cur_cut on output */ + + void print_cur_cut(); + void print_cut_list(cut_list *cuts); + //@} +public: + /**@name Constructors and destructors */ + //@{ + /// Default constructor + Cgl012Cut (); + + /// Copy constructor + Cgl012Cut ( + const Cgl012Cut &); + + /// Assignment operator + Cgl012Cut & + operator=( + const Cgl012Cut& rhs); + + /// Destructor + virtual ~Cgl012Cut (); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + //@} + + + /**@name Private member data */ + //@{ + +ilp *inp_ilp; /* input ILP data structure */ +parity_ilp *p_ilp; /* parity ILP data structure */ +int iter; +double gap; +double maxgap; +int errorNo; +int sep_iter; /* number of the current separation iteration */ +log_var **vlog; /* information about the value attained + by the variables in the last iterations, + used to possibly set to 0 some coefficient + > 0 in a cut to be added */ +bool aggr; /* flag saying whether as many cuts as possible are required + from the separation procedure (TRUE) or not (FALSE) */ + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CglAllDifferent.hpp b/thirdparty/linux/include/coin/CglAllDifferent.hpp new file mode 100644 index 0000000..ed369d1 --- /dev/null +++ b/thirdparty/linux/include/coin/CglAllDifferent.hpp @@ -0,0 +1,115 @@ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglAllDifferent_H +#define CglAllDifferent_H + +#include <string> + +#include "CglCutGenerator.hpp" + +/** AllDifferent Cut Generator Class + This has a number of sets. All the members in each set are general integer + variables which have to be different from all others in the set. + + At present this only generates column cuts + + At present it is very primitive compared to proper CSP implementations + */ +class CglAllDifferent : public CglCutGenerator { + +public: + + + /**@name Generate Cuts */ + //@{ + /** This fixes (or reduces bounds) on sets of all different variables + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglAllDifferent (); + + /// Useful constructot + CglAllDifferent(int numberSets, const int * starts, const int * which); + + /// Copy constructor + CglAllDifferent ( + const CglAllDifferent &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglAllDifferent & + operator=( + const CglAllDifferent& rhs); + + /// Destructor + virtual + ~CglAllDifferent (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /** + Returns true if may generate Row cuts in tree (rather than root node). + Used so know if matrix will change in tree. Really + meant so column cut generators can still be active + without worrying code. + Default is true + */ + virtual bool mayGenerateRowCutsInTree() const + { return false;} + //@} + /**@name Sets and Gets */ + //@{ + /// Set log level + inline void setLogLevel(int value) + { logLevel_=value;} + /// Get log level + inline int getLogLevel() const + { return logLevel_;} + /// Set Maximum number of sets to look at at once + inline void setMaxLook(int value) + { maxLook_=value;} + /// Get Maximum number of sets to look at at once + inline int getMaxLook() const + { return maxLook_;} + //@} + +private: + + // Private member methods + /**@name */ + //@{ + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// Number of sets + int numberSets_; + /// Total number of variables in all different sets + int numberDifferent_; + /// Maximum number of sets to look at at once + int maxLook_; + /// Log level - 0 none, 1 - a bit, 2 - more details + int logLevel_; + /// Start of each set + int * start_; + /// Members (0,1,....) not as in original model + int * which_; + /// Original members + int * originalWhich_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CglClique.hpp b/thirdparty/linux/include/coin/CglClique.hpp new file mode 100644 index 0000000..5b47b40 --- /dev/null +++ b/thirdparty/linux/include/coin/CglClique.hpp @@ -0,0 +1,308 @@ +// $Id: CglClique.hpp 1119 2013-04-06 20:24:18Z stefan $ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _CglClique_h_ +#define _CglClique_h_ + +#include "CglCutGenerator.hpp" + +//class OsiCuts; +//class OsiSolverInterface; + +class CglClique : public CglCutGenerator { + + friend void CglCliqueUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); +public: + /// Copy constructor + CglClique(const CglClique& rhs); + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglClique& operator=(const CglClique& rhs); + +public: + + virtual void + generateCuts(const OsiSolverInterface& si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /**@name Constructors and destructors */ + //@{ + /** Default constructor. + If the setPacking argument is set to true then CglClique will assume that the + problem in the solverinterface passed to the generateCuts() method + describes a set packing problem, i.e., + - all variables are binary + - the matrix is a 0-1 matrix + - all constraints are '= 1' or '<= 1' + + Otherwise the user can use the considerRows() method to set the list of + clique rows, that is, + - all coeffs corresponding to binary variables at fractional level is 1 + - all other coeffs are non-negative + - the constraint is '= 1' or '<= 1'. + + If the user does not set the list of clique rows then CglClique will + start the generateCuts() methods by scanning the matrix for them. + Also justOriginalRows can be set to true to limit clique creation + */ + CglClique(bool setPacking = false, bool justOriginalRows = false); + /// Destructor + virtual ~CglClique() {} + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + void considerRows(const int numRows, const int* rowInd); + +public: + /** possible choices for selecting the next node in the star clique search + */ + enum scl_next_node_method { + SCL_MIN_DEGREE, + SCL_MAX_DEGREE, + SCL_MAX_XJ_MAX_DEG + }; + + void setStarCliqueNextNodeMethod(scl_next_node_method method) { + scl_next_node_rule = method; + } + + void setStarCliqueCandidateLengthThreshold(int maxlen) { + scl_candidate_length_threshold = maxlen; + } + void setRowCliqueCandidateLengthThreshold(int maxlen) { + rcl_candidate_length_threshold = maxlen; + } + + void setStarCliqueReport(bool yesno = true) { scl_report_result = yesno; } + void setRowCliqueReport(bool yesno = true) { rcl_report_result = yesno; } + + void setDoStarClique(bool yesno = true) { do_star_clique = yesno; } + void setDoRowClique(bool yesno = true) { do_row_clique = yesno; } + + void setMinViolation(double minviol) { petol = minviol; } + double getMinViolation() const { return petol; } + +private: + + struct frac_graph ; + friend struct frac_graph ; + + /** A node of the fractional graph. There is a node for every variable at + fractional level. */ + struct fnode { + /** pointer into all_nbr */ + int *nbrs; + /** 1-x_i-x_j, needed for odd holes, in the same order as the adj list, + pointer into all_edgecost */ + double *edgecosts; + /** degree of the node */ + int degree; + /** the fractional value of the variable corresponding to this node */ + double val; + }; + + /** A graph corresponding to a fractional solution of an LP. Two nodes are + adjacent iff their columns are non-orthogonal. */ + struct frac_graph { + /** # of nodes = # of fractional values in the LP solution */ + int nodenum; + /** # of edges in the graph */ + int edgenum; + /** density= edgenum/(nodenum choose 2) */ + double density; + int min_deg_node; + int min_degree; + int max_deg_node; + int max_degree; + /** The array of the nodes in the graph */ + fnode *nodes; + /** The array of all the neighbors. First the indices of the nodes + adjacent to node 0 are listed, then those adjacent to node 1, etc. */ + int *all_nbr; + /** The array of the costs of the edges going to the neighbors */ + double *all_edgecost; + + frac_graph() : + nodenum(0), edgenum(0), density(0), + min_deg_node(0), min_degree(0), max_deg_node(0), max_degree(0), + nodes(0), all_nbr(0), all_edgecost(0) {} + }; + +protected: + /** An indicator showing whether the whole matrix in the solverinterface is + a set packing problem or not */ + bool setPacking_; + /// True if just look at original rows + bool justOriginalRows_; + /** pieces of the set packing part of the solverinterface */ + int sp_numrows; + int* sp_orig_row_ind; + int sp_numcols; + int* sp_orig_col_ind; + double* sp_colsol; + int* sp_col_start; + int* sp_col_ind; + int* sp_row_start; + int* sp_row_ind; + + /** the intersection graph corresponding to the set packing problem */ + frac_graph fgraph; + /** the node-node incidence matrix of the intersection graph. */ + bool* node_node; + + /** The primal tolerance in the solverinterface. */ + double petol; + + /** data for the star clique algorithm */ + + /** Parameters */ + /**@{*/ + /** whether to do the row clique algorithm or not. */ + bool do_row_clique; + /** whether to do the star clique algorithm or not. */ + bool do_star_clique; + + /** How the next node to be added to the star clique should be selected */ + scl_next_node_method scl_next_node_rule; + /** In the star clique method the maximal length of the candidate list + (those nodes that are in a star, i.e., connected to the center of the + star) to allow complete enumeration of maximal cliques. Otherwise a + greedy algorithm is used. */ + int scl_candidate_length_threshold; + /** whether to give a detailed statistics on the star clique method */ + bool scl_report_result; + + /** In the row clique method the maximal length of the candidate list + (those nodes that can extend the row clique, i.e., connected to all + nodes in the row clique) to allow complete enumeration of maximal + cliques. Otherwise a greedy algorithm is used. */ + int rcl_candidate_length_threshold; + /** whether to give a detailed statistics on the row clique method */ + bool rcl_report_result; + /**@}*/ + + /** variables/arrays that are used across many methods */ + /**@{*/ + /** List of indices that must be in the to be created clique. This is just + a pointer, it is never new'd and therefore does not need to be + delete[]'d either. */ + const int* cl_perm_indices; + /** The length of cl_perm_indices */ + int cl_perm_length; + + /** List of indices that should be considered for extending the ones listed + in cl_perm_indices. */ + int* cl_indices; + /** The length of cl_indices */ + int cl_length; + + /** An array of nodes discarded from the candidate list. These are + rechecked when a maximal clique is found just to make sure that the + clique is really maximal. */ + int* cl_del_indices; + /** The length of cl_del_indices */ + int cl_del_length; + + /**@}*/ + +private: + /** Scan through the variables and select those that are binary and are at + a fractional level. */ + void selectFractionalBinaries(const OsiSolverInterface& si); + /** Scan through the variables and select those that are at a fractional + level. We already know that everything is binary. */ + void selectFractionals(const OsiSolverInterface& si); + /** */ + void selectRowCliques(const OsiSolverInterface& si,int numOriginalRows); + /** */ + void createSetPackingSubMatrix(const OsiSolverInterface& si); + /** */ + void createFractionalGraph(); + /** */ + int createNodeNode(); + /** */ + void deleteSetPackingSubMatrix(); + /** */ + void deleteFractionalGraph(); + /** */ + void find_scl(OsiCuts& cs); + /** */ + void find_rcl(OsiCuts& cs); + /** */ + int scl_choose_next_node(const int current_nodenum, + const int *current_indices, + const int *current_degrees, + const double *current_values); + /** */ + void scl_delete_node(const int del_ind, int& current_nodenum, + int *current_indices, int *current_degrees, + double *current_values); + /** */ + int enumerate_maximal_cliques(int& pos, bool* scl_label, OsiCuts& cs); + /** */ + int greedy_maximal_clique(OsiCuts& cs); + /** */ + void recordClique(const int len, int* indices, OsiCuts& cs); +}; +//############################################################################# +/** A function that tests the methods in the CglClique class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglCliqueUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +/// This works on a fake solver i.e. invented rows +class CglProbing; +class CglFakeClique : public CglClique { + +public: + /// Copy constructor + CglFakeClique(const CglFakeClique& rhs); + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglFakeClique& operator=(const CglFakeClique& rhs); + + virtual void + generateCuts(const OsiSolverInterface& si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /**@name Constructors and destructors */ + //@{ + /** Default constructor. + If the setPacking argument is set to true then CglFakeClique will assume that the + problem in the solverinterface passed to the generateCuts() method + describes a set packing problem, i.e., + - all variables are binary + - the matrix is a 0-1 matrix + - all constraints are '= 1' or '<= 1' + + Otherwise the user can use the considerRows() method to set the list of + clique rows, that is, + - all coeffs corresponding to binary variables at fractional level is 1 + - all other coeffs are non-negative + - the constraint is '= 1' or '<= 1'. + + If the user does not set the list of clique rows then CglFakeClique will + start the generateCuts() methods by scanning the matrix for them. + */ + CglFakeClique(OsiSolverInterface * solver=NULL,bool setPacking = false); + /// Destructor + virtual ~CglFakeClique(); + /// Assign solver (generator takes over ownership) + void assignSolver(OsiSolverInterface * fakeSolver); +protected: + /// fake solver to use + OsiSolverInterface * fakeSolver_; + /// Probing object + CglProbing * probing_; +}; + +#endif diff --git a/thirdparty/linux/include/coin/CglConfig.h b/thirdparty/linux/include/coin/CglConfig.h new file mode 100644 index 0000000..bca5553 --- /dev/null +++ b/thirdparty/linux/include/coin/CglConfig.h @@ -0,0 +1,19 @@ +/* src/config_cgl.h. Generated by configure. */ +/* src/config_cgl.h.in. */ + +#ifndef __CONFIG_CGL_H__ +#define __CONFIG_CGL_H__ + +/* Version number of project */ +#define CGL_VERSION "0.59.4" + +/* Major Version number of project */ +#define CGL_VERSION_MAJOR 0 + +/* Minor Version number of project */ +#define CGL_VERSION_MINOR 59 + +/* Release Version number of project */ +#define CGL_VERSION_RELEASE 4 + +#endif diff --git a/thirdparty/linux/include/coin/CglCutGenerator.hpp b/thirdparty/linux/include/coin/CglCutGenerator.hpp new file mode 100644 index 0000000..7629140 --- /dev/null +++ b/thirdparty/linux/include/coin/CglCutGenerator.hpp @@ -0,0 +1,121 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglCutGenerator_H +#define CglCutGenerator_H + +#include "OsiCuts.hpp" +#include "OsiSolverInterface.hpp" +#include "CglTreeInfo.hpp" + +//------------------------------------------------------------------- +// +// Abstract base class for generating cuts. +// +//------------------------------------------------------------------- +/// +/** Cut Generator Base Class + +This is an abstract base class for generating cuts. A specific cut +generator will inherit from this class. +*/ +class CglCutGenerator { + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate cuts for the model data contained in si. + The generated cuts are inserted into and returned in the + collection of cuts cs. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo())=0; + //@} + + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglCutGenerator (); + + /// Copy constructor + CglCutGenerator ( const CglCutGenerator &); + + /// Clone + virtual CglCutGenerator * clone() const = 0; + + /// Assignment operator + CglCutGenerator & operator=(const CglCutGenerator& rhs); + + /// Destructor + virtual ~CglCutGenerator (); + + /** Create C++ lines to set the generator in the current state. + The output must be parsed by the calling code, as each line + starts with a key indicating the following:<BR> + 0: must be kept (for #includes etc)<BR> + 3: Set to changed (not default) values<BR> + 4: Set to default values (redundant)<BR> + + Keys 1, 2, 5, 6, 7, 8 are defined, but not applicable to + cut generators. + */ + virtual std::string generateCpp( FILE * ) {return "";} + + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface * ) {} + //@} + + /**@name Gets and Sets */ + //@{ + /** + Get Aggressiveness - 0 = neutral, 100 is normal root node. + Really just a hint to cut generator + */ + inline int getAggressiveness() const + { return aggressive_;} + + /** + Set Aggressiveness - 0 = neutral, 100 is normal root node. + Really just a hint to cut generator + */ + inline void setAggressiveness(int value) + { aggressive_=value;} + /// Set whether can do global cuts + inline void setGlobalCuts(bool trueOrFalse) + { canDoGlobalCuts_ = trueOrFalse;} + /// Say whether can do global cuts + inline bool canDoGlobalCuts() const + {return canDoGlobalCuts_;} + /** + Returns true if may generate Row cuts in tree (rather than root node). + Used so know if matrix will change in tree. Really + meant so column cut generators can still be active + without worrying code. + Default is true + */ + virtual bool mayGenerateRowCutsInTree() const; + /// Return true if needs optimal basis to do cuts + virtual bool needsOptimalBasis() const; + /// Return maximum length of cut in tree + virtual int maximumLengthOfCutInTree() const + { return COIN_INT_MAX;} + //@} + + // test this class + //static void unitTest(); + +// private: + + /** + Aggressiveness - 0 = neutral, 100 is normal root node. + Really just a hint to cut generator + */ + int aggressive_; + /// True if can do global cuts i.e. no general integers + bool canDoGlobalCuts_; +}; + +#endif diff --git a/thirdparty/linux/include/coin/CglDuplicateRow.hpp b/thirdparty/linux/include/coin/CglDuplicateRow.hpp new file mode 100644 index 0000000..b40f969 --- /dev/null +++ b/thirdparty/linux/include/coin/CglDuplicateRow.hpp @@ -0,0 +1,189 @@ +// $Id: CglDuplicateRow.hpp 1119 2013-04-06 20:24:18Z stefan $ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglDuplicateRow_H +#define CglDuplicateRow_H + +#include <string> + +#include "CglCutGenerator.hpp" +class CglStored; + +/** DuplicateRow Cut Generator Class */ +class CglDuplicateRow : public CglCutGenerator { + +public: + + + /**@name Generate Cuts */ + //@{ + /** Fix variables and find duplicate/dominated rows for the model of the + solver interface, si. + + This is a very simple minded idea but I (JJF) am using it in a project so thought + I might as well add it. It should really be called before first solve and I may + modify CBC to allow for that. + + This is designed for problems with few rows and many integer variables where the rhs + are <= or == and all coefficients and rhs are small integers. + + If effective rhs is K then we can fix all variables with coefficients > K to their lower bounds + (effective rhs just means original with variables with nonzero lower bounds subtracted out). + + If one row is a subset of another and the effective rhs are same we can fix some variables + and then the two rows are identical. + + The generator marks identical rows so can be taken out in solve + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); +private: + /// Does work for modes 1,2 + void generateCuts12( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /// Does work for mode 4 + void generateCuts4( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /// Does work for mode 8 + void generateCuts8( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); +public: + /** Fix variables and find duplicate/dominated rows for the model of the + solver interface, si. + + This is a very simple minded idea but I (JJF) am using it in a project so thought + I might as well add it. It should really be called before first solve and I may + modify CBC to allow for that. + + This is designed for problems with few rows and many integer variables where the rhs + are <= or == and all coefficients and rhs are small integers. + + If effective rhs is K then we can fix all variables with coefficients > K to their lower bounds + (effective rhs just means original with variables with nonzero lower bounds subtracted out). + + If one row is a subset of another and the effective rhs are same we can fix some variables + and then the two rows are identical. + + This version does deletions and fixings and may return stored cuts for + dominated columns + */ + CglStored * outDuplicates( OsiSolverInterface * solver); + + //@} + + /**@name Get information on size of problem */ + //@{ + /// Get duplicate row list, -1 means still in, -2 means out (all fixed), k>= means same as row k + inline const int * duplicate() const + { return duplicate_;} + /// Size of dynamic program + inline int sizeDynamic() const + { return sizeDynamic_;} + /// Number of rows in original problem + inline int numberOriginalRows() const + { return matrix_.getNumRows();} + //@} + + /**@name Get information on size of problem */ + //@{ + /// logLevel + inline int logLevel() const + { return logLevel_;} + inline void setLogLevel(int value) + { logLevel_ = value;} + //@} + + + /**@name We only check for duplicates amongst rows with effective rhs <= this */ + //@{ + /// Get + inline int maximumRhs() const + { return maximumRhs_;} + /// Set + inline void setMaximumRhs(int value) + { maximumRhs_=value;} + //@} + + /**@name We only check for dominated amongst groups of columns whose size <= this */ + //@{ + /// Get + inline int maximumDominated() const + { return maximumDominated_;} + /// Set + inline void setMaximumDominated(int value) + { maximumDominated_=value;} + //@} + /**@name gets and sets */ + //@{ + /// Get mode + inline int mode() const + { return mode_;} + /// Set mode + inline void setMode(int value) + { mode_=value;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglDuplicateRow (); + + /// Useful constructor + CglDuplicateRow (OsiSolverInterface * solver); + + /// Copy constructor + CglDuplicateRow ( + const CglDuplicateRow & rhs); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglDuplicateRow & + operator=( + const CglDuplicateRow& rhs); + + /// Destructor + virtual + ~CglDuplicateRow (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +protected: + + + // Protected member data + + /**@name Protected member data */ + //@{ + /// Matrix + CoinPackedMatrix matrix_; + /// Matrix by row + CoinPackedMatrix matrixByRow_; + /// Possible rhs (if 0 then not possible) + int * rhs_; + /// Marks duplicate rows + int * duplicate_; + /// To allow for <= rows + int * lower_; + /// Stored cuts if we found dominance cuts + CglStored * storedCuts_; + /// Check dominated columns if less than this number of candidates + int maximumDominated_; + /// Check duplicates if effective rhs <= this + int maximumRhs_; + /// Size of dynamic program + int sizeDynamic_; + /// 1 do rows, 2 do columns, 3 do both + int mode_; + /// Controls print out + int logLevel_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CglFlowCover.hpp b/thirdparty/linux/include/coin/CglFlowCover.hpp new file mode 100644 index 0000000..eea070f --- /dev/null +++ b/thirdparty/linux/include/coin/CglFlowCover.hpp @@ -0,0 +1,371 @@ +// $Id: CglFlowCover.hpp 1119 2013-04-06 20:24:18Z stefan $ +//----------------------------------------------------------------------------- +// name: Cgl Lifted Simple Generalized Flow Cover Cut Generator +// author: Yan Xu email: yan.xu@sas.com +// Jeff Linderoth email: jtl3@lehigh.edu +// Martin Savelsberg email: martin.savelsbergh@isye.gatech.edu +// date: 05/01/2003 +// comments: please scan this file for '???' and read the comments +//----------------------------------------------------------------------------- +// Copyright (C) 2003, Yan Xu, Jeff Linderoth, Martin Savelsberg and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglFlowCover_H +#define CglFlowCover_H + +#include <iostream> + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" + +//============================================================================= + +//============================================================================= + +/** This enumerative constant describes the various col types.*/ +enum CglFlowColType { + /** The column(variable) is a negative binary variable.*/ + CGLFLOW_COL_BINNEG = -2, + /** The column is a negative continous variable.*/ + CGLFLOW_COL_CONTNEG, + /** The column is a positive continous variable.*/ + CGLFLOW_COL_CONTPOS = 1, + /** The column is a positive binary variable.*/ + CGLFLOW_COL_BINPOS +}; + +enum CglFlowColStatus{ +}; + +/** This enumerative constant describes the various stati of vars in + a cut or not.*/ +enum CglFlowColCut{ + /** The column is NOT in cover.*/ + CGLFLOW_COL_OUTCUT = 0, + /** The column is in cover now. */ + CGLFLOW_COL_INCUT, + /** The column is decided to be in cover. */ + CGLFLOW_COL_INCUTDONE, + /** The column is in L-. */ + CGLFLOW_COL_INLMIN, + /** The column is decided to be in L-. */ + CGLFLOW_COL_INLMINDONE, + /** The column is in L--.*/ + CGLFLOW_COL_INLMINMIN, + /** This enumerative constant describes the various stati of vars in + determining the cover.*/ + /** The column is a prime candidate. */ + CGLFLOW_COL_PRIME, + /** The column is a secondary candidate. */ + CGLFLOW_COL_SECONDARY +}; + +/** This enumerative constant describes the various row types.*/ +enum CglFlowRowType { + /** The row type of this row is NOT defined yet.*/ + CGLFLOW_ROW_UNDEFINED, + /** After the row is flipped to 'L', the row has exactly two variables: + one is negative binary and the other is continous, and the RHS + is zero.*/ + CGLFLOW_ROW_VARUB, + /** After the row is flipped to 'L', the row has exactlytwo variables: + one is positive binary and the other is continous, and the RHS + is zero.*/ + CGLFLOW_ROW_VARLB, + /** The row sense is 'E', the row has exactly two variables: + one is binary and the other is a continous, and the RHS is zero.*/ + CGLFLOW_ROW_VAREQ, + /** Rows can not be classfied into other types and the row sense + is NOT 'E'.*/ + CGLFLOW_ROW_MIXUB, + /** Rows can not be classfied into other types and the row sense is 'E'.*/ + CGLFLOW_ROW_MIXEQ, + /** All variables are NOT binary and the row sense is NOT 'E'. */ + CGLFLOW_ROW_NOBINUB, + /** All variables are NOT binary and the row sense is 'E'. */ + CGLFLOW_ROW_NOBINEQ, + /** The row has one binary and 2 or more other types of variables and + the row sense is NOT 'E'. */ + CGLFLOW_ROW_SUMVARUB, + /** The row has one binary and 2 or more other types of variables and + the row sense is 'E'. */ + CGLFLOW_ROW_SUMVAREQ, + /** All variables are binary. */ + CGLFLOW_ROW_UNINTERSTED +}; + +//============================================================================= + +/** Variable upper bound class. */ +class CglFlowVUB +{ +protected: + int varInd_; /** The index of the associated 0-1 variable.*/ + double upper_; /** The Value of the associated upper bound.*/ + +public: + CglFlowVUB() : varInd_(-1), upper_(-1) {} + + CglFlowVUB(const CglFlowVUB& source) { + varInd_= source.varInd_; + upper_ = source.upper_; + } + + CglFlowVUB& operator=(const CglFlowVUB& rhs) { + if (this == &rhs) + return *this; + varInd_= rhs.varInd_; + upper_ = rhs.upper_; + return *this; + } + + /**@name Query and set functions for associated 0-1 variable index + and value. + */ + //@{ + inline int getVar() const { return varInd_; } + inline double getVal() const { return upper_; } + inline void setVar(const int v) { varInd_ = v; } + inline void setVal(const double v) { upper_ = v; } + //@} +}; + +//============================================================================= + +/** Variable lower bound class, which is the same as vub. */ +typedef CglFlowVUB CglFlowVLB; + +/** Overloaded operator<< for printing VUB and VLB.*/ +std::ostream& operator<<( std::ostream& os, const CglFlowVUB &v ); + +//============================================================================= + +/** + * Lifed Simple Generalized Flow Cover Cut Generator Class. + */ +class CglFlowCover : public CglCutGenerator { + friend void CglFlowCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + /** + * Do the following tasks: + * <ul> + * <li> classify row types + * <li> indentify vubs and vlbs + * </ul> + * This function is called by + * <CODE>generateCuts(const OsiSolverInterface & si, OsiCuts & cs)</CODE>. + */ + void flowPreprocess(const OsiSolverInterface& si); + + /**@name Generate Cuts */ + //@{ + /** Generate Lifed Simple Generalized flow cover cuts for the model data + contained in si. The generated cuts are inserted into and returned + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Functions to query and set maximum number of cuts can be + generated. */ + //@{ + inline int getMaxNumCuts() const { return maxNumCuts_; } + inline void setMaxNumCuts(int mc) { maxNumCuts_ = mc; } + //@} + + /**@name Functions to query and set the number of cuts have been + generated. */ + //@{ + static int getNumFlowCuts() { return numFlowCuts_; } + static void setNumFlowCuts(int fc) { numFlowCuts_ = fc; } + static void incNumFlowCuts(int fc = 1) { numFlowCuts_ += fc; } + //@} + + //------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglFlowCover (); + + /// Copy constructor + CglFlowCover ( + const CglFlowCover &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglFlowCover & + operator=( + const CglFlowCover& rhs); + + /// Destructor + virtual + ~CglFlowCover (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + //------------------------------------------------------------------------- + // Private member functions + + /** Based a given row, a LP solution and other model data, this function + tries to generate a violated lifted simple generalized flow cover. + */ + bool generateOneFlowCut( const OsiSolverInterface & si, + const int rowLen, + int* ind, + double* coef, + char sense, + double rhs, + OsiRowCut& flowCut, + double& violation ); + + + /** Transform a row from ">=" to "<=", and vice versa. */ + void flipRow(int rowLen, double* coef, double& rhs) const; + + /** Transform a row from ">=" to "<=", and vice versa. Have 'sense'. */ + void flipRow(int rowLen, double* coef, char& sen, double& rhs) const; + + /** Determine the type of a given row. */ + CglFlowRowType determineOneRowType(const OsiSolverInterface& si, + int rowLen, int* ind, + double* coef, char sen, + double rhs) const; + /** Lift functions */ + void liftMinus(double &movement, /* Output */ + int t, + int r, + double z, + double dPrimePrime, + double lambda, + double ml, + double *M, + double *rho) const; + + bool liftPlus(double &alpha, + double &beta, + int r, + double m_j, + double lambda, + double y_j, + double x_j, + double dPrimePrime, + double *M) const; + + + //------------------------------------------------------------------------- + //**@name Query and set the row type of a givne row. */ + //@{ + inline const CglFlowRowType* getRowTypes() const + { return rowTypes_; } + inline CglFlowRowType getRowType(const int i) const + { return rowTypes_[i]; } + /** Set rowtypes, take over the ownership. */ + inline void setRowTypes(CglFlowRowType* rt) + { rowTypes_ = rt; rt = 0; } + inline void setRowTypes(const CglFlowRowType rt, const int i) { + if (rowTypes_ != 0) + rowTypes_[i] = rt; + else { + std::cout << "ERROR: Should allocate memory for rowType_ before " + << "using it " << std::endl; + throw CoinError("Forgot to allocate memory for rowType_", + "setRowType", "CglFlowCover"); + } + } + //@} + + //------------------------------------------------------------------------- + //**@name Query and set vubs. */ + //@{ + inline const CglFlowVUB* getVubs() const { return vubs_; } + inline const CglFlowVUB& getVubs(int i) const { return vubs_[i]; } + /** Set CglFlowVUBs,take over the ownership. */ + inline void setVubs(CglFlowVUB* vubs) { vubs_ = vubs; vubs = 0; } + inline void setVubs(const CglFlowVUB& vub, int i) { + if (vubs_ != 0) + vubs_[i] = vub; + else { + std::cout << "ERROR: Should allocate memory for vubs_ before " + << "using it " << std::endl; + throw CoinError("Forgot to allocate memory for vubs_", "setVubs", + "CglFlowCover"); + } + } + inline void printVubs(std::ostream& os) const { + for (int i = 0; i < numCols_; ++i) { + os << "ix: " << i << ", " << vubs_[i]; + } + } + //@} + + //------------------------------------------------------------------------- + //**@name Query and set vlbs. */ + //@{ + inline const CglFlowVLB* getVlbs() const { return vlbs_; } + inline const CglFlowVLB& getVlbs(int i) const { return vlbs_[i]; } + /** Set CglFlowVLBs,take over the ownership. */ + inline void setVlbs(CglFlowVLB* vlbs) { vlbs_ = vlbs; vlbs = 0; } + inline void setVlbs(const CglFlowVLB& vlb, int i) { + if (vlbs_ != 0) + vlbs_[i] = vlb; + else { + std::cout << "ERROR: Should allocate memory for vlbs_ before " + << "using it " << std::endl; + throw CoinError("Forgot to allocate memory for vlbs_", "setVlbs", + "CglFlowCover"); + } + } + //@} + +private: + //------------------------------------------------------------------------ + // Private member data + + /** The maximum number of flow cuts to be generated. Default is 1000. */ + int maxNumCuts_; + /** Tolerance used for numerical purpose. */ + double EPSILON_; + /** The variable upper bound of a flow is not indentified yet.*/ + int UNDEFINED_; + /** Very large number. */ + double INFTY_; + /** If violation of a cut is greater that this number, the cut is useful.*/ + double TOLERANCE_; + /** First time preprocessing */ + bool firstProcess_; + /** The number rows of the problem.*/ + int numRows_; + /** The number columns of the problem.*/ + int numCols_; + /** The number flow cuts found.*/ + static int numFlowCuts_; + /** Indicate whether initial flow preprecessing has been done. */ + bool doneInitPre_; + /** The array of CglFlowVUBs. */ + CglFlowVUB* vubs_; + /** The array of CglFlowVLBs. */ + CglFlowVLB* vlbs_; + /** CglFlowRowType of the rows in model. */ + CglFlowRowType* rowTypes_; +}; + +//############################################################################# +/** A function that tests the methods in the CglFlowCover class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglFlowCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/thirdparty/linux/include/coin/CglGMI.hpp b/thirdparty/linux/include/coin/CglGMI.hpp new file mode 100644 index 0000000..240f6ad --- /dev/null +++ b/thirdparty/linux/include/coin/CglGMI.hpp @@ -0,0 +1,364 @@ +// Last edit: 02/05/2013 +// +// Name: CglGMI.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design, Singapore +// email: nannicini@sutd.edu.sg +// Date: 11/17/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2009, Giacomo Nannicini. All Rights Reserved. + +#ifndef CglGMI_H +#define CglGMI_H + +#include "CglCutGenerator.hpp" +#include "CglGMIParam.hpp" +#include "CoinWarmStartBasis.hpp" +#include "CoinFactorization.hpp" + +/* Enable tracking of rejection of cutting planes. If this is disabled, + the cut generator is slightly faster. If defined, it enables proper use + of setTrackRejection and related functions. */ +//#define TRACK_REJECT + +/* Debug output */ +//#define GMI_TRACE + +/* Debug output: print optimal tableau */ +//#define GMI_TRACETAB + +/* Print reason for cut rejection, whenever a cut is discarded */ +//#define GMI_TRACE_CLEAN + +/** Gomory cut generator with several cleaning procedures, used to test + * the numerical safety of the resulting cuts + */ + +class CglGMI : public CglCutGenerator { + + friend void CglGMIUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +public: + + /** Public enum: all possible reasons for cut rejection */ + enum RejectionType{ + failureFractionality, + failureDynamism, + failureViolation, + failureSupport, + failureScale + }; + + /**@name generateCuts */ + //@{ + /** Generate Gomory Mixed-Integer cuts for the model of the solver + interface si. + + Insert the generated cuts into OsiCuts cs. + + Warning: This generator currently works only with the Lp solvers Clp or + Cplex9.0 or higher. It requires access to the optimal tableau and + optimal basis inverse and makes assumptions on the way slack variables + are added by the solver. The Osi implementations for Clp and Cplex + verify these assumptions. + + When calling the generator, the solver interface si must contain + an optimized problem and information related to the optimal + basis must be available through the OsiSolverInterface methods + (si->optimalBasisIsAvailable() must return 'true'). It is also + essential that the integrality of structural variable i can be + obtained using si->isInteger(i). + + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const { return true; } + //@} + + /**@name Common Methods */ + //@{ + // Function for checking equality with user tolerance + inline bool areEqual(double x, double y, + double epsAbs = 1e-12, + double epsRel = 1e-12) { + return (fabs((x) - (y)) <= + std::max(epsAbs, epsRel * std::max(fabs(x), fabs(y)))); + } + + // Function for checking is a number is zero + inline bool isZero(double x, double epsZero = 1e-20) { + return (fabs(x) <= epsZero); + } + + + // Function for checking if a number is integer + inline bool isIntegerValue(double x, + double intEpsAbs = 1e-9, + double intEpsRel = 1e-15) { + return (fabs((x) - floor((x)+0.5)) <= + std::max(intEpsAbs, intEpsRel * fabs(x))); + } + + + //@} + + + /**@name Public Methods */ + //@{ + + // Set the parameters to the values of the given CglGMIParam object. + void setParam(const CglGMIParam &source); + // Return the CglGMIParam object of the generator. + inline CglGMIParam getParam() const {return param;} + inline CglGMIParam & getParam() {return param;} + + // Compute entries of is_integer. + void computeIsInteger(); + + /// Print the current simplex tableau + void printOptTab(OsiSolverInterface *solver) const; + + /// Set/get tracking of the rejection of cutting planes. + /// Note that all rejection related functions will not do anything + /// unless the generator is compiled with the define GMI_TRACK_REJECTION + void setTrackRejection(bool value); + bool getTrackRejection(); + + /// Get number of cuts rejected for given reason; see above + int getNumberRejectedCuts(RejectionType reason); + + /// Reset counters for cut rejection tracking; see above + void resetRejectionCounters(); + + /// Get total number of generated cuts since last resetRejectionCounters() + int getNumberGeneratedCuts(); + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglGMI(); + + /// Constructor with specified parameters + CglGMI(const CglGMIParam ¶m); + + /// Copy constructor + CglGMI(const CglGMI &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglGMI & operator=(const CglGMI& rhs); + + /// Destructor + virtual ~CglGMI(); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + //@} + +private: + + // Private member methods + +/**@name Private member methods */ + + //@{ + + // Method generating the cuts after all CglGMI members are properly set. + void generateCuts(OsiCuts & cs); + + /// Compute the fractional part of value, allowing for small error. + inline double aboveInteger(double value) const; + + /// Compute the fractionalities involved in the cut, and the cut rhs. + /// Returns true if cut is accepted, false if discarded + inline bool computeCutFractionality(double varRhs, double& cutRhs); + + /// Compute the cut coefficient on a given variable + inline double computeCutCoefficient(double rowElem, int index); + + /// Use multiples of the initial inequalities to cancel out the coefficient + /// on a slack variables. + inline void eliminateSlack(double cutElem, int cutIndex, double* cut, + double& cutRhs, const double *elements, + const int *rowStart, const int *indices, + const int *rowLength, const double *rhs); + + /// Change the sign of the coefficients of the non basic + /// variables at their upper bound. + inline void flip(double& rowElem, int rowIndex); + + /// Change the sign of the coefficients of the non basic + /// variables at their upper bound and do the translations restoring + /// the original bounds. Modify the right hand side + /// accordingly. Two functions: one for original variables, one for slacks. + inline void unflipOrig(double& rowElem, int rowIndex, double& rowRhs); + inline void unflipSlack(double& rowElem, int rowIndex, double& rowRhs, + const double* slack_val); + + /// Pack a row of ncol elements + inline void packRow(double* row, double* rowElem, int* rowIndex, + int& rowNz); + + /// Clean the cutting plane; the cleaning procedure does several things + /// like removing small coefficients, scaling, and checks several + /// acceptance criteria. If this returns false, the cut should be discarded. + /// There are several cleaning procedures available, that can be selected + /// via the parameter param.setCLEANING_PROCEDURE(int value) + bool cleanCut(double* cutElem, int* cutIndex, int& cutNz, + double& cutRhs, const double* xbar); + + /// Cut cleaning procedures: return true if successfull, false if + /// cut should be discarded by the caller of if problems encountered + + /// Check the violation + bool checkViolation(const double* cutElem, const int* cutIndex, + int cutNz, double cutrhs, const double* xbar); + + /// Check the dynamism + bool checkDynamism(const double* cutElem, const int* cutIndex, + int cutNz); + + /// Check the support + bool checkSupport(int cutNz); + + /// Remove small coefficients and adjust the rhs accordingly + bool removeSmallCoefficients(double* cutElem, int* cutIndex, + int& cutNz, double& cutRhs); + + /// Adjust the rhs by relaxing by a small amount (relative or absolute) + void relaxRhs(double& rhs); + + /// Scale the cutting plane in different ways; + /// scaling_type possible values: + /// 0 : scale to obtain integral cut + /// 1 : scale based on norm, to obtain cut norm equal to ncol + /// 2 : scale to obtain largest coefficient equal to 1 + bool scaleCut(double* cutElem, int* cutIndex, int cutNz, + double& cutRhs, int scalingType); + + /// Scale the cutting plane in order to generate integral coefficients + bool scaleCutIntegral(double* cutElem, int* cutIndex, int cutNz, + double& cutRhs); + + /// Compute the nearest rational number; used by scale_row_integral + bool nearestRational(double val, double maxdelta, long maxdnom, + long& numerator, long& denominator); + + /// Compute the greatest common divisor + long computeGcd(long a, long b); + + /// print a vector of integers + void printvecINT(const char *vecstr, const int *x, int n) const; + /// print a vector of doubles: dense form + void printvecDBL(const char *vecstr, const double *x, int n) const; + /// print a vector of doubles: sparse form + void printvecDBL(const char *vecstr, const double *elem, const int * index, + int nz) const; + + /// Recompute the simplex tableau for want of a better accuracy. + /// Requires an empty CoinFactorization object to do the computations, + /// and two empty (already allocated) arrays which will contain + /// the basis indices on exit. Returns 0 if successfull. + int factorize(CoinFactorization & factorization, + int* colBasisIndex, int* rowBasisIndex); + + + //@} + + + // Private member data + +/**@name Private member data */ + + //@{ + + /// Object with CglGMIParam members. + CglGMIParam param; + + /// Number of rows ( = number of slack variables) in the current LP. + int nrow; + + /// Number of structural variables in the current LP. + int ncol; + + /// Lower bounds for structural variables + const double *colLower; + + /// Upper bounds for structural variables + const double *colUpper; + + /// Lower bounds for constraints + const double *rowLower; + + /// Upper bounds for constraints + const double *rowUpper; + + /// Righ hand side for constraints (upper bound for ranged constraints). + const double *rowRhs; + + /// Characteristic vectors of structural integer variables or continuous + /// variables currently fixed to integer values. + bool *isInteger; + + /// Current basis status: columns + int *cstat; + + /// Current basis status: rows + int *rstat; + + /// Pointer on solver. Reset by each call to generateCuts(). + OsiSolverInterface *solver; + + /// Pointer on point to separate. Reset by each call to generateCuts(). + const double *xlp; + + /// Pointer on row activity. Reset by each call to generateCuts(). + const double *rowActivity; + + /// Pointer on matrix of coefficient ordered by rows. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byRow; + + /// Pointer on matrix of coefficient ordered by columns. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byCol; + + /// Fractionality of the cut and related quantities. + double f0; + double f0compl; + double ratiof0compl; + +#if defined(TRACK_REJECT) || defined (TRACK_REJECT_SIMPLE) + /// Should we track the reason of each cut rejection? + bool trackRejection; + /// Number of failures by type + int fracFail; + int dynFail; + int violFail; + int suppFail; + int smallCoeffFail; + int scaleFail; + /// Total number of generated cuts + int numGeneratedCuts; +#endif + + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglGMI class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglGMIUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +#endif diff --git a/thirdparty/linux/include/coin/CglGMIParam.hpp b/thirdparty/linux/include/coin/CglGMIParam.hpp new file mode 100644 index 0000000..a1aae41 --- /dev/null +++ b/thirdparty/linux/include/coin/CglGMIParam.hpp @@ -0,0 +1,313 @@ +// Name: CglGMIParam.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design +// email: nannicini@sutd.edu.sg +// based on CglRedSplitParam.hpp by Francois Margot +// Date: 11/17/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2009, Giacomo Nannicini and others. All Rights Reserved. + +#ifndef CglGMIParam_H +#define CglGMIParam_H + +#include "CglParam.hpp" + + + /**@name CglGMI Parameters */ + //@{ + + /** Class collecting parameters for the GMI cut generator. + + Parameters of the generator are listed below. Modifying the default + values for parameters other than the last four might result in + invalid cuts. + + - MAXDYN: Maximum ratio between largest and smallest non zero + coefficients in a cut. See method setMAXDYN(). + - EPS_ELIM: Precision for deciding if a coefficient is zero when + eliminating slack variables. See method setEPS_ELIM(). + - MINVIOL: Minimum violation for the current basic solution in + a generated cut. See method setMINVIOL(). + - USE_INTSLACKS: Use integer slacks to generate cuts. + (not implemented yet, will be in the future). + See method setUSE_INTSLACKS(). + - AWAY: Look only at basic integer variables whose current value is at + least this value away from being integer. See method setAway(). + - CHECK_DUPLICATES: Should we check for duplicates when adding a cut + to the collection? Can be slow. + Default 0 - do not check, add cuts anyway. + - CLEAN_PROC: Cleaning procedure that should be used. Look below at the + enumeration CleaningProcedure for possible values. + - INTEGRAL_SCALE_CONT: If we try to scale cut coefficients so that + they become integral, do we also scale on + continuous variables? + Default 0 - do not scale continuous vars. + Used only if CLEAN_PROC does integral scaling. + - ENFORCE_SCALING: Discard badly scaled cuts, or keep them (unscaled). + Default 1 - yes. + + */ + //@} + +class CglGMIParam : public CglParam { + +public: + + /**@name Enumerations */ + enum CleaningProcedure{ + /* CglLandP procedure I */ + CP_CGLLANDP1, + /* CglLandP procedure II */ + CP_CGLLANDP2, + /* CglRedSplit procedure I */ + CP_CGLREDSPLIT, + /* Only integral cuts, i.e. cuts with integral coefficients */ + CP_INTEGRAL_CUTS, + /* CglLandP procedure I with integral scaling */ + CP_CGLLANDP1_INT, + /* CglLandP procedure I with scaling of the max element to 1 if possible */ + CP_CGLLANDP1_SCALEMAX, + /* CglLandP procedure I with scaling of the rhs to 1 if possible */ + CP_CGLLANDP1_SCALERHS + }; + + /**@name Set/get methods */ + + //@{ + /** Aliases for parameter get/set method in the base class CglParam */ + + /** Value for Infinity. Default: DBL_MAX */ + inline void setInfinity(double value) {setINFINIT(value);} + inline double getInfinity() const {return INFINIT;} + + /** Epsilon for comparing numbers. Default: 1.0e-6 */ + inline void setEps(double value) {setEPS(value);} + inline double getEps() const {return EPS;} + + /** Epsilon for zeroing out coefficients. Default: 1.0e-5 */ + inline void setEpsCoeff(double value) {setEPS_COEFF(value);} + inline double getEpsCoeff() const {return EPS_COEFF;} + + /** Maximum support of the cutting planes. Default: INT_MAX */ + inline void setMaxSupport(int value) {setMAX_SUPPORT(value);} + inline int getMaxSupport() const {return MAX_SUPPORT;} + /** Alias for consistency with our naming scheme */ + inline void setMaxSupportAbs(int value) {setMAX_SUPPORT(value);} + inline int getMaxSupportAbs() const {return MAX_SUPPORT;} + inline int getMAX_SUPPORT_ABS() const {return MAX_SUPPORT;} + + /** Set AWAY, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.005 */ + virtual void setAway(double value); + /** Get value of away */ + inline double getAway() const {return AWAY;} + /// Aliases + inline void setAWAY(double value) {setAway(value);} + inline double getAWAY() const {return AWAY;} + + /** Set the value of EPS_ELIM, epsilon for values of coefficients when + eliminating slack variables; + Default: 0 */ + virtual void setEPS_ELIM(double value); + /** Get the value of EPS_ELIM */ + inline double getEPS_ELIM() const {return EPS_ELIM;} + /// Aliases + inline void setEpsElim(double value) {setEPS_ELIM(value);} + inline double getEpsElim() const {return EPS_ELIM;} + + /** Set EPS_RELAX_ABS */ + virtual void setEPS_RELAX_ABS(double value); + /** Get value of EPS_RELAX_ABS */ + inline double getEPS_RELAX_ABS() const {return EPS_RELAX_ABS;} + /// Aliases + inline void setEpsRelaxAbs(double value) {setEPS_RELAX_ABS(value);} + inline double getEpsRelaxAbs() const {return EPS_RELAX_ABS;} + + /** Set EPS_RELAX_REL */ + virtual void setEPS_RELAX_REL(double value); + /** Get value of EPS_RELAX_REL */ + inline double getEPS_RELAX_REL() const {return EPS_RELAX_REL;} + /// Aliases + inline void setEpsRelaxRel(double value) {setEPS_RELAX_REL(value);} + inline double getEpsRelaxRel() const {return EPS_RELAX_REL;} + + // Set the maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e6. + virtual void setMAXDYN(double value); + /** Get the value of MAXDYN */ + inline double getMAXDYN() const {return MAXDYN;} + /// Aliases + inline void setMaxDyn(double value) {setMAXDYN(value);} + inline double getMaxDyn() const {return MAXDYN;} + + /** Set the value of MINVIOL, the minimum violation for the current + basic solution in a generated cut. Default: 1e-7 */ + virtual void setMINVIOL(double value); + /** Get the value of MINVIOL */ + inline double getMINVIOL() const {return MINVIOL;} + /// Aliases + inline void setMinViol(double value) {setMINVIOL(value);} + inline double getMinViol() const {return MINVIOL;} + + /** Set the value of MAX_SUPPORT_REL, the factor contributing to the + maximum support relative to the number of columns. Maximum + allowed support is: MAX_SUPPORT_ABS + + MAX_SUPPORT_REL*ncols. Default: 0.1 */ + virtual void setMAX_SUPPORT_REL(double value); + /** Get the value of MINVIOL */ + inline double getMAX_SUPPORT_REL() const {return MAX_SUPPORT_REL;} + /// Aliases + inline void setMaxSupportRel(double value) {setMAX_SUPPORT_REL(value);} + inline double getMaxSupportRel() const {return MAX_SUPPORT_REL;} + + /** Set the value of USE_INTSLACKS. Default: 0 */ + virtual void setUSE_INTSLACKS(bool value); + /** Get the value of USE_INTSLACKS */ + inline bool getUSE_INTSLACKS() const {return USE_INTSLACKS;} + /// Aliases + inline void setUseIntSlacks(bool value) {setUSE_INTSLACKS(value);} + inline int getUseIntSlacks() const {return USE_INTSLACKS;} + + /** Set the value of CHECK_DUPLICATES. Default: 0 */ + virtual void setCHECK_DUPLICATES(bool value); + /** Get the value of CHECK_DUPLICATES */ + inline bool getCHECK_DUPLICATES() const {return CHECK_DUPLICATES;} + /// Aliases + inline void setCheckDuplicates(bool value) {setCHECK_DUPLICATES(value);} + inline bool getCheckDuplicates() const {return CHECK_DUPLICATES;} + + /** Set the value of CLEAN_PROC. Default: CP_CGLLANDP1 */ + virtual void setCLEAN_PROC(CleaningProcedure value); + /** Get the value of CLEAN_PROC. */ + inline CleaningProcedure getCLEAN_PROC() const {return CLEAN_PROC;} + /// Aliases + inline void setCleanProc(CleaningProcedure value) {setCLEAN_PROC(value);} + inline CleaningProcedure getCleaningProcedure() const {return CLEAN_PROC;} + + /** Set the value of INTEGRAL_SCALE_CONT. Default: 0 */ + virtual void setINTEGRAL_SCALE_CONT(bool value); + /** Get the value of INTEGRAL_SCALE_CONT. */ + inline bool getINTEGRAL_SCALE_CONT() const {return INTEGRAL_SCALE_CONT;} + /// Aliases + inline void setIntegralScaleCont(bool value) {setINTEGRAL_SCALE_CONT(value);} + inline bool getIntegralScaleCont() const {return INTEGRAL_SCALE_CONT;} + + /** Set the value of ENFORCE_SCALING. Default: 1 */ + virtual void setENFORCE_SCALING(bool value); + /** Get the value of ENFORCE_SCALING. */ + inline bool getENFORCE_SCALING() const {return ENFORCE_SCALING;} + /// Aliases + inline void setEnforceScaling(bool value) {setENFORCE_SCALING(value);} + inline bool getEnforcescaling() const {return ENFORCE_SCALING;} + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglGMIParam(double eps = 1e-12, + double away = 0.005, + double eps_coeff = 1e-11, + double eps_elim = 0, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-4, + int max_supp_abs = 1000, + double max_supp_rel = 0.1, + CleaningProcedure clean_proc = CP_CGLLANDP1, + bool use_int_slacks = false, + bool check_duplicates = false, + bool integral_scale_cont = false, + bool enforce_scaling = true); + + /// Constructor from CglParam + CglGMIParam(CglParam &source, + double away = 0.005, + double eps_elim = 1e-12, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-4, + double max_supp_rel = 0.1, + CleaningProcedure clean_proc = CP_CGLLANDP1, + bool use_int_slacks = false, + bool check_duplicates = false, + bool integral_scale_cont = false, + bool enforce_scaling = true); + + /// Copy constructor + CglGMIParam(const CglGMIParam &source); + + /// Clone + virtual CglGMIParam* clone() const; + + /// Assignment operator + virtual CglGMIParam& operator=(const CglGMIParam &rhs); + + /// Destructor + virtual ~CglGMIParam(); + //@} + +protected: + + /**@name Parameters */ + //@{ + + /** Use row only if pivot variable should be integer but is more + than AWAY from being integer. */ + double AWAY; + + /** Epsilon for value of coefficients when eliminating slack variables. + Default: 0. */ + double EPS_ELIM; + + /** Value added to the right hand side of each generated cut to relax it. + Default: 1e-11 */ + double EPS_RELAX_ABS; + + /** For a generated cut with right hand side rhs_val, + EPS_RELAX_EPS * fabs(rhs_val) is used to relax the constraint. + Default: 1.e-13 */ + double EPS_RELAX_REL; + + /** Maximum ratio between largest and smallest non zero + coefficients in a cut. Default: 1e6. */ + double MAXDYN; + + /** Minimum violation for the current basic solution in a generated cut. + Default: 1e-4. */ + double MINVIOL; + + /** Maximum support relative to number of columns. Must be between 0 + and 1. Default: 0. */ + double MAX_SUPPORT_REL; + + /** Which cleaning procedure should be used? */ + CleaningProcedure CLEAN_PROC; + + /** Use integer slacks to generate cuts if USE_INTSLACKS = 1. Default: 0. */ + bool USE_INTSLACKS; + + /** Check for duplicates when adding the cut to the collection? */ + bool CHECK_DUPLICATES; + + /** Should we try to rescale cut coefficients on continuous variables + so that they become integral, or do we only rescale coefficients + on integral variables? Used only by cleaning procedure that try + the integral scaling. */ + bool INTEGRAL_SCALE_CONT; + + /** Should we discard badly scaled cuts (according to the scaling + procedure in use)? If false, CglGMI::scaleCut always returns + true, even though it still scales cuts whenever possible, but + not cut is rejected for scaling. Default true. Used only by + cleaning procedure that try to scale. */ + bool ENFORCE_SCALING; + + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/CglGomory.hpp b/thirdparty/linux/include/coin/CglGomory.hpp new file mode 100644 index 0000000..2d7f5c5 --- /dev/null +++ b/thirdparty/linux/include/coin/CglGomory.hpp @@ -0,0 +1,204 @@ +// 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). + +#ifndef CglGomory_H +#define CglGomory_H + +#include <string> + +#include "CglCutGenerator.hpp" + +class CoinWarmStartBasis; +/** Gomory Cut Generator Class */ +class CglGomory : public CglCutGenerator { + friend void CglGomoryUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Gomory cuts for the model of the + solver interface, si. + + Insert the generated cuts into OsiCut, cs. + + There is a limit option, which will only generate cuts with + less than this number of entries. + + We can also only look at 0-1 variables a certain distance + from integer. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /** Generates cuts given matrix and solution etc, + returns number of cuts generated */ + int generateCuts( const OsiRowCutDebugger * debugger, + OsiCuts & cs, + const CoinPackedMatrix & columnCopy, + const CoinPackedMatrix & rowCopy, + const double * colsol, + const double * colLower, const double * colUpper, + const double * rowLower, const double * rowUpper, + const char * intVar , + const CoinWarmStartBasis* warm, + const CglTreeInfo info = CglTreeInfo()); + /** Generates cuts given matrix and solution etc, + returns number of cuts generated (no row copy passed in) */ + int generateCuts( const OsiRowCutDebugger * debugger, + OsiCuts & cs, + const CoinPackedMatrix & columnCopy, + const double * colsol, + const double * colLower, const double * colUpper, + const double * rowLower, const double * rowUpper, + const char * intVar , + const CoinWarmStartBasis* warm, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const { return true; } + //@} + + /**@name Change way Gomory works */ + //@{ + /// Pass in a copy of original solver (clone it) + void passInOriginalSolver(OsiSolverInterface * solver); + /// Returns original solver + inline OsiSolverInterface * originalSolver() const + { return originalSolver_;} + /// Set type - 0 normal, 1 add original matrix one, 2 replace + inline void setGomoryType(int type) + { gomoryType_=type;} + /// Return type + inline int gomoryType() const + { return gomoryType_;} + //@} + + /**@name Change limit on how many variables in cut (default 50) */ + //@{ + /// Set + void setLimit(int limit); + /// Get + int getLimit() const; + /// Set at root (if <normal then use normal) + void setLimitAtRoot(int limit); + /// Get at root + int getLimitAtRoot() const; + /// Return maximum length of cut in tree + virtual int maximumLengthOfCutInTree() const; + //@} + + /**@name Change criterion on which variables to look at. All ones + more than "away" away from integrality will be investigated + (default 0.05) */ + //@{ + /// Set away + void setAway(double value); + /// Get away + double getAway() const; + /// Set away at root + void setAwayAtRoot(double value); + /// Get away at root + double getAwayAtRoot() const; + //@} + + /**@name Change criterion on which the cut id relaxed if the code + thinks the factorization has inaccuracies. The relaxation to + RHS is smallest of - + 1) 1.0e-4 + 2) conditionNumberMultiplier * condition number of factorization + 3) largestFactorMultiplier * largest (dual*element) forming tableau + row + */ + //@{ + /// Set ConditionNumberMultiplier + void setConditionNumberMultiplier(double value); + /// Get ConditionNumberMultiplier + double getConditionNumberMultiplier() const; + /// Set LargestFactorMultiplier + void setLargestFactorMultiplier(double value); + /// Get LargestFactorMultiplier + double getLargestFactorMultiplier() const; + //@} + + /**@name change factorization */ + //@{ + /// Set/unset alternative factorization + inline void useAlternativeFactorization(bool yes=true) + { alternateFactorization_= (yes) ? 1 : 0;} + /// Get whether alternative factorization being used + inline bool alternativeFactorization() const + { return (alternateFactorization_!=0);} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglGomory (); + + /// Copy constructor + CglGomory ( + const CglGomory &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglGomory & + operator=( + const CglGomory& rhs); + + /// Destructor + virtual + ~CglGomory (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +private: + + // Private member methods + + // Private member data + + /**@name Private member data */ + //@{ + /// Only investigate if more than this away from integrality + double away_; + /// Only investigate if more than this away from integrality (at root) + double awayAtRoot_; + /// Multiplier for conditionNumber cut relaxation + double conditionNumberMultiplier_; + /// Multiplier for largest factor cut relaxation + double largestFactorMultiplier_; + /// Original solver + OsiSolverInterface * originalSolver_; + /// Limit - only generate if fewer than this in cut + int limit_; + /// Limit - only generate if fewer than this in cut (at root) + int limitAtRoot_; + /// Dynamic limit in tree + int dynamicLimitInTree_; + /// Number of times stalled + int numberTimesStalled_; + /// nonzero to use alternative factorization + int alternateFactorization_; + /// Type - 0 normal, 1 add original matrix one, 2 replace + int gomoryType_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglGomory class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglGomoryUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/thirdparty/linux/include/coin/CglKnapsackCover.hpp b/thirdparty/linux/include/coin/CglKnapsackCover.hpp new file mode 100644 index 0000000..b0e81d6 --- /dev/null +++ b/thirdparty/linux/include/coin/CglKnapsackCover.hpp @@ -0,0 +1,310 @@ +// $Id: CglKnapsackCover.hpp 1201 2014-03-07 17:24:04Z forrest $ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglKnapsackCover_H +#define CglKnapsackCover_H + +#include <string> + +#include "CglCutGenerator.hpp" +#include "CglTreeInfo.hpp" + +/** Knapsack Cover Cut Generator Class */ +class CglKnapsackCover : public CglCutGenerator { + friend void CglKnapsackCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + /** A method to set which rows should be tested for knapsack covers */ + void setTestedRowIndices(int num, const int* ind); + + /**@name Generate Cuts */ + //@{ + /** Generate knapsack cover cuts for the model of the solver interface, si. + Insert the generated cuts into OsiCut, cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglKnapsackCover (); + + /// Copy constructor + CglKnapsackCover ( + const CglKnapsackCover &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglKnapsackCover & + operator=( + const CglKnapsackCover& rhs); + + /// Destructor + virtual + ~CglKnapsackCover (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + + + /**@name Sets and gets */ + //@{ + /// Set limit on number in knapsack + inline void setMaxInKnapsack(int value) + { if (value>0) maxInKnapsack_ = value;} + /// get limit on number in knapsack + inline int getMaxInKnapsack() const + {return maxInKnapsack_;} + /// Switch off expensive cuts + inline void switchOffExpensive() + { expensiveCuts_=false;} + /// Switch on expensive cuts + inline void switchOnExpensive() + { expensiveCuts_=true;} +private: + + // Private member methods + + + /**@name Private methods */ + //@{ + + /** deriveAKnapsack + returns 1 if it is able to derive + a (canonical) knapsack inequality + in binary variables of the form ax<=b + from the rowIndex-th row in the model, + returns 0 otherwise. + */ + int deriveAKnapsack( + const OsiSolverInterface & si, + OsiCuts & cs, + CoinPackedVector & krow, + bool treatAsLRow, + double & b, + int * complement, + double * xstar, + int rowIndex, + int numberElements, + const int * index, + const double * element); + + int deriveAKnapsack( + const OsiSolverInterface & si, + OsiCuts & cs, + CoinPackedVector & krow, + double & b, + int * complement, + double * xstar, + int rowIndex, + const CoinPackedVectorBase & matrixRow); + + /** Find a violated minimal cover from + a canonical form knapsack inequality by + solving the -most- violated cover problem + and postprocess to ensure minimality + */ + int findExactMostViolatedMinCover( + int nCols, + int row, + CoinPackedVector & krow, + double b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder); + + /** Find the most violate minimum cover by solving the lp-relaxation of the + most-violate-min-cover problem + */ + int findLPMostViolatedMinCover( + int nCols, + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder); + +/// find a minimum cover by a simple greedy approach + int findGreedyCover( + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder + ); + + /// lift the cover inequality + int liftCoverCut( + double & b, + int nRowElem, + CoinPackedVector & cover, + CoinPackedVector & remainder, + CoinPackedVector & cut ); + + /// sequence-independent lift and uncomplement and add the resulting cut to the cut set + int liftAndUncomplementAndAdd( + double rowub, + CoinPackedVector & krow, + double & b, + int * complement, + int row, + CoinPackedVector & cover, + CoinPackedVector & remainder, + OsiCuts & cs ); + + /// sequence-dependent lift, uncomplement and add the resulting cut to the cut set +void seqLiftAndUncomplementAndAdd( + int nCols, + double * xstar, + int * complement, + int row, + int nRowElem, + double & b, + CoinPackedVector & cover, // need not be violated + CoinPackedVector & remainder, + OsiCuts & cs ); + + /// sequence-dependent lift binary variables either up or down, uncomplement and add to the cut set +void liftUpDownAndUncomplementAndAdd( + int nCols, + double * xstar, + int * complement, + int row, + int nRowElem, + double & b, + + // the following 3 packed vectors partition the krow: + CoinPackedVector & fracCover, // vars have frac soln values in lp relaxation + // and form cover with the vars atOne + CoinPackedVector & atOne, // vars have soln value of 1 in lp relaxation + // and together with fracCover form minimal (?) cover. + CoinPackedVector & remainder, + OsiCuts & cs ); + + /// find a cover using a variation of the logic found in OSL (w/o SOS) + int findPseudoJohnAndEllisCover ( + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder); + + /// find a cover using the basic logic found in OSL (w/o SOS) + int findJohnAndEllisCover ( + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & fracCover, + CoinPackedVector & atOnes, + CoinPackedVector & remainder); + + + /** A C-style implementation of the Horowitz-Sahni exact solution + procedure for solving knapsack problem. + + (ToDo: implement the more efficient dynamic programming approach) + + (Reference: Martello and Toth, Knapsack Problems, Wiley, 1990, p30.) + */ + int exactSolveKnapsack( + int n, + double c, + double const *pp, + double const *ww, + double & z, + int * x); + /// For testing gub stuff + int gubifyCut(CoinPackedVector & cut); +public: + /** Creates cliques for use by probing. + Only cliques >= minimumSize and < maximumSize created + Can also try and extend cliques as a result of probing (root node). + Returns number of cliques found. + */ + int createCliques( OsiSolverInterface & si, + int minimumSize=2, int maximumSize=100, bool extendCliques=false); +private: + /// Delete all clique information + void deleteCliques(); + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// epsilon + double epsilon_; + /// Tolerance to use for violation - bigger than epsilon_ + double epsilon2_; + /// 1-epsilon + double onetol_; + /// Maximum in knapsack + int maxInKnapsack_; + /** which rows to look at. If specified, only these rows will be considered + for generating knapsack covers. Otherwise all rows will be tried */ + int numRowsToCheck_; + int* rowsToCheck_; + /// exactKnapsack can be expensive - this switches off some + bool expensiveCuts_; + /// Cliques + /// **** TEMP so can reference from listing + const OsiSolverInterface * solver_; + int whichRow_; + int * complement_; + double * elements_; + /// Number of cliques + int numberCliques_; + /// Clique type + typedef struct { + unsigned int equality:1; // nonzero if clique is == + } CliqueType; + CliqueType * cliqueType_; + /// Start of each clique + int * cliqueStart_; + /// Entries for clique + CliqueEntry * cliqueEntry_; + /** Start of oneFixes cliques for a column in matrix or -1 if not + in any clique */ + int * oneFixStart_; + /** Start of zeroFixes cliques for a column in matrix or -1 if not + in any clique */ + int * zeroFixStart_; + /// End of fixes for a column + int * endFixStart_; + /// Clique numbers for one or zero fixes + int * whichClique_; + /// Number of columns + int numberColumns_; + /** For each column with nonzero in row copy this gives a clique "number". + So first clique mentioned in row is always 0. If no entries for row + then no cliques. If sequence > numberColumns then not in clique. + */ + //CliqueEntry * cliqueRow_; + /// cliqueRow_ starts for each row + //int * cliqueRowStart_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglKnapsackCover class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglKnapsackCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/thirdparty/linux/include/coin/CglLandP.hpp b/thirdparty/linux/include/coin/CglLandP.hpp new file mode 100644 index 0000000..64447e7 --- /dev/null +++ b/thirdparty/linux/include/coin/CglLandP.hpp @@ -0,0 +1,306 @@ +// Copyright (C) 2005-2009, Pierre Bonami and others. All Rights Reserved. +// Author: Pierre Bonami +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// Date: 07/21/05 +// +// $Id: CglLandP.hpp 1122 2013-04-06 20:39:53Z stefan $ +// +// This code is licensed under the terms of the Eclipse Public License (EPL). +//--------------------------------------------------------------------------- +#ifndef CglLandP_H +#define CglLandP_H + +#include "CglLandPValidator.hpp" +#include "CglCutGenerator.hpp" +#include "CglParam.hpp" + +#include <iostream> +class CoinWarmStartBasis; +/** Performs one round of Lift & Project using CglLandPSimplex + to build cuts +*/ + +namespace LAP +{ +enum LapMessagesTypes +{ + BEGIN_ROUND, + END_ROUND, + DURING_SEP, + CUT_REJECTED, + CUT_FAILED, + CUT_GAP, + LAP_CUT_FAILED_DO_MIG, + LAP_MESSAGES_DUMMY_END +}; +/** Output messages for Cgl */ +class LapMessages : public CoinMessages +{ +public: + /** Constructor */ + LapMessages( ); + /** destructor.*/ + virtual ~LapMessages() {} +}; +class CglLandPSimplex; +} + +class CglLandP : public CglCutGenerator +{ + friend void CglLandPUnitTest(OsiSolverInterface *si, const std::string & mpsDir); + + friend class LAP::CglLandPSimplex; + friend class CftCglp; + +public: + + enum SelectionRules + { + mostNegativeRc /** select most negative reduced cost */, + bestPivot /** select best possible pivot.*/, + initialReducedCosts/** Select only those rows which had initialy a 0 reduced cost.*/ + }; + + enum ExtraCutsMode + { + none/** Generate no extra cuts.*/, + AtOptimalBasis /** Generate cuts from the optimal basis.*/, + WhenEnteringBasis /** Generate cuts as soon as a structural enters the basis.*/, + AllViolatedMigs/** Generate all violated Mixed integer Gomory cuts in the course of the optimization.*/ + }; + + /** Space where cuts are optimized.*/ + enum SeparationSpaces + { + Fractional=0 /** True fractional space.*/, + Fractional_rc/** Use fractional space only for computing reduced costs.*/, + Full /** Work in full space.*/ + }; + + /** Normalization */ + enum Normalization + { + Unweighted = 0, + WeightRHS, + WeightLHS, + WeightBoth + }; + + enum LHSnorm + { + L1 = 0, + L2, + SupportSize, + Infinity, + Average, + Uniform + }; + /** RHS weight in normalization.*/ + enum RhsWeightType + { + Fixed = 0 /** 2*initial number of constraints. */, + Dynamic /** 2 * current number of constraints. */ + }; + /** Class storing parameters. + \remark I take all parameters from Ionut's code */ + class Parameters : public CglParam + { + public: + /** Default constructor (with default values)*/ + Parameters(); + /** Copy constructor */ + Parameters(const Parameters &other); + /** Assignment opertator */ + Parameters & operator=(const Parameters &other); + /// @name integer parameters + ///@{ + + /** Max number of pivots before we generate the cut + \default 20 */ + int pivotLimit; + /** Max number of pivots at regular nodes. Put a value if you want it lower than the global pivot limit. + \default 100.*/ + int pivotLimitInTree; + /** Maximum number of cuts generated at a given round*/ + int maxCutPerRound; + /** Maximum number of failed pivots before aborting */ + int failedPivotLimit; + /** maximum number of consecutive degenerate pivots + \default 0 */ + int degeneratePivotLimit; + /** Maximum number of extra rows to generate per round.*/ + int extraCutsLimit; + ///@} + /// @name double parameters + ///@{ + /** Tolerance for small pivots values (should be the same as the solver */ + double pivotTol; + /** A variable have to be at least away from integrity to be generated */ + double away; + /** Total time limit for cut generation.*/ + double timeLimit; + /** Time limit for generating a single cut.*/ + double singleCutTimeLimit; + /** Weight to put in RHS of normalization if static.*/ + double rhsWeight; + ///@} + + /// @name Flags + ///@{ + /** Do we use tableau row or the disjunction (I don't really get that there should be a way to always use the tableau)*/ + bool useTableauRow; + /** Do we apply Egon Balas's Heuristic for modularized cuts */ + bool modularize; + /** Do we strengthen the final cut (always do if modularize is 1) */ + bool strengthen; + /** Wether to limit or not the number of mistaken RC (when perturbation is applied).*/ + bool countMistakenRc; + /** Work in the reduced space (only non-structurals enter the basis) */ + SeparationSpaces sepSpace; + /** Apply perturbation procedure. */ + bool perturb; + /** How to weight normalization.*/ + Normalization normalization; + /** How to weight RHS of normalization.*/ + RhsWeightType rhsWeightType; + /** How to weight LHS of normalization.*/ + LHSnorm lhs_norm; + /** Generate extra constraints from optimal lift-and-project basis.*/ + ExtraCutsMode generateExtraCuts; + /** Which rule to apply for choosing entering and leaving variables.*/ + SelectionRules pivotSelection; + ///@} + }; + + + /** Constructor for the class*/ + CglLandP(const CglLandP::Parameters ¶ms = CglLandP::Parameters(), + const LAP::Validator &validator = LAP::Validator()); + /** Destructor */ + ~CglLandP(); + /** Copy constructor */ + CglLandP(const CglLandP &source); + /** Assignment operator */ + CglLandP& operator=(const CglLandP &rhs); + /** Clone function */ + CglCutGenerator * clone() const; + + /**@name Generate Cuts */ + //@{ + + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + //@} + + virtual bool needsOptimalBasis() const + { + return true; + } + + LAP::Validator & validator() + { + return validator_; + } + /** set level of log for cut generation procedure : + <ol start=0 > + <li> for none </li> + <li> for log at begin and end of procedure + at some time interval </li> + <li> for log at every cut generated </li> + </ol> + */ + void setLogLevel(int level) + { + handler_->setLogLevel(level); + } + + class NoBasisError : public CoinError + { + public: + NoBasisError(): CoinError("No basis available","LandP","") {} + }; + + class SimplexInterfaceError : public CoinError + { + public: + SimplexInterfaceError(): CoinError("Invalid conversion to simplex interface", "CglLandP","CglLandP") {} + }; + Parameters & parameter() + { + return params_; + } +private: + + + void scanExtraCuts(OsiCuts& cs, const double * colsol) const; + + Parameters params_; + + /** Some informations that will be changed by the pivots and that we want to keep*/ + struct CachedData + { + CachedData(int nBasics = 0 , int nNonBasics = 0); + CachedData(const CachedData & source); + + CachedData& operator=(const CachedData &source); + /** Get the data from a problem */ + void getData(const OsiSolverInterface &si); + + void clean(); + + ~CachedData(); + /** Indices of basic variables in starting basis (ordered if variable basics_[i] s basic in row i)*/ + int * basics_; + /** Indices of non-basic variables */ + int *nonBasics_; + /** number of basics variables */ + int nBasics_; + /** number of non-basics */ + int nNonBasics_; + /** Optimal basis */ + CoinWarmStartBasis * basis_; + /** Stores the value of the solution to cut */ + double * colsol_; + /** Stores the values of the slacks */ + double * slacks_; + /** Stores wheter slacks are integer constrained */ + bool * integers_; + /** Solver before pivots */ + OsiSolverInterface * solver_; + }; + /** Retrieve sorted integer variables which are fractional in the solution. + Return the number of variables.*/ + int getSortedFractionals(CoinPackedVector &xFrac, + const CachedData & data, + const CglLandP::Parameters& params) const; + /** Retrieve sorted integer variables which are fractional in the solution. + Return the number of variables.*/ + void getSortedFractionalIndices(std::vector<int>& indices, + const CachedData &data, + const CglLandP::Parameters & params) const; + /** Cached informations about problem.*/ + CachedData cached_; + /** message handler */ + CoinMessageHandler * handler_; + /** messages */ + CoinMessages messages_; + /** cut validator */ + LAP::Validator validator_; + /** number of rows in the original problems. */ + int numrows_; + /** number of columns in the original problems. */ + int numcols_; + /** Original lower bounds for the problem (for lifting cuts).*/ + double * originalColLower_; + /** Original upper bounds for the problem (for lifting cuts).*/ + double * originalColUpper_; + /** Flag to say if cuts can be lifted.*/ + bool canLift_; + /** Store some extra cut which could be cheaply generated but do not cut current incumbent.*/ + OsiCuts extraCuts_; +}; +void CglLandPUnitTest(OsiSolverInterface *si, const std::string & mpsDir); + +#endif + diff --git a/thirdparty/linux/include/coin/CglLandPValidator.hpp b/thirdparty/linux/include/coin/CglLandPValidator.hpp new file mode 100644 index 0000000..8b05597 --- /dev/null +++ b/thirdparty/linux/include/coin/CglLandPValidator.hpp @@ -0,0 +1,131 @@ +// Copyright (C) 2005-2009, Pierre Bonami and others. All Rights Reserved. +// Author: Pierre Bonami +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// Date: 11/22/05 +// +// $Id: CglLandPValidator.hpp 1122 2013-04-06 20:39:53Z stefan $ +// +// This code is licensed under the terms of the Eclipse Public License (EPL). +//--------------------------------------------------------------------------- + +#ifndef CglLandPValidator_H +#define CglLandPValidator_H +#include "OsiSolverInterface.hpp" +#include "CglParam.hpp" +#include <vector> + +/** constants describing rejection codes*/ +//[5] = {"Accepted", "violation too small", "small coefficient too small", "big dynamic","too dense"} + + +namespace LAP +{ + +/** Class to validate or reject a cut */ +class Validator +{ +public: + /** Reasons for rejecting a cut */ + enum RejectionsReasons + { + NoneAccepted=0 /**Cut was accepted*/, + SmallViolation /** Violation of the cut is too small */, + SmallCoefficient /** There is a small coefficient we can not get rid off.*/, + BigDynamic /** Dynamic of coefficinet is too important. */, + DenseCut/**cut is too dense */, + EmptyCut/**After cleaning cut has become empty*/, + DummyEnd/** dummy*/ + }; + + /** Constructor with default values */ + Validator(double maxFillIn = 1., + double maxRatio = 1e8, + double minViolation = 0, + bool scale = false, + double rhsScale = 1); + + /** Clean an OsiCut */ + int cleanCut(OsiRowCut & aCut, const double * solCut,const OsiSolverInterface &si, const CglParam & par, + const double * colLower, const double * colUpper); + /** Clean an OsiCut by another method */ + int cleanCut2(OsiRowCut & aCut, const double * solCut, const OsiSolverInterface &si, const CglParam & par, + const double * colLower, const double * colUpper); + /** Call the cut cleaner */ + int operator()(OsiRowCut & aCut, const double * solCut,const OsiSolverInterface &si, const CglParam & par, + const double * colLower, const double * colUpper) + { + return cleanCut(aCut, solCut, si, par, colLower, colUpper); + } + /** @name set functions */ + /** @{ */ + void setMaxFillIn(double value) + { + maxFillIn_ = value; + } + void setMaxRatio(double value) + { + maxRatio_ = value; + } + void setMinViolation(double value) + { + minViolation_ = value; + } + + void setRhsScale(double v) + { + rhsScale_ = v; + } + /** @} */ + /** @name get functions */ + /** @{ */ + double getMaxFillIn() + { + return maxFillIn_; + } + double getMaxRatio() + { + return maxRatio_; + } + double getMinViolation() + { + return minViolation_; + } + /** @} */ + + const std::string& failureString(RejectionsReasons code) const + { + return rejections_[static_cast<int> (code)]; + } + const std::string& failureString(int code) const + { + return rejections_[ code]; + } + int numRejected(RejectionsReasons code)const + { + return numRejected_[static_cast<int> (code)]; + } + int numRejected(int code)const + { + return numRejected_[ code]; + } +private: + static void fillRejectionReasons(); + /** max percentage of given formulation fillIn should be accepted for cut fillin.*/ + double maxFillIn_; + /** max ratio between smallest and biggest coefficient */ + double maxRatio_; + /** minimum violation for accepting a cut */ + double minViolation_; + /** Do we do scaling? */ + bool scale_; + /** Scale of right-hand-side.*/ + double rhsScale_; + /** Strings explaining reason for rejections */ + static std::vector<std::string> rejections_; + /** Number of cut rejected for each of the reasons.*/ + std::vector<int> numRejected_; +}; + +}/* Ends namespace LAP.*/ +#endif diff --git a/thirdparty/linux/include/coin/CglLiftAndProject.hpp b/thirdparty/linux/include/coin/CglLiftAndProject.hpp new file mode 100644 index 0000000..364ba5a --- /dev/null +++ b/thirdparty/linux/include/coin/CglLiftAndProject.hpp @@ -0,0 +1,104 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglLiftAndProject_H +#define CglLiftAndProject_H + +#include <string> + +#include "CglCutGenerator.hpp" + +/** Lift And Project Cut Generator Class */ +class CglLiftAndProject : public CglCutGenerator { + friend void CglLiftAndProjectUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + /**@name Generate Cuts */ + //@{ + /** Generate lift-and-project cuts for the + model of the solver interface, si. + Insert the generated cuts into OsiCut, cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /** Get the normalization : Either beta=+1 or beta=-1. + */ + + double getBeta() const { + return beta_; + } + + /** Set the normalization : Either beta=+1 or beta=-1. + Default value is 1. + */ + void setBeta(int oneOrMinusOne){ + if (oneOrMinusOne==1 || oneOrMinusOne==-1){ + beta_= static_cast<double>(oneOrMinusOne); + } + else { + throw CoinError("Unallowable value. Beta must be 1 or -1", + "cutGeneration","CglLiftAndProject"); + } + } + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglLiftAndProject (); + + /// Copy constructor + CglLiftAndProject ( + const CglLiftAndProject &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglLiftAndProject & + operator=( + const CglLiftAndProject& rhs); + + /// Destructor + virtual + ~CglLiftAndProject (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// The normalization is beta_=1 or beta_=-1 + double beta_; + /// epsilon + double epsilon_; + /// 1-epsilon + double onetol_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglLiftAndProject class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglLiftAndProjectUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/thirdparty/linux/include/coin/CglMessage.hpp b/thirdparty/linux/include/coin/CglMessage.hpp new file mode 100644 index 0000000..5f080e8 --- /dev/null +++ b/thirdparty/linux/include/coin/CglMessage.hpp @@ -0,0 +1,50 @@ +// $Id: CglMessage.hpp 1105 2013-03-19 12:43:52Z forrest $ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglMessage_H +#define CglMessage_H + + +#include "CoinPragma.hpp" + +// This deals with Cgl messages (as against Osi messages etc) + +#include "CoinMessageHandler.hpp" +enum CGL_Message +{ + CGL_INFEASIBLE, + CGL_CLIQUES, + CGL_FIXED, + CGL_PROCESS_STATS, + CGL_SLACKS, + CGL_PROCESS_STATS2, + CGL_PROCESS_SOS1, + CGL_PROCESS_SOS2, + CGL_UNBOUNDED, + CGL_ELEMENTS_CHANGED1, + CGL_ELEMENTS_CHANGED2, + CGL_MADE_INTEGER, + CGL_ADDED_INTEGERS, + CGL_POST_INFEASIBLE, + CGL_POST_CHANGED, + CGL_GENERAL, + CGL_DUMMY_END +}; + +/** This deals with Cgl messages (as against Osi messages etc) + */ +class CglMessage : public CoinMessages { + +public: + + /**@name Constructors etc */ + //@{ + /** Constructor */ + CglMessage(Language language=us_en); + //@} + +}; + +#endif diff --git a/thirdparty/linux/include/coin/CglMixedIntegerRounding.hpp b/thirdparty/linux/include/coin/CglMixedIntegerRounding.hpp new file mode 100644 index 0000000..10580cb --- /dev/null +++ b/thirdparty/linux/include/coin/CglMixedIntegerRounding.hpp @@ -0,0 +1,429 @@ +// LAST EDIT: +//----------------------------------------------------------------------------- +// name: Mixed Integer Rounding Cut Generator +// authors: Joao Goncalves (jog7@lehigh.edu) +// Laszlo Ladanyi (ladanyi@us.ibm.com) +// date: August 11, 2004 +//----------------------------------------------------------------------------- +// Copyright (C) 2004, International Business Machines Corporation and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglMixedIntegerRounding_H +#define CglMixedIntegerRounding_H + +#include <iostream> +#include <fstream> +//#include <vector> + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" + +//============================================================================= + +#ifndef CGL_DEBUG +#define CGL_DEBUG 0 +#endif + +//============================================================================= + +// Class to store variable upper bounds (VUB) +class CglMixIntRoundVUB +{ + // Variable upper bounds have the form x_j <= a y_j, where x_j is + // a continuous variable and y_j is an integer variable + +protected: + int var_; // The index of y_j + double val_; // The value of a + +public: + // Default constructor + CglMixIntRoundVUB() : var_(-1), val_(-1) {} + + // Copy constructor + CglMixIntRoundVUB(const CglMixIntRoundVUB& source) { + var_ = source.var_; + val_ = source.val_; + } + + // Assignment operator + CglMixIntRoundVUB& operator=(const CglMixIntRoundVUB& rhs) { + if (this != &rhs) { + var_ = rhs.var_; + val_ = rhs.val_; + } + return *this; + } + + // Destructor + ~CglMixIntRoundVUB() {} + + // Query and set functions + int getVar() const { return var_; } + double getVal() const { return val_; } + void setVar(const int v) { var_ = v; } + void setVal(const double v) { val_ = v; } +}; + +//============================================================================= + +// Class to store variable lower bounds (VLB). +// It is the same as the class to store variable upper bounds +typedef CglMixIntRoundVUB CglMixIntRoundVLB; + +//============================================================================= + +/** Mixed Integer Rounding Cut Generator Class */ + +// Reference: +// Hugues Marchand and Laurence A. Wolsey +// Aggregation and Mixed Integer Rounding to Solve MIPs +// Operations Research, 49(3), May-June 2001. +// Also published as CORE Dicusion Paper 9839, June 1998. + +class CglMixedIntegerRounding : public CglCutGenerator { + + friend void CglMixedIntegerRoundingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +private: + //--------------------------------------------------------------------------- + // Enumeration constants that describe the various types of rows + enum RowType { + // The row type of this row is NOT defined yet. + ROW_UNDEFINED, + /** After the row is flipped to 'L', the row has exactly two variables: + one is negative binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARUB, + /** After the row is flipped to 'L', the row has exactly two variables: + one is positive binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARLB, + /** The row sense is 'E', the row has exactly two variables: + one is binary and the other is a continous, and the RHS is zero.*/ + ROW_VAREQ, + // The row contains continuous and integer variables; + // the total number of variables is at least 2 + ROW_MIX, + // The row contains only continuous variables + ROW_CONT, + // The row contains only integer variables + ROW_INT, + // The row contains other types of rows + ROW_OTHER + }; + + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Rounding cuts for the model data + contained in si. The generated cuts are inserted + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + //--------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglMixedIntegerRounding (); + + /// Alternate Constructor + CglMixedIntegerRounding (const int maxaggr, + const bool multiply, + const int criterion, + const int preproc = -1); + + /// Copy constructor + CglMixedIntegerRounding ( + const CglMixedIntegerRounding &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglMixedIntegerRounding & + operator=( + const CglMixedIntegerRounding& rhs); + + /// Destructor + virtual + ~CglMixedIntegerRounding (); + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + + //--------------------------------------------------------------------------- + /**@name Set and get methods */ + //@{ + /// Set MAXAGGR_ + inline void setMAXAGGR_ (int maxaggr) { + if (maxaggr > 0) { + MAXAGGR_ = maxaggr; + } + else { + throw CoinError("Unallowable value. maxaggr must be > 0", + "gutsOfConstruct","CglMixedIntegerRounding"); + } + } + + /// Get MAXAGGR_ + inline int getMAXAGGR_ () const { return MAXAGGR_; } + + /// Set MULTIPLY_ + inline void setMULTIPLY_ (bool multiply) { MULTIPLY_ = multiply; } + + /// Get MULTIPLY_ + inline bool getMULTIPLY_ () const { return MULTIPLY_; } + + /// Set CRITERION_ + inline void setCRITERION_ (int criterion) { + if ((criterion >= 1) && (criterion <= 3)) { + CRITERION_ = criterion; + } + else { + throw CoinError("Unallowable value. criterion must be 1, 2 or 3", + "gutsOfConstruct","CglMixedIntegerRounding"); + } + } + + /// Get CRITERION_ + inline int getCRITERION_ () const { return CRITERION_; } + + + /// Set doPreproc + void setDoPreproc(int value); + /// Get doPreproc + bool getDoPreproc() const; + + //@} + +private: + //-------------------------------------------------------------------------- + // Private member methods + + // Construct + void gutsOfConstruct (const int maxaggr, + const bool multiply, + const int criterion, + const int preproc); + + // Delete + void gutsOfDelete(); + + // Copy + void gutsOfCopy (const CglMixedIntegerRounding& rhs); + + // Do preprocessing. + // It determines the type of each row. It also identifies the variable + // upper bounds and variable lower bounds. + // It may change sense and RHS for ranged rows + void mixIntRoundPreprocess(const OsiSolverInterface& si); + + // Determine the type of a given row. + RowType determineRowType(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, const char sense, + const double rhs) const; + + // Generate MIR cuts + void generateMirCuts( const OsiSolverInterface& si, + const double* xlp, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedMatrix& matrixByRow, + const double* LHS, + const double* coefByRow, + const int* colInds, + const int* rowStarts, + const int* rowLengths, + //const CoinPackedMatrix& matrixByCol, + const double* coefByCol, + const int* rowInds, + const int* colStarts, + const int* colLengths, + OsiCuts& cs ) const; + + // Copy row selected to CoinPackedVector + void copyRowSelected( const int iAggregate, + const int rowSelected, + std::set<int>& setRowsAggregated, + int* listRowsAggregated, + double* xlpExtra, + const char sen, + const double rhs, + const double lhs, + const CoinPackedMatrix& matrixByRow, + CoinPackedVector& rowToAggregate, + double& rhsToAggregate) const; + + // Select a row to aggregate + bool selectRowToAggregate( const OsiSolverInterface& si, + const CoinPackedVector& rowAggregated, + const double* colUpperBound, + const double* colLowerBound, + const std::set<int>& setRowsAggregated, + const double* xlp, const double* coefByCol, + const int* rowInds, const int* colStarts, + const int* colLengths, + int& rowSelected, + int& colSelected ) const; + + // Aggregation heuristic. + // Combines one or more rows of the original matrix + void aggregateRow( const int colSelected, + CoinPackedVector& rowToAggregate, double rhs, + CoinPackedVector& rowAggregated, + double& rhsAggregated ) const; + + // Choose the bound substitution based on the criteria defined by the user + inline bool isLowerSubst(const double inf, + const double aj, + const double xlp, + const double LB, + const double UB) const; + + // Bound substitution heuristic + bool boundSubstitution( const OsiSolverInterface& si, + const CoinPackedVector& rowAggregated, + const double* xlp, + const double* xlpExtra, + const double* colUpperBound, + const double* colLowerBound, + CoinPackedVector& mixedKnapsack, + double& rhsMixedKnapsack, double& sStar, + CoinPackedVector& contVariablesInS ) const; + + // c-MIR separation heuristic + bool cMirSeparation ( const OsiSolverInterface& si, + const CoinPackedMatrix& matrixByRow, + const CoinPackedVector& rowAggregated, + const int* listRowsAggregated, + const char* sense, const double* RHS, + //const double* coefByRow, + //const int* colInds, const int* rowStarts, + //const int* rowLengths, + const double* xlp, const double sStar, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedVector& mixedKnapsack, + const double& rhsMixedKnapsack, + const CoinPackedVector& contVariablesInS, + OsiRowCut& flowCut ) const; + + // function to create one c-MIR inequality + void cMirInequality( const int numInt, + const double delta, + const double numeratorBeta, + const int *knapsackIndices, + const double* knapsackElements, + const double* xlp, + const double sStar, + const double* colUpperBound, + const std::set<int>& setC, + CoinPackedVector& cMIR, + double& rhscMIR, + double& sCoef, + double& violation) const; + + // function to compute G + inline double functionG( const double d, const double f ) const; + + // function to print statistics (used only in debug mode) + void printStats( + std::ofstream & fout, + const bool hasCut, + const OsiSolverInterface& si, + const CoinPackedVector& rowAggregated, + const double& rhsAggregated, const double* xlp, + const double* xlpExtra, + const int* listRowsAggregated, + const int* listColsSelected, + const int level, + const double* colUpperBound, + const double* colLowerBound ) const; + + +private: + //--------------------------------------------------------------------------- + // Private member data + + // Maximum number of rows to aggregate + int MAXAGGR_; + // Flag that indicates if an aggregated row is also multiplied by -1 + bool MULTIPLY_; + // The criterion to use in the bound substitution + int CRITERION_; + // Tolerance used for numerical purposes + double EPSILON_; + /// There is no variable upper bound or variable lower bound defined + int UNDEFINED_; + // If violation of a cut is greater that this number, the cut is accepted + double TOLERANCE_; + /** Controls the preprocessing of the matrix to identify rows suitable for + cut generation.<UL> + <LI> -1: preprocess according to solver settings; + <LI> 0: Do preprocessing only if it has not yet been done; + <LI> 1: Do preprocessing. + </UL> + Default value: -1 **/ + int doPreproc_; + // The number of rows of the problem. + int numRows_; + // The number columns of the problem. + int numCols_; + // Indicates whether preprocessing has been done. + bool doneInitPre_; + // The array of CglMixIntRoundVUBs. + CglMixIntRoundVUB* vubs_; + // The array of CglMixIntRoundVLBs. + CglMixIntRoundVLB* vlbs_; + // Array with the row types of the rows in the model. + RowType* rowTypes_; + // The indices of the rows of the initial matrix + int* indRows_; + // The number of rows of type ROW_MIX + int numRowMix_; + // The indices of the rows of type ROW_MIX + int* indRowMix_; + // The number of rows of type ROW_CONT + int numRowCont_; + // The indices of the rows of type ROW_CONT + int* indRowCont_; + // The number of rows of type ROW_INT + int numRowInt_; + // The indices of the rows of type ROW_INT + int* indRowInt_; + // The number of rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int numRowContVB_; + // The indices of the rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int* indRowContVB_; + // Sense of rows (modified if ranges) + char * sense_; + // RHS of rows (modified if ranges) + double * RHS_; + +}; + +//############################################################################# +// A function that tests the methods in the CglMixedIntegerRounding class. The +// only reason for it not to be a member method is that this way it doesn't +// have to be compiled into the library. And that's a gain, because the +// library should be compiled with optimization on, but this method should be +// compiled with debugging. +void CglMixedIntegerRoundingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + +#endif diff --git a/thirdparty/linux/include/coin/CglMixedIntegerRounding2.hpp b/thirdparty/linux/include/coin/CglMixedIntegerRounding2.hpp new file mode 100644 index 0000000..abf2530 --- /dev/null +++ b/thirdparty/linux/include/coin/CglMixedIntegerRounding2.hpp @@ -0,0 +1,427 @@ +// LAST EDIT: +//----------------------------------------------------------------------------- +// name: Mixed Integer Rounding Cut Generator +// authors: Joao Goncalves (jog7@lehigh.edu) +// Laszlo Ladanyi (ladanyi@us.ibm.com) +// date: August 11, 2004 +//----------------------------------------------------------------------------- +// Copyright (C) 2004, International Business Machines Corporation and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglMixedIntegerRounding2_H +#define CglMixedIntegerRounding2_H + +#include <iostream> +#include <fstream> +//#include <vector> + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" +#include "CoinIndexedVector.hpp" + +//============================================================================= + +#ifndef CGL_DEBUG +#define CGL_DEBUG 0 +#endif + +//============================================================================= + +// Class to store variable upper bounds (VUB) +class CglMixIntRoundVUB2 +{ + // Variable upper bounds have the form x_j <= a y_j, where x_j is + // a continuous variable and y_j is an integer variable + +protected: + int var_; // The index of y_j + double val_; // The value of a + +public: + // Default constructor + CglMixIntRoundVUB2() : var_(-1), val_(-1) {} + + // Copy constructor + CglMixIntRoundVUB2(const CglMixIntRoundVUB2& source) { + var_ = source.var_; + val_ = source.val_; + } + + // Assignment operator + CglMixIntRoundVUB2& operator=(const CglMixIntRoundVUB2& rhs) { + if (this != &rhs) { + var_ = rhs.var_; + val_ = rhs.val_; + } + return *this; + } + + // Destructor + ~CglMixIntRoundVUB2() {} + + // Query and set functions + int getVar() const { return var_; } + double getVal() const { return val_; } + void setVar(const int v) { var_ = v; } + void setVal(const double v) { val_ = v; } +}; + +//============================================================================= + +// Class to store variable lower bounds (VLB). +// It is the same as the class to store variable upper bounds +typedef CglMixIntRoundVUB2 CglMixIntRoundVLB2; + +//============================================================================= + +/** Mixed Integer Rounding Cut Generator Class */ + +// Reference: +// Hugues Marchand and Laurence A. Wolsey +// Aggregation and Mixed Integer Rounding to Solve MIPs +// Operations Research, 49(3), May-June 2001. +// Also published as CORE Dicusion Paper 9839, June 1998. + +class CglMixedIntegerRounding2 : public CglCutGenerator { + + friend void CglMixedIntegerRounding2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +private: + //--------------------------------------------------------------------------- + // Enumeration constants that describe the various types of rows + enum RowType { + // The row type of this row is NOT defined yet. + ROW_UNDEFINED, + /** After the row is flipped to 'L', the row has exactly two variables: + one is negative binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARUB, + /** After the row is flipped to 'L', the row has exactly two variables: + one is positive binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARLB, + /** The row sense is 'E', the row has exactly two variables: + one is binary and the other is a continous, and the RHS is zero.*/ + ROW_VAREQ, + // The row contains continuous and integer variables; + // the total number of variables is at least 2 + ROW_MIX, + // The row contains only continuous variables + ROW_CONT, + // The row contains only integer variables + ROW_INT, + // The row contains other types of rows + ROW_OTHER + }; + + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Rounding cuts for the model data + contained in si. The generated cuts are inserted + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + //--------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglMixedIntegerRounding2 (); + + /// Alternate Constructor + CglMixedIntegerRounding2 (const int maxaggr, + const bool multiply, + const int criterion, + const int preproc = -1); + + /// Copy constructor + CglMixedIntegerRounding2 ( + const CglMixedIntegerRounding2 &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglMixedIntegerRounding2 & + operator=( + const CglMixedIntegerRounding2& rhs); + + /// Destructor + virtual + ~CglMixedIntegerRounding2 (); + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + + //--------------------------------------------------------------------------- + /**@name Set and get methods */ + //@{ + /// Set MAXAGGR_ + inline void setMAXAGGR_ (int maxaggr) { + if (maxaggr > 0) { + MAXAGGR_ = maxaggr; + } + else { + throw CoinError("Unallowable value. maxaggr must be > 0", + "gutsOfConstruct","CglMixedIntegerRounding2"); + } + } + + /// Get MAXAGGR_ + inline int getMAXAGGR_ () const { return MAXAGGR_; } + + /// Set MULTIPLY_ + inline void setMULTIPLY_ (bool multiply) { MULTIPLY_ = multiply; } + + /// Get MULTIPLY_ + inline bool getMULTIPLY_ () const { return MULTIPLY_; } + + /// Set CRITERION_ + inline void setCRITERION_ (int criterion) { + if ((criterion >= 1) && (criterion <= 3)) { + CRITERION_ = criterion; + } + else { + throw CoinError("Unallowable value. criterion must be 1, 2 or 3", + "gutsOfConstruct","CglMixedIntegerRounding2"); + } + } + + /// Get CRITERION_ + inline int getCRITERION_ () const { return CRITERION_; } + + /// Set doPreproc + void setDoPreproc(int value); + /// Get doPreproc + bool getDoPreproc() const; + //@} + +private: + //-------------------------------------------------------------------------- + // Private member methods + + // Construct + void gutsOfConstruct ( const int maxaggr, + const bool multiply, + const int criterion, + const int preproc); + + // Delete + void gutsOfDelete(); + + // Copy + void gutsOfCopy (const CglMixedIntegerRounding2& rhs); + + // Do preprocessing. + // It determines the type of each row. It also identifies the variable + // upper bounds and variable lower bounds. + // It may change sense and RHS for ranged rows + void mixIntRoundPreprocess(const OsiSolverInterface& si); + + // Determine the type of a given row. + RowType determineRowType(//const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, const char sense, + const double rhs) const; + + // Generate MIR cuts + void generateMirCuts( const OsiSolverInterface& si, + const double* xlp, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedMatrix& matrixByRow, + const double* LHS, + //const double* coefByRow, + //const int* colInds, + //const int* rowStarts, + //const CoinPackedMatrix& matrixByCol, + const double* coefByCol, + const int* rowInds, + const int* colStarts, + OsiCuts& cs ) const; + + // Copy row selected to CoinIndexedVector + void copyRowSelected( const int iAggregate, + const int rowSelected, + CoinIndexedVector& setRowsAggregated, + int* listRowsAggregated, + double* xlpExtra, + const char sen, + const double rhs, + const double lhs, + const CoinPackedMatrix& matrixByRow, + CoinIndexedVector& rowToAggregate, + double& rhsToAggregate) const; + + // Select a row to aggregate + bool selectRowToAggregate( //const OsiSolverInterface& si, + const CoinIndexedVector& rowAggregated, + const double* colUpperBound, + const double* colLowerBound, + const CoinIndexedVector& setRowsAggregated, + const double* xlp, const double* coefByCol, + const int* rowInds, const int* colStarts, + int& rowSelected, + int& colSelected ) const; + + // Aggregation heuristic. + // Combines one or more rows of the original matrix + void aggregateRow( const int colSelected, + CoinIndexedVector& rowToAggregate, double rhs, + CoinIndexedVector& rowAggregated, + double& rhsAggregated ) const; + + // Choose the bound substitution based on the criteria defined by the user + inline bool isLowerSubst(const double inf, + const double aj, + const double xlp, + const double LB, + const double UB) const; + + // Bound substitution heuristic + bool boundSubstitution( const OsiSolverInterface& si, + const CoinIndexedVector& rowAggregated, + const double* xlp, + const double* xlpExtra, + const double* colUpperBound, + const double* colLowerBound, + CoinIndexedVector& mixedKnapsack, + double& rhsMixedKnapsack, double& sStar, + CoinIndexedVector& contVariablesInS ) const; + + // c-MIR separation heuristic + bool cMirSeparation ( const OsiSolverInterface& si, + const CoinPackedMatrix& matrixByRow, + const CoinIndexedVector& rowAggregated, + const int* listRowsAggregated, + const char* sense, const double* RHS, + //const double* coefByRow, + //const int* colInds, const int* rowStarts, + const double* xlp, const double sStar, + const double* colUpperBound, + const double* colLowerBound, + const CoinIndexedVector& mixedKnapsack, + const double& rhsMixedKnapsack, + const CoinIndexedVector& contVariablesInS, + CoinIndexedVector * workVector, + OsiRowCut& flowCut ) const; + + // function to create one c-MIR inequality + void cMirInequality( const int numInt, + const double delta, + const double numeratorBeta, + const int *knapsackIndices, + const double* knapsackElements, + const double* xlp, + const double sStar, + const double* colUpperBound, + const CoinIndexedVector& setC, + CoinIndexedVector& cMIR, + double& rhscMIR, + double& sCoef, + double& violation) const; + + // function to compute G + inline double functionG( const double d, const double f ) const; + + // function to print statistics (used only in debug mode) + void printStats( + std::ofstream & fout, + const bool hasCut, + const OsiSolverInterface& si, + const CoinIndexedVector& rowAggregated, + const double& rhsAggregated, const double* xlp, + const double* xlpExtra, + const int* listRowsAggregated, + const int* listColsSelected, + const int level, + const double* colUpperBound, + const double* colLowerBound ) const; + + +private: + //--------------------------------------------------------------------------- + // Private member data + + // Maximum number of rows to aggregate + int MAXAGGR_; + // Flag that indicates if an aggregated row is also multiplied by -1 + bool MULTIPLY_; + // The criterion to use in the bound substitution + int CRITERION_; + // Tolerance used for numerical purposes + double EPSILON_; + /// There is no variable upper bound or variable lower bound defined + int UNDEFINED_; + // If violation of a cut is greater that this number, the cut is accepted + double TOLERANCE_; + /** Controls the preprocessing of the matrix to identify rows suitable for + cut generation.<UL> + <LI> -1: preprocess according to solver settings; + <LI> 0: Do preprocessing only if it has not yet been done; + <LI> 1: Do preprocessing. + </UL> + Default value: -1 **/ + int doPreproc_; + // The number of rows of the problem. + int numRows_; + // The number columns of the problem. + int numCols_; + // Indicates whether preprocessing has been done. + bool doneInitPre_; + // The array of CglMixIntRoundVUB2s. + CglMixIntRoundVUB2* vubs_; + // The array of CglMixIntRoundVLB2s. + CglMixIntRoundVLB2* vlbs_; + // Array with the row types of the rows in the model. + RowType* rowTypes_; + // The indices of the rows of the initial matrix + int* indRows_; + // The number of rows of type ROW_MIX + int numRowMix_; + // The indices of the rows of type ROW_MIX + int* indRowMix_; + // The number of rows of type ROW_CONT + int numRowCont_; + // The indices of the rows of type ROW_CONT + int* indRowCont_; + // The number of rows of type ROW_INT + int numRowInt_; + // The indices of the rows of type ROW_INT + int* indRowInt_; + // The number of rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int numRowContVB_; + // The indices of the rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int* indRowContVB_; + // If integer - for speed + char * integerType_; + // Sense of rows (modified if ranges) + char * sense_; + // RHS of rows (modified if ranges) + double * RHS_; + +}; + +//############################################################################# +// A function that tests the methods in the CglMixedIntegerRounding2 class. The +// only reason for it not to be a member method is that this way it doesn't +// have to be compiled into the library. And that's a gain, because the +// library should be compiled with optimization on, but this method should be +// compiled with debugging. +void CglMixedIntegerRounding2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + +#endif diff --git a/thirdparty/linux/include/coin/CglOddHole.hpp b/thirdparty/linux/include/coin/CglOddHole.hpp new file mode 100644 index 0000000..3b80caa --- /dev/null +++ b/thirdparty/linux/include/coin/CglOddHole.hpp @@ -0,0 +1,160 @@ +// $Id: CglOddHole.hpp 1119 2013-04-06 20:24:18Z stefan $ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglOddHole_H +#define CglOddHole_H + +#include <string> + +#include "CglCutGenerator.hpp" + +/** Odd Hole Cut Generator Class */ +class CglOddHole : public CglCutGenerator { + friend void CglOddHoleUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + + /**@name Generate Cuts */ + //@{ + /** Generate odd hole cuts for the model of the solver interface, si. + This looks at all rows of type sum x(i) <= 1 (or == 1) (x 0-1) + and sees if there is an odd cycle cut. See Grotschel, Lovasz + and Schrijver (1988) for method. + This is then lifted by using the corresponding Chvatal cut i.e. + Take all rows in cycle and add them together. RHS will be odd so + weaken all odd coefficients so 1.0 goes to 0.0 etc - then + constraint is sum even(j)*x(j) <= odd which can be replaced by + sum (even(j)/2)*x(j) <= (odd-1.0)/2. + A similar cut can be generated for sum x(i) >= 1. + + Insert the generated cuts into OsiCut, cs. + + This is only done for rows with unsatisfied 0-1 variables. If there + are many of these it will be slow. Improvements would do a + randomized subset and also speed up shortest path algorithm used. + + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Create Row List */ + //@{ + /// Create a list of rows which might yield cuts + /// this is to speed up process + /// The possible parameter is a list to cut down search + void createRowList( const OsiSolverInterface & si, + const int * possible=NULL); + /// This version passes in a list - 1 marks possible + void createRowList(int numberRows, const int * whichRow); + //@} + + /**@name Create Clique List */ + //@{ + /// Create a list of extra row cliques which may not be in matrix + /// At present these are classical cliques + void createCliqueList(int numberCliques, const int * cliqueStart, + const int * cliqueMember); + //@} + + /**@name Number Possibilities */ + //@{ + /// Returns how many rows might give odd hole cuts + int numberPossible(); + //@} + /**@name Gets and Sets */ + //@{ + /// Minimum violation + double getMinimumViolation() const; + void setMinimumViolation(double value); + /// Minimum violation per entry + double getMinimumViolationPer() const; + void setMinimumViolationPer(double value); + /// Maximum number of entries in a cut + int getMaximumEntries() const; + void setMaximumEntries(int value); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglOddHole (); + + /// Copy constructor + CglOddHole ( + const CglOddHole &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglOddHole & + operator=( + const CglOddHole& rhs); + + /// Destructor + virtual + ~CglOddHole (); + + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +private: + + // Private member methods + + + /**@name Private methods */ + //@{ + /// Generate cuts from matrix copy and solution + /// If packed true then <=1 rows, otherwise >=1 rows. + void generateCuts(const OsiRowCutDebugger * debugger, + const CoinPackedMatrix & rowCopy, + const double * solution, const double * dj, + OsiCuts & cs, const int * suitableRow, + const int * fixedColumn,const CglTreeInfo info, + bool packed); + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// list of suitableRows + int * suitableRows_; + /// start of each clique + int * startClique_; + /// clique members + int * member_; + /// epsilon + double epsilon_; + /// 1-epsilon + double onetol_; + /// Minimum violation + double minimumViolation_; + /// Minimum violation per entry + double minimumViolationPer_; + /// Maximum number of entries in a cut + int maximumEntries_; + /// number of rows when suitability tested + int numberRows_; + /// number of cliques + int numberCliques_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglOddHole class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglOddHoleUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/thirdparty/linux/include/coin/CglParam.hpp b/thirdparty/linux/include/coin/CglParam.hpp new file mode 100644 index 0000000..4463ef5 --- /dev/null +++ b/thirdparty/linux/include/coin/CglParam.hpp @@ -0,0 +1,93 @@ +// Name: CglParam.hpp +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 11/24/06 +// +// $Id: CglParam.hpp 1122 2013-04-06 20:39:53Z stefan $ +// +// This code is licensed under the terms of the Eclipse Public License (EPL). +//----------------------------------------------------------------------------- +// Copyright (C) 2006, Francois Margot and others. All Rights Reserved. + +#ifndef CglParam_H +#define CglParam_H +#include "CglConfig.h" +#include "CoinFinite.hpp" +/** Class collecting parameters for all cut generators. Each generator + may have a derived class to add parameters. Each generator might + also set different default values for the parameters in CglParam. */ + +class CglParam { + +public: + + /**@name Public Set/get methods */ + //@{ + + /** Set INFINIT */ + virtual void setINFINIT(const double inf); + /** Get value of INFINIT */ + inline double getINFINIT() const {return INFINIT;} + + /** Set EPS */ + virtual void setEPS(const double eps); + /** Get value of EPS */ + inline double getEPS() const {return EPS;} + + /** Set EPS_COEFF */ + virtual void setEPS_COEFF(const double eps_c); + /** Get value of EPS_COEFF */ + inline double getEPS_COEFF() const {return EPS_COEFF;} + + /** Set MAX_SUPPORT */ + virtual void setMAX_SUPPORT(const int max_s); + /** Get value of MAX_SUPPORT */ + inline int getMAX_SUPPORT() const {return MAX_SUPPORT;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglParam(const double inf = COIN_DBL_MAX, const double eps = 1e-6, + const double eps_c = 1e-5, const int max_s = COIN_INT_MAX); + + /// Copy constructor + CglParam(const CglParam&); + + /// Clone + virtual CglParam* clone() const; + + /// Assignment operator + CglParam& operator=(const CglParam &rhs); + + /// Destructor + virtual ~CglParam(); + //@} + +protected: + + // Protected member data + + /**@name Protected member data */ + + //@{ + // Value for infinity. Default: COIN_DBL_MAX. + double INFINIT; + + // EPSILON for double comparisons. Default: 1e-6. + double EPS; + + // Returned cuts do not have coefficients with absolute value smaller + // than EPS_COEFF. Default: 1e-5. + double EPS_COEFF; + + /** Maximum number of non zero coefficients in a generated cut; + Default: COIN_INT_MAX */ + int MAX_SUPPORT; + //@} + +}; + +#endif diff --git a/thirdparty/linux/include/coin/CglPreProcess.hpp b/thirdparty/linux/include/coin/CglPreProcess.hpp new file mode 100644 index 0000000..65c04ca --- /dev/null +++ b/thirdparty/linux/include/coin/CglPreProcess.hpp @@ -0,0 +1,492 @@ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglPreProcess_H +#define CglPreProcess_H + +#include <string> +#include <vector> + +#include "CoinMessageHandler.hpp" +#include "OsiSolverInterface.hpp" +#include "CglStored.hpp" +#include "OsiPresolve.hpp" +#include "CglCutGenerator.hpp" + +//############################################################################# + +/** Class for preProcessing and postProcessing. + + While cuts can be added at any time in the tree, some cuts are actually just + stronger versions of existing constraints. In this case they can replace those + constraints rather than being added as new constraints. This is awkward in the + tree but reasonable at the root node. + + This is a general process class which uses other cut generators to strengthen + constraints, establish that constraints are redundant, fix variables and + find relationships such as x + y == 1. + + Presolve will also be done. + + If row names existed they may be replaced by R0000000 etc + +*/ + +class CglPreProcess { + +public: + + ///@name Main methods + //@{ + /** preProcess problem - returning new problem. + If makeEquality true then <= cliques converted to ==. + Presolve will be done numberPasses times. + + Returns NULL if infeasible + + This version uses default strategy. For more control copy and edit + code from this function i.e. call preProcessNonDefault + */ + OsiSolverInterface * preProcess(OsiSolverInterface & model, + bool makeEquality=false, int numberPasses=5); + /** preProcess problem - returning new problem. + If makeEquality true then <= cliques converted to ==. + Presolve will be done numberPasses times. + + Returns NULL if infeasible + + This version assumes user has added cut generators to CglPreProcess object + before calling it. As an example use coding in preProcess + If makeEquality is 1 add slacks to get cliques, + if 2 add slacks to get sos (but only if looks plausible) and keep sos info + */ + OsiSolverInterface * preProcessNonDefault(OsiSolverInterface & model, + int makeEquality=0, int numberPasses=5, + int tuning=0); + /// Creates solution in original model + void postProcess(OsiSolverInterface &model + ,bool deleteStuff=true); + /** Tightens primal bounds to make dual and branch and cutfaster. Unless + fixed or integral, bounds are slightly looser than they could be. + Returns non-zero if problem infeasible + Fudge for branch and bound - put bounds on columns of factor * + largest value (at continuous) - should improve stability + in branch and bound on infeasible branches (0.0 is off) + */ + int tightenPrimalBounds(OsiSolverInterface & model,double factor=0.0); + /** Fix some of problem - returning new problem. + Uses reduced costs. + Optional signed character array + 1 always keep, -1 always discard, 0 use djs + + */ + OsiSolverInterface * someFixed(OsiSolverInterface & model, + double fractionToKeep=0.25, + bool fixContinuousAsWell=false, + char * keep=NULL) const; + /** Replace cliques by more maximal cliques + Returns NULL if rows not reduced by greater than cliquesNeeded*rows + + */ + OsiSolverInterface * cliqueIt(OsiSolverInterface & model, + double cliquesNeeded=0.0) const; + /// If we have a cutoff - fix variables + int reducedCostFix(OsiSolverInterface & model); + //@} + + //--------------------------------------------------------------------------- + + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false if the value of the parameter is out of range. + + The get methods return the value of the parameter. + + */ + //@{ + /** Set cutoff bound on the objective function. + + When using strict comparison, the bound is adjusted by a tolerance to + avoid accidentally cutting off the optimal solution. + */ + void setCutoff(double value) ; + + /// Get the cutoff bound on the objective function - always as minimize + double getCutoff() const; + /// The original solver associated with this model. + inline OsiSolverInterface * originalModel() const + { return originalModel_;} + /// Solver after making clique equalities (may == original) + inline OsiSolverInterface * startModel() const + { return startModel_;} + /// Copies of solver at various stages after presolve + inline OsiSolverInterface * modelAtPass(int iPass) const + { if (iPass>=0&&iPass<numberSolvers_) return model_[iPass]; else return NULL;} + /// Copies of solver at various stages after presolve after modifications + inline OsiSolverInterface * modifiedModel(int iPass) const + { if (iPass>=0&&iPass<numberSolvers_) return modifiedModel_[iPass]; else return NULL;} + /// Matching presolve information + inline OsiPresolve * presolve(int iPass) const + { if (iPass>=0&&iPass<numberSolvers_) return presolve_[iPass]; else return NULL;} + /** Return a pointer to the original columns (with possible clique slacks) + MUST be called before postProcess otherwise you just get 0,1,2.. */ + const int * originalColumns(); + /** Return a pointer to the original rows + MUST be called before postProcess otherwise you just get 0,1,2.. */ + const int * originalRows(); + /// Number of SOS if found + inline int numberSOS() const + { return numberSOS_;} + /// Type of each SOS + inline const int * typeSOS() const + { return typeSOS_;} + /// Start of each SOS + inline const int * startSOS() const + { return startSOS_;} + /// Columns in SOS + inline const int * whichSOS() const + { return whichSOS_;} + /// Weights for each SOS column + inline const double * weightSOS() const + { return weightSOS_;} + /// Pass in prohibited columns + void passInProhibited(const char * prohibited,int numberColumns); + /// Updated prohibited columns + inline const char * prohibited() + { return prohibited_;} + /// Number of iterations PreProcessing + inline int numberIterationsPre() const + { return numberIterationsPre_;} + /// Number of iterations PostProcessing + inline int numberIterationsPost() const + { return numberIterationsPost_;} + /** Pass in row types + 0 normal + 1 cut rows - will be dropped if remain in + At end of preprocess cut rows will be dropped + and put into cuts + */ + void passInRowTypes(const char * rowTypes,int numberRows); + /** Updated row types - may be NULL + Carried around and corresponds to existing rows + -1 added by preprocess e.g. x+y=1 + 0 normal + 1 cut rows - can be dropped if wanted + */ + inline const char * rowTypes() + { return rowType_;} + /// Return cuts from dropped rows + inline const CglStored & cuts() const + { return cuts_;} + /// Return pointer to cuts from dropped rows + inline const CglStored * cutsPointer() const + { return &cuts_;} + /// Update prohibited and rowType + void update(const OsiPresolve * pinfo,const OsiSolverInterface * solver); + /// Set options + inline void setOptions(int value) + { options_=value;} + //@} + + ///@name Cut generator methods + //@{ + /// Get the number of cut generators + inline int numberCutGenerators() const + { return numberCutGenerators_;} + /// Get the list of cut generators + inline CglCutGenerator ** cutGenerators() const + { return generator_;} + ///Get the specified cut generator + inline CglCutGenerator * cutGenerator(int i) const + { return generator_[i];} + /** Add one generator - up to user to delete generators. + */ + void addCutGenerator(CglCutGenerator * generator); +//@} + + /**@name Setting/Accessing application data */ + //@{ + /** Set application data. + + This is a pointer that the application can store into and + retrieve. + This field is available for the application to optionally + define and use. + */ + void setApplicationData (void * appData); + + /// Get application data + void * getApplicationData() const; + //@} + + //--------------------------------------------------------------------------- + + /**@name Message handling */ + //@{ + /// Pass in Message handler (not deleted at end) + void passInMessageHandler(CoinMessageHandler * handler); + /// Set language + void newLanguage(CoinMessages::Language language); + inline void setLanguage(CoinMessages::Language language) + {newLanguage(language);} + /// Return handler + inline CoinMessageHandler * messageHandler() const + {return handler_;} + /// Return messages + inline CoinMessages messages() + {return messages_;} + /// Return pointer to messages + inline CoinMessages * messagesPointer() + {return &messages_;} + //@} + //--------------------------------------------------------------------------- + + + ///@name Constructors and destructors etc + //@{ + /// Constructor + CglPreProcess(); + + /// Copy constructor . + CglPreProcess(const CglPreProcess & rhs); + + /// Assignment operator + CglPreProcess & operator=(const CglPreProcess& rhs); + + /// Destructor + ~CglPreProcess (); + + /// Clears out as much as possible + void gutsOfDestructor(); + //@} +private: + + ///@name private methods + //@{ + /** Return model with useful modifications. + If constraints true then adds any x+y=1 or x-y=0 constraints + If NULL infeasible + */ + OsiSolverInterface * modified(OsiSolverInterface * model, + bool constraints, + int & numberChanges, + int iBigPass, + int numberPasses); + /// create original columns and rows + void createOriginalIndices(); + /// Make continuous variables integer + void makeInteger(); + //@} + +//--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@{ + + /// The original solver associated with this model. + OsiSolverInterface * originalModel_; + /// Solver after making clique equalities (may == original) + OsiSolverInterface * startModel_; + /// Number of solvers at various stages + int numberSolvers_; + /// Copies of solver at various stages after presolve + OsiSolverInterface ** model_; + /// Copies of solver at various stages after presolve after modifications + OsiSolverInterface ** modifiedModel_; + /// Matching presolve information + OsiPresolve ** presolve_; + + /// Message handler + CoinMessageHandler * handler_; + + /** Flag to say if handler_ is the default handler. + + The default handler is deleted when the model is deleted. Other + handlers (supplied by the client) will not be deleted. + */ + bool defaultHandler_; + + /// Cgl messages + CoinMessages messages_; + + /// Pointer to user-defined data structure + void * appData_; + /// Original column numbers + int * originalColumn_; + /// Original row numbers + int * originalRow_; + /// Number of cut generators + int numberCutGenerators_; + /// Cut generators + CglCutGenerator ** generator_; + /// Number of SOS if found + int numberSOS_; + /// Type of each SOS + int * typeSOS_; + /// Start of each SOS + int * startSOS_; + /// Columns in SOS + int * whichSOS_; + /// Weights for each SOS column + double * weightSOS_; + /// Number of columns in original prohibition set + int numberProhibited_; + /// Number of iterations done in PreProcessing + int numberIterationsPre_; + /// Number of iterations done in PostProcessing + int numberIterationsPost_; + /// Columns which should not be presolved e.g. SOS + char * prohibited_; + /// Number of rows in original row types + int numberRowType_; + /** Options + 1 - original model had integer bounds before tightening + 2 - don't do probing + 4 - don't do duplicate rows + 8 - don't do cliques + 16 - some heavy probing options + 64 - very heavy probing + */ + int options_; + /** Row types (may be NULL) + Carried around and corresponds to existing rows + -1 added by preprocess e.g. x+y=1 + 0 normal + 1 cut rows - can be dropped if wanted + */ + char * rowType_; + /// Cuts from dropped rows + CglStored cuts_; + //@} +}; +/// For Bron-Kerbosch +class CglBK { + +public: + + ///@name Main methods + //@{ + /// For recursive Bron-Kerbosch + void bronKerbosch(); + /// Creates strengthened smaller model + OsiSolverInterface * newSolver(const OsiSolverInterface & model); + //@} + + //--------------------------------------------------------------------------- + + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false if the value of the parameter is out of range. + + The get methods return the value of the parameter. + + */ + //@{ + //@} + + //--------------------------------------------------------------------------- + + + ///@name Constructors and destructors etc + //@{ + /// Default constructor + CglBK(); + + /// Useful constructor + CglBK(const OsiSolverInterface & model, const char * rowType, + int numberElements); + + /// Copy constructor . + CglBK(const CglBK & rhs); + + /// Assignment operator + CglBK & operator=(const CglBK& rhs); + + /// Destructor + ~CglBK (); + + //@} + +//--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@{ + /// Current candidates (created at each level) + int * candidates_; + /// Array to mark stuff + char * mark_; + /// Starts for graph (numberPossible+1) + int * start_; + /// Other column/node + int * otherColumn_; + /// Original row (in parallel with otherColumn_) + int * originalRow_; + /// How many times each original row dominated + int * dominated_; + /// Clique entries + CoinPackedMatrix * cliqueMatrix_; + /// points to row types + const char * rowType_; + /// Number of original columns + int numberColumns_; + /// Number of original rows + int numberRows_; + /// Number possible + int numberPossible_; + /// Current number of candidates + int numberCandidates_; + /// First not (stored backwards from numberPossible_) + int firstNot_; + /// Current number in clique + int numberIn_; + /// For acceleration + int left_; + int lastColumn_; + //@} +}; +/** + Only store unique row cuts +*/ +// for hashing +typedef struct { + int index, next; +} CglHashLink; +class OsiRowCut; +class CglUniqueRowCuts { +public: + + CglUniqueRowCuts(int initialMaxSize=0, int hashMultiplier=4 ); + ~CglUniqueRowCuts(); + CglUniqueRowCuts(const CglUniqueRowCuts& rhs); + CglUniqueRowCuts& operator=(const CglUniqueRowCuts& rhs); + inline OsiRowCut * cut(int sequence) const + { return rowCut_[sequence];} + inline int numberCuts() const + { return numberCuts_;} + inline int sizeRowCuts() const + { return numberCuts_;} + inline OsiRowCut * rowCutPtr(int sequence) + { return rowCut_[sequence];} + void eraseRowCut(int sequence); + // insert cut + inline void insert(const OsiRowCut & cut) + { insertIfNotDuplicate(cut);} + // Return 0 if added, 1 if not + int insertIfNotDuplicate(const OsiRowCut & cut); + // Add in cuts as normal cuts (and delete) + void addCuts(OsiCuts & cs); +private: + OsiRowCut ** rowCut_; + /// Hash table + CglHashLink *hash_; + int size_; + int hashMultiplier_; + int numberCuts_; + int lastHash_; +}; +#endif diff --git a/thirdparty/linux/include/coin/CglProbing.hpp b/thirdparty/linux/include/coin/CglProbing.hpp new file mode 100644 index 0000000..5ca8996 --- /dev/null +++ b/thirdparty/linux/include/coin/CglProbing.hpp @@ -0,0 +1,543 @@ +// $Id: CglProbing.hpp 1201 2014-03-07 17:24:04Z 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). + +#ifndef CglProbing_H +#define CglProbing_H + +#include <string> + +#include "CglCutGenerator.hpp" + /** Only useful type of disaggregation is most normal + For now just done for 0-1 variables + Can be used for building cliques + */ + typedef struct { + //unsigned int zeroOne:1; // nonzero if affected variable is 0-1 + //unsigned int whenAtUB:1; // nonzero if fixing happens when this variable at 1 + //unsigned int affectedToUB:1; // nonzero if affected variable fixed to UB + //unsigned int affected:29; // If 0-1 then 0-1 sequence, otherwise true + unsigned int affected; + } disaggregationAction; + +/** Probing Cut Generator Class */ +class CglProbing : public CglCutGenerator { + friend void CglProbingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + + /**@name Generate Cuts */ + //@{ + /** Generate probing/disaggregation cuts for the model of the + solver interface, si. + + This is a simplification of probing ideas put into OSL about + ten years ago. The only known documentation is a copy of a + talk handout - we think Robin Lougee-Heimer has a copy! + + For selected integer variables (e.g. unsatisfied ones) the effect of + setting them up or down is investigated. Setting a variable up + may in turn set other variables (continuous as well as integer). + There are various possible results: + + 1) It is shown that problem is infeasible (this may also be + because objective function or reduced costs show worse than + best solution). If the other way is feasible we can generate + a column cut (and continue probing), if not feasible we can + say problem infeasible. + + 2) If both ways are feasible, it can happen that x to 0 implies y to 1 + ** and x to 1 implies y to 1 (again a column cut). More common + is that x to 0 implies y to 1 and x to 1 implies y to 0 so we could + substitute for y which might lead later to more powerful cuts. + ** This is not done in this code as there is no mechanism for + returning information. + + 3) When x to 1 a constraint went slack by c. We can tighten the + constraint ax + .... <= b (where a may be zero) to + (a+c)x + .... <= b. If this cut is violated then it is + generated. + + 4) Similarly we can generate implied disaggregation cuts + + Note - differences to cuts in OSL. + + a) OSL had structures intended to make this faster. + b) The "chaining" in 2) was done + c) Row cuts modified original constraint rather than adding cut + b) This code can cope with general integer variables. + + Insert the generated cuts into OsiCut, cs. + + If a "snapshot" of a matrix exists then this will be used. + Presumably this will give global cuts and will be faster. + No check is done to see if cuts will be global. + + Otherwise use current matrix. + + Both row cuts and column cuts may be returned + + The mode options are: + 0) Only unsatisfied integer variables will be looked at. + If no information exists for that variable then + probing will be done so as a by-product you "may" get a fixing + or infeasibility. This will be fast and is only available + if a snapshot exists (otherwise as 1). + The bounds in the snapshot are the ones used. + 1) Look at unsatisfied integer variables, using current bounds. + Probing will be done on all looked at. + 2) Look at all integer variables, using current bounds. + Probing will be done on all + + ** If generateCutsAndModify is used then new relaxed + row bounds and tightened column bounds are generated + Returns number of infeasibilities + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + int generateCutsAndModify( const OsiSolverInterface & si, OsiCuts & cs, + CglTreeInfo * info); + //@} + + /**@name snapshot etc */ + //@{ + /** Create a copy of matrix which is to be used + this is to speed up process and to give global cuts + Can give an array with 1 set to select, 0 to ignore + column bounds are tightened + If array given then values of 1 will be set to 0 if redundant. + Objective may be added as constraint + Returns 1 if infeasible otherwise 0 + */ + int snapshot ( const OsiSolverInterface & si, + char * possible=NULL, + bool withObjective=true); + /// Deletes snapshot + void deleteSnapshot ( ); + /** Creates cliques for use by probing. + Only cliques >= minimumSize and < maximumSize created + Can also try and extend cliques as a result of probing (root node). + Returns number of cliques found. + */ + int createCliques( OsiSolverInterface & si, + int minimumSize=2, int maximumSize=100); + /// Delete all clique information + void deleteCliques(); + /** Create a fake model by adding cliques + if type&4 then delete rest of model first, + if 1 then add proper cliques, 2 add fake cliques */ + OsiSolverInterface * cliqueModel(const OsiSolverInterface * model, + int type); + //@} + + /**@name Get tighter column bounds */ + //@{ + /// Lower + const double * tightLower() const; + /// Upper + const double * tightUpper() const; + /// Array which says tighten continuous + const char * tightenBounds() const + { return tightenBounds_;} + //@} + + /**@name Get possible freed up row bounds - only valid after mode==3 */ + //@{ + /// Lower + const double * relaxedRowLower() const; + /// Upper + const double * relaxedRowUpper() const; + //@} + + /**@name Change mode */ + //@{ + /// Set + void setMode(int mode); + /// Get + int getMode() const; + //@} + + /**@name Change maxima */ + //@{ + /// Set maximum number of passes per node + void setMaxPass(int value); + /// Get maximum number of passes per node + int getMaxPass() const; + /// Set log level - 0 none, 1 - a bit, 2 - more details + void setLogLevel(int value); + /// Get log level + int getLogLevel() const; + /// Set maximum number of unsatisfied variables to look at + void setMaxProbe(int value); + /// Get maximum number of unsatisfied variables to look at + int getMaxProbe() const; + /// Set maximum number of variables to look at in one probe + void setMaxLook(int value); + /// Get maximum number of variables to look at in one probe + int getMaxLook() const; + /// Set maximum number of elements in row for it to be considered + void setMaxElements(int value); + /// Get maximum number of elements in row for it to be considered + int getMaxElements() const; + /// Set maximum number of passes per node (root node) + void setMaxPassRoot(int value); + /// Get maximum number of passes per node (root node) + int getMaxPassRoot() const; + /// Set maximum number of unsatisfied variables to look at (root node) + void setMaxProbeRoot(int value); + /// Get maximum number of unsatisfied variables to look at (root node) + int getMaxProbeRoot() const; + /// Set maximum number of variables to look at in one probe (root node) + void setMaxLookRoot(int value); + /// Get maximum number of variables to look at in one probe (root node) + int getMaxLookRoot() const; + /// Set maximum number of elements in row for it to be considered (root node) + void setMaxElementsRoot(int value); + /// Get maximum number of elements in row for it to be considered (root node) + int getMaxElementsRoot() const; + /** + Returns true if may generate Row cuts in tree (rather than root node). + Used so know if matrix will change in tree. Really + meant so column cut generators can still be active + without worrying code. + Default is true + */ + virtual bool mayGenerateRowCutsInTree() const; + //@} + + /**@name Get information back from probing */ + //@{ + /// Number looked at this time + inline int numberThisTime() const + { return numberThisTime_;} + /// Which ones looked at this time + inline const int * lookedAt() const + { return lookedAt_;} + //@} + + /**@name Stop or restart row cuts (otherwise just fixing from probing) */ + //@{ + /// Set + /// 0 no cuts, 1 just disaggregation type, 2 coefficient ( 3 both) + void setRowCuts(int type); + /// Get + int rowCuts() const; + //@} + /// Clique type + typedef struct { + unsigned int equality:1; // nonzero if clique is == + } CliqueType; + + /**@name Information on cliques */ + //@{ + /// Number of cliques + inline int numberCliques() const + { return numberCliques_;} + /// Clique type + inline CliqueType * cliqueType() const + { return cliqueType_;} + /// Start of each clique + inline int * cliqueStart() const + { return cliqueStart_;} + /// Entries for clique + inline CliqueEntry * cliqueEntry() const + { return cliqueEntry_;} + //@} + + /**@name Whether use objective as constraint */ + //@{ + /** Set + 0 don't + 1 do + -1 don't even think about it + */ + void setUsingObjective(int yesNo); + /// Get + int getUsingObjective() const; + //@} + + /**@name Mark which continuous variables are to be tightened */ + //@{ + /// Mark variables to be tightened + void tightenThese(const OsiSolverInterface & solver, int number, const int * which); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglProbing (); + + /// Copy constructor + CglProbing ( + const CglProbing &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglProbing & + operator=( + const CglProbing& rhs); + + /// Destructor + virtual + ~CglProbing (); + + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + /**@name probe */ + //@{ + /// Does probing and adding cuts (without cliques and mode_!=0) + int probe( const OsiSolverInterface & si, + const OsiRowCutDebugger * debugger, + OsiCuts & cs, + double * colLower, double * colUpper, CoinPackedMatrix *rowCopy, + CoinPackedMatrix *columnCopy,const CoinBigIndex * rowStartPos, + const int * realRow, const double * rowLower, const double * rowUpper, + const char * intVar, double * minR, double * maxR, int * markR, + CglTreeInfo * info); + /// Does probing and adding cuts (with cliques) + int probeCliques( const OsiSolverInterface & si, + const OsiRowCutDebugger * debugger, + OsiCuts & cs, + double * colLower, double * colUpper, CoinPackedMatrix *rowCopy, + CoinPackedMatrix *columnCopy, const int * realRow, + double * rowLower, double * rowUpper, + char * intVar, double * minR, double * maxR, int * markR, + CglTreeInfo * info); + /// Does probing and adding cuts for clique slacks + int probeSlacks( const OsiSolverInterface & si, + const OsiRowCutDebugger * debugger, + OsiCuts & cs, + double * colLower, double * colUpper, CoinPackedMatrix *rowCopy, + CoinPackedMatrix *columnCopy, + double * rowLower, double * rowUpper, + char * intVar, double * minR, double * maxR,int * markR, + CglTreeInfo * info); + /** Does most of work of generateCuts + Returns number of infeasibilities */ + int gutsOfGenerateCuts( const OsiSolverInterface & si, + OsiCuts & cs, + double * rowLower, double * rowUpper, + double * colLower, double * colUpper, + CglTreeInfo * info); + /// Sets up clique information for each row + void setupRowCliqueInformation(const OsiSolverInterface & si); + /** This tightens column bounds (and can declare infeasibility) + It may also declare rows to be redundant */ + int tighten(double *colLower, double * colUpper, + const int *column, const double *rowElements, + const CoinBigIndex *rowStart,const CoinBigIndex * rowStartPos, + const int * rowLength, + double *rowLower, double *rowUpper, + int nRows,int nCols,char * intVar,int maxpass, + double tolerance); + /// This just sets minima and maxima on rows + void tighten2(double *colLower, double * colUpper, + const int *column, const double *rowElements, + const CoinBigIndex *rowStart, + const int * rowLength, + double *rowLower, double *rowUpper, + double * minR, double * maxR, int * markR, + int nRows); + //@} + + // Private member data + + struct disaggregation_struct_tag ; + friend struct CglProbing::disaggregation_struct_tag ; + + /**@name Private member data */ + //@{ + /// Row copy (only if snapshot) + CoinPackedMatrix * rowCopy_; + /// Column copy (only if snapshot) + CoinPackedMatrix * columnCopy_; + /// Lower bounds on rows + double * rowLower_; + /// Upper bounds on rows + double * rowUpper_; + /// Lower bounds on columns + double * colLower_; + /// Upper bounds on columns + double * colUpper_; + /// Number of rows in snapshot (or when cliqueRow stuff computed) + int numberRows_; + /// Number of columns in problem ( must == current) + int numberColumns_; + /// Tolerance to see if infeasible + double primalTolerance_; + /** Mode - 0 lazy using snapshot, 1 just unsatisfied, 2 all. + 16 bit set if want to extend cliques at root node + */ + int mode_; + /** Row cuts flag + 0 no cuts, 1 just disaggregation type, 2 coefficient ( 3 both), 4 just column cuts + -n as +n but just fixes variables unless at root + */ + int rowCuts_; + /// Maximum number of passes to do in probing + int maxPass_; + /// Log level - 0 none, 1 - a bit, 2 - more details + int logLevel_; + /// Maximum number of unsatisfied variables to probe + int maxProbe_; + /// Maximum number of variables to look at in one probe + int maxStack_; + /// Maximum number of elements in row for scan + int maxElements_; + /// Maximum number of passes to do in probing at root + int maxPassRoot_; + /// Maximum number of unsatisfied variables to probe at root + int maxProbeRoot_; + /// Maximum number of variables to look at in one probe at root + int maxStackRoot_; + /// Maximum number of elements in row for scan at root + int maxElementsRoot_; + /// Whether to include objective as constraint + int usingObjective_; + /// Number of integer variables + int numberIntegers_; + /// Number of 0-1 integer variables + int number01Integers_; + /// Number looked at this time + int numberThisTime_; + /// Total number of times called + int totalTimesCalled_; + /// Which ones looked at this time + int * lookedAt_; + /// Disaggregation cuts and for building cliques + typedef struct disaggregation_struct_tag { + int sequence; // integer variable + // index will be NULL if no probing done yet + int length; // length of newValue + disaggregationAction * index; // columns whose bounds will be changed + } disaggregation; + disaggregation * cutVector_; + /// Cliques + /// Number of cliques + int numberCliques_; + /// Clique type + CliqueType * cliqueType_; + /// Start of each clique + int * cliqueStart_; + /// Entries for clique + CliqueEntry * cliqueEntry_; + /** Start of oneFixes cliques for a column in matrix or -1 if not + in any clique */ + int * oneFixStart_; + /** Start of zeroFixes cliques for a column in matrix or -1 if not + in any clique */ + int * zeroFixStart_; + /// End of fixes for a column + int * endFixStart_; + /// Clique numbers for one or zero fixes + int * whichClique_; + /** For each column with nonzero in row copy this gives a clique "number". + So first clique mentioned in row is always 0. If no entries for row + then no cliques. If sequence > numberColumns then not in clique. + */ + CliqueEntry * cliqueRow_; + /// cliqueRow_ starts for each row + int * cliqueRowStart_; + /// If not null and [i] !=0 then also tighten even if continuous + char * tightenBounds_; + //@} +}; +inline int affectedInDisaggregation(const disaggregationAction & dis) +{ return dis.affected&0x1fffffff;} +inline void setAffectedInDisaggregation(disaggregationAction & dis, + int affected) +{ dis.affected = affected|(dis.affected&0xe0000000);} +#ifdef NDEBUG +inline bool zeroOneInDisaggregation(const disaggregationAction & ) +{ return true;} +#else +inline bool zeroOneInDisaggregation(const disaggregationAction & dis) +//{ return (dis.affected&0x80000000)!=0;} +{ assert ((dis.affected&0x80000000)!=0); return true;} +#endif +inline void setZeroOneInDisaggregation(disaggregationAction & dis,bool zeroOne) +{ dis.affected = (zeroOne ? 0x80000000 : 0)|(dis.affected&0x7fffffff);} +inline bool whenAtUBInDisaggregation(const disaggregationAction & dis) +{ return (dis.affected&0x40000000)!=0;} +inline void setWhenAtUBInDisaggregation(disaggregationAction & dis,bool whenAtUB) +{ dis.affected = (whenAtUB ? 0x40000000 : 0)|(dis.affected&0xbfffffff);} +inline bool affectedToUBInDisaggregation(const disaggregationAction & dis) +{ return (dis.affected&0x20000000)!=0;} +inline void setAffectedToUBInDisaggregation(disaggregationAction & dis,bool affectedToUB) +{ dis.affected = (affectedToUB ? 0x20000000 : 0)|(dis.affected&0xdfffffff);} + +//############################################################################# +/** A function that tests the methods in the CglProbing class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglProbingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); +/// This just uses implication info +class CglImplication : public CglCutGenerator { + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate cuts from implication table + Insert generated cuts into the cut set cs. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglImplication (); + + /// Constructor with info + CglImplication (CglTreeProbingInfo * info); + + /// Copy constructor + CglImplication ( + const CglImplication &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglImplication & + operator=( + const CglImplication& rhs); + + /// Destructor + virtual + ~CglImplication (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + /**@name Set implication */ + //@{ + /// Set implication + inline void setProbingInfo(CglTreeProbingInfo * info) + { probingInfo_=info;} + //@} + +private: + /**@name Private member data */ + //@{ + /// Pointer to tree probing info + CglTreeProbingInfo * probingInfo_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CglRedSplit.hpp b/thirdparty/linux/include/coin/CglRedSplit.hpp new file mode 100644 index 0000000..1265b1d --- /dev/null +++ b/thirdparty/linux/include/coin/CglRedSplit.hpp @@ -0,0 +1,448 @@ +// Last edit: 4/20/07 +// +// Name: CglRedSplit.hpp +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 2/6/05 +// +// $Id: CglRedSplit.hpp 1119 2013-04-06 20:24:18Z stefan $ +//----------------------------------------------------------------------------- +// Copyright (C) 2005, Francois Margot and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglRedSplit_H +#define CglRedSplit_H + +#include "CglCutGenerator.hpp" +#include "CglRedSplitParam.hpp" + +/** Gomory Reduce-and-Split Cut Generator Class; See method generateCuts(). + Based on the paper by K. Anderson, G. Cornuejols, Yanjun Li, + "Reduce-and-Split Cuts: Improving the Performance of Mixed Integer + Gomory Cuts", Management Science 51 (2005). */ + +class CglRedSplit : public CglCutGenerator { + + friend void CglRedSplitUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +public: + /**@name generateCuts */ + //@{ + /** Generate Reduce-and-Split Mixed Integer Gomory cuts + for the model of the solver interface si. + + Insert the generated cuts into OsiCuts cs. + + Warning: This generator currently works only with the Lp solvers Clp or + Cplex9.0 or higher. It requires access to the optimal tableau and + optimal basis inverse and makes assumptions on the way slack variables + are added by the solver. The Osi implementations for Clp and Cplex + verify these assumptions. + + When calling the generator, the solver interface si + must contain an optimized + problem and information related to the optimal basis must be available + through the OsiSolverInterface methods (si->optimalBasisIsAvailable() + must return 'true'). It is also essential that the integrality of + structural variable i can be obtained using si->isInteger(i). + + Reduce-and-Split cuts are variants of Gomory cuts: Starting from + the current optimal tableau, linear combinations of the rows of + the current optimal simplex tableau are used for generating Gomory + cuts. The choice of the linear combinations is driven by the objective + of reducing the coefficients of the non basic continuous variables + in the resulting row. + Note that this generator might not be able to generate cuts for some + solutions violating integrality constraints. + + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const; + //@} + + + /**@name Public Methods */ + //@{ + + // Set the parameters to the values of the given CglRedSplitParam object. + void setParam(const CglRedSplitParam &source); + // Return the CglRedSplitParam object of the generator. + inline CglRedSplitParam getParam() const {return param;} + + // Compute entries of low_is_lub and up_is_lub. + void compute_is_lub(); + + // Compute entries of is_integer. + void compute_is_integer(); + + /// Set given_optsol to the given optimal solution given_sol. + /// If given_optsol is set using this method, + /// the code will stop as soon as + /// a generated cut is violated by the given solution; exclusively + /// for debugging purposes. + void set_given_optsol(const double *given_sol, const int card_sol); + + /// Print some of the data members + void print() const; + + /// Print the current simplex tableau + void printOptTab(OsiSolverInterface *solver) const; + + //@} + + /**@name Public Methods (soon to be obsolete)*/ + //@{ + //************************************************************ + // TO BE REMOVED + /** Set limit, the maximum number of non zero coefficients in generated cut; + Default: 50 */ + void setLimit(int limit); + /** Get value of limit */ + int getLimit() const; + + /** Set away, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.05 */ + void setAway(double value); + /// Get value of away + double getAway() const; + /** Set the value of LUB, value considered large for the absolute value of + a lower or upper bound on a variable; + Default: 1000 */ + void setLUB(double value); + /** Get the value of LUB */ + double getLUB() const; + + /** Set the value of EPS, epsilon for double computations; + Default: 1e-7 */ + void setEPS(double value); + /** Get the value of EPS */ + double getEPS() const; + + /** Set the value of EPS_COEFF, epsilon for values of coefficients; + Default: 1e-8 */ + void setEPS_COEFF(double value); + /** Get the value of EPS_COEFF */ + double getEPS_COEFF() const; + + /** Set the value of EPS_COEFF_LUB, epsilon for values of coefficients for + variables with absolute value of lower or upper bound larger than LUB; + Default: 1e-13 */ + void setEPS_COEFF_LUB(double value); + /** Get the value of EPS_COEFF_LUB */ + double getEPS_COEFF_LUB() const; + + /** Set the value of EPS_RELAX, value used for relaxing the right hand side + of each generated cut; + Default: 1e-8 */ + void setEPS_RELAX(double value); + /** Get the value of EPS_RELAX */ + double getEPS_RELAX() const; + + /** Set the value of normIsZero, the threshold for considering a norm to be + 0; Default: 1e-5 */ + void setNormIsZero(double value); + /** Get the value of normIsZero */ + double getNormIsZero() const; + + /** Set the value of minReduc, threshold for relative norm improvement for + performing a reduction; Default: 0.05 */ + void setMinReduc(double value); + /// Get the value of minReduc + double getMinReduc() const; + + /** Set the maximum allowed value for (mTab * mTab * CoinMax(mTab, nTab)) where + mTab is the number of rows used in the combinations and nTab is the + number of continuous non basic variables. The work of the generator is + proportional to (mTab * mTab * CoinMax(mTab, nTab)). Reducing the value of + maxTab makes the generator faster, but weaker. Default: 1e7. */ + void setMaxTab(double value); + /// Get the value of maxTab + double getMaxTab() const; + // END TO BE REMOVED + //************************************************************ + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglRedSplit(); + + /// Constructor with specified parameters + CglRedSplit(const CglRedSplitParam &RS_param); + + /// Copy constructor + CglRedSplit (const CglRedSplit &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglRedSplit & + operator=( + const CglRedSplit& rhs); + + /// Destructor + virtual + ~CglRedSplit (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + +/**@name Private member methods */ + + //@{ + + // Method generating the cuts after all CglRedSplit members are properly set. + void generateCuts(OsiCuts & cs); + + /// Compute the fractional part of value, allowing for small error. + inline double rs_above_integer(double value); + + /// Perform row r1 of pi := row r1 of pi - step * row r2 of pi. + void update_pi_mat(int r1, int r2, int step); + + /// Perform row r1 of tab := row r1 of tab - step * row r2 of tab. + void update_redTab(int r1, int r2, int step); + + /// Find optimal integer step for changing row r1 by adding to it a + /// multiple of another row r2. + void find_step(int r1, int r2, int *step, + double *reduc, double *norm); + + /// Test if an ordered pair of rows yields a reduction. Perform the + /// reduction if it is acceptable. + int test_pair(int r1, int r2, double *norm); + + /// Reduce rows of contNonBasicTab. + void reduce_contNonBasicTab(); + + /// Generate a row of the current LP tableau. + void generate_row(int index_row, double *row); + + /// Generate a mixed integer Chvatal-Gomory cut, when all non basic + /// variables are non negative and at their lower bound. + int generate_cgcut(double *row, double *rhs); + + /// Generate a mixed integer Chvatal-Gomory cut, when all non basic + /// variables are non negative and at their lower bound (different formula) + int generate_cgcut_2(int basic_ind, double *row, double *rhs); + + /// Use multiples of the initial inequalities to cancel out the coefficients + /// of the slack variables. + void eliminate_slacks(double *row, + const double *elements, + const int *start, + const int *indices, + const int *rowLength, + const double *rhs, double *rowrhs); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound. + void flip(double *row); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound and do the translations restoring + /// the original bounds. Modify the right hand side + /// accordingly. + void unflip(double *row, double *rowrhs, double *slack_val); + + /// Return the scale factor for the row. + /// Compute max_coeff: maximum absolute value of the coefficients. + /// Compute min_coeff: minimum absolute value of the coefficients + /// larger than EPS_COEFF. + /// Return -1 if max_coeff < EPS_COEFF or if max_coeff/min_coeff > MAXDYN + /// or MAXDYN_LUB (depending if the row has a non zero coeff. for a variable + /// with large lower/upper bound) */. + double row_scale_factor(double *row); + + /// Generate the packed cut from the row representation. + int generate_packed_row(const double *xlp, double *row, + int *rowind, double *rowelem, + int *card_row, double & rhs); + + /// Check that the generated cuts do not cut a given optimal solution. + void check_optsol(const int calling_place, + const double *xlp, const double *slack_val, + const int do_flip); + + /// Check that the generated cuts do not cut a given optimal solution. + void check_optsol(const int calling_place, + const double *xlp, const double *slack_val, + const double *ck_row, const double ck_rhs, + const int cut_number, const int do_flip); + + // Check that two vectors are different. + bool rs_are_different_vectors(const int *vect1, + const int *vect2, + const int dim); + + // Check that two vectors are different. + bool rs_are_different_vectors(const double *vect1, + const double *vect2, + const int dim); + + // Check that two matrices are different. + bool rs_are_different_matrices(const CoinPackedMatrix *mat1, + const CoinPackedMatrix *mat2, + const int nmaj, + const int nmin); + //@} + + + // Private member data + +/**@name Private member data */ + + //@{ + + /// Object with CglRedSplitParam members. + CglRedSplitParam param; + + /// Number of rows ( = number of slack variables) in the current LP. + int nrow; + + /// Number of structural variables in the current LP. + int ncol; + + /// Lower bounds for structural variables + const double *colLower; + + /// Upper bounds for structural variables + const double *colUpper; + + /// Lower bounds for constraints + const double *rowLower; + + /// Upper bounds for constraints + const double *rowUpper; + + /// Righ hand side for constraints (upper bound for ranged constraints). + const double *rowRhs; + + /// Number of integer basic structural variables that are fractional in the + /// current lp solution (at least param.away_ from being integer). + int card_intBasicVar_frac; + + /// Number of integer non basic structural variables in the + /// current lp solution. + int card_intNonBasicVar; + + /// Number of continuous non basic variables (structural or slack) in the + /// current lp solution. + int card_contNonBasicVar; + + /// Number of non basic variables (structural or slack) at their + /// upper bound in the current lp solution. + int card_nonBasicAtUpper; + + /// Number of non basic variables (structural or slack) at their + /// lower bound in the current lp solution. + int card_nonBasicAtLower; + + /// Characteristic vector for integer basic structural variables + /// with non integer value in the current lp solution. + int *cv_intBasicVar_frac; + + /// List of integer structural basic variables + /// (in order of pivot in selected rows for cut generation). + int *intBasicVar_frac; + + /// List of integer structural non basic variables. + int *intNonBasicVar; + + /// List of continuous non basic variables (structural or slack). + // slacks are considered continuous (no harm if this is not the case). + int *contNonBasicVar; + + /// List of non basic variables (structural or slack) at their + /// upper bound. + int *nonBasicAtUpper; + + /// List of non basic variables (structural or slack) at their lower + /// bound. + int *nonBasicAtLower; + + /// Number of rows in the reduced tableau (= card_intBasicVar_frac). + int mTab; + + /// Number of columns in the reduced tableau (= card_contNonBasicVar) + int nTab; + + /// Tableau of multipliers used to alter the rows used in generation. + /// Dimensions: mTab by mTab. Initially, pi_mat is the identity matrix. + int **pi_mat; + + /// Current tableau for continuous non basic variables (structural or slack). + /// Only rows used for generation. + /// Dimensions: mTab by nTab. + double **contNonBasicTab; + + /// Current tableau for integer non basic structural variables. + /// Only rows used for generation. + // Dimensions: mTab by card_intNonBasicVar. + double **intNonBasicTab; + + /// Right hand side of the tableau. + /// Only rows used for generation. + double *rhsTab ; + + /// Given optimal solution that should not be cut; only for debug. + const double *given_optsol; + + /// Number of entries in given_optsol. + int card_given_optsol; + + /// Characteristic vectors of structural integer variables or continuous + /// variables currently fixed to integer values. + int *is_integer; + + /// Characteristic vector of the structural variables whose lower bound + /// in absolute value is larger than LUB. + int *low_is_lub; + + /// Characteristic vector of the structural variables whose upper bound + /// in absolute value is larger than LUB. + int *up_is_lub; + + /// Pointer on solver. Reset by each call to generateCuts(). + OsiSolverInterface *solver; + + /// Pointer on point to separate. Reset by each call to generateCuts(). + const double *xlp; + + /// Pointer on row activity. Reset by each call to generateCuts(). + const double *rowActivity; + + /// Pointer on column type. Reset by each call to generateCuts(). + const char *colType; + + /// Pointer on matrix of coefficient ordered by rows. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byRow; + + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglRedSplit class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglRedSplitUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +#endif diff --git a/thirdparty/linux/include/coin/CglRedSplit2.hpp b/thirdparty/linux/include/coin/CglRedSplit2.hpp new file mode 100644 index 0000000..c66e1ca --- /dev/null +++ b/thirdparty/linux/include/coin/CglRedSplit2.hpp @@ -0,0 +1,494 @@ +// Last edit: 04/03/10 +// +// Name: CglRedSplit2.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design +// Singapore +// email: nannicini@sutd.edu.sg +// based on CglRedSplit by Francois Margot +// Date: 03/09/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2010, Giacomo Nannicini and others. All Rights Reserved. + +#ifndef CglRedSplit2_H +#define CglRedSplit2_H + +#include "CglCutGenerator.hpp" +#include "CglRedSplit2Param.hpp" +#include "CoinWarmStartBasis.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinTime.hpp" + +/** Reduce-and-Split Cut Generator Class; See method generateCuts(). + Based on the papers "Practical strategies for generating rank-1 + split cuts in mixed-integer linear programming" by G. Cornuejols + and G. Nannicini, published on Mathematical Programming + Computation, and "Combining Lift-and-Project and Reduce-and-Split" + by E. Balas, G. Cornuejols, T. Kis and G. Nannicini, published on + INFORMS Journal on Computing. Part of this code is based on + CglRedSplit by F. Margot. */ + +class CglRedSplit2 : public CglCutGenerator { + + friend void CglRedSplit2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +public: + /**@name generateCuts */ + //@{ + /** Generate Reduce-and-Split Mixed Integer Gomory cuts + for the model of the solver interface si. + + Insert the generated cuts into OsiCuts cs. + + This generator currently works only with the Lp solvers Clp or + Cplex9.0 or higher. It requires access to the optimal tableau + and optimal basis inverse and makes assumptions on the way slack + variables are added by the solver. The Osi implementations for + Clp and Cplex verify these assumptions. + + When calling the generator, the solver interface si must contain + an optimized problem and information related to the optimal + basis must be available through the OsiSolverInterface methods + (si->optimalBasisIsAvailable() must return 'true'). It is also + essential that the integrality of structural variable i can be + obtained using si->isInteger(i). + + Reduce-and-Split cuts are a class of split cuts. We compute + linear combinations of the rows of the simplex tableau, trying + to reduce some of the coefficients on the nonbasic continuous + columns. We have a large number of heuristics to choose which + coefficients should be reduced, and by using which rows. The + paper explains everything in detail. + + Note that this generator can potentially generate a huge number + of cuts, depending on how it is parametered. Default parameters + should be good for most situations; if you want to go heavy on + split cuts, use more row selection strategies or a different + number of rows in the linear combinations. Again, look at the + paper for details. If you want to generate a small number of + cuts, default parameters are not the best choice. + + A combination of Reduce-and-Split with Lift & Project is + described in the paper "Combining Lift-and-Project and + Reduce-and-Split". The Reduce-and-Split code for the + implementation used in that paper is included here. + + This generator does not generate the same cuts as CglRedSplit, + therefore both generators can be used in conjunction. + + */ + + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const; + + // Generate the row multipliers computed by Reduce-and-Split from the + // given OsiSolverInterface. The multipliers are written in lambda; + // lambda should be of size nrow*maxNumMultipliers. We generate at most + // maxNumMultipliers m-vectors of row multipliers, and return the number + // of m-vectors that were generated. + // If the caller wants to know which variables are basic in each row + // (same order as lambda), basicVariables should be non-NULL (size nrow). + // This method can also generate the cuts corresponding to the multipliers + // returned; it suffices to pass non-NULL OsiCuts. + // This method is not needed by the typical user; however, it is useful + // in the context of generating Lift & Project cuts. + int generateMultipliers(const OsiSolverInterface& si, int* lambda, + int maxNumMultipliers, int* basicVariables = NULL, + OsiCuts* cs = NULL); + + // Try to improve a Lift & Project cut, by employing the + // Reduce-and-Split procedure. We start from a row of a L&P tableau, + // and generate a cut trying to reduce the coefficients on the + // nonbasic variables. Note that this L&P tableau will in general + // have nonbasic variables which are nonzero in the point that we + // want to cut off, so we should be careful. Arguments: + // OsiSolverInterface which contains the simplex tableau, initial + // row from which the cut is derived, row rhs, row number of the + // source row (if it is in the simplex tableau; otherwise, a + // negative number; needed to avoid using duplicate rows), point + // that we want to cut off (note: this is NOT a basic solution for + // the OsiSolverInterace!), list of variables which are basic in + // xbar but are nonbasic in the OsiSolverInterface. The computed cut + // is written in OsiRowCut* cs. Finally, if a starting disjunction + // is provided in the vector lambda (of size ncols, i.e. a + // disjunction on the structural variables), the disjunction is + // modified according to the cut which is produced. + int tiltLandPcut(const OsiSolverInterface* si, double* row, + double rowRhs, int rownumber, const double* xbar, + const int* newnonbasics, OsiRowCut* cs, int* lambda = NULL); + + //@} + + + /**@name Public Methods */ + //@{ + + // Set the parameters to the values of the given CglRedSplit2Param object. + void setParam(const CglRedSplit2Param &source); + // Return the CglRedSplit2Param object of the generator. + inline CglRedSplit2Param& getParam() {return param;} + + /// Print some of the data members; used for debugging + void print() const; + + /// Print the current simplex tableau + void printOptTab(OsiSolverInterface *solver) const; + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglRedSplit2(); + + /// Constructor with specified parameters + CglRedSplit2(const CglRedSplit2Param &RS_param); + + /// Copy constructor + CglRedSplit2(const CglRedSplit2 &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglRedSplit2 & operator=(const CglRedSplit2& rhs); + + /// Destructor + virtual ~CglRedSplit2 (); + + //@} + +private: + + // Private member methods + +/**@name Private member methods */ + + //@{ + + // Method generating the cuts after all CglRedSplit2 members are + // properly set. This does the actual work. Returns the number of + // generated cuts (or multipliers). + // Will generate cuts if cs != NULL, and will generate multipliers + // if lambda != NULL. + int generateCuts(OsiCuts* cs, int maxNumCuts, int* lambda = NULL); + + /// Compute the fractional part of value, allowing for small error. + inline double rs_above_integer(const double value) const; + + /// Fill workNonBasicTab, depending on the column selection strategy. + /// Accepts a list of variables indices that should be ignored; by + /// default, this list is empty (it is only used by Lift & Project). + /// The list ignore_list contains -1 as the last element. + /// Note that the implementation of the ignore_list is not very efficient + /// if the list is long, so it should be used only if its short. + void fill_workNonBasicTab(CglRedSplit2Param::ColumnSelectionStrategy + strategy, const int* ignore_list = NULL); + + /// Fill workNonBasicTab, alternate version for Lift & Project: also + /// reduces columns which are now nonbasic but are basic in xbar. + /// This function should be called only when CglRedSplit2 is used in + /// conjunction with CglLandP to generate L&P+RS cuts. + void fill_workNonBasicTab(const int* newnonbasics, const double* xbar, + CglRedSplit2Param::ColumnScalingStrategy scaling); + + /// Reduce rows of workNonBasicTab, i.e. compute integral linear + /// combinations of the rows in order to reduce row coefficients on + /// workNonBasicTab + void reduce_workNonBasicTab(int numRows, + CglRedSplit2Param::RowSelectionStrategy + rowSelectionStrategy, + int maxIterations); + + /// Generate a linear combination of the rows of the current LP + /// tableau, using the row multipliers stored in the matrix pi_mat + /// on the row of index index_row + void generate_row(int index_row, double *row); + + /// Generate a mixed integer Gomory cut, when all non basic + /// variables are non negative and at their lower bound. + int generate_cgcut(double *row, double *rhs); + + /// Use multiples of the initial inequalities to cancel out the coefficients + /// of the slack variables. + void eliminate_slacks(double *row, + const double *elements, + const int *start, + const int *indices, + const int *rowLength, + const double *rhs, double *rowrhs); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound. + void flip(double *row); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound and do the translations restoring + /// the original bounds. Modify the right hand side + /// accordingly. + void unflip(double *row, double *rowrhs); + + /// Returns 1 if the row has acceptable max/min coeff ratio. + /// Compute max_coeff: maximum absolute value of the coefficients. + /// Compute min_coeff: minimum absolute value of the coefficients + /// larger than EPS_COEFF. + /// Return 0 if max_coeff/min_coeff > MAXDYN. + int check_dynamism(double *row); + + /// Generate the packed cut from the row representation. + int generate_packed_row(const double *xlp, double *row, + int *rowind, double *rowelem, + int *card_row, double & rhs); + + // Compute entries of is_integer. + void compute_is_integer(); + + // Check that two vectors are different. + bool rs_are_different_vectors(const int *vect1, + const int *vect2, + const int dim); + + // allocate matrix of integers + void rs_allocmatINT(int ***v, int m, int n); + // deallocate matrix of integers + void rs_deallocmatINT(int ***v, int m); + // allocate matrix of doubles + void rs_allocmatDBL(double ***v, int m, int n); + // deallocate matrix of doubles + void rs_deallocmatDBL(double ***v, int m); + // print a vector of integers + void rs_printvecINT(const char *vecstr, const int *x, int n) const; + // print a vector of doubles + void rs_printvecDBL(const char *vecstr, const double *x, int n) const; + // print a matrix of integers + void rs_printmatINT(const char *vecstr, const int * const *x, int m, int n) const; + // print a matrix of doubles + void rs_printmatDBL(const char *vecstr, const double * const *x, int m, int n) const; + // dot product + double rs_dotProd(const double *u, const double *v, int dim) const; + double rs_dotProd(const int *u, const double *v, int dim) const; + // From Numerical Recipes in C: LU decomposition + int ludcmp(double **a, int n, int *indx, double *d, double* vv) const; + // from Numerical Recipes in C: backward substitution + void lubksb(double **a, int n, int *indx, double *b) const; + + // Check if the linear combination given by listOfRows with given multipliers + // improves the norm of row #rowindex; note: multipliers are rounded! + // Returns the difference with respect to the old norm (if negative there is + // an improvement, if positive norm increases) + double compute_norm_change(double oldnorm, const int* listOfRows, + int numElemList, const double* multipliers) const; + + // Compute the list of rows that should be used to reduce row #rowIndex + int get_list_rows_reduction(int rowIndex, int numRowsReduction, + int* list, const double* norm, + CglRedSplit2Param::RowSelectionStrategy + rowSelectionStrategy) const; + + // Sorts the rows by increasing number of nonzeroes with respect to a given + // row (rowIndex), on the nonbasic variables (whichTab == 0 means only + // integer, whichTab == 1 means only workTab, whichTab == 2 means both). + // The array for sorting must be allocated (and deleted) by caller. + // Corresponds to BRS1 in the paper. + int sort_rows_by_nonzeroes(struct sortElement* array, int rowIndex, + int maxRows, int whichTab) const; + + // Greedy variant of the previous function; slower but typically + // more effective. Corresponds to BRS2 in the paper. + int sort_rows_by_nonzeroes_greedy(struct sortElement* array, int rowIndex, + int maxRows, int whichTab) const; + + // Sorts the rows by decreasing absolute value of the cosine of the + // angle with respect to a given row (rowIndex), on the nonbasic + // variables (whichTab == 0 means only integer, whichTab == 1 means + // only workTab, whichTab == 2 means both). The array for sorting + // must be allocated (and deleted) by caller. Very effective + // strategy in practice. Corresponds to BRS3 in the paper. + int sort_rows_by_cosine(struct sortElement* array, int rowIndex, + int maxRows, int whichTab) const; + + // Did we hit the time limit? + inline bool checkTime() const{ + if ((CoinCpuTime() - startTime) < param.getTimeLimit()){ + return true; + } + return false; + } + + //@} + + + // Private member data + + /**@name Private member data */ + + //@{ + + /// Object with CglRedSplit2Param members. + CglRedSplit2Param param; + + /// Number of rows ( = number of slack variables) in the current LP. + int nrow; + + /// Number of structural variables in the current LP. + int ncol; + + /// Number of rows which have been reduced + int numRedRows; + + /// Lower bounds for structural variables + const double *colLower; + + /// Upper bounds for structural variables + const double *colUpper; + + /// Lower bounds for constraints + const double *rowLower; + + /// Upper bounds for constraints + const double *rowUpper; + + /// Righ hand side for constraints (upper bound for ranged constraints). + const double *rowRhs; + + /// Reduced costs for columns + const double *reducedCost; + + /// Row price + const double *rowPrice; + + /// Objective coefficients + const double* objective; + + /// Number of integer basic structural variables + int card_intBasicVar; + + /// Number of integer basic structural variables that are fractional in the + /// current lp solution (at least param.away_ from being integer). + int card_intBasicVar_frac; + + /// Number of integer non basic structural variables in the + /// current lp solution. + int card_intNonBasicVar; + + /// Number of continuous non basic variables (structural or slack) in the + /// current lp solution. + int card_contNonBasicVar; + + /// Number of continuous non basic variables (structural or slack) in the + /// current working set for coefficient reduction + int card_workNonBasicVar; + + /// Number of non basic variables (structural or slack) at their + /// upper bound in the current lp solution. + int card_nonBasicAtUpper; + + /// Number of non basic variables (structural or slack) at their + /// lower bound in the current lp solution. + int card_nonBasicAtLower; + + /// Characteristic vector for integer basic structural variables + int *cv_intBasicVar; + + /// Characteristic vector for integer basic structural variables + /// with non integer value in the current lp solution. + int *cv_intBasicVar_frac; + + /// Characteristic vector for rows of the tableau selected for reduction + /// with non integer value in the current lp solution + int *cv_fracRowsTab; + + /// List of integer structural basic variables + /// (in order of pivot in selected rows for cut generation). + int *intBasicVar; + + /// List of integer structural basic variables with fractional value + /// (in order of pivot in selected rows for cut generation). + int *intBasicVar_frac; + + /// List of integer structural non basic variables. + int *intNonBasicVar; + + /// List of continuous non basic variables (structural or slack). + // slacks are considered continuous (no harm if this is not the case). + int *contNonBasicVar; + + /// List of non basic variables (structural or slack) at their + /// upper bound. + int *nonBasicAtUpper; + + /// List of non basic variables (structural or slack) at their lower + /// bound. + int *nonBasicAtLower; + + /// Number of rows in the reduced tableau (= card_intBasicVar). + int mTab; + + /// Number of columns in the reduced tableau (= card_contNonBasicVar) + int nTab; + + /// Tableau of multipliers used to alter the rows used in generation. + /// Dimensions: mTab by mTab. Initially, pi_mat is the identity matrix. + int **pi_mat; + + /// Simplex tableau for continuous non basic variables (structural or slack). + /// Only rows used for generation. + /// Dimensions: mTab by card_contNonBasicVar. + double **contNonBasicTab; + + /// Current tableau for continuous non basic variables (structural or slack). + /// Only columns used for coefficient reduction. + /// Dimensions: mTab by card_workNonBasicVar. + double **workNonBasicTab; + + /// Simplex tableau for integer non basic structural variables. + /// Only rows used for generation. + // Dimensions: mTab by card_intNonBasicVar. + double **intNonBasicTab; + + /// Right hand side of the tableau. + /// Only rows used for generation. + double *rhsTab; + + /// Norm of rows in workNonBasicTab; needed for faster computations + double *norm; + + /// Characteristic vectors of structural integer variables or continuous + /// variables currently fixed to integer values. + int *is_integer; + + /// Pointer on solver. Reset by each call to generateCuts(). + OsiSolverInterface *solver; + + /// Pointer on point to separate. Reset by each call to generateCuts(). + const double *xlp; + + /// Pointer on row activity. Reset by each call to generateCuts(). + const double *rowActivity; + + /// Pointer on matrix of coefficient ordered by rows. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byRow; + + /// Time at which cut computations began. + /// Reset by each call to generateCuts(). + double startTime; + + //@} +}; + +//############################################################################# +/** A function that tests some of the methods in the CglRedSplit2 + class. The only reason for it not to be a member method is that + this way it doesn't have to be compiled into the library. And + that's a gain, because the library should be compiled with + optimization on, but this method should be compiled with + debugging. */ +void CglRedSplit2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +#endif diff --git a/thirdparty/linux/include/coin/CglRedSplit2Param.hpp b/thirdparty/linux/include/coin/CglRedSplit2Param.hpp new file mode 100644 index 0000000..369c676 --- /dev/null +++ b/thirdparty/linux/include/coin/CglRedSplit2Param.hpp @@ -0,0 +1,495 @@ +// Name: CglRedSplit2Param.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design +// Singapore +// email: nannicini@sutd.edu.sg +// Date: 03/09/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2010, Giacomo Nannicini and others. All Rights Reserved. + +#ifndef CglRedSplit2Param_H +#define CglRedSplit2Param_H + +#include "CglParam.hpp" +#include <vector> + + /**@name CglRedSplit2 Parameters */ + //@{ + + /** Class collecting parameters the Reduced-and-split cut generator. + + An important thing to note is that the cut generator allows for + the selection of a number of strategies that can be combined + together. By default, a selection that typically yields a good + compromise between speed and cut strenght is made. The selection + can be changed by resetting the default choices (see the + functions whose name starts with "reset") or by setting the + parameter use_default_strategies to false in the + constructors. After this, the chosen strategies can be added to + the list by using the functions whose name starts with + "add". All strategies will be combined together: if we choose 3 + row selection strategies, 2 column selection strategies, and 2 + possible numbers of rows, we end up with a total of 3*2*2 + combinations. + + For a detailed explanation of the parameters and their meaning, + see the paper by Cornuejols and Nannicini: "Practical strategies + for generating rank-1 split cuts in mixed-integer linear + programming", on Mathematical Programming Computation. + + Parameters of the generator are listed below. + + - MAXDYN: Maximum ratio between largest and smallest non zero + coefficients in a cut. See method setMAXDYN(). + - EPS_ELIM: Precision for deciding if a coefficient is zero when + eliminating slack variables. See method setEPS_ELIM(). + - MINVIOL: Minimum violation for the current basic solution in + a generated cut. See method setMINVIOL(). + - EPS_RELAX_ABS: Absolute relaxation of cut rhs. + - EPS_RELAX_REL: Relative relaxation of cut rhs. + - MAX_SUPP_ABS: Maximum cut support (absolute). + - MAX_SUPP_REL: Maximum cut support (relative): the formula to + compute maximum cut support is + MAX_SUPP_ABS + ncol*MAX_SUPP_REL. + - USE_INTSLACKS: Use integer slacks to generate cuts. (not implemented). + See method setUSE_INTSLACKS(). + - normIsZero: Norm of a vector is considered zero if smaller than + this value. See method setNormIsZero(). + - minNormReduction: a cut is generated if the new norm of the row on the + continuous nonbasics is reduced by at least + this factor (relative reduction). + - away: Look only at basic integer variables whose current value + is at least this value from being integer. See method setAway(). + - maxSumMultipliers: maximum sum (in absolute value) of row multipliers + - normalization: normalization factor for the norm of lambda in the + coefficient reduction algorithm (convex min problem) + - numRowsReduction: Maximum number of rows in the linear system for + norm reduction. + - columnSelectionStrategy: parameter to select which columns should be + used for coefficient reduction. + - rowSelectionStrategy: parameter to select which rows should be + used for coefficient reduction. + - timeLimit: Time limit (in seconds) for cut generation. + - maxNumCuts: Maximum number of cuts that can be returned at each pass; + we could generate more cuts than this number (see below) + - maxNumComputedCuts: Maximum number of cuts that can be computed + by the generator at each pass + - maxNonzeroesTab : Rows of the simplex tableau with more than + this number of nonzeroes will not be + considered for reduction. Only works if + RS_FAST_* are defined in CglRedSplit2. + - skipGomory: Skip traditional Gomory cuts, i.e. GMI cuts arising from + a single row of the tableau (instead of a combination). + Default is 1 (true), because we assume that they are + generated by a traditional Gomory generator anyway. + */ + //@} + +class CglRedSplit2Param : public CglParam { + +public: + /** Enumerations for parameters */ + + /** Row selection strategies; same names as in the paper */ + enum RowSelectionStrategy{ + /* Pick rows that introduce the fewest nonzeroes on integer nonbasics */ + RS1, + /* Pick rows that introduce the fewest nonzeroes on the set of working + continuous nonbasics */ + RS2, + /* Pick rows that introduce the fewest nonzeroes on both integer and + working continuous nonbasics */ + RS3, + /* Same as RS0 but with greedy algorithm */ + RS4, + /* Same as RS1 but with greedy algorithm */ + RS5, + /* Same as RS2 but with greedy algorithm */ + RS6, + /* Pick rows with smallest angle in the space of integer and working + continuous nonbasics */ + RS7, + /* Pick rows with smallest angle in the space of working + continuous nonbasics */ + RS8, + /* Use all strategies */ + RS_ALL, + /* Use best ones - that is, RS8 and RS7 */ + RS_BEST + }; + + /** Column selection strategies; again, look them up in the paper. */ + enum ColumnSelectionStrategy{ + /* C-3P */ + CS1, CS2, CS3, + /* C-5P */ + CS4, CS5, CS6, CS7, CS8, + /* I-2P-2/3 */ + CS9, CS10, + /* I-2P-4/5 */ + CS11, CS12, + /* I-2P-1/2 */ + CS13, CS14, + /* I-3P */ + CS15, CS16, CS17, + /* I-4P */ + CS18, CS19, CS20, CS21, + /* Use all strategies up to this point */ + CS_ALL, + /* Use best strategies (same effect as CS_ALL, because it turns out that + using all strategies is the best thing to do) */ + CS_BEST, + /* Optimize over all continuous nonbasic columns; this does not give + good results, but we use it for testing Lift & Project + RedSplit */ + CS_ALLCONT, + /* Lift & Project specific strategy: only select variables which + are nonbasic in the tableau but are basic in the point to cut + off. This strategy cannot be used outside L&P. It is not very + effective even with L&P, but is left here for testing.*/ + CS_LAP_NONBASICS + }; + + /** Scaling strategies for new nonbasic columns for Lift & Project; + * "factor" is the value of columnScalingBoundLAP_ */ + enum ColumnScalingStrategy{ + /* No scaling */ + SC_NONE, + /* Multiply by |xbar[i]| where xbar[i] is the value of the + corresponding component of the point that we want to cut off */ + SC_LINEAR, + /* Multiply by min(factor,|xbar[i]|) */ + SC_LINEAR_BOUNDED, + /* Multiply by min(factor,log(|xbar[i]|)) */ + SC_LOG_BOUNDED, + /* Multiply all new nonbasics by factor */ + SC_UNIFORM, + /* Multiply only nonzero coefficients by factor */ + SC_UNIFORM_NZ + }; + + /**@name Set/get methods */ + //@{ + /** Set away, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.005 */ + virtual void setAway(double value); + /// Get value of away + inline double getAway() const {return away_;} + + /** Set the value of EPS_ELIM, epsilon for values of coefficients when + eliminating slack variables; + Default: 0.0 */ + void setEPS_ELIM(double value); + /** Get the value of EPS_ELIM */ + double getEPS_ELIM() const {return EPS_ELIM;} + + /** Set EPS_RELAX_ABS */ + virtual void setEPS_RELAX_ABS(double eps_ra); + /** Get value of EPS_RELAX_ABS */ + inline double getEPS_RELAX_ABS() const {return EPS_RELAX_ABS;} + + /** Set EPS_RELAX_REL */ + virtual void setEPS_RELAX_REL(double eps_rr); + /** Get value of EPS_RELAX_REL */ + inline double getEPS_RELAX_REL() const {return EPS_RELAX_REL;} + + // Set the maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e6. + virtual void setMAXDYN(double value); + /** Get the value of MAXDYN */ + inline double getMAXDYN() const {return MAXDYN;} + + /** Set the value of MINVIOL, the minimum violation for the current + basic solution in a generated cut. Default: 1e-3 */ + virtual void setMINVIOL(double value); + /** Get the value of MINVIOL */ + inline double getMINVIOL() const {return MINVIOL;} + + /** Maximum absolute support of the cutting planes. Default: INT_MAX. + Aliases for consistency with our naming scheme. */ + inline void setMAX_SUPP_ABS(int value) {setMAX_SUPPORT(value);} + inline int getMAX_SUPP_ABS() const {return MAX_SUPPORT;} + + /** Maximum relative support of the cutting planes. Default: 0.0. + The maximum support is MAX_SUPP_ABS + MAX_SUPPREL*ncols. */ + inline void setMAX_SUPP_REL(double value); + inline double getMAX_SUPP_REL() const {return MAX_SUPP_REL;} + + /** Set the value of USE_INTSLACKS. Default: 0 */ + virtual void setUSE_INTSLACKS(int value); + /** Get the value of USE_INTSLACKS */ + inline int getUSE_INTSLACKS() const {return USE_INTSLACKS;} + + /** Set the value of normIsZero, the threshold for considering a norm to be + 0; Default: 1e-5 */ + virtual void setNormIsZero(double value); + /** Get the value of normIsZero */ + inline double getNormIsZero() const {return normIsZero_;} + + /** Set the value of minNormReduction; Default: 0.1 */ + virtual void setMinNormReduction(double value); + /** Get the value of normIsZero */ + inline double getMinNormReduction() const {return minNormReduction_;} + + /** Set the value of maxSumMultipliers; Default: 10 */ + virtual void setMaxSumMultipliers(int value); + /** Get the value of maxSumMultipliers */ + inline int getMaxSumMultipliers() const {return maxSumMultipliers_;} + + /** Set the value of normalization; Default: 0.0001 */ + virtual void setNormalization(double value); + /** Get the value of normalization */ + inline double getNormalization() const {return normalization_;} + + /** Set the value of numRowsReduction, max number of rows that are used + * for each row reduction step. In particular, the linear system will + * involve a numRowsReduction*numRowsReduction matrix */ + virtual void addNumRowsReduction(int value); + /// get the value + inline std::vector<int> getNumRowsReduction() const {return numRowsReduction_;} + /// reset + inline void resetNumRowsReduction() {numRowsReduction_.clear();} + + /** Add the value of columnSelectionStrategy */ + virtual void addColumnSelectionStrategy(ColumnSelectionStrategy value); + /// get the value + inline std::vector<ColumnSelectionStrategy> getColumnSelectionStrategy() const {return columnSelectionStrategy_;} + /// reset + inline void resetColumnSelectionStrategy(){columnSelectionStrategy_.clear();} + + /** Set the value for rowSelectionStrategy, which changes the way we choose + * the rows for the reduction step */ + virtual void addRowSelectionStrategy(RowSelectionStrategy value); + /// get the value + inline std::vector<RowSelectionStrategy> getRowSelectionStrategy() const {return rowSelectionStrategy_;}; + /// reset + inline void resetRowSelectionStrategy() {rowSelectionStrategy_.clear();} + + /** Set the value of numRowsReductionLAP, max number of rows that are used + * for each row reduction step during Lift & Project. + * In particular, the linear system will involve a + * numRowsReduction*numRowsReduction matrix */ + virtual void addNumRowsReductionLAP(int value); + /// get the value + inline std::vector<int> getNumRowsReductionLAP() const {return numRowsReductionLAP_;} + /// reset + inline void resetNumRowsReductionLAP() {numRowsReductionLAP_.clear();} + + /** Add the value of columnSelectionStrategyLAP */ + virtual void addColumnSelectionStrategyLAP(ColumnSelectionStrategy value); + /// get the value + inline std::vector<ColumnSelectionStrategy> getColumnSelectionStrategyLAP() const {return columnSelectionStrategyLAP_;} + /// reset + inline void resetColumnSelectionStrategyLAP(){columnSelectionStrategyLAP_.clear();} + + /** Set the value for rowSelectionStrategyLAP, which changes the way we + * choose the rows for the reduction step */ + virtual void addRowSelectionStrategyLAP(RowSelectionStrategy value); + /// get the value + inline std::vector<RowSelectionStrategy> getRowSelectionStrategyLAP() const {return rowSelectionStrategyLAP_;}; + /// reset + inline void resetRowSelectionStrategyLAP() {rowSelectionStrategyLAP_.clear();} + + /** Set the value for columnScalingStrategyLAP, which sets the way nonbasic + * columns that are basic in the fractional point to cut off are scaled */ + virtual void setColumnScalingStrategyLAP(ColumnScalingStrategy value); + /// get the value + inline ColumnScalingStrategy getColumnScalingStrategyLAP() const {return columnScalingStrategyLAP_; }; + + /** Set the value for the bound in the column scaling factor */ + virtual void setColumnScalingBoundLAP(double value); + /// get the value + inline double getColumnScalingBoundLAP() const {return columnScalingBoundLAP_;}; + + /** Set the value of the time limit for cut generation (in seconds) */ + virtual void setTimeLimit(double value); + /// get the value + inline double getTimeLimit() const {return timeLimit_;} + + /** Set the value for the maximum number of cuts that can be returned */ + virtual void setMaxNumCuts(int value); + /// get the value + inline int getMaxNumCuts() const {return maxNumCuts_;} + + /** Set the value for the maximum number of cuts that can be computed */ + virtual void setMaxNumComputedCuts(int value); + /// get the value + inline int getMaxNumComputedCuts() const {return maxNumComputedCuts_;} + + /** Set the value for the maximum number of nonzeroes in a row of + * the simplex tableau for the row to be considered */ + virtual void setMaxNonzeroesTab(int value); + /// get the value + inline int getMaxNonzeroesTab() const {return maxNonzeroesTab_;} + + /** Set the value of skipGomory: should we skip simple Gomory cuts, + * i.e. GMI cuts derived from a single row of the simple tableau? + * This is 1 (true) by default: we only generate cuts from linear + * combinations of at least two rows. */ + virtual void setSkipGomory(int value); + /// get the value + inline int getSkipGomory() const {return skipGomory_;} + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor. If use_default_strategies is true, we add + /// to the list of strategies the default ones. If is false, the + /// list of strategies is left empty (must be populated before usage!). + CglRedSplit2Param(bool use_default_strategies = true, + double eps = 1e-12, + double eps_coeff = 1e-11, + double eps_elim = 0.0, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-3, + int max_supp_abs = 1000, + double max_supp_rel = 0.1, + int use_int_slacks = 0, + double norm_zero = 1e-5, + double minNormReduction = 0.1, + int maxSumMultipliers = 10, + double normalization = 0.0001, + double away = 0.005, + double timeLimit = 60, + int maxNumCuts = 10000, + int maxNumComputedCuts = 10000, + int maxNonzeroesTab = 1000, + double columnScalingBoundLAP = 5.0, + int skipGomory = 1); + + /// Constructor from CglParam. If use_default_strategies is true, we + /// add to the list of strategies the default ones. If is false, the + /// list of strategies is left empty (must be populated before + /// usage!). + CglRedSplit2Param(const CglParam &source, + bool use_default_strategies = true, + double eps_elim = 0.0, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-3, + double max_supp_rel = 0.1, + int use_int_slacks = 0, + double norm_zero = 1e-5, + double minNormReduction = 0.1, + int maxSumMultipliers = 10, + double normalization = 0.0001, + double away = 0.005, + double timeLimit = 60, + int maxNumCuts = 10000, + int maxNumComputedCuts = 10000, + int maxNonzeroesTab = 1000, + double columnScalingBoundLAP = 5.0, + int skipGomory = 1); + + /// Copy constructor + CglRedSplit2Param(const CglRedSplit2Param &source); + + /// Clone + virtual CglRedSplit2Param* clone() const; + + /// Assignment operator + virtual CglRedSplit2Param& operator=(const CglRedSplit2Param &rhs); + + /// Destructor + virtual ~CglRedSplit2Param(); + //@} + +protected: + + /**@name Parameters */ + //@{ + + /** Epsilon for value of coefficients when eliminating slack variables. + Default: 0.0. */ + double EPS_ELIM; + + /** Value added to the right hand side of each generated cut to relax it. + Default: 1e-11 */ + double EPS_RELAX_ABS; + + /** For a generated cut with right hand side rhs_val, + EPS_RELAX_EPS * fabs(rhs_val) is used to relax the constraint. + Default: 1e-13 */ + double EPS_RELAX_REL; + + // Maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e6. + double MAXDYN; + + /// Minimum violation for the current basic solution in a generated cut. + /// Default: 1e-3. + double MINVIOL; + + /// Maximum support - relative part of the formula + double MAX_SUPP_REL; + + /// Use integer slacks to generate cuts if USE_INTSLACKS = 1. Default: 0. + int USE_INTSLACKS; + + /// Norm of a vector is considered zero if smaller than normIsZero; + /// Default: 1e-5. + double normIsZero_; + + /// Minimum reduction to accept a new row. + double minNormReduction_; + + /// Maximum sum of the vector of row multipliers to generate a cut + int maxSumMultipliers_; + + /// Normalization factor for the norm of lambda in the quadratic + /// minimization problem that is solved during the coefficient reduction step + double normalization_; + + /// Use row only if pivot variable should be integer but is more + /// than away_ from being integer. Default: 0.005 + double away_; + + /// Maximum number of rows to use for the reduction of a given row. + std::vector<int> numRowsReduction_; + + /// Column selection method + std::vector<ColumnSelectionStrategy> columnSelectionStrategy_; + + /// Row selection method + std::vector<RowSelectionStrategy> rowSelectionStrategy_; + + /// Maximum number of rows to use for the reduction during Lift & Project + std::vector<int> numRowsReductionLAP_; + + /// Column selection method for Lift & Project + std::vector<ColumnSelectionStrategy> columnSelectionStrategyLAP_; + + /// Row selection method for Lift & Project + std::vector<RowSelectionStrategy> rowSelectionStrategyLAP_; + + /// Column scaling strategy for the nonbasics columns that were basic in + /// the point that we want to cut off (Lift & Project only) + ColumnScalingStrategy columnScalingStrategyLAP_; + + /// Minimum value for column scaling (Lift & Project only) + double columnScalingBoundLAP_; + + /// Time limit + double timeLimit_; + + /// Maximum number of returned cuts + int maxNumCuts_; + + /// Maximum number of computed cuts + int maxNumComputedCuts_; + + /// Maximum number of nonzeroes in tableau row for reduction + int maxNonzeroesTab_; + + /// Skip simple Gomory cuts + int skipGomory_; + + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/CglRedSplitParam.hpp b/thirdparty/linux/include/coin/CglRedSplitParam.hpp new file mode 100644 index 0000000..2601fb2 --- /dev/null +++ b/thirdparty/linux/include/coin/CglRedSplitParam.hpp @@ -0,0 +1,272 @@ +// Name: CglRedSplitParam.hpp +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 11/24/06 +// +// $Id: CglRedSplitParam.hpp 1122 2013-04-06 20:39:53Z stefan $ +//----------------------------------------------------------------------------- +// Copyright (C) 2006, Francois Margot and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglRedSplitParam_H +#define CglRedSplitParam_H + +#include "CglParam.hpp" + + + /**@name CglRedSplit Parameters */ + //@{ + + /** Class collecting parameters the Reduced-and-split cut generator. + + Parameters of the generator are listed below. Modifying the default + values for parameters other than the last four might result in + invalid cuts. + + - LUB: Value considered large for the absolute value of a lower or upper + bound on a variable. See method setLUB(). + - MAXDYN: Maximum ratio between largest and smallest non zero + coefficients in a cut. See method setMAXDYN(). + - MAXDYN_LUB: Maximum ratio between largest and smallest non zero + coefficients in a cut involving structural variables with + lower or upper bound in absolute value larger than LUB. + Should logically be larger or equal to MAXDYN. + See method setMAXDYN_LUB(). + - EPS_ELIM: Precision for deciding if a coefficient is zero when + eliminating slack variables. See method setEPS_ELIM(). + - EPS_COEFF_LUB: Precision for deciding if a coefficient of a + generated cut is zero when the corresponding + variable has a lower or upper bound larger than + LUB in absolute value. See method setEPS_COEFF_LUB(). + - MINVIOL: Minimum violation for the current basic solution in + a generated cut. See method setMINVIOL(). + - USE_INTSLACKS: Use integer slacks to generate cuts. (not implemented). + See method setUSE_INTSLACKS(). + - USE_CG2: Use alternative formula to generate a mixed integer Gomory + cut (see methods CglRedSPlit::generate_cgcut() + and CglRedSPlit::generate_cgcut_2()). See method setUSE_CG2(). + - normIsZero: Norm of a vector is considered zero if smaller than + this value. See method setNormIsZero(). + - minReduc: Reduction is performed only if the norm of the vector is + reduced by this fraction. See method setMinReduc(). + - away: Look only at basic integer variables whose current value + is at least this value from being integer. See method setAway(). + - maxTab: Controls the number of rows selected for the generation. See + method setMaxTab(). + */ + //@} + +class CglRedSplitParam : public CglParam { + +public: + + /**@name Set/get methods */ + //@{ + /** Set away, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.05 */ + virtual void setAway(const double value); + /// Get value of away + inline double getAway() const {return away_;} + + /** Set the value of LUB, value considered large for the absolute value of + a lower or upper bound on a variable; + Default: 1000 */ + virtual void setLUB(const double value); + /** Get the value of LUB */ + inline double getLUB() const {return LUB;} + + /** Set the value of EPS_ELIM, epsilon for values of coefficients when + eliminating slack variables; + Default: 1e-12 */ + void setEPS_ELIM(const double value); + /** Get the value of EPS_ELIM */ + double getEPS_ELIM() const {return EPS_ELIM;} + + /** Set EPS_RELAX_ABS */ + virtual void setEPS_RELAX_ABS(const double eps_ra); + /** Get value of EPS_RELAX_ABS */ + inline double getEPS_RELAX_ABS() const {return EPS_RELAX_ABS;} + + /** Set EPS_RELAX_REL */ + virtual void setEPS_RELAX_REL(const double eps_rr); + /** Get value of EPS_RELAX_REL */ + inline double getEPS_RELAX_REL() const {return EPS_RELAX_REL;} + + // Set the maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e8. + virtual void setMAXDYN(double value); + /** Get the value of MAXDYN */ + inline double getMAXDYN() const {return MAXDYN_LUB;} + + // Set the maximum ratio between largest and smallest non zero + // coefficient in a cut involving structural variables with + // lower or upper bound in absolute value larger than LUB. + // Should logically be larger or equal to MAXDYN. Default: 1e13. + virtual void setMAXDYN_LUB(double value); + /** Get the value of MAXDYN_LUB */ + inline double getMAXDYN_LUB() const {return MAXDYN_LUB;} + + /** Set the value of EPS_COEFF_LUB, epsilon for values of coefficients for + variables with absolute value of lower or upper bound larger than LUB; + Default: 1e-13 */ + virtual void setEPS_COEFF_LUB(const double value); + /** Get the value of EPS_COEFF_LUB */ + inline double getEPS_COEFF_LUB() const {return EPS_COEFF_LUB;} + + /** Set the value of MINVIOL, the minimum violation for the current + basic solution in a generated cut. Default: 1e-7 */ + virtual void setMINVIOL(double value); + /** Get the value of MINVIOL */ + inline double getMINVIOL() const {return MINVIOL;} + + /** Set the value of USE_INTSLACKS. Default: 0 */ + virtual void setUSE_INTSLACKS(int value); + /** Get the value of USE_INTSLACKS */ + inline int getUSE_INTSLACKS() const {return USE_INTSLACKS;} + + /** Set the value of USE_CG2. Default: 0 */ + virtual void setUSE_CG2(int value); + /** Get the value of USE_CG2 */ + inline int getUSE_CG2() const {return USE_CG2;} + + /** Set the value of normIsZero, the threshold for considering a norm to be + 0; Default: 1e-5 */ + virtual void setNormIsZero(const double value); + /** Get the value of normIsZero */ + inline double getNormIsZero() const {return normIsZero;} + + /** Set the value of minReduc, threshold for relative norm improvement for + performing a reduction; Default: 0.05 */ + virtual void setMinReduc(const double value); + /// Get the value of minReduc + inline double getMinReduc() const {return minReduc;} + + /** Set the maximum allowed value for (mTab * mTab * CoinMax(mTab, nTab)) where + mTab is the number of rows used in the combinations and nTab is the + number of continuous non basic variables. The work of the generator is + proportional to (mTab * mTab * CoinMax(mTab, nTab)). Reducing the value of + maxTab makes the generator faster, but weaker. Default: 1e7. */ + virtual void setMaxTab(const double value); + /// Get the value of maxTab + inline double getMaxTab() const {return maxTab_;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglRedSplitParam(const double lub = 1000.0, + const double eps_elim = 1e-12, + const double eps_relax_abs = 1e-8, + const double eps_relax_rel = 0.0, + const double max_dyn = 1e8, + const double max_dyn_lub = 1e13, + const double eps_coeff_lub = 1e-13, + const double min_viol = 1e-7, + const int use_int_slacks = 0, + const int use_cg2 = 0, + const double norm_zero = 1e-5, + const double min_reduc = 0.05, + const double away = 0.05, + const double max_tab = 1e7); + + /// Constructor from CglParam + CglRedSplitParam(const CglParam &source, + const double lub = 1000.0, + const double eps_elim = 1e-12, + const double eps_relax_abs = 1e-8, + const double eps_relax_rel = 0.0, + const double max_dyn = 1e8, + const double max_dyn_lub = 1e13, + const double eps_coeff_lub = 1e-13, + const double min_viol = 1e-7, + const int use_int_slacks = 0, + const int use_cg2 = 0, + const double norm_zero = 1e-5, + const double min_reduc = 0.05, + const double away = 0.05, + const double max_tab = 1e7); + + /// Copy constructor + CglRedSplitParam(const CglRedSplitParam &source); + + /// Clone + virtual CglRedSplitParam* clone() const; + + /// Assignment operator + virtual CglRedSplitParam& operator=(const CglRedSplitParam &rhs); + + /// Destructor + virtual ~CglRedSplitParam(); + //@} + +protected: + + /**@name Parameters */ + //@{ + + /** Value considered large for the absolute value of lower or upper + bound on a variable. Default: 1000. */ + double LUB; + + /** Epsilon for value of coefficients when eliminating slack variables. + Default: 1e-12. */ + double EPS_ELIM; + + /** Value added to the right hand side of each generated cut to relax it. + Default: 1e-8 */ + double EPS_RELAX_ABS; + + /** For a generated cut with right hand side rhs_val, + EPS_RELAX_EPS * fabs(rhs_val) is used to relax the constraint. + Default: 0 */ + double EPS_RELAX_REL; + + // Maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e8. + double MAXDYN; + + // Maximum ratio between largest and smallest non zero + // coefficients in a cut involving structural variables with + // lower or upper bound in absolute value larger than LUB. + // Should logically be larger or equal to MAXDYN. Default: 1e13. + double MAXDYN_LUB; + + /// Epsilon for value of coefficients for variables with absolute value of + /// lower or upper bound larger than LUB. Default: 1e-13. + double EPS_COEFF_LUB; + + /// Minimum violation for the current basic solution in a generated cut. + /// Default: 1e-7. + double MINVIOL; + + /// Use integer slacks to generate cuts if USE_INTSLACKS = 1. Default: 0. + int USE_INTSLACKS; + + /// Use second way to generate a mixed integer Gomory cut + /// (see methods generate_cgcut()) and generate_cgcut_2()). Default: 0. + int USE_CG2; + + /// Norm of a vector is considered zero if smaller than normIsZero; + /// Default: 1e-5. + double normIsZero; + + /// Minimum reduction in percent that must be achieved by a potential + /// reduction step in order to be performed; Between 0 and 1, default: 0.05. + double minReduc; + + /// Use row only if pivot variable should be integer but is more + /// than away_ from being integer. + double away_; + + /// Maximum value for (mTab * mTab * CoinMax(mTab, nTab)). See method + /// setMaxTab(). + double maxTab_; + + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/CglResidualCapacity.hpp b/thirdparty/linux/include/coin/CglResidualCapacity.hpp new file mode 100644 index 0000000..1e26e46 --- /dev/null +++ b/thirdparty/linux/include/coin/CglResidualCapacity.hpp @@ -0,0 +1,240 @@ +// LAST EDIT: +//----------------------------------------------------------------------------- +// Implementation of Residual Capacity Inequalities +// Francisco Barahona (barahon@us.ibm.com) +// +// date: May 18, 2006 +//----------------------------------------------------------------------------- +// Copyright (C) 2004, International Business Machines Corporation and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglResidualCapacity_H +#define CglResidualCapacity_H + +#include <iostream> +#include <fstream> +//#include <vector> + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" + +//============================================================================= + +#ifndef CGL_DEBUG +#define CGL_DEBUG 0 +#endif + +//============================================================================= + + + + +//============================================================================= + +/** Residual Capacity Inequalities Cut Generator Class + + References: + T Magnanti, P Mirchandani, R Vachani, + "The convex hull of two core capacitated network design problems," + Math Programming 60 (1993), 233-250. + + A Atamturk, D Rajan, + "On splittable and unsplittable flow capacitated network design + arc-set polyhedra," Math Programming 92 (2002), 315-333. **/ + +class CglResidualCapacity : public CglCutGenerator { + + friend void CglResidualCapacityUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +private: + //--------------------------------------------------------------------------- + // Enumeration constants that describe the various types of rows + enum RowType { + /** row of the type a_1 c_1 + + a_k c_k - d z_1 - - d z_p <= b, + where c_i are continuous variables and z_j are integer variables + */ + ROW_L, + /** row of the type -a_1 c_1 - - a_k c_k + d z_1 + + d z_p >= b, + where c_i are continuous variables and z_j are integer variables + */ + ROW_G, + /** equation that can be treated as ROW_L and ROW_G + */ + ROW_BOTH, + /** Other types of rows + */ + ROW_OTHER + }; + + +public: + /**@name Get and Set Parameters */ + //@{ + /// Set Epsilon + void setEpsilon(double value); + /// Get Epsilon + double getEpsilon() const; + /// Set Tolerance + void setTolerance(double value); + /// Get Tolerance + double getTolerance() const; + /// Set doPreproc + void setDoPreproc(int value); + /// Get doPreproc + bool getDoPreproc() const; + //@} + + /**@name Generate Cuts */ + //@{ + /** Generate Residual Capacity cuts for the model data + contained in si. The generated cuts are inserted + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + //--------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglResidualCapacity (); + + /// Alternate Constructor + CglResidualCapacity ( const double tolerance ); + + /// Copy constructor + CglResidualCapacity ( + const CglResidualCapacity &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglResidualCapacity & + operator=( + const CglResidualCapacity& rhs); + + /// Destructor + virtual + ~CglResidualCapacity (); + /// This is to refresh preprocessing + virtual void refreshPrep(); + //@} + + + +private: + //-------------------------------------------------------------------------- + // Private member methods + + // Construct + void gutsOfConstruct ( const double tolerance); + + // Delete + void gutsOfDelete(); + + // Copy + void gutsOfCopy (const CglResidualCapacity& rhs); + + // Do preprocessing. + // It determines the type of each row. + // It may change sense and RHS for ranged rows + void resCapPreprocess(const OsiSolverInterface& si); + + // Determine the type of a given row. + RowType determineRowType(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, const char sense, + const double rhs, + const double* colLowerBound, + const double* colUpperBound) const; + // helps the function above + bool treatAsLessThan(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, + const double rhs, + const double* colLowerBound, + const double* colUpperBound) const; + + // Generate Residual Capacity cuts + void generateResCapCuts( const OsiSolverInterface& si, + const double* xlp, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedMatrix& matrixByRow, + const double* LHS, + const double* coefByRow, + const int* colInds, + const int* rowStarts, + const int* rowLengths, + OsiCuts& cs ) const; + + + // Residual Capacity separation + bool resCapSeparation(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, + const double rhs, + const double *xlp, + const double* colUpperBound, + const double* colLowerBound, + OsiRowCut& resCapCut) const; + + + +private: + //--------------------------------------------------------------------------- + // Private member data + /** Tolerance used for numerical purposes, default value: 1.e-6 **/ + double EPSILON_; + /** If violation of a cut is greater that this number, + the cut is accepted, default value: 1.e-4 **/ + double TOLERANCE_; + /** Controls the preprocessing of the matrix to identify rows suitable for + cut generation.<UL> + <LI> -1: preprocess according to solver settings; + <LI> 0: Do preprocessing only if it has not yet been done; + <LI> 1: Do preprocessing. + </UL> + Default value: -1 **/ + int doPreproc_; + // The number of rows of the problem. + int numRows_; + // The number columns of the problem. + int numCols_; + // Indicates whether preprocessing has been done. + bool doneInitPre_; + // Array with the row types of the rows in the model. + RowType* rowTypes_; + // The indices of the rows of the initial matrix + int* indRows_; + // Sense of rows (modified if ranges) + char * sense_; + // RHS of rows (modified if ranges) + double * RHS_; + // The number of rows of type ROW_L + int numRowL_; + // The indices of the rows of type ROW_L + int* indRowL_; + // The number of rows of type ROW_G + int numRowG_; + // The indices of the rows of type ROW_G + int* indRowG_; +}; + +//############################################################################# +/** A function that tests the methods in the CglResidualCapacity class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglResidualCapacityUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +#endif diff --git a/thirdparty/linux/include/coin/CglSimpleRounding.hpp b/thirdparty/linux/include/coin/CglSimpleRounding.hpp new file mode 100644 index 0000000..b93c8bf --- /dev/null +++ b/thirdparty/linux/include/coin/CglSimpleRounding.hpp @@ -0,0 +1,174 @@ +// $Id: CglSimpleRounding.hpp 1149 2013-10-21 18:23:53Z tkr $ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglSimpleRounding_H +#define CglSimpleRounding_H + +#include <string> + +#include "CglCutGenerator.hpp" +#include "CoinPackedMatrix.hpp" + +/** Simple Rounding Cut Generator Class + + This class generates simple rounding cuts via the following method: + For each contraint, + attempt to derive a <= inequality in all integer variables + by netting out any continuous variables. + Divide the resulting integer inequality through by + the greatest common denomimator (gcd) of the lhs coefficients. + Round down the rhs. + + Warning: Use with careful attention to data precision. + + (Reference: Nemhauser and Wolsey, Integer and Combinatorial Optimization, 1988, pg 211.) +*/ + +class CglSimpleRounding : public CglCutGenerator { + friend void CglSimpleRoundingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate simple rounding cuts for the model accessed through the solver interface. + Insert generated cuts into the cut set cs. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglSimpleRounding (); + + /// Copy constructor + CglSimpleRounding ( + const CglSimpleRounding &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglSimpleRounding & + operator=( + const CglSimpleRounding& rhs); + + /// Destructor + virtual + ~CglSimpleRounding (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + + /// Derive a <= inequality in integer variables from the rowIndex-th constraint + bool deriveAnIntegerRow( + const OsiSolverInterface & si, + int rowIndex, + const CoinShallowPackedVector & matrixRow, + CoinPackedVector & irow, + double & b, + bool * negative) const; + + + /** Given a vector of doubles, x, with size elements and a positive tolerance, + dataTol, this method returns the smallest power of 10 needed so that + x[i]*10**power "is integer" for all i=0,...,size-1. + + ** change of definition of dataTol so that it refers to original + data, not to scaled data as that seems to lead to problems. + + So if xScaled is x[i]*10**power and xInt is rounded(xScaled) + then fabs(xScaled-xInt) <= dataTol*10**power. This means that + dataTol should be smaller - say 1.0e-12 rather tahn 1.0e-8 + + Returns -number of times overflowed if the power is so big that it will + cause overflow (i.e. integer stored will be bigger than 2**31). + Test in cut generator. + */ + int power10ToMakeDoubleAnInt( + int size, // the length of the vector x + const double * x, + double dataTol ) const; // the precision of the data, i.e. the positive + // epsilon, which is equivalent to zero + + /**@name Greatest common denominators methods */ + //@{ + /// Returns the greatest common denominator of two positive integers, a and b. + inline int gcd(int a, int b) const; + + /** Returns the greatest common denominator of a vector of + positive integers, vi, of length n. + */ + inline int gcdv(int n, const int * const vi) const; + //@} + + //@} + + /**@name Private member data */ + //@{ + /// A value within an epsilon_ neighborhood of 0 is considered to be 0. + double epsilon_; + //@} +}; + + +//------------------------------------------------------------------- +// Returns the greatest common denominator of two +// positive integers, a and b, found using Euclid's algorithm +//------------------------------------------------------------------- +int +CglSimpleRounding::gcd(int a, int b) const +{ + if(a > b) { + // Swap a and b + int temp = a; + a = b; + b = temp; + } + int remainder = b % a; + if (remainder == 0) return a; + else return gcd(remainder,a); +} + +//------------------------------------------------------------------- +// Returns the greatest common denominator of a vector of +// positive integers, vi, of length n. +//------------------------------------------------------------------- +int +CglSimpleRounding::gcdv(int n, const int* const vi) const +{ + if (n==0) + abort(); + + if (n==1) + return vi[0]; + + int retval=gcd(vi[0], vi[1]); + for (int i=2; i<n; i++){ + retval=gcd(retval,vi[i]); + } + return retval; +} + +//############################################################################# +/** A function that tests the methods in the CglSimpleRounding class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglSimpleRoundingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/thirdparty/linux/include/coin/CglStored.hpp b/thirdparty/linux/include/coin/CglStored.hpp new file mode 100644 index 0000000..07039d9 --- /dev/null +++ b/thirdparty/linux/include/coin/CglStored.hpp @@ -0,0 +1,125 @@ +// $Id: CglStored.hpp 1119 2013-04-06 20:24:18Z stefan $ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglStored_H +#define CglStored_H + +#include <string> + +#include "CglCutGenerator.hpp" + +class CoinWarmStartBasis; +class CglTreeProbingInfo; +/** Stored Cut Generator Class */ +class CglStored : public CglCutGenerator { + +public: + + + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Stored cuts for the model of the + solver interface, si. + + Insert the generated cuts into OsiCut, cs. + + This generator just looks at previously stored cuts + and inserts any that are violated by enough + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Change criterion on whether to include cut. + Violations of more than this will be added to current cut list + (default 1.0e-5) */ + //@{ + /// Set + inline void setRequiredViolation(double value) + { requiredViolation_=value;} + /// Get + inline double getRequiredViolation() const + { return requiredViolation_;} + /// Takes over ownership of probing info + inline void setProbingInfo(CglTreeProbingInfo * info) + { probingInfo_ = info;} + //@} + + /**@name Cut stuff */ + //@{ + /// Add cuts + void addCut(const OsiCuts & cs); + /// Add a row cut + void addCut(const OsiRowCut & cut); + /// Add a row cut from a packed vector + void addCut(double lb, double ub, const CoinPackedVector & vector); + /// Add a row cut from elements + void addCut(double lb, double ub, int size, const int * colIndices, const double * elements); + inline int sizeRowCuts() const + { return cuts_.sizeRowCuts();} + const OsiRowCut * rowCutPointer(int index) const + { return cuts_.rowCutPtr(index);} + /// Save stuff + void saveStuff(double bestObjective, const double * bestSolution, + const double * lower, const double * upper); + /// Best solution (or NULL) + inline const double * bestSolution() const + { return bestSolution_;} + /// Best objective + double bestObjective() const; + /// Tight lower bounds + const double * tightLower() const + { return bounds_;} + /// Tight upper bounds + const double * tightUpper() const + { return bounds_+numberColumns_;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglStored (int numberColumns=0); + + /// Copy constructor + CglStored (const CglStored & rhs); + + /// Constructor from file + CglStored (const char * fileName); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglStored & + operator=(const CglStored& rhs); + + /// Destructor + virtual + ~CglStored (); + //@} + +protected: + + // Protected member methods + + // Protected member data + + /**@name Protected member data */ + //@{ + /// Only add if more than this requiredViolation + double requiredViolation_; + /// Pointer to probing information + CglTreeProbingInfo * probingInfo_; + /// Cuts + OsiCuts cuts_; + /// Number of columns in model + int numberColumns_; + /// Best solution (objective at end) + double * bestSolution_; + /// Tight bounds + double * bounds_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CglTreeInfo.hpp b/thirdparty/linux/include/coin/CglTreeInfo.hpp new file mode 100644 index 0000000..4f85aca --- /dev/null +++ b/thirdparty/linux/include/coin/CglTreeInfo.hpp @@ -0,0 +1,180 @@ +// $Id: CglTreeInfo.hpp 1201 2014-03-07 17:24:04Z forrest $ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglTreeInfo_H +#define CglTreeInfo_H + +#include "OsiCuts.hpp" +#include "OsiSolverInterface.hpp" +#include "CoinHelperFunctions.hpp" +class CglStored; +/** Information about where the cut generator is invoked from. */ + +class CglTreeInfo { +public: + /// The level of the search tree node + int level; + /** How many times the cut generator was already invoked in this search tree + node */ + int pass; + /** The number of rows in the original formulation. Some generators may not + want to consider already generated rows when generating new ones. */ + int formulation_rows; + /** Options + 1 - treat costed integers as important + 2 - switch off some stuff as variables semi-integer + 4 - set global cut flag if at root node + 8 - set global cut flag if at root node and first pass + 16 - set global cut flag and make cuts globally valid + 32 - last round of cuts did nothing - maybe be more aggressive + 64 - in preprocessing stage + 128 - looks like solution + 256 - want alternate cuts + 512 - in sub tree (i.e. parent model) + 1024 - in must call again mode or after everything mode + */ + int options; + /// Set true if in tree (to avoid ambiguity at first branch) + bool inTree; + /** Replacement array. Before Branch and Cut it may be beneficial to strengthen rows + rather than adding cuts. If this array is not NULL then the cut generator can + place a pointer to the stronger cut in this array which is number of rows in size. + + A null (i.e. zero elements and free rhs) cut indicates that the row is useless + and can be removed. + + The calling function can then replace those rows. + */ + OsiRowCut ** strengthenRow; + /// Optional pointer to thread specific random number generator + CoinThreadRandom * randomNumberGenerator; + /// Default constructor + CglTreeInfo (); + + /// Copy constructor + CglTreeInfo ( + const CglTreeInfo &); + /// Clone + virtual CglTreeInfo * clone() const; + + /// Assignment operator + CglTreeInfo & + operator=( + const CglTreeInfo& rhs); + + /// Destructor + virtual + ~CglTreeInfo (); + /// Take action if cut generator can fix a variable (toValue -1 for down, +1 for up) + virtual bool fixes(int , int , int ,bool) {return false;} + /** Initalizes fixing arrays etc - returns >0 if we want to save info + 0 if we don't and -1 if is to be used */ + virtual int initializeFixing(const OsiSolverInterface * ) {return 0;} + +}; + +/** Derived class to pick up probing info. */ +typedef struct { + //unsigned int oneFixed:1; // nonzero if variable to 1 fixes all + //unsigned int sequence:31; // variable (in matrix) (but also see cliqueRow_) + unsigned int fixes; +} CliqueEntry; + +class CglTreeProbingInfo : public CglTreeInfo { +public: + /// Default constructor + CglTreeProbingInfo (); + /// Constructor from model + CglTreeProbingInfo (const OsiSolverInterface * model); + + /// Copy constructor + CglTreeProbingInfo ( + const CglTreeProbingInfo &); + /// Clone + virtual CglTreeInfo * clone() const; + + /// Assignment operator + CglTreeProbingInfo & + operator=( + const CglTreeProbingInfo& rhs); + + /// Destructor + virtual + ~CglTreeProbingInfo (); + OsiSolverInterface * analyze(const OsiSolverInterface & si, int createSolver=0, + int numberExtraCliques=0,const int * starts=NULL, + const CliqueEntry * entries=NULL,const char * type=NULL); + /** Take action if cut generator can fix a variable + (toValue -1 for down, +1 for up) + Returns true if still room, false if not */ + virtual bool fixes(int variable, int toValue, int fixedVariable,bool fixedToLower); + /** Initalizes fixing arrays etc - returns >0 if we want to save info + 0 if we don't and -1 if is to be used */ + virtual int initializeFixing(const OsiSolverInterface * model) ; + /// Fix entries in a solver using implications + int fixColumns(OsiSolverInterface & si) const; + /// Fix entries in a solver using implications for one variable + int fixColumns(int iColumn, int value, OsiSolverInterface & si) const; + /// Packs down entries + int packDown(); + /// Generate cuts from implications + void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info) const; + /// Entries for fixing variables + inline CliqueEntry * fixEntries() + { convert(); return fixEntry_;} + /// Starts of integer variable going to zero + inline int * toZero() + { convert(); return toZero_;} + /// Starts of integer variable going to one + inline int * toOne() + { convert(); return toOne_;} + /// List of 0-1 integer variables + inline int * integerVariable() const + { return integerVariable_;} + /// Backward look up + inline int * backward() const + { return backward_;} + /// Number of variables + inline int numberVariables() const + { return numberVariables_;} + /// Number of 0-1 variables + inline int numberIntegers() const + { return numberIntegers_;} +private: + /// Converts to ordered + void convert(); +protected: + /// Entries for fixing variables + CliqueEntry * fixEntry_; + /// Starts of integer variable going to zero + int * toZero_; + /// Starts of integer variable going to one + int * toOne_; + /// List of 0-1 integer variables + int * integerVariable_; + /// Backward look up + int * backward_; + /// Entries for fixing variable when collecting + int * fixingEntry_; + /// Number of variables + int numberVariables_; + /// Number of 0-1 variables + int numberIntegers_; + /// Maximum number in fixEntry_ + int maximumEntries_; + /// Number entries in fixingEntry_ (and fixEntry_) or -2 if correct style + int numberEntries_; +}; +inline int sequenceInCliqueEntry(const CliqueEntry & cEntry) +{ return cEntry.fixes&0x7fffffff;} +inline void setSequenceInCliqueEntry(CliqueEntry & cEntry,int sequence) +{ cEntry.fixes = sequence|(cEntry.fixes&0x80000000);} +inline bool oneFixesInCliqueEntry(const CliqueEntry & cEntry) +{ return (cEntry.fixes&0x80000000)!=0;} +inline void setOneFixesInCliqueEntry(CliqueEntry & cEntry,bool oneFixes) +{ cEntry.fixes = (oneFixes ? 0x80000000 : 0)|(cEntry.fixes&0x7fffffff);} + +#endif diff --git a/thirdparty/linux/include/coin/CglTwomir.hpp b/thirdparty/linux/include/coin/CglTwomir.hpp new file mode 100644 index 0000000..ba00380 --- /dev/null +++ b/thirdparty/linux/include/coin/CglTwomir.hpp @@ -0,0 +1,565 @@ +// $Id: CglTwomir.hpp 1119 2013-04-06 20:24:18Z stefan $ +// 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). + +#ifndef CglTwomir_H +#define CglTwomir_H +#include <string> + +#include "CglCutGenerator.hpp" +#include "CoinFactorization.hpp" + +typedef struct +{ + + int nz; /* current length of arrays index[] and coeff[] */ + int max_nz; /* max length of arrays index[] and coeff[] */ + double *coeff; /* coefficient of each variable in the constraint */ + int *index; /* index of the variable (value in 0 ... nrow+ncol) */ + double rhs; /* rhs of the constraint */ + char sense; /* ?? is it necessary */ + +} DGG_constraint_t; + +typedef struct{ + int n; + DGG_constraint_t **c; + int *ctype; + double *alpha; +} DGG_list_t; + +/******************** BASIS INFORMATION ADTs **********************************/ +typedef struct{ + int q_min; + int q_max; + int t_min; + int t_max; + int a_max; + int max_elements; +} cutParams; + +typedef struct +{ + double gomory_threshold; /* factional variable must be this away from int */ + int ncol, /* number of columns in LP */ + nrow, /* number of constaints in LP */ + ninteger; /* number of integer variables in LP */ + + int nbasic_col, /* number of basic columns in the LP */ + nbasic_row; /* number of basic rows in the LP */ + + /* the following arrays are all of size (ncol+nrow) */ + int *info; /* description of each variable (see below) */ + double *lb; /* specifies the lower bound (if any) of each variable */ + double *ub; /* specifies the upper bound (if any) of each variable */ + double *x; /* current solution */ + double *rc; /* current reduced cost */ + double *opt_x; + + cutParams cparams; +} DGG_data_t; + +/* the following macros allow us to decode the info of the DGG_data + type. The encoding is as follows, + bit 1 : if the variable is basic or not (non-basic). + bit 2 : if the variable is integer or or not (rational). + bit 3 : if the variable is structural or not (artifical). + bit 4 : if the variable is non-basic and at its upper bound + (else if non-basic at lower bound). */ + +#define DGG_isBasic(data,idx) ((data->info[idx])&1) +#define DGG_isInteger(data,idx) ((data->info[idx] >> 1)&1) +#define DGG_isStructural(data,idx) ((data->info[idx] >> 2)&1) +#define DGG_isEqualityConstraint(data,idx) ((data->info[idx] >> 3)&1) +#define DGG_isNonBasicAtUB(data,idx) ((data->info[idx] >> 4)&1) +#define DGG_isNonBasicAtLB(data,idx) ((data->info[idx] >> 5)&1) +#define DGG_isConstraintBoundedAbove(data,idx) ((data->info[idx] >> 6)&1) +#define DGG_isConstraintBoundedBelow(data,idx) ((data->info[idx] >> 7)&1) + +#define DGG_setIsBasic(data,idx) ((data->info[idx]) |= 1) +#define DGG_setIsInteger(data,idx) ((data->info[idx]) |= (1<<1)) +#define DGG_setIsStructural(data,idx) ((data->info[idx]) |= (1<<2)) +#define DGG_setEqualityConstraint(data,idx) ((data->info[idx]) |= (1<<3)) +#define DGG_setIsNonBasicAtUB(data,idx) ((data->info[idx]) |= (1<<4)) +#define DGG_setIsNonBasicAtLB(data,idx) ((data->info[idx]) |= (1<<5)) +#define DGG_setIsConstraintBoundedAbove(data,idx) ((data->info[idx]) |= (1<<6)) +#define DGG_setIsConstraintBoundedBelow(data,idx) ((data->info[idx]) |= (1<<7)) + +class CoinWarmStartBasis; +/** Twostep MIR Cut Generator Class */ +class CglTwomir : public CglCutGenerator { + + friend void CglTwomirUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +public: + + /// Problem name + std::string probname_; + + /**@name Generate Cuts */ + //@{ + /** Generate Two step MIR cuts either from the tableau rows or from the + formulation rows + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const; + + /**@name Change criterion on which scalings to use (default = 1,1,1,1) */ + //@{ + /// Set + void setMirScale (int tmin, int tmax) {t_min_ = tmin; t_max_ = tmax;} + void setTwomirScale (int qmin, int qmax) {q_min_ = qmin; q_max_ = qmax;} + void setAMax (int a) {a_max_ = a;} + void setMaxElements (int n) {max_elements_ = n;} + void setMaxElementsRoot (int n) {max_elements_root_ = n;} + void setCutTypes (bool mir, bool twomir, bool tab, bool form) + { do_mir_ = mir; do_2mir_ = twomir; do_tab_ = tab; do_form_ = form;} + void setFormulationRows (int n) {form_nrows_ = n;} + + /// Get + int getTmin() const {return t_min_;} + int getTmax() const {return t_max_;} + int getQmin() const {return q_min_;} + int getQmax() const {return q_max_;} + int getAmax() const {return a_max_;} + int getMaxElements() const {return max_elements_;} + int getMaxElementsRoot() const {return max_elements_root_;} + int getIfMir() const { return do_mir_;} + int getIfTwomir() const { return do_2mir_;} + int getIfTableau() const { return do_tab_;} + int getIfFormulation() const { return do_form_;} + //@} + + /**@name Change criterion on which variables to look at. All ones + more than "away" away from integrality will be investigated + (default 0.05) */ + //@{ + /// Set away + void setAway(double value); + /// Get away + double getAway() const; + /// Set away at root + void setAwayAtRoot(double value); + /// Get away at root + double getAwayAtRoot() const; + /// Return maximum length of cut in tree + virtual int maximumLengthOfCutInTree() const + { return max_elements_;} + //@} + + /**@name Change way TwoMir works */ + //@{ + /// Pass in a copy of original solver (clone it) + void passInOriginalSolver(OsiSolverInterface * solver); + /// Returns original solver + inline OsiSolverInterface * originalSolver() const + { return originalSolver_;} + /// Set type - 0 normal, 1 add original matrix one, 2 replace + inline void setTwomirType(int type) + { twomirType_=type;} + /// Return type + inline int twomirType() const + { return twomirType_;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglTwomir (); + + /// Copy constructor + CglTwomir (const CglTwomir &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglTwomir & operator=(const CglTwomir& rhs); + + /// Destructor + virtual ~CglTwomir (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +private: + // Private member data + /**@name Private member data */ + //@{ + /// Threadsafe random number generator + CoinThreadRandom randomNumberGenerator_; + /// Original solver + OsiSolverInterface * originalSolver_; + /// Only investigate if more than this away from integrality + double away_; + /// Only investigate if more than this away from integrality (at root) + double awayAtRoot_; + /// Type - 0 normal, 1 add original matrix one, 2 replace + int twomirType_; + bool do_mir_; + bool do_2mir_; + bool do_tab_; + bool do_form_; + + int t_min_; /// t_min - first value of t to use for tMIR inequalities + int t_max_; /// t_max - last value of t to use for tMIR inequalities + int q_min_; /// q_min - first value of t to use for 2-Step tMIR inequalities + int q_max_; /// q_max - last value of t to use for 2-Step tMIR inequalities + int a_max_; /// a_max - maximum value of bhat/alpha + int max_elements_; /// Maximum number of elements in cut + int max_elements_root_; /// Maximum number of elements in cut at root + int form_nrows_; //number of rows on which formulation cuts will be generated + //@} +}; + +//############################################################################# + +/* +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <math.h> +#include <float.h> +#include <cassert> +#include <iostream.h> +*/ + +/******************** DEBUG DEFINITIONS ***************************************/ + +#define DGG_DEBUG_DGG 1 +#define DGG_TRACE_ERRORS 0 +#define DGG_DISPLAY 0 +#define DGG_AUTO_CHECK_CUT_OFF_OPTIMAL 1 + +/******************** CONFIGURATION DEFAULTS **********************************/ + +#define DGG_DEFAULT_METHOD 2 +#define DGG_DEFAULT_TMIN 1 +#define DGG_DEFAULT_TMAX 1 +#define DGG_DEFAULT_TAUMIN 2 +#define DGG_DEFAULT_TAUMAX 6 +#define DGG_DEFAULT_MAX_CUTS 500 +#define DGG_DEFAULT_IMPROVEMENT_THRESH 0.001 +#define DGG_DEFAULT_NBELOW_THRESH INT_MAX +#define DGG_DEFAULT_NROOT_ROUNDS 2 +#define DGG_DEFAULT_NEGATIVE_SCALED_TWOSTEPS 0 +#define DGG_DEFAULT_ALPHA_RULE 0 +#define DGG_DEFAULT_CUT_INC 250 +#define DGG_DEFAULT_CUT_FORM 0 +#define DGG_DEFAULT_NICEFY 0 +#define DGG_DEFAULT_ONLY_DELAYED 0 +#define DGG_DEFAULT_DELAYED_FREQ 9999999 +#define DGG_DEFAULT_LPROWS_FREQ 9999999 +#define DGG_DEFAULT_WHICH_FORMULATION_CUTS 2 + +/******************** SOLVER CONFIGURATION DEFINITIONS ************************/ + +#define DGG_OSI 0 +#define DGG_CPX 1 +#define DGG_QSO 2 + +/* determines the solver to be used */ +#define DGG_SOLVER DGG_OSI + +/* adds checking routines to make sure solver works as expected */ +#define DGG_DEBUG_SOLVER 0 + +/* turn off screen output from solver */ +#define DGG_SOLVER_SCREEN_FLAG 0 + +/******************** CUT DEFINITIONS *****************************************/ + +/* internal names for cut types */ +#define DGG_TMIR_CUT 1 +#define DGG_2STEP_CUT 2 + +/* internal names for alpha-selection rules */ +#define DGG_ALPHA_MIN_SUM 0 +#define DGG_ALPHA_RANDOM_01 1 +#define DGG_ALPHA_RANDOM_COEFF 2 +#define DGG_ALPHA_ALL 3 +#define DGG_ALPHA_MAX_STEEP 5 + +/******************** PRECISION & NUMERICAL ISSUES DEFINITIONS ****************/ + +/* how steep a cut must be before adding it to the lp */ +#define DGG_MIN_STEEPNESS 1.0e-4 +#define DGG_MAX_L2NORM 1.0e7 + +/* 0 = min steepness, 1 = max norm */ +#define DGG_NORM_CRITERIA 1 + +/* internal representation of +infinity */ +#define UB_MAX DBL_MAX + +/* used to define how fractional a basic-integer variable must be + before choosing to use it to generate a TMIR cut on. + OSI's default is 1.0e-7 */ +#define DGG_GOMORY_THRESH 0.005 + +#define DGG_RHS_THRESH 0.005 + +/* used for comparing variables to their upper bounds. + OSI's default is 1.0e-7. + We set it to 1.0e6 because e-7 seems too sensitive. + In fact, with e-7 the problem dsbmip.mps complains. */ +#define DGG_BOUND_THRESH 1.0e-6 + +/* used for comparing the lhs (activity) value of a tableau row + with the rhs. This is only used for debugging purposes. */ +#define DGG_EQUALITY_THRESH 1.0e-5 + +/* used for comparing a variable's lower bound to 0.0 + and determining if we need to shift the variable */ +#define DGG_SHIFT_THRESH 1.0e-6 + +/* used for determing how far from an integer is still an integer. + This value is used for comparing coefficients to integers. + OSI's default is 1.0e-10. */ +#define DGG_INTEGRALITY_THRESH 1.0e-10 + +/* the min value that a coeff can have in the tableau row + before being set to zero. */ +#define CBC_CHECK_CUT +#ifndef CBC_CHECK_CUT +#define DGG_MIN_TABLEAU_COEFFICIENT 1.0e-8 +#else +#define DGG_MIN_TABLEAU_COEFFICIENT 1.0e-12 +#endif + +/* smallest value rho is allowed to have for a simple 2-step MIR + (ie: not an extended two-step MIR) */ +#define DGG_MIN_RHO 1.0e-7 +#define DGG_MIN_ALPHA 1.0e-7 + +/* when a slack is null: used to check if a cut is satisfied or not. */ +#define DGG_NULL_SLACK 1.0e-5 + +/* nicefy constants */ +#define DGG_NICEFY_MIN_ABSVALUE 1.0e-13 +#define DGG_NICEFY_MIN_FIX 1.0e-7 +#define DGG_NICEFY_MAX_PADDING 1.0e-6 +#define DGG_NICEFY_MAX_RATIO 1.0e9 + + +/******************** ERROR-CATCHING MACROS ***********************************/ +#if DGG_TRACE_ERRORS > 0 + +#define __DGG_PRINT_LOC__(F) fprintf(((F==0)?stdout:F), " in %s (%s:%d)\n", __func__, __FILE__, __LINE__) + +#define DGG_THROW(A,REST...) {\ + fprintf(stdout, ##REST); \ + __DGG_PRINT_LOC__(stdout); \ + return (A);} + +#define DGG_IF_EXIT(A,B,REST...) {\ + if(A) {\ + fprintf(stdout, ##REST); \ + __DGG_PRINT_LOC__(stdout); \ + exit(B);}} + +#define DGG_CHECKRVAL(A,B) {\ + if(A) {\ + __DGG_PRINT_LOC__(stdout); \ + return B; } } + +#define DGG_CHECKRVAL1(A,B) {\ + if(A) {\ + __DGG_PRINT_LOC__(stdout); \ + rval = B; goto CLEANUP; } } + +#define DGG_WARNING(A, REST...) {\ + if(A) {\ + fprintf(stdout, ##REST); \ + __DGG_PRINT_LOC__(stdout); \ + }} + +#define DGG_TEST(A,B,REST...) {\ + if(A) DGG_THROW(B,##REST) } + +#define DGG_TEST2(A,B,C,REST) {DGG_TEST(A,B,C,REST) } +#define DGG_TEST3(A,B,C,D,REST) {DGG_TEST(A,B,C,D,REST) } + +#else + +#define DGG_IF_EXIT(A,B,REST) {if(A) {fprintf(stdout, REST);exit(B);}} + +#define DGG_THROW(A,B) return(A) + +#define DGG_CHECKRVAL(A,B) { if(A) return(B); } +#define DGG_CHECKRVAL1(A,B){ if(A) { rval = B; goto CLEANUP; } } + +#define DGG_TEST(A,B,REST) { if(A) return(B);} +#define DGG_TEST2(A,B,REST,C) { DGG_TEST(A,B,REST) } +#define DGG_TEST3(A,B,REST,C,D) { DGG_TEST(A,B,REST) } + +#endif + +/******************** SIMPLE MACROS AND FUNCTIONS *****************************/ + +#define DGG_MIN(a,b) ( (a<b)?a:b ) +#define DGG_MAX(a,b) ( (a>b)?a:b ) +#define KREM(vht,alpha,tau) (DGG_MIN( ceil(vht / alpha), tau ) - 1) +#define LMIN(vht, d, bht) (DGG_MIN( floor(d*bht/bht), d)) +#define ABOV(v) (v - floor(v)) +#define QINT(vht,bht,tau) ( (int)floor( (vht*(tau-1))/bht ) ) +#define V2I(bht,tau,i) ( ((i+1)*bht / tau) ) + +int DGG_is_even(double vht, double bht, int tau, int q); +double frac_part(double value); +int DGG_is_a_multiple_of_b(double a, double b); + + +/* free function for DGG_data_t. Frees internal arrays and data structure */ +int DGG_freeData( DGG_data_t *data ); + +/******************** CONSTRAINT ADTs *****************************************/ +DGG_constraint_t* DGG_newConstraint(int max_arrays); +void DGG_freeConstraint(DGG_constraint_t *c); +DGG_constraint_t *DGG_copyConstraint(DGG_constraint_t *c); +void DGG_scaleConstraint(DGG_constraint_t *c, int t); + +/******************** CONFIGURATION *******************************************/ +void DGG_list_init (DGG_list_t *l); +int DGG_list_addcut (DGG_list_t *l, DGG_constraint_t *cut, int ctype, double alpha); +void DGG_list_delcut (DGG_list_t *l, int i); +void DGG_list_free(DGG_list_t *l); + +/******************* SOLVER SPECIFIC METHODS **********************************/ +DGG_data_t *DGG_getData(const void *solver_ptr); + +/******************* CONSTRAINT MANIPULATION **********************************/ + +/* DGG_transformConstraint: manipulates a constraint in the following way: + +packs everything in output + +1 - variables at their upper bounds are substituted for their +complements. This is done by adjusting the coefficients and +the right hand side (simple substitution). + +2 - variables with non-zero lower bounds are shifted. */ + +int DGG_transformConstraint( DGG_data_t *data, + double **x_out, + double **rc_out, + char **isint_out, + DGG_constraint_t *constraint ); + +/* DGG_unTransformConstraint : + +1 - Undoes step (1) of DGG_transformConstraint +2 - Undoes step (2) of DGG_transformConstraint */ + +int DGG_unTransformConstraint( DGG_data_t *data, + DGG_constraint_t *constraint ); + +/* substitutes each slack variable by the structural variables which + define it. This function, hence, changes the constraint 'cut'. */ + +int DGG_substituteSlacks( const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t *cut ); + +int DGG_nicefyConstraint( const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t *cut); + +/******************* CUT GENERATION *******************************************/ +int DGG_getFormulaConstraint( int row_idx, + const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t* row ); + +int DGG_getTableauConstraint( int index, + const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t* tabrow, + const int * colIsBasic, + const int * rowIsBasic, + CoinFactorization & factorization, + int mode ); + +DGG_constraint_t* DGG_getSlackExpression(const void *solver_ptr, DGG_data_t* data, int row_index); + + int DGG_generateTabRowCuts( DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr ); + + int DGG_generateFormulationCuts( DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr, + int nrows, + CoinThreadRandom & generator); + + + int DGG_generateFormulationCutsFromBase( DGG_constraint_t *base, + double slack, + DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr, + CoinThreadRandom & generator); + + int DGG_generateCutsFromBase( DGG_constraint_t *base, + DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr ); + +int DGG_buildMir( char *isint, + DGG_constraint_t *base, + DGG_constraint_t **cut_out ); + +int DGG_build2step( double alpha, + char *isint, + DGG_constraint_t *base, + DGG_constraint_t **cut_out ); + + int DGG_addMirToList ( DGG_constraint_t *base, + char *isint, + double *x, + DGG_list_t *list, + DGG_data_t *data, + DGG_constraint_t *orig_base ); + + int DGG_add2stepToList ( DGG_constraint_t *base, + char *isint, + double *x, + double *rc, + DGG_list_t *list, + DGG_data_t *data, + DGG_constraint_t *orig_base ); + +/******************* CUT INFORMATION ******************************************/ + +double DGG_cutLHS(DGG_constraint_t *c, double *x); +int DGG_isCutDesirable(DGG_constraint_t *c, DGG_data_t *d); + +/******************* TEST / DEBUGGING ROUTINES ********************************/ + +int DGG_isConstraintViolated(DGG_data_t *d, DGG_constraint_t *c); + +int DGG_isBaseTrivial(DGG_data_t *d, DGG_constraint_t* c); +int DGG_is2stepValid(double alpha, double bht); + +int DGG_cutsOffPoint(double *x, DGG_constraint_t *cut); + +//############################################################################# +/** A function that tests the methods in the CglTwomir class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglTwomirUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +#endif + + diff --git a/thirdparty/linux/include/coin/CglZeroHalf.hpp b/thirdparty/linux/include/coin/CglZeroHalf.hpp new file mode 100644 index 0000000..929269a --- /dev/null +++ b/thirdparty/linux/include/coin/CglZeroHalf.hpp @@ -0,0 +1,133 @@ +// $Id: CglZeroHalf.hpp 1122 2013-04-06 20:39:53Z stefan $ +// Copyright (C) 2010, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +#ifndef CglZeroHalf_H +#define CglZeroHalf_H + +#include <string> + +#include "CglCutGenerator.hpp" +#include "CoinPackedMatrix.hpp" +#include "Cgl012cut.hpp" + +/** Zero Half Cut Generator Class + + This class generates zero half cuts via the following method: + + See - + +G. Andreello, A. Caprara, M. Fischetti, + “Embedding Cuts in a Branch and Cut Framework: a Computational Study + with {0,1/2}-Cuts”, INFORMS Journal on Computing 19(2), 229-238, 2007. + +*/ + +class CglZeroHalf : public CglCutGenerator { + friend void CglZeroHalfUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate zero half cuts for the model accessed through the solver interface. + Insert generated cuts into the cut set cs. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Sets and Gets */ + //@{ + /// Get flags + inline int getFlags() const + { return flags_;} + /// Set flags + inline void setFlags(int value) + { flags_ = value;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglZeroHalf (); + + /// Copy constructor + CglZeroHalf ( + const CglZeroHalf &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglZeroHalf & + operator=( + const CglZeroHalf& rhs); + + /// Destructor + virtual + ~CglZeroHalf (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + //@} + + + /**@name Private member data */ + //@{ + /// number of rows in the ILP matrix + int mr_; + /// number of columns in the ILP matrix + int mc_; + /// number of nonzero's in the ILP matrix + int mnz_; + /// starting position of each row in arrays mtind and mtval + int *mtbeg_; + /// number of entries of each row in arrays mtind and mtval + int *mtcnt_; + /// column indices of the nonzero entries of the ILP matrix + int *mtind_; + /// values of the nonzero entries of the ILP matrix + int *mtval_; + /// lower bounds on the variables + int *vlb_; + /// upper bounds on the variables + int *vub_; + /// right hand sides of the constraints + int *mrhs_; + /// senses of the constraints: 'L', 'G' or 'E' + char *msense_; + /// Cgl012Cut object to make thread safe + Cgl012Cut cutInfo_; + /** Flags + 1 bit - global cuts + */ + int flags_; + //@} +}; +/// A simple Dijkstra shortest path - make better later +#ifndef CGL_NEW_SHORT +void cglShortestPath(cgl_graph * graph, int source, int maximumLength); +#else +void cglShortestPath(auxiliary_graph * graph, int source, int maximumLength); +#endif +//############################################################################# +/** A function that tests the methods in the CglZeroHalf class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglZeroHalfUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/thirdparty/linux/include/coin/ClpCholeskyBase.hpp b/thirdparty/linux/include/coin/ClpCholeskyBase.hpp new file mode 100644 index 0000000..815af01 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpCholeskyBase.hpp @@ -0,0 +1,294 @@ +/* $Id: ClpCholeskyBase.hpp 1722 2011-04-17 09:58:37Z stefan $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpCholeskyBase_H +#define ClpCholeskyBase_H + +#include "CoinPragma.hpp" +#include "CoinTypes.hpp" +//#define CLP_LONG_CHOLESKY 0 +#ifndef CLP_LONG_CHOLESKY +#define CLP_LONG_CHOLESKY 0 +#endif +/* valid combinations are + CLP_LONG_CHOLESKY 0 and COIN_LONG_WORK 0 + CLP_LONG_CHOLESKY 1 and COIN_LONG_WORK 1 + CLP_LONG_CHOLESKY 2 and COIN_LONG_WORK 1 +*/ +#if COIN_LONG_WORK==0 +#if CLP_LONG_CHOLESKY>0 +#define CHOLESKY_BAD_COMBINATION +#endif +#else +#if CLP_LONG_CHOLESKY==0 +#define CHOLESKY_BAD_COMBINATION +#endif +#endif +#ifdef CHOLESKY_BAD_COMBINATION +# warning("Bad combination of CLP_LONG_CHOLESKY and COIN_BIG_DOUBLE/COIN_LONG_WORK"); +"Bad combination of CLP_LONG_CHOLESKY and COIN_LONG_WORK" +#endif +#if CLP_LONG_CHOLESKY>1 +typedef long double longDouble; +#define CHOL_SMALL_VALUE 1.0e-15 +#elif CLP_LONG_CHOLESKY==1 +typedef double longDouble; +#define CHOL_SMALL_VALUE 1.0e-11 +#else +typedef double longDouble; +#define CHOL_SMALL_VALUE 1.0e-11 +#endif +class ClpInterior; +class ClpCholeskyDense; +class ClpMatrixBase; + +/** Base class for Clp Cholesky factorization + Will do better factorization. very crude ordering + + Derived classes may be using more sophisticated methods +*/ + +class ClpCholeskyBase { + +public: + /**@name Virtual methods that the derived classes may provide */ + //@{ + /** Orders rows and saves pointer to matrix.and model. + returns non-zero if not enough memory. + You can use preOrder to set up ADAT + If using default symbolic etc then must set sizeFactor_ to + size of input matrix to order (and to symbolic). + Also just permute_ and permuteInverse_ should be created */ + virtual int order(ClpInterior * model); + /** Does Symbolic factorization given permutation. + This is called immediately after order. If user provides this then + user must provide factorize and solve. Otherwise the default factorization is used + returns non-zero if not enough memory */ + virtual int symbolic(); + /** Factorize - filling in rowsDropped and returning number dropped. + If return code negative then out of memory */ + virtual int factorize(const CoinWorkDouble * diagonal, int * rowsDropped) ; + /** Uses factorization to solve. */ + virtual void solve (CoinWorkDouble * region) ; + /** Uses factorization to solve. - given as if KKT. + region1 is rows+columns, region2 is rows */ + virtual void solveKKT (CoinWorkDouble * region1, CoinWorkDouble * region2, const CoinWorkDouble * diagonal, + CoinWorkDouble diagonalScaleFactor); +private: + /// AMD ordering + int orderAMD(); +public: + //@} + + /**@name Gets */ + //@{ + /// status. Returns status + inline int status() const { + return status_; + } + /// numberRowsDropped. Number of rows gone + inline int numberRowsDropped() const { + return numberRowsDropped_; + } + /// reset numberRowsDropped and rowsDropped. + void resetRowsDropped(); + /// rowsDropped - which rows are gone + inline char * rowsDropped() const { + return rowsDropped_; + } + /// choleskyCondition. + inline double choleskyCondition() const { + return choleskyCondition_; + } + /// goDense i.e. use dense factoriaztion if > this (default 0.7). + inline double goDense() const { + return goDense_; + } + /// goDense i.e. use dense factoriaztion if > this (default 0.7). + inline void setGoDense(double value) { + goDense_ = value; + } + /// rank. Returns rank + inline int rank() const { + return numberRows_ - numberRowsDropped_; + } + /// Return number of rows + inline int numberRows() const { + return numberRows_; + } + /// Return size + inline CoinBigIndex size() const { + return sizeFactor_; + } + /// Return sparseFactor + inline longDouble * sparseFactor() const { + return sparseFactor_; + } + /// Return diagonal + inline longDouble * diagonal() const { + return diagonal_; + } + /// Return workDouble + inline longDouble * workDouble() const { + return workDouble_; + } + /// If KKT on + inline bool kkt() const { + return doKKT_; + } + /// Set KKT + inline void setKKT(bool yesNo) { + doKKT_ = yesNo; + } + /// Set integer parameter + inline void setIntegerParameter(int i, int value) { + integerParameters_[i] = value; + } + /// get integer parameter + inline int getIntegerParameter(int i) { + return integerParameters_[i]; + } + /// Set double parameter + inline void setDoubleParameter(int i, double value) { + doubleParameters_[i] = value; + } + /// get double parameter + inline double getDoubleParameter(int i) { + return doubleParameters_[i]; + } + //@} + + +public: + + /**@name Constructors, destructor + */ + //@{ + /** Constructor which has dense columns activated. + Default is off. */ + ClpCholeskyBase(int denseThreshold = -1); + /** Destructor (has to be public) */ + virtual ~ClpCholeskyBase(); + /// Copy + ClpCholeskyBase(const ClpCholeskyBase&); + /// Assignment + ClpCholeskyBase& operator=(const ClpCholeskyBase&); + //@} + //@{ + ///@name Other + /// Clone + virtual ClpCholeskyBase * clone() const; + + /// Returns type + inline int type() const { + if (doKKT_) return 100; + else return type_; + } +protected: + /// Sets type + inline void setType(int type) { + type_ = type; + } + /// model. + inline void setModel(ClpInterior * model) { + model_ = model; + } + //@} + + /**@name Symbolic, factor and solve */ + //@{ + /** Symbolic1 - works out size without clever stuff. + Uses upper triangular as much easier. + Returns size + */ + int symbolic1(const CoinBigIndex * Astart, const int * Arow); + /** Symbolic2 - Fills in indices + Uses lower triangular so can do cliques etc + */ + void symbolic2(const CoinBigIndex * Astart, const int * Arow); + /** Factorize - filling in rowsDropped and returning number dropped + in integerParam. + */ + void factorizePart2(int * rowsDropped) ; + /** solve - 1 just first half, 2 just second half - 3 both. + If 1 and 2 then diagonal has sqrt of inverse otherwise inverse + */ + void solve(CoinWorkDouble * region, int type); + /// Forms ADAT - returns nonzero if not enough memory + int preOrder(bool lowerTriangular, bool includeDiagonal, bool doKKT); + /// Updates dense part (broken out for profiling) + void updateDense(longDouble * d, /*longDouble * work,*/ int * first); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// type (may be useful) if > 20 do KKT + int type_; + /// Doing full KKT (only used if default symbolic and factorization) + bool doKKT_; + /// Go dense at this fraction + double goDense_; + /// choleskyCondition. + double choleskyCondition_; + /// model. + ClpInterior * model_; + /// numberTrials. Number of trials before rejection + int numberTrials_; + /// numberRows. Number of Rows in factorization + int numberRows_; + /// status. Status of factorization + int status_; + /// rowsDropped + char * rowsDropped_; + /// permute inverse. + int * permuteInverse_; + /// main permute. + int * permute_; + /// numberRowsDropped. Number of rows gone + int numberRowsDropped_; + /// sparseFactor. + longDouble * sparseFactor_; + /// choleskyStart - element starts + CoinBigIndex * choleskyStart_; + /// choleskyRow (can be shorter than sparsefactor) + int * choleskyRow_; + /// Index starts + CoinBigIndex * indexStart_; + /// Diagonal + longDouble * diagonal_; + /// double work array + longDouble * workDouble_; + /// link array + int * link_; + // Integer work array + CoinBigIndex * workInteger_; + // Clique information + int * clique_; + /// sizeFactor. + CoinBigIndex sizeFactor_; + /// Size of index array + CoinBigIndex sizeIndex_; + /// First dense row + int firstDense_; + /// integerParameters + int integerParameters_[64]; + /// doubleParameters; + double doubleParameters_[64]; + /// Row copy of matrix + ClpMatrixBase * rowCopy_; + /// Dense indicators + char * whichDense_; + /// Dense columns (updated) + longDouble * denseColumn_; + /// Dense cholesky + ClpCholeskyDense * dense_; + /// Dense threshold (for taking out of Cholesky) + int denseThreshold_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpCholeskyDense.hpp b/thirdparty/linux/include/coin/ClpCholeskyDense.hpp new file mode 100644 index 0000000..d8428b6 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpCholeskyDense.hpp @@ -0,0 +1,162 @@ +/* $Id: ClpCholeskyDense.hpp 1910 2013-01-27 02:00:13Z stefan $ */ +/* + Copyright (C) 2003, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ +#ifndef ClpCholeskyDense_H +#define ClpCholeskyDense_H + +#include "ClpCholeskyBase.hpp" +class ClpMatrixBase; + +class ClpCholeskyDense : public ClpCholeskyBase { + +public: + /**@name Virtual methods that the derived classes provides */ + /**@{*/ + /** Orders rows and saves pointer to matrix.and model. + Returns non-zero if not enough memory */ + virtual int order(ClpInterior * model) ; + /** Does Symbolic factorization given permutation. + This is called immediately after order. If user provides this then + user must provide factorize and solve. Otherwise the default factorization is used + returns non-zero if not enough memory */ + virtual int symbolic(); + /** Factorize - filling in rowsDropped and returning number dropped. + If return code negative then out of memory */ + virtual int factorize(const CoinWorkDouble * diagonal, int * rowsDropped) ; + /** Uses factorization to solve. */ + virtual void solve (CoinWorkDouble * region) ; + /**@}*/ + + /**@name Non virtual methods for ClpCholeskyDense */ + /**@{*/ + /** Reserves space. + If factor not NULL then just uses passed space + Returns non-zero if not enough memory */ + int reserveSpace(const ClpCholeskyBase * factor, int numberRows) ; + /** Returns space needed */ + CoinBigIndex space( int numberRows) const; + /** part 2 of Factorize - filling in rowsDropped */ + void factorizePart2(int * rowsDropped) ; + /** part 2 of Factorize - filling in rowsDropped - blocked */ + void factorizePart3(int * rowsDropped) ; + /** Forward part of solve */ + void solveF1(longDouble * a, int n, CoinWorkDouble * region); + void solveF2(longDouble * a, int n, CoinWorkDouble * region, CoinWorkDouble * region2); + /** Backward part of solve */ + void solveB1(longDouble * a, int n, CoinWorkDouble * region); + void solveB2(longDouble * a, int n, CoinWorkDouble * region, CoinWorkDouble * region2); + int bNumber(const longDouble * array, int &, int&); + /** A */ + inline longDouble * aMatrix() const { + return sparseFactor_; + } + /** Diagonal */ + inline longDouble * diagonal() const { + return diagonal_; + } + /**@}*/ + + + /**@name Constructors, destructor */ + /**@{*/ + /** Default constructor. */ + ClpCholeskyDense(); + /** Destructor */ + virtual ~ClpCholeskyDense(); + /** Copy */ + ClpCholeskyDense(const ClpCholeskyDense&); + /** Assignment */ + ClpCholeskyDense& operator=(const ClpCholeskyDense&); + /** Clone */ + virtual ClpCholeskyBase * clone() const ; + /**@}*/ + + +private: + /**@name Data members */ + /**@{*/ + /** Just borrowing space */ + bool borrowSpace_; + /**@}*/ +}; + +/* structure for C */ +typedef struct { + longDouble * diagonal_; + longDouble * a; + longDouble * work; + int * rowsDropped; + double doubleParameters_[1]; /* corresponds to 10 */ + int integerParameters_[2]; /* corresponds to 34, nThreads */ + int n; + int numberBlocks; +} ClpCholeskyDenseC; + +extern "C" { + void ClpCholeskySpawn(void *); +} +/**Non leaf recursive factor */ +void +ClpCholeskyCfactor(ClpCholeskyDenseC * thisStruct, + longDouble * a, int n, int numberBlocks, + longDouble * diagonal, longDouble * work, int * rowsDropped); + +/**Non leaf recursive triangle rectangle update */ +void +ClpCholeskyCtriRec(ClpCholeskyDenseC * thisStruct, + longDouble * aTri, int nThis, + longDouble * aUnder, longDouble * diagonal, + longDouble * work, + int nLeft, int iBlock, int jBlock, + int numberBlocks); +/**Non leaf recursive rectangle triangle update */ +void +ClpCholeskyCrecTri(ClpCholeskyDenseC * thisStruct, + longDouble * aUnder, int nTri, int nDo, + int iBlock, int jBlock, longDouble * aTri, + longDouble * diagonal, longDouble * work, + int numberBlocks); +/** Non leaf recursive rectangle rectangle update, + nUnder is number of rows in iBlock, + nUnderK is number of rows in kBlock +*/ +void +ClpCholeskyCrecRec(ClpCholeskyDenseC * thisStruct, + longDouble * above, int nUnder, int nUnderK, + int nDo, longDouble * aUnder, longDouble *aOther, + longDouble * work, + int iBlock, int jBlock, + int numberBlocks); +/**Leaf recursive factor */ +void +ClpCholeskyCfactorLeaf(ClpCholeskyDenseC * thisStruct, + longDouble * a, int n, + longDouble * diagonal, longDouble * work, + int * rowsDropped); +/**Leaf recursive triangle rectangle update */ +void +ClpCholeskyCtriRecLeaf(/*ClpCholeskyDenseC * thisStruct,*/ + longDouble * aTri, longDouble * aUnder, + longDouble * diagonal, longDouble * work, + int nUnder); +/**Leaf recursive rectangle triangle update */ +void +ClpCholeskyCrecTriLeaf(/*ClpCholeskyDenseC * thisStruct, */ + longDouble * aUnder, longDouble * aTri, + /*longDouble * diagonal,*/ longDouble * work, int nUnder); +/** Leaf recursive rectangle rectangle update, + nUnder is number of rows in iBlock, + nUnderK is number of rows in kBlock +*/ +void +ClpCholeskyCrecRecLeaf(/*ClpCholeskyDenseC * thisStruct, */ + const longDouble * COIN_RESTRICT above, + const longDouble * COIN_RESTRICT aUnder, + longDouble * COIN_RESTRICT aOther, + const longDouble * COIN_RESTRICT work, + int nUnder); +#endif diff --git a/thirdparty/linux/include/coin/ClpConfig.h b/thirdparty/linux/include/coin/ClpConfig.h new file mode 100644 index 0000000..d10a206 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpConfig.h @@ -0,0 +1,17 @@ +/* src/config_clp.h. Generated by configure. */ +/* src/config_clp.h.in. */ + +/* Define to 1, 2, 3, or 4 if Aboca should be build. */ +/* #undef CLP_HAS_ABC */ + +/* Version number of project */ +#define CLP_VERSION "1.16.6" + +/* Major Version number of project */ +#define CLP_VERSION_MAJOR 1 + +/* Minor Version number of project */ +#define CLP_VERSION_MINOR 16 + +/* Release Version number of project */ +#define CLP_VERSION_RELEASE 6 diff --git a/thirdparty/linux/include/coin/ClpConstraint.hpp b/thirdparty/linux/include/coin/ClpConstraint.hpp new file mode 100644 index 0000000..be43bb8 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpConstraint.hpp @@ -0,0 +1,125 @@ +/* $Id: ClpConstraint.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpConstraint_H +#define ClpConstraint_H + + +//############################################################################# +class ClpSimplex; +class ClpModel; + +/** Constraint Abstract Base Class + +Abstract Base Class for describing a constraint or objective function + +*/ +class ClpConstraint { + +public: + + ///@name Stuff + //@{ + + /** Fills gradient. If Linear then solution may be NULL, + also returns true value of function and offset so we can use x not deltaX in constraint + If refresh is false then uses last solution + Uses model for scaling + Returns non-zero if gradient undefined at current solution + */ + virtual int gradient(const ClpSimplex * model, + const double * solution, + double * gradient, + double & functionValue , + double & offset, + bool useScaling = false, + bool refresh = true) const = 0; + /// Constraint function value + virtual double functionValue (const ClpSimplex * model, + const double * solution, + bool useScaling = false, + bool refresh = true) const ; + /// Resize constraint + virtual void resize(int newNumberColumns) = 0; + /// Delete columns in constraint + virtual void deleteSome(int numberToDelete, const int * which) = 0; + /// Scale constraint + virtual void reallyScale(const double * columnScale) = 0; + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char * which) const = 0; + /** Given a zeroed array sets possible nonzero coefficients to 1. + Returns number of nonzeros + */ + virtual int markNonzero(char * which) const = 0; + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpConstraint(); + + /// Copy constructor + ClpConstraint(const ClpConstraint &); + + /// Assignment operator + ClpConstraint & operator=(const ClpConstraint& rhs); + + /// Destructor + virtual ~ClpConstraint (); + + /// Clone + virtual ClpConstraint * clone() const = 0; + + //@} + + ///@name Other + //@{ + /// Returns type, 0 linear, 1 nonlinear + inline int type() { + return type_; + } + /// Row number (-1 is objective) + inline int rowNumber() const { + return rowNumber_; + } + + /// Number of possible coefficients in gradient + virtual int numberCoefficients() const = 0; + + /// Stored constraint function value + inline double functionValue () const { + return functionValue_; + } + + /// Constraint offset + inline double offset () const { + return offset_; + } + /// Say we have new primal solution - so may need to recompute + virtual void newXValues() {} + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Gradient at last evaluation + mutable double * lastGradient_; + /// Value of non-linear part of constraint + mutable double functionValue_; + /// Value of offset for constraint + mutable double offset_; + /// Type of constraint - linear is 1 + int type_; + /// Row number (-1 is objective) + int rowNumber_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpConstraintLinear.hpp b/thirdparty/linux/include/coin/ClpConstraintLinear.hpp new file mode 100644 index 0000000..fd0a4da --- /dev/null +++ b/thirdparty/linux/include/coin/ClpConstraintLinear.hpp @@ -0,0 +1,110 @@ +/* $Id: ClpConstraintLinear.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpConstraintLinear_H +#define ClpConstraintLinear_H + +#include "ClpConstraint.hpp" + +//############################################################################# + +/** Linear Constraint Class + +*/ + +class ClpConstraintLinear : public ClpConstraint { + +public: + + ///@name Stuff + //@{ + + + /** Fills gradient. If Linear then solution may be NULL, + also returns true value of function and offset so we can use x not deltaX in constraint + If refresh is false then uses last solution + Uses model for scaling + Returns non-zero if gradient udefined at current solution + */ + virtual int gradient(const ClpSimplex * model, + const double * solution, + double * gradient, + double & functionValue , + double & offset, + bool useScaling = false, + bool refresh = true) const ; + /// Resize constraint + virtual void resize(int newNumberColumns) ; + /// Delete columns in constraint + virtual void deleteSome(int numberToDelete, const int * which) ; + /// Scale constraint + virtual void reallyScale(const double * columnScale) ; + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char * which) const ; + /** Given a zeroed array sets possible nonzero coefficients to 1. + Returns number of nonzeros + */ + virtual int markNonzero(char * which) const; + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpConstraintLinear(); + + /// Constructor from constraint + ClpConstraintLinear(int row, int numberCoefficients, int numberColumns, + const int * column, const double * element); + + /** Copy constructor . + */ + ClpConstraintLinear(const ClpConstraintLinear & rhs); + + /// Assignment operator + ClpConstraintLinear & operator=(const ClpConstraintLinear& rhs); + + /// Destructor + virtual ~ClpConstraintLinear (); + + /// Clone + virtual ClpConstraint * clone() const; + //@} + ///@name Gets and sets + //@{ + /// Number of coefficients + virtual int numberCoefficients() const; + /// Number of columns in linear constraint + inline int numberColumns() const { + return numberColumns_; + } + /// Columns + inline const int * column() const { + return column_; + } + /// Coefficients + inline const double * coefficient() const { + return coefficient_; + } + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Column + int * column_; + /// Coefficients + double * coefficient_; + /// Useful to have number of columns about + int numberColumns_; + /// Number of coefficients + int numberCoefficients_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpConstraintQuadratic.hpp b/thirdparty/linux/include/coin/ClpConstraintQuadratic.hpp new file mode 100644 index 0000000..2eff6cc --- /dev/null +++ b/thirdparty/linux/include/coin/ClpConstraintQuadratic.hpp @@ -0,0 +1,119 @@ +/* $Id: ClpConstraintQuadratic.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpConstraintQuadratic_H +#define ClpConstraintQuadratic_H + +#include "ClpConstraint.hpp" + +//############################################################################# + +/** Quadratic Constraint Class + +*/ + +class ClpConstraintQuadratic : public ClpConstraint { + +public: + + ///@name Stuff + //@{ + + + /** Fills gradient. If Quadratic then solution may be NULL, + also returns true value of function and offset so we can use x not deltaX in constraint + If refresh is false then uses last solution + Uses model for scaling + Returns non-zero if gradient udefined at current solution + */ + virtual int gradient(const ClpSimplex * model, + const double * solution, + double * gradient, + double & functionValue , + double & offset, + bool useScaling = false, + bool refresh = true) const ; + /// Resize constraint + virtual void resize(int newNumberColumns) ; + /// Delete columns in constraint + virtual void deleteSome(int numberToDelete, const int * which) ; + /// Scale constraint + virtual void reallyScale(const double * columnScale) ; + /** Given a zeroed array sets nonquadratic columns to 1. + Returns number of nonquadratic columns + */ + virtual int markNonlinear(char * which) const ; + /** Given a zeroed array sets possible nonzero coefficients to 1. + Returns number of nonzeros + */ + virtual int markNonzero(char * which) const; + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpConstraintQuadratic(); + + /// Constructor from quadratic + ClpConstraintQuadratic(int row, int numberQuadraticColumns, int numberColumns, + const CoinBigIndex * start, + const int * column, const double * element); + + /** Copy constructor . + */ + ClpConstraintQuadratic(const ClpConstraintQuadratic & rhs); + + /// Assignment operator + ClpConstraintQuadratic & operator=(const ClpConstraintQuadratic& rhs); + + /// Destructor + virtual ~ClpConstraintQuadratic (); + + /// Clone + virtual ClpConstraint * clone() const; + //@} + ///@name Gets and sets + //@{ + /// Number of coefficients + virtual int numberCoefficients() const; + /// Number of columns in constraint + inline int numberColumns() const { + return numberColumns_; + } + /// Column starts + inline CoinBigIndex * start() const { + return start_; + } + /// Columns + inline const int * column() const { + return column_; + } + /// Coefficients + inline const double * coefficient() const { + return coefficient_; + } + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Column starts + CoinBigIndex * start_; + /// Column (if -1 then linear coefficient) + int * column_; + /// Coefficients + double * coefficient_; + /// Useful to have number of columns about + int numberColumns_; + /// Number of coefficients in gradient + int numberCoefficients_; + /// Number of quadratic columns + int numberQuadraticColumns_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpDualRowDantzig.hpp b/thirdparty/linux/include/coin/ClpDualRowDantzig.hpp new file mode 100644 index 0000000..73b42b3 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpDualRowDantzig.hpp @@ -0,0 +1,71 @@ +/* $Id: ClpDualRowDantzig.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// 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). + +#ifndef ClpDualRowDantzig_H +#define ClpDualRowDantzig_H + +#include "ClpDualRowPivot.hpp" + +//############################################################################# + +/** Dual Row Pivot Dantzig Algorithm Class + +This is simplest choice - choose largest infeasibility + +*/ + +class ClpDualRowDantzig : public ClpDualRowPivot { + +public: + + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow(); + + /** Updates weights and returns pivot alpha. + Also does FT update */ + virtual double updateWeights(CoinIndexedVector * input, + CoinIndexedVector * spare, + CoinIndexedVector * spare2, + CoinIndexedVector * updatedColumn); + /** Updates primal solution (and maybe list of candidates) + Uses input vector which it deletes + Computes change in objective function + */ + virtual void updatePrimalSolution(CoinIndexedVector * input, + double theta, + double & changeInObjective); + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpDualRowDantzig(); + + /// Copy constructor + ClpDualRowDantzig(const ClpDualRowDantzig &); + + /// Assignment operator + ClpDualRowDantzig & operator=(const ClpDualRowDantzig& rhs); + + /// Destructor + virtual ~ClpDualRowDantzig (); + + /// Clone + virtual ClpDualRowPivot * clone(bool copyData = true) const; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpDualRowPivot.hpp b/thirdparty/linux/include/coin/ClpDualRowPivot.hpp new file mode 100644 index 0000000..f1f57a6 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpDualRowPivot.hpp @@ -0,0 +1,129 @@ +/* $Id: ClpDualRowPivot.hpp 2070 2014-11-18 11:12:54Z 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). + +#ifndef ClpDualRowPivot_H +#define ClpDualRowPivot_H + +class ClpSimplex; +class CoinIndexedVector; + +//############################################################################# + +/** Dual Row Pivot Abstract Base Class + +Abstract Base Class for describing an interface to an algorithm +to choose row pivot in dual simplex algorithm. For some algorithms +e.g. Dantzig choice then some functions may be null. + +*/ + +class ClpDualRowPivot { + +public: + + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow() = 0; + + /** Updates weights and returns pivot alpha. + Also does FT update */ + virtual double updateWeights(CoinIndexedVector * input, + CoinIndexedVector * spare, + CoinIndexedVector * spare2, + CoinIndexedVector * updatedColumn) = 0; + + /** Updates primal solution (and maybe list of candidates) + Uses input vector which it deletes + Computes change in objective function + Would be faster if we kept basic regions, but on other hand it + means everything is always in sync + */ + /* FIXME: this was pure virtul (=0). Why? */ + virtual void updatePrimalSolution(CoinIndexedVector * input, + double theta, + double & changeInObjective) = 0; + /** Saves any weights round factorization as pivot rows may change + Will be empty unless steepest edge (will save model) + May also recompute infeasibility stuff + 1) before factorization + 2) after good factorization (if weights empty may initialize) + 3) after something happened but no factorization + (e.g. check for infeasible) + 4) as 2 but restore weights from previous snapshot + 5) for strong branching - initialize to 1 , infeasibilities + 6) scale back + 7) for strong branching - initialize full weights , infeasibilities + */ + virtual void saveWeights(ClpSimplex * model, int mode); + /// checks accuracy and may re-initialize (may be empty) + virtual void checkAccuracy(); + /// Gets rid of last update (may be empty) + virtual void unrollWeights(); + /// Gets rid of all arrays (may be empty) + virtual void clearArrays(); + /// Returns true if would not find any row + virtual bool looksOptimal() const { + return false; + } + /// Called when maximum pivots changes + virtual void maximumPivotsChanged() {} + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpDualRowPivot(); + + /// Copy constructor + ClpDualRowPivot(const ClpDualRowPivot &); + + /// Assignment operator + ClpDualRowPivot & operator=(const ClpDualRowPivot& rhs); + + /// Destructor + virtual ~ClpDualRowPivot (); + + /// Clone + virtual ClpDualRowPivot * clone(bool copyData = true) const = 0; + + //@} + + ///@name Other + //@{ + /// Returns model + inline ClpSimplex * model() { + return model_; + } + + /// Sets model (normally to NULL) + inline void setModel(ClpSimplex * newmodel) { + model_ = newmodel; + } + + /// Returns type (above 63 is extra information) + inline int type() { + return type_; + } + + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Pointer to model + ClpSimplex * model_; + /// Type of row pivot algorithm + int type_; + //@} +}; +#ifndef CLP_DUAL_COLUMN_MULTIPLIER +//#define CLP_DUAL_COLUMN_MULTIPLIER 0.99999 +#endif +#endif diff --git a/thirdparty/linux/include/coin/ClpDualRowSteepest.hpp b/thirdparty/linux/include/coin/ClpDualRowSteepest.hpp new file mode 100644 index 0000000..7e2cc62 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpDualRowSteepest.hpp @@ -0,0 +1,153 @@ +/* $Id: ClpDualRowSteepest.hpp 2070 2014-11-18 11:12:54Z 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). + +#ifndef ClpDualRowSteepest_H +#define ClpDualRowSteepest_H + +#include "ClpDualRowPivot.hpp" +class CoinIndexedVector; + + +//############################################################################# + +/** Dual Row Pivot Steepest Edge Algorithm Class + +See Forrest-Goldfarb paper for algorithm + +*/ + +class ClpDualRowSteepest : public ClpDualRowPivot { + +public: + + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow(); + + /** Updates weights and returns pivot alpha. + Also does FT update */ + virtual double updateWeights(CoinIndexedVector * input, + CoinIndexedVector * spare, + CoinIndexedVector * spare2, + CoinIndexedVector * updatedColumn); + + /** Updates primal solution (and maybe list of candidates) + Uses input vector which it deletes + Computes change in objective function + */ + virtual void updatePrimalSolution(CoinIndexedVector * input, + double theta, + double & changeInObjective); + + /** Saves any weights round factorization as pivot rows may change + Save model + May also recompute infeasibility stuff + 1) before factorization + 2) after good factorization (if weights empty may initialize) + 3) after something happened but no factorization + (e.g. check for infeasible) + 4) as 2 but restore weights from previous snapshot + 5) for strong branching - initialize (uninitialized) , infeasibilities + */ + virtual void saveWeights(ClpSimplex * model, int mode); + /// Pass in saved weights + void passInSavedWeights(const CoinIndexedVector * saved); + /// Get saved weights + inline CoinIndexedVector * savedWeights() + { return savedWeights_;} + /// Gets rid of last update + virtual void unrollWeights(); + /// Gets rid of all arrays + virtual void clearArrays(); + /// Returns true if would not find any row + virtual bool looksOptimal() const; + /// Called when maximum pivots changes + virtual void maximumPivotsChanged(); + //@} + + /** enums for persistence + */ + enum Persistence { + normal = 0x00, // create (if necessary) and destroy + keep = 0x01 // create (if necessary) and leave + }; + + ///@name Constructors and destructors + //@{ + /** Default Constructor + 0 is uninitialized, 1 full, 2 is partial uninitialized, + 3 starts as 2 but may switch to 1. + By partial is meant that the weights are updated as normal + but only part of the infeasible basic variables are scanned. + This can be faster on very easy problems. + */ + ClpDualRowSteepest(int mode = 3); + + /// Copy constructor + ClpDualRowSteepest(const ClpDualRowSteepest &); + + /// Assignment operator + ClpDualRowSteepest & operator=(const ClpDualRowSteepest& rhs); + + /// Fill most values + void fill(const ClpDualRowSteepest& rhs); + + /// Destructor + virtual ~ClpDualRowSteepest (); + + /// Clone + virtual ClpDualRowPivot * clone(bool copyData = true) const; + + //@} + /**@name gets and sets */ + //@{ + /// Mode + inline int mode() const { + return mode_; + } + /// Set mode + inline void setMode(int mode) { + mode_ = mode; + } + /// Set/ get persistence + inline void setPersistence(Persistence life) { + persistence_ = life; + } + inline Persistence persistence() const { + return persistence_ ; + } +//@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /** Status + 0) Normal + -1) Needs initialization + 1) Weights are stored by sequence number + */ + int state_; + /** If 0 then we are using uninitialized weights, 1 then full, + if 2 then uninitialized partial, 3 switchable */ + int mode_; + /// Life of weights + Persistence persistence_; + /// weight array + double * weights_; + /// square of infeasibility array (just for infeasible rows) + CoinIndexedVector * infeasible_; + /// alternate weight array (so we can unroll) + CoinIndexedVector * alternateWeights_; + /// save weight array (so we can use checkpoint) + CoinIndexedVector * savedWeights_; + /// Dubious weights + int * dubiousWeights_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpDummyMatrix.hpp b/thirdparty/linux/include/coin/ClpDummyMatrix.hpp new file mode 100644 index 0000000..1b4a2d4 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpDummyMatrix.hpp @@ -0,0 +1,183 @@ +/* $Id: ClpDummyMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDummyMatrix_H +#define ClpDummyMatrix_H + + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" + +/** This implements a dummy matrix as derived from ClpMatrixBase. + This is so you can do ClpPdco but may come in useful elsewhere. + It just has dimensions but no data +*/ + + +class ClpDummyMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix * getPackedMatrix() const; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const { + return true; + } + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const { + return numberElements_; + } + /** Number of columns. */ + virtual int getNumCols() const { + return numberColumns_; + } + /** Number of rows. */ + virtual int getNumRows() const { + return numberRows_; + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double * getElements() const; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int * getIndices() const; + + virtual const CoinBigIndex * getVectorStarts() const; + /** The lengths of the major-dimension vectors. */ + virtual const int * getVectorLengths() const; + + /** Delete the columns whose indices are listed in <code>indDel</code>. */ + virtual void deleteCols(const int numDel, const int * indDel); + /** Delete the rows whose indices are listed in <code>indDel</code>. */ + virtual void deleteRows(const int numDel, const int * indDel); + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase * reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual CoinBigIndex countBasis(const int * whichColumn, + int & numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex * model, + const int * whichColumn, + int & numberColumnBasic, + int * row, int * start, + int * rowCount, int * columnCount, + CoinFactorizationDouble * element); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column) const ; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex * model, + CoinIndexedVector * rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column, double multiplier) const ; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex * model, double * array, + int column, double multiplier) const; + /// Allow any parts of a created CoinMatrix to be deleted + /// Allow any parts of a created CoinPackedMatrix to be deleted + virtual void releasePackedMatrix() const {} + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return <code>y + A * scalar *x</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + virtual void times(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void times(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale) const; + /** Return <code>y + x * scalar * A</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> */ + virtual void transposeTimes(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale) const; + + using ClpMatrixBase::transposeTimes ; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode */ + virtual void transposeTimes(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x *A</code> in <code>z</code> but + just for indices in y. + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void subsetTransposeTimes(const ClpSimplex * model, + const CoinIndexedVector * x, + const CoinIndexedVector * y, + CoinIndexedVector * z) const; + //@} + + /**@name Other */ + //@{ + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpDummyMatrix(); + /// Constructor with data + ClpDummyMatrix(int numberColumns, int numberRows, + int numberElements); + /** Destructor */ + virtual ~ClpDummyMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpDummyMatrix(const ClpDummyMatrix&); + /** The copy constructor from an CoinDummyMatrix. */ + ClpDummyMatrix(const CoinPackedMatrix&); + + ClpDummyMatrix& operator=(const ClpDummyMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; + /// Number of elements + int numberElements_; + + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpDynamicExampleMatrix.hpp b/thirdparty/linux/include/coin/ClpDynamicExampleMatrix.hpp new file mode 100644 index 0000000..81fe5ba --- /dev/null +++ b/thirdparty/linux/include/coin/ClpDynamicExampleMatrix.hpp @@ -0,0 +1,186 @@ +/* $Id: ClpDynamicExampleMatrix.hpp 1936 2013-04-09 10:29:27Z forrest $ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDynamicExampleMatrix_H +#define ClpDynamicExampleMatrix_H + + +#include "CoinPragma.hpp" + +#include "ClpDynamicMatrix.hpp" +class ClpSimplex; +/** This implements a dynamic matrix when we have a limit on the number of + "interesting rows". This version inherits from ClpDynamicMatrix and knows that + the real matrix is gub. This acts just like ClpDynamicMatrix but generates columns. + This "generates" columns by choosing from stored set. It is maent as a starting point + as to how you could use shortest path to generate columns. + + So it has its own copy of all data needed. It populates ClpDynamicWatrix with enough + to allow for gub keys and active variables. In turn ClpDynamicMatrix populates + a CoinPackedMatrix with active columns and rows. + + As there is one copy here and one in ClpDynamicmatrix these names end in Gen_ + + It is obviously more efficient to just use ClpDynamicMatrix but the ideas is to + show how much code a user would have to write. + + This does not work very well with bounds + +*/ + +class ClpDynamicExampleMatrix : public ClpDynamicMatrix { + +public: + /**@name Main functions provided */ + //@{ + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + + /** Creates a variable. This is called after partial pricing and will modify matrix. + Will update bestSequence. + */ + virtual void createVariable(ClpSimplex * model, int & bestSequence); + /** If addColumn forces compression then this allows descendant to know what to do. + If >= then entry stayed in, if -1 then entry went out to lower bound.of zero. + Entries at upper bound (really nonzero) never go out (at present). + */ + virtual void packDown(const int * in, int numberToPack); + //@} + + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpDynamicExampleMatrix(); + /** This is the real constructor. + It assumes factorization frequency will not be changed. + This resizes model !!!! + The contents of original matrix in model will be taken over and original matrix + will be sanitized so can be deleted (to avoid a very small memory leak) + */ + ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, + int numberColumns, const int * starts, + const double * lower, const double * upper, + const int * startColumn, const int * row, + const double * element, const double * cost, + const double * columnLower = NULL, const double * columnUpper = NULL, + const unsigned char * status = NULL, + const unsigned char * dynamicStatus = NULL, + int numberIds = 0, const int *ids = NULL); +#if 0 + /// This constructor just takes over ownership (except for lower, upper) + ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, + int numberColumns, int * starts, + const double * lower, const double * upper, + int * startColumn, int * row, + double * element, double * cost, + double * columnLower = NULL, double * columnUpper = NULL, + const unsigned char * status = NULL, + const unsigned char * dynamicStatus = NULL, + int numberIds = 0, const int *ids = NULL); +#endif + /** Destructor */ + virtual ~ClpDynamicExampleMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpDynamicExampleMatrix(const ClpDynamicExampleMatrix&); + ClpDynamicExampleMatrix& operator=(const ClpDynamicExampleMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + //@} + /**@name gets and sets */ + //@{ + /// Starts of each column + inline CoinBigIndex * startColumnGen() const { + return startColumnGen_; + } + /// rows + inline int * rowGen() const { + return rowGen_; + } + /// elements + inline double * elementGen() const { + return elementGen_; + } + /// costs + inline double * costGen() const { + return costGen_; + } + /// full starts + inline int * fullStartGen() const { + return fullStartGen_; + } + /// ids in next level matrix + inline int * idGen() const { + return idGen_; + } + /// Optional lower bounds on columns + inline double * columnLowerGen() const { + return columnLowerGen_; + } + /// Optional upper bounds on columns + inline double * columnUpperGen() const { + return columnUpperGen_; + } + /// size + inline int numberColumns() const { + return numberColumns_; + } + inline void setDynamicStatusGen(int sequence, DynamicStatus status) { + unsigned char & st_byte = dynamicStatusGen_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | status); + } + inline DynamicStatus getDynamicStatusGen(int sequence) const { + return static_cast<DynamicStatus> (dynamicStatusGen_[sequence] & 7); + } + /// Whether flagged + inline bool flaggedGen(int i) const { + return (dynamicStatusGen_[i] & 8) != 0; + } + inline void setFlaggedGen(int i) { + dynamicStatusGen_[i] = static_cast<unsigned char>(dynamicStatusGen_[i] | 8); + } + inline void unsetFlagged(int i) { + dynamicStatusGen_[i] = static_cast<unsigned char>(dynamicStatusGen_[i] & ~8); + } + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// size + int numberColumns_; + /// Starts of each column + CoinBigIndex * startColumnGen_; + /// rows + int * rowGen_; + /// elements + double * elementGen_; + /// costs + double * costGen_; + /// start of each set + int * fullStartGen_; + /// for status and which bound + unsigned char * dynamicStatusGen_; + /** identifier for each variable up one level (startColumn_, etc). This is + of length maximumGubColumns_. For this version it is just sequence number + at this level */ + int * idGen_; + /// Optional lower bounds on columns + double * columnLowerGen_; + /// Optional upper bounds on columns + double * columnUpperGen_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpDynamicMatrix.hpp b/thirdparty/linux/include/coin/ClpDynamicMatrix.hpp new file mode 100644 index 0000000..da4e144 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpDynamicMatrix.hpp @@ -0,0 +1,381 @@ +/* $Id: ClpDynamicMatrix.hpp 1755 2011-06-28 18:24:31Z lou $ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDynamicMatrix_H +#define ClpDynamicMatrix_H + + +#include "CoinPragma.hpp" + +#include "ClpPackedMatrix.hpp" +class ClpSimplex; +/** This implements a dynamic matrix when we have a limit on the number of + "interesting rows". This version inherits from ClpPackedMatrix and knows that + the real matrix is gub. A later version could use shortest path to generate columns. + +*/ + +class ClpDynamicMatrix : public ClpPackedMatrix { + +public: + /// enums for status of various sorts + enum DynamicStatus { + soloKey = 0x00, + inSmall = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03 + }; + /**@name Main functions provided */ + //@{ + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big dynamic or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, + bool check = false); + + using ClpPackedMatrix::times ; + /** Return <code>y + A * scalar *x</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + virtual void times(double scalar, + const double * x, double * y) const; + /// Modifies rhs offset + void modifyOffset(int sequence, double amount); + /// Gets key value when none in small + double keyValue(int iSet) const; + /** + mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended + updates array (and may use other if dual values pass) + mode=1 - Update dual solution after "transposeTimes" using extended rows. + mode=2 - Compute all djs and compute key dual infeasibilities + mode=3 - Report on key dual infeasibilities + mode=4 - Modify before updateTranspose in partial pricing + */ + virtual void dualExpanded(ClpSimplex * model, CoinIndexedVector * array, + double * other, int mode); + /** + mode=0 - Create list of non-key basics in pivotVariable_ using + number as numberBasic in and out + mode=1 - Set all key variables as basic + mode=2 - return number extra rows needed, number gives maximum number basic + mode=3 - before replaceColumn + mode=4 - return 1 if can do primal, 2 if dual, 3 if both + mode=5 - save any status stuff (when in good state) + mode=6 - restore status stuff + mode=7 - flag given variable (normally sequenceIn) + mode=8 - unflag all variables + mode=9 - synchronize costs + mode=10 - return 1 if there may be changing bounds on variable (column generation) + mode=11 - make sure set is clean (used when a variable rejected - but not flagged) + mode=12 - after factorize but before permute stuff + mode=13 - at end of simplex to delete stuff + */ + virtual int generalExpanded(ClpSimplex * model, int mode, int & number); + /** Purely for column generation and similar ideas. Allows + matrix and any bounds or costs to be updated (sensibly). + Returns non-zero if any changes. + */ + virtual int refresh(ClpSimplex * model); + /** Creates a variable. This is called after partial pricing and will modify matrix. + Will update bestSequence. + */ + virtual void createVariable(ClpSimplex * model, int & bestSequence); + /// Returns reduced cost of a variable + virtual double reducedCost( ClpSimplex * model, int sequence) const; + /// Does gub crash + void gubCrash(); + /// Writes out model (without names) + void writeMps(const char * name); + /// Populates initial matrix from dynamic status + void initialProblem(); + /** Adds in a column to gub structure (called from descendant) and returns sequence */ + int addColumn(int numberEntries, const int * row, const double * element, + double cost, double lower, double upper, int iSet, + DynamicStatus status); + /** If addColumn forces compression then this allows descendant to know what to do. + If >=0 then entry stayed in, if -1 then entry went out to lower bound.of zero. + Entries at upper bound (really nonzero) never go out (at present). + */ + virtual void packDown(const int * , int ) {} + /// Gets lower bound (to simplify coding) + inline double columnLower(int sequence) const { + if (columnLower_) return columnLower_[sequence]; + else return 0.0; + } + /// Gets upper bound (to simplify coding) + inline double columnUpper(int sequence) const { + if (columnUpper_) return columnUpper_[sequence]; + else return COIN_DBL_MAX; + } + + //@} + + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpDynamicMatrix(); + /** This is the real constructor. + It assumes factorization frequency will not be changed. + This resizes model !!!! + The contents of original matrix in model will be taken over and original matrix + will be sanitized so can be deleted (to avoid a very small memory leak) + */ + ClpDynamicMatrix(ClpSimplex * model, int numberSets, + int numberColumns, const int * starts, + const double * lower, const double * upper, + const CoinBigIndex * startColumn, const int * row, + const double * element, const double * cost, + const double * columnLower = NULL, const double * columnUpper = NULL, + const unsigned char * status = NULL, + const unsigned char * dynamicStatus = NULL); + + /** Destructor */ + virtual ~ClpDynamicMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpDynamicMatrix(const ClpDynamicMatrix&); + /** The copy constructor from an CoinPackedMatrix. */ + ClpDynamicMatrix(const CoinPackedMatrix&); + + ClpDynamicMatrix& operator=(const ClpDynamicMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + //@} + /**@name gets and sets */ + //@{ + /// Status of row slacks + inline ClpSimplex::Status getStatus(int sequence) const { + return static_cast<ClpSimplex::Status> (status_[sequence] & 7); + } + inline void setStatus(int sequence, ClpSimplex::Status status) { + unsigned char & st_byte = status_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | status); + } + /// Whether flagged slack + inline bool flaggedSlack(int i) const { + return (status_[i] & 8) != 0; + } + inline void setFlaggedSlack(int i) { + status_[i] = static_cast<unsigned char>(status_[i] | 8); + } + inline void unsetFlaggedSlack(int i) { + status_[i] = static_cast<unsigned char>(status_[i] & ~8); + } + /// Number of sets (dynamic rows) + inline int numberSets() const { + return numberSets_; + } + /// Number of possible gub variables + inline int numberGubEntries() const + { return startSet_[numberSets_];} + /// Sets + inline int * startSets() const + { return startSet_;} + /// Whether flagged + inline bool flagged(int i) const { + return (dynamicStatus_[i] & 8) != 0; + } + inline void setFlagged(int i) { + dynamicStatus_[i] = static_cast<unsigned char>(dynamicStatus_[i] | 8); + } + inline void unsetFlagged(int i) { + dynamicStatus_[i] = static_cast<unsigned char>(dynamicStatus_[i] & ~8); + } + inline void setDynamicStatus(int sequence, DynamicStatus status) { + unsigned char & st_byte = dynamicStatus_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | status); + } + inline DynamicStatus getDynamicStatus(int sequence) const { + return static_cast<DynamicStatus> (dynamicStatus_[sequence] & 7); + } + /// Saved value of objective offset + inline double objectiveOffset() const { + return objectiveOffset_; + } + /// Starts of each column + inline CoinBigIndex * startColumn() const { + return startColumn_; + } + /// rows + inline int * row() const { + return row_; + } + /// elements + inline double * element() const { + return element_; + } + /// costs + inline double * cost() const { + return cost_; + } + /// ids of active columns (just index here) + inline int * id() const { + return id_; + } + /// Optional lower bounds on columns + inline double * columnLower() const { + return columnLower_; + } + /// Optional upper bounds on columns + inline double * columnUpper() const { + return columnUpper_; + } + /// Lower bounds on sets + inline double * lowerSet() const { + return lowerSet_; + } + /// Upper bounds on sets + inline double * upperSet() const { + return upperSet_; + } + /// size + inline int numberGubColumns() const { + return numberGubColumns_; + } + /// first free + inline int firstAvailable() const { + return firstAvailable_; + } + /// first dynamic + inline int firstDynamic() const { + return firstDynamic_; + } + /// number of columns in dynamic model + inline int lastDynamic() const { + return lastDynamic_; + } + /// number of rows in original model + inline int numberStaticRows() const { + return numberStaticRows_; + } + /// size of working matrix (max) + inline int numberElements() const { + return numberElements_; + } + inline int * keyVariable() const { + return keyVariable_; + } + /// Switches off dj checking each factorization (for BIG models) + void switchOffCheck(); + /// Status region for gub slacks + inline unsigned char * gubRowStatus() const { + return status_; + } + /// Status region for gub variables + inline unsigned char * dynamicStatus() const { + return dynamicStatus_; + } + /// Returns which set a variable is in + int whichSet (int sequence) const; + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Sum of dual infeasibilities + double sumDualInfeasibilities_; + /// Sum of primal infeasibilities + double sumPrimalInfeasibilities_; + /// Sum of Dual infeasibilities using tolerance based on error in duals + double sumOfRelaxedDualInfeasibilities_; + /// Sum of Primal infeasibilities using tolerance based on error in primals + double sumOfRelaxedPrimalInfeasibilities_; + /// Saved best dual on gub row in pricing + double savedBestGubDual_; + /// Saved best set in pricing + int savedBestSet_; + /// Backward pointer to pivot row !!! + int * backToPivotRow_; + /// Key variable of set (only accurate if none in small problem) + mutable int * keyVariable_; + /// Backward pointer to extra row + int * toIndex_; + // Reverse pointer from index to set + int * fromIndex_; + /// Number of sets (dynamic rows) + int numberSets_; + /// Number of active sets + int numberActiveSets_; + /// Saved value of objective offset + double objectiveOffset_; + /// Lower bounds on sets + double * lowerSet_; + /// Upper bounds on sets + double * upperSet_; + /// Status of slack on set + unsigned char * status_; + /// Pointer back to model + ClpSimplex * model_; + /// first free + int firstAvailable_; + /// first free when iteration started + int firstAvailableBefore_; + /// first dynamic + int firstDynamic_; + /// number of columns in dynamic model + int lastDynamic_; + /// number of rows in original model + int numberStaticRows_; + /// size of working matrix (max) + int numberElements_; + /// Number of dual infeasibilities + int numberDualInfeasibilities_; + /// Number of primal infeasibilities + int numberPrimalInfeasibilities_; + /** If pricing will declare victory (i.e. no check every factorization). + -1 - always check + 0 - don't check + 1 - in don't check mode but looks optimal + */ + int noCheck_; + /// Infeasibility weight when last full pass done + double infeasibilityWeight_; + /// size + int numberGubColumns_; + /// current maximum number of columns (then compress) + int maximumGubColumns_; + /// current maximum number of elemnts (then compress) + int maximumElements_; + /// Start of each set + int * startSet_; + /// next in chain + int * next_; + /// Starts of each column + CoinBigIndex * startColumn_; + /// rows + int * row_; + /// elements + double * element_; + /// costs + double * cost_; + /// ids of active columns (just index here) + int * id_; + /// for status and which bound + unsigned char * dynamicStatus_; + /// Optional lower bounds on columns + double * columnLower_; + /// Optional upper bounds on columns + double * columnUpper_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpEventHandler.hpp b/thirdparty/linux/include/coin/ClpEventHandler.hpp new file mode 100644 index 0000000..0a49c83 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpEventHandler.hpp @@ -0,0 +1,186 @@ +/* $Id: ClpEventHandler.hpp 1825 2011-11-20 16:02:57Z forrest $ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpEventHandler_H +#define ClpEventHandler_H + +#include "ClpSimplex.hpp" +/** Base class for Clp event handling + +This is just here to allow for event handling. By event I mean a Clp event +e.g. end of values pass. + +One use would be to let a user handle a system event e.g. Control-C. This could be done +by deriving a class MyEventHandler which knows about such events. If one occurs +MyEventHandler::event() could clear event status and return 3 (stopped). + +Clp would then return to user code. + +As it is called every iteration this should be fine grained enough. + +User can derive and construct from CbcModel - not pretty + +*/ + +class ClpEventHandler { + +public: + /** enums for what sort of event. + + These will also be returned in ClpModel::secondaryStatus() as int + */ + enum Event { + endOfIteration = 100, // used to set secondary status + endOfFactorization, // after gutsOfSolution etc + endOfValuesPass, + node, // for Cbc + treeStatus, // for Cbc + solution, // for Cbc + theta, // hit in parametrics + pivotRow, // used to choose pivot row + presolveStart, // ClpSolve presolve start + presolveSize, // sees if ClpSolve presolve too big or too small + presolveInfeasible, // ClpSolve presolve infeasible + presolveBeforeSolve, // ClpSolve presolve before solve + presolveAfterFirstSolve, // ClpSolve presolve after solve + presolveAfterSolve, // ClpSolve presolve after solve + presolveEnd, // ClpSolve presolve end + goodFactorization, // before gutsOfSolution + complicatedPivotIn, // in modifyCoefficients + noCandidateInPrimal, // tentative end + looksEndInPrimal, // About to declare victory (or defeat) + endInPrimal, // Victory (or defeat) + beforeStatusOfProblemInPrimal, + startOfStatusOfProblemInPrimal, + complicatedPivotOut, // in modifyCoefficients + noCandidateInDual, // tentative end + looksEndInDual, // About to declare victory (or defeat) + endInDual, // Victory (or defeat) + beforeStatusOfProblemInDual, + startOfStatusOfProblemInDual, + startOfIterationInDual, + updateDualsInDual, + endOfCreateRim, + slightlyInfeasible, + modifyMatrixInMiniPresolve, + moreMiniPresolve, + modifyMatrixInMiniPostsolve, + noTheta // At end (because no pivot) + }; + /**@name Virtual method that the derived classes should provide. + The base class instance does nothing and as event() is only useful method + it would not be very useful NOT providing one! + */ + //@{ + /** This can do whatever it likes. If return code -1 then carries on + if 0 sets ClpModel::status() to 5 (stopped by event) and will return to user. + At present if <-1 carries on and if >0 acts as if 0 - this may change. + For ClpSolve 2 -> too big return status of -2 and -> too small 3 + */ + virtual int event(Event whichEvent); + /** This can do whatever it likes. Return code -1 means no action. + This passes in something + */ + virtual int eventWithInfo(Event whichEvent, void * info) ; + //@} + + + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + ClpEventHandler(ClpSimplex * model = NULL); + /** Destructor */ + virtual ~ClpEventHandler(); + // Copy + ClpEventHandler(const ClpEventHandler&); + // Assignment + ClpEventHandler& operator=(const ClpEventHandler&); + /// Clone + virtual ClpEventHandler * clone() const; + + //@} + + /**@name Sets/gets */ + + //@{ + /** set model. */ + void setSimplex(ClpSimplex * model); + /// Get model + inline ClpSimplex * simplex() const { + return model_; + } + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer to simplex + ClpSimplex * model_; + //@} +}; +/** Base class for Clp disaster handling + +This is here to allow for disaster handling. By disaster I mean that Clp +would otherwise give up + +*/ + +class ClpDisasterHandler { + +public: + /**@name Virtual methods that the derived classe should provide. + */ + //@{ + /// Into simplex + virtual void intoSimplex() = 0; + /// Checks if disaster + virtual bool check() const = 0; + /// saves information for next attempt + virtual void saveInfo() = 0; + /// Type of disaster 0 can fix, 1 abort + virtual int typeOfDisaster(); + //@} + + + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + ClpDisasterHandler(ClpSimplex * model = NULL); + /** Destructor */ + virtual ~ClpDisasterHandler(); + // Copy + ClpDisasterHandler(const ClpDisasterHandler&); + // Assignment + ClpDisasterHandler& operator=(const ClpDisasterHandler&); + /// Clone + virtual ClpDisasterHandler * clone() const = 0; + + //@} + + /**@name Sets/gets */ + + //@{ + /** set model. */ + void setSimplex(ClpSimplex * model); + /// Get model + inline ClpSimplex * simplex() const { + return model_; + } + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer to simplex + ClpSimplex * model_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/ClpFactorization.hpp b/thirdparty/linux/include/coin/ClpFactorization.hpp new file mode 100644 index 0000000..dda8ff7 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpFactorization.hpp @@ -0,0 +1,432 @@ +/* $Id: ClpFactorization.hpp 2078 2015-01-05 12:39:49Z 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). + +#ifndef ClpFactorization_H +#define ClpFactorization_H + + +#include "CoinPragma.hpp" + +#include "CoinFactorization.hpp" +class ClpMatrixBase; +class ClpSimplex; +class ClpNetworkBasis; +class CoinOtherFactorization; +#ifndef CLP_MULTIPLE_FACTORIZATIONS +#define CLP_MULTIPLE_FACTORIZATIONS 4 +#endif +#ifdef CLP_MULTIPLE_FACTORIZATIONS +#include "CoinDenseFactorization.hpp" +#include "ClpSimplex.hpp" +#endif +#ifndef COIN_FAST_CODE +#define COIN_FAST_CODE +#endif +#ifndef CLP_FACTORIZATION_NEW_TIMING +#define CLP_FACTORIZATION_NEW_TIMING 1 +#endif + +/** This just implements CoinFactorization when an ClpMatrixBase object + is passed. If a network then has a dummy CoinFactorization and + a genuine ClpNetworkBasis object +*/ +class ClpFactorization +#ifndef CLP_MULTIPLE_FACTORIZATIONS + : public CoinFactorization +#endif +{ + + //friend class CoinFactorization; + +public: + /**@name factorization */ + //@{ + /** When part of LP - given by basic variables. + Actually does factorization. + Arrays passed in have non negative value to say basic. + If status is okay, basic variables have pivot row - this is only needed + if increasingRows_ >1. + Allows scaling + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ + int factorize (ClpSimplex * model, int solveType, bool valuesPass); + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpFactorization(); + /** Destructor */ + ~ClpFactorization(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor from an CoinFactorization. */ + ClpFactorization(const CoinFactorization&); + /** The copy constructor. */ + ClpFactorization(const ClpFactorization&, int denseIfSmaller = 0); +#ifdef CLP_MULTIPLE_FACTORIZATIONS + /** The copy constructor from an CoinOtherFactorization. */ + ClpFactorization(const CoinOtherFactorization&); +#endif + ClpFactorization& operator=(const ClpFactorization&); + //@} + + /* **** below here is so can use networkish basis */ + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + int replaceColumn ( const ClpSimplex * model, + CoinIndexedVector * regionSparse, + CoinIndexedVector * tableauColumn, + int pivotRow, + double pivotCheck , + bool checkBeforeModifying = false, + double acceptablePivot = 1.0e-8); + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from region2 + Tries to do FT update + number returned is negative if no room + region1 starts as zero and is zero at end */ + int updateColumnFT ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2); + /** Updates one column (FTRAN) from region2 + region1 starts as zero and is zero at end */ + int updateColumn ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute = false) const; + /** Updates one column (FTRAN) from region2 + Tries to do FT update + number returned is negative if no room. + Also updates region3 + region1 starts as zero and is zero at end */ + int updateTwoColumnsFT ( CoinIndexedVector * regionSparse1, + CoinIndexedVector * regionSparse2, + CoinIndexedVector * regionSparse3, + bool noPermuteRegion3 = false) ; + /// For debug (no statistics update) + int updateColumnForDebug ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute = false) const; + /** Updates one column (BTRAN) from region2 + region1 starts as zero and is zero at end */ + int updateColumnTranspose ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2) const; + //@} +#ifdef CLP_MULTIPLE_FACTORIZATIONS + /**@name Lifted from CoinFactorization */ + //@{ + /// Total number of elements in factorization + inline int numberElements ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->numberElements(); + else return coinFactorizationB_->numberElements() ; + } + /// Returns address of permute region + inline int *permute ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->permute(); + else return coinFactorizationB_->permute() ; + } + /// Returns address of pivotColumn region (also used for permuting) + inline int *pivotColumn ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->pivotColumn(); + else return coinFactorizationB_->permute() ; + } + /// Maximum number of pivots between factorizations + inline int maximumPivots ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->maximumPivots(); + else return coinFactorizationB_->maximumPivots() ; + } + /// Set maximum number of pivots between factorizations + inline void maximumPivots ( int value) { + if (coinFactorizationA_) coinFactorizationA_->maximumPivots(value); + else coinFactorizationB_->maximumPivots(value); + } + /// Returns number of pivots since factorization + inline int pivots ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->pivots(); + else return coinFactorizationB_->pivots() ; + } + /// Whether larger areas needed + inline double areaFactor ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->areaFactor(); + else return 0.0 ; + } + /// Set whether larger areas needed + inline void areaFactor ( double value) { + if (coinFactorizationA_) coinFactorizationA_->areaFactor(value); + } + /// Zero tolerance + inline double zeroTolerance ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->zeroTolerance(); + else return coinFactorizationB_->zeroTolerance() ; + } + /// Set zero tolerance + inline void zeroTolerance ( double value) { + if (coinFactorizationA_) coinFactorizationA_->zeroTolerance(value); + else coinFactorizationB_->zeroTolerance(value); + } + /// Set tolerances to safer of existing and given + void saferTolerances ( double zeroTolerance, double pivotTolerance); + /** get sparse threshold */ + inline int sparseThreshold ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->sparseThreshold(); + else return 0 ; + } + /** Set sparse threshold */ + inline void sparseThreshold ( int value) { + if (coinFactorizationA_) coinFactorizationA_->sparseThreshold(value); + } + /// Returns status + inline int status ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->status(); + else return coinFactorizationB_->status() ; + } + /// Sets status + inline void setStatus ( int value) { + if (coinFactorizationA_) coinFactorizationA_->setStatus(value); + else coinFactorizationB_->setStatus(value) ; + } + /// Returns number of dense rows + inline int numberDense() const { + if (coinFactorizationA_) return coinFactorizationA_->numberDense(); + else return 0 ; + } +#if 1 + /// Returns number in U area + inline CoinBigIndex numberElementsU ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->numberElementsU(); + else return -1 ; + } + /// Returns number in L area + inline CoinBigIndex numberElementsL ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->numberElementsL(); + else return -1 ; + } + /// Returns number in R area + inline CoinBigIndex numberElementsR ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->numberElementsR(); + else return 0 ; + } +#endif + bool timeToRefactorize() const; +#if CLP_FACTORIZATION_NEW_TIMING>1 + void statsRefactor(char when) const; +#endif + /// Level of detail of messages + inline int messageLevel ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->messageLevel(); + else return 1 ; + } + /// Set level of detail of messages + inline void messageLevel ( int value) { + if (coinFactorizationA_) coinFactorizationA_->messageLevel(value); + } + /// Get rid of all memory + inline void clearArrays() { + if (coinFactorizationA_) + coinFactorizationA_->clearArrays(); + else if (coinFactorizationB_) + coinFactorizationB_->clearArrays(); + } + /// Number of Rows after factorization + inline int numberRows ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->numberRows(); + else return coinFactorizationB_->numberRows() ; + } + /// Gets dense threshold + inline int denseThreshold() const { + if (coinFactorizationA_) return coinFactorizationA_->denseThreshold(); + else return 0 ; + } + /// Sets dense threshold + inline void setDenseThreshold(int value) { + if (coinFactorizationA_) coinFactorizationA_->setDenseThreshold(value); + } + /// Pivot tolerance + inline double pivotTolerance ( ) const { + if (coinFactorizationA_) return coinFactorizationA_->pivotTolerance(); + else if (coinFactorizationB_) return coinFactorizationB_->pivotTolerance(); + return 1.0e-8 ; + } + /// Set pivot tolerance + inline void pivotTolerance ( double value) { + if (coinFactorizationA_) coinFactorizationA_->pivotTolerance(value); + else if (coinFactorizationB_) coinFactorizationB_->pivotTolerance(value); + } + /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed + inline void relaxAccuracyCheck(double value) { + if (coinFactorizationA_) coinFactorizationA_->relaxAccuracyCheck(value); + } + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + inline int persistenceFlag() const { + if (coinFactorizationA_) return coinFactorizationA_->persistenceFlag(); + else return 0 ; + } + inline void setPersistenceFlag(int value) { + if (coinFactorizationA_) coinFactorizationA_->setPersistenceFlag(value); + } + /// Delete all stuff (leaves as after CoinFactorization()) + inline void almostDestructor() { + if (coinFactorizationA_) + coinFactorizationA_->almostDestructor(); + else if (coinFactorizationB_) + coinFactorizationB_->clearArrays(); + } + /// Returns areaFactor but adjusted for dense + inline double adjustedAreaFactor() const { + if (coinFactorizationA_) return coinFactorizationA_->adjustedAreaFactor(); + else return 0.0 ; + } + inline void setBiasLU(int value) { + if (coinFactorizationA_) coinFactorizationA_->setBiasLU(value); + } + /// true if Forrest Tomlin update, false if PFI + inline void setForrestTomlin(bool value) { + if (coinFactorizationA_) coinFactorizationA_->setForrestTomlin(value); + } + /// Sets default values + inline void setDefaultValues() { + if (coinFactorizationA_) { + // row activities have negative sign +#ifndef COIN_FAST_CODE + coinFactorizationA_->slackValue(-1.0); +#endif + coinFactorizationA_->zeroTolerance(1.0e-13); + } + } + /// If nonzero force use of 1,dense 2,small 3,osl + void forceOtherFactorization(int which); + /// Get switch to osl if number rows <= this + inline int goOslThreshold() const { + return goOslThreshold_; + } + /// Set switch to osl if number rows <= this + inline void setGoOslThreshold(int value) { + goOslThreshold_ = value; + } + /// Get switch to dense if number rows <= this + inline int goDenseThreshold() const { + return goDenseThreshold_; + } + /// Set switch to dense if number rows <= this + inline void setGoDenseThreshold(int value) { + goDenseThreshold_ = value; + } + /// Get switch to small if number rows <= this + inline int goSmallThreshold() const { + return goSmallThreshold_; + } + /// Set switch to small if number rows <= this + inline void setGoSmallThreshold(int value) { + goSmallThreshold_ = value; + } + /// Go over to dense or small code if small enough + void goDenseOrSmall(int numberRows) ; + /// Sets factorization + void setFactorization(ClpFactorization & factorization); + /// Return 1 if dense code + inline int isDenseOrSmall() const { + return coinFactorizationB_ ? 1 : 0; + } +#else + inline bool timeToRefactorize() const { + return (pivots() * 3 > maximumPivots() * 2 && + numberElementsR() * 3 > (numberElementsL() + numberElementsU()) * 2 + 1000 && + !numberDense()); + } + /// Sets default values + inline void setDefaultValues() { + // row activities have negative sign +#ifndef COIN_FAST_CODE + slackValue(-1.0); +#endif + zeroTolerance(1.0e-13); + } + /// Go over to dense code + inline void goDense() {} +#endif + //@} + + /**@name other stuff */ + //@{ + /** makes a row copy of L for speed and to allow very sparse problems */ + void goSparse(); + /// Cleans up i.e. gets rid of network basis + void cleanUp(); + /// Says whether to redo pivot order + bool needToReorder() const; +#ifndef SLIM_CLP + /// Says if a network basis + inline bool networkBasis() const { + return (networkBasis_ != NULL); + } +#else + /// Says if a network basis + inline bool networkBasis() const { + return false; + } +#endif + /// Fills weighted row list + void getWeights(int * weights) const; + //@} + +////////////////// data ////////////////// +private: + + /**@name data */ + //@{ + /// Pointer to network basis +#ifndef SLIM_CLP + ClpNetworkBasis * networkBasis_; +#endif +#ifdef CLP_MULTIPLE_FACTORIZATIONS + /// Pointer to CoinFactorization + CoinFactorization * coinFactorizationA_; + /// Pointer to CoinOtherFactorization + CoinOtherFactorization * coinFactorizationB_; +#ifdef CLP_REUSE_ETAS + /// Pointer to model + ClpSimplex * model_; +#endif + /// If nonzero force use of 1,dense 2,small 3,osl + int forceB_; + /// Switch to osl if number rows <= this + int goOslThreshold_; + /// Switch to small if number rows <= this + int goSmallThreshold_; + /// Switch to dense if number rows <= this + int goDenseThreshold_; +#endif +#ifdef CLP_FACTORIZATION_NEW_TIMING + /// For guessing when to re-factorize + mutable double shortestAverage_; + mutable double totalInR_; + mutable double totalInIncreasingU_; + mutable int endLengthU_; + mutable int lastNumberPivots_; + mutable int effectiveStartNumberU_; +#endif + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpGubDynamicMatrix.hpp b/thirdparty/linux/include/coin/ClpGubDynamicMatrix.hpp new file mode 100644 index 0000000..2d13e6d --- /dev/null +++ b/thirdparty/linux/include/coin/ClpGubDynamicMatrix.hpp @@ -0,0 +1,247 @@ +/* $Id: ClpGubDynamicMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpGubDynamicMatrix_H +#define ClpGubDynamicMatrix_H + + +#include "CoinPragma.hpp" + +#include "ClpGubMatrix.hpp" +/** This implements Gub rows plus a ClpPackedMatrix. + This a dynamic version which stores the gub part and dynamically creates matrix. + All bounds are assumed to be zero and infinity + + This is just a simple example for real column generation +*/ + +class ClpGubDynamicMatrix : public ClpGubMatrix { + +public: + /**@name Main functions provided */ + //@{ + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + /** This is local to Gub to allow synchronization: + mode=0 when status of basis is good + mode=1 when variable is flagged + mode=2 when all variables unflagged (returns number flagged) + mode=3 just reset costs (primal) + mode=4 correct number of dual infeasibilities + mode=5 return 4 if time to re-factorize + mode=8 - make sure set is clean + mode=9 - adjust lower, upper on set by incoming + */ + virtual int synchronize(ClpSimplex * model, int mode); + /// Sets up an effective RHS and does gub crash if needed + virtual void useEffectiveRhs(ClpSimplex * model, bool cheapest = true); + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); + /// Add a new variable to a set + void insertNonBasic(int sequence, int iSet); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, + bool check = false); + + using ClpPackedMatrix::times ; + /** Return <code>y + A * scalar *x</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + virtual void times(double scalar, + const double * x, double * y) const; + /** Just for debug + Returns sum and number of primal infeasibilities. Recomputes keys + */ + virtual int checkFeasible(ClpSimplex * model, double & sum) const; + /// Cleans data after setWarmStart + void cleanData(ClpSimplex * model); + //@} + + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpGubDynamicMatrix(); + /** Destructor */ + virtual ~ClpGubDynamicMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpGubDynamicMatrix(const ClpGubDynamicMatrix&); + /** This is the real constructor. + It assumes factorization frequency will not be changed. + This resizes model !!!! + */ + ClpGubDynamicMatrix(ClpSimplex * model, int numberSets, + int numberColumns, const int * starts, + const double * lower, const double * upper, + const int * startColumn, const int * row, + const double * element, const double * cost, + const double * lowerColumn = NULL, const double * upperColumn = NULL, + const unsigned char * status = NULL); + + ClpGubDynamicMatrix& operator=(const ClpGubDynamicMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + //@} + /**@name gets and sets */ + //@{ + /// enums for status of various sorts + enum DynamicStatus { + inSmall = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03 + }; + /// Whether flagged + inline bool flagged(int i) const { + return (dynamicStatus_[i] & 8) != 0; + } + inline void setFlagged(int i) { + dynamicStatus_[i] = static_cast<unsigned char>(dynamicStatus_[i] | 8); + } + inline void unsetFlagged(int i) { + dynamicStatus_[i] = static_cast<unsigned char>(dynamicStatus_[i] & ~8); + } + inline void setDynamicStatus(int sequence, DynamicStatus status) { + unsigned char & st_byte = dynamicStatus_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | status); + } + inline DynamicStatus getDynamicStatus(int sequence) const { + return static_cast<DynamicStatus> (dynamicStatus_[sequence] & 7); + } + /// Saved value of objective offset + inline double objectiveOffset() const { + return objectiveOffset_; + } + /// Starts of each column + inline CoinBigIndex * startColumn() const { + return startColumn_; + } + /// rows + inline int * row() const { + return row_; + } + /// elements + inline double * element() const { + return element_; + } + /// costs + inline double * cost() const { + return cost_; + } + /// full starts + inline int * fullStart() const { + return fullStart_; + } + /// ids of active columns (just index here) + inline int * id() const { + return id_; + } + /// Optional lower bounds on columns + inline double * lowerColumn() const { + return lowerColumn_; + } + /// Optional upper bounds on columns + inline double * upperColumn() const { + return upperColumn_; + } + /// Optional true lower bounds on sets + inline double * lowerSet() const { + return lowerSet_; + } + /// Optional true upper bounds on sets + inline double * upperSet() const { + return upperSet_; + } + /// size + inline int numberGubColumns() const { + return numberGubColumns_; + } + /// first free + inline int firstAvailable() const { + return firstAvailable_; + } + /// set first free + inline void setFirstAvailable(int value) { + firstAvailable_ = value; + } + /// first dynamic + inline int firstDynamic() const { + return firstDynamic_; + } + /// number of columns in dynamic model + inline int lastDynamic() const { + return lastDynamic_; + } + /// size of working matrix (max) + inline int numberElements() const { + return numberElements_; + } + /// Status region for gub slacks + inline unsigned char * gubRowStatus() const { + return status_; + } + /// Status region for gub variables + inline unsigned char * dynamicStatus() const { + return dynamicStatus_; + } + /// Returns which set a variable is in + int whichSet (int sequence) const; + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Saved value of objective offset + double objectiveOffset_; + /// Starts of each column + CoinBigIndex * startColumn_; + /// rows + int * row_; + /// elements + double * element_; + /// costs + double * cost_; + /// full starts + int * fullStart_; + /// ids of active columns (just index here) + int * id_; + /// for status and which bound + unsigned char * dynamicStatus_; + /// Optional lower bounds on columns + double * lowerColumn_; + /// Optional upper bounds on columns + double * upperColumn_; + /// Optional true lower bounds on sets + double * lowerSet_; + /// Optional true upper bounds on sets + double * upperSet_; + /// size + int numberGubColumns_; + /// first free + int firstAvailable_; + /// saved first free + int savedFirstAvailable_; + /// first dynamic + int firstDynamic_; + /// number of columns in dynamic model + int lastDynamic_; + /// size of working matrix (max) + int numberElements_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpGubMatrix.hpp b/thirdparty/linux/include/coin/ClpGubMatrix.hpp new file mode 100644 index 0000000..26c3f62 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpGubMatrix.hpp @@ -0,0 +1,358 @@ +/* $Id: ClpGubMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpGubMatrix_H +#define ClpGubMatrix_H + + +#include "CoinPragma.hpp" + +#include "ClpPackedMatrix.hpp" +class ClpSimplex; +/** This implements Gub rows plus a ClpPackedMatrix. + + There will be a version using ClpPlusMinusOne matrix but + there is no point doing one with ClpNetworkMatrix (although + an embedded network is attractive). + +*/ + +class ClpGubMatrix : public ClpPackedMatrix { + +public: + /**@name Main functions provided */ + //@{ + /** Returns a new matrix in reverse order without gaps (GUB wants NULL) */ + virtual ClpMatrixBase * reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual CoinBigIndex countBasis(const int * whichColumn, + int & numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex * model, + const int * whichColumn, + int & numberColumnBasic, + int * row, int * start, + int * rowCount, int * columnCount, + CoinFactorizationDouble * element); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column) const ; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex * model, + CoinIndexedVector * rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column, double multiplier) const ; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex * model, double * array, + int column, double multiplier) const; + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + /// Returns number of hidden rows e.g. gub + virtual int hiddenRows() const; + //@} + + /**@name Matrix times vector methods */ + //@{ + + using ClpPackedMatrix::transposeTimes ; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex. + This version uses row copy*/ + virtual void transposeTimesByRow(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x *A</code> in <code>z</code> but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex * model, + const CoinIndexedVector * x, + const CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** expands an updated column to allow for extra rows which the main + solver does not know about and returns number added if mode 0. + If mode 1 deletes extra entries + + This active in Gub + */ + virtual int extendUpdated(ClpSimplex * model, CoinIndexedVector * update, int mode); + /** + mode=0 - Set up before "update" and "times" for primal solution using extended rows + mode=1 - Cleanup primal solution after "times" using extended rows. + mode=2 - Check (or report on) primal infeasibilities + */ + virtual void primalExpanded(ClpSimplex * model, int mode); + /** + mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended + updates array (and may use other if dual values pass) + mode=1 - Update dual solution after "transposeTimes" using extended rows. + mode=2 - Compute all djs and compute key dual infeasibilities + mode=3 - Report on key dual infeasibilities + mode=4 - Modify before updateTranspose in partial pricing + */ + virtual void dualExpanded(ClpSimplex * model, CoinIndexedVector * array, + double * other, int mode); + /** + mode=0 - Create list of non-key basics in pivotVariable_ using + number as numberBasic in and out + mode=1 - Set all key variables as basic + mode=2 - return number extra rows needed, number gives maximum number basic + mode=3 - before replaceColumn + mode=4 - return 1 if can do primal, 2 if dual, 3 if both + mode=5 - save any status stuff (when in good state) + mode=6 - restore status stuff + mode=7 - flag given variable (normally sequenceIn) + mode=8 - unflag all variables + mode=9 - synchronize costs + mode=10 - return 1 if there may be changing bounds on variable (column generation) + mode=11 - make sure set is clean (used when a variable rejected - but not flagged) + mode=12 - after factorize but before permute stuff + mode=13 - at end of simplex to delete stuff + */ + virtual int generalExpanded(ClpSimplex * model, int mode, int & number); + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); + /// Sets up an effective RHS and does gub crash if needed + virtual void useEffectiveRhs(ClpSimplex * model, bool cheapest = true); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, + bool check = false); + /** This is local to Gub to allow synchronization: + mode=0 when status of basis is good + mode=1 when variable is flagged + mode=2 when all variables unflagged (returns number flagged) + mode=3 just reset costs (primal) + mode=4 correct number of dual infeasibilities + mode=5 return 4 if time to re-factorize + mode=6 - return 1 if there may be changing bounds on variable (column generation) + mode=7 - do extra restores for column generation + mode=8 - make sure set is clean + mode=9 - adjust lower, upper on set by incoming + */ + virtual int synchronize(ClpSimplex * model, int mode); + /// Correct sequence in and out to give true value + virtual void correctSequence(const ClpSimplex * model, int & sequenceIn, int & sequenceOut) ; + //@} + + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpGubMatrix(); + /** Destructor */ + virtual ~ClpGubMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpGubMatrix(const ClpGubMatrix&); + /** The copy constructor from an CoinPackedMatrix. */ + ClpGubMatrix(const CoinPackedMatrix&); + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpGubMatrix (const ClpGubMatrix & wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + ClpGubMatrix (const CoinPackedMatrix & wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + + /** This takes over ownership (for space reasons) */ + ClpGubMatrix(CoinPackedMatrix * matrix); + + /** This takes over ownership (for space reasons) and is the + real constructor*/ + ClpGubMatrix(ClpPackedMatrix * matrix, int numberSets, + const int * start, const int * end, + const double * lower, const double * upper, + const unsigned char * status = NULL); + + ClpGubMatrix& operator=(const ClpGubMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase * subsetClone ( + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns) const ; + /** redoes next_ for a set. */ + void redoSet(ClpSimplex * model, int newKey, int oldKey, int iSet); + //@} + /**@name gets and sets */ + //@{ + /// Status + inline ClpSimplex::Status getStatus(int sequence) const { + return static_cast<ClpSimplex::Status> (status_[sequence] & 7); + } + inline void setStatus(int sequence, ClpSimplex::Status status) { + unsigned char & st_byte = status_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | status); + } + /// To flag a variable + inline void setFlagged( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 64); + } + inline void clearFlagged( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~64); + } + inline bool flagged(int sequence) const { + return ((status_[sequence] & 64) != 0); + } + /// To say key is above ub + inline void setAbove( int sequence) { + unsigned char iStat = status_[sequence]; + iStat = static_cast<unsigned char>(iStat & ~24); + status_[sequence] = static_cast<unsigned char>(iStat | 16); + } + /// To say key is feasible + inline void setFeasible( int sequence) { + unsigned char iStat = status_[sequence]; + iStat = static_cast<unsigned char>(iStat & ~24); + status_[sequence] = static_cast<unsigned char>(iStat | 8); + } + /// To say key is below lb + inline void setBelow( int sequence) { + unsigned char iStat = status_[sequence]; + iStat = static_cast<unsigned char>(iStat & ~24); + status_[sequence] = iStat; + } + inline double weight( int sequence) const { + int iStat = status_[sequence] & 31; + iStat = iStat >> 3; + return static_cast<double> (iStat - 1); + } + /// Starts + inline int * start() const { + return start_; + } + /// End + inline int * end() const { + return end_; + } + /// Lower bounds on sets + inline double * lower() const { + return lower_; + } + /// Upper bounds on sets + inline double * upper() const { + return upper_; + } + /// Key variable of set + inline int * keyVariable() const { + return keyVariable_; + } + /// Backward pointer to set number + inline int * backward() const { + return backward_; + } + /// Number of sets (gub rows) + inline int numberSets() const { + return numberSets_; + } + /// Switches off dj checking each factorization (for BIG models) + void switchOffCheck(); + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Sum of dual infeasibilities + double sumDualInfeasibilities_; + /// Sum of primal infeasibilities + double sumPrimalInfeasibilities_; + /// Sum of Dual infeasibilities using tolerance based on error in duals + double sumOfRelaxedDualInfeasibilities_; + /// Sum of Primal infeasibilities using tolerance based on error in primals + double sumOfRelaxedPrimalInfeasibilities_; + /// Infeasibility weight when last full pass done + double infeasibilityWeight_; + /// Starts + int * start_; + /// End + int * end_; + /// Lower bounds on sets + double * lower_; + /// Upper bounds on sets + double * upper_; + /// Status of slacks + mutable unsigned char * status_; + /// Saved status of slacks + unsigned char * saveStatus_; + /// Saved key variables + int * savedKeyVariable_; + /// Backward pointer to set number + int * backward_; + /// Backward pointer to pivot row !!! + int * backToPivotRow_; + /// Change in costs for keys + double * changeCost_; + /// Key variable of set + mutable int * keyVariable_; + /** Next basic variable in set - starts at key and end with -(set+1). + Now changes to -(nonbasic+1). + next_ has extra space for 2* longest set */ + mutable int * next_; + /// Backward pointer to index in CoinIndexedVector + int * toIndex_; + // Reverse pointer from index to set + int * fromIndex_; + /// Pointer back to model + ClpSimplex * model_; + /// Number of dual infeasibilities + int numberDualInfeasibilities_; + /// Number of primal infeasibilities + int numberPrimalInfeasibilities_; + /** If pricing will declare victory (i.e. no check every factorization). + -1 - always check + 0 - don't check + 1 - in don't check mode but looks optimal + */ + int noCheck_; + /// Number of sets (gub rows) + int numberSets_; + /// Number in vector without gub extension + int saveNumber_; + /// Pivot row of possible next key + int possiblePivotKey_; + /// Gub slack in (set number or -1) + int gubSlackIn_; + /// First gub variables (same as start_[0] at present) + int firstGub_; + /// last gub variable (same as end_[numberSets_-1] at present) + int lastGub_; + /** type of gub - 0 not contiguous, 1 contiguous + add 8 bit to say no ubs on individual variables */ + int gubType_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpInterior.hpp b/thirdparty/linux/include/coin/ClpInterior.hpp new file mode 100644 index 0000000..7f87e1e --- /dev/null +++ b/thirdparty/linux/include/coin/ClpInterior.hpp @@ -0,0 +1,570 @@ +/* $Id: ClpInterior.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Tomlin (pdco) + John Forrest (standard predictor-corrector) + + Note JJF has added arrays - this takes more memory but makes + flow easier to understand and hopefully easier to extend + + */ +#ifndef ClpInterior_H +#define ClpInterior_H + +#include <iostream> +#include <cfloat> +#include "ClpModel.hpp" +#include "ClpMatrixBase.hpp" +#include "ClpSolve.hpp" +#include "CoinDenseVector.hpp" +class ClpLsqr; +class ClpPdcoBase; +/// ******** DATA to be moved into protected section of ClpInterior +typedef struct { + double atolmin; + double r3norm; + double LSdamp; + double* deltay; +} Info; +/// ******** DATA to be moved into protected section of ClpInterior + +typedef struct { + double atolold; + double atolnew; + double r3ratio; + int istop; + int itncg; +} Outfo; +/// ******** DATA to be moved into protected section of ClpInterior + +typedef struct { + double gamma; + double delta; + int MaxIter; + double FeaTol; + double OptTol; + double StepTol; + double x0min; + double z0min; + double mu0; + int LSmethod; // 1=Cholesky 2=QR 3=LSQR + int LSproblem; // See below + int LSQRMaxIter; + double LSQRatol1; // Initial atol + double LSQRatol2; // Smallest atol (unless atol1 is smaller) + double LSQRconlim; + int wait; +} Options; +class Lsqr; +class ClpCholeskyBase; +// ***** END +/** This solves LPs using interior point methods + + It inherits from ClpModel and all its arrays are created at + algorithm time. + +*/ + +class ClpInterior : public ClpModel { + friend void ClpInteriorUnitTest(const std::string & mpsDir, + const std::string & netlibDir); + +public: + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpInterior ( ); + + /// Copy constructor. + ClpInterior(const ClpInterior &); + /// Copy constructor from model. + ClpInterior(const ClpModel &); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + */ + ClpInterior (const ClpModel * wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns, + bool dropNames = true, bool dropIntegers = true); + /// Assignment operator. This copies the data + ClpInterior & operator=(const ClpInterior & rhs); + /// Destructor + ~ClpInterior ( ); + // Ones below are just ClpModel with some changes + /** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + */ + void loadProblem ( const ClpMatrixBase& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + void loadProblem ( const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + + /** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ + void loadProblem ( const int numcols, const int numrows, + const CoinBigIndex* start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + /// This one is for after presolve to save memory + void loadProblem ( const int numcols, const int numrows, + const CoinBigIndex* start, const int* index, + const double* value, const int * length, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + /// Read an mps file from the given filename + int readMps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + /** Borrow model. This is so we dont have to copy large amounts + of data around. It assumes a derived class wants to overwrite + an empty model with a real one - while it does an algorithm. + This is same as ClpModel one. */ + void borrowModel(ClpModel & otherModel); + /** Return model - updates any scalars */ + void returnModel(ClpModel & otherModel); + //@} + + /**@name Functions most useful to user */ + //@{ + /** Pdco algorithm - see ClpPdco.hpp for method */ + int pdco(); + // ** Temporary version + int pdco( ClpPdcoBase * stuff, Options &options, Info &info, Outfo &outfo); + /// Primal-Dual Predictor-Corrector barrier + int primalDual(); + //@} + + /**@name most useful gets and sets */ + //@{ + /// If problem is primal feasible + inline bool primalFeasible() const { + return (sumPrimalInfeasibilities_ <= 1.0e-5); + } + /// If problem is dual feasible + inline bool dualFeasible() const { + return (sumDualInfeasibilities_ <= 1.0e-5); + } + /// Current (or last) algorithm + inline int algorithm() const { + return algorithm_; + } + /// Set algorithm + inline void setAlgorithm(int value) { + algorithm_ = value; + } + /// Sum of dual infeasibilities + inline CoinWorkDouble sumDualInfeasibilities() const { + return sumDualInfeasibilities_; + } + /// Sum of primal infeasibilities + inline CoinWorkDouble sumPrimalInfeasibilities() const { + return sumPrimalInfeasibilities_; + } + /// dualObjective. + inline CoinWorkDouble dualObjective() const { + return dualObjective_; + } + /// primalObjective. + inline CoinWorkDouble primalObjective() const { + return primalObjective_; + } + /// diagonalNorm + inline CoinWorkDouble diagonalNorm() const { + return diagonalNorm_; + } + /// linearPerturbation + inline CoinWorkDouble linearPerturbation() const { + return linearPerturbation_; + } + inline void setLinearPerturbation(CoinWorkDouble value) { + linearPerturbation_ = value; + } + /// projectionTolerance + inline CoinWorkDouble projectionTolerance() const { + return projectionTolerance_; + } + inline void setProjectionTolerance(CoinWorkDouble value) { + projectionTolerance_ = value; + } + /// diagonalPerturbation + inline CoinWorkDouble diagonalPerturbation() const { + return diagonalPerturbation_; + } + inline void setDiagonalPerturbation(CoinWorkDouble value) { + diagonalPerturbation_ = value; + } + /// gamma + inline CoinWorkDouble gamma() const { + return gamma_; + } + inline void setGamma(CoinWorkDouble value) { + gamma_ = value; + } + /// delta + inline CoinWorkDouble delta() const { + return delta_; + } + inline void setDelta(CoinWorkDouble value) { + delta_ = value; + } + /// ComplementarityGap + inline CoinWorkDouble complementarityGap() const { + return complementarityGap_; + } + //@} + + /**@name most useful gets and sets */ + //@{ + /// Largest error on Ax-b + inline CoinWorkDouble largestPrimalError() const { + return largestPrimalError_; + } + /// Largest error on basic duals + inline CoinWorkDouble largestDualError() const { + return largestDualError_; + } + /// Maximum iterations + inline int maximumBarrierIterations() const { + return maximumBarrierIterations_; + } + inline void setMaximumBarrierIterations(int value) { + maximumBarrierIterations_ = value; + } + /// Set cholesky (and delete present one) + void setCholesky(ClpCholeskyBase * cholesky); + /// Return number fixed to see if worth presolving + int numberFixed() const; + /** fix variables interior says should be. If reallyFix false then just + set values to exact bounds */ + void fixFixed(bool reallyFix = true); + /// Primal erturbation vector + inline CoinWorkDouble * primalR() const { + return primalR_; + } + /// Dual erturbation vector + inline CoinWorkDouble * dualR() const { + return dualR_; + } + //@} + +protected: + /**@name protected methods */ + //@{ + /// Does most of deletion + void gutsOfDelete(); + /// Does most of copying + void gutsOfCopy(const ClpInterior & rhs); + /// Returns true if data looks okay, false if not + bool createWorkingData(); + void deleteWorkingData(); + /// Sanity check on input rim data + bool sanityCheck(); + /// This does housekeeping + int housekeeping(); + //@} +public: + /**@name public methods */ + //@{ + /// Raw objective value (so always minimize) + inline CoinWorkDouble rawObjectiveValue() const { + return objectiveValue_; + } + /// Returns 1 if sequence indicates column + inline int isColumn(int sequence) const { + return sequence < numberColumns_ ? 1 : 0; + } + /// Returns sequence number within section + inline int sequenceWithin(int sequence) const { + return sequence < numberColumns_ ? sequence : sequence - numberColumns_; + } + /// Checks solution + void checkSolution(); + /** Modifies djs to allow for quadratic. + returns quadratic offset */ + CoinWorkDouble quadraticDjs(CoinWorkDouble * djRegion, const CoinWorkDouble * solution, + CoinWorkDouble scaleFactor); + + /// To say a variable is fixed + inline void setFixed( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 1) ; + } + inline void clearFixed( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~1) ; + } + inline bool fixed(int sequence) const { + return ((status_[sequence] & 1) != 0); + } + + /// To flag a variable + inline void setFlagged( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 2) ; + } + inline void clearFlagged( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~2) ; + } + inline bool flagged(int sequence) const { + return ((status_[sequence] & 2) != 0); + } + + /// To say a variable is fixed OR free + inline void setFixedOrFree( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 4) ; + } + inline void clearFixedOrFree( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~4) ; + } + inline bool fixedOrFree(int sequence) const { + return ((status_[sequence] & 4) != 0); + } + + /// To say a variable has lower bound + inline void setLowerBound( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 8) ; + } + inline void clearLowerBound( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~8) ; + } + inline bool lowerBound(int sequence) const { + return ((status_[sequence] & 8) != 0); + } + + /// To say a variable has upper bound + inline void setUpperBound( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 16) ; + } + inline void clearUpperBound( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~16) ; + } + inline bool upperBound(int sequence) const { + return ((status_[sequence] & 16) != 0); + } + + /// To say a variable has fake lower bound + inline void setFakeLower( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 32) ; + } + inline void clearFakeLower( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~32) ; + } + inline bool fakeLower(int sequence) const { + return ((status_[sequence] & 32) != 0); + } + + /// To say a variable has fake upper bound + inline void setFakeUpper( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 64) ; + } + inline void clearFakeUpper( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~64) ; + } + inline bool fakeUpper(int sequence) const { + return ((status_[sequence] & 64) != 0); + } + //@} + +////////////////// data ////////////////// +protected: + + /**@name data. Many arrays have a row part and a column part. + There is a single array with both - columns then rows and + then normally two arrays pointing to rows and columns. The + single array is the owner of memory + */ + //@{ + /// Largest error on Ax-b + CoinWorkDouble largestPrimalError_; + /// Largest error on basic duals + CoinWorkDouble largestDualError_; + /// Sum of dual infeasibilities + CoinWorkDouble sumDualInfeasibilities_; + /// Sum of primal infeasibilities + CoinWorkDouble sumPrimalInfeasibilities_; + /// Worst complementarity + CoinWorkDouble worstComplementarity_; + /// +public: + CoinWorkDouble xsize_; + CoinWorkDouble zsize_; +protected: + /// Working copy of lower bounds (Owner of arrays below) + CoinWorkDouble * lower_; + /// Row lower bounds - working copy + CoinWorkDouble * rowLowerWork_; + /// Column lower bounds - working copy + CoinWorkDouble * columnLowerWork_; + /// Working copy of upper bounds (Owner of arrays below) + CoinWorkDouble * upper_; + /// Row upper bounds - working copy + CoinWorkDouble * rowUpperWork_; + /// Column upper bounds - working copy + CoinWorkDouble * columnUpperWork_; + /// Working copy of objective + CoinWorkDouble * cost_; +public: + /// Rhs + CoinWorkDouble * rhs_; + CoinWorkDouble * x_; + CoinWorkDouble * y_; + CoinWorkDouble * dj_; +protected: + /// Pointer to Lsqr object + ClpLsqr * lsqrObject_; + /// Pointer to stuff + ClpPdcoBase * pdcoStuff_; + /// Below here is standard barrier stuff + /// mu. + CoinWorkDouble mu_; + /// objectiveNorm. + CoinWorkDouble objectiveNorm_; + /// rhsNorm. + CoinWorkDouble rhsNorm_; + /// solutionNorm. + CoinWorkDouble solutionNorm_; + /// dualObjective. + CoinWorkDouble dualObjective_; + /// primalObjective. + CoinWorkDouble primalObjective_; + /// diagonalNorm. + CoinWorkDouble diagonalNorm_; + /// stepLength + CoinWorkDouble stepLength_; + /// linearPerturbation + CoinWorkDouble linearPerturbation_; + /// diagonalPerturbation + CoinWorkDouble diagonalPerturbation_; + // gamma from Saunders and Tomlin regularized + CoinWorkDouble gamma_; + // delta from Saunders and Tomlin regularized + CoinWorkDouble delta_; + /// targetGap + CoinWorkDouble targetGap_; + /// projectionTolerance + CoinWorkDouble projectionTolerance_; + /// maximumRHSError. maximum Ax + CoinWorkDouble maximumRHSError_; + /// maximumBoundInfeasibility. + CoinWorkDouble maximumBoundInfeasibility_; + /// maximumDualError. + CoinWorkDouble maximumDualError_; + /// diagonalScaleFactor. + CoinWorkDouble diagonalScaleFactor_; + /// scaleFactor. For scaling objective + CoinWorkDouble scaleFactor_; + /// actualPrimalStep + CoinWorkDouble actualPrimalStep_; + /// actualDualStep + CoinWorkDouble actualDualStep_; + /// smallestInfeasibility + CoinWorkDouble smallestInfeasibility_; + /// historyInfeasibility. +#define LENGTH_HISTORY 5 + CoinWorkDouble historyInfeasibility_[LENGTH_HISTORY]; + /// complementarityGap. + CoinWorkDouble complementarityGap_; + /// baseObjectiveNorm + CoinWorkDouble baseObjectiveNorm_; + /// worstDirectionAccuracy + CoinWorkDouble worstDirectionAccuracy_; + /// maximumRHSChange + CoinWorkDouble maximumRHSChange_; + /// errorRegion. i.e. Ax + CoinWorkDouble * errorRegion_; + /// rhsFixRegion. + CoinWorkDouble * rhsFixRegion_; + /// upperSlack + CoinWorkDouble * upperSlack_; + /// lowerSlack + CoinWorkDouble * lowerSlack_; + /// diagonal + CoinWorkDouble * diagonal_; + /// solution + CoinWorkDouble * solution_; + /// work array + CoinWorkDouble * workArray_; + /// delta X + CoinWorkDouble * deltaX_; + /// delta Y + CoinWorkDouble * deltaY_; + /// deltaZ. + CoinWorkDouble * deltaZ_; + /// deltaW. + CoinWorkDouble * deltaW_; + /// deltaS. + CoinWorkDouble * deltaSU_; + CoinWorkDouble * deltaSL_; + /// Primal regularization array + CoinWorkDouble * primalR_; + /// Dual regularization array + CoinWorkDouble * dualR_; + /// rhs B + CoinWorkDouble * rhsB_; + /// rhsU. + CoinWorkDouble * rhsU_; + /// rhsL. + CoinWorkDouble * rhsL_; + /// rhsZ. + CoinWorkDouble * rhsZ_; + /// rhsW. + CoinWorkDouble * rhsW_; + /// rhs C + CoinWorkDouble * rhsC_; + /// zVec + CoinWorkDouble * zVec_; + /// wVec + CoinWorkDouble * wVec_; + /// cholesky. + ClpCholeskyBase * cholesky_; + /// numberComplementarityPairs i.e. ones with lower and/or upper bounds (not fixed) + int numberComplementarityPairs_; + /// numberComplementarityItems_ i.e. number of active bounds + int numberComplementarityItems_; + /// Maximum iterations + int maximumBarrierIterations_; + /// gonePrimalFeasible. + bool gonePrimalFeasible_; + /// goneDualFeasible. + bool goneDualFeasible_; + /// Which algorithm being used + int algorithm_; + //@} +}; +//############################################################################# +/** A function that tests the methods in the ClpInterior class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. + + It also does some testing of ClpFactorization class + */ +void +ClpInteriorUnitTest(const std::string & mpsDir, + const std::string & netlibDir); + + +#endif diff --git a/thirdparty/linux/include/coin/ClpLinearObjective.hpp b/thirdparty/linux/include/coin/ClpLinearObjective.hpp new file mode 100644 index 0000000..ff035d4 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpLinearObjective.hpp @@ -0,0 +1,103 @@ +/* $Id: ClpLinearObjective.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpLinearObjective_H +#define ClpLinearObjective_H + +#include "ClpObjective.hpp" + +//############################################################################# + +/** Linear Objective Class + +*/ + +class ClpLinearObjective : public ClpObjective { + +public: + + ///@name Stuff + //@{ + + /** Returns objective coefficients. + + Offset is always set to 0.0. All other parameters unused. + */ + virtual double * gradient(const ClpSimplex * model, + const double * solution, double & offset, bool refresh, + int includeLinear = 2); + /** Returns reduced gradient.Returns an offset (to be added to current one). + */ + virtual double reducedGradient(ClpSimplex * model, double * region, + bool useFeasibleCosts); + /** Returns step length which gives minimum of objective for + solution + theta * change vector up to maximum theta. + + arrays are numberColumns+numberRows + Also sets current objective, predicted and at maximumTheta + */ + virtual double stepLength(ClpSimplex * model, + const double * solution, + const double * change, + double maximumTheta, + double & currentObj, + double & predictedObj, + double & thetaObj); + /// Return objective value (without any ClpModel offset) (model may be NULL) + virtual double objectiveValue(const ClpSimplex * model, const double * solution) const ; + /// Resize objective + virtual void resize(int newNumberColumns) ; + /// Delete columns in objective + virtual void deleteSome(int numberToDelete, const int * which) ; + /// Scale objective + virtual void reallyScale(const double * columnScale) ; + + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpLinearObjective(); + + /// Constructor from objective + ClpLinearObjective(const double * objective, int numberColumns); + + /// Copy constructor + ClpLinearObjective(const ClpLinearObjective &); + /** Subset constructor. Duplicates are allowed + and order is as given. + */ + ClpLinearObjective (const ClpLinearObjective &rhs, int numberColumns, + const int * whichColumns) ; + + /// Assignment operator + ClpLinearObjective & operator=(const ClpLinearObjective& rhs); + + /// Destructor + virtual ~ClpLinearObjective (); + + /// Clone + virtual ClpObjective * clone() const; + /** Subset clone. Duplicates are allowed + and order is as given. + */ + virtual ClpObjective * subsetClone (int numberColumns, + const int * whichColumns) const; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Objective + double * objective_; + /// number of columns + int numberColumns_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpMatrixBase.hpp b/thirdparty/linux/include/coin/ClpMatrixBase.hpp new file mode 100644 index 0000000..06dc523 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpMatrixBase.hpp @@ -0,0 +1,524 @@ +/* $Id: ClpMatrixBase.hpp 2078 2015-01-05 12:39:49Z 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). + +#ifndef ClpMatrixBase_H +#define ClpMatrixBase_H + +#include "CoinPragma.hpp" +#include "CoinTypes.hpp" + +#include "CoinPackedMatrix.hpp" +class CoinIndexedVector; +class ClpSimplex; +class ClpModel; +// Compilers can produce better code if they know about __restrict +#ifndef COIN_RESTRICT +#ifdef COIN_USE_RESTRICT +#define COIN_RESTRICT __restrict +#else +#define COIN_RESTRICT +#endif +#endif + +/** Abstract base class for Clp Matrices + +Since this class is abstract, no object of this type can be created. + +If a derived class provides all methods then all Clp algorithms +should work. Some can be very inefficient e.g. getElements etc is +only used for tightening bounds for dual and the copies are +deleted. Many methods can just be dummy i.e. abort(); if not +all features are being used. So if column generation was being done +then it makes no sense to do steepest edge so there would be +no point providing subsetTransposeTimes. +*/ + +class ClpMatrixBase { + +public: + /**@name Virtual methods that the derived classes must provide */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix * getPackedMatrix() const = 0; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const = 0; + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const = 0; + /** Number of columns. */ + virtual int getNumCols() const = 0; + /** Number of rows. */ + virtual int getNumRows() const = 0; + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double * getElements() const = 0; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int * getIndices() const = 0; + + virtual const CoinBigIndex * getVectorStarts() const = 0; + /** The lengths of the major-dimension vectors. */ + virtual const int * getVectorLengths() const = 0 ; + /** The length of a single major-dimension vector. */ + virtual int getVectorLength(int index) const ; + /** Delete the columns whose indices are listed in <code>indDel</code>. */ + virtual void deleteCols(const int numDel, const int * indDel) = 0; + /** Delete the rows whose indices are listed in <code>indDel</code>. */ + virtual void deleteRows(const int numDel, const int * indDel) = 0; +#ifndef CLP_NO_VECTOR + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); +#endif + /** Modify one element of packed matrix. An element may be added. + This works for either ordering If the new element is zero it will be + deleted unless keepZero true */ + virtual void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false); + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex * starts, const int * index, + const double * element, int numberOther = -1); + + /** Returns a new matrix in reverse order without gaps + Is allowed to return NULL if doesn't want to have row copy */ + virtual ClpMatrixBase * reverseOrderedCopy() const { + return NULL; + } + + /// Returns number of elements in column part of basis + virtual CoinBigIndex countBasis(const int * whichColumn, + int & numberColumnBasic) = 0; + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex * model, + const int * whichColumn, + int & numberColumnBasic, + int * row, int * start, + int * rowCount, int * columnCount, + CoinFactorizationDouble * element) = 0; + /** Creates scales for column copy (rowCopy in model may be modified) + default does not allow scaling + returns non-zero if no scaling done */ + virtual int scale(ClpModel * , const ClpSimplex * = NULL) const { + return 1; + } + /** Scales rowCopy if column copy scaled + Only called if scales already exist */ + virtual void scaleRowCopy(ClpModel * ) const { } + /// Returns true if can create row copy + virtual bool canGetRowCopy() const { + return true; + } + /** Realy really scales column copy + Only called if scales already exist. + Up to user to delete */ + inline virtual ClpMatrixBase * scaledColumnCopy(ClpModel * ) const { + return this->clone(); + } + + /** Checks if all elements are in valid range. Can just + return true if you are not paranoid. For Clp I will + probably expect no zeros. Code can modify matrix to get rid of + small elements. + check bits (can be turned off to save time) : + 1 - check if matrix has gaps + 2 - check if zero elements + 4 - check and compress duplicates + 8 - report on large and small + */ + virtual bool allElementsInRange(ClpModel * , + double , double , + int = 15) { + return true; + } + /** Set the dimensions of the matrix. In effect, append new empty + columns/rows to the matrix. A negative number for either dimension + means that that dimension doesn't change. Otherwise the new dimensions + MUST be at least as large as the current ones otherwise an exception + is thrown. */ + virtual void setDimensions(int numrows, int numcols); + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + If returns zeros then can't tell anything */ + virtual void rangeOfElements(double & smallestNegative, double & largestNegative, + double & smallestPositive, double & largestPositive); + + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column) const = 0; + /** Unpacks a column into an CoinIndexedvector + ** in packed format + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex * model, + CoinIndexedVector * rowArray, + int column) const = 0; + /** Purely for column generation and similar ideas. Allows + matrix and any bounds or costs to be updated (sensibly). + Returns non-zero if any changes. + */ + virtual int refresh(ClpSimplex * ) { + return 0; + } + + // Really scale matrix + virtual void reallyScale(const double * rowScale, const double * columnScale); + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + Default returns vector of ones + */ + virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column, double multiplier) const = 0; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex * model, double * array, + int column, double multiplier) const = 0; + /// Allow any parts of a created CoinPackedMatrix to be deleted + virtual void releasePackedMatrix() const = 0; + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Returns number of hidden rows e.g. gub + virtual int hiddenRows() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + /** expands an updated column to allow for extra rows which the main + solver does not know about and returns number added. + + This will normally be a no-op - it is in for GUB but may get extended to + general non-overlapping and embedded networks. + + mode 0 - extend + mode 1 - delete etc + */ + virtual int extendUpdated(ClpSimplex * model, CoinIndexedVector * update, int mode); + /** + utility primal function for dealing with dynamic constraints + mode=0 - Set up before "update" and "times" for primal solution using extended rows + mode=1 - Cleanup primal solution after "times" using extended rows. + mode=2 - Check (or report on) primal infeasibilities + */ + virtual void primalExpanded(ClpSimplex * model, int mode); + /** + utility dual function for dealing with dynamic constraints + mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended + updates array (and may use other if dual values pass) + mode=1 - Update dual solution after "transposeTimes" using extended rows. + mode=2 - Compute all djs and compute key dual infeasibilities + mode=3 - Report on key dual infeasibilities + mode=4 - Modify before updateTranspose in partial pricing + */ + virtual void dualExpanded(ClpSimplex * model, CoinIndexedVector * array, + double * other, int mode); + /** + general utility function for dealing with dynamic constraints + mode=0 - Create list of non-key basics in pivotVariable_ using + number as numberBasic in and out + mode=1 - Set all key variables as basic + mode=2 - return number extra rows needed, number gives maximum number basic + mode=3 - before replaceColumn + mode=4 - return 1 if can do primal, 2 if dual, 3 if both + mode=5 - save any status stuff (when in good state) + mode=6 - restore status stuff + mode=7 - flag given variable (normally sequenceIn) + mode=8 - unflag all variables + mode=9 - synchronize costs and bounds + mode=10 - return 1 if there may be changing bounds on variable (column generation) + mode=11 - make sure set is clean (used when a variable rejected - but not flagged) + mode=12 - after factorize but before permute stuff + mode=13 - at end of simplex to delete stuff + + */ + virtual int generalExpanded(ClpSimplex * model, int mode, int & number); + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); + /** Creates a variable. This is called after partial pricing and may modify matrix. + May update bestSequence. + */ + virtual void createVariable(ClpSimplex * model, int & bestSequence); + /** Just for debug if odd type matrix. + Returns number of primal infeasibilities. */ + virtual int checkFeasible(ClpSimplex * model, double & sum) const ; + /// Returns reduced cost of a variable + double reducedCost(ClpSimplex * model, int sequence) const; + /// Correct sequence in and out to give true value (if both -1 maybe do whole matrix) + virtual void correctSequence(const ClpSimplex * model, int & sequenceIn, int & sequenceOut) ; + //@} + + //--------------------------------------------------------------------------- + /**@name Matrix times vector methods + They can be faster if scalar is +- 1 + Also for simplex I am not using basic/non-basic split */ + //@{ + /** Return <code>y + A * x * scalar</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + virtual void times(double scalar, + const double * COIN_RESTRICT x, double * COIN_RESTRICT y) const = 0; + /** And for scaling - default aborts for when scaling not supported + (unless pointers NULL when as normal) + */ + virtual void times(double scalar, + const double * COIN_RESTRICT x, double * COIN_RESTRICT y, + const double * COIN_RESTRICT rowScale, + const double * COIN_RESTRICT columnScale) const; + /** Return <code>y + x * scalar * A</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> */ + virtual void transposeTimes(double scalar, + const double * COIN_RESTRICT x, double * COIN_RESTRICT y) const = 0; + /** And for scaling - default aborts for when scaling not supported + (unless pointers NULL when as normal) + */ + virtual void transposeTimes(double scalar, + const double * COIN_RESTRICT x, double * COIN_RESTRICT y, + const double * COIN_RESTRICT rowScale, + const double * COIN_RESTRICT columnScale, + double * COIN_RESTRICT spare = NULL) const; +#if COIN_LONG_WORK + // For long double versions (aborts if not supported) + virtual void times(CoinWorkDouble scalar, + const CoinWorkDouble * COIN_RESTRICT x, CoinWorkDouble * COIN_RESTRICT y) const ; + virtual void transposeTimes(CoinWorkDouble scalar, + const CoinWorkDouble * COIN_RESTRICT x, CoinWorkDouble * COIN_RESTRICT y) const ; +#endif + /** Return <code>x * scalar *A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const = 0; + /** Return <code>x *A</code> in <code>z</code> but + just for indices in y. + This is only needed for primal steepest edge. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex * model, + const CoinIndexedVector * x, + const CoinIndexedVector * y, + CoinIndexedVector * z) const = 0; + /** Returns true if can combine transposeTimes and subsetTransposeTimes + and if it would be faster */ + virtual bool canCombine(const ClpSimplex * , + const CoinIndexedVector * ) const { + return false; + } + /// Updates two arrays for steepest and does devex weights (need not be coded) + virtual void transposeTimes2(const ClpSimplex * model, + const CoinIndexedVector * pi1, CoinIndexedVector * dj1, + const CoinIndexedVector * pi2, + CoinIndexedVector * spare, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int * reference, + double * weights, double scaleFactor); + /// Updates second array for steepest and does devex weights (need not be coded) + virtual void subsetTimes2(const ClpSimplex * model, + CoinIndexedVector * dj1, + const CoinIndexedVector * pi2, CoinIndexedVector * dj2, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int * reference, + double * weights, double scaleFactor); + /** Return <code>x *A</code> in <code>z</code> but + just for number indices in y. + Default cheats with fake CoinIndexedVector and + then calls subsetTransposeTimes */ + virtual void listTransposeTimes(const ClpSimplex * model, + double * x, + int * y, + int number, + double * z) const; + //@} + //@{ + ///@name Other + /// Clone + virtual ClpMatrixBase * clone() const = 0; + /** Subset clone (without gaps). Duplicates are allowed + and order is as given. + Derived classes need not provide this as it may not always make + sense */ + virtual ClpMatrixBase * subsetClone ( + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns) const; + /// Gets rid of any mutable by products + virtual void backToBasics() {} + /** Returns type. + The types which code may need to know about are: + 1 - ClpPackedMatrix + 11 - ClpNetworkMatrix + 12 - ClpPlusMinusOneMatrix + */ + inline int type() const { + return type_; + } + /// Sets type + void setType(int newtype) { + type_ = newtype; + } + /// Sets up an effective RHS + void useEffectiveRhs(ClpSimplex * model); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, + bool check = false); + /// If rhsOffset used this is iteration last refreshed + inline int lastRefresh() const { + return lastRefresh_; + } + /// If rhsOffset used this is refresh frequency (0==off) + inline int refreshFrequency() const { + return refreshFrequency_; + } + inline void setRefreshFrequency(int value) { + refreshFrequency_ = value; + } + /// whether to skip dual checks most of time + inline bool skipDualCheck() const { + return skipDualCheck_; + } + inline void setSkipDualCheck(bool yes) { + skipDualCheck_ = yes; + } + /** Partial pricing tuning parameter - minimum number of "objects" to scan. + e.g. number of Gub sets but could be number of variables */ + inline int minimumObjectsScan() const { + return minimumObjectsScan_; + } + inline void setMinimumObjectsScan(int value) { + minimumObjectsScan_ = value; + } + /// Partial pricing tuning parameter - minimum number of negative reduced costs to get + inline int minimumGoodReducedCosts() const { + return minimumGoodReducedCosts_; + } + inline void setMinimumGoodReducedCosts(int value) { + minimumGoodReducedCosts_ = value; + } + /// Current start of search space in matrix (as fraction) + inline double startFraction() const { + return startFraction_; + } + inline void setStartFraction(double value) { + startFraction_ = value; + } + /// Current end of search space in matrix (as fraction) + inline double endFraction() const { + return endFraction_; + } + inline void setEndFraction(double value) { + endFraction_ = value; + } + /// Current best reduced cost + inline double savedBestDj() const { + return savedBestDj_; + } + inline void setSavedBestDj(double value) { + savedBestDj_ = value; + } + /// Initial number of negative reduced costs wanted + inline int originalWanted() const { + return originalWanted_; + } + inline void setOriginalWanted(int value) { + originalWanted_ = value; + } + /// Current number of negative reduced costs which we still need + inline int currentWanted() const { + return currentWanted_; + } + inline void setCurrentWanted(int value) { + currentWanted_ = value; + } + /// Current best sequence + inline int savedBestSequence() const { + return savedBestSequence_; + } + inline void setSavedBestSequence(int value) { + savedBestSequence_ = value; + } + //@} + + +protected: + + /**@name Constructors, destructor<br> + <strong>NOTE</strong>: All constructors are protected. There's no need + to expose them, after all, this is an abstract class. */ + //@{ + /** Default constructor. */ + ClpMatrixBase(); + /** Destructor (has to be public) */ +public: + virtual ~ClpMatrixBase(); +protected: + // Copy + ClpMatrixBase(const ClpMatrixBase&); + // Assignment + ClpMatrixBase& operator=(const ClpMatrixBase&); + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /** Effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive */ + double * rhsOffset_; + /// Current start of search space in matrix (as fraction) + double startFraction_; + /// Current end of search space in matrix (as fraction) + double endFraction_; + /// Best reduced cost so far + double savedBestDj_; + /// Initial number of negative reduced costs wanted + int originalWanted_; + /// Current number of negative reduced costs which we still need + int currentWanted_; + /// Saved best sequence in pricing + int savedBestSequence_; + /// type (may be useful) + int type_; + /// If rhsOffset used this is iteration last refreshed + int lastRefresh_; + /// If rhsOffset used this is refresh frequency (0==off) + int refreshFrequency_; + /// Partial pricing tuning parameter - minimum number of "objects" to scan + int minimumObjectsScan_; + /// Partial pricing tuning parameter - minimum number of negative reduced costs to get + int minimumGoodReducedCosts_; + /// True sequence in (i.e. from larger problem) + int trueSequenceIn_; + /// True sequence out (i.e. from larger problem) + int trueSequenceOut_; + /// whether to skip dual checks most of time + bool skipDualCheck_; + //@} +}; +// bias for free variables +#define FREE_BIAS 1.0e1 +// Acceptance criteria for free variables +#define FREE_ACCEPT 1.0e2 + +#endif diff --git a/thirdparty/linux/include/coin/ClpMessage.hpp b/thirdparty/linux/include/coin/ClpMessage.hpp new file mode 100644 index 0000000..5eb3653 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpMessage.hpp @@ -0,0 +1,131 @@ +/* $Id: ClpMessage.hpp 1926 2013-03-26 15:23:38Z 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). + +#ifndef ClpMessage_H +#define ClpMessage_H + + +#include "CoinPragma.hpp" +#include <cstring> + +// This deals with Clp messages (as against Osi messages etc) + +#include "CoinMessageHandler.hpp" +enum CLP_Message { + CLP_SIMPLEX_FINISHED, + CLP_SIMPLEX_INFEASIBLE, + CLP_SIMPLEX_UNBOUNDED, + CLP_SIMPLEX_STOPPED, + CLP_SIMPLEX_ERROR, + CLP_SIMPLEX_INTERRUPT, + CLP_SIMPLEX_STATUS, + CLP_DUAL_BOUNDS, + CLP_SIMPLEX_ACCURACY, + CLP_SIMPLEX_BADFACTOR, + CLP_SIMPLEX_BOUNDTIGHTEN, + CLP_SIMPLEX_INFEASIBILITIES, + CLP_SIMPLEX_FLAG, + CLP_SIMPLEX_GIVINGUP, + CLP_DUAL_CHECKB, + CLP_DUAL_ORIGINAL, + CLP_SIMPLEX_PERTURB, + CLP_PRIMAL_ORIGINAL, + CLP_PRIMAL_WEIGHT, + CLP_PRIMAL_OPTIMAL, + CLP_SINGULARITIES, + CLP_MODIFIEDBOUNDS, + CLP_RIMSTATISTICS1, + CLP_RIMSTATISTICS2, + CLP_RIMSTATISTICS3, + CLP_POSSIBLELOOP, + CLP_SMALLELEMENTS, + CLP_DUPLICATEELEMENTS, + CLP_SIMPLEX_HOUSE1, + CLP_SIMPLEX_HOUSE2, + CLP_SIMPLEX_NONLINEAR, + CLP_SIMPLEX_FREEIN, + CLP_SIMPLEX_PIVOTROW, + CLP_DUAL_CHECK, + CLP_PRIMAL_DJ, + CLP_PACKEDSCALE_INITIAL, + CLP_PACKEDSCALE_WHILE, + CLP_PACKEDSCALE_FINAL, + CLP_PACKEDSCALE_FORGET, + CLP_INITIALIZE_STEEP, + CLP_UNABLE_OPEN, + CLP_BAD_BOUNDS, + CLP_BAD_MATRIX, + CLP_LOOP, + CLP_IMPORT_RESULT, + CLP_IMPORT_ERRORS, + CLP_EMPTY_PROBLEM, + CLP_CRASH, + CLP_END_VALUES_PASS, + CLP_QUADRATIC_BOTH, + CLP_QUADRATIC_PRIMAL_DETAILS, + CLP_IDIOT_ITERATION, + CLP_INFEASIBLE, + CLP_MATRIX_CHANGE, + CLP_TIMING, + CLP_INTERVAL_TIMING, + CLP_SPRINT, + CLP_BARRIER_ITERATION, + CLP_BARRIER_OBJECTIVE_GAP, + CLP_BARRIER_GONE_INFEASIBLE, + CLP_BARRIER_CLOSE_TO_OPTIMAL, + CLP_BARRIER_COMPLEMENTARITY, + CLP_BARRIER_EXIT2, + CLP_BARRIER_STOPPING, + CLP_BARRIER_EXIT, + CLP_BARRIER_SCALING, + CLP_BARRIER_MU, + CLP_BARRIER_INFO, + CLP_BARRIER_END, + CLP_BARRIER_ACCURACY, + CLP_BARRIER_SAFE, + CLP_BARRIER_NEGATIVE_GAPS, + CLP_BARRIER_REDUCING, + CLP_BARRIER_DIAGONAL, + CLP_BARRIER_SLACKS, + CLP_BARRIER_DUALINF, + CLP_BARRIER_KILLED, + CLP_BARRIER_ABS_DROPPED, + CLP_BARRIER_ABS_ERROR, + CLP_BARRIER_FEASIBLE, + CLP_BARRIER_STEP, + CLP_BARRIER_KKT, + CLP_RIM_SCALE, + CLP_SLP_ITER, + CLP_COMPLICATED_MODEL, + CLP_BAD_STRING_VALUES, + CLP_CRUNCH_STATS, + CLP_PARAMETRICS_STATS, + CLP_PARAMETRICS_STATS2, +#ifndef NO_FATHOM_PRINT + CLP_FATHOM_STATUS, + CLP_FATHOM_SOLUTION, + CLP_FATHOM_FINISH, +#endif + CLP_GENERAL, + CLP_GENERAL2, + CLP_GENERAL_WARNING, + CLP_DUMMY_END +}; + +/** This deals with Clp messages (as against Osi messages etc) + */ +class ClpMessage : public CoinMessages { + +public: + + /**@name Constructors etc */ + //@{ + /** Constructor */ + ClpMessage(Language language = us_en); + //@} + +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpModel.hpp b/thirdparty/linux/include/coin/ClpModel.hpp new file mode 100644 index 0000000..4a22539 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpModel.hpp @@ -0,0 +1,1307 @@ +/* $Id: ClpModel.hpp 2074 2014-12-10 09:43:54Z 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). + +#ifndef ClpModel_H +#define ClpModel_H + +#include "ClpConfig.h" + +#include <iostream> +#include <cassert> +#include <cmath> +#include <vector> +#include <string> +//#ifndef COIN_USE_CLP +//#define COIN_USE_CLP +//#endif +#include "ClpPackedMatrix.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinTypes.hpp" +#include "CoinFinite.hpp" +#include "ClpParameters.hpp" +#include "ClpObjective.hpp" +class ClpEventHandler; +/** This is the base class for Linear and quadratic Models + This knows nothing about the algorithm, but it seems to + have a reasonable amount of information + + I would welcome suggestions for what should be in this and + how it relates to OsiSolverInterface. Some methods look + very similar. + +*/ +class CoinBuild; +class CoinModel; +class ClpModel { + +public: + + /**@name Constructors and destructor + Note - copy methods copy ALL data so can chew up memory + until other copy is freed + */ + //@{ + /// Default constructor + ClpModel (bool emptyMessages = false ); + + /** Copy constructor. May scale depending on mode + -1 leave mode as is + 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 auto-but-as-initialSolve-in-bab + */ + ClpModel(const ClpModel & rhs, int scalingMode = -1); + /// Assignment operator. This copies the data + ClpModel & operator=(const ClpModel & rhs); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + */ + ClpModel (const ClpModel * wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns, + bool dropNames = true, bool dropIntegers = true); + /// Destructor + ~ClpModel ( ); + //@} + + /**@name Load model - loads some stuff and initializes others */ + //@{ + /** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + */ + void loadProblem ( const ClpMatrixBase& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + void loadProblem ( const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + + /** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ + void loadProblem ( const int numcols, const int numrows, + const CoinBigIndex* start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + /** This loads a model from a coinModel object - returns number of errors. + + modelObject not const as may be changed as part of process + If tryPlusMinusOne then will try adding as +-1 matrix + */ + int loadProblem ( CoinModel & modelObject, bool tryPlusMinusOne = false); + /// This one is for after presolve to save memory + void loadProblem ( const int numcols, const int numrows, + const CoinBigIndex* start, const int* index, + const double* value, const int * length, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + /** Load up quadratic objective. This is stored as a CoinPackedMatrix */ + void loadQuadraticObjective(const int numberColumns, + const CoinBigIndex * start, + const int * column, const double * element); + void loadQuadraticObjective ( const CoinPackedMatrix& matrix); + /// Get rid of quadratic objective + void deleteQuadraticObjective(); + /// This just loads up a row objective + void setRowObjective(const double * rowObjective); + /// Read an mps file from the given filename + int readMps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + /// Read GMPL files from the given filenames + int readGMPL(const char *filename, const char * dataName, + bool keepNames = false); + /// Copy in integer informations + void copyInIntegerInformation(const char * information); + /// Drop integer informations + void deleteIntegerInformation(); + /** Set the index-th variable to be a continuous variable */ + void setContinuous(int index); + /** Set the index-th variable to be an integer variable */ + void setInteger(int index); + /** Return true if the index-th variable is an integer variable */ + bool isInteger(int index) const; + /// Resizes rim part of model + void resize (int newNumberRows, int newNumberColumns); + /// Deletes rows + void deleteRows(int number, const int * which); + /// Add one row + void addRow(int numberInRow, const int * columns, + const double * elements, double rowLower = -COIN_DBL_MAX, + double rowUpper = COIN_DBL_MAX); + /// Add rows + void addRows(int number, const double * rowLower, + const double * rowUpper, + const CoinBigIndex * rowStarts, const int * columns, + const double * elements); + /// Add rows + void addRows(int number, const double * rowLower, + const double * rowUpper, + const CoinBigIndex * rowStarts, const int * rowLengths, + const int * columns, + const double * elements); +#ifndef CLP_NO_VECTOR + void addRows(int number, const double * rowLower, + const double * rowUpper, + const CoinPackedVectorBase * const * rows); +#endif + /** Add rows from a build object. + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + Returns number of errors e.g. duplicates + */ + int addRows(const CoinBuild & buildObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + /** Add rows from a model object. returns + -1 if object in bad state (i.e. has column information) + otherwise number of errors. + + modelObject non const as can be regularized as part of build + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + */ + int addRows(CoinModel & modelObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + + /// Deletes columns + void deleteColumns(int number, const int * which); + /// Deletes rows AND columns (keeps old sizes) + void deleteRowsAndColumns(int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + /// Add one column + void addColumn(int numberInColumn, + const int * rows, + const double * elements, + double columnLower = 0.0, + double columnUpper = COIN_DBL_MAX, + double objective = 0.0); + /// Add columns + void addColumns(int number, const double * columnLower, + const double * columnUpper, + const double * objective, + const CoinBigIndex * columnStarts, const int * rows, + const double * elements); + void addColumns(int number, const double * columnLower, + const double * columnUpper, + const double * objective, + const CoinBigIndex * columnStarts, const int * columnLengths, + const int * rows, + const double * elements); +#ifndef CLP_NO_VECTOR + void addColumns(int number, const double * columnLower, + const double * columnUpper, + const double * objective, + const CoinPackedVectorBase * const * columns); +#endif + /** Add columns from a build object + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + Returns number of errors e.g. duplicates + */ + int addColumns(const CoinBuild & buildObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + /** Add columns from a model object. returns + -1 if object in bad state (i.e. has row information) + otherwise number of errors + modelObject non const as can be regularized as part of build + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + */ + int addColumns(CoinModel & modelObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + /// Modify one element of a matrix + inline void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false) { + matrix_->modifyCoefficient(row, column, newElement, keepZero); + } + /** Change row lower bounds */ + void chgRowLower(const double * rowLower); + /** Change row upper bounds */ + void chgRowUpper(const double * rowUpper); + /** Change column lower bounds */ + void chgColumnLower(const double * columnLower); + /** Change column upper bounds */ + void chgColumnUpper(const double * columnUpper); + /** Change objective coefficients */ + void chgObjCoefficients(const double * objIn); + /** Borrow model. This is so we don't have to copy large amounts + of data around. It assumes a derived class wants to overwrite + an empty model with a real one - while it does an algorithm */ + void borrowModel(ClpModel & otherModel); + /** Return model - nulls all arrays so can be deleted safely + also updates any scalars */ + void returnModel(ClpModel & otherModel); + + /// Create empty ClpPackedMatrix + void createEmptyMatrix(); + /** Really clean up matrix (if ClpPackedMatrix). + a) eliminate all duplicate AND small elements in matrix + b) remove all gaps and set extraGap_ and extraMajor_ to 0.0 + c) reallocate arrays and make max lengths equal to lengths + d) orders elements + returns number of elements eliminated or -1 if not ClpPackedMatrix + */ + int cleanMatrix(double threshold = 1.0e-20); + /// Copy contents - resizing if necessary - otherwise re-use memory + void copy(const ClpMatrixBase * from, ClpMatrixBase * & to); +#ifndef CLP_NO_STD + /// Drops names - makes lengthnames 0 and names empty + void dropNames(); + /// Copies in names + void copyNames(const std::vector<std::string> & rowNames, + const std::vector<std::string> & columnNames); + /// Copies in Row names - modifies names first .. last-1 + void copyRowNames(const std::vector<std::string> & rowNames, int first, int last); + /// Copies in Column names - modifies names first .. last-1 + void copyColumnNames(const std::vector<std::string> & columnNames, int first, int last); + /// Copies in Row names - modifies names first .. last-1 + void copyRowNames(const char * const * rowNames, int first, int last); + /// Copies in Column names - modifies names first .. last-1 + void copyColumnNames(const char * const * columnNames, int first, int last); + /// Set name of row + void setRowName(int rowIndex, std::string & name) ; + /// Set name of col + void setColumnName(int colIndex, std::string & name) ; +#endif + /** Find a network subset. + rotate array should be numberRows. On output + -1 not in network + 0 in network as is + 1 in network with signs swapped + Returns number of network rows + */ + int findNetwork(char * rotate, double fractionNeeded = 0.75); + /** This creates a coinModel object + */ + CoinModel * createCoinModel() const; + + /** Write the problem in MPS format to the specified file. + + Row and column names may be null. + formatType is + <ul> + <li> 0 - normal + <li> 1 - extra accuracy + <li> 2 - IEEE hex + </ul> + + Returns non-zero on I/O error + */ + int writeMps(const char *filename, + int formatType = 0, int numberAcross = 2, + double objSense = 0.0) const ; + //@} + /**@name gets and sets */ + //@{ + /// Number of rows + inline int numberRows() const { + return numberRows_; + } + inline int getNumRows() const { + return numberRows_; + } + /// Number of columns + inline int getNumCols() const { + return numberColumns_; + } + inline int numberColumns() const { + return numberColumns_; + } + /// Primal tolerance to use + inline double primalTolerance() const { + return dblParam_[ClpPrimalTolerance]; + } + void setPrimalTolerance( double value) ; + /// Dual tolerance to use + inline double dualTolerance() const { + return dblParam_[ClpDualTolerance]; + } + void setDualTolerance( double value) ; + /// Primal objective limit + inline double primalObjectiveLimit() const { + return dblParam_[ClpPrimalObjectiveLimit]; + } + void setPrimalObjectiveLimit(double value); + /// Dual objective limit + inline double dualObjectiveLimit() const { + return dblParam_[ClpDualObjectiveLimit]; + } + void setDualObjectiveLimit(double value); + /// Objective offset + inline double objectiveOffset() const { + return dblParam_[ClpObjOffset]; + } + void setObjectiveOffset(double value); + /// Presolve tolerance to use + inline double presolveTolerance() const { + return dblParam_[ClpPresolveTolerance]; + } +#ifndef CLP_NO_STD + inline const std::string & problemName() const { + return strParam_[ClpProbName]; + } +#endif + /// Number of iterations + inline int numberIterations() const { + return numberIterations_; + } + inline int getIterationCount() const { + return numberIterations_; + } + inline void setNumberIterations(int numberIterationsNew) { + numberIterations_ = numberIterationsNew; + } + /** Solve type - 1 simplex, 2 simplex interface, 3 Interior.*/ + inline int solveType() const { + return solveType_; + } + inline void setSolveType(int type) { + solveType_ = type; + } + /// Maximum number of iterations + inline int maximumIterations() const { + return intParam_[ClpMaxNumIteration]; + } + void setMaximumIterations(int value); + /// Maximum time in seconds (from when set called) + inline double maximumSeconds() const { + return dblParam_[ClpMaxSeconds]; + } + void setMaximumSeconds(double value); + void setMaximumWallSeconds(double value); + /// Returns true if hit maximum iterations (or time) + bool hitMaximumIterations() const; + /** Status of problem: + -1 - unknown e.g. before solve or if postSolve says not optimal + 0 - optimal + 1 - primal infeasible + 2 - dual infeasible + 3 - stopped on iterations or time + 4 - stopped due to errors + 5 - stopped by event handler (virtual int ClpEventHandler::event()) + */ + inline int status() const { + return problemStatus_; + } + inline int problemStatus() const { + return problemStatus_; + } + /// Set problem status + inline void setProblemStatus(int problemStatusNew) { + problemStatus_ = problemStatusNew; + } + /** Secondary status of problem - may get extended + 0 - none + 1 - primal infeasible because dual limit reached OR (probably primal + infeasible but can't prove it - main status was 4) + 2 - scaled problem optimal - unscaled problem has primal infeasibilities + 3 - scaled problem optimal - unscaled problem has dual infeasibilities + 4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities + 5 - giving up in primal with flagged variables + 6 - failed due to empty problem check + 7 - postSolve says not optimal + 8 - failed due to bad element check + 9 - status was 3 and stopped on time + 10 - status was 3 but stopped as primal feasible + 100 up - translation of enum from ClpEventHandler + */ + inline int secondaryStatus() const { + return secondaryStatus_; + } + inline void setSecondaryStatus(int newstatus) { + secondaryStatus_ = newstatus; + } + /// Are there a numerical difficulties? + inline bool isAbandoned() const { + return problemStatus_ == 4; + } + /// Is optimality proven? + inline bool isProvenOptimal() const { + return problemStatus_ == 0; + } + /// Is primal infeasiblity proven? + inline bool isProvenPrimalInfeasible() const { + return problemStatus_ == 1; + } + /// Is dual infeasiblity proven? + inline bool isProvenDualInfeasible() const { + return problemStatus_ == 2; + } + /// Is the given primal objective limit reached? + bool isPrimalObjectiveLimitReached() const ; + /// Is the given dual objective limit reached? + bool isDualObjectiveLimitReached() const ; + /// Iteration limit reached? + inline bool isIterationLimitReached() const { + return problemStatus_ == 3; + } + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const { + return optimizationDirection_; + } + inline double getObjSense() const { + return optimizationDirection_; + } + void setOptimizationDirection(double value); + /// Primal row solution + inline double * primalRowSolution() const { + return rowActivity_; + } + inline const double * getRowActivity() const { + return rowActivity_; + } + /// Primal column solution + inline double * primalColumnSolution() const { + return columnActivity_; + } + inline const double * getColSolution() const { + return columnActivity_; + } + inline void setColSolution(const double * input) { + memcpy(columnActivity_, input, numberColumns_ * sizeof(double)); + } + /// Dual row solution + inline double * dualRowSolution() const { + return dual_; + } + inline const double * getRowPrice() const { + return dual_; + } + /// Reduced costs + inline double * dualColumnSolution() const { + return reducedCost_; + } + inline const double * getReducedCost() const { + return reducedCost_; + } + /// Row lower + inline double* rowLower() const { + return rowLower_; + } + inline const double* getRowLower() const { + return rowLower_; + } + /// Row upper + inline double* rowUpper() const { + return rowUpper_; + } + inline const double* getRowUpper() const { + return rowUpper_; + } + //------------------------------------------------------------------------- + /**@name Changing bounds on variables and constraints */ + //@{ + /** Set an objective function coefficient */ + void setObjectiveCoefficient( int elementIndex, double elementValue ); + /** Set an objective function coefficient */ + inline void setObjCoeff( int elementIndex, double elementValue ) { + setObjectiveCoefficient( elementIndex, elementValue); + } + + /** Set a single column lower bound<br> + Use -DBL_MAX for -infinity. */ + void setColumnLower( int elementIndex, double elementValue ); + + /** Set a single column upper bound<br> + Use DBL_MAX for infinity. */ + void setColumnUpper( int elementIndex, double elementValue ); + + /** Set a single column lower and upper bound */ + void setColumnBounds( int elementIndex, + double lower, double upper ); + + /** Set the bounds on a number of columns simultaneously<br> + The default implementation just invokes setColLower() and + setColUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + void setColumnSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + + /** Set a single column lower bound<br> + Use -DBL_MAX for -infinity. */ + inline void setColLower( int elementIndex, double elementValue ) { + setColumnLower(elementIndex, elementValue); + } + /** Set a single column upper bound<br> + Use DBL_MAX for infinity. */ + inline void setColUpper( int elementIndex, double elementValue ) { + setColumnUpper(elementIndex, elementValue); + } + + /** Set a single column lower and upper bound */ + inline void setColBounds( int elementIndex, + double lower, double upper ) { + setColumnBounds(elementIndex, lower, upper); + } + + /** Set the bounds on a number of columns simultaneously<br> + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + inline void setColSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList) { + setColumnSetBounds(indexFirst, indexLast, boundList); + } + + /** Set a single row lower bound<br> + Use -DBL_MAX for -infinity. */ + void setRowLower( int elementIndex, double elementValue ); + + /** Set a single row upper bound<br> + Use DBL_MAX for infinity. */ + void setRowUpper( int elementIndex, double elementValue ) ; + + /** Set a single row lower and upper bound */ + void setRowBounds( int elementIndex, + double lower, double upper ) ; + + /** Set the bounds on a number of rows simultaneously<br> + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the constraints + */ + void setRowSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + + //@} + /// Scaling + inline const double * rowScale() const { + return rowScale_; + } + inline const double * columnScale() const { + return columnScale_; + } + inline const double * inverseRowScale() const { + return inverseRowScale_; + } + inline const double * inverseColumnScale() const { + return inverseColumnScale_; + } + inline double * mutableRowScale() const { + return rowScale_; + } + inline double * mutableColumnScale() const { + return columnScale_; + } + inline double * mutableInverseRowScale() const { + return inverseRowScale_; + } + inline double * mutableInverseColumnScale() const { + return inverseColumnScale_; + } + inline double * swapRowScale(double * newScale) { + double * oldScale = rowScale_; + rowScale_ = newScale; + return oldScale; + } + void setRowScale(double * scale) ; + void setColumnScale(double * scale); + /// Scaling of objective + inline double objectiveScale() const { + return objectiveScale_; + } + inline void setObjectiveScale(double value) { + objectiveScale_ = value; + } + /// Scaling of rhs and bounds + inline double rhsScale() const { + return rhsScale_; + } + inline void setRhsScale(double value) { + rhsScale_ = value; + } + /// Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3 auto, 4 auto-but-as-initialSolve-in-bab + void scaling(int mode = 1); + /** If we constructed a "really" scaled model then this reverses the operation. + Quantities may not be exactly as they were before due to rounding errors */ + void unscale(); + /// Gets scalingFlag + inline int scalingFlag() const { + return scalingFlag_; + } + /// Objective + inline double * objective() const { + if (objective_) { + double offset; + return objective_->gradient(NULL, NULL, offset, false); + } else { + return NULL; + } + } + inline double * objective(const double * solution, double & offset, bool refresh = true) const { + offset = 0.0; + if (objective_) { + return objective_->gradient(NULL, solution, offset, refresh); + } else { + return NULL; + } + } + inline const double * getObjCoefficients() const { + if (objective_) { + double offset; + return objective_->gradient(NULL, NULL, offset, false); + } else { + return NULL; + } + } + /// Row Objective + inline double * rowObjective() const { + return rowObjective_; + } + inline const double * getRowObjCoefficients() const { + return rowObjective_; + } + /// Column Lower + inline double * columnLower() const { + return columnLower_; + } + inline const double * getColLower() const { + return columnLower_; + } + /// Column Upper + inline double * columnUpper() const { + return columnUpper_; + } + inline const double * getColUpper() const { + return columnUpper_; + } + /// Matrix (if not ClpPackedmatrix be careful about memory leak + inline CoinPackedMatrix * matrix() const { + if ( matrix_ == NULL ) return NULL; + else return matrix_->getPackedMatrix(); + } + /// Number of elements in matrix + inline int getNumElements() const { + return matrix_->getNumElements(); + } + /** Small element value - elements less than this set to zero, + default is 1.0e-20 */ + inline double getSmallElementValue() const { + return smallElement_; + } + inline void setSmallElementValue(double value) { + smallElement_ = value; + } + /// Row Matrix + inline ClpMatrixBase * rowCopy() const { + return rowCopy_; + } + /// Set new row matrix + void setNewRowCopy(ClpMatrixBase * newCopy); + /// Clp Matrix + inline ClpMatrixBase * clpMatrix() const { + return matrix_; + } + /// Scaled ClpPackedMatrix + inline ClpPackedMatrix * clpScaledMatrix() const { + return scaledMatrix_; + } + /// Sets pointer to scaled ClpPackedMatrix + inline void setClpScaledMatrix(ClpPackedMatrix * scaledMatrix) { + delete scaledMatrix_; + scaledMatrix_ = scaledMatrix; + } + /// Swaps pointer to scaled ClpPackedMatrix + inline ClpPackedMatrix * swapScaledMatrix(ClpPackedMatrix * scaledMatrix) { + ClpPackedMatrix * oldMatrix = scaledMatrix_; + scaledMatrix_ = scaledMatrix; + return oldMatrix; + } + /** Replace Clp Matrix (current is not deleted unless told to + and new is used) + So up to user to delete current. This was used where + matrices were being rotated. ClpModel takes ownership. + */ + void replaceMatrix(ClpMatrixBase * matrix, bool deleteCurrent = false); + /** Replace Clp Matrix (current is not deleted unless told to + and new is used) So up to user to delete current. This was used where + matrices were being rotated. This version changes CoinPackedMatrix + to ClpPackedMatrix. ClpModel takes ownership. + */ + inline void replaceMatrix(CoinPackedMatrix * newmatrix, + bool deleteCurrent = false) { + replaceMatrix(new ClpPackedMatrix(newmatrix), deleteCurrent); + } + /// Objective value + inline double objectiveValue() const { + return objectiveValue_ * optimizationDirection_ - dblParam_[ClpObjOffset]; + } + inline void setObjectiveValue(double value) { + objectiveValue_ = (value + dblParam_[ClpObjOffset]) / optimizationDirection_; + } + inline double getObjValue() const { + return objectiveValue_ * optimizationDirection_ - dblParam_[ClpObjOffset]; + } + /// Integer information + inline char * integerInformation() const { + return integerType_; + } + /** Infeasibility/unbounded ray (NULL returned if none/wrong) + Up to user to use delete [] on these arrays. */ + double * infeasibilityRay(bool fullRay=false) const; + double * unboundedRay() const; + /// For advanced users - no need to delete - sign not changed + inline double * ray() const + { return ray_;} + /// just test if infeasibility or unbounded Ray exists + inline bool rayExists() const { + return (ray_!=NULL); + } + /// just delete ray if exists + inline void deleteRay() { + delete [] ray_; + ray_=NULL; + } + /// Access internal ray storage. Users should call infeasibilityRay() or unboundedRay() instead. + inline const double * internalRay() const { + return ray_; + } + /// See if status (i.e. basis) array exists (partly for OsiClp) + inline bool statusExists() const { + return (status_ != NULL); + } + /// Return address of status (i.e. basis) array (char[numberRows+numberColumns]) + inline unsigned char * statusArray() const { + return status_; + } + /** Return copy of status (i.e. basis) array (char[numberRows+numberColumns]), + use delete [] */ + unsigned char * statusCopy() const; + /// Copy in status (basis) vector + void copyinStatus(const unsigned char * statusArray); + + /// User pointer for whatever reason + inline void setUserPointer (void * pointer) { + userPointer_ = pointer; + } + inline void * getUserPointer () const { + return userPointer_; + } + /// Trusted user pointer + inline void setTrustedUserPointer (ClpTrustedData * pointer) { + trustedUserPointer_ = pointer; + } + inline ClpTrustedData * getTrustedUserPointer () const { + return trustedUserPointer_; + } + /// What has changed in model (only for masochistic users) + inline int whatsChanged() const { + return whatsChanged_; + } + inline void setWhatsChanged(int value) { + whatsChanged_ = value; + } + /// Number of threads (not really being used) + inline int numberThreads() const { + return numberThreads_; + } + inline void setNumberThreads(int value) { + numberThreads_ = value; + } + //@} + /**@name Message handling */ + //@{ + /// Pass in Message handler (not deleted at end) + void passInMessageHandler(CoinMessageHandler * handler); + /// Pass in Message handler (not deleted at end) and return current + CoinMessageHandler * pushMessageHandler(CoinMessageHandler * handler, + bool & oldDefault); + /// back to previous message handler + void popMessageHandler(CoinMessageHandler * oldHandler, bool oldDefault); + /// Set language + void newLanguage(CoinMessages::Language language); + inline void setLanguage(CoinMessages::Language language) { + newLanguage(language); + } + /// Overrides message handler with a default one + void setDefaultMessageHandler(); + /// Return handler + inline CoinMessageHandler * messageHandler() const { + return handler_; + } + /// Return messages + inline CoinMessages messages() const { + return messages_; + } + /// Return pointer to messages + inline CoinMessages * messagesPointer() { + return & messages_; + } + /// Return Coin messages + inline CoinMessages coinMessages() const { + return coinMessages_; + } + /// Return pointer to Coin messages + inline CoinMessages * coinMessagesPointer() { + return & coinMessages_; + } + /** Amount of print out: + 0 - none + 1 - just final + 2 - just factorizations + 3 - as 2 plus a bit more + 4 - verbose + above that 8,16,32 etc just for selective debug + */ + inline void setLogLevel(int value) { + handler_->setLogLevel(value); + } + inline int logLevel() const { + return handler_->logLevel(); + } + /// Return true if default handler + inline bool defaultHandler() const { + return defaultHandler_; + } + /// Pass in Event handler (cloned and deleted at end) + void passInEventHandler(const ClpEventHandler * eventHandler); + /// Event handler + inline ClpEventHandler * eventHandler() const { + return eventHandler_; + } + /// Thread specific random number generator + inline CoinThreadRandom * randomNumberGenerator() { + return &randomNumberGenerator_; + } + /// Thread specific random number generator + inline CoinThreadRandom & mutableRandomNumberGenerator() { + return randomNumberGenerator_; + } + /// Set seed for thread specific random number generator + inline void setRandomSeed(int value) { + randomNumberGenerator_.setSeed(value); + } + /// length of names (0 means no names0 + inline int lengthNames() const { + return lengthNames_; + } +#ifndef CLP_NO_STD + /// length of names (0 means no names0 + inline void setLengthNames(int value) { + lengthNames_ = value; + } + /// Row names + inline const std::vector<std::string> * rowNames() const { + return &rowNames_; + } + inline const std::string& rowName(int iRow) const { + return rowNames_[iRow]; + } + /// Return name or Rnnnnnnn + std::string getRowName(int iRow) const; + /// Column names + inline const std::vector<std::string> * columnNames() const { + return &columnNames_; + } + inline const std::string& columnName(int iColumn) const { + return columnNames_[iColumn]; + } + /// Return name or Cnnnnnnn + std::string getColumnName(int iColumn) const; +#endif + /// Objective methods + inline ClpObjective * objectiveAsObject() const { + return objective_; + } + void setObjective(ClpObjective * objective); + inline void setObjectivePointer(ClpObjective * newobjective) { + objective_ = newobjective; + } + /** Solve a problem with no elements - return status and + dual and primal infeasibilites */ + int emptyProblem(int * infeasNumber = NULL, double * infeasSum = NULL, bool printMessage = true); + + //@} + + /**@name Matrix times vector methods + They can be faster if scalar is +- 1 + These are covers so user need not worry about scaling + Also for simplex I am not using basic/non-basic split */ + //@{ + /** Return <code>y + A * x * scalar</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + void times(double scalar, + const double * x, double * y) const; + /** Return <code>y + x * scalar * A</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> */ + void transposeTimes(double scalar, + const double * x, double * y) const ; + //@} + + + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. There can be various reasons for failure: the given + parameter is not applicable for the solver (e.g., refactorization + frequency for the volume algorithm), the parameter is not yet implemented + for the solver or simply the value of the parameter is out of the range + the solver accepts. If a parameter setting call returns false check the + details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + + ** once it has been decided where solver sits this may be redone + */ + //@{ + /// Set an integer parameter + bool setIntParam(ClpIntParam key, int value) ; + /// Set an double parameter + bool setDblParam(ClpDblParam key, double value) ; +#ifndef CLP_NO_STD + /// Set an string parameter + bool setStrParam(ClpStrParam key, const std::string & value); +#endif + // Get an integer parameter + inline bool getIntParam(ClpIntParam key, int& value) const { + if (key < ClpLastIntParam) { + value = intParam_[key]; + return true; + } else { + return false; + } + } + // Get an double parameter + inline bool getDblParam(ClpDblParam key, double& value) const { + if (key < ClpLastDblParam) { + value = dblParam_[key]; + return true; + } else { + return false; + } + } +#ifndef CLP_NO_STD + // Get a string parameter + inline bool getStrParam(ClpStrParam key, std::string& value) const { + if (key < ClpLastStrParam) { + value = strParam_[key]; + return true; + } else { + return false; + } + } +#endif + /// Create C++ lines to get to current state + void generateCpp( FILE * fp); + /** For advanced options + 1 - Don't keep changing infeasibility weight + 2 - Keep nonLinearCost round solves + 4 - Force outgoing variables to exact bound (primal) + 8 - Safe to use dense initial factorization + 16 -Just use basic variables for operation if column generation + 32 -Create ray even in BAB + 64 -Treat problem as feasible until last minute (i.e. minimize infeasibilities) + 128 - Switch off all matrix sanity checks + 256 - No row copy + 512 - If not in values pass, solution guaranteed, skip as much as possible + 1024 - In branch and bound + 2048 - Don't bother to re-factorize if < 20 iterations + 4096 - Skip some optimality checks + 8192 - Do Primal when cleaning up primal + 16384 - In fast dual (so we can switch off things) + 32768 - called from Osi + 65536 - keep arrays around as much as possible (also use maximumR/C) + 131072 - transposeTimes is -1.0 and can skip basic and fixed + 262144 - extra copy of scaled matrix + 524288 - Clp fast dual + 1048576 - don't need to finish dual (can return 3) + 2097152 - zero costs! + 4194304 - don't scale integer variables + 8388608 - Idiot when not really sure about it + NOTE - many applications can call Clp but there may be some short cuts + which are taken which are not guaranteed safe from all applications. + Vetted applications will have a bit set and the code may test this + At present I expect a few such applications - if too many I will + have to re-think. It is up to application owner to change the code + if she/he needs these short cuts. I will not debug unless in Coin + repository. See COIN_CLP_VETTED comments. + 0x01000000 is Cbc (and in branch and bound) + 0x02000000 is in a different branch and bound + */ + inline unsigned int specialOptions() const { + return specialOptions_; + } + void setSpecialOptions(unsigned int value); +#define COIN_CBC_USING_CLP 0x01000000 + inline bool inCbcBranchAndBound() const { + return (specialOptions_ & COIN_CBC_USING_CLP) != 0; + } + //@} + + /**@name private or protected methods */ + //@{ +protected: + /// Does most of deletion (0 = all, 1 = most) + void gutsOfDelete(int type); + /** Does most of copying + If trueCopy 0 then just points to arrays + If -1 leaves as much as possible */ + void gutsOfCopy(const ClpModel & rhs, int trueCopy = 1); + /// gets lower and upper bounds on rows + void getRowBound(int iRow, double& lower, double& upper) const; + /// puts in format I like - 4 array matrix - may make row copy + void gutsOfLoadModel ( int numberRows, int numberColumns, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + /// Does much of scaling + void gutsOfScaling(); + /// Objective value - always minimize + inline double rawObjectiveValue() const { + return objectiveValue_; + } + /// If we are using maximumRows_ and Columns_ + inline bool permanentArrays() const { + return (specialOptions_ & 65536) != 0; + } + /// Start using maximumRows_ and Columns_ + void startPermanentArrays(); + /// Stop using maximumRows_ and Columns_ + void stopPermanentArrays(); + /// Create row names as char ** + const char * const * rowNamesAsChar() const; + /// Create column names as char ** + const char * const * columnNamesAsChar() const; + /// Delete char * version of names + void deleteNamesAsChar(const char * const * names, int number) const; + /// On stopped - sets secondary status + void onStopped(); + //@} + + +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + double optimizationDirection_; + /// Array of double parameters + double dblParam_[ClpLastDblParam]; + /// Objective value + double objectiveValue_; + /// Small element value + double smallElement_; + /// Scaling of objective + double objectiveScale_; + /// Scaling of rhs and bounds + double rhsScale_; + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; + /// Row activities + double * rowActivity_; + /// Column activities + double * columnActivity_; + /// Duals + double * dual_; + /// Reduced costs + double * reducedCost_; + /// Row lower + double* rowLower_; + /// Row upper + double* rowUpper_; + /// Objective + ClpObjective * objective_; + /// Row Objective (? sign) - may be NULL + double * rowObjective_; + /// Column Lower + double * columnLower_; + /// Column Upper + double * columnUpper_; + /// Packed matrix + ClpMatrixBase * matrix_; + /// Row copy if wanted + ClpMatrixBase * rowCopy_; + /// Scaled packed matrix + ClpPackedMatrix * scaledMatrix_; + /// Infeasible/unbounded ray + double * ray_; + /// Row scale factors for matrix + double * rowScale_; + /// Column scale factors + double * columnScale_; + /// Inverse row scale factors for matrix (end of rowScale_) + double * inverseRowScale_; + /// Inverse column scale factors for matrix (end of columnScale_) + double * inverseColumnScale_; + /** Scale flag, 0 none, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic, + 5 geometric on rows */ + int scalingFlag_; + /** Status (i.e. basis) Region. I know that not all algorithms need a status + array, but it made sense for things like crossover and put + all permanent stuff in one place. No assumption is made + about what is in status array (although it might be good to reserve + bottom 3 bits (i.e. 0-7 numeric) for classic status). This + is number of columns + number of rows long (in that order). + */ + unsigned char * status_; + /// Integer information + char * integerType_; + /// User pointer for whatever reason + void * userPointer_; + /// Trusted user pointer e.g. for heuristics + ClpTrustedData * trustedUserPointer_; + /// Array of integer parameters + int intParam_[ClpLastIntParam]; + /// Number of iterations + int numberIterations_; + /** Solve type - 1 simplex, 2 simplex interface, 3 Interior.*/ + int solveType_; + /** Whats changed since last solve. This is a work in progress + It is designed so careful people can make go faster. + It is only used when startFinishOptions used in dual or primal. + Bit 1 - number of rows/columns has not changed (so work arrays valid) + 2 - matrix has not changed + 4 - if matrix has changed only by adding rows + 8 - if matrix has changed only by adding columns + 16 - row lbs not changed + 32 - row ubs not changed + 64 - column objective not changed + 128 - column lbs not changed + 256 - column ubs not changed + 512 - basis not changed (up to user to set this to 0) + top bits may be used internally + shift by 65336 is 3 all same, 1 all except col bounds + */ +#define ROW_COLUMN_COUNTS_SAME 1 +#define MATRIX_SAME 2 +#define MATRIX_JUST_ROWS_ADDED 4 +#define MATRIX_JUST_COLUMNS_ADDED 8 +#define ROW_LOWER_SAME 16 +#define ROW_UPPER_SAME 32 +#define OBJECTIVE_SAME 64 +#define COLUMN_LOWER_SAME 128 +#define COLUMN_UPPER_SAME 256 +#define BASIS_SAME 512 +#define ALL_SAME 65339 +#define ALL_SAME_EXCEPT_COLUMN_BOUNDS 65337 + unsigned int whatsChanged_; + /// Status of problem + int problemStatus_; + /// Secondary status of problem + int secondaryStatus_; + /// length of names (0 means no names) + int lengthNames_; + /// Number of threads (not very operational) + int numberThreads_; + /** For advanced options + See get and set for meaning + */ + unsigned int specialOptions_; + /// Message handler + CoinMessageHandler * handler_; + /// Flag to say if default handler (so delete) + bool defaultHandler_; + /// Thread specific random number generator + CoinThreadRandom randomNumberGenerator_; + /// Event handler + ClpEventHandler * eventHandler_; +#ifndef CLP_NO_STD + /// Row names + std::vector<std::string> rowNames_; + /// Column names + std::vector<std::string> columnNames_; +#endif + /// Messages + CoinMessages messages_; + /// Coin messages + CoinMessages coinMessages_; + /// Maximum number of columns in model + int maximumColumns_; + /// Maximum number of rows in model + int maximumRows_; + /// Maximum number of columns (internal arrays) in model + int maximumInternalColumns_; + /// Maximum number of rows (internal arrays) in model + int maximumInternalRows_; + /// Base packed matrix + CoinPackedMatrix baseMatrix_; + /// Base row copy + CoinPackedMatrix baseRowCopy_; + /// Saved row scale factors for matrix + double * savedRowScale_; + /// Saved column scale factors + double * savedColumnScale_; +#ifndef CLP_NO_STD + /// Array of string parameters + std::string strParam_[ClpLastStrParam]; +#endif + //@} +}; +/** This is a tiny class where data can be saved round calls. + */ +class ClpDataSave { + +public: + /**@name Constructors and destructor + */ + //@{ + /// Default constructor + ClpDataSave ( ); + + /// Copy constructor. + ClpDataSave(const ClpDataSave &); + /// Assignment operator. This copies the data + ClpDataSave & operator=(const ClpDataSave & rhs); + /// Destructor + ~ClpDataSave ( ); + + //@} + +////////////////// data ////////////////// +public: + + /**@name data - with same names as in other classes*/ + //@{ + double dualBound_; + double infeasibilityCost_; + double pivotTolerance_; + double zeroFactorizationTolerance_; + double zeroSimplexTolerance_; + double acceptablePivot_; + double objectiveScale_; + int sparseThreshold_; + int perturbation_; + int forceFactorization_; + int scalingFlag_; + unsigned int specialOptions_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpNetworkMatrix.hpp b/thirdparty/linux/include/coin/ClpNetworkMatrix.hpp new file mode 100644 index 0000000..ec650a4 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpNetworkMatrix.hpp @@ -0,0 +1,229 @@ +/* $Id: ClpNetworkMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpNetworkMatrix_H +#define ClpNetworkMatrix_H + + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" + +/** This implements a simple network matrix as derived from ClpMatrixBase. + +If you want more sophisticated version then you could inherit from this. +Also you might want to allow networks with gain */ + +class ClpNetworkMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix * getPackedMatrix() const; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const { + return true; + } + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const { + return 2 * numberColumns_; + } + /** Number of columns. */ + virtual int getNumCols() const { + return numberColumns_; + } + /** Number of rows. */ + virtual int getNumRows() const { + return numberRows_; + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double * getElements() const; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int * getIndices() const { + return indices_; + } + + virtual const CoinBigIndex * getVectorStarts() const; + /** The lengths of the major-dimension vectors. */ + virtual const int * getVectorLengths() const; + + /** Delete the columns whose indices are listed in <code>indDel</code>. */ + virtual void deleteCols(const int numDel, const int * indDel); + /** Delete the rows whose indices are listed in <code>indDel</code>. */ + virtual void deleteRows(const int numDel, const int * indDel); + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); +#ifndef SLIM_CLP + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex * starts, const int * index, + const double * element, int numberOther = -1); +#endif + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase * reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual CoinBigIndex countBasis( + const int * whichColumn, + int & numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex * model, + const int * whichColumn, + int & numberColumnBasic, + int * row, int * start, + int * rowCount, int * columnCount, + CoinFactorizationDouble * element); + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + */ + virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + */ + virtual void rangeOfElements(double & smallestNegative, double & largestNegative, + double & smallestPositive, double & largestPositive); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column) const ; + /** Unpacks a column into an CoinIndexedvector + ** in packed format + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex * model, + CoinIndexedVector * rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column, double multiplier) const ; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex * model, double * array, + int column, double multiplier) const; + /// Allow any parts of a created CoinMatrix to be deleted + virtual void releasePackedMatrix() const ; + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return <code>y + A * scalar *x</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + virtual void times(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void times(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale) const; + /** Return <code>y + x * scalar * A</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> */ + virtual void transposeTimes(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale, double * spare = NULL) const; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x *A</code> in <code>z</code> but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex * model, + const CoinIndexedVector * x, + const CoinIndexedVector * y, + CoinIndexedVector * z) const; + //@} + + /**@name Other */ + //@{ + /// Return true if really network, false if has slacks + inline bool trueNetwork() const { + return trueNetwork_; + } + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpNetworkMatrix(); + /** Constructor from two arrays */ + ClpNetworkMatrix(int numberColumns, const int * head, + const int * tail); + /** Destructor */ + virtual ~ClpNetworkMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpNetworkMatrix(const ClpNetworkMatrix&); + /** The copy constructor from an CoinNetworkMatrix. */ + ClpNetworkMatrix(const CoinPackedMatrix&); + + ClpNetworkMatrix& operator=(const ClpNetworkMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpNetworkMatrix (const ClpNetworkMatrix & wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase * subsetClone ( + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns) const ; + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// For fake CoinPackedMatrix + mutable CoinPackedMatrix * matrix_; + mutable int * lengths_; + /// Data -1, then +1 rows in pairs (row==-1 if one entry) + int * indices_; + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; + /// True if all entries have two elements + bool trueNetwork_; + + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpNode.hpp b/thirdparty/linux/include/coin/ClpNode.hpp new file mode 100644 index 0000000..671d62f --- /dev/null +++ b/thirdparty/linux/include/coin/ClpNode.hpp @@ -0,0 +1,349 @@ +/* $Id: ClpNode.hpp 1910 2013-01-27 02:00:13Z stefan $ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpNode_H +#define ClpNode_H + +#include "CoinPragma.hpp" + +// This implements all stuff for Clp fathom +/** This contains what is in a Clp "node" + + */ + +class ClpFactorization; +class ClpDualRowSteepest; +class ClpNodeStuff; +class ClpNode { + +public: + /**@name Useful methods */ + //@{ + /** Applies node to model + 0 - just tree bounds + 1 - tree bounds and basis etc + 2 - saved bounds and basis etc + */ + void applyNode(ClpSimplex * model, int doBoundsEtc ); + /// Choose a new variable + void chooseVariable(ClpSimplex * model, ClpNodeStuff * info); + /// Fix on reduced costs + int fixOnReducedCosts(ClpSimplex * model); + /// Create odd arrays + void createArrays(ClpSimplex * model); + /// Clean up as crunch is different model + void cleanUpForCrunch(); + //@} + + /**@name Gets and sets */ + //@{ + /// Objective value + inline double objectiveValue() const { + return objectiveValue_; + } + /// Set objective value + inline void setObjectiveValue(double value) { + objectiveValue_ = value; + } + /// Primal solution + inline const double * primalSolution() const { + return primalSolution_; + } + /// Dual solution + inline const double * dualSolution() const { + return dualSolution_; + } + /// Initial value of integer variable + inline double branchingValue() const { + return branchingValue_; + } + /// Sum infeasibilities + inline double sumInfeasibilities() const { + return sumInfeasibilities_; + } + /// Number infeasibilities + inline int numberInfeasibilities() const { + return numberInfeasibilities_; + } + /// Relative depth + inline int depth() const { + return depth_; + } + /// Estimated solution value + inline double estimatedSolution() const { + return estimatedSolution_; + } + /** Way for integer variable -1 down , +1 up */ + int way() const; + /// Return true if branch exhausted + bool fathomed() const; + /// Change state of variable i.e. go other way + void changeState(); + /// Sequence number of integer variable (-1 if none) + inline int sequence() const { + return sequence_; + } + /// If odd arrays exist + inline bool oddArraysExist() const { + return lower_ != NULL; + } + /// Status array + inline const unsigned char * statusArray() const { + return status_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpNode(); + /// Constructor from model + ClpNode (ClpSimplex * model, const ClpNodeStuff * stuff, int depth); + /// Does work of constructor (partly so gdb will work) + void gutsOfConstructor(ClpSimplex * model, const ClpNodeStuff * stuff, + int arraysExist, int depth); + /** Destructor */ + virtual ~ClpNode(); + //@} + + /**@name Copy methods (at present illegal - will abort) */ + //@{ + /** The copy constructor. */ + ClpNode(const ClpNode&); + /// Operator = + ClpNode& operator=(const ClpNode&); + //@} + +protected: +// For state of branch + typedef struct { + unsigned int firstBranch: 1; // nonzero if first branch on variable is up + unsigned int branch: 2; // 0 means do first branch next, 1 second, 2 finished + unsigned int spare: 29; + } branchState; + /**@name Data */ + //@{ + /// Initial value of integer variable + double branchingValue_; + /// Value of objective + double objectiveValue_; + /// Sum of infeasibilities + double sumInfeasibilities_; + /// Estimated solution value + double estimatedSolution_; + /// Factorization + ClpFactorization * factorization_; + /// Steepest edge weights + ClpDualRowSteepest * weights_; + /// Status vector + unsigned char * status_; + /// Primal solution + double * primalSolution_; + /// Dual solution + double * dualSolution_; + /// Integer lower bounds (only used in fathomMany) + int * lower_; + /// Integer upper bounds (only used in fathomMany) + int * upper_; + /// Pivot variables for factorization + int * pivotVariables_; + /// Variables fixed by reduced costs (at end of branch) 0x10000000 added if fixed to UB + int * fixed_; + /// State of branch + branchState branchState_; + /// Sequence number of integer variable (-1 if none) + int sequence_; + /// Number of infeasibilities + int numberInfeasibilities_; + /// Relative depth + int depth_; + /// Number fixed by reduced cost + int numberFixed_; + /// Flags - 1 duals scaled + int flags_; + /// Maximum number fixed by reduced cost + int maximumFixed_; + /// Maximum rows so far + int maximumRows_; + /// Maximum columns so far + int maximumColumns_; + /// Maximum Integers so far + int maximumIntegers_; + //@} +}; +class ClpNodeStuff { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpNodeStuff(); + /** Destructor */ + virtual ~ClpNodeStuff(); + //@} + + /**@name Copy methods (only copies ints etc, nulls arrays) */ + //@{ + /** The copy constructor. */ + ClpNodeStuff(const ClpNodeStuff&); + /// Operator = + ClpNodeStuff& operator=(const ClpNodeStuff&); + /// Zaps stuff 1 - arrays, 2 ints, 3 both + void zap(int type); + //@} + + + /**@name Fill methods */ + //@{ + /** Fill with pseudocosts */ + void fillPseudoCosts(const double * down, const double * up, + const int * priority, + const int * numberDown, const int * numberUp, + const int * numberDownInfeasible, const int * numberUpInfeasible, + int number); + /// Update pseudo costs + void update(int way, int sequence, double change, bool feasible); + /// Return maximum number of nodes + int maximumNodes() const; + /// Return maximum space for nodes + int maximumSpace() const; + //@} + +public: + /**@name Data */ + //@{ + /// Integer tolerance + double integerTolerance_; + /// Integer increment + double integerIncrement_; + /// Small change in branch + double smallChange_; + /// Down pseudo costs + double * downPseudo_; + /// Up pseudo costs + double * upPseudo_; + /// Priority + int * priority_; + /// Number of times down + int * numberDown_; + /// Number of times up + int * numberUp_; + /// Number of times down infeasible + int * numberDownInfeasible_; + /// Number of times up infeasible + int * numberUpInfeasible_; + /// Copy of costs (local) + double * saveCosts_; + /// Array of ClpNodes + ClpNode ** nodeInfo_; + /// Large model if crunched + ClpSimplex * large_; + /// Which rows in large model + int * whichRow_; + /// Which columns in large model + int * whichColumn_; +#ifndef NO_FATHOM_PRINT + /// Cbc's message handler + CoinMessageHandler * handler_; +#endif + /// Number bounds in large model + int nBound_; + /// Save of specialOptions_ (local) + int saveOptions_; + /** Options to pass to solver + 1 - create external reduced costs for columns + 2 - create external reduced costs for rows + 4 - create external row activity (columns always done) + Above only done if feasible + 32 - just create up to nDepth_+1 nodes + 65536 - set if activated + */ + int solverOptions_; + /// Maximum number of nodes to do + int maximumNodes_; + /// Number before trust from CbcModel + int numberBeforeTrust_; + /// State of search from CbcModel + int stateOfSearch_; + /// Number deep + int nDepth_; + /// Number nodes returned (-1 if fathom aborted) + int nNodes_; + /// Number of nodes explored + int numberNodesExplored_; + /// Number of iterations + int numberIterations_; + /// Type of presolve - 0 none, 1 crunch + int presolveType_; +#ifndef NO_FATHOM_PRINT + /// Depth passed in + int startingDepth_; + /// Node at which called + int nodeCalled_; +#endif + //@} +}; +class ClpHashValue { + +public: + /**@name Useful methods */ + //@{ + /// Return index or -1 if not found + int index(double value) const; + /// Add value to list and return index + int addValue(double value) ; + /// Number of different entries + inline int numberEntries() const { + return numberHash_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpHashValue(); + /** Useful constructor. */ + ClpHashValue(ClpSimplex * model); + /** Destructor */ + virtual ~ClpHashValue(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpHashValue(const ClpHashValue&); + /// = + ClpHashValue& operator=(const ClpHashValue&); + //@} +private: + /**@name private stuff */ + //@{ + /** returns hash */ + int hash(double value) const; + /// Resizes + void resize(bool increaseMax); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Data + // for hashing + typedef struct { + double value; + int index, next; + } CoinHashLink; + /// Hash table + mutable CoinHashLink *hash_; + /// Number of entries in hash table + int numberHash_; + /// Maximum number of entries in hash table i.e. size + int maxHash_; + /// Last used space + int lastUsed_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/ClpNonLinearCost.hpp b/thirdparty/linux/include/coin/ClpNonLinearCost.hpp new file mode 100644 index 0000000..1007865 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpNonLinearCost.hpp @@ -0,0 +1,401 @@ +/* $Id: ClpNonLinearCost.hpp 1769 2011-07-26 09:31:51Z 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). + +#ifndef ClpNonLinearCost_H +#define ClpNonLinearCost_H + + +#include "CoinPragma.hpp" + +class ClpSimplex; +class CoinIndexedVector; + +/** Trivial class to deal with non linear costs + + I don't make any explicit assumptions about convexity but I am + sure I do make implicit ones. + + One interesting idea for normal LP's will be to allow non-basic + variables to come into basis as infeasible i.e. if variable at + lower bound has very large positive reduced cost (when problem + is infeasible) could it reduce overall problem infeasibility more + by bringing it into basis below its lower bound. + + Another feature would be to automatically discover when problems + are convex piecewise linear and re-formulate to use non-linear. + I did some work on this many years ago on "grade" problems, but + while it improved primal interior point algorithms were much better + for that particular problem. +*/ +/* status has original status and current status + 0 - below lower so stored is upper + 1 - in range + 2 - above upper so stored is lower + 4 - (for current) - same as original +*/ +#define CLP_BELOW_LOWER 0 +#define CLP_FEASIBLE 1 +#define CLP_ABOVE_UPPER 2 +#define CLP_SAME 4 +inline int originalStatus(unsigned char status) +{ + return (status & 15); +} +inline int currentStatus(unsigned char status) +{ + return (status >> 4); +} +inline void setOriginalStatus(unsigned char & status, int value) +{ + status = static_cast<unsigned char>(status & ~15); + status = static_cast<unsigned char>(status | value); +} +inline void setCurrentStatus(unsigned char &status, int value) +{ + status = static_cast<unsigned char>(status & ~(15 << 4)); + status = static_cast<unsigned char>(status | (value << 4)); +} +inline void setInitialStatus(unsigned char &status) +{ + status = static_cast<unsigned char>(CLP_FEASIBLE | (CLP_SAME << 4)); +} +inline void setSameStatus(unsigned char &status) +{ + status = static_cast<unsigned char>(status & ~(15 << 4)); + status = static_cast<unsigned char>(status | (CLP_SAME << 4)); +} +// Use second version to get more speed +//#define FAST_CLPNON +#ifndef FAST_CLPNON +#define CLP_METHOD1 ((method_&1)!=0) +#define CLP_METHOD2 ((method_&2)!=0) +#else +#define CLP_METHOD1 (false) +#define CLP_METHOD2 (true) +#endif +class ClpNonLinearCost { + +public: + +public: + + /**@name Constructors, destructor */ + //@{ + /// Default constructor. + ClpNonLinearCost(); + /** Constructor from simplex. + This will just set up wasteful arrays for linear, but + later may do dual analysis and even finding duplicate columns . + */ + ClpNonLinearCost(ClpSimplex * model, int method = 1); + /** Constructor from simplex and list of non-linearities (columns only) + First lower of each column has to match real lower + Last lower has to be <= upper (if == then cost ignored) + This could obviously be changed to make more user friendly + */ + ClpNonLinearCost(ClpSimplex * model, const int * starts, + const double * lower, const double * cost); + /// Destructor + ~ClpNonLinearCost(); + // Copy + ClpNonLinearCost(const ClpNonLinearCost&); + // Assignment + ClpNonLinearCost& operator=(const ClpNonLinearCost&); + //@} + + + /**@name Actual work in primal */ + //@{ + /** Changes infeasible costs and computes number and cost of infeas + Puts all non-basic (non free) variables to bounds + and all free variables to zero if oldTolerance is non-zero + - but does not move those <= oldTolerance away*/ + void checkInfeasibilities(double oldTolerance = 0.0); + /** Changes infeasible costs for each variable + The indices are row indices and need converting to sequences + */ + void checkInfeasibilities(int numberInArray, const int * index); + /** Puts back correct infeasible costs for each variable + The input indices are row indices and need converting to sequences + for costs. + On input array is empty (but indices exist). On exit just + changed costs will be stored as normal CoinIndexedVector + */ + void checkChanged(int numberInArray, CoinIndexedVector * update); + /** Goes through one bound for each variable. + If multiplier*work[iRow]>0 goes down, otherwise up. + The indices are row indices and need converting to sequences + Temporary offsets may be set + Rhs entries are increased + */ + void goThru(int numberInArray, double multiplier, + const int * index, const double * work, + double * rhs); + /** Takes off last iteration (i.e. offsets closer to 0) + */ + void goBack(int numberInArray, const int * index, + double * rhs); + /** Puts back correct infeasible costs for each variable + The input indices are row indices and need converting to sequences + for costs. + At the end of this all temporary offsets are zero + */ + void goBackAll(const CoinIndexedVector * update); + /// Temporary zeroing of feasible costs + void zapCosts(); + /// Refreshes costs always makes row costs zero + void refreshCosts(const double * columnCosts); + /// Puts feasible bounds into lower and upper + void feasibleBounds(); + /// Refresh - assuming regions OK + void refresh(); + /** Sets bounds and cost for one variable + Returns change in cost + May need to be inline for speed */ + double setOne(int sequence, double solutionValue); + /** Sets bounds and infeasible cost and true cost for one variable + This is for gub and column generation etc */ + void setOne(int sequence, double solutionValue, double lowerValue, double upperValue, + double costValue = 0.0); + /** Sets bounds and cost for outgoing variable + may change value + Returns direction */ + int setOneOutgoing(int sequence, double &solutionValue); + /// Returns nearest bound + double nearest(int sequence, double solutionValue); + /** Returns change in cost - one down if alpha >0.0, up if <0.0 + Value is current - new + */ + inline double changeInCost(int sequence, double alpha) const { + double returnValue = 0.0; + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (alpha > 0.0) + returnValue = cost_[iRange] - cost_[iRange-1]; + else + returnValue = cost_[iRange] - cost_[iRange+1]; + } + if (CLP_METHOD2) { + returnValue = (alpha > 0.0) ? infeasibilityWeight_ : -infeasibilityWeight_; + } + return returnValue; + } + inline double changeUpInCost(int sequence) const { + double returnValue = 0.0; + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (iRange + 1 != start_[sequence+1] && !infeasible(iRange + 1)) + returnValue = cost_[iRange] - cost_[iRange+1]; + else + returnValue = -1.0e100; + } + if (CLP_METHOD2) { + returnValue = -infeasibilityWeight_; + } + return returnValue; + } + inline double changeDownInCost(int sequence) const { + double returnValue = 0.0; + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (iRange != start_[sequence] && !infeasible(iRange - 1)) + returnValue = cost_[iRange] - cost_[iRange-1]; + else + returnValue = 1.0e100; + } + if (CLP_METHOD2) { + returnValue = infeasibilityWeight_; + } + return returnValue; + } + /// This also updates next bound + inline double changeInCost(int sequence, double alpha, double &rhs) { + double returnValue = 0.0; +#ifdef NONLIN_DEBUG + double saveRhs = rhs; +#endif + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (alpha > 0.0) { + assert(iRange - 1 >= start_[sequence]); + offset_[sequence]--; + rhs += lower_[iRange] - lower_[iRange-1]; + returnValue = alpha * (cost_[iRange] - cost_[iRange-1]); + } else { + assert(iRange + 1 < start_[sequence+1] - 1); + offset_[sequence]++; + rhs += lower_[iRange+2] - lower_[iRange+1]; + returnValue = alpha * (cost_[iRange] - cost_[iRange+1]); + } + } + if (CLP_METHOD2) { +#ifdef NONLIN_DEBUG + double saveRhs1 = rhs; + rhs = saveRhs; +#endif + unsigned char iStatus = status_[sequence]; + int iWhere = currentStatus(iStatus); + if (iWhere == CLP_SAME) + iWhere = originalStatus(iStatus); + // rhs always increases + if (iWhere == CLP_FEASIBLE) { + if (alpha > 0.0) { + // going below + iWhere = CLP_BELOW_LOWER; + rhs = COIN_DBL_MAX; + } else { + // going above + iWhere = CLP_ABOVE_UPPER; + rhs = COIN_DBL_MAX; + } + } else if (iWhere == CLP_BELOW_LOWER) { + assert (alpha < 0); + // going feasible + iWhere = CLP_FEASIBLE; + rhs += bound_[sequence] - model_->upperRegion()[sequence]; + } else { + assert (iWhere == CLP_ABOVE_UPPER); + // going feasible + iWhere = CLP_FEASIBLE; + rhs += model_->lowerRegion()[sequence] - bound_[sequence]; + } + setCurrentStatus(status_[sequence], iWhere); +#ifdef NONLIN_DEBUG + assert(saveRhs1 == rhs); +#endif + returnValue = fabs(alpha) * infeasibilityWeight_; + } + return returnValue; + } + /// Returns current lower bound + inline double lower(int sequence) const { + return lower_[whichRange_[sequence] + offset_[sequence]]; + } + /// Returns current upper bound + inline double upper(int sequence) const { + return lower_[whichRange_[sequence] + offset_[sequence] + 1]; + } + /// Returns current cost + inline double cost(int sequence) const { + return cost_[whichRange_[sequence] + offset_[sequence]]; + } + //@} + + + /**@name Gets and sets */ + //@{ + /// Number of infeasibilities + inline int numberInfeasibilities() const { + return numberInfeasibilities_; + } + /// Change in cost + inline double changeInCost() const { + return changeCost_; + } + /// Feasible cost + inline double feasibleCost() const { + return feasibleCost_; + } + /// Feasible cost with offset and direction (i.e. for reporting) + double feasibleReportCost() const; + /// Sum of infeasibilities + inline double sumInfeasibilities() const { + return sumInfeasibilities_; + } + /// Largest infeasibility + inline double largestInfeasibility() const { + return largestInfeasibility_; + } + /// Average theta + inline double averageTheta() const { + return averageTheta_; + } + inline void setAverageTheta(double value) { + averageTheta_ = value; + } + inline void setChangeInCost(double value) { + changeCost_ = value; + } + inline void setMethod(int value) { + method_ = value; + } + /// See if may want to look both ways + inline bool lookBothWays() const { + return bothWays_; + } + //@} + ///@name Private functions to deal with infeasible regions + inline bool infeasible(int i) const { + return ((infeasible_[i>>5] >> (i & 31)) & 1) != 0; + } + inline void setInfeasible(int i, bool trueFalse) { + unsigned int & value = infeasible_[i>>5]; + int bit = i & 31; + if (trueFalse) + value |= (1 << bit); + else + value &= ~(1 << bit); + } + inline unsigned char * statusArray() const { + return status_; + } + /// For debug + void validate(); + //@} + +private: + /**@name Data members */ + //@{ + /// Change in cost because of infeasibilities + double changeCost_; + /// Feasible cost + double feasibleCost_; + /// Current infeasibility weight + double infeasibilityWeight_; + /// Largest infeasibility + double largestInfeasibility_; + /// Sum of infeasibilities + double sumInfeasibilities_; + /// Average theta - kept here as only for primal + double averageTheta_; + /// Number of rows (mainly for checking and copy) + int numberRows_; + /// Number of columns (mainly for checking and copy) + int numberColumns_; + /// Starts for each entry (columns then rows) + int * start_; + /// Range for each entry (columns then rows) + int * whichRange_; + /// Temporary range offset for each entry (columns then rows) + int * offset_; + /** Lower bound for each range (upper bound is next lower). + For various reasons there is always an infeasible range + at bottom - even if lower bound is - infinity */ + double * lower_; + /// Cost for each range + double * cost_; + /// Model + ClpSimplex * model_; + // Array to say which regions are infeasible + unsigned int * infeasible_; + /// Number of infeasibilities found + int numberInfeasibilities_; + // new stuff + /// Contains status at beginning and current + unsigned char * status_; + /// Bound which has been replaced in lower_ or upper_ + double * bound_; + /// Feasible cost array + double * cost2_; + /// Method 1 old, 2 new, 3 both! + int method_; + /// If all non-linear costs convex + bool convex_; + /// If we should look both ways for djs + bool bothWays_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpObjective.hpp b/thirdparty/linux/include/coin/ClpObjective.hpp new file mode 100644 index 0000000..f98903a --- /dev/null +++ b/thirdparty/linux/include/coin/ClpObjective.hpp @@ -0,0 +1,134 @@ +/* $Id: ClpObjective.hpp 1825 2011-11-20 16:02:57Z 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). + +#ifndef ClpObjective_H +#define ClpObjective_H + + +//############################################################################# +class ClpSimplex; +class ClpModel; + +/** Objective Abstract Base Class + +Abstract Base Class for describing an objective function + +*/ +class ClpObjective { + +public: + + ///@name Stuff + //@{ + + /** Returns gradient. If Linear then solution may be NULL, + also returns an offset (to be added to current one) + If refresh is false then uses last solution + Uses model for scaling + includeLinear 0 - no, 1 as is, 2 as feasible + */ + virtual double * gradient(const ClpSimplex * model, + const double * solution, + double & offset, bool refresh, + int includeLinear = 2) = 0; + /** Returns reduced gradient.Returns an offset (to be added to current one). + */ + virtual double reducedGradient(ClpSimplex * model, double * region, + bool useFeasibleCosts) = 0; + /** Returns step length which gives minimum of objective for + solution + theta * change vector up to maximum theta. + + arrays are numberColumns+numberRows + Also sets current objective, predicted and at maximumTheta + */ + virtual double stepLength(ClpSimplex * model, + const double * solution, + const double * change, + double maximumTheta, + double & currentObj, + double & predictedObj, + double & thetaObj) = 0; + /// Return objective value (without any ClpModel offset) (model may be NULL) + virtual double objectiveValue(const ClpSimplex * model, const double * solution) const = 0; + /// Resize objective + virtual void resize(int newNumberColumns) = 0; + /// Delete columns in objective + virtual void deleteSome(int numberToDelete, const int * which) = 0; + /// Scale objective + virtual void reallyScale(const double * columnScale) = 0; + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char * which); + /// Say we have new primal solution - so may need to recompute + virtual void newXValues() {} + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpObjective(); + + /// Copy constructor + ClpObjective(const ClpObjective &); + + /// Assignment operator + ClpObjective & operator=(const ClpObjective& rhs); + + /// Destructor + virtual ~ClpObjective (); + + /// Clone + virtual ClpObjective * clone() const = 0; + /** Subset clone. Duplicates are allowed + and order is as given. + Derived classes need not provide this as it may not always make + sense */ + virtual ClpObjective * subsetClone (int numberColumns, + const int * whichColumns) const; + + //@} + + ///@name Other + //@{ + /// Returns type (above 63 is extra information) + inline int type() const { + return type_; + } + /// Sets type (above 63 is extra information) + inline void setType(int value) { + type_ = value; + } + /// Whether activated + inline int activated() const { + return activated_; + } + /// Set whether activated + inline void setActivated(int value) { + activated_ = value; + } + + /// Objective offset + inline double nonlinearOffset () const { + return offset_; + } + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Value of non-linear part of objective + double offset_; + /// Type of objective - linear is 1 + int type_; + /// Whether activated + int activated_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpPackedMatrix.hpp b/thirdparty/linux/include/coin/ClpPackedMatrix.hpp new file mode 100644 index 0000000..ec0c0b9 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpPackedMatrix.hpp @@ -0,0 +1,638 @@ +/* $Id: ClpPackedMatrix.hpp 2078 2015-01-05 12:39:49Z 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). + +#ifndef ClpPackedMatrix_H +#define ClpPackedMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" + +/** This implements CoinPackedMatrix as derived from ClpMatrixBase. + + It adds a few methods that know about model as well as matrix + + For details see CoinPackedMatrix */ + +class ClpPackedMatrix2; +class ClpPackedMatrix3; +class ClpPackedMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix * getPackedMatrix() const { + return matrix_; + } + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const { + return matrix_->isColOrdered(); + } + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const { + return matrix_->getNumElements(); + } + /** Number of columns. */ + virtual int getNumCols() const { + return matrix_->getNumCols(); + } + /** Number of rows. */ + virtual int getNumRows() const { + return matrix_->getNumRows(); + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double * getElements() const { + return matrix_->getElements(); + } + /// Mutable elements + inline double * getMutableElements() const { + return matrix_->getMutableElements(); + } + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int * getIndices() const { + return matrix_->getIndices(); + } + + virtual const CoinBigIndex * getVectorStarts() const { + return matrix_->getVectorStarts(); + } + /** The lengths of the major-dimension vectors. */ + virtual const int * getVectorLengths() const { + return matrix_->getVectorLengths(); + } + /** The length of a single major-dimension vector. */ + virtual int getVectorLength(int index) const { + return matrix_->getVectorSize(index); + } + + /** Delete the columns whose indices are listed in <code>indDel</code>. */ + virtual void deleteCols(const int numDel, const int * indDel); + /** Delete the rows whose indices are listed in <code>indDel</code>. */ + virtual void deleteRows(const int numDel, const int * indDel); +#ifndef CLP_NO_VECTOR + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); +#endif + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex * starts, const int * index, + const double * element, int numberOther = -1); + /** Replace the elements of a vector. The indices remain the same. + This is only needed if scaling and a row copy is used. + At most the number specified will be replaced. + The index is between 0 and major dimension of matrix */ + virtual void replaceVector(const int index, + const int numReplace, const double * newElements) { + matrix_->replaceVector(index, numReplace, newElements); + } + /** Modify one element of packed matrix. An element may be added. + This works for either ordering If the new element is zero it will be + deleted unless keepZero true */ + virtual void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false) { + matrix_->modifyCoefficient(row, column, newElement, keepZero); + } + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase * reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual CoinBigIndex countBasis(const int * whichColumn, + int & numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex * model, + const int * whichColumn, + int & numberColumnBasic, + int * row, int * start, + int * rowCount, int * columnCount, + CoinFactorizationDouble * element); + /** Creates scales for column copy (rowCopy in model may be modified) + returns non-zero if no scaling done */ + virtual int scale(ClpModel * model, const ClpSimplex * baseModel = NULL) const ; + /** Scales rowCopy if column copy scaled + Only called if scales already exist */ + virtual void scaleRowCopy(ClpModel * model) const ; + /// Creates scaled column copy if scales exist + void createScaledMatrix(ClpSimplex * model) const; + /** Realy really scales column copy + Only called if scales already exist. + Up to user ro delete */ + virtual ClpMatrixBase * scaledColumnCopy(ClpModel * model) const ; + /** Checks if all elements are in valid range. Can just + return true if you are not paranoid. For Clp I will + probably expect no zeros. Code can modify matrix to get rid of + small elements. + check bits (can be turned off to save time) : + 1 - check if matrix has gaps + 2 - check if zero elements + 4 - check and compress duplicates + 8 - report on large and small + */ + virtual bool allElementsInRange(ClpModel * model, + double smallest, double largest, + int check = 15); + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + */ + virtual void rangeOfElements(double & smallestNegative, double & largestNegative, + double & smallestPositive, double & largestPositive); + + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column) const ; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex * model, + CoinIndexedVector * rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column, double multiplier) const ; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex * model, double * array, + int column, double multiplier) const; + /// Allow any parts of a created CoinPackedMatrix to be deleted + virtual void releasePackedMatrix() const { } + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + */ + virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + /// makes sure active columns correct + virtual int refresh(ClpSimplex * model); + // Really scale matrix + virtual void reallyScale(const double * rowScale, const double * columnScale); + /** Set the dimensions of the matrix. In effect, append new empty + columns/rows to the matrix. A negative number for either dimension + means that that dimension doesn't change. Otherwise the new dimensions + MUST be at least as large as the current ones otherwise an exception + is thrown. */ + virtual void setDimensions(int numrows, int numcols); + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return <code>y + A * scalar *x</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + virtual void times(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void times(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale) const; + /** Return <code>y + x * scalar * A</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> */ + virtual void transposeTimes(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale, + double * spare = NULL) const; + /** Return <code>y - pi * A</code> in <code>y</code>. + @pre <code>pi</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> + This just does subset (but puts in correct place in y) */ + void transposeTimesSubset( int number, + const int * which, + const double * pi, double * y, + const double * rowScale, + const double * columnScale, + double * spare = NULL) const; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Note - If x packed mode - then z packed mode + This does by column and knows no gaps + Squashes small elements and knows about ClpSimplex */ + void transposeTimesByColumn(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex. + This version uses row copy*/ + virtual void transposeTimesByRow(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x *A</code> in <code>z</code> but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex * model, + const CoinIndexedVector * x, + const CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Returns true if can combine transposeTimes and subsetTransposeTimes + and if it would be faster */ + virtual bool canCombine(const ClpSimplex * model, + const CoinIndexedVector * pi) const; + /// Updates two arrays for steepest + virtual void transposeTimes2(const ClpSimplex * model, + const CoinIndexedVector * pi1, CoinIndexedVector * dj1, + const CoinIndexedVector * pi2, + CoinIndexedVector * spare, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int * reference, + double * weights, double scaleFactor); + /// Updates second array for steepest and does devex weights + virtual void subsetTimes2(const ClpSimplex * model, + CoinIndexedVector * dj1, + const CoinIndexedVector * pi2, CoinIndexedVector * dj2, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int * reference, + double * weights, double scaleFactor); + /// Sets up an effective RHS + void useEffectiveRhs(ClpSimplex * model); +#if COIN_LONG_WORK + // For long double versions + virtual void times(CoinWorkDouble scalar, + const CoinWorkDouble * x, CoinWorkDouble * y) const ; + virtual void transposeTimes(CoinWorkDouble scalar, + const CoinWorkDouble * x, CoinWorkDouble * y) const ; +#endif +//@} + + /**@name Other */ + //@{ + /// Returns CoinPackedMatrix (non const) + inline CoinPackedMatrix * matrix() const { + return matrix_; + } + /** Just sets matrix_ to NULL so it can be used elsewhere. + used in GUB + */ + inline void setMatrixNull() { + matrix_ = NULL; + } + /// Say we want special column copy + inline void makeSpecialColumnCopy() { + flags_ |= 16; + } + /// Say we don't want special column copy + void releaseSpecialColumnCopy(); + /// Are there zeros? + inline bool zeros() const { + return ((flags_ & 1) != 0); + } + /// Do we want special column copy + inline bool wantsSpecialColumnCopy() const { + return ((flags_ & 16) != 0); + } + /// Flags + inline int flags() const { + return flags_; + } + /// Sets flags_ correctly + inline void checkGaps() { + flags_ = (matrix_->hasGaps()) ? (flags_ | 2) : (flags_ & (~2)); + } + /// number of active columns (normally same as number of columns) + inline int numberActiveColumns() const + { return numberActiveColumns_;} + /// Set number of active columns (normally same as number of columns) + inline void setNumberActiveColumns(int value) + { numberActiveColumns_ = value;} + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPackedMatrix(); + /** Destructor */ + virtual ~ClpPackedMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPackedMatrix(const ClpPackedMatrix&); + /** The copy constructor from an CoinPackedMatrix. */ + ClpPackedMatrix(const CoinPackedMatrix&); + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpPackedMatrix (const ClpPackedMatrix & wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + ClpPackedMatrix (const CoinPackedMatrix & wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + + /** This takes over ownership (for space reasons) */ + ClpPackedMatrix(CoinPackedMatrix * matrix); + + ClpPackedMatrix& operator=(const ClpPackedMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + /// Copy contents - resizing if necessary - otherwise re-use memory + virtual void copy(const ClpPackedMatrix * from); + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase * subsetClone ( + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns) const ; + /// make special row copy + void specialRowCopy(ClpSimplex * model, const ClpMatrixBase * rowCopy); + /// make special column copy + void specialColumnCopy(ClpSimplex * model); + /// Correct sequence in and out to give true value + virtual void correctSequence(const ClpSimplex * model, int & sequenceIn, int & sequenceOut) ; + //@} +private: + /// Meat of transposeTimes by column when not scaled + int gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, + int * COIN_RESTRICT index, + double * COIN_RESTRICT array, + const double tolerance) const; + /// Meat of transposeTimes by column when scaled + int gutsOfTransposeTimesScaled(const double * COIN_RESTRICT pi, + const double * COIN_RESTRICT columnScale, + int * COIN_RESTRICT index, + double * COIN_RESTRICT array, + const double tolerance) const; + /// Meat of transposeTimes by column when not scaled and skipping + int gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, + int * COIN_RESTRICT index, + double * COIN_RESTRICT array, + const unsigned char * status, + const double tolerance) const; + /** Meat of transposeTimes by column when not scaled and skipping + and doing part of dualColumn */ + int gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, + int * COIN_RESTRICT index, + double * COIN_RESTRICT array, + const unsigned char * status, + int * COIN_RESTRICT spareIndex, + double * COIN_RESTRICT spareArray, + const double * COIN_RESTRICT reducedCost, + double & upperTheta, + double & bestPossible, + double acceptablePivot, + double dualTolerance, + int & numberRemaining, + const double zeroTolerance) const; + /// Meat of transposeTimes by column when scaled and skipping + int gutsOfTransposeTimesScaled(const double * COIN_RESTRICT pi, + const double * COIN_RESTRICT columnScale, + int * COIN_RESTRICT index, + double * COIN_RESTRICT array, + const unsigned char * status, + const double tolerance) const; + /// Meat of transposeTimes by row n > K if packed - returns number nonzero + int gutsOfTransposeTimesByRowGEK(const CoinIndexedVector * COIN_RESTRICT piVector, + int * COIN_RESTRICT index, + double * COIN_RESTRICT output, + int numberColumns, + const double tolerance, + const double scalar) const; + /// Meat of transposeTimes by row n > 2 if packed - returns number nonzero + int gutsOfTransposeTimesByRowGE3(const CoinIndexedVector * COIN_RESTRICT piVector, + int * COIN_RESTRICT index, + double * COIN_RESTRICT output, + double * COIN_RESTRICT array2, + const double tolerance, + const double scalar) const; + /// Meat of transposeTimes by row n > 2 if packed - returns number nonzero + int gutsOfTransposeTimesByRowGE3a(const CoinIndexedVector * COIN_RESTRICT piVector, + int * COIN_RESTRICT index, + double * COIN_RESTRICT output, + int * COIN_RESTRICT lookup, + char * COIN_RESTRICT marked, + const double tolerance, + const double scalar) const; + /// Meat of transposeTimes by row n == 2 if packed + void gutsOfTransposeTimesByRowEQ2(const CoinIndexedVector * piVector, CoinIndexedVector * output, + CoinIndexedVector * spareVector, const double tolerance, const double scalar) const; + /// Meat of transposeTimes by row n == 1 if packed + void gutsOfTransposeTimesByRowEQ1(const CoinIndexedVector * piVector, CoinIndexedVector * output, + const double tolerance, const double scalar) const; + /// Gets rid of special copies + void clearCopies(); + + +protected: + /// Check validity + void checkFlags(int type) const; + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Data + CoinPackedMatrix * matrix_; + /// number of active columns (normally same as number of columns) + int numberActiveColumns_; + /** Flags - + 1 - has zero elements + 2 - has gaps + 4 - has special row copy + 8 - has special column copy + 16 - wants special column copy + */ + mutable int flags_; + /// Special row copy + ClpPackedMatrix2 * rowCopy_; + /// Special column copy + ClpPackedMatrix3 * columnCopy_; + //@} +}; +#ifdef THREAD +#include <pthread.h> +typedef struct { + double acceptablePivot; + const ClpSimplex * model; + double * spare; + int * spareIndex; + double * arrayTemp; + int * indexTemp; + int * numberInPtr; + double * bestPossiblePtr; + double * upperThetaPtr; + int * posFreePtr; + double * freePivotPtr; + int * numberOutPtr; + const unsigned short * count; + const double * pi; + const CoinBigIndex * rowStart; + const double * element; + const unsigned short * column; + int offset; + int numberInRowArray; + int numberLook; +} dualColumn0Struct; +#endif +class ClpPackedMatrix2 { + +public: + /**@name Useful methods */ + //@{ + /** Return <code>x * -1 * A in <code>z</code>. + Note - x packed and z will be packed mode + Squashes small elements and knows about ClpSimplex */ + void transposeTimes(const ClpSimplex * model, + const CoinPackedMatrix * rowCopy, + const CoinIndexedVector * x, + CoinIndexedVector * spareArray, + CoinIndexedVector * z) const; + /// Returns true if copy has useful information + inline bool usefulInfo() const { + return rowStart_ != NULL; + } + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPackedMatrix2(); + /** Constructor from copy. */ + ClpPackedMatrix2(ClpSimplex * model, const CoinPackedMatrix * rowCopy); + /** Destructor */ + virtual ~ClpPackedMatrix2(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPackedMatrix2(const ClpPackedMatrix2&); + ClpPackedMatrix2& operator=(const ClpPackedMatrix2&); + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Number of blocks + int numberBlocks_; + /// Number of rows + int numberRows_; + /// Column offset for each block (plus one at end) + int * offset_; + /// Counts of elements in each part of row + mutable unsigned short * count_; + /// Row starts + mutable CoinBigIndex * rowStart_; + /// columns within block + unsigned short * column_; + /// work arrays + double * work_; +#ifdef THREAD + pthread_t * threadId_; + dualColumn0Struct * info_; +#endif + //@} +}; +typedef struct { + CoinBigIndex startElements_; // point to data + int startIndices_; // point to column_ + int numberInBlock_; + int numberPrice_; // at beginning + int numberElements_; // number elements per column +} blockStruct; +class ClpPackedMatrix3 { + +public: + /**@name Useful methods */ + //@{ + /** Return <code>x * -1 * A in <code>z</code>. + Note - x packed and z will be packed mode + Squashes small elements and knows about ClpSimplex */ + void transposeTimes(const ClpSimplex * model, + const double * pi, + CoinIndexedVector * output) const; + /// Updates two arrays for steepest + void transposeTimes2(const ClpSimplex * model, + const double * pi, CoinIndexedVector * dj1, + const double * piWeight, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int * reference, + double * weights, double scaleFactor); + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPackedMatrix3(); + /** Constructor from copy. */ + ClpPackedMatrix3(ClpSimplex * model, const CoinPackedMatrix * columnCopy); + /** Destructor */ + virtual ~ClpPackedMatrix3(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPackedMatrix3(const ClpPackedMatrix3&); + ClpPackedMatrix3& operator=(const ClpPackedMatrix3&); + //@} + /**@name Sort methods */ + //@{ + /** Sort blocks */ + void sortBlocks(const ClpSimplex * model); + /// Swap one variable + void swapOne(const ClpSimplex * model, const ClpPackedMatrix * matrix, + int iColumn); + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Number of blocks + int numberBlocks_; + /// Number of columns + int numberColumns_; + /// Column indices and reverse lookup (within block) + int * column_; + /// Starts for odd/long vectors + CoinBigIndex * start_; + /// Rows + int * row_; + /// Elements + double * element_; + /// Blocks (ordinary start at 0 and go to first block) + blockStruct * block_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpParameters.hpp b/thirdparty/linux/include/coin/ClpParameters.hpp new file mode 100644 index 0000000..7252d2b --- /dev/null +++ b/thirdparty/linux/include/coin/ClpParameters.hpp @@ -0,0 +1,126 @@ +/* $Id: ClpParameters.hpp 2046 2014-08-14 04:13:10Z tkr $ */ +// Copyright (C) 2000, 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _ClpParameters_H +#define _ClpParameters_H + +/** This is where to put any useful stuff. + +*/ +enum ClpIntParam { + /** The maximum number of iterations Clp can execute in the simplex methods + */ + ClpMaxNumIteration = 0, + /** The maximum number of iterations Clp can execute in hotstart before + terminating */ + ClpMaxNumIterationHotStart, + /** The name discipline; specifies how the solver will handle row and + column names. + - 0: Auto names: Names cannot be set by the client. Names of the form + Rnnnnnnn or Cnnnnnnn are generated on demand when a name for a + specific row or column is requested; nnnnnnn is derived from the row + or column index. Requests for a vector of names return a vector with + zero entries. + - 1: Lazy names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to the largest index of a name supplied by the client; + some entries in the vector may be null strings. + - 2: Full names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to match the constraint system, and all entries will + contain either the name specified by the client or a generated name. + */ + ClpNameDiscipline, + /** Just a marker, so that we can allocate a static sized array to store + parameters. */ + ClpLastIntParam +}; + +enum ClpDblParam { + /** Set Dual objective limit. This is to be used as a termination criteria + in methods where the dual objective monotonically changes (dual + simplex). */ + ClpDualObjectiveLimit, + /** Primal objective limit. This is to be used as a termination + criteria in methods where the primal objective monotonically changes + (e.g., primal simplex) */ + ClpPrimalObjectiveLimit, + /** The maximum amount the dual constraints can be violated and still be + considered feasible. */ + ClpDualTolerance, + /** The maximum amount the primal constraints can be violated and still be + considered feasible. */ + ClpPrimalTolerance, + /** Objective function constant. This the value of the constant term in + the objective function. */ + ClpObjOffset, + /// Maximum time in seconds - after, this action is as max iterations + ClpMaxSeconds, + /// Maximum wallclock running time in seconds - after, this action is as max iterations + ClpMaxWallSeconds, + /// Tolerance to use in presolve + ClpPresolveTolerance, + /** Just a marker, so that we can allocate a static sized array to store + parameters. */ + ClpLastDblParam +}; + + +enum ClpStrParam { + /** Name of the problem. This is the found on the Name card of + an mps file. */ + ClpProbName = 0, + /** Just a marker, so that we can allocate a static sized array to store + parameters. */ + ClpLastStrParam +}; + +/// Copy (I don't like complexity of Coin version) +template <class T> inline void +ClpDisjointCopyN( const T * array, const int size, T * newArray) +{ + memcpy(reinterpret_cast<void *> (newArray), array, size * sizeof(T)); +} +/// And set +template <class T> inline void +ClpFillN( T * array, const int size, T value) +{ + int i; + for (i = 0; i < size; i++) + array[i] = value; +} +/// This returns a non const array filled with input from scalar or actual array +template <class T> inline T* +ClpCopyOfArray( const T * array, const int size, T value) +{ + T * arrayNew = new T[size]; + if (array) + ClpDisjointCopyN(array, size, arrayNew); + else + ClpFillN ( arrayNew, size, value); + return arrayNew; +} + +/// This returns a non const array filled with actual array (or NULL) +template <class T> inline T* +ClpCopyOfArray( const T * array, const int size) +{ + if (array) { + T * arrayNew = new T[size]; + ClpDisjointCopyN(array, size, arrayNew); + return arrayNew; + } else { + return NULL; + } +} +/// For a structure to be used by trusted code +typedef struct { + int typeStruct; // allocated as 1,2 etc + int typeCall; + void * data; +} ClpTrustedData; +#endif diff --git a/thirdparty/linux/include/coin/ClpPdcoBase.hpp b/thirdparty/linux/include/coin/ClpPdcoBase.hpp new file mode 100644 index 0000000..cb8fd8f --- /dev/null +++ b/thirdparty/linux/include/coin/ClpPdcoBase.hpp @@ -0,0 +1,103 @@ +/* $Id: ClpPdcoBase.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPdcoBase_H +#define ClpPdcoBase_H + +#include "CoinPragma.hpp" + +#include "CoinPackedMatrix.hpp" +#include "CoinDenseVector.hpp" +class ClpInterior; + +/** Abstract base class for tailoring everything for Pcdo + + Since this class is abstract, no object of this type can be created. + + If a derived class provides all methods then all ClpPcdo algorithms + should work. + + Eventually we should be able to use ClpObjective and ClpMatrixBase. +*/ + +class ClpPdcoBase { + +public: + /**@name Virtual methods that the derived classes must provide */ + //@{ + virtual void matVecMult(ClpInterior * model, int mode, double * x, double * y) const = 0; + + virtual void getGrad(ClpInterior * model, CoinDenseVector<double> &x, CoinDenseVector<double> &grad) const = 0; + + virtual void getHessian(ClpInterior * model, CoinDenseVector<double> &x, CoinDenseVector<double> &H) const = 0; + + virtual double getObj(ClpInterior * model, CoinDenseVector<double> &x) const = 0; + + virtual void matPrecon(ClpInterior * model, double delta, double * x, double * y) const = 0; + + //@} + //@{ + ///@name Other + /// Clone + virtual ClpPdcoBase * clone() const = 0; + /// Returns type + inline int type() const { + return type_; + }; + /// Sets type + inline void setType(int type) { + type_ = type; + }; + /// Returns size of d1 + inline int sizeD1() const { + return 1; + }; + /// Returns d1 as scalar + inline double getD1() const { + return d1_; + }; + /// Returns size of d2 + inline int sizeD2() const { + return 1; + }; + /// Returns d2 as scalar + inline double getD2() const { + return d2_; + }; + //@} + + +protected: + + /**@name Constructors, destructor<br> + <strong>NOTE</strong>: All constructors are protected. There's no need + to expose them, after all, this is an abstract class. */ + //@{ + /** Default constructor. */ + ClpPdcoBase(); + /** Destructor (has to be public) */ +public: + virtual ~ClpPdcoBase(); +protected: + // Copy + ClpPdcoBase(const ClpPdcoBase&); + // Assignment + ClpPdcoBase& operator=(const ClpPdcoBase&); + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Should be dense vectors + double d1_; + double d2_; + /// type (may be useful) + int type_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpPlusMinusOneMatrix.hpp b/thirdparty/linux/include/coin/ClpPlusMinusOneMatrix.hpp new file mode 100644 index 0000000..0cf27a4 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpPlusMinusOneMatrix.hpp @@ -0,0 +1,290 @@ +/* $Id: ClpPlusMinusOneMatrix.hpp 2078 2015-01-05 12:39:49Z forrest $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPlusMinusOneMatrix_H +#define ClpPlusMinusOneMatrix_H + + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" + +/** This implements a simple +- one matrix as derived from ClpMatrixBase. + +*/ + +class ClpPlusMinusOneMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix * getPackedMatrix() const; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const ; + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const; + /** Number of columns. */ + virtual int getNumCols() const { + return numberColumns_; + } + /** Number of rows. */ + virtual int getNumRows() const { + return numberRows_; + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double * getElements() const; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int * getIndices() const { + return indices_; + } + // and for advanced use + int * getMutableIndices() const { + return indices_; + } + + virtual const CoinBigIndex * getVectorStarts() const; + /** The lengths of the major-dimension vectors. */ + virtual const int * getVectorLengths() const; + + /** Delete the columns whose indices are listed in <code>indDel</code>. */ + virtual void deleteCols(const int numDel, const int * indDel); + /** Delete the rows whose indices are listed in <code>indDel</code>. */ + virtual void deleteRows(const int numDel, const int * indDel); + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); +#ifndef SLIM_CLP + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex * starts, const int * index, + const double * element, int numberOther = -1); +#endif + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase * reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual CoinBigIndex countBasis( + const int * whichColumn, + int & numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex * model, + const int * whichColumn, + int & numberColumnBasic, + int * row, int * start, + int * rowCount, int * columnCount, + CoinFactorizationDouble * element); + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + */ + virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + */ + virtual void rangeOfElements(double & smallestNegative, double & largestNegative, + double & smallestPositive, double & largestPositive); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column) const ; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex * model, + CoinIndexedVector * rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, + int column, double multiplier) const ; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex * model, double * array, + int column, double multiplier) const; + /// Allow any parts of a created CoinMatrix to be deleted + virtual void releasePackedMatrix() const; + /** Set the dimensions of the matrix. In effect, append new empty + columns/rows to the matrix. A negative number for either dimension + means that that dimension doesn't change. Otherwise the new dimensions + MUST be at least as large as the current ones otherwise an exception + is thrown. */ + virtual void setDimensions(int numrows, int numcols); + /// Just checks matrix valid - will say if dimensions not quite right if detail + void checkValid(bool detail) const; + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return <code>y + A * scalar *x</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + virtual void times(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void times(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale) const; + /** Return <code>y + x * scalar * A</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> */ + virtual void transposeTimes(double scalar, + const double * x, double * y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double * x, double * y, + const double * rowScale, + const double * columnScale, double * spare = NULL) const; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x * scalar * A + y</code> in <code>z</code>. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex. + This version uses row copy*/ + virtual void transposeTimesByRow(const ClpSimplex * model, double scalar, + const CoinIndexedVector * x, + CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Return <code>x *A</code> in <code>z</code> but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex * model, + const CoinIndexedVector * x, + const CoinIndexedVector * y, + CoinIndexedVector * z) const; + /** Returns true if can combine transposeTimes and subsetTransposeTimes + and if it would be faster */ + virtual bool canCombine(const ClpSimplex * model, + const CoinIndexedVector * pi) const; + /// Updates two arrays for steepest + virtual void transposeTimes2(const ClpSimplex * model, + const CoinIndexedVector * pi1, CoinIndexedVector * dj1, + const CoinIndexedVector * pi2, + CoinIndexedVector * spare, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int * reference, + double * weights, double scaleFactor); + /// Updates second array for steepest and does devex weights + virtual void subsetTimes2(const ClpSimplex * model, + CoinIndexedVector * dj1, + const CoinIndexedVector * pi2, CoinIndexedVector * dj2, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int * reference, + double * weights, double scaleFactor); + //@} + + /**@name Other */ + //@{ + /// Return starts of +1s + inline CoinBigIndex * startPositive() const { + return startPositive_; + } + /// Return starts of -1s + inline CoinBigIndex * startNegative() const { + return startNegative_; + } + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPlusMinusOneMatrix(); + /** Destructor */ + virtual ~ClpPlusMinusOneMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPlusMinusOneMatrix(const ClpPlusMinusOneMatrix&); + /** The copy constructor from an CoinPlusMinusOneMatrix. + If not a valid matrix then getIndices will be NULL and + startPositive[0] will have number of +1, + startPositive[1] will have number of -1, + startPositive[2] will have number of others, + */ + ClpPlusMinusOneMatrix(const CoinPackedMatrix&); + /// Constructor from arrays + ClpPlusMinusOneMatrix(int numberRows, int numberColumns, + bool columnOrdered, const int * indices, + const CoinBigIndex * startPositive, const CoinBigIndex * startNegative); + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpPlusMinusOneMatrix (const ClpPlusMinusOneMatrix & wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + + ClpPlusMinusOneMatrix& operator=(const ClpPlusMinusOneMatrix&); + /// Clone + virtual ClpMatrixBase * clone() const ; + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase * subsetClone ( + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns) const ; + /// pass in copy (object takes ownership) + void passInCopy(int numberRows, int numberColumns, + bool columnOrdered, int * indices, + CoinBigIndex * startPositive, CoinBigIndex * startNegative); + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex * model, double start, double end, + int & bestSequence, int & numberWanted); + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// For fake CoinPackedMatrix + mutable CoinPackedMatrix * matrix_; + mutable int * lengths_; + /// Start of +1's for each + CoinBigIndex * COIN_RESTRICT startPositive_; + /// Start of -1's for each + CoinBigIndex * COIN_RESTRICT startNegative_; + /// Data -1, then +1 rows in pairs (row==-1 if one entry) + int * COIN_RESTRICT indices_; + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; +#ifdef CLP_PLUS_ONE_MATRIX + /** Other flags (could have columnOrdered_?) + 1 bit - says just +1 + */ + mutable int otherFlags_; +#endif + /// True if column ordered + bool columnOrdered_; + + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpPresolve.hpp b/thirdparty/linux/include/coin/ClpPresolve.hpp new file mode 100644 index 0000000..5e28289 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpPresolve.hpp @@ -0,0 +1,299 @@ +/* $Id: ClpPresolve.hpp 2134 2015-03-22 16:40:43Z 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). + +#ifndef ClpPresolve_H +#define ClpPresolve_H +#include "ClpSimplex.hpp" + +class CoinPresolveAction; +#include "CoinPresolveMatrix.hpp" +/** This is the Clp interface to CoinPresolve + +*/ +class ClpPresolve { +public: + /**@name Main Constructor, destructor */ + //@{ + /// Default constructor + ClpPresolve(); + + /// Virtual destructor + virtual ~ClpPresolve(); + //@} + /**@name presolve - presolves a model, transforming the model + * and saving information in the ClpPresolve object needed for postsolving. + * This underlying (protected) method is virtual; the idea is that in the future, + * one could override this method to customize how the various + * presolve techniques are applied. + + This version of presolve returns a pointer to a new presolved + model. NULL if infeasible or unbounded. + This should be paired with postsolve + below. The advantage of going back to original model is that it + will be exactly as it was i.e. 0.0 will not become 1.0e-19. + If keepIntegers is true then bounds may be tightened in + original. Bounds will be moved by up to feasibilityTolerance + to try and stay feasible. + Names will be dropped in presolved model if asked + */ + ClpSimplex * presolvedModel(ClpSimplex & si, + double feasibilityTolerance = 0.0, + bool keepIntegers = true, + int numberPasses = 5, + bool dropNames = false, + bool doRowObjective = false, + const char * prohibitedRows=NULL, + const char * prohibitedColumns=NULL); +#ifndef CLP_NO_STD + /** This version saves data in a file. The passed in model + is updated to be presolved model. + Returns non-zero if infeasible*/ + int presolvedModelToFile(ClpSimplex &si, std::string fileName, + double feasibilityTolerance = 0.0, + bool keepIntegers = true, + int numberPasses = 5, + bool dropNames = false, + bool doRowObjective = false); +#endif + /** Return pointer to presolved model, + Up to user to destroy */ + ClpSimplex * model() const; + /// Return pointer to original model + ClpSimplex * originalModel() const; + /// Set pointer to original model + void setOriginalModel(ClpSimplex * model); + + /// return pointer to original columns + const int * originalColumns() const; + /// return pointer to original rows + const int * originalRows() const; + /** "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + */ + inline void setNonLinearValue(double value) { + nonLinearValue_ = value; + } + inline double nonLinearValue() const { + return nonLinearValue_; + } + /// Whether we want to do dual part of presolve + inline bool doDual() const { + return (presolveActions_ & 1) == 0; + } + inline void setDoDual(bool doDual) { + if (doDual) presolveActions_ &= ~1; + else presolveActions_ |= 1; + } + /// Whether we want to do singleton part of presolve + inline bool doSingleton() const { + return (presolveActions_ & 2) == 0; + } + inline void setDoSingleton(bool doSingleton) { + if (doSingleton) presolveActions_ &= ~2; + else presolveActions_ |= 2; + } + /// Whether we want to do doubleton part of presolve + inline bool doDoubleton() const { + return (presolveActions_ & 4) == 0; + } + inline void setDoDoubleton(bool doDoubleton) { + if (doDoubleton) presolveActions_ &= ~4; + else presolveActions_ |= 4; + } + /// Whether we want to do tripleton part of presolve + inline bool doTripleton() const { + return (presolveActions_ & 8) == 0; + } + inline void setDoTripleton(bool doTripleton) { + if (doTripleton) presolveActions_ &= ~8; + else presolveActions_ |= 8; + } + /// Whether we want to do tighten part of presolve + inline bool doTighten() const { + return (presolveActions_ & 16) == 0; + } + inline void setDoTighten(bool doTighten) { + if (doTighten) presolveActions_ &= ~16; + else presolveActions_ |= 16; + } + /// Whether we want to do forcing part of presolve + inline bool doForcing() const { + return (presolveActions_ & 32) == 0; + } + inline void setDoForcing(bool doForcing) { + if (doForcing) presolveActions_ &= ~32; + else presolveActions_ |= 32; + } + /// Whether we want to do impliedfree part of presolve + inline bool doImpliedFree() const { + return (presolveActions_ & 64) == 0; + } + inline void setDoImpliedFree(bool doImpliedfree) { + if (doImpliedfree) presolveActions_ &= ~64; + else presolveActions_ |= 64; + } + /// Whether we want to do dupcol part of presolve + inline bool doDupcol() const { + return (presolveActions_ & 128) == 0; + } + inline void setDoDupcol(bool doDupcol) { + if (doDupcol) presolveActions_ &= ~128; + else presolveActions_ |= 128; + } + /// Whether we want to do duprow part of presolve + inline bool doDuprow() const { + return (presolveActions_ & 256) == 0; + } + inline void setDoDuprow(bool doDuprow) { + if (doDuprow) presolveActions_ &= ~256; + else presolveActions_ |= 256; + } + /// Whether we want to do dependency part of presolve + inline bool doDependency() const { + return (presolveActions_ & 32768) != 0; + } + inline void setDoDependency(bool doDependency) { + if (doDependency) presolveActions_ |= 32768; + else presolveActions_ &= ~32768; + } + /// Whether we want to do singleton column part of presolve + inline bool doSingletonColumn() const { + return (presolveActions_ & 512) == 0; + } + inline void setDoSingletonColumn(bool doSingleton) { + if (doSingleton) presolveActions_ &= ~512; + else presolveActions_ |= 512; + } + /// Whether we want to do gubrow part of presolve + inline bool doGubrow() const { + return (presolveActions_ & 1024) == 0; + } + inline void setDoGubrow(bool doGubrow) { + if (doGubrow) presolveActions_ &= ~1024; + else presolveActions_ |= 1024; + } + /// Whether we want to do twoxtwo part of presolve + inline bool doTwoxTwo() const { + return (presolveActions_ & 2048) != 0; + } + inline void setDoTwoxtwo(bool doTwoxTwo) { + if (!doTwoxTwo) presolveActions_ &= ~2048; + else presolveActions_ |= 2048; + } + /// Whether we want to allow duplicate intersections + inline bool doIntersection() const { + return (presolveActions_ & 4096) != 0; + } + inline void setDoIntersection(bool doIntersection) { + if (doIntersection) presolveActions_ &= ~4096; + else presolveActions_ |= 4096; + } + /** How much we want to zero small values from aggregation - ratio + 0 - 1.0e-12, 1 1.0e-11, 2 1.0e-10, 3 1.0e-9 */ + inline int zeroSmall() const { + return (presolveActions_&(8192|16384))>>13; + } + inline void setZeroSmall(int value) { + presolveActions_ &= ~(8192|16384); + presolveActions_ |= value<<13; + } + /// Set whole group + inline int presolveActions() const { + return presolveActions_ & 0xffff; + } + inline void setPresolveActions(int action) { + presolveActions_ = (presolveActions_ & 0xffff0000) | (action & 0xffff); + } + /// Substitution level + inline void setSubstitution(int value) { + substitution_ = value; + } + /// Asks for statistics + inline void statistics() { + presolveActions_ |= 0x80000000; + } + /// Return presolve status (0,1,2) + int presolveStatus() const; + + /**@name postsolve - postsolve the problem. If the problem + has not been solved to optimality, there are no guarantees. + If you are using an algorithm like simplex that has a concept + of "basic" rows/cols, then set updateStatus + + Note that if you modified the original problem after presolving, + then you must ``undo'' these modifications before calling postsolve. + This version updates original*/ + virtual void postsolve(bool updateStatus = true); + + /// Gets rid of presolve actions (e.g.when infeasible) + void destroyPresolve(); + + /**@name private or protected data */ +private: + /// Original model - must not be destroyed before postsolve + ClpSimplex * originalModel_; + + /// ClpPresolved model - up to user to destroy by deleteClpPresolvedModel + ClpSimplex * presolvedModel_; + /** "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + One could also allow for cases where sign of coefficient is known. + */ + double nonLinearValue_; + /// Original column numbers + int * originalColumn_; + /// Original row numbers + int * originalRow_; + /// Row objective + double * rowObjective_; + /// The list of transformations applied. + const CoinPresolveAction *paction_; + + /// The postsolved problem will expand back to its former size + /// as postsolve transformations are applied. + /// It is efficient to allocate data structures for the final size + /// of the problem rather than expand them as needed. + /// These fields give the size of the original problem. + int ncols_; + int nrows_; + CoinBigIndex nelems_; + /// Number of major passes + int numberPasses_; + /// Substitution level + int substitution_; +#ifndef CLP_NO_STD + /// Name of saved model file + std::string saveFile_; +#endif + /** Whether we want to skip dual part of presolve etc. + 512 bit allows duplicate column processing on integer columns + and dual stuff on integers + */ + int presolveActions_; +protected: + /// If you want to apply the individual presolve routines differently, + /// or perhaps add your own to the mix, + /// define a derived class and override this method + virtual const CoinPresolveAction *presolve(CoinPresolveMatrix *prob); + + /// Postsolving is pretty generic; just apply the transformations + /// in reverse order. + /// You will probably only be interested in overriding this method + /// if you want to add code to test for consistency + /// while debugging new presolve techniques. + virtual void postsolve(CoinPostsolveMatrix &prob); + /** This is main part of Presolve */ + virtual ClpSimplex * gutsOfPresolvedModel(ClpSimplex * originalModel, + double feasibilityTolerance, + bool keepIntegers, + int numberPasses, + bool dropNames, + bool doRowObjective, + const char * prohibitedRows=NULL, + const char * prohibitedColumns=NULL); +}; +#endif diff --git a/thirdparty/linux/include/coin/ClpPrimalColumnDantzig.hpp b/thirdparty/linux/include/coin/ClpPrimalColumnDantzig.hpp new file mode 100644 index 0000000..7289ead --- /dev/null +++ b/thirdparty/linux/include/coin/ClpPrimalColumnDantzig.hpp @@ -0,0 +1,72 @@ +/* $Id: ClpPrimalColumnDantzig.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// 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). + +#ifndef ClpPrimalColumnDantzig_H +#define ClpPrimalColumnDantzig_H + +#include "ClpPrimalColumnPivot.hpp" + +//############################################################################# + +/** Primal Column Pivot Dantzig Algorithm Class + +This is simplest choice - choose largest infeasibility + +*/ + +class ClpPrimalColumnDantzig : public ClpPrimalColumnPivot { + +public: + + ///@name Algorithmic methods + //@{ + + /** Returns pivot column, -1 if none. + Lumbers over all columns - slow + The Packed CoinIndexedVector updates has cost updates - for normal LP + that is just +-weight where a feasibility changed. It also has + reduced cost from last iteration in pivot row + Can just do full price if you really want to be slow + */ + virtual int pivotColumn(CoinIndexedVector * updates, + CoinIndexedVector * spareRow1, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + + /// Just sets model + virtual void saveWeights(ClpSimplex * model, int) { + model_ = model; + } + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpPrimalColumnDantzig(); + + /// Copy constructor + ClpPrimalColumnDantzig(const ClpPrimalColumnDantzig &); + + /// Assignment operator + ClpPrimalColumnDantzig & operator=(const ClpPrimalColumnDantzig& rhs); + + /// Destructor + virtual ~ClpPrimalColumnDantzig (); + + /// Clone + virtual ClpPrimalColumnPivot * clone(bool copyData = true) const; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpPrimalColumnPivot.hpp b/thirdparty/linux/include/coin/ClpPrimalColumnPivot.hpp new file mode 100644 index 0000000..678da30 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpPrimalColumnPivot.hpp @@ -0,0 +1,155 @@ +/* $Id: ClpPrimalColumnPivot.hpp 1732 2011-05-31 08:09:41Z 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). + +#ifndef ClpPrimalcolumnPivot_H +#define ClpPrimalcolumnPivot_H + +class ClpSimplex; +class CoinIndexedVector; + +//############################################################################# + +/** Primal Column Pivot Abstract Base Class + +Abstract Base Class for describing an interface to an algorithm +to choose column pivot in primal simplex algorithm. For some algorithms +e.g. Dantzig choice then some functions may be null. For Dantzig +the only one of any importance is pivotColumn. + +If you wish to inherit from this look at ClpPrimalColumnDantzig.cpp +as that is simplest version. +*/ + +class ClpPrimalColumnPivot { + +public: + + ///@name Algorithmic methods + //@{ + + /** Returns pivot column, -1 if none + + Normally updates reduced costs using result of last iteration + before selecting incoming column. + + The Packed CoinIndexedVector updates has cost updates - for normal LP + that is just +-weight where a feasibility changed. It also has + reduced cost from last iteration in pivot row + + Inside pivotColumn the pivotRow_ and reduced cost from last iteration + are also used. + + So in the simplest case i.e. feasible we compute the row of the + tableau corresponding to last pivot and add a multiple of this + to current reduced costs. + + We can use other arrays to help updates + */ + virtual int pivotColumn(CoinIndexedVector * updates, + CoinIndexedVector * spareRow1, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2) = 0; + + /// Updates weights - part 1 (may be empty) + virtual void updateWeights(CoinIndexedVector * input); + + /** Saves any weights round factorization as pivot rows may change + Will be empty unless steepest edge (will save model) + May also recompute infeasibility stuff + 1) before factorization + 2) after good factorization (if weights empty may initialize) + 3) after something happened but no factorization + (e.g. check for infeasible) + 4) as 2 but restore weights from previous snapshot + 5) forces some initialization e.g. weights + Also sets model + */ + virtual void saveWeights(ClpSimplex * model, int mode) = 0; + /** Signals pivot row choice: + -2 (default) - use normal pivot row choice + -1 to numberRows-1 - use this (will be checked) + way should be -1 to go to lower bound, +1 to upper bound + */ + virtual int pivotRow(double & way) { + way = 0; + return -2; + } + /// Gets rid of all arrays (may be empty) + virtual void clearArrays(); + /// Returns true if would not find any column + virtual bool looksOptimal() const { + return looksOptimal_; + } + /// Sets optimality flag (for advanced use) + virtual void setLooksOptimal(bool flag) { + looksOptimal_ = flag; + } + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpPrimalColumnPivot(); + + /// Copy constructor + ClpPrimalColumnPivot(const ClpPrimalColumnPivot &); + + /// Assignment operator + ClpPrimalColumnPivot & operator=(const ClpPrimalColumnPivot& rhs); + + /// Destructor + virtual ~ClpPrimalColumnPivot (); + + /// Clone + virtual ClpPrimalColumnPivot * clone(bool copyData = true) const = 0; + + //@} + + ///@name Other + //@{ + /// Returns model + inline ClpSimplex * model() { + return model_; + } + /// Sets model + inline void setModel(ClpSimplex * newmodel) { + model_ = newmodel; + } + + /// Returns type (above 63 is extra information) + inline int type() { + return type_; + } + + /** Returns number of extra columns for sprint algorithm - 0 means off. + Also number of iterations before recompute + */ + virtual int numberSprintColumns(int & numberIterations) const; + /// Switch off sprint idea + virtual void switchOffSprint(); + /// Called when maximum pivots changes + virtual void maximumPivotsChanged() {} + + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Pointer to model + ClpSimplex * model_; + /// Type of column pivot algorithm + int type_; + /// Says if looks optimal (normally computed) + bool looksOptimal_; + //@} +}; +#ifndef CLP_PRIMAL_SLACK_MULTIPLIER +#define CLP_PRIMAL_SLACK_MULTIPLIER 1.01 +#endif +#endif diff --git a/thirdparty/linux/include/coin/ClpPrimalColumnSteepest.hpp b/thirdparty/linux/include/coin/ClpPrimalColumnSteepest.hpp new file mode 100644 index 0000000..2da7542 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpPrimalColumnSteepest.hpp @@ -0,0 +1,247 @@ +/* $Id: ClpPrimalColumnSteepest.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// 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). + +#ifndef ClpPrimalColumnSteepest_H +#define ClpPrimalColumnSteepest_H + +#include "ClpPrimalColumnPivot.hpp" +#include <bitset> + +//############################################################################# +class CoinIndexedVector; + + +/** Primal Column Pivot Steepest Edge Algorithm Class + +See Forrest-Goldfarb paper for algorithm + +*/ + + +class ClpPrimalColumnSteepest : public ClpPrimalColumnPivot { + +public: + + ///@name Algorithmic methods + //@{ + + /** Returns pivot column, -1 if none. + The Packed CoinIndexedVector updates has cost updates - for normal LP + that is just +-weight where a feasibility changed. It also has + reduced cost from last iteration in pivot row + Parts of operation split out into separate functions for + profiling and speed + */ + virtual int pivotColumn(CoinIndexedVector * updates, + CoinIndexedVector * spareRow1, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// For quadratic or funny nonlinearities + int pivotColumnOldMethod(CoinIndexedVector * updates, + CoinIndexedVector * spareRow1, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Just update djs + void justDjs(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Update djs doing partial pricing (dantzig) + int partialPricing(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + int numberWanted, + int numberLook); + /// Update djs, weights for Devex using djs + void djsAndDevex(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Update djs, weights for Steepest using djs + void djsAndSteepest(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Update djs, weights for Devex using pivot row + void djsAndDevex2(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Update djs, weights for Steepest using pivot row + void djsAndSteepest2(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Update weights for Devex + void justDevex(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Update weights for Steepest + void justSteepest(CoinIndexedVector * updates, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + /// Updates two arrays for steepest + void transposeTimes2(const CoinIndexedVector * pi1, CoinIndexedVector * dj1, + const CoinIndexedVector * pi2, CoinIndexedVector * dj2, + CoinIndexedVector * spare, double scaleFactor); + + /// Updates weights - part 1 - also checks accuracy + virtual void updateWeights(CoinIndexedVector * input); + + /// Checks accuracy - just for debug + void checkAccuracy(int sequence, double relativeTolerance, + CoinIndexedVector * rowArray1, + CoinIndexedVector * rowArray2); + + /// Initialize weights + void initializeWeights(); + + /** Save weights - this may initialize weights as well + mode is - + 1) before factorization + 2) after factorization + 3) just redo infeasibilities + 4) restore weights + 5) at end of values pass (so need initialization) + */ + virtual void saveWeights(ClpSimplex * model, int mode); + /// Gets rid of last update + virtual void unrollWeights(); + /// Gets rid of all arrays + virtual void clearArrays(); + /// Returns true if would not find any column + virtual bool looksOptimal() const; + /// Called when maximum pivots changes + virtual void maximumPivotsChanged(); + //@} + + /**@name gets and sets */ + //@{ + /// Mode + inline int mode() const { + return mode_; + } + /** Returns number of extra columns for sprint algorithm - 0 means off. + Also number of iterations before recompute + */ + virtual int numberSprintColumns(int & numberIterations) const; + /// Switch off sprint idea + virtual void switchOffSprint(); + +//@} + + /** enums for persistence + */ + enum Persistence { + normal = 0x00, // create (if necessary) and destroy + keep = 0x01 // create (if necessary) and leave + }; + + ///@name Constructors and destructors + //@{ + /** Default Constructor + 0 is exact devex, 1 full steepest, 2 is partial exact devex + 3 switches between 0 and 2 depending on factorization + 4 starts as partial dantzig/devex but then may switch between 0 and 2. + By partial exact devex is meant that the weights are updated as normal + but only part of the nonbasic variables are scanned. + This can be faster on very easy problems. + */ + ClpPrimalColumnSteepest(int mode = 3); + + /// Copy constructor + ClpPrimalColumnSteepest(const ClpPrimalColumnSteepest & rhs); + + /// Assignment operator + ClpPrimalColumnSteepest & operator=(const ClpPrimalColumnSteepest& rhs); + + /// Destructor + virtual ~ClpPrimalColumnSteepest (); + + /// Clone + virtual ClpPrimalColumnPivot * clone(bool copyData = true) const; + + //@} + + ///@name Private functions to deal with devex + /** reference would be faster using ClpSimplex's status_, + but I prefer to keep modularity. + */ + inline bool reference(int i) const { + return ((reference_[i>>5] >> (i & 31)) & 1) != 0; + } + inline void setReference(int i, bool trueFalse) { + unsigned int & value = reference_[i>>5]; + int bit = i & 31; + if (trueFalse) + value |= (1 << bit); + else + value &= ~(1 << bit); + } + /// Set/ get persistence + inline void setPersistence(Persistence life) { + persistence_ = life; + } + inline Persistence persistence() const { + return persistence_ ; + } + + //@} + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + // Update weight + double devex_; + /// weight array + double * weights_; + /// square of infeasibility array (just for infeasible columns) + CoinIndexedVector * infeasible_; + /// alternate weight array (so we can unroll) + CoinIndexedVector * alternateWeights_; + /// save weight array (so we can use checkpoint) + double * savedWeights_; + // Array for exact devex to say what is in reference framework + unsigned int * reference_; + /** Status + 0) Normal + -1) Needs initialization + 1) Weights are stored by sequence number + */ + int state_; + /** + 0 is exact devex, 1 full steepest, 2 is partial exact devex + 3 switches between 0 and 2 depending on factorization + 4 starts as partial dantzig/devex but then may switch between 0 and 2. + 5 is always partial dantzig + By partial exact devex is meant that the weights are updated as normal + but only part of the nonbasic variables are scanned. + This can be faster on very easy problems. + + New dubious option is >=10 which does mini-sprint + + */ + int mode_; + /// Life of weights + Persistence persistence_; + /// Number of times switched from partial dantzig to 0/2 + int numberSwitched_; + // This is pivot row (or pivot sequence round re-factorization) + int pivotSequence_; + // This is saved pivot sequence + int savedPivotSequence_; + // This is saved outgoing variable + int savedSequenceOut_; + // Iteration when last rectified + int lastRectified_; + // Size of factorization at invert (used to decide algorithm) + int sizeFactorization_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpQuadraticObjective.hpp b/thirdparty/linux/include/coin/ClpQuadraticObjective.hpp new file mode 100644 index 0000000..a52b097 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpQuadraticObjective.hpp @@ -0,0 +1,155 @@ +/* $Id: ClpQuadraticObjective.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpQuadraticObjective_H +#define ClpQuadraticObjective_H + +#include "ClpObjective.hpp" +#include "CoinPackedMatrix.hpp" + +//############################################################################# + +/** Quadratic Objective Class + +*/ + +class ClpQuadraticObjective : public ClpObjective { + +public: + + ///@name Stuff + //@{ + + /** Returns gradient. If Quadratic then solution may be NULL, + also returns an offset (to be added to current one) + If refresh is false then uses last solution + Uses model for scaling + includeLinear 0 - no, 1 as is, 2 as feasible + */ + virtual double * gradient(const ClpSimplex * model, + const double * solution, double & offset, bool refresh, + int includeLinear = 2); + /// Resize objective + /** Returns reduced gradient.Returns an offset (to be added to current one). + */ + virtual double reducedGradient(ClpSimplex * model, double * region, + bool useFeasibleCosts); + /** Returns step length which gives minimum of objective for + solution + theta * change vector up to maximum theta. + + arrays are numberColumns+numberRows + Also sets current objective, predicted and at maximumTheta + */ + virtual double stepLength(ClpSimplex * model, + const double * solution, + const double * change, + double maximumTheta, + double & currentObj, + double & predictedObj, + double & thetaObj); + /// Return objective value (without any ClpModel offset) (model may be NULL) + virtual double objectiveValue(const ClpSimplex * model, const double * solution) const ; + virtual void resize(int newNumberColumns) ; + /// Delete columns in objective + virtual void deleteSome(int numberToDelete, const int * which) ; + /// Scale objective + virtual void reallyScale(const double * columnScale) ; + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char * which); + + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpQuadraticObjective(); + + /// Constructor from objective + ClpQuadraticObjective(const double * linearObjective, int numberColumns, + const CoinBigIndex * start, + const int * column, const double * element, + int numberExtendedColumns_ = -1); + + /** Copy constructor . + If type is -1 then make sure half symmetric, + if +1 then make sure full + */ + ClpQuadraticObjective(const ClpQuadraticObjective & rhs, int type = 0); + /** Subset constructor. Duplicates are allowed + and order is as given. + */ + ClpQuadraticObjective (const ClpQuadraticObjective &rhs, int numberColumns, + const int * whichColumns) ; + + /// Assignment operator + ClpQuadraticObjective & operator=(const ClpQuadraticObjective& rhs); + + /// Destructor + virtual ~ClpQuadraticObjective (); + + /// Clone + virtual ClpObjective * clone() const; + /** Subset clone. Duplicates are allowed + and order is as given. + */ + virtual ClpObjective * subsetClone (int numberColumns, + const int * whichColumns) const; + + /** Load up quadratic objective. This is stored as a CoinPackedMatrix */ + void loadQuadraticObjective(const int numberColumns, + const CoinBigIndex * start, + const int * column, const double * element, + int numberExtendedColumns = -1); + void loadQuadraticObjective ( const CoinPackedMatrix& matrix); + /// Get rid of quadratic objective + void deleteQuadraticObjective(); + //@} + ///@name Gets and sets + //@{ + /// Quadratic objective + inline CoinPackedMatrix * quadraticObjective() const { + return quadraticObjective_; + } + /// Linear objective + inline double * linearObjective() const { + return objective_; + } + /// Length of linear objective which could be bigger + inline int numberExtendedColumns() const { + return numberExtendedColumns_; + } + /// Number of columns in quadratic objective + inline int numberColumns() const { + return numberColumns_; + } + /// If a full or half matrix + inline bool fullMatrix() const { + return fullMatrix_; + } + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Quadratic objective + CoinPackedMatrix * quadraticObjective_; + /// Objective + double * objective_; + /// Gradient + double * gradient_; + /// Useful to have number of columns about + int numberColumns_; + /// Also length of linear objective which could be bigger + int numberExtendedColumns_; + /// True if full symmetric matrix, false if half + bool fullMatrix_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/ClpSimplex.hpp b/thirdparty/linux/include/coin/ClpSimplex.hpp new file mode 100644 index 0000000..bab4506 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpSimplex.hpp @@ -0,0 +1,1797 @@ +/* $Id: ClpSimplex.hpp 2114 2015-02-10 12:12:46Z 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). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplex_H +#define ClpSimplex_H + +#include <iostream> +#include <cfloat> +#include "ClpModel.hpp" +#include "ClpMatrixBase.hpp" +#include "ClpSolve.hpp" +#include "ClpConfig.h" +class ClpDualRowPivot; +class ClpPrimalColumnPivot; +class ClpFactorization; +class CoinIndexedVector; +class ClpNonLinearCost; +class ClpNodeStuff; +class CoinStructuredModel; +class OsiClpSolverInterface; +class CoinWarmStartBasis; +class ClpDisasterHandler; +class ClpConstraint; +/* + May want to use Clp defaults so that with ABC defined but not used + it behaves as Clp (and ABC used will be different than if not defined) + */ +#ifdef ABC_INHERIT +#ifndef CLP_INHERIT_MODE +#define CLP_INHERIT_MODE 1 +#endif +#ifndef ABC_CLP_DEFAULTS +#define ABC_CLP_DEFAULTS 0 +#endif +#else +#undef ABC_CLP_DEFAULTS +#define ABC_CLP_DEFAULTS 1 +#endif +#ifdef CLP_HAS_ABC +#include "AbcCommon.hpp" +class AbcTolerancesEtc; +class AbcSimplex; +#include "CoinAbcCommon.hpp" +#endif +/** This solves LPs using the simplex method + + It inherits from ClpModel and all its arrays are created at + algorithm time. Originally I tried to work with model arrays + but for simplicity of coding I changed to single arrays with + structural variables then row variables. Some coding is still + based on old style and needs cleaning up. + + For a description of algorithms: + + for dual see ClpSimplexDual.hpp and at top of ClpSimplexDual.cpp + for primal see ClpSimplexPrimal.hpp and at top of ClpSimplexPrimal.cpp + + There is an algorithm data member. + for primal variations + and - for dual variations + +*/ + +class ClpSimplex : public ClpModel { + friend void ClpSimplexUnitTest(const std::string & mpsDir); + +public: + /** enums for status of various sorts. + First 4 match CoinWarmStartBasis, + isFixed means fixed at lower bound and out of basis + */ + enum Status { + isFree = 0x00, + basic = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03, + superBasic = 0x04, + isFixed = 0x05 + }; + // For Dual + enum FakeBound { + noFake = 0x00, + lowerFake = 0x01, + upperFake = 0x02, + bothFake = 0x03 + }; + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpSimplex (bool emptyMessages = false ); + + /** Copy constructor. May scale depending on mode + -1 leave mode as is + 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) + */ + ClpSimplex(const ClpSimplex & rhs, int scalingMode = -1); + /** Copy constructor from model. May scale depending on mode + -1 leave mode as is + 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) + */ + ClpSimplex(const ClpModel & rhs, int scalingMode = -1); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + Can optionally modify rhs to take into account variables NOT in list + in this case duplicates are not allowed (also see getbackSolution) + */ + ClpSimplex (const ClpModel * wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns, + bool dropNames = true, bool dropIntegers = true, + bool fixOthers = false); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + Can optionally modify rhs to take into account variables NOT in list + in this case duplicates are not allowed (also see getbackSolution) + */ + ClpSimplex (const ClpSimplex * wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns, + bool dropNames = true, bool dropIntegers = true, + bool fixOthers = false); + /** This constructor modifies original ClpSimplex and stores + original stuff in created ClpSimplex. It is only to be used in + conjunction with originalModel */ + ClpSimplex (ClpSimplex * wholeModel, + int numberColumns, const int * whichColumns); + /** This copies back stuff from miniModel and then deletes miniModel. + Only to be used with mini constructor */ + void originalModel(ClpSimplex * miniModel); + inline int abcState() const + { return abcState_;} + inline void setAbcState(int state) + { abcState_=state;} +#ifdef ABC_INHERIT + inline AbcSimplex * abcSimplex() const + { return abcSimplex_;} + inline void setAbcSimplex(AbcSimplex * simplex) + { abcSimplex_=simplex;} + /// Returns 0 if dual can be skipped + int doAbcDual(); + /// Returns 0 if primal can be skipped + int doAbcPrimal(int ifValuesPass); +#endif + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + void setPersistenceFlag(int value); + /// Save a copy of model with certain state - normally without cuts + void makeBaseModel(); + /// Switch off base model + void deleteBaseModel(); + /// See if we have base model + inline ClpSimplex * baseModel() const { + return baseModel_; + } + /** Reset to base model (just size and arrays needed) + If model NULL use internal copy + */ + void setToBaseModel(ClpSimplex * model = NULL); + /// Assignment operator. This copies the data + ClpSimplex & operator=(const ClpSimplex & rhs); + /// Destructor + ~ClpSimplex ( ); + // Ones below are just ClpModel with some changes + /** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + */ + void loadProblem ( const ClpMatrixBase& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + void loadProblem ( const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + + /** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ + void loadProblem ( const int numcols, const int numrows, + const CoinBigIndex* start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + /// This one is for after presolve to save memory + void loadProblem ( const int numcols, const int numrows, + const CoinBigIndex* start, const int* index, + const double* value, const int * length, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + const double * rowObjective = NULL); + /** This loads a model from a coinModel object - returns number of errors. + If keepSolution true and size is same as current then + keeps current status and solution + */ + int loadProblem ( CoinModel & modelObject, bool keepSolution = false); + /// Read an mps file from the given filename + int readMps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + /// Read GMPL files from the given filenames + int readGMPL(const char *filename, const char * dataName, + bool keepNames = false); + /// Read file in LP format from file with name filename. + /// See class CoinLpIO for description of this format. + int readLp(const char *filename, const double epsilon = 1e-5); + /** Borrow model. This is so we dont have to copy large amounts + of data around. It assumes a derived class wants to overwrite + an empty model with a real one - while it does an algorithm. + This is same as ClpModel one, but sets scaling on etc. */ + void borrowModel(ClpModel & otherModel); + void borrowModel(ClpSimplex & otherModel); + /// Pass in Event handler (cloned and deleted at end) + void passInEventHandler(const ClpEventHandler * eventHandler); + /// Puts solution back into small model + void getbackSolution(const ClpSimplex & smallModel, const int * whichRow, const int * whichColumn); + /** Load nonlinear part of problem from AMPL info + Returns 0 if linear + 1 if quadratic objective + 2 if quadratic constraints + 3 if nonlinear objective + 4 if nonlinear constraints + -1 on failure + */ + int loadNonLinear(void * info, int & numberConstraints, + ClpConstraint ** & constraints); +#ifdef ABC_INHERIT + /// Loads tolerances etc + void loadTolerancesEtc(const AbcTolerancesEtc & data); + /// Unloads tolerances etc + void unloadTolerancesEtc(AbcTolerancesEtc & data); +#endif + //@} + + /**@name Functions most useful to user */ + //@{ + /** General solve algorithm which can do presolve. + See ClpSolve.hpp for options + */ + int initialSolve(ClpSolve & options); + /// Default initial solve + int initialSolve(); + /// Dual initial solve + int initialDualSolve(); + /// Primal initial solve + int initialPrimalSolve(); + /// Barrier initial solve + int initialBarrierSolve(); + /// Barrier initial solve, not to be followed by crossover + int initialBarrierNoCrossSolve(); + /** Dual algorithm - see ClpSimplexDual.hpp for method. + ifValuesPass==2 just does values pass and then stops. + + startFinishOptions - bits + 1 - do not delete work areas and factorization at end + 2 - use old factorization if same number of rows + 4 - skip as much initialization of work areas as possible + (based on whatsChanged in clpmodel.hpp) ** work in progress + maybe other bits later + */ + int dual(int ifValuesPass = 0, int startFinishOptions = 0); + // If using Debug + int dualDebug(int ifValuesPass = 0, int startFinishOptions = 0); + /** Primal algorithm - see ClpSimplexPrimal.hpp for method. + ifValuesPass==2 just does values pass and then stops. + + startFinishOptions - bits + 1 - do not delete work areas and factorization at end + 2 - use old factorization if same number of rows + 4 - skip as much initialization of work areas as possible + (based on whatsChanged in clpmodel.hpp) ** work in progress + maybe other bits later + */ + int primal(int ifValuesPass = 0, int startFinishOptions = 0); + /** Solves nonlinear problem using SLP - may be used as crash + for other algorithms when number of iterations small. + Also exits if all problematical variables are changing + less than deltaTolerance + */ + int nonlinearSLP(int numberPasses, double deltaTolerance); + /** Solves problem with nonlinear constraints using SLP - may be used as crash + for other algorithms when number of iterations small. + Also exits if all problematical variables are changing + less than deltaTolerance + */ + int nonlinearSLP(int numberConstraints, ClpConstraint ** constraints, + int numberPasses, double deltaTolerance); + /** Solves using barrier (assumes you have good cholesky factor code). + Does crossover to simplex if asked*/ + int barrier(bool crossover = true); + /** Solves non-linear using reduced gradient. Phase = 0 get feasible, + =1 use solution */ + int reducedGradient(int phase = 0); + /// Solve using structure of model and maybe in parallel + int solve(CoinStructuredModel * model); +#ifdef ABC_INHERIT + /** solvetype 0 for dual, 1 for primal + startup 1 for values pass + interrupt whether to pass across interrupt handler + add 10 to return AbcSimplex + */ + AbcSimplex * dealWithAbc(int solveType,int startUp,bool interrupt=false); + //void dealWithAbc(int solveType,int startUp,bool interrupt=false); +#endif + /** This loads a model from a CoinStructuredModel object - returns number of errors. + If originalOrder then keep to order stored in blocks, + otherwise first column/rows correspond to first block - etc. + If keepSolution true and size is same as current then + keeps current status and solution + */ + int loadProblem ( CoinStructuredModel & modelObject, + bool originalOrder = true, bool keepSolution = false); + /** + When scaling is on it is possible that the scaled problem + is feasible but the unscaled is not. Clp returns a secondary + status code to that effect. This option allows for a cleanup. + If you use it I would suggest 1. + This only affects actions when scaled optimal + 0 - no action + 1 - clean up using dual if primal infeasibility + 2 - clean up using dual if dual infeasibility + 3 - clean up using dual if primal or dual infeasibility + 11,12,13 - as 1,2,3 but use primal + + return code as dual/primal + */ + int cleanup(int cleanupScaling); + /** Dual ranging. + This computes increase/decrease in cost for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + For non-basic variables the information is trivial to compute and the change in cost is just minus the + reduced cost and the sequence number will be that of the non-basic variables. + For basic variables a ratio test is between the reduced costs for non-basic variables + and the row of the tableau corresponding to the basic variable. + The increase/decrease value is always >= 0.0 + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + If valueIncrease/Decrease not NULL (both must be NULL or both non NULL) then these are filled with + the value of variable if such a change in cost were made (the existing bounds are ignored) + + Returns non-zero if infeasible unbounded etc + */ + int dualRanging(int numberCheck, const int * which, + double * costIncrease, int * sequenceIncrease, + double * costDecrease, int * sequenceDecrease, + double * valueIncrease = NULL, double * valueDecrease = NULL); + /** Primal ranging. + This computes increase/decrease in value for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + This should only be used for non-basic variabls as otherwise information is pretty useless + For basic variables the sequence number will be that of the basic variables. + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + Returns non-zero if infeasible unbounded etc + */ + int primalRanging(int numberCheck, const int * which, + double * valueIncrease, int * sequenceIncrease, + double * valueDecrease, int * sequenceDecrease); + /** + Modifies coefficients etc and if necessary pivots in and out. + All at same status will be done (basis may go singular). + User can tell which others have been done (i.e. if status matches). + If called from outside will change status and return 0. + If called from event handler returns non-zero if user has to take action. + indices>=numberColumns are slacks (obviously no coefficients) + status array is (char) Status enum + */ + int modifyCoefficientsAndPivot(int number, + const int * which, + const CoinBigIndex * start, + const int * row, + const double * newCoefficient, + const unsigned char * newStatus=NULL, + const double * newLower=NULL, + const double * newUpper=NULL, + const double * newObjective=NULL); + /** Take out duplicate rows (includes scaled rows and intersections). + On exit whichRows has rows to delete - return code is number can be deleted + or -1 if would be infeasible. + If tolerance is -1.0 use primalTolerance for equality rows and infeasibility + If cleanUp not zero then spend more time trying to leave more stable row + and make row bounds exact multiple of cleanUp if close enough + */ + int outDuplicateRows(int numberLook,int * whichRows, bool noOverlaps=false, double tolerance=-1.0, + double cleanUp=0.0); + /** Try simple crash like techniques to get closer to primal feasibility + returns final sum of infeasibilities */ + double moveTowardsPrimalFeasible(); + /** Try simple crash like techniques to remove super basic slacks + but only if > threshold */ + void removeSuperBasicSlacks(int threshold=0); + /** Mini presolve (faster) + Char arrays must be numberRows and numberColumns long + on entry second part must be filled in as follows - + 0 - possible + >0 - take out and do something (depending on value - TBD) + -1 row/column can't vanish but can have entries removed/changed + -2 don't touch at all + on exit <=0 ones will be in presolved problem + struct will be created and will be long enough + (information on length etc in first entry) + user must delete struct + */ + ClpSimplex * miniPresolve(char * rowType, char * columnType,void ** info); + /// After mini presolve + void miniPostsolve(const ClpSimplex * presolvedModel,void * info); + /// mini presolve and solve + void miniSolve(char * rowType, char *columnType,int algorithm, int startUp); + /** Write the basis in MPS format to the specified file. + If writeValues true writes values of structurals + (and adds VALUES to end of NAME card) + + Row and column names may be null. + formatType is + <ul> + <li> 0 - normal + <li> 1 - extra accuracy + <li> 2 - IEEE hex (later) + </ul> + + Returns non-zero on I/O error + */ + int writeBasis(const char *filename, + bool writeValues = false, + int formatType = 0) const; + /** Read a basis from the given filename, + returns -1 on file error, 0 if no values, 1 if values */ + int readBasis(const char *filename); + /// Returns a basis (to be deleted by user) + CoinWarmStartBasis * getBasis() const; + /// Passes in factorization + void setFactorization( ClpFactorization & factorization); + // Swaps factorization + ClpFactorization * swapFactorization( ClpFactorization * factorization); + /// Copies in factorization to existing one + void copyFactorization( ClpFactorization & factorization); + /** Tightens primal bounds to make dual faster. Unless + fixed or doTight>10, bounds are slightly looser than they could be. + This is to make dual go faster and is probably not needed + with a presolve. Returns non-zero if problem infeasible. + + Fudge for branch and bound - put bounds on columns of factor * + largest value (at continuous) - should improve stability + in branch and bound on infeasible branches (0.0 is off) + */ + int tightenPrimalBounds(double factor = 0.0, int doTight = 0, bool tightIntegers = false); + /** Crash - at present just aimed at dual, returns + -2 if dual preferred and crash basis created + -1 if dual preferred and all slack basis preferred + 0 if basis going in was not all slack + 1 if primal preferred and all slack basis preferred + 2 if primal preferred and crash basis created. + + if gap between bounds <="gap" variables can be flipped + ( If pivot -1 then can be made super basic!) + + If "pivot" is + -1 No pivoting - always primal + 0 No pivoting (so will just be choice of algorithm) + 1 Simple pivoting e.g. gub + 2 Mini iterations + */ + int crash(double gap, int pivot); + /// Sets row pivot choice algorithm in dual + void setDualRowPivotAlgorithm(ClpDualRowPivot & choice); + /// Sets column pivot choice algorithm in primal + void setPrimalColumnPivotAlgorithm(ClpPrimalColumnPivot & choice); + /// Create a hotstart point of the optimization process + void markHotStart(void * & saveStuff); + /// Optimize starting from the hotstart + void solveFromHotStart(void * saveStuff); + /// Delete the snapshot + void unmarkHotStart(void * saveStuff); + /** For strong branching. On input lower and upper are new bounds + while on output they are change in objective function values + (>1.0e50 infeasible). + Return code is 0 if nothing interesting, -1 if infeasible both + ways and +1 if infeasible one way (check values to see which one(s)) + Solutions are filled in as well - even down, odd up - also + status and number of iterations + */ + int strongBranching(int numberVariables, const int * variables, + double * newLower, double * newUpper, + double ** outputSolution, + int * outputStatus, int * outputIterations, + bool stopOnFirstInfeasible = true, + bool alwaysFinish = false, + int startFinishOptions = 0); + /// Fathom - 1 if solution + int fathom(void * stuff); + /** Do up to N deep - returns + -1 - no solution nNodes_ valid nodes + >= if solution and that node gives solution + ClpNode array is 2**N long. Values for N and + array are in stuff (nNodes_ also in stuff) */ + int fathomMany(void * stuff); + /// Double checks OK + double doubleCheck(); + /// Starts Fast dual2 + int startFastDual2(ClpNodeStuff * stuff); + /// Like Fast dual + int fastDual2(ClpNodeStuff * stuff); + /// Stops Fast dual2 + void stopFastDual2(ClpNodeStuff * stuff); + /** Deals with crunch aspects + mode 0 - in + 1 - out with solution + 2 - out without solution + returns small model or NULL + */ + ClpSimplex * fastCrunch(ClpNodeStuff * stuff, int mode); + //@} + + /**@name Needed for functionality of OsiSimplexInterface */ + //@{ + /** Pivot in a variable and out a variable. Returns 0 if okay, + 1 if inaccuracy forced re-factorization, -1 if would be singular. + Also updates primal/dual infeasibilities. + Assumes sequenceIn_ and pivotRow_ set and also directionIn and Out. + */ + int pivot(); + + /** Pivot in a variable and choose an outgoing one. Assumes primal + feasible - will not go through a bound. Returns step length in theta + Returns ray in ray_ (or NULL if no pivot) + Return codes as before but -1 means no acceptable pivot + */ + int primalPivotResult(); + + /** Pivot out a variable and choose an incoing one. Assumes dual + feasible - will not go through a reduced cost. + Returns step length in theta + Return codes as before but -1 means no acceptable pivot + */ + int dualPivotResultPart1(); + /** Do actual pivot + state is 0 if need tableau column, 1 if in rowArray_[1] + */ + int pivotResultPart2(int algorithm,int state); + + /** Common bits of coding for dual and primal. Return 0 if okay, + 1 if bad matrix, 2 if very bad factorization + + startFinishOptions - bits + 1 - do not delete work areas and factorization at end + 2 - use old factorization if same number of rows + 4 - skip as much initialization of work areas as possible + (based on whatsChanged in clpmodel.hpp) ** work in progress + maybe other bits later + + */ + int startup(int ifValuesPass, int startFinishOptions = 0); + void finish(int startFinishOptions = 0); + + /** Factorizes and returns true if optimal. Used by user */ + bool statusOfProblem(bool initial = false); + /// If user left factorization frequency then compute + void defaultFactorizationFrequency(); + /// Copy across enabled stuff from one solver to another + void copyEnabledStuff(const ClpSimplex * rhs); + //@} + + /**@name most useful gets and sets */ + //@{ + /// If problem is primal feasible + inline bool primalFeasible() const { + return (numberPrimalInfeasibilities_ == 0); + } + /// If problem is dual feasible + inline bool dualFeasible() const { + return (numberDualInfeasibilities_ == 0); + } + /// factorization + inline ClpFactorization * factorization() const { + return factorization_; + } + /// Sparsity on or off + bool sparseFactorization() const; + void setSparseFactorization(bool value); + /// Factorization frequency + int factorizationFrequency() const; + void setFactorizationFrequency(int value); + /// Dual bound + inline double dualBound() const { + return dualBound_; + } + void setDualBound(double value); + /// Infeasibility cost + inline double infeasibilityCost() const { + return infeasibilityCost_; + } + void setInfeasibilityCost(double value); + /** Amount of print out: + 0 - none + 1 - just final + 2 - just factorizations + 3 - as 2 plus a bit more + 4 - verbose + above that 8,16,32 etc just for selective debug + */ + /** Perturbation: + 50 - switch on perturbation + 100 - auto perturb if takes too long (1.0e-6 largest nonzero) + 101 - we are perturbed + 102 - don't try perturbing again + default is 100 + others are for playing + */ + inline int perturbation() const { + return perturbation_; + } + void setPerturbation(int value); + /// Current (or last) algorithm + inline int algorithm() const { + return algorithm_; + } + /// Set algorithm + inline void setAlgorithm(int value) { + algorithm_ = value; + } + /// Return true if the objective limit test can be relied upon + bool isObjectiveLimitTestValid() const ; + /// Sum of dual infeasibilities + inline double sumDualInfeasibilities() const { + return sumDualInfeasibilities_; + } + inline void setSumDualInfeasibilities(double value) { + sumDualInfeasibilities_ = value; + } + /// Sum of relaxed dual infeasibilities + inline double sumOfRelaxedDualInfeasibilities() const { + return sumOfRelaxedDualInfeasibilities_; + } + inline void setSumOfRelaxedDualInfeasibilities(double value) { + sumOfRelaxedDualInfeasibilities_ = value; + } + /// Number of dual infeasibilities + inline int numberDualInfeasibilities() const { + return numberDualInfeasibilities_; + } + inline void setNumberDualInfeasibilities(int value) { + numberDualInfeasibilities_ = value; + } + /// Number of dual infeasibilities (without free) + inline int numberDualInfeasibilitiesWithoutFree() const { + return numberDualInfeasibilitiesWithoutFree_; + } + /// Sum of primal infeasibilities + inline double sumPrimalInfeasibilities() const { + return sumPrimalInfeasibilities_; + } + inline void setSumPrimalInfeasibilities(double value) { + sumPrimalInfeasibilities_ = value; + } + /// Sum of relaxed primal infeasibilities + inline double sumOfRelaxedPrimalInfeasibilities() const { + return sumOfRelaxedPrimalInfeasibilities_; + } + inline void setSumOfRelaxedPrimalInfeasibilities(double value) { + sumOfRelaxedPrimalInfeasibilities_ = value; + } + /// Number of primal infeasibilities + inline int numberPrimalInfeasibilities() const { + return numberPrimalInfeasibilities_; + } + inline void setNumberPrimalInfeasibilities(int value) { + numberPrimalInfeasibilities_ = value; + } + /** Save model to file, returns 0 if success. This is designed for + use outside algorithms so does not save iterating arrays etc. + It does not save any messaging information. + Does not save scaling values. + It does not know about all types of virtual functions. + */ + int saveModel(const char * fileName); + /** Restore model from file, returns 0 if success, + deletes current model */ + int restoreModel(const char * fileName); + + /** Just check solution (for external use) - sets sum of + infeasibilities etc. + If setToBounds 0 then primal column values not changed + and used to compute primal row activity values. If 1 or 2 + then status used - so all nonbasic variables set to + indicated bound and if any values changed (or ==2) basic values re-computed. + */ + void checkSolution(int setToBounds = 0); + /** Just check solution (for internal use) - sets sum of + infeasibilities etc. */ + void checkSolutionInternal(); + /// Check unscaled primal solution but allow for rounding error + void checkUnscaledSolution(); + /// Useful row length arrays (0,1,2,3,4,5) + inline CoinIndexedVector * rowArray(int index) const { + return rowArray_[index]; + } + /// Useful column length arrays (0,1,2,3,4,5) + inline CoinIndexedVector * columnArray(int index) const { + return columnArray_[index]; + } + //@} + + /******************** End of most useful part **************/ + /**@name Functions less likely to be useful to casual user */ + //@{ + /** Given an existing factorization computes and checks + primal and dual solutions. Uses input arrays for variables at + bounds. Returns feasibility states */ + int getSolution ( const double * rowActivities, + const double * columnActivities); + /** Given an existing factorization computes and checks + primal and dual solutions. Uses current problem arrays for + bounds. Returns feasibility states */ + int getSolution (); + /** Constructs a non linear cost from list of non-linearities (columns only) + First lower of each column is taken as real lower + Last lower is taken as real upper and cost ignored + + Returns nonzero if bad data e.g. lowers not monotonic + */ + int createPiecewiseLinearCosts(const int * starts, + const double * lower, const double * gradient); + /// dual row pivot choice + inline ClpDualRowPivot * dualRowPivot() const { + return dualRowPivot_; + } + /// primal column pivot choice + inline ClpPrimalColumnPivot * primalColumnPivot() const { + return primalColumnPivot_; + } + /// Returns true if model looks OK + inline bool goodAccuracy() const { + return (largestPrimalError_ < 1.0e-7 && largestDualError_ < 1.0e-7); + } + /** Return model - updates any scalars */ + void returnModel(ClpSimplex & otherModel); + /** Factorizes using current basis. + solveType - 1 iterating, 0 initial, -1 external + If 10 added then in primal values pass + Return codes are as from ClpFactorization unless initial factorization + when total number of singularities is returned. + Special case is numberRows_+1 -> all slack basis. + */ + int internalFactorize(int solveType); + /// Save data + ClpDataSave saveData() ; + /// Restore data + void restoreData(ClpDataSave saved); + /// Clean up status + void cleanStatus(); + /// Factorizes using current basis. For external use + int factorize(); + /** Computes duals from scratch. If givenDjs then + allows for nonzero basic djs */ + void computeDuals(double * givenDjs); + /// Computes primals from scratch + void computePrimals ( const double * rowActivities, + const double * columnActivities); + /** Adds multiple of a column into an array */ + void add(double * array, + int column, double multiplier) const; + /** + Unpacks one column of the matrix into indexed array + Uses sequenceIn_ + Also applies scaling if needed + */ + void unpack(CoinIndexedVector * rowArray) const ; + /** + Unpacks one column of the matrix into indexed array + Slack if sequence>= numberColumns + Also applies scaling if needed + */ + void unpack(CoinIndexedVector * rowArray, int sequence) const; + /** + Unpacks one column of the matrix into indexed array + ** as packed vector + Uses sequenceIn_ + Also applies scaling if needed + */ + void unpackPacked(CoinIndexedVector * rowArray) ; + /** + Unpacks one column of the matrix into indexed array + ** as packed vector + Slack if sequence>= numberColumns + Also applies scaling if needed + */ + void unpackPacked(CoinIndexedVector * rowArray, int sequence); +#ifndef CLP_USER_DRIVEN +protected: +#endif + /** + This does basis housekeeping and does values for in/out variables. + Can also decide to re-factorize + */ + int housekeeping(double objectiveChange); + /** This sets largest infeasibility and most infeasible and sum + and number of infeasibilities (Primal) */ + void checkPrimalSolution(const double * rowActivities = NULL, + const double * columnActivies = NULL); + /** This sets largest infeasibility and most infeasible and sum + and number of infeasibilities (Dual) */ + void checkDualSolution(); + /** This sets sum and number of infeasibilities (Dual and Primal) */ + void checkBothSolutions(); + /** If input negative scales objective so maximum <= -value + and returns scale factor used. If positive unscales and also + redoes dual stuff + */ + double scaleObjective(double value); + /// Solve using Dantzig-Wolfe decomposition and maybe in parallel + int solveDW(CoinStructuredModel * model, ClpSolve & options); + /// Solve using Benders decomposition and maybe in parallel + int solveBenders(CoinStructuredModel * model, ClpSolve & options); +public: + /** For advanced use. When doing iterative solves things can get + nasty so on values pass if incoming solution has largest + infeasibility < incomingInfeasibility throw out variables + from basis until largest infeasibility < allowedInfeasibility + or incoming largest infeasibility. + If allowedInfeasibility>= incomingInfeasibility this is + always possible altough you may end up with an all slack basis. + + Defaults are 1.0,10.0 + */ + void setValuesPassAction(double incomingInfeasibility, + double allowedInfeasibility); + /** Get a clean factorization - i.e. throw out singularities + may do more later */ + int cleanFactorization(int ifValuesPass); + //@} + /**@name most useful gets and sets */ + //@{ +public: + /// Initial value for alpha accuracy calculation (-1.0 off) + inline double alphaAccuracy() const { + return alphaAccuracy_; + } + inline void setAlphaAccuracy(double value) { + alphaAccuracy_ = value; + } +public: + /// Objective value + //inline double objectiveValue() const { + //return (objectiveValue_-bestPossibleImprovement_)*optimizationDirection_ - dblParam_[ClpObjOffset]; + //} + /// Set disaster handler + inline void setDisasterHandler(ClpDisasterHandler * handler) { + disasterArea_ = handler; + } + /// Get disaster handler + inline ClpDisasterHandler * disasterHandler() const { + return disasterArea_; + } + /// Large bound value (for complementarity etc) + inline double largeValue() const { + return largeValue_; + } + void setLargeValue( double value) ; + /// Largest error on Ax-b + inline double largestPrimalError() const { + return largestPrimalError_; + } + /// Largest error on basic duals + inline double largestDualError() const { + return largestDualError_; + } + /// Largest error on Ax-b + inline void setLargestPrimalError(double value) { + largestPrimalError_ = value; + } + /// Largest error on basic duals + inline void setLargestDualError(double value) { + largestDualError_ = value; + } + /// Get zero tolerance + inline double zeroTolerance() const { + return zeroTolerance_;/*factorization_->zeroTolerance();*/ + } + /// Set zero tolerance + inline void setZeroTolerance( double value) { + zeroTolerance_ = value; + } + /// Basic variables pivoting on which rows + inline int * pivotVariable() const { + return pivotVariable_; + } + /// If automatic scaling on + inline bool automaticScaling() const { + return automaticScale_ != 0; + } + inline void setAutomaticScaling(bool onOff) { + automaticScale_ = onOff ? 1 : 0; + } + /// Current dual tolerance + inline double currentDualTolerance() const { + return dualTolerance_; + } + inline void setCurrentDualTolerance(double value) { + dualTolerance_ = value; + } + /// Current primal tolerance + inline double currentPrimalTolerance() const { + return primalTolerance_; + } + inline void setCurrentPrimalTolerance(double value) { + primalTolerance_ = value; + } + /// How many iterative refinements to do + inline int numberRefinements() const { + return numberRefinements_; + } + void setNumberRefinements( int value) ; + /// Alpha (pivot element) for use by classes e.g. steepestedge + inline double alpha() const { + return alpha_; + } + inline void setAlpha(double value) { + alpha_ = value; + } + /// Reduced cost of last incoming for use by classes e.g. steepestedge + inline double dualIn() const { + return dualIn_; + } + /// Set reduced cost of last incoming to force error + inline void setDualIn(double value) { + dualIn_ = value; + } + /// Pivot Row for use by classes e.g. steepestedge + inline int pivotRow() const { + return pivotRow_; + } + inline void setPivotRow(int value) { + pivotRow_ = value; + } + /// value of incoming variable (in Dual) + double valueIncomingDual() const; + //@} + +#ifndef CLP_USER_DRIVEN +protected: +#endif + /**@name protected methods */ + //@{ + /** May change basis and then returns number changed. + Computation of solutions may be overriden by given pi and solution + */ + int gutsOfSolution ( double * givenDuals, + const double * givenPrimals, + bool valuesPass = false); + /// Does most of deletion (0 = all, 1 = most, 2 most + factorization) + void gutsOfDelete(int type); + /// Does most of copying + void gutsOfCopy(const ClpSimplex & rhs); + /** puts in format I like (rowLower,rowUpper) also see StandardMatrix + 1 bit does rows (now and columns), (2 bit does column bounds), 4 bit does objective(s). + 8 bit does solution scaling in + 16 bit does rowArray and columnArray indexed vectors + and makes row copy if wanted, also sets columnStart_ etc + Also creates scaling arrays if needed. It does scaling if needed. + 16 also moves solutions etc in to work arrays + On 16 returns false if problem "bad" i.e. matrix or bounds bad + If startFinishOptions is -1 then called by user in getSolution + so do arrays but keep pivotVariable_ + */ + bool createRim(int what, bool makeRowCopy = false, int startFinishOptions = 0); + /// Does rows and columns + void createRim1(bool initial); + /// Does objective + void createRim4(bool initial); + /// Does rows and columns and objective + void createRim5(bool initial); + /** releases above arrays and does solution scaling out. May also + get rid of factorization data - + 0 get rid of nothing, 1 get rid of arrays, 2 also factorization + */ + void deleteRim(int getRidOfFactorizationData = 2); + /// Sanity check on input rim data (after scaling) - returns true if okay + bool sanityCheck(); + //@} +public: + /**@name public methods */ + //@{ + /** Return row or column sections - not as much needed as it + once was. These just map into single arrays */ + inline double * solutionRegion(int section) const { + if (!section) return rowActivityWork_; + else return columnActivityWork_; + } + inline double * djRegion(int section) const { + if (!section) return rowReducedCost_; + else return reducedCostWork_; + } + inline double * lowerRegion(int section) const { + if (!section) return rowLowerWork_; + else return columnLowerWork_; + } + inline double * upperRegion(int section) const { + if (!section) return rowUpperWork_; + else return columnUpperWork_; + } + inline double * costRegion(int section) const { + if (!section) return rowObjectiveWork_; + else return objectiveWork_; + } + /// Return region as single array + inline double * solutionRegion() const { + return solution_; + } + inline double * djRegion() const { + return dj_; + } + inline double * lowerRegion() const { + return lower_; + } + inline double * upperRegion() const { + return upper_; + } + inline double * costRegion() const { + return cost_; + } + inline Status getStatus(int sequence) const { + return static_cast<Status> (status_[sequence] & 7); + } + inline void setStatus(int sequence, Status newstatus) { + unsigned char & st_byte = status_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | newstatus); + } + /// Start or reset using maximumRows_ and Columns_ - true if change + bool startPermanentArrays(); + /** Normally the first factorization does sparse coding because + the factorization could be singular. This allows initial dense + factorization when it is known to be safe + */ + void setInitialDenseFactorization(bool onOff); + bool initialDenseFactorization() const; + /** Return sequence In or Out */ + inline int sequenceIn() const { + return sequenceIn_; + } + inline int sequenceOut() const { + return sequenceOut_; + } + /** Set sequenceIn or Out */ + inline void setSequenceIn(int sequence) { + sequenceIn_ = sequence; + } + inline void setSequenceOut(int sequence) { + sequenceOut_ = sequence; + } + /** Return direction In or Out */ + inline int directionIn() const { + return directionIn_; + } + inline int directionOut() const { + return directionOut_; + } + /** Set directionIn or Out */ + inline void setDirectionIn(int direction) { + directionIn_ = direction; + } + inline void setDirectionOut(int direction) { + directionOut_ = direction; + } + /// Value of Out variable + inline double valueOut() const { + return valueOut_; + } + /// Set value of out variable + inline void setValueOut(double value) { + valueOut_ = value; + } + /// Dual value of Out variable + inline double dualOut() const { + return dualOut_; + } + /// Set dual value of out variable + inline void setDualOut(double value) { + dualOut_ = value; + } + /// Set lower of out variable + inline void setLowerOut(double value) { + lowerOut_ = value; + } + /// Set upper of out variable + inline void setUpperOut(double value) { + upperOut_ = value; + } + /// Set theta of out variable + inline void setTheta(double value) { + theta_ = value; + } + /// Returns 1 if sequence indicates column + inline int isColumn(int sequence) const { + return sequence < numberColumns_ ? 1 : 0; + } + /// Returns sequence number within section + inline int sequenceWithin(int sequence) const { + return sequence < numberColumns_ ? sequence : sequence - numberColumns_; + } + /// Return row or column values + inline double solution(int sequence) { + return solution_[sequence]; + } + /// Return address of row or column values + inline double & solutionAddress(int sequence) { + return solution_[sequence]; + } + inline double reducedCost(int sequence) { + return dj_[sequence]; + } + inline double & reducedCostAddress(int sequence) { + return dj_[sequence]; + } + inline double lower(int sequence) { + return lower_[sequence]; + } + /// Return address of row or column lower bound + inline double & lowerAddress(int sequence) { + return lower_[sequence]; + } + inline double upper(int sequence) { + return upper_[sequence]; + } + /// Return address of row or column upper bound + inline double & upperAddress(int sequence) { + return upper_[sequence]; + } + inline double cost(int sequence) { + return cost_[sequence]; + } + /// Return address of row or column cost + inline double & costAddress(int sequence) { + return cost_[sequence]; + } + /// Return original lower bound + inline double originalLower(int iSequence) const { + if (iSequence < numberColumns_) return columnLower_[iSequence]; + else + return rowLower_[iSequence-numberColumns_]; + } + /// Return original lower bound + inline double originalUpper(int iSequence) const { + if (iSequence < numberColumns_) return columnUpper_[iSequence]; + else + return rowUpper_[iSequence-numberColumns_]; + } + /// Theta (pivot change) + inline double theta() const { + return theta_; + } + /** Best possible improvement using djs (primal) or + obj change by flipping bounds to make dual feasible (dual) */ + inline double bestPossibleImprovement() const { + return bestPossibleImprovement_; + } + /// Return pointer to details of costs + inline ClpNonLinearCost * nonLinearCost() const { + return nonLinearCost_; + } + /** Return more special options + 1 bit - if presolve says infeasible in ClpSolve return + 2 bit - if presolved problem infeasible return + 4 bit - keep arrays like upper_ around + 8 bit - if factorization kept can still declare optimal at once + 16 bit - if checking replaceColumn accuracy before updating + 32 bit - say optimal if primal feasible! + 64 bit - give up easily in dual (and say infeasible) + 128 bit - no objective, 0-1 and in B&B + 256 bit - in primal from dual or vice versa + 512 bit - alternative use of solveType_ + 1024 bit - don't do row copy of factorization + 2048 bit - perturb in complete fathoming + 4096 bit - try more for complete fathoming + 8192 bit - don't even think of using primal if user asks for dual (and vv) + 16384 bit - in initialSolve so be more flexible + 32768 bit - don't swap algorithms from dual if small infeasibility + 65536 bit - perturb in postsolve cleanup (even if < 10000 rows) + 131072 bit (*3) initial stateDualColumn + 524288 bit - stop when primal feasible + */ + inline int moreSpecialOptions() const { + return moreSpecialOptions_; + } + /** Set more special options + 1 bit - if presolve says infeasible in ClpSolve return + 2 bit - if presolved problem infeasible return + 4 bit - keep arrays like upper_ around + 8 bit - no free or superBasic variables + 16 bit - if checking replaceColumn accuracy before updating + 32 bit - say optimal if primal feasible! + 64 bit - give up easily in dual (and say infeasible) + 128 bit - no objective, 0-1 and in B&B + 256 bit - in primal from dual or vice versa + 512 bit - alternative use of solveType_ + 1024 bit - don't do row copy of factorization + 2048 bit - perturb in complete fathoming + 4096 bit - try more for complete fathoming + 8192 bit - don't even think of using primal if user asks for dual (and vv) + 16384 bit - in initialSolve so be more flexible + 32768 bit - don't swap algorithms from dual if small infeasibility + 65536 bit - perturb in postsolve cleanup (even if < 10000 rows) + 131072 bit (*3) initial stateDualColumn + 524288 bit - stop when primal feasible + 1048576 bit - don't perturb even if long time + 2097152 bit - no primal in fastDual2 if feasible + 4194304 bit - tolerances have been changed by code + 8388608 bit - tolerances are dynamic (at first) + */ + inline void setMoreSpecialOptions(int value) { + moreSpecialOptions_ = value; + } + //@} + /**@name status methods */ + //@{ + inline void setFakeBound(int sequence, FakeBound fakeBound) { + unsigned char & st_byte = status_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~24); + st_byte = static_cast<unsigned char>(st_byte | (fakeBound << 3)); + } + inline FakeBound getFakeBound(int sequence) const { + return static_cast<FakeBound> ((status_[sequence] >> 3) & 3); + } + inline void setRowStatus(int sequence, Status newstatus) { + unsigned char & st_byte = status_[sequence+numberColumns_]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | newstatus); + } + inline Status getRowStatus(int sequence) const { + return static_cast<Status> (status_[sequence+numberColumns_] & 7); + } + inline void setColumnStatus(int sequence, Status newstatus) { + unsigned char & st_byte = status_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & ~7); + st_byte = static_cast<unsigned char>(st_byte | newstatus); + } + inline Status getColumnStatus(int sequence) const { + return static_cast<Status> (status_[sequence] & 7); + } + inline void setPivoted( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] | 32); + } + inline void clearPivoted( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~32); + } + inline bool pivoted(int sequence) const { + return (((status_[sequence] >> 5) & 1) != 0); + } + /// To flag a variable (not inline to allow for column generation) + void setFlagged( int sequence); + inline void clearFlagged( int sequence) { + status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~64); + } + inline bool flagged(int sequence) const { + return ((status_[sequence] & 64) != 0); + } + /// To say row active in primal pivot row choice + inline void setActive( int iRow) { + status_[iRow] = static_cast<unsigned char>(status_[iRow] | 128); + } + inline void clearActive( int iRow) { + status_[iRow] = static_cast<unsigned char>(status_[iRow] & ~128); + } + inline bool active(int iRow) const { + return ((status_[iRow] & 128) != 0); + } + /// To say perturbed + inline void setPerturbed( int iSequence) { + status_[iSequence] = static_cast<unsigned char>(status_[iSequence] | 128); + } + inline void clearPerturbed( int iSequence) { + status_[iSequence] = static_cast<unsigned char>(status_[iSequence] & ~128); + } + inline bool perturbed(int iSequence) const { + return ((status_[iSequence] & 128) != 0); + } + /** Set up status array (can be used by OsiClp). + Also can be used to set up all slack basis */ + void createStatus() ; + /** Sets up all slack basis and resets solution to + as it was after initial load or readMps */ + void allSlackBasis(bool resetSolution = false); + + /// So we know when to be cautious + inline int lastBadIteration() const { + return lastBadIteration_; + } + /// Set so we know when to be cautious + inline void setLastBadIteration(int value) { + lastBadIteration_=value; + } + /// Progress flag - at present 0 bit says artificials out + inline int progressFlag() const { + return (progressFlag_ & 3); + } + /// For dealing with all issues of cycling etc + inline ClpSimplexProgress * progress() + { return &progress_;} + /// Force re-factorization early value + inline int forceFactorization() const { + return forceFactorization_ ; + } + /// Force re-factorization early + inline void forceFactorization(int value) { + forceFactorization_ = value; + } + /// Raw objective value (so always minimize in primal) + inline double rawObjectiveValue() const { + return objectiveValue_; + } + /// Compute objective value from solution and put in objectiveValue_ + void computeObjectiveValue(bool useWorkingSolution = false); + /// Compute minimization objective value from internal solution without perturbation + double computeInternalObjectiveValue(); + /** Infeasibility/unbounded ray (NULL returned if none/wrong) + Up to user to use delete [] on these arrays. */ + double * infeasibilityRay(bool fullRay=false) const; + /** Number of extra rows. These are ones which will be dynamically created + each iteration. This is for GUB but may have other uses. + */ + inline int numberExtraRows() const { + return numberExtraRows_; + } + /** Maximum number of basic variables - can be more than number of rows if GUB + */ + inline int maximumBasic() const { + return maximumBasic_; + } + /// Iteration when we entered dual or primal + inline int baseIteration() const { + return baseIteration_; + } + /// Create C++ lines to get to current state + void generateCpp( FILE * fp, bool defaultFactor = false); + /// Gets clean and emptyish factorization + ClpFactorization * getEmptyFactorization(); + /// May delete or may make clean and emptyish factorization + void setEmptyFactorization(); + /// Move status and solution across + void moveInfo(const ClpSimplex & rhs, bool justStatus = false); + //@} + + ///@name Basis handling + // These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal) + // *** At present only without scaling + // *** Slacks havve -1.0 element (so == row activity) - take care + ///Get a row of the tableau (slack part in slack if not NULL) + void getBInvARow(int row, double* z, double * slack = NULL); + + ///Get a row of the basis inverse + void getBInvRow(int row, double* z); + + ///Get a column of the tableau + void getBInvACol(int col, double* vec); + + ///Get a column of the basis inverse + void getBInvCol(int col, double* vec); + + /** Get basic indices (order of indices corresponds to the + order of elements in a vector retured by getBInvACol() and + getBInvCol()). + */ + void getBasics(int* index); + + //@} + //------------------------------------------------------------------------- + /**@name Changing bounds on variables and constraints */ + //@{ + /** Set an objective function coefficient */ + void setObjectiveCoefficient( int elementIndex, double elementValue ); + /** Set an objective function coefficient */ + inline void setObjCoeff( int elementIndex, double elementValue ) { + setObjectiveCoefficient( elementIndex, elementValue); + } + + /** Set a single column lower bound<br> + Use -DBL_MAX for -infinity. */ + void setColumnLower( int elementIndex, double elementValue ); + + /** Set a single column upper bound<br> + Use DBL_MAX for infinity. */ + void setColumnUpper( int elementIndex, double elementValue ); + + /** Set a single column lower and upper bound */ + void setColumnBounds( int elementIndex, + double lower, double upper ); + + /** Set the bounds on a number of columns simultaneously<br> + The default implementation just invokes setColLower() and + setColUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + void setColumnSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + + /** Set a single column lower bound<br> + Use -DBL_MAX for -infinity. */ + inline void setColLower( int elementIndex, double elementValue ) { + setColumnLower(elementIndex, elementValue); + } + /** Set a single column upper bound<br> + Use DBL_MAX for infinity. */ + inline void setColUpper( int elementIndex, double elementValue ) { + setColumnUpper(elementIndex, elementValue); + } + + /** Set a single column lower and upper bound */ + inline void setColBounds( int elementIndex, + double newlower, double newupper ) { + setColumnBounds(elementIndex, newlower, newupper); + } + + /** Set the bounds on a number of columns simultaneously<br> + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + inline void setColSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList) { + setColumnSetBounds(indexFirst, indexLast, boundList); + } + + /** Set a single row lower bound<br> + Use -DBL_MAX for -infinity. */ + void setRowLower( int elementIndex, double elementValue ); + + /** Set a single row upper bound<br> + Use DBL_MAX for infinity. */ + void setRowUpper( int elementIndex, double elementValue ) ; + + /** Set a single row lower and upper bound */ + void setRowBounds( int elementIndex, + double lower, double upper ) ; + + /** Set the bounds on a number of rows simultaneously<br> + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the constraints + */ + void setRowSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + /// Resizes rim part of model + void resize (int newNumberRows, int newNumberColumns); + + //@} + +////////////////// data ////////////////// +protected: + + /**@name data. Many arrays have a row part and a column part. + There is a single array with both - columns then rows and + then normally two arrays pointing to rows and columns. The + single array is the owner of memory + */ + //@{ + /** Best possible improvement using djs (primal) or + obj change by flipping bounds to make dual feasible (dual) */ + double bestPossibleImprovement_; + /// Zero tolerance + double zeroTolerance_; + /// Sequence of worst (-1 if feasible) + int columnPrimalSequence_; + /// Sequence of worst (-1 if feasible) + int rowPrimalSequence_; + /// "Best" objective value + double bestObjectiveValue_; + /// More special options - see set for details + int moreSpecialOptions_; + /// Iteration when we entered dual or primal + int baseIteration_; + /// Primal tolerance needed to make dual feasible (<largeTolerance) + double primalToleranceToGetOptimal_; + /// Large bound value (for complementarity etc) + double largeValue_; + /// Largest error on Ax-b + double largestPrimalError_; + /// Largest error on basic duals + double largestDualError_; + /// For computing whether to re-factorize + double alphaAccuracy_; + /// Dual bound + double dualBound_; + /// Alpha (pivot element) + double alpha_; + /// Theta (pivot change) + double theta_; + /// Lower Bound on In variable + double lowerIn_; + /// Value of In variable + double valueIn_; + /// Upper Bound on In variable + double upperIn_; + /// Reduced cost of In variable + double dualIn_; + /// Lower Bound on Out variable + double lowerOut_; + /// Value of Out variable + double valueOut_; + /// Upper Bound on Out variable + double upperOut_; + /// Infeasibility (dual) or ? (primal) of Out variable + double dualOut_; + /// Current dual tolerance for algorithm + double dualTolerance_; + /// Current primal tolerance for algorithm + double primalTolerance_; + /// Sum of dual infeasibilities + double sumDualInfeasibilities_; + /// Sum of primal infeasibilities + double sumPrimalInfeasibilities_; + /// Weight assigned to being infeasible in primal + double infeasibilityCost_; + /// Sum of Dual infeasibilities using tolerance based on error in duals + double sumOfRelaxedDualInfeasibilities_; + /// Sum of Primal infeasibilities using tolerance based on error in primals + double sumOfRelaxedPrimalInfeasibilities_; + /// Acceptable pivot value just after factorization + double acceptablePivot_; + /// Minimum primal tolerance + double minimumPrimalTolerance_; + /// Last few infeasibilities +#define CLP_INFEAS_SAVE 5 + double averageInfeasibility_[CLP_INFEAS_SAVE]; + /// Working copy of lower bounds (Owner of arrays below) + double * lower_; + /// Row lower bounds - working copy + double * rowLowerWork_; + /// Column lower bounds - working copy + double * columnLowerWork_; + /// Working copy of upper bounds (Owner of arrays below) + double * upper_; + /// Row upper bounds - working copy + double * rowUpperWork_; + /// Column upper bounds - working copy + double * columnUpperWork_; + /// Working copy of objective (Owner of arrays below) + double * cost_; + /// Row objective - working copy + double * rowObjectiveWork_; + /// Column objective - working copy + double * objectiveWork_; + /// Useful row length arrays + CoinIndexedVector * rowArray_[6]; + /// Useful column length arrays + CoinIndexedVector * columnArray_[6]; + /// Sequence of In variable + int sequenceIn_; + /// Direction of In, 1 going up, -1 going down, 0 not a clude + int directionIn_; + /// Sequence of Out variable + int sequenceOut_; + /// Direction of Out, 1 to upper bound, -1 to lower bound, 0 - superbasic + int directionOut_; + /// Pivot Row + int pivotRow_; + /// Last good iteration (immediately after a re-factorization) + int lastGoodIteration_; + /// Working copy of reduced costs (Owner of arrays below) + double * dj_; + /// Reduced costs of slacks not same as duals (or - duals) + double * rowReducedCost_; + /// Possible scaled reduced costs + double * reducedCostWork_; + /// Working copy of primal solution (Owner of arrays below) + double * solution_; + /// Row activities - working copy + double * rowActivityWork_; + /// Column activities - working copy + double * columnActivityWork_; + /// Number of dual infeasibilities + int numberDualInfeasibilities_; + /// Number of dual infeasibilities (without free) + int numberDualInfeasibilitiesWithoutFree_; + /// Number of primal infeasibilities + int numberPrimalInfeasibilities_; + /// How many iterative refinements to do + int numberRefinements_; + /// dual row pivot choice + ClpDualRowPivot * dualRowPivot_; + /// primal column pivot choice + ClpPrimalColumnPivot * primalColumnPivot_; + /// Basic variables pivoting on which rows + int * pivotVariable_; + /// factorization + ClpFactorization * factorization_; + /// Saved version of solution + double * savedSolution_; + /// Number of times code has tentatively thought optimal + int numberTimesOptimal_; + /// Disaster handler + ClpDisasterHandler * disasterArea_; + /// If change has been made (first attempt at stopping looping) + int changeMade_; + /// Algorithm >0 == Primal, <0 == Dual + int algorithm_; + /** Now for some reliability aids + This forces re-factorization early */ + int forceFactorization_; + /** Perturbation: + -50 to +50 - perturb by this power of ten (-6 sounds good) + 100 - auto perturb if takes too long (1.0e-6 largest nonzero) + 101 - we are perturbed + 102 - don't try perturbing again + default is 100 + */ + int perturbation_; + /// Saved status regions + unsigned char * saveStatus_; + /** Very wasteful way of dealing with infeasibilities in primal. + However it will allow non-linearities and use of dual + analysis. If it doesn't work it can easily be replaced. + */ + ClpNonLinearCost * nonLinearCost_; + /// So we know when to be cautious + int lastBadIteration_; + /// So we know when to open up again + int lastFlaggedIteration_; + /// Can be used for count of fake bounds (dual) or fake costs (primal) + int numberFake_; + /// Can be used for count of changed costs (dual) or changed bounds (primal) + int numberChanged_; + /// Progress flag - at present 0 bit says artificials out, 1 free in + int progressFlag_; + /// First free/super-basic variable (-1 if none) + int firstFree_; + /** Number of extra rows. These are ones which will be dynamically created + each iteration. This is for GUB but may have other uses. + */ + int numberExtraRows_; + /** Maximum number of basic variables - can be more than number of rows if GUB + */ + int maximumBasic_; + /// If may skip final factorize then allow up to this pivots (default 20) + int dontFactorizePivots_; + /** For advanced use. When doing iterative solves things can get + nasty so on values pass if incoming solution has largest + infeasibility < incomingInfeasibility throw out variables + from basis until largest infeasibility < allowedInfeasibility. + if allowedInfeasibility>= incomingInfeasibility this is + always possible altough you may end up with an all slack basis. + + Defaults are 1.0,10.0 + */ + double incomingInfeasibility_; + double allowedInfeasibility_; + /// Automatic scaling of objective and rhs and bounds + int automaticScale_; + /// Maximum perturbation array size (take out when code rewritten) + int maximumPerturbationSize_; + /// Perturbation array (maximumPerturbationSize_) + double * perturbationArray_; + /// A copy of model with certain state - normally without cuts + ClpSimplex * baseModel_; + /// For dealing with all issues of cycling etc + ClpSimplexProgress progress_; +#ifdef ABC_INHERIT + AbcSimplex * abcSimplex_; +#define CLP_ABC_WANTED 1 +#define CLP_ABC_WANTED_PARALLEL 2 +#define CLP_ABC_FULL_DONE 8 + // bits 256,512,1024 for crash +#endif +#define CLP_ABC_BEEN_FEASIBLE 65536 + int abcState_; + /// Number of degenerate pivots since last perturbed + int numberDegeneratePivots_; +public: + /// Spare int array for passing information [0]!=0 switches on + mutable int spareIntArray_[4]; + /// Spare double array for passing information [0]!=0 switches on + mutable double spareDoubleArray_[4]; +protected: + /// Allow OsiClp certain perks + friend class OsiClpSolverInterface; + /// And OsiCLP + friend class OsiCLPSolverInterface; + //@} +}; +//############################################################################# +/** A function that tests the methods in the ClpSimplex class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. + + It also does some testing of ClpFactorization class + */ +void +ClpSimplexUnitTest(const std::string & mpsDir); + +// For Devex stuff +#define DEVEX_TRY_NORM 1.0e-4 +#define DEVEX_ADD_ONE 1.0 +#if defined(ABC_INHERIT) || defined(CBC_THREAD) || defined(THREADS_IN_ANALYZE) +// Use pthreads +#include <pthread.h> +typedef struct { + double result; + //const CoinIndexedVector * constVector; // can get rid of + //CoinIndexedVector * vectors[2]; // can get rid of + void * extraInfo; + void * extraInfo2; + int status; + int stuff[4]; +} CoinThreadInfo; +class CoinPthreadStuff { +public: + /**@name Constructors and destructor and copy */ + //@{ + /** Main constructor + */ + CoinPthreadStuff (int numberThreads=0, + void * parallelManager(void * stuff)=NULL); + /// Assignment operator. This copies the data + CoinPthreadStuff & operator=(const CoinPthreadStuff & rhs); + /// Destructor + ~CoinPthreadStuff ( ); + /// set stop start + inline void setStopStart(int value) + { stopStart_=value;} +#ifndef NUMBER_THREADS +#define NUMBER_THREADS 8 +#endif + // For waking up thread + inline pthread_mutex_t * mutexPointer(int which,int thread=0) + { return mutex_+which+3*thread;} +#ifdef PTHREAD_BARRIER_SERIAL_THREAD + inline pthread_barrier_t * barrierPointer() + { return &barrier_;} +#endif + inline int whichLocked(int thread=0) const + { return locked_[thread];} + inline CoinThreadInfo * threadInfoPointer(int thread=0) + { return threadInfo_+thread;} + void startParallelTask(int type,int iThread,void * info=NULL); + int waitParallelTask(int type, int & iThread,bool allowIdle); + void waitAllTasks(); + /// so thread can find out which one it is + int whichThread() const; + void sayIdle(int iThread); + //void startThreads(int numberThreads); + //void stopThreads(); + // For waking up thread + pthread_mutex_t mutex_[3*(NUMBER_THREADS+1)]; +#ifdef PTHREAD_BARRIER_SERIAL_THREAD + pthread_barrier_t barrier_; +#endif + CoinThreadInfo threadInfo_[NUMBER_THREADS+1]; + pthread_t abcThread_[NUMBER_THREADS+1]; + int locked_[NUMBER_THREADS+1]; + int stopStart_; + int numberThreads_; +}; +void * clp_parallelManager(void * stuff); +#endif +#endif diff --git a/thirdparty/linux/include/coin/ClpSimplexDual.hpp b/thirdparty/linux/include/coin/ClpSimplexDual.hpp new file mode 100644 index 0000000..77cc577 --- /dev/null +++ b/thirdparty/linux/include/coin/ClpSimplexDual.hpp @@ -0,0 +1,300 @@ +/* $Id: ClpSimplexDual.hpp 1761 2011-07-06 16:06:24Z 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). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexDual_H +#define ClpSimplexDual_H + +#include "ClpSimplex.hpp" + +/** This solves LPs using the dual simplex method + + It inherits from ClpSimplex. It has no data of its own and + is never created - only cast from a ClpSimplex object at algorithm time. + +*/ + +class ClpSimplexDual : public ClpSimplex { + +public: + + /**@name Description of algorithm */ + //@{ + /** Dual algorithm + + Method + + It tries to be a single phase approach with a weight of 1.0 being + given to getting optimal and a weight of updatedDualBound_ being + given to getting dual feasible. In this version I have used the + idea that this weight can be thought of as a fake bound. If the + distance between the lower and upper bounds on a variable is less + than the feasibility weight then we are always better off flipping + to other bound to make dual feasible. If the distance is greater + then we make up a fake bound updatedDualBound_ away from one bound. + If we end up optimal or primal infeasible, we check to see if + bounds okay. If so we have finished, if not we increase updatedDualBound_ + and continue (after checking if unbounded). I am undecided about + free variables - there is coding but I am not sure about it. At + present I put them in basis anyway. + + The code is designed to take advantage of sparsity so arrays are + seldom zeroed out from scratch or gone over in their entirety. + The only exception is a full scan to find outgoing variable for + Dantzig row choice. For steepest edge we keep an updated list + of infeasibilities (actually squares). + On easy problems we don't need full scan - just + pick first reasonable. + + One problem is how to tackle degeneracy and accuracy. At present + I am using the modification of costs which I put in OSL and some + of what I think is the dual analog of Gill et al. + I am still not sure of the exact details. + + The flow of dual is three while loops as follows: + + while (not finished) { + + while (not clean solution) { + + Factorize and/or clean up solution by flipping variables so + dual feasible. If looks finished check fake dual bounds. + Repeat until status is iterating (-1) or finished (0,1,2) + + } + + while (status==-1) { + + Iterate until no pivot in or out or time to re-factorize. + + Flow is: + + choose pivot row (outgoing variable). if none then + we are primal feasible so looks as if done but we need to + break and check bounds etc. + + Get pivot row in tableau + + Choose incoming column. If we don't find one then we look + primal infeasible so break and check bounds etc. (Also the + pivot tolerance is larger after any iterations so that may be + reason) + + If we do find incoming column, we may have to adjust costs to + keep going forwards (anti-degeneracy). Check pivot will be stable + and if unstable throw away iteration and break to re-factorize. + If minor error re-factorize after iteration. + + Update everything (this may involve flipping variables to stay + dual feasible. + + } + + } + + TODO's (or maybe not) + + At present we never check we are going forwards. I overdid that in + OSL so will try and make a last resort. + + Needs partial scan pivot out option. + + May need other anti-degeneracy measures, especially if we try and use + loose tolerances as a way to solve in fewer iterations. + + I like idea of dynamic scaling. This gives opportunity to decouple + different implications of scaling for accuracy, iteration count and + feasibility tolerance. + + for use of exotic parameter startFinishoptions see Clpsimplex.hpp + */ + + int dual(int ifValuesPass, int startFinishOptions = 0); + /** For strong branching. On input lower and upper are new bounds + while on output they are change in objective function values + (>1.0e50 infeasible). + Return code is 0 if nothing interesting, -1 if infeasible both + ways and +1 if infeasible one way (check values to see which one(s)) + Solutions are filled in as well - even down, odd up - also + status and number of iterations + */ + int strongBranching(int numberVariables, const int * variables, + double * newLower, double * newUpper, + double ** outputSolution, + int * outputStatus, int * outputIterations, + bool stopOnFirstInfeasible = true, + bool alwaysFinish = false, + int startFinishOptions = 0); + /// This does first part of StrongBranching + ClpFactorization * setupForStrongBranching(char * arrays, int numberRows, + int numberColumns, bool solveLp = false); + /// This cleans up after strong branching + void cleanupAfterStrongBranching(ClpFactorization * factorization); + //@} + + /**@name Functions used in dual */ + //@{ + /** This has the flow between re-factorizations + Broken out for clarity and will be used by strong branching + + Reasons to come out: + -1 iterations etc + -2 inaccuracy + -3 slight inaccuracy (and done iterations) + +0 looks optimal (might be unbounded - but we will investigate) + +1 looks infeasible + +3 max iterations + + If givenPi not NULL then in values pass + */ + int whileIterating(double * & givenPi, int ifValuesPass); + /** The duals are updated by the given arrays. + Returns number of infeasibilities. + After rowArray and columnArray will just have those which + have been flipped. + Variables may be flipped between bounds to stay dual feasible. + The output vector has movement of primal + solution (row length array) */ + int updateDualsInDual(CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray, + CoinIndexedVector * outputArray, + double theta, + double & objectiveChange, + bool fullRecompute); + /** The duals are updated by the given arrays. + This is in values pass - so no changes to primal is made + */ + void updateDualsInValuesPass(CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray, + double theta); + /** While updateDualsInDual sees what effect is of flip + this does actual flipping. + */ + void flipBounds(CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray); + /** + Row array has row part of pivot row + Column array has column part. + This chooses pivot column. + Spare arrays are used to save pivots which will go infeasible + We will check for basic so spare array will never overflow. + If necessary will modify costs + For speed, we may need to go to a bucket approach when many + variables are being flipped. + Returns best possible pivot value + */ + double dualColumn(CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray, + CoinIndexedVector * spareArray, + CoinIndexedVector * spareArray2, + double accpetablePivot, + CoinBigIndex * dubiousWeights); + /// Does first bit of dualColumn + int dualColumn0(const CoinIndexedVector * rowArray, + const CoinIndexedVector * columnArray, + CoinIndexedVector * spareArray, + double acceptablePivot, + double & upperReturn, double &bestReturn, double & badFree); + /** + Row array has row part of pivot row + Column array has column part. + This sees what is best thing to do in dual values pass + if sequenceIn==sequenceOut can change dual on chosen row and leave variable in basis + */ + void checkPossibleValuesMove(CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray, + double acceptablePivot); + /** + Row array has row part of pivot row + Column array has column part. + This sees what is best thing to do in branch and bound cleanup + If sequenceIn_ < 0 then can't do anything + */ + void checkPossibleCleanup(CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray, + double acceptablePivot); + /** + This sees if we can move duals in dual values pass. + This is done before any pivoting + */ + void doEasyOnesInValuesPass(double * givenReducedCosts); + /** + Chooses dual pivot row + Would be faster with separate region to scan + and will have this (with square of infeasibility) when steepest + For easy problems we can just choose one of the first rows we look at + + If alreadyChosen >=0 then in values pass and that row has been + selected + */ + void dualRow(int alreadyChosen); + /** Checks if any fake bounds active - if so returns number and modifies + updatedDualBound_ and everything. + Free variables will be left as free + Returns number of bounds changed if >=0 + Returns -1 if not initialize and no effect + Fills in changeVector which can be used to see if unbounded + and cost of change vector + If 2 sets to original (just changed) + */ + int changeBounds(int initialize, CoinIndexedVector * outputArray, + double & changeCost); + /** As changeBounds but just changes new bounds for a single variable. + Returns true if change */ + bool changeBound( int iSequence); + /// Restores bound to original bound + void originalBound(int iSequence); + /** Checks if tentative optimal actually means unbounded in dual + Returns -3 if not, 2 if is unbounded */ + int checkUnbounded(CoinIndexedVector * ray, CoinIndexedVector * spare, + double changeCost); + /** Refactorizes if necessary + Checks if finished. Updates status. + lastCleaned refers to iteration at which some objective/feasibility + cleaning too place. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + */ + void statusOfProblemInDual(int & lastCleaned, int type, + double * givenDjs, ClpDataSave & saveData, + int ifValuesPass); + /** Perturbs problem (method depends on perturbation()) + returns nonzero if should go to dual */ + int perturb(); + /** Fast iterations. Misses out a lot of initialization. + Normally stops on maximum iterations, first re-factorization + or tentative optimum. If looks interesting then continues as + normal. Returns 0 if finished properly, 1 otherwise. + */ + int fastDual(bool alwaysFinish = false); + /** Checks number of variables at fake bounds. This is used by fastDual + so can exit gracefully before end */ + int numberAtFakeBound(); + + /** Pivot in a variable and choose an outgoing one. Assumes dual + feasible - will not go through a reduced cost. Returns step length in theta + Return codes as before but -1 means no acceptable pivot + */ + int pivotResultPart1(); + /** Get next free , -1 if none */ + int nextSuperBasic(); + /** Startup part of dual (may be extended to other algorithms) + returns 0 if good, 1 if bad */ + int startupSolve(int ifValuesPass, double * saveDuals, int startFinishOptions); + void finishSolve(int startFinishOptions); + void gutsOfDual(int ifValuesPass, double * & saveDuals, int initialStatus, + ClpDataSave & saveData); + //int dual2(int ifValuesPass,int startFinishOptions=0); + void resetFakeBounds(int type); + + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/ClpSimplexNonlinear.hpp b/thirdparty/linux/include/coin/ClpSimplexNonlinear.hpp new file mode 100644 index 0000000..6c1088b --- /dev/null +++ b/thirdparty/linux/include/coin/ClpSimplexNonlinear.hpp @@ -0,0 +1,117 @@ +/* $Id: ClpSimplexNonlinear.hpp 2025 2014-03-19 12:49:55Z forrest $ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexNonlinear_H +#define ClpSimplexNonlinear_H + +class ClpNonlinearInfo; +class ClpQuadraticObjective; +class ClpConstraint; + +#include "ClpSimplexPrimal.hpp" + +/** This solves non-linear LPs using the primal simplex method + + It inherits from ClpSimplexPrimal. It has no data of its own and + is never created - only cast from a ClpSimplexPrimal object at algorithm time. + If needed create new class and pass around + +*/ + +class ClpSimplexNonlinear : public ClpSimplexPrimal { + +public: + + /**@name Description of algorithm */ + //@{ + /** Primal algorithms for reduced gradient + At present we have two algorithms: + + */ + /// A reduced gradient method. + int primal(); + /** Primal algorithm for quadratic + Using a semi-trust region approach as for pooling problem + This is in because I have it lying around + */ + int primalSLP(int numberPasses, double deltaTolerance, + int otherOptions=0); + /// May use a cut approach for solving any LP + int primalDualCuts(char * rowsIn, int startUp, int algorithm); + /** Primal algorithm for nonlinear constraints + Using a semi-trust region approach as for pooling problem + This is in because I have it lying around + + */ + int primalSLP(int numberConstraints, ClpConstraint ** constraints, + int numberPasses, double deltaTolerance); + + /** Creates direction vector. note longArray is long enough + for rows and columns. If numberNonBasic 0 then is updated + otherwise mode is ignored and those are used. + Norms are only for those > 1.0e3*dualTolerance + If mode is nonzero then just largest dj */ + void directionVector (CoinIndexedVector * longArray, + CoinIndexedVector * spare1, CoinIndexedVector * spare2, + int mode, + double & normFlagged, double & normUnflagged, + int & numberNonBasic); + /// Main part. + int whileIterating (int & pivotMode); + /** + longArray has direction + pivotMode - + 0 - use all dual infeasible variables + 1 - largest dj + while >= 10 trying startup phase + Returns 0 - can do normal iteration (basis change) + 1 - no basis change + 2 - if wants singleton + 3 - if time to re-factorize + If sequenceIn_ >=0 then that will be incoming variable + */ + int pivotColumn(CoinIndexedVector * longArray, + CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray, + CoinIndexedVector * spare, + int & pivotMode, + double & solutionError, + double * array1); + /** Refactorizes if necessary + Checks if finished. Updates status. + lastCleaned refers to iteration at which some objective/feasibility + cleaning too place. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + */ + void statusOfProblemInPrimal(int & lastCleaned, int type, + ClpSimplexProgress * progress, + bool doFactorization, + double & bestObjectiveWhenFlagged); + /** Do last half of an iteration. + Return codes + Reasons to come out normal mode + -1 normal + -2 factorize now - good iteration + -3 slight inaccuracy - refactorize - iteration done + -4 inaccuracy - refactorize - no iteration + -5 something flagged - go round again + +2 looks unbounded + +3 max iterations (iteration done) + + */ + int pivotNonlinearResult(); + //@} + +}; +#endif + diff --git a/thirdparty/linux/include/coin/ClpSimplexOther.hpp b/thirdparty/linux/include/coin/ClpSimplexOther.hpp new file mode 100644 index 0000000..c5014ec --- /dev/null +++ b/thirdparty/linux/include/coin/ClpSimplexOther.hpp @@ -0,0 +1,277 @@ +/* $Id: ClpSimplexOther.hpp 2070 2014-11-18 11:12:54Z forrest $ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexOther_H +#define ClpSimplexOther_H + +#include "ClpSimplex.hpp" + +/** This is for Simplex stuff which is neither dual nor primal + + It inherits from ClpSimplex. It has no data of its own and + is never created - only cast from a ClpSimplex object at algorithm time. + +*/ + +class ClpSimplexOther : public ClpSimplex { + +public: + + /**@name Methods */ + //@{ + /** Dual ranging. + This computes increase/decrease in cost for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + For non-basic variables the information is trivial to compute and the change in cost is just minus the + reduced cost and the sequence number will be that of the non-basic variables. + For basic variables a ratio test is between the reduced costs for non-basic variables + and the row of the tableau corresponding to the basic variable. + The increase/decrease value is always >= 0.0 + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + If valueIncrease/Decrease not NULL (both must be NULL or both non NULL) then these are filled with + the value of variable if such a change in cost were made (the existing bounds are ignored) + + When here - guaranteed optimal + */ + void dualRanging(int numberCheck, const int * which, + double * costIncrease, int * sequenceIncrease, + double * costDecrease, int * sequenceDecrease, + double * valueIncrease = NULL, double * valueDecrease = NULL); + /** Primal ranging. + This computes increase/decrease in value for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + This should only be used for non-basic variabls as otherwise information is pretty useless + For basic variables the sequence number will be that of the basic variables. + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + When here - guaranteed optimal + */ + void primalRanging(int numberCheck, const int * which, + double * valueIncrease, int * sequenceIncrease, + double * valueDecrease, int * sequenceDecrease); + /** Parametrics + This is an initial slow version. + The code uses current bounds + theta * change (if change array not NULL) + and similarly for objective. + It starts at startingTheta and returns ending theta in endingTheta. + If reportIncrement 0.0 it will report on any movement + If reportIncrement >0.0 it will report at startingTheta+k*reportIncrement. + If it can not reach input endingTheta return code will be 1 for infeasible, + 2 for unbounded, if error on ranges -1, otherwise 0. + Normal report is just theta and objective but + if event handler exists it may do more + On exit endingTheta is maximum reached (can be used for next startingTheta) + */ + int parametrics(double startingTheta, double & endingTheta, double reportIncrement, + const double * changeLowerBound, const double * changeUpperBound, + const double * changeLowerRhs, const double * changeUpperRhs, + const double * changeObjective); + /** Version of parametrics which reads from file + See CbcClpParam.cpp for details of format + Returns -2 if unable to open file */ + int parametrics(const char * dataFile); + /** Parametrics + This is an initial slow version. + The code uses current bounds + theta * change (if change array not NULL) + It starts at startingTheta and returns ending theta in endingTheta. + If it can not reach input endingTheta return code will be 1 for infeasible, + 2 for unbounded, if error on ranges -1, otherwise 0. + Event handler may do more + On exit endingTheta is maximum reached (can be used for next startingTheta) + */ + int parametrics(double startingTheta, double & endingTheta, + const double * changeLowerBound, const double * changeUpperBound, + const double * changeLowerRhs, const double * changeUpperRhs); + int parametricsObj(double startingTheta, double & endingTheta, + const double * changeObjective); + /// Finds best possible pivot + double bestPivot(bool justColumns=false); + typedef struct { + double startingTheta; + double endingTheta; + double maxTheta; + double acceptableMaxTheta; // if this far then within tolerances + double * lowerChange; // full array of lower bound changes + int * lowerList; // list of lower bound changes + double * upperChange; // full array of upper bound changes + int * upperList; // list of upper bound changes + char * markDone; // mark which ones looked at + int * backwardBasic; // from sequence to pivot row + int * lowerActive; + double * lowerGap; + double * lowerCoefficient; + int * upperActive; + double * upperGap; + double * upperCoefficient; + int unscaledChangesOffset; + bool firstIteration; // so can update rhs for accuracy + } parametricsData; + +private: + /** Parametrics - inner loop + This first attempt is when reportIncrement non zero and may + not report endingTheta correctly + If it can not reach input endingTheta return code will be 1 for infeasible, + 2 for unbounded, otherwise 0. + Normal report is just theta and objective but + if event handler exists it may do more + */ + int parametricsLoop(parametricsData & paramData, double reportIncrement, + const double * changeLower, const double * changeUpper, + const double * changeObjective, ClpDataSave & data, + bool canTryQuick); + int parametricsLoop(parametricsData & paramData, + ClpDataSave & data,bool canSkipFactorization=false); + int parametricsObjLoop(parametricsData & paramData, + ClpDataSave & data,bool canSkipFactorization=false); + /** Refactorizes if necessary + Checks if finished. Updates status. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + */ + void statusOfProblemInParametrics(int type, ClpDataSave & saveData); + void statusOfProblemInParametricsObj(int type, ClpDataSave & saveData); + /** This has the flow between re-factorizations + + Reasons to come out: + -1 iterations etc + -2 inaccuracy + -3 slight inaccuracy (and done iterations) + +0 looks optimal (might be unbounded - but we will investigate) + +1 looks infeasible + +3 max iterations + */ + int whileIterating(parametricsData & paramData, double reportIncrement, + const double * changeObjective); + /** Computes next theta and says if objective or bounds (0= bounds, 1 objective, -1 none). + theta is in theta_. + type 1 bounds, 2 objective, 3 both. + */ + int nextTheta(int type, double maxTheta, parametricsData & paramData, + const double * changeObjective); + int whileIteratingObj(parametricsData & paramData); + int nextThetaObj(double maxTheta, parametricsData & paramData); + /// Restores bound to original bound + void originalBound(int iSequence, double theta, const double * changeLower, + const double * changeUpper); + /// Compute new rowLower_ etc (return negative if infeasible - otherwise largest change) + double computeRhsEtc(parametricsData & paramData); + /// Redo lower_ from rowLower_ etc + void redoInternalArrays(); + /** + Row array has row part of pivot row + Column array has column part. + This is used in dual ranging + */ + void checkDualRatios(CoinIndexedVector * rowArray, + CoinIndexedVector * columnArray, + double & costIncrease, int & sequenceIncrease, double & alphaIncrease, + double & costDecrease, int & sequenceDecrease, double & alphaDecrease); + /** + Row array has pivot column + This is used in primal ranging + */ + void checkPrimalRatios(CoinIndexedVector * rowArray, + int direction); + /// Returns new value of whichOther when whichIn enters basis + double primalRanging1(int whichIn, int whichOther); + +public: + /** Write the basis in MPS format to the specified file. + If writeValues true writes values of structurals + (and adds VALUES to end of NAME card) + + Row and column names may be null. + formatType is + <ul> + <li> 0 - normal + <li> 1 - extra accuracy + <li> 2 - IEEE hex (later) + </ul> + + Returns non-zero on I/O error + */ + int writeBasis(const char *filename, + bool writeValues = false, + int formatType = 0) const; + /// Read a basis from the given filename + int readBasis(const char *filename); + /** Creates dual of a problem if looks plausible + (defaults will always create model) + fractionRowRanges is fraction of rows allowed to have ranges + fractionColumnRanges is fraction of columns allowed to have ranges + */ + ClpSimplex * dualOfModel(double fractionRowRanges = 1.0, double fractionColumnRanges = 1.0) const; + /** Restores solution from dualized problem + non-zero return code indicates minor problems + */ + int restoreFromDual(const ClpSimplex * dualProblem, + bool checkAccuracy=false); + /** Sets solution in dualized problem + non-zero return code indicates minor problems + */ + int setInDual(ClpSimplex * dualProblem); + /** Does very cursory presolve. + rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns. + */ + ClpSimplex * crunch(double * rhs, int * whichRows, int * whichColumns, + int & nBound, bool moreBounds = false, bool tightenBounds = false); + /** After very cursory presolve. + rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns. + */ + void afterCrunch(const ClpSimplex & small, + const int * whichRows, const int * whichColumns, + int nBound); + /** Returns gub version of model or NULL + whichRows has to be numberRows + whichColumns has to be numberRows+numberColumns */ + ClpSimplex * gubVersion(int * whichRows, int * whichColumns, + int neededGub, + int factorizationFrequency=50); + /// Sets basis from original + void setGubBasis(ClpSimplex &original,const int * whichRows, + const int * whichColumns); + /// Restores basis to original + void getGubBasis(ClpSimplex &original,const int * whichRows, + const int * whichColumns) const; + /// Quick try at cleaning up duals if postsolve gets wrong + void cleanupAfterPostsolve(); + /** Tightens integer bounds - returns number tightened or -1 if infeasible + */ + int tightenIntegerBounds(double * rhsSpace); + /** Expands out all possible combinations for a knapsack + If buildObj NULL then just computes space needed - returns number elements + On entry numberOutput is maximum allowed, on exit it is number needed or + -1 (as will be number elements) if maximum exceeded. numberOutput will have at + least space to return values which reconstruct input. + Rows returned will be original rows but no entries will be returned for + any rows all of whose entries are in knapsack. So up to user to allow for this. + If reConstruct >=0 then returns number of entrie which make up item "reConstruct" + in expanded knapsack. Values in buildRow and buildElement; + */ + int expandKnapsack(int knapsackRow, int & numberOutput, + double * buildObj, CoinBigIndex * buildStart, + int * buildRow, double * buildElement, int reConstruct = -1) const; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/ClpSimplexPrimal.hpp b/thirdparty/linux/include/coin/ClpSimplexPrimal.hpp new file mode 100644 index 0000000..d78e54e --- /dev/null +++ b/thirdparty/linux/include/coin/ClpSimplexPrimal.hpp @@ -0,0 +1,244 @@ +/* $Id: ClpSimplexPrimal.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// 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). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexPrimal_H +#define ClpSimplexPrimal_H + +#include "ClpSimplex.hpp" + +/** This solves LPs using the primal simplex method + + It inherits from ClpSimplex. It has no data of its own and + is never created - only cast from a ClpSimplex object at algorithm time. + +*/ + +class ClpSimplexPrimal : public ClpSimplex { + +public: + + /**@name Description of algorithm */ + //@{ + /** Primal algorithm + + Method + + It tries to be a single phase approach with a weight of 1.0 being + given to getting optimal and a weight of infeasibilityCost_ being + given to getting primal feasible. In this version I have tried to + be clever in a stupid way. The idea of fake bounds in dual + seems to work so the primal analogue would be that of getting + bounds on reduced costs (by a presolve approach) and using + these for being above or below feasible region. I decided to waste + memory and keep these explicitly. This allows for non-linear + costs! I have not tested non-linear costs but will be glad + to do something if a reasonable example is provided. + + The code is designed to take advantage of sparsity so arrays are + seldom zeroed out from scratch or gone over in their entirety. + The only exception is a full scan to find incoming variable for + Dantzig row choice. For steepest edge we keep an updated list + of dual infeasibilities (actually squares). + On easy problems we don't need full scan - just + pick first reasonable. This method has not been coded. + + One problem is how to tackle degeneracy and accuracy. At present + I am using the modification of costs which I put in OSL and which was + extended by Gill et al. I am still not sure whether we will also + need explicit perturbation. + + The flow of primal is three while loops as follows: + + while (not finished) { + + while (not clean solution) { + + Factorize and/or clean up solution by changing bounds so + primal feasible. If looks finished check fake primal bounds. + Repeat until status is iterating (-1) or finished (0,1,2) + + } + + while (status==-1) { + + Iterate until no pivot in or out or time to re-factorize. + + Flow is: + + choose pivot column (incoming variable). if none then + we are primal feasible so looks as if done but we need to + break and check bounds etc. + + Get pivot column in tableau + + Choose outgoing row. If we don't find one then we look + primal unbounded so break and check bounds etc. (Also the + pivot tolerance is larger after any iterations so that may be + reason) + + If we do find outgoing row, we may have to adjust costs to + keep going forwards (anti-degeneracy). Check pivot will be stable + and if unstable throw away iteration and break to re-factorize. + If minor error re-factorize after iteration. + + Update everything (this may involve changing bounds on + variables to stay primal feasible. + + } + + } + + TODO's (or maybe not) + + At present we never check we are going forwards. I overdid that in + OSL so will try and make a last resort. + + Needs partial scan pivot in option. + + May need other anti-degeneracy measures, especially if we try and use + loose tolerances as a way to solve in fewer iterations. + + I like idea of dynamic scaling. This gives opportunity to decouple + different implications of scaling for accuracy, iteration count and + feasibility tolerance. + + for use of exotic parameter startFinishoptions see Clpsimplex.hpp + */ + + int primal(int ifValuesPass = 0, int startFinishOptions = 0); + //@} + + /**@name For advanced users */ + //@{ + /// Do not change infeasibility cost and always say optimal + void alwaysOptimal(bool onOff); + bool alwaysOptimal() const; + /** Normally outgoing variables can go out to slightly negative + values (but within tolerance) - this is to help stability and + and degeneracy. This can be switched off + */ + void exactOutgoing(bool onOff); + bool exactOutgoing() const; + //@} + + /**@name Functions used in primal */ + //@{ + /** This has the flow between re-factorizations + + Returns a code to say where decision to exit was made + Problem status set to: + + -2 re-factorize + -4 Looks optimal/infeasible + -5 Looks unbounded + +3 max iterations + + valuesOption has original value of valuesPass + */ + int whileIterating(int valuesOption); + + /** Do last half of an iteration. This is split out so people can + force incoming variable. If solveType_ is 2 then this may + re-factorize while normally it would exit to re-factorize. + Return codes + Reasons to come out (normal mode/user mode): + -1 normal + -2 factorize now - good iteration/ NA + -3 slight inaccuracy - refactorize - iteration done/ same but factor done + -4 inaccuracy - refactorize - no iteration/ NA + -5 something flagged - go round again/ pivot not possible + +2 looks unbounded + +3 max iterations (iteration done) + + With solveType_ ==2 this should + Pivot in a variable and choose an outgoing one. Assumes primal + feasible - will not go through a bound. Returns step length in theta + Returns ray in ray_ + */ + int pivotResult(int ifValuesPass = 0); + + + /** The primals are updated by the given array. + Returns number of infeasibilities. + After rowArray will have cost changes for use next iteration + */ + int updatePrimalsInPrimal(CoinIndexedVector * rowArray, + double theta, + double & objectiveChange, + int valuesPass); + /** + Row array has pivot column + This chooses pivot row. + Rhs array is used for distance to next bound (for speed) + For speed, we may need to go to a bucket approach when many + variables go through bounds + If valuesPass non-zero then compute dj for direction + */ + void primalRow(CoinIndexedVector * rowArray, + CoinIndexedVector * rhsArray, + CoinIndexedVector * spareArray, + int valuesPass); + /** + Chooses primal pivot column + updateArray has cost updates (also use pivotRow_ from last iteration) + Would be faster with separate region to scan + and will have this (with square of infeasibility) when steepest + For easy problems we can just choose one of the first columns we look at + */ + void primalColumn(CoinIndexedVector * updateArray, + CoinIndexedVector * spareRow1, + CoinIndexedVector * spareRow2, + CoinIndexedVector * spareColumn1, + CoinIndexedVector * spareColumn2); + + /** Checks if tentative optimal actually means unbounded in primal + Returns -3 if not, 2 if is unbounded */ + int checkUnbounded(CoinIndexedVector * ray, CoinIndexedVector * spare, + double changeCost); + /** Refactorizes if necessary + Checks if finished. Updates status. + lastCleaned refers to iteration at which some objective/feasibility + cleaning too place. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + saveModel is normally NULL but may not be if doing Sprint + */ + void statusOfProblemInPrimal(int & lastCleaned, int type, + ClpSimplexProgress * progress, + bool doFactorization, + int ifValuesPass, + ClpSimplex * saveModel = NULL); + /// Perturbs problem (method depends on perturbation()) + void perturb(int type); + /// Take off effect of perturbation and say whether to try dual + bool unPerturb(); + /// Unflag all variables and return number unflagged + int unflag(); + /** Get next superbasic -1 if none, + Normal type is 1 + If type is 3 then initializes sorted list + if 2 uses list. + */ + int nextSuperBasic(int superBasicType, CoinIndexedVector * columnArray); + + /// Create primal ray + void primalRay(CoinIndexedVector * rowArray); + /// Clears all bits and clears rowArray[1] etc + void clearAll(); + + /// Sort of lexicographic resolve + int lexSolve(); + + //@} +}; +#endif + diff --git a/thirdparty/linux/include/coin/ClpSolve.hpp b/thirdparty/linux/include/coin/ClpSolve.hpp new file mode 100644 index 0000000..280e33d --- /dev/null +++ b/thirdparty/linux/include/coin/ClpSolve.hpp @@ -0,0 +1,446 @@ +/* $Id: ClpSolve.hpp 2078 2015-01-05 12:39:49Z forrest $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSolve_H +#define ClpSolve_H + +/** + This is a very simple class to guide algorithms. It is used to tidy up + passing parameters to initialSolve and maybe for output from that + +*/ + +class ClpSolve { + +public: + + /** enums for solve function */ + enum SolveType { + useDual = 0, + usePrimal, + usePrimalorSprint, + useBarrier, + useBarrierNoCross, + automatic, + tryDantzigWolfe, + tryBenders, + notImplemented + }; + enum PresolveType { + presolveOn = 0, + presolveOff, + presolveNumber, + presolveNumberCost + }; + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpSolve ( ); + /// Constructor when you really know what you are doing + ClpSolve ( SolveType method, PresolveType presolveType, + int numberPasses, int options[6], + int extraInfo[6], int independentOptions[3]); + /// Generates code for above constructor + void generateCpp(FILE * fp); + /// Copy constructor. + ClpSolve(const ClpSolve &); + /// Assignment operator. This copies the data + ClpSolve & operator=(const ClpSolve & rhs); + /// Destructor + ~ClpSolve ( ); + //@} + + /**@name Functions most useful to user */ + //@{ + /** Special options - bits + 0 4 - use crash (default allslack in dual, idiot in primal) + 8 - all slack basis in primal + 2 16 - switch off interrupt handling + 3 32 - do not try and make plus minus one matrix + 64 - do not use sprint even if problem looks good + */ + /** which translation is: + which: + 0 - startup in Dual (nothing if basis exists).: + 0 - no basis + 1 - crash + 2 - use initiative about idiot! but no crash + 1 - startup in Primal (nothing if basis exists): + 0 - use initiative + 1 - use crash + 2 - use idiot and look at further info + 3 - use sprint and look at further info + 4 - use all slack + 5 - use initiative but no idiot + 6 - use initiative but no sprint + 7 - use initiative but no crash + 8 - do allslack or idiot + 9 - do allslack or sprint + 10 - slp before + 11 - no nothing and primal(0) + 2 - interrupt handling - 0 yes, 1 no (for threadsafe) + 3 - whether to make +- 1matrix - 0 yes, 1 no + 4 - for barrier + 0 - dense cholesky + 1 - Wssmp allowing some long columns + 2 - Wssmp not allowing long columns + 3 - Wssmp using KKT + 4 - Using Florida ordering + 8 - bit set to do scaling + 16 - set to be aggressive with gamma/delta? + 32 - Use KKT + 5 - for presolve + 1 - switch off dual stuff + 6 - extra switches + + */ + void setSpecialOption(int which, int value, int extraInfo = -1); + int getSpecialOption(int which) const; + + /// Solve types + void setSolveType(SolveType method, int extraInfo = -1); + SolveType getSolveType(); + + // Presolve types + void setPresolveType(PresolveType amount, int extraInfo = -1); + PresolveType getPresolveType(); + int getPresolvePasses() const; + /// Extra info for idiot (or sprint) + int getExtraInfo(int which) const; + /** Say to return at once if infeasible, + default is to solve */ + void setInfeasibleReturn(bool trueFalse); + inline bool infeasibleReturn() const { + return independentOptions_[0] != 0; + } + /// Whether we want to do dual part of presolve + inline bool doDual() const { + return (independentOptions_[1] & 1) == 0; + } + inline void setDoDual(bool doDual_) { + if (doDual_) independentOptions_[1] &= ~1; + else independentOptions_[1] |= 1; + } + /// Whether we want to do singleton part of presolve + inline bool doSingleton() const { + return (independentOptions_[1] & 2) == 0; + } + inline void setDoSingleton(bool doSingleton_) { + if (doSingleton_) independentOptions_[1] &= ~2; + else independentOptions_[1] |= 2; + } + /// Whether we want to do doubleton part of presolve + inline bool doDoubleton() const { + return (independentOptions_[1] & 4) == 0; + } + inline void setDoDoubleton(bool doDoubleton_) { + if (doDoubleton_) independentOptions_[1] &= ~4; + else independentOptions_[1] |= 4; + } + /// Whether we want to do tripleton part of presolve + inline bool doTripleton() const { + return (independentOptions_[1] & 8) == 0; + } + inline void setDoTripleton(bool doTripleton_) { + if (doTripleton_) independentOptions_[1] &= ~8; + else independentOptions_[1] |= 8; + } + /// Whether we want to do tighten part of presolve + inline bool doTighten() const { + return (independentOptions_[1] & 16) == 0; + } + inline void setDoTighten(bool doTighten_) { + if (doTighten_) independentOptions_[1] &= ~16; + else independentOptions_[1] |= 16; + } + /// Whether we want to do forcing part of presolve + inline bool doForcing() const { + return (independentOptions_[1] & 32) == 0; + } + inline void setDoForcing(bool doForcing_) { + if (doForcing_) independentOptions_[1] &= ~32; + else independentOptions_[1] |= 32; + } + /// Whether we want to do impliedfree part of presolve + inline bool doImpliedFree() const { + return (independentOptions_[1] & 64) == 0; + } + inline void setDoImpliedFree(bool doImpliedfree) { + if (doImpliedfree) independentOptions_[1] &= ~64; + else independentOptions_[1] |= 64; + } + /// Whether we want to do dupcol part of presolve + inline bool doDupcol() const { + return (independentOptions_[1] & 128) == 0; + } + inline void setDoDupcol(bool doDupcol_) { + if (doDupcol_) independentOptions_[1] &= ~128; + else independentOptions_[1] |= 128; + } + /// Whether we want to do duprow part of presolve + inline bool doDuprow() const { + return (independentOptions_[1] & 256) == 0; + } + inline void setDoDuprow(bool doDuprow_) { + if (doDuprow_) independentOptions_[1] &= ~256; + else independentOptions_[1] |= 256; + } + /// Whether we want to do singleton column part of presolve + inline bool doSingletonColumn() const { + return (independentOptions_[1] & 512) == 0; + } + inline void setDoSingletonColumn(bool doSingleton_) { + if (doSingleton_) independentOptions_[1] &= ~512; + else independentOptions_[1] |= 512; + } + /// Whether we want to kill small substitutions + inline bool doKillSmall() const { + return (independentOptions_[1] & 8192) == 0; + } + inline void setDoKillSmall(bool doKill) { + if (doKill) independentOptions_[1] &= ~8192; + else independentOptions_[1] |= 8192; + } + /// Set whole group + inline int presolveActions() const { + return independentOptions_[1] & 0xffff; + } + inline void setPresolveActions(int action) { + independentOptions_[1] = (independentOptions_[1] & 0xffff0000) | (action & 0xffff); + } + /// Largest column for substitution (normally 3) + inline int substitution() const { + return independentOptions_[2]; + } + inline void setSubstitution(int value) { + independentOptions_[2] = value; + } + inline void setIndependentOption(int type,int value) { + independentOptions_[type] = value; + } + inline int independentOption(int type) const { + return independentOptions_[type]; + } + //@} + +////////////////// data ////////////////// +private: + + /**@name data. + */ + //@{ + /// Solve type + SolveType method_; + /// Presolve type + PresolveType presolveType_; + /// Amount of presolve + int numberPasses_; + /// Options - last is switch for OsiClp + int options_[7]; + /// Extra information + int extraInfo_[7]; + /** Extra algorithm dependent options + 0 - if set return from clpsolve if infeasible + 1 - To be copied over to presolve options + 2 - max substitution level + If Dantzig Wolfe/benders 0 is number blocks, 2 is #passes (notional) + */ + int independentOptions_[3]; + //@} +}; + +/// For saving extra information to see if looping. +class ClpSimplexProgress { + +public: + + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpSimplexProgress ( ); + + /// Constructor from model + ClpSimplexProgress ( ClpSimplex * model ); + + /// Copy constructor. + ClpSimplexProgress(const ClpSimplexProgress &); + + /// Assignment operator. This copies the data + ClpSimplexProgress & operator=(const ClpSimplexProgress & rhs); + /// Destructor + ~ClpSimplexProgress ( ); + /// Resets as much as possible + void reset(); + /// Fill from model + void fillFromModel ( ClpSimplex * model ); + + //@} + + /**@name Check progress */ + //@{ + /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, + >=0 if give up and use as problem status + */ + int looping ( ); + /// Start check at beginning of whileIterating + void startCheck(); + /// Returns cycle length in whileIterating + int cycle(int in, int out, int wayIn, int wayOut); + + /// Returns previous objective (if -1) - current if (0) + double lastObjective(int back = 1) const; + /// Set real primal infeasibility and move back + void setInfeasibility(double value); + /// Returns real primal infeasibility (if -1) - current if (0) + double lastInfeasibility(int back = 1) const; + /// Returns number of primal infeasibilities (if -1) - current if (0) + int numberInfeasibilities(int back = 1) const; + /// Modify objective e.g. if dual infeasible in dual + void modifyObjective(double value); + /// Returns previous iteration number (if -1) - current if (0) + int lastIterationNumber(int back = 1) const; + /// clears all iteration numbers (to switch off panic) + void clearIterationNumbers(); + /// Odd state + inline void newOddState() { + oddState_ = - oddState_ - 1; + } + inline void endOddState() { + oddState_ = abs(oddState_); + } + inline void clearOddState() { + oddState_ = 0; + } + inline int oddState() const { + return oddState_; + } + /// number of bad times + inline int badTimes() const { + return numberBadTimes_; + } + inline void clearBadTimes() { + numberBadTimes_ = 0; + } + /// number of really bad times + inline int reallyBadTimes() const { + return numberReallyBadTimes_; + } + inline void incrementReallyBadTimes() { + numberReallyBadTimes_++; + } + /// number of times flagged + inline int timesFlagged() const { + return numberTimesFlagged_; + } + inline void clearTimesFlagged() { + numberTimesFlagged_ = 0; + } + inline void incrementTimesFlagged() { + numberTimesFlagged_++; + } + + //@} + /**@name Data */ +#define CLP_PROGRESS 5 + //#define CLP_PROGRESS_WEIGHT 10 + //@{ + /// Objective values + double objective_[CLP_PROGRESS]; + /// Sum of infeasibilities for algorithm + double infeasibility_[CLP_PROGRESS]; + /// Sum of real primal infeasibilities for primal + double realInfeasibility_[CLP_PROGRESS]; +#ifdef CLP_PROGRESS_WEIGHT + /// Objective values for weights + double objectiveWeight_[CLP_PROGRESS_WEIGHT]; + /// Sum of infeasibilities for algorithm for weights + double infeasibilityWeight_[CLP_PROGRESS_WEIGHT]; + /// Sum of real primal infeasibilities for primal for weights + double realInfeasibilityWeight_[CLP_PROGRESS_WEIGHT]; + /// Drop for weights + double drop_; + /// Best? for weights + double best_; +#endif + /// Initial weight for weights + double initialWeight_; +#define CLP_CYCLE 12 + /// For cycle checking + //double obj_[CLP_CYCLE]; + int in_[CLP_CYCLE]; + int out_[CLP_CYCLE]; + char way_[CLP_CYCLE]; + /// Pointer back to model so we can get information + ClpSimplex * model_; + /// Number of infeasibilities + int numberInfeasibilities_[CLP_PROGRESS]; + /// Iteration number at which occurred + int iterationNumber_[CLP_PROGRESS]; +#ifdef CLP_PROGRESS_WEIGHT + /// Number of infeasibilities for weights + int numberInfeasibilitiesWeight_[CLP_PROGRESS_WEIGHT]; + /// Iteration number at which occurred for weights + int iterationNumberWeight_[CLP_PROGRESS_WEIGHT]; +#endif + /// Number of times checked (so won't stop too early) + int numberTimes_; + /// Number of times it looked like loop + int numberBadTimes_; + /// Number really bad times + int numberReallyBadTimes_; + /// Number of times no iterations as flagged + int numberTimesFlagged_; + /// If things are in an odd state + int oddState_; + //@} +}; + +#include "ClpConfig.h" +#if CLP_HAS_ABC +#include "AbcCommon.hpp" +/// For saving extra information to see if looping. +class AbcSimplexProgress : public ClpSimplexProgress { + +public: + + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + AbcSimplexProgress ( ); + + /// Constructor from model + AbcSimplexProgress ( ClpSimplex * model ); + + /// Copy constructor. + AbcSimplexProgress(const AbcSimplexProgress &); + + /// Assignment operator. This copies the data + AbcSimplexProgress & operator=(const AbcSimplexProgress & rhs); + /// Destructor + ~AbcSimplexProgress ( ); + + //@} + + /**@name Check progress */ + //@{ + /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, + >=0 if give up and use as problem status + */ + int looping ( ); + + //@} + /**@name Data */ + //@} +}; +#endif +#endif diff --git a/thirdparty/linux/include/coin/Clp_C_Interface.h b/thirdparty/linux/include/coin/Clp_C_Interface.h new file mode 100644 index 0000000..b91b2d2 --- /dev/null +++ b/thirdparty/linux/include/coin/Clp_C_Interface.h @@ -0,0 +1,525 @@ +/* $Id: Clp_C_Interface.h 2019 2014-01-31 05:18:01Z stefan $ */ +/* + Copyright (C) 2002, 2003 International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ +#ifndef ClpSimplexC_H +#define ClpSimplexC_H + +/* include all defines and ugly stuff */ +#include "Coin_C_defines.h" + +#if defined (CLP_EXTERN_C) +typedef struct { + ClpSolve options; +} Clp_Solve; +#else +typedef void Clp_Solve; +#endif + +/** This is a first "C" interface to Clp. + It has similarities to the OSL V3 interface + and only has most common functions +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + /**@name Version info + * + * A Clp library has a version number of the form <major>.<minor>.<release>, + * where each of major, minor, and release are nonnegative integers. + * For a checkout of the Clp stable branch, release is 9999. + * For a checkout of the Clp development branch, major, minor, and release are 9999. + */ + /*@{*/ + /** Clp library version number as string. */ + COINLIBAPI const char* COINLINKAGE Clp_Version(void); + /** Major number of Clp library version. */ + COINLIBAPI int COINLINKAGE Clp_VersionMajor(void); + /** Minor number of Clp library version. */ + COINLIBAPI int COINLINKAGE Clp_VersionMinor(void); + /** Release number of Clp library version. */ + COINLIBAPI int COINLINKAGE Clp_VersionRelease(void); + /*@}*/ + + /**@name Constructors and destructor + These do not have an exact analogue in C++. + The user does not need to know structure of Clp_Simplex or Clp_Solve. + + For (almost) all Clp_* functions outside this group there is an exact C++ + analogue created by taking the first parameter out, removing the Clp_ + from name and applying the method to an object of type ClpSimplex. + + Similarly, for all ClpSolve_* functions there is an exact C++ + analogue created by taking the first parameter out, removing the ClpSolve_ + from name and applying the method to an object of type ClpSolve. + */ + /*@{*/ + + /** Default constructor */ + COINLIBAPI Clp_Simplex * COINLINKAGE Clp_newModel(void); + /** Destructor */ + COINLIBAPI void COINLINKAGE Clp_deleteModel(Clp_Simplex * model); + /** Default constructor */ + COINLIBAPI Clp_Solve * COINLINKAGE ClpSolve_new(); + /** Destructor */ + COINLIBAPI void COINLINKAGE ClpSolve_delete(Clp_Solve * solve); + /*@}*/ + + /**@name Load model - loads some stuff and initializes others */ + /*@{*/ + /** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + */ + /** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ + COINLIBAPI void COINLINKAGE Clp_loadProblem (Clp_Simplex * model, const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub); + + /* read quadratic part of the objective (the matrix part) */ + COINLIBAPI void COINLINKAGE + Clp_loadQuadraticObjective(Clp_Simplex * model, + const int numberColumns, + const CoinBigIndex * start, + const int * column, + const double * element); + /** Read an mps file from the given filename */ + COINLIBAPI int COINLINKAGE Clp_readMps(Clp_Simplex * model, const char *filename, + int keepNames, + int ignoreErrors); + /** Copy in integer informations */ + COINLIBAPI void COINLINKAGE Clp_copyInIntegerInformation(Clp_Simplex * model, const char * information); + /** Drop integer informations */ + COINLIBAPI void COINLINKAGE Clp_deleteIntegerInformation(Clp_Simplex * model); + /** Resizes rim part of model */ + COINLIBAPI void COINLINKAGE Clp_resize (Clp_Simplex * model, int newNumberRows, int newNumberColumns); + /** Deletes rows */ + COINLIBAPI void COINLINKAGE Clp_deleteRows(Clp_Simplex * model, int number, const int * which); + /** Add rows */ + COINLIBAPI void COINLINKAGE Clp_addRows(Clp_Simplex * model, int number, const double * rowLower, + const double * rowUpper, + const int * rowStarts, const int * columns, + const double * elements); + + /** Deletes columns */ + COINLIBAPI void COINLINKAGE Clp_deleteColumns(Clp_Simplex * model, int number, const int * which); + /** Add columns */ + COINLIBAPI void COINLINKAGE Clp_addColumns(Clp_Simplex * model, int number, const double * columnLower, + const double * columnUpper, + const double * objective, + const int * columnStarts, const int * rows, + const double * elements); + /** Change row lower bounds */ + COINLIBAPI void COINLINKAGE Clp_chgRowLower(Clp_Simplex * model, const double * rowLower); + /** Change row upper bounds */ + COINLIBAPI void COINLINKAGE Clp_chgRowUpper(Clp_Simplex * model, const double * rowUpper); + /** Change column lower bounds */ + COINLIBAPI void COINLINKAGE Clp_chgColumnLower(Clp_Simplex * model, const double * columnLower); + /** Change column upper bounds */ + COINLIBAPI void COINLINKAGE Clp_chgColumnUpper(Clp_Simplex * model, const double * columnUpper); + /** Change objective coefficients */ + COINLIBAPI void COINLINKAGE Clp_chgObjCoefficients(Clp_Simplex * model, const double * objIn); + /** Drops names - makes lengthnames 0 and names empty */ + COINLIBAPI void COINLINKAGE Clp_dropNames(Clp_Simplex * model); + /** Copies in names */ + COINLIBAPI void COINLINKAGE Clp_copyNames(Clp_Simplex * model, const char * const * rowNames, + const char * const * columnNames); + + /*@}*/ + /**@name gets and sets - you will find some synonyms at the end of this file */ + /*@{*/ + /** Number of rows */ + COINLIBAPI int COINLINKAGE Clp_numberRows(Clp_Simplex * model); + /** Number of columns */ + COINLIBAPI int COINLINKAGE Clp_numberColumns(Clp_Simplex * model); + /** Primal tolerance to use */ + COINLIBAPI double COINLINKAGE Clp_primalTolerance(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setPrimalTolerance(Clp_Simplex * model, double value) ; + /** Dual tolerance to use */ + COINLIBAPI double COINLINKAGE Clp_dualTolerance(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setDualTolerance(Clp_Simplex * model, double value) ; + /** Dual objective limit */ + COINLIBAPI double COINLINKAGE Clp_dualObjectiveLimit(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setDualObjectiveLimit(Clp_Simplex * model, double value); + /** Objective offset */ + COINLIBAPI double COINLINKAGE Clp_objectiveOffset(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setObjectiveOffset(Clp_Simplex * model, double value); + /** Fills in array with problem name */ + COINLIBAPI void COINLINKAGE Clp_problemName(Clp_Simplex * model, int maxNumberCharacters, char * array); + /* Sets problem name. Must have \0 at end. */ + COINLIBAPI int COINLINKAGE + Clp_setProblemName(Clp_Simplex * model, int maxNumberCharacters, char * array); + /** Number of iterations */ + COINLIBAPI int COINLINKAGE Clp_numberIterations(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setNumberIterations(Clp_Simplex * model, int numberIterations); + /** Maximum number of iterations */ + COINLIBAPI int maximumIterations(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setMaximumIterations(Clp_Simplex * model, int value); + /** Maximum time in seconds (from when set called) */ + COINLIBAPI double COINLINKAGE Clp_maximumSeconds(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setMaximumSeconds(Clp_Simplex * model, double value); + /** Returns true if hit maximum iterations (or time) */ + COINLIBAPI int COINLINKAGE Clp_hitMaximumIterations(Clp_Simplex * model); + /** Status of problem: + 0 - optimal + 1 - primal infeasible + 2 - dual infeasible + 3 - stopped on iterations etc + 4 - stopped due to errors + */ + COINLIBAPI int COINLINKAGE Clp_status(Clp_Simplex * model); + /** Set problem status */ + COINLIBAPI void COINLINKAGE Clp_setProblemStatus(Clp_Simplex * model, int problemStatus); + /** Secondary status of problem - may get extended + 0 - none + 1 - primal infeasible because dual limit reached + 2 - scaled problem optimal - unscaled has primal infeasibilities + 3 - scaled problem optimal - unscaled has dual infeasibilities + 4 - scaled problem optimal - unscaled has both dual and primal infeasibilities + */ + COINLIBAPI int COINLINKAGE Clp_secondaryStatus(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setSecondaryStatus(Clp_Simplex * model, int status); + /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ + COINLIBAPI double COINLINKAGE Clp_optimizationDirection(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setOptimizationDirection(Clp_Simplex * model, double value); + /** Primal row solution */ + COINLIBAPI double * COINLINKAGE Clp_primalRowSolution(Clp_Simplex * model); + /** Primal column solution */ + COINLIBAPI double * COINLINKAGE Clp_primalColumnSolution(Clp_Simplex * model); + /** Dual row solution */ + COINLIBAPI double * COINLINKAGE Clp_dualRowSolution(Clp_Simplex * model); + /** Reduced costs */ + COINLIBAPI double * COINLINKAGE Clp_dualColumnSolution(Clp_Simplex * model); + /** Row lower */ + COINLIBAPI double* COINLINKAGE Clp_rowLower(Clp_Simplex * model); + /** Row upper */ + COINLIBAPI double* COINLINKAGE Clp_rowUpper(Clp_Simplex * model); + /** Objective */ + COINLIBAPI double * COINLINKAGE Clp_objective(Clp_Simplex * model); + /** Column Lower */ + COINLIBAPI double * COINLINKAGE Clp_columnLower(Clp_Simplex * model); + /** Column Upper */ + COINLIBAPI double * COINLINKAGE Clp_columnUpper(Clp_Simplex * model); + /** Number of elements in matrix */ + COINLIBAPI int COINLINKAGE Clp_getNumElements(Clp_Simplex * model); + /* Column starts in matrix */ + COINLIBAPI const CoinBigIndex * COINLINKAGE Clp_getVectorStarts(Clp_Simplex * model); + /* Row indices in matrix */ + COINLIBAPI const int * COINLINKAGE Clp_getIndices(Clp_Simplex * model); + /* Column vector lengths in matrix */ + COINLIBAPI const int * COINLINKAGE Clp_getVectorLengths(Clp_Simplex * model); + /* Element values in matrix */ + COINLIBAPI const double * COINLINKAGE Clp_getElements(Clp_Simplex * model); + /** Objective value */ + COINLIBAPI double COINLINKAGE Clp_objectiveValue(Clp_Simplex * model); + /** Integer information */ + COINLIBAPI char * COINLINKAGE Clp_integerInformation(Clp_Simplex * model); + /** Gives Infeasibility ray. + * + * Use Clp_freeRay to free the returned array. + * + * @return infeasibility ray, or NULL returned if none/wrong. + */ + COINLIBAPI double * COINLINKAGE Clp_infeasibilityRay(Clp_Simplex * model); + /** Gives ray in which the problem is unbounded. + * + * Use Clp_freeRay to free the returned array. + * + * @return unbounded ray, or NULL returned if none/wrong. + */ + COINLIBAPI double * COINLINKAGE Clp_unboundedRay(Clp_Simplex * model); + /** Frees a infeasibility or unbounded ray. */ + COINLIBAPI void COINLINKAGE Clp_freeRay(Clp_Simplex * model, double * ray); + /** See if status array exists (partly for OsiClp) */ + COINLIBAPI int COINLINKAGE Clp_statusExists(Clp_Simplex * model); + /** Return address of status array (char[numberRows+numberColumns]) */ + COINLIBAPI unsigned char * COINLINKAGE Clp_statusArray(Clp_Simplex * model); + /** Copy in status vector */ + COINLIBAPI void COINLINKAGE Clp_copyinStatus(Clp_Simplex * model, const unsigned char * statusArray); + /* status values are as in ClpSimplex.hpp i.e. 0 - free, 1 basic, 2 at upper, + 3 at lower, 4 superbasic, (5 fixed) */ + /* Get variable basis info */ + COINLIBAPI int COINLINKAGE Clp_getColumnStatus(Clp_Simplex * model, int sequence); + /* Get row basis info */ + COINLIBAPI int COINLINKAGE Clp_getRowStatus(Clp_Simplex * model, int sequence); + /* Set variable basis info (and value if at bound) */ + COINLIBAPI void COINLINKAGE Clp_setColumnStatus(Clp_Simplex * model, + int sequence, int value); + /* Set row basis info (and value if at bound) */ + COINLIBAPI void COINLINKAGE Clp_setRowStatus(Clp_Simplex * model, + int sequence, int value); + + /** User pointer for whatever reason */ + COINLIBAPI void COINLINKAGE Clp_setUserPointer (Clp_Simplex * model, void * pointer); + COINLIBAPI void * COINLINKAGE Clp_getUserPointer (Clp_Simplex * model); + /*@}*/ + /**@name Message handling. Call backs are handled by ONE function */ + /*@{*/ + /** Pass in Callback function. + Message numbers up to 1000000 are Clp, Coin ones have 1000000 added */ + COINLIBAPI void COINLINKAGE Clp_registerCallBack(Clp_Simplex * model, + clp_callback userCallBack); + /** Unset Callback function */ + COINLIBAPI void COINLINKAGE Clp_clearCallBack(Clp_Simplex * model); + /** Amount of print out: + 0 - none + 1 - just final + 2 - just factorizations + 3 - as 2 plus a bit more + 4 - verbose + above that 8,16,32 etc just for selective debug + */ + COINLIBAPI void COINLINKAGE Clp_setLogLevel(Clp_Simplex * model, int value); + COINLIBAPI int COINLINKAGE Clp_logLevel(Clp_Simplex * model); + /** length of names (0 means no names0 */ + COINLIBAPI int COINLINKAGE Clp_lengthNames(Clp_Simplex * model); + /** Fill in array (at least lengthNames+1 long) with a row name */ + COINLIBAPI void COINLINKAGE Clp_rowName(Clp_Simplex * model, int iRow, char * name); + /** Fill in array (at least lengthNames+1 long) with a column name */ + COINLIBAPI void COINLINKAGE Clp_columnName(Clp_Simplex * model, int iColumn, char * name); + + /*@}*/ + + + /**@name Functions most useful to user */ + /*@{*/ + /** General solve algorithm which can do presolve. + See ClpSolve.hpp for options + */ + COINLIBAPI int COINLINKAGE Clp_initialSolve(Clp_Simplex * model); + /** Pass solve options. (Exception to direct analogue rule) */ + COINLIBAPI int COINLINKAGE Clp_initialSolveWithOptions(Clp_Simplex * model, Clp_Solve *); + /** Dual initial solve */ + COINLIBAPI int COINLINKAGE Clp_initialDualSolve(Clp_Simplex * model); + /** Primal initial solve */ + COINLIBAPI int COINLINKAGE Clp_initialPrimalSolve(Clp_Simplex * model); + /** Barrier initial solve */ + COINLIBAPI int COINLINKAGE Clp_initialBarrierSolve(Clp_Simplex * model); + /** Barrier initial solve, no crossover */ + COINLIBAPI int COINLINKAGE Clp_initialBarrierNoCrossSolve(Clp_Simplex * model); + /** Dual algorithm - see ClpSimplexDual.hpp for method */ + COINLIBAPI int COINLINKAGE Clp_dual(Clp_Simplex * model, int ifValuesPass); + /** Primal algorithm - see ClpSimplexPrimal.hpp for method */ + COINLIBAPI int COINLINKAGE Clp_primal(Clp_Simplex * model, int ifValuesPass); +#ifndef SLIM_CLP + /** Solve the problem with the idiot code */ + COINLIBAPI void COINLINKAGE Clp_idiot(Clp_Simplex * model, int tryhard); +#endif + /** Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) */ + COINLIBAPI void COINLINKAGE Clp_scaling(Clp_Simplex * model, int mode); + /** Gets scalingFlag */ + COINLIBAPI int COINLINKAGE Clp_scalingFlag(Clp_Simplex * model); + /** Crash - at present just aimed at dual, returns + -2 if dual preferred and crash basis created + -1 if dual preferred and all slack basis preferred + 0 if basis going in was not all slack + 1 if primal preferred and all slack basis preferred + 2 if primal preferred and crash basis created. + + if gap between bounds <="gap" variables can be flipped + + If "pivot" is + 0 No pivoting (so will just be choice of algorithm) + 1 Simple pivoting e.g. gub + 2 Mini iterations + */ + COINLIBAPI int COINLINKAGE Clp_crash(Clp_Simplex * model, double gap, int pivot); + /*@}*/ + + + /**@name most useful gets and sets */ + /*@{*/ + /** If problem is primal feasible */ + COINLIBAPI int COINLINKAGE Clp_primalFeasible(Clp_Simplex * model); + /** If problem is dual feasible */ + COINLIBAPI int COINLINKAGE Clp_dualFeasible(Clp_Simplex * model); + /** Dual bound */ + COINLIBAPI double COINLINKAGE Clp_dualBound(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setDualBound(Clp_Simplex * model, double value); + /** Infeasibility cost */ + COINLIBAPI double COINLINKAGE Clp_infeasibilityCost(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setInfeasibilityCost(Clp_Simplex * model, double value); + /** Perturbation: + 50 - switch on perturbation + 100 - auto perturb if takes too long (1.0e-6 largest nonzero) + 101 - we are perturbed + 102 - don't try perturbing again + default is 100 + others are for playing + */ + COINLIBAPI int COINLINKAGE Clp_perturbation(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setPerturbation(Clp_Simplex * model, int value); + /** Current (or last) algorithm */ + COINLIBAPI int COINLINKAGE Clp_algorithm(Clp_Simplex * model); + /** Set algorithm */ + COINLIBAPI void COINLINKAGE Clp_setAlgorithm(Clp_Simplex * model, int value); + /** Sum of dual infeasibilities */ + COINLIBAPI double COINLINKAGE Clp_sumDualInfeasibilities(Clp_Simplex * model); + /** Number of dual infeasibilities */ + COINLIBAPI int COINLINKAGE Clp_numberDualInfeasibilities(Clp_Simplex * model); + /** Sum of primal infeasibilities */ + COINLIBAPI double COINLINKAGE Clp_sumPrimalInfeasibilities(Clp_Simplex * model); + /** Number of primal infeasibilities */ + COINLIBAPI int COINLINKAGE Clp_numberPrimalInfeasibilities(Clp_Simplex * model); + /** Save model to file, returns 0 if success. This is designed for + use outside algorithms so does not save iterating arrays etc. + It does not save any messaging information. + Does not save scaling values. + It does not know about all types of virtual functions. + */ + COINLIBAPI int COINLINKAGE Clp_saveModel(Clp_Simplex * model, const char * fileName); + /** Restore model from file, returns 0 if success, + deletes current model */ + COINLIBAPI int COINLINKAGE Clp_restoreModel(Clp_Simplex * model, const char * fileName); + + /** Just check solution (for external use) - sets sum of + infeasibilities etc */ + COINLIBAPI void COINLINKAGE Clp_checkSolution(Clp_Simplex * model); + /*@}*/ + + /******************** End of most useful part **************/ + /**@name gets and sets - some synonyms */ + /*@{*/ + /** Number of rows */ + COINLIBAPI int COINLINKAGE Clp_getNumRows(Clp_Simplex * model); + /** Number of columns */ + COINLIBAPI int COINLINKAGE Clp_getNumCols(Clp_Simplex * model); + /** Number of iterations */ + COINLIBAPI int COINLINKAGE Clp_getIterationCount(Clp_Simplex * model); + /** Are there a numerical difficulties? */ + COINLIBAPI int COINLINKAGE Clp_isAbandoned(Clp_Simplex * model); + /** Is optimality proven? */ + COINLIBAPI int COINLINKAGE Clp_isProvenOptimal(Clp_Simplex * model); + /** Is primal infeasiblity proven? */ + COINLIBAPI int COINLINKAGE Clp_isProvenPrimalInfeasible(Clp_Simplex * model); + /** Is dual infeasiblity proven? */ + COINLIBAPI int COINLINKAGE Clp_isProvenDualInfeasible(Clp_Simplex * model); + /** Is the given primal objective limit reached? */ + COINLIBAPI int COINLINKAGE Clp_isPrimalObjectiveLimitReached(Clp_Simplex * model) ; + /** Is the given dual objective limit reached? */ + COINLIBAPI int COINLINKAGE Clp_isDualObjectiveLimitReached(Clp_Simplex * model) ; + /** Iteration limit reached? */ + COINLIBAPI int COINLINKAGE Clp_isIterationLimitReached(Clp_Simplex * model); + /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ + COINLIBAPI double COINLINKAGE Clp_getObjSense(Clp_Simplex * model); + /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ + COINLIBAPI void COINLINKAGE Clp_setObjSense(Clp_Simplex * model, double objsen); + /** Primal row solution */ + COINLIBAPI const double * COINLINKAGE Clp_getRowActivity(Clp_Simplex * model); + /** Primal column solution */ + COINLIBAPI const double * COINLINKAGE Clp_getColSolution(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setColSolution(Clp_Simplex * model, const double * input); + /** Dual row solution */ + COINLIBAPI const double * COINLINKAGE Clp_getRowPrice(Clp_Simplex * model); + /** Reduced costs */ + COINLIBAPI const double * COINLINKAGE Clp_getReducedCost(Clp_Simplex * model); + /** Row lower */ + COINLIBAPI const double* COINLINKAGE Clp_getRowLower(Clp_Simplex * model); + /** Row upper */ + COINLIBAPI const double* COINLINKAGE Clp_getRowUpper(Clp_Simplex * model); + /** Objective */ + COINLIBAPI const double * COINLINKAGE Clp_getObjCoefficients(Clp_Simplex * model); + /** Column Lower */ + COINLIBAPI const double * COINLINKAGE Clp_getColLower(Clp_Simplex * model); + /** Column Upper */ + COINLIBAPI const double * COINLINKAGE Clp_getColUpper(Clp_Simplex * model); + /** Objective value */ + COINLIBAPI double COINLINKAGE Clp_getObjValue(Clp_Simplex * model); + /** Print model for debugging purposes */ + COINLIBAPI void COINLINKAGE Clp_printModel(Clp_Simplex * model, const char * prefix); + /* Small element value - elements less than this set to zero, + default is 1.0e-20 */ + COINLIBAPI double COINLINKAGE Clp_getSmallElementValue(Clp_Simplex * model); + COINLIBAPI void COINLINKAGE Clp_setSmallElementValue(Clp_Simplex * model, double value); + /*@}*/ + + + /**@name Get and set ClpSolve options + */ + /*@{*/ + COINLIBAPI void COINLINKAGE ClpSolve_setSpecialOption(Clp_Solve *, int which, int value, int extraInfo); + COINLIBAPI int COINLINKAGE ClpSolve_getSpecialOption(Clp_Solve *, int which); + + /** method: (see ClpSolve::SolveType) + 0 - dual simplex + 1 - primal simplex + 2 - primal or sprint + 3 - barrier + 4 - barrier no crossover + 5 - automatic + 6 - not implemented + -- pass extraInfo == -1 for default behavior */ + COINLIBAPI void COINLINKAGE ClpSolve_setSolveType(Clp_Solve *, int method, int extraInfo); + COINLIBAPI int COINLINKAGE ClpSolve_getSolveType(Clp_Solve *); + + /** amount: (see ClpSolve::PresolveType) + 0 - presolve on + 1 - presolve off + 2 - presolve number + 3 - presolve number cost + -- pass extraInfo == -1 for default behavior */ + COINLIBAPI void COINLINKAGE ClpSolve_setPresolveType(Clp_Solve *, int amount, int extraInfo); + COINLIBAPI int COINLINKAGE ClpSolve_getPresolveType(Clp_Solve *); + + COINLIBAPI int COINLINKAGE ClpSolve_getPresolvePasses(Clp_Solve *); + COINLIBAPI int COINLINKAGE ClpSolve_getExtraInfo(Clp_Solve *, int which); + COINLIBAPI void COINLINKAGE ClpSolve_setInfeasibleReturn(Clp_Solve *, int trueFalse); + COINLIBAPI int COINLINKAGE ClpSolve_infeasibleReturn(Clp_Solve *); + + COINLIBAPI int COINLINKAGE ClpSolve_doDual(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoDual(Clp_Solve *, int doDual); + + COINLIBAPI int COINLINKAGE ClpSolve_doSingleton(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoSingleton(Clp_Solve *, int doSingleton); + + COINLIBAPI int COINLINKAGE ClpSolve_doDoubleton(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoDoubleton(Clp_Solve *, int doDoubleton); + + COINLIBAPI int COINLINKAGE ClpSolve_doTripleton(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoTripleton(Clp_Solve *, int doTripleton); + + COINLIBAPI int COINLINKAGE ClpSolve_doTighten(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoTighten(Clp_Solve *, int doTighten); + + COINLIBAPI int COINLINKAGE ClpSolve_doForcing(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoForcing(Clp_Solve *, int doForcing); + + COINLIBAPI int COINLINKAGE ClpSolve_doImpliedFree(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoImpliedFree(Clp_Solve *, int doImpliedFree); + + COINLIBAPI int COINLINKAGE ClpSolve_doDupcol(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoDupcol(Clp_Solve *, int doDupcol); + + COINLIBAPI int COINLINKAGE ClpSolve_doDuprow(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoDuprow(Clp_Solve *, int doDuprow); + + COINLIBAPI int COINLINKAGE ClpSolve_doSingletonColumn(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setDoSingletonColumn(Clp_Solve *, int doSingleton); + + COINLIBAPI int COINLINKAGE ClpSolve_presolveActions(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setPresolveActions(Clp_Solve *, int action); + + COINLIBAPI int COINLINKAGE ClpSolve_substitution(Clp_Solve *); + COINLIBAPI void COINLINKAGE ClpSolve_setSubstitution(Clp_Solve *, int value); + + /*@}*/ +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/linux/include/coin/CoinAlloc.hpp b/thirdparty/linux/include/coin/CoinAlloc.hpp new file mode 100644 index 0000000..8f6b08c --- /dev/null +++ b/thirdparty/linux/include/coin/CoinAlloc.hpp @@ -0,0 +1,176 @@ +/* $Id: CoinAlloc.hpp 1438 2011-06-09 18:14:12Z stefan $ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinAlloc_hpp +#define CoinAlloc_hpp + +#include "CoinUtilsConfig.h" +#include <cstdlib> + +#if !defined(COINUTILS_MEMPOOL_MAXPOOLED) +# define COINUTILS_MEMPOOL_MAXPOOLED -1 +#endif + +#if (COINUTILS_MEMPOOL_MAXPOOLED >= 0) + +#ifndef COINUTILS_MEMPOOL_ALIGNMENT +#define COINUTILS_MEMPOOL_ALIGNMENT 16 +#endif + +/* Note: + This memory pool implementation assumes that sizeof(size_t) and + sizeof(void*) are both <= COINUTILS_MEMPOOL_ALIGNMENT. + Choosing an alignment of 4 will cause segfault on 64-bit platforms and may + lead to bad performance on 32-bit platforms. So 8 is a mnimum recommended + alignment. Probably 16 does not waste too much space either and may be even + better for performance. One must play with it. +*/ + +//############################################################################# + +#if (COINUTILS_MEMPOOL_ALIGNMENT == 16) +static const std::size_t CoinAllocPtrShift = 4; +static const std::size_t CoinAllocRoundMask = ~((std::size_t)15); +#elif (COINUTILS_MEMPOOL_ALIGNMENT == 8) +static const std::size_t CoinAllocPtrShift = 3; +static const std::size_t CoinAllocRoundMask = ~((std::size_t)7); +#else +#error "COINUTILS_MEMPOOL_ALIGNMENT must be defined as 8 or 16 (or this code needs to be changed :-)" +#endif + +//############################################################################# + +#ifndef COIN_MEMPOOL_SAVE_BLOCKHEADS +# define COIN_MEMPOOL_SAVE_BLOCKHEADS 0 +#endif + +//############################################################################# + +class CoinMempool +{ +private: +#if (COIN_MEMPOOL_SAVE_BLOCKHEADS == 1) + char** block_heads; + std::size_t block_num; + std::size_t max_block_num; +#endif +#if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) + pthread_mutex_t mutex_; +#endif + int last_block_size_; + char* first_free_; + const std::size_t entry_size_; + +private: + CoinMempool(const CoinMempool&); + CoinMempool& operator=(const CoinMempool&); + +private: + char* allocate_new_block(); + inline void lock_mutex() { +#if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) + pthread_mutex_lock(&mutex_); +#endif + } + inline void unlock_mutex() { +#if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) + pthread_mutex_unlock(&mutex_); +#endif + } + +public: + CoinMempool(std::size_t size = 0); + ~CoinMempool(); + + char* alloc(); + inline void dealloc(char *p) + { + char** pp = (char**)p; + lock_mutex(); + *pp = first_free_; + first_free_ = p; + unlock_mutex(); + } +}; + +//############################################################################# + +/** A memory pool allocator. + + If a request arrives for allocating \c n bytes then it is first + rounded up to the nearest multiple of \c sizeof(void*) (this is \c + n_roundup), then one more \c sizeof(void*) is added to this + number. If the result is no more than maxpooled_ then + the appropriate pool is used to get a chunk of memory, if not, + then malloc is used. In either case, the size of the allocated + chunk is written into the first \c sizeof(void*) bytes and a + pointer pointing afterwards is returned. +*/ + +class CoinAlloc +{ +private: + CoinMempool* pool_; + int maxpooled_; +public: + CoinAlloc(); + ~CoinAlloc() {} + + inline void* alloc(const std::size_t n) + { + if (maxpooled_ <= 0) { + return std::malloc(n); + } + char *p = NULL; + const std::size_t to_alloc = + ((n+COINUTILS_MEMPOOL_ALIGNMENT-1) & CoinAllocRoundMask) + + COINUTILS_MEMPOOL_ALIGNMENT; + CoinMempool* pool = NULL; + if (maxpooled_ > 0 && to_alloc >= (size_t)maxpooled_) { + p = static_cast<char*>(std::malloc(to_alloc)); + if (p == NULL) throw std::bad_alloc(); + } else { + pool = pool_ + (to_alloc >> CoinAllocPtrShift); + p = pool->alloc(); + } + *((CoinMempool**)p) = pool; + return static_cast<void*>(p+COINUTILS_MEMPOOL_ALIGNMENT); + } + + inline void dealloc(void* p) + { + if (maxpooled_ <= 0) { + std::free(p); + return; + } + if (p) { + char* base = static_cast<char*>(p)-COINUTILS_MEMPOOL_ALIGNMENT; + CoinMempool* pool = *((CoinMempool**)base); + if (!pool) { + std::free(base); + } else { + pool->dealloc(base); + } + } + } +}; + +extern CoinAlloc CoinAllocator; + +//############################################################################# + +#if defined(COINUTILS_MEMPOOL_OVERRIDE_NEW) && (COINUTILS_MEMPOOL_OVERRIDE_NEW == 1) +void* operator new(std::size_t size) throw (std::bad_alloc); +void* operator new[](std::size_t) throw (std::bad_alloc); +void operator delete(void*) throw(); +void operator delete[](void*) throw(); +void* operator new(std::size_t, const std::nothrow_t&) throw(); +void* operator new[](std::size_t, const std::nothrow_t&) throw(); +void operator delete(void*, const std::nothrow_t&) throw(); +void operator delete[](void*, const std::nothrow_t&) throw(); +#endif + +#endif /*(COINUTILS_MEMPOOL_MAXPOOLED >= 0)*/ +#endif diff --git a/thirdparty/linux/include/coin/CoinBuild.hpp b/thirdparty/linux/include/coin/CoinBuild.hpp new file mode 100644 index 0000000..770c269 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinBuild.hpp @@ -0,0 +1,149 @@ +/* $Id: CoinBuild.hpp 1416 2011-04-17 09:57:29Z stefan $ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinBuild_H +#define CoinBuild_H + + +#include "CoinPragma.hpp" +#include "CoinTypes.hpp" +#include "CoinFinite.hpp" + + +/** + In many cases it is natural to build a model by adding one row at a time. In Coin this + is inefficient so this class gives some help. An instance of CoinBuild can be built up + more efficiently and then added to the Clp/OsiModel in one go. + + It may be more efficient to have fewer arrays and re-allocate them but this should + give a large gain over addRow. + + I have now extended it to columns. + +*/ + +class CoinBuild { + +public: + /**@name Useful methods */ + //@{ + /// add a row + void addRow(int numberInRow, const int * columns, + const double * elements, double rowLower=-COIN_DBL_MAX, + double rowUpper=COIN_DBL_MAX); + /// add a column + void addColumn(int numberInColumn, const int * rows, + const double * elements, + double columnLower=0.0, + double columnUpper=COIN_DBL_MAX, double objectiveValue=0.0); + /// add a column + inline void addCol(int numberInColumn, const int * rows, + const double * elements, + double columnLower=0.0, + double columnUpper=COIN_DBL_MAX, double objectiveValue=0.0) + { addColumn(numberInColumn, rows, elements, columnLower, columnUpper, objectiveValue);} + /// Return number of rows or maximum found so far + inline int numberRows() const + { return (type_==0) ? numberItems_ : numberOther_;} + /// Return number of columns or maximum found so far + inline int numberColumns() const + { return (type_==1) ? numberItems_ : numberOther_;} + /// Return number of elements + inline CoinBigIndex numberElements() const + { return numberElements_;} + /** Returns number of elements in a row and information in row + */ + int row(int whichRow, double & rowLower, double & rowUpper, + const int * & indices, const double * & elements) const; + /** Returns number of elements in current row and information in row + Used as rows may be stored in a chain + */ + int currentRow(double & rowLower, double & rowUpper, + const int * & indices, const double * & elements) const; + /// Set current row + void setCurrentRow(int whichRow); + /// Returns current row number + int currentRow() const; + /** Returns number of elements in a column and information in column + */ + int column(int whichColumn, + double & columnLower, double & columnUpper,double & objectiveValue, + const int * & indices, const double * & elements) const; + /** Returns number of elements in current column and information in column + Used as columns may be stored in a chain + */ + int currentColumn( double & columnLower, double & columnUpper,double & objectiveValue, + const int * & indices, const double * & elements) const; + /// Set current column + void setCurrentColumn(int whichColumn); + /// Returns current column number + int currentColumn() const; + /// Returns type + inline int type() const + { return type_;} + //@} + + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinBuild(); + /** Constructor with type 0==for addRow, 1== for addColumn. */ + CoinBuild(int type); + /** Destructor */ + ~CoinBuild(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinBuild(const CoinBuild&); + /// = + CoinBuild& operator=(const CoinBuild&); + //@} +private: + /// Set current + void setMutableCurrent(int which) const; + /// add a item + void addItem(int numberInItem, const int * indices, + const double * elements, + double itemLower, + double itemUpper, double objectiveValue); + /** Returns number of elements in a item and information in item + */ + int item(int whichItem, + double & itemLower, double & itemUpper,double & objectiveValue, + const int * & indices, const double * & elements) const; + /** Returns number of elements in current item and information in item + Used as items may be stored in a chain + */ + int currentItem( double & itemLower, double & itemUpper,double & objectiveValue, + const int * & indices, const double * & elements) const; + /// Set current item + void setCurrentItem(int whichItem); + /// Returns current item number + int currentItem() const; + +private: + /**@name Data members */ + //@{ + /// Current number of items + int numberItems_; + /// Current number of other dimension i.e. Columns if addRow (i.e. max) + int numberOther_; + /// Current number of elements + CoinBigIndex numberElements_; + /// Current item pointer + mutable double * currentItem_; + /// First item pointer + double * firstItem_; + /// Last item pointer + double * lastItem_; + /// Type of build - 0 for row, 1 for column, -1 unset + int type_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinDenseFactorization.hpp b/thirdparty/linux/include/coin/CoinDenseFactorization.hpp new file mode 100644 index 0000000..3ba7528 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinDenseFactorization.hpp @@ -0,0 +1,419 @@ +/* $Id: CoinDenseFactorization.hpp 1759 2014-11-18 11:07:23Z forrest $ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + + +/* + Authors + + John Forrest + + */ +#ifndef CoinDenseFactorization_H +#define CoinDenseFactorization_H + +#include <iostream> +#include <string> +#include <cassert> +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinFactorization.hpp" +#if COIN_FACTORIZATION_DENSE_CODE == 2 +#undef COIN_FACTORIZATION_DENSE_CODE +#endif +class CoinPackedMatrix; +/// Abstract base class which also has some scalars so can be used from Dense or Simp +class CoinOtherFactorization { + +public: + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinOtherFactorization ( ); + /// Copy constructor + CoinOtherFactorization ( const CoinOtherFactorization &other); + + /// Destructor + virtual ~CoinOtherFactorization ( ); + /// = copy + CoinOtherFactorization & operator = ( const CoinOtherFactorization & other ); + + /// Clone + virtual CoinOtherFactorization * clone() const = 0; + //@} + + /**@name general stuff such as status */ + //@{ + /// Returns status + inline int status ( ) const { + return status_; + } + /// Sets status + inline void setStatus ( int value) + { status_=value; } + /// Returns number of pivots since factorization + inline int pivots ( ) const { + return numberPivots_; + } + /// Sets number of pivots since factorization + inline void setPivots ( int value ) + { numberPivots_=value; } + /// Set number of Rows after factorization + inline void setNumberRows(int value) + { numberRows_ = value; } + /// Number of Rows after factorization + inline int numberRows ( ) const { + return numberRows_; + } + /// Total number of columns in factorization + inline int numberColumns ( ) const { + return numberColumns_; + } + /// Number of good columns in factorization + inline int numberGoodColumns ( ) const { + return numberGoodU_; + } + /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed + inline void relaxAccuracyCheck(double value) + { relaxCheck_ = value;} + inline double getAccuracyCheck() const + { return relaxCheck_;} + /// Maximum number of pivots between factorizations + inline int maximumPivots ( ) const { + return maximumPivots_ ; + } + /// Set maximum pivots + virtual void maximumPivots ( int value ); + + /// Pivot tolerance + inline double pivotTolerance ( ) const { + return pivotTolerance_ ; + } + void pivotTolerance ( double value ); + /// Zero tolerance + inline double zeroTolerance ( ) const { + return zeroTolerance_ ; + } + void zeroTolerance ( double value ); +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + inline double slackValue ( ) const { + return slackValue_ ; + } + void slackValue ( double value ); +#endif + /// Returns array to put basis elements in + virtual CoinFactorizationDouble * elements() const; + /// Returns pivot row + virtual int * pivotRow() const; + /// Returns work area + virtual CoinFactorizationDouble * workArea() const; + /// Returns int work area + virtual int * intWorkArea() const; + /// Number of entries in each row + virtual int * numberInRow() const; + /// Number of entries in each column + virtual int * numberInColumn() const; + /// Returns array to put basis starts in + virtual CoinBigIndex * starts() const; + /// Returns permute back + virtual int * permuteBack() const; + /** Get solve mode e.g. 0 C++ code, 1 Lapack, 2 choose + If 4 set then values pass + if 8 set then has iterated + */ + inline int solveMode() const + { return solveMode_ ;} + /** Set solve mode e.g. 0 C++ code, 1 Lapack, 2 choose + If 4 set then values pass + if 8 set then has iterated + */ + inline void setSolveMode(int value) + { solveMode_ = value;} + /// Returns true if wants tableauColumn in replaceColumn + virtual bool wantsTableauColumn() const; + /** Useful information for factorization + 0 - iteration number + whereFrom is 0 for factorize and 1 for replaceColumn + */ + virtual void setUsefulInformation(const int * info,int whereFrom); + /// Get rid of all memory + virtual void clearArrays() {} + //@} + /**@name virtual general stuff such as permutation */ + //@{ + /// Returns array to put basis indices in + virtual int * indices() const = 0; + /// Returns permute in + virtual int * permute() const = 0; + /// Total number of elements in factorization + virtual int numberElements ( ) const = 0; + //@} + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas ( int numberRows, + int numberColumns, + CoinBigIndex maximumL, + CoinBigIndex maximumU ) = 0; + + /// PreProcesses column ordered copy of basis + virtual void preProcess ( ) = 0; + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor ( ) = 0; + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int * sequence, int * pivotVariable) = 0; + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int * sequence, int numberColumns) = 0; + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn ( CoinIndexedVector * regionSparse, + int pivotRow, + double pivotCheck , + bool checkBeforeModifying=false, + double acceptablePivot=1.0e-8)=0; + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnFT ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false) = 0; + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false) const = 0; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, + CoinIndexedVector * regionSparse2, + CoinIndexedVector * regionSparse3, + bool noPermute=false) = 0; + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2) const = 0; + //@} + +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + /// Pivot tolerance + double pivotTolerance_; + /// Zero tolerance + double zeroTolerance_; +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + double slackValue_; +#else +#ifndef slackValue_ +#define slackValue_ -1.0 +#endif +#endif + /// Relax check on accuracy in replaceColumn + double relaxCheck_; + /// Number of elements after factorization + CoinBigIndex factorElements_; + /// Number of Rows in factorization + int numberRows_; + /// Number of Columns in factorization + int numberColumns_; + /// Number factorized in U (not row singletons) + int numberGoodU_; + /// Maximum number of pivots before factorization + int maximumPivots_; + /// Number pivots since last factorization + int numberPivots_; + /// Status of factorization + int status_; + /// Maximum rows ever (i.e. use to copy arrays etc) + int maximumRows_; + /// Maximum length of iterating area + CoinBigIndex maximumSpace_; + /// Pivot row + int * pivotRow_; + /** Elements of factorization and updates + length is maxR*maxR+maxSpace + will always be long enough so can have nR*nR ints in maxSpace + */ + CoinFactorizationDouble * elements_; + /// Work area of numberRows_ + CoinFactorizationDouble * workArea_; + /** Solve mode e.g. 0 C++ code, 1 Lapack, 2 choose + If 4 set then values pass + if 8 set then has iterated + */ + int solveMode_; + //@} +}; +/** This deals with Factorization and Updates + This is a simple dense version so other people can write a better one + + I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex + may be redefined to get 64 bits. + */ + + + +class CoinDenseFactorization : public CoinOtherFactorization { + friend void CoinDenseFactorizationUnitTest( const std::string & mpsDir ); + +public: + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinDenseFactorization ( ); + /// Copy constructor + CoinDenseFactorization ( const CoinDenseFactorization &other); + + /// Destructor + virtual ~CoinDenseFactorization ( ); + /// = copy + CoinDenseFactorization & operator = ( const CoinDenseFactorization & other ); + /// Clone + virtual CoinOtherFactorization * clone() const ; + //@} + + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas ( int numberRows, + int numberColumns, + CoinBigIndex maximumL, + CoinBigIndex maximumU ); + + /// PreProcesses column ordered copy of basis + virtual void preProcess ( ); + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor ( ); + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int * sequence, int * pivotVariable); + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int * sequence, int numberColumns); + //@} + + /**@name general stuff such as number of elements */ + //@{ + /// Total number of elements in factorization + virtual inline int numberElements ( ) const { + return numberRows_*(numberColumns_+numberPivots_); + } + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn ( CoinIndexedVector * regionSparse, + int pivotRow, + double pivotCheck , + bool checkBeforeModifying=false, + double acceptablePivot=1.0e-8); + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual inline int updateColumnFT ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool = false) + { return updateColumn(regionSparse,regionSparse2);} + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false) const; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, + CoinIndexedVector * regionSparse2, + CoinIndexedVector * regionSparse3, + bool noPermute=false); + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2) const; + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + inline void clearArrays() + { gutsOfDestructor();} + /// Returns array to put basis indices in + virtual inline int * indices() const + { return reinterpret_cast<int *> (elements_+numberRows_*numberRows_);} + /// Returns permute in + virtual inline int * permute() const + { return NULL;/*pivotRow_*/;} + //@} + + /// The real work of desstructor + void gutsOfDestructor(); + /// The real work of constructor + void gutsOfInitialize(); + /// The real work of copy + void gutsOfCopy(const CoinDenseFactorization &other); + + //@} +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CoinDenseVector.hpp b/thirdparty/linux/include/coin/CoinDenseVector.hpp new file mode 100644 index 0000000..77ff9af --- /dev/null +++ b/thirdparty/linux/include/coin/CoinDenseVector.hpp @@ -0,0 +1,383 @@ +/* $Id: CoinDenseVector.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinDenseVector_H +#define CoinDenseVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +#endif + +#include <cassert> +#include <cstdlib> +#include <cmath> +#include "CoinHelperFunctions.hpp" + +//############################################################################# +/** A function that tests the methods in the CoinDenseVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ + template <typename T> void + CoinDenseVectorUnitTest(T dummy); + +//############################################################################# +/** Dense Vector + +Stores a dense (or expanded) vector of floating point values. +Type of vector elements is controlled by templating. +(Some working quantities such as accumulated sums +are explicitly declared of type double). This allows the +components of the vector integer, single or double precision. + +Here is a sample usage: +@verbatim + const int ne = 4; + double el[ne] = { 10., 40., 1., 50. } + + // Create vector and set its value + CoinDenseVector<double> r(ne,el); + + // access each element + assert( r.getElements()[0]==10. ); + assert( r.getElements()[1]==40. ); + assert( r.getElements()[2]== 1. ); + assert( r.getElements()[3]==50. ); + + // Test for equality + CoinDenseVector<double> r1; + r1=r; + + // Add dense vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinDenseVector<double> add = r + r1; + assert( add[0] == 10.+10. ); + assert( add[1] == 40.+40. ); + assert( add[2] == 1.+ 1. ); + assert( add[3] == 50.+50. ); + + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +template <typename T> class CoinDenseVector { +private: + /**@name Private member data */ + //@{ + /// Size of element vector + int nElements_; + ///Vector elements + T * elements_; + //@} + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getNumElements() const { return nElements_; } + inline int size() const { return nElements_; } + /// Get element values + inline const T * getElements() const { return elements_; } + /// Get element values + inline T * getElements() { return elements_; } + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Reset the vector (i.e. set all elemenets to zero) + void clear(); + /** Assignment operator */ + CoinDenseVector & operator=(const CoinDenseVector &); + /** Member of array operator */ + T & operator[](int index) const; + + /** Set vector size, and elements. + Size is the length of the elements vector. + The element vector is copied into this class instance's + member data. */ + void setVector(int size, const T * elems); + + + /** Elements set to have the same scalar value */ + void setConstant(int size, T elems); + + + /** Set an existing element in the dense vector + The first argument is the "index" into the elements() array + */ + void setElement(int index, T element); + /** Resize the dense vector to be the first newSize elements. + If length is decreased, vector is truncated. If increased + new entries, set to new default element */ + void resize(int newSize, T fill=T()); + + /** Append a dense vector to this dense vector */ + void append(const CoinDenseVector &); + //@} + + /**@name norms, sum and scale */ + //@{ + /// 1-norm of vector + inline T oneNorm() const { + T norm = 0; + for (int i=0; i<nElements_; i++) + norm += CoinAbs(elements_[i]); + return norm; + } + /// 2-norm of vector + inline double twoNorm() const { + double norm = 0.; + for (int i=0; i<nElements_; i++) + norm += elements_[i] * elements_[i]; + // std namespace removed because it was causing a compile + // problem with Microsoft Visual C++ + return /*std::*/sqrt(norm); + } + /// infinity-norm of vector + inline T infNorm() const { + T norm = 0; + for (int i=0; i<nElements_; i++) + norm = CoinMax(norm, CoinAbs(elements_[i])); + return norm; + } + /// sum of vector elements + inline T sum() const { + T sume = 0; + for (int i=0; i<nElements_; i++) + sume += elements_[i]; + return sume; + } + /// scale vector elements + inline void scale(T factor) { + for (int i=0; i<nElements_; i++) + elements_[i] *= factor; + return; + } + //@} + + /**@name Arithmetic operators. */ + //@{ + /// add <code>value</code> to every entry + void operator+=(T value); + /// subtract <code>value</code> from every entry + void operator-=(T value); + /// multiply every entry by <code>value</code> + void operator*=(T value); + /// divide every entry by <code>value</code> + void operator/=(T value); + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor */ + CoinDenseVector(); + /** Alternate Constructors - set elements to vector of Ts */ + CoinDenseVector(int size, const T * elems); + /** Alternate Constructors - set elements to same scalar value */ + CoinDenseVector(int size, T element=T()); + /** Copy constructors */ + CoinDenseVector(const CoinDenseVector &); + + /** Destructor */ + ~CoinDenseVector (); + //@} + +private: + /**@name Private methods */ + //@{ + /// Copy internal data + void gutsOfSetVector(int size, const T * elems); + /// Set all elements to a given value + void gutsOfSetConstant(int size, T value); + //@} +}; + +//############################################################################# + +/**@name Arithmetic operators on dense vectors. + + <strong>NOTE</strong>: Because these methods return an object (they can't + return a reference, though they could return a pointer...) they are + <em>very</em> inefficient... + */ +//@{ +/// Return the sum of two dense vectors +template <typename T> inline +CoinDenseVector<T> operator+(const CoinDenseVector<T>& op1, + const CoinDenseVector<T>& op2){ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for(int i=0; i<size; i++) + elements3[i] = elements1[i] + elements2[i]; + return op3; +} + +/// Return the difference of two dense vectors +template <typename T> inline +CoinDenseVector<T> operator-(const CoinDenseVector<T>& op1, + const CoinDenseVector<T>& op2){ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for(int i=0; i<size; i++) + elements3[i] = elements1[i] - elements2[i]; + return op3; +} + + +/// Return the element-wise product of two dense vectors +template <typename T> inline +CoinDenseVector<T> operator*(const CoinDenseVector<T>& op1, + const CoinDenseVector<T>& op2){ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for(int i=0; i<size; i++) + elements3[i] = elements1[i] * elements2[i]; + return op3; +} + +/// Return the element-wise ratio of two dense vectors +template <typename T> inline +CoinDenseVector<T> operator/(const CoinDenseVector<T>& op1, + const CoinDenseVector<T>& op2){ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for(int i=0; i<size; i++) + elements3[i] = elements1[i] / elements2[i]; + return op3; +} +//@} + +/**@name Arithmetic operators on dense vector and a constant. + These functions create a dense vector as a result. That dense vector will + have the same indices as <code>op1</code> and the specified operation is + done entry-wise with the given value. */ +//@{ +/// Return the sum of a dense vector and a constant +template <typename T> inline +CoinDenseVector<T> operator+(const CoinDenseVector<T>& op1, T value){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = elements1[i] + dvalue; + return op3; +} + +/// Return the difference of a dense vector and a constant +template <typename T> inline +CoinDenseVector<T> operator-(const CoinDenseVector<T>& op1, T value){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = elements1[i] - dvalue; + return op3; +} + +/// Return the element-wise product of a dense vector and a constant +template <typename T> inline +CoinDenseVector<T> operator*(const CoinDenseVector<T>& op1, T value){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = elements1[i] * dvalue; + return op3; +} + +/// Return the element-wise ratio of a dense vector and a constant +template <typename T> inline +CoinDenseVector<T> operator/(const CoinDenseVector<T>& op1, T value){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = elements1[i] / dvalue; + return op3; +} + +/// Return the sum of a constant and a dense vector +template <typename T> inline +CoinDenseVector<T> operator+(T value, const CoinDenseVector<T>& op1){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = elements1[i] + dvalue; + return op3; +} + +/// Return the difference of a constant and a dense vector +template <typename T> inline +CoinDenseVector<T> operator-(T value, const CoinDenseVector<T>& op1){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = dvalue - elements1[i]; + return op3; +} + +/// Return the element-wise product of a constant and a dense vector +template <typename T> inline +CoinDenseVector<T> operator*(T value, const CoinDenseVector<T>& op1){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = elements1[i] * dvalue; + return op3; +} + +/// Return the element-wise ratio of a a constant and dense vector +template <typename T> inline +CoinDenseVector<T> operator/(T value, const CoinDenseVector<T>& op1){ + int size = op1.size(); + CoinDenseVector<T> op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for(int i=0; i<size; i++) + elements3[i] = dvalue / elements1[i]; + return op3; +} +//@} + +#endif diff --git a/thirdparty/linux/include/coin/CoinDistance.hpp b/thirdparty/linux/include/coin/CoinDistance.hpp new file mode 100644 index 0000000..acaa908 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinDistance.hpp @@ -0,0 +1,48 @@ +/* $Id: CoinDistance.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinDistance_H +#define CoinDistance_H + +#include <iterator> + +//------------------------------------------------------------------- +// +// Attempt to provide an std::distance function +// that will work on multiple platforms +// +//------------------------------------------------------------------- + +/** CoinDistance + +This is the Coin implementation of the std::function that is +designed to work on multiple platforms. +*/ +template <class ForwardIterator, class Distance> +void coinDistance(ForwardIterator first, ForwardIterator last, + Distance& n) +{ +#if defined(__SUNPRO_CC) + n = 0; + std::distance(first,last,n); +#else + n = std::distance(first,last); +#endif +} + +template <class ForwardIterator> +size_t coinDistance(ForwardIterator first, ForwardIterator last) +{ + size_t retVal; +#if defined(__SUNPRO_CC) + retVal = 0; + std::distance(first,last,retVal); +#else + retVal = std::distance(first,last); +#endif + return retVal; +} + +#endif diff --git a/thirdparty/linux/include/coin/CoinError.hpp b/thirdparty/linux/include/coin/CoinError.hpp new file mode 100644 index 0000000..704cfea --- /dev/null +++ b/thirdparty/linux/include/coin/CoinError.hpp @@ -0,0 +1,257 @@ +/* $Id: CoinError.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinError_H +#define CoinError_H + +#include <string> +#include <iostream> +#include <cassert> +#include <cstring> + +#include "CoinUtilsConfig.h" +#include "CoinPragma.hpp" + +/** A function to block the popup windows that windows creates when the code + crashes */ +void WindowsErrorPopupBlocker(); + +//------------------------------------------------------------------- +// +// Error class used to throw exceptions +// +// Errors contain: +// +//------------------------------------------------------------------- + +/** Error Class thrown by an exception + +This class is used when exceptions are thrown. +It contains: + <ul> + <li>message text + <li>name of method throwing exception + <li>name of class throwing exception or hint + <li>name of file if assert + <li>line number + </ul> + For asserts class=> optional hint +*/ +class CoinError { + friend void CoinErrorUnitTest(); + +private: + CoinError() + : + message_(), + method_(), + class_(), + file_(), + lineNumber_() + { + // nothing to do here + } + +public: + + //------------------------------------------------------------------- + // Get methods + //------------------------------------------------------------------- + /**@name Get error attributes */ + //@{ + /// get message text + inline const std::string & message() const + { return message_; } + /// get name of method instantiating error + inline const std::string & methodName() const + { return method_; } + /// get name of class instantiating error (or hint for assert) + inline const std::string & className() const + { return class_; } + /// get name of file for assert + inline const std::string & fileName() const + { return file_; } + /// get line number of assert (-1 if not assert) + inline int lineNumber() const + { return lineNumber_; } + /// Just print (for asserts) + inline void print(bool doPrint = true) const + { + if (! doPrint) + return; + if (lineNumber_<0) { + std::cout<<message_<<" in "<<class_<<"::"<<method_<<std::endl; + } else { + std::cout<<file_<<":"<<lineNumber_<<" method "<<method_ + <<" : assertion \'"<<message_<<"\' failed."<<std::endl; + if(class_!="") + std::cout<<"Possible reason: "<<class_<<std::endl; + } + } + //@} + + + /**@name Constructors and destructors */ + //@{ + /// Alternate Constructor + CoinError ( + std::string message__, + std::string methodName__, + std::string className__, + std::string fileName_ = std::string(), + int line = -1) + : + message_(message__), + method_(methodName__), + class_(className__), + file_(fileName_), + lineNumber_(line) + { + print(printErrors_); + } + + /// Copy constructor + CoinError (const CoinError & source) + : + message_(source.message_), + method_(source.method_), + class_(source.class_), + file_(source.file_), + lineNumber_(source.lineNumber_) + { + // nothing to do here + } + + /// Assignment operator + CoinError & operator=(const CoinError& rhs) + { + if (this != &rhs) { + message_=rhs.message_; + method_=rhs.method_; + class_=rhs.class_; + file_=rhs.file_; + lineNumber_ = rhs.lineNumber_; + } + return *this; + } + + /// Destructor + virtual ~CoinError () + { + // nothing to do here + } + //@} + +private: + + /**@name Private member data */ + //@{ + /// message test + std::string message_; + /// method name + std::string method_; + /// class name or hint + std::string class_; + /// file name + std::string file_; + /// Line number + int lineNumber_; + //@} + +public: + /// Whether to print every error + static bool printErrors_; +}; + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#ifndef __GNUC_PREREQ +# define __GNUC_PREREQ(maj, min) (0) +#endif + +#ifndef COIN_ASSERT +# define CoinAssertDebug(expression) assert(expression) +# define CoinAssertDebugHint(expression,hint) assert(expression) +# define CoinAssert(expression) assert(expression) +# define CoinAssertHint(expression,hint) assert(expression) +#else +# ifdef NDEBUG +# define CoinAssertDebug(expression) {} +# define CoinAssertDebugHint(expression,hint) {} +# else +# if defined(__GNUC__) && __GNUC_PREREQ(2, 6) +# define CoinAssertDebug(expression) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + "", __FILE__, __LINE__); \ + } \ + } +# define CoinAssertDebugHint(expression,hint) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + hint, __FILE__,__LINE__); \ + } \ + } +# else +# define CoinAssertDebug(expression) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + "", __FILE__,__LINE__); \ + } \ + } +# define CoinAssertDebugHint(expression,hint) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + hint, __FILE__,__LINE__); \ + } \ + } +# endif +# endif +# if defined(__GNUC__) && __GNUC_PREREQ(2, 6) +# define CoinAssert(expression) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + "", __FILE__, __LINE__); \ + } \ + } +# define CoinAssertHint(expression,hint) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + hint, __FILE__,__LINE__); \ + } \ + } +# else +# define CoinAssert(expression) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + "", __FILE__,__LINE__); \ + } \ + } +# define CoinAssertHint(expression,hint) { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + hint, __FILE__,__LINE__); \ + } \ + } +# endif +#endif + + +//############################################################################# +/** A function that tests the methods in the CoinError class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void +CoinErrorUnitTest(); + +#ifdef __LINE__ +#define CoinErrorFL(x, y, z) CoinError((x), (y), (z), __FILE__, __LINE__) +#endif + +#endif diff --git a/thirdparty/linux/include/coin/CoinFactorization.hpp b/thirdparty/linux/include/coin/CoinFactorization.hpp new file mode 100644 index 0000000..0a532bf --- /dev/null +++ b/thirdparty/linux/include/coin/CoinFactorization.hpp @@ -0,0 +1,2044 @@ +/* $Id: CoinFactorization.hpp 1767 2015-01-05 12:36:13Z 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). + +/* + Authors + + John Forrest + + */ +#ifndef CoinFactorization_H +#define CoinFactorization_H +//#define COIN_ONE_ETA_COPY 100 + +#include <iostream> +#include <string> +#include <cassert> +#include <cstdio> +#include <cmath> +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" + +class CoinPackedMatrix; +/** This deals with Factorization and Updates + + This class started with a parallel simplex code I was writing in the + mid 90's. The need for parallelism led to many complications and + I have simplified as much as I could to get back to this. + + I was aiming at problems where I might get speed-up so I was looking at dense + problems or ones with structure. This led to permuting input and output + vectors and to increasing the number of rows each rank-one update. This is + still in as a minor overhead. + + I have also put in handling for hyper-sparsity. I have taken out + all outer loop unrolling, dense matrix handling and most of the + book-keeping for slacks. Also I always use FTRAN approach to updating + even if factorization fairly dense. All these could improve performance. + + I blame some of the coding peculiarities on the history of the code + but mostly it is just because I can't do elegant code (or useful + comments). + + I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex + may be redefined to get 64 bits. + */ + + +class CoinFactorization { + friend void CoinFactorizationUnitTest( const std::string & mpsDir ); + +public: + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinFactorization ( ); + /// Copy constructor + CoinFactorization ( const CoinFactorization &other); + + /// Destructor + ~CoinFactorization ( ); + /// Delete all stuff (leaves as after CoinFactorization()) + void almostDestructor(); + /// Debug show object (shows one representation) + void show_self ( ) const; + /// Debug - save on file - 0 if no error + int saveFactorization (const char * file ) const; + /** Debug - restore from file - 0 if no error on file. + If factor true then factorizes as if called from ClpFactorization + */ + int restoreFactorization (const char * file , bool factor=false) ; + /// Debug - sort so can compare + void sort ( ) const; + /// = copy + CoinFactorization & operator = ( const CoinFactorization & other ); + //@} + + /**@name Do factorization */ + //@{ + /** When part of LP - given by basic variables. + Actually does factorization. + Arrays passed in have non negative value to say basic. + If status is okay, basic variables have pivot row - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ + int factorize ( const CoinPackedMatrix & matrix, + int rowIsBasic[], int columnIsBasic[] , + double areaFactor = 0.0 ); + /** When given as triplets. + Actually does factorization. maximumL is guessed maximum size of L part of + final factorization, maximumU of U part. These are multiplied by + areaFactor which can be computed by user or internally. + Arrays are copied in. I could add flag to delete arrays to save a + bit of memory. + If status okay, permutation has pivot rows - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -99 memory */ + int factorize ( int numberRows, + int numberColumns, + CoinBigIndex numberElements, + CoinBigIndex maximumL, + CoinBigIndex maximumU, + const int indicesRow[], + const int indicesColumn[], const double elements[] , + int permutation[], + double areaFactor = 0.0); + /** Two part version for maximum flexibility + This part creates arrays for user to fill. + estimateNumberElements is safe estimate of number + returns 0 -okay, -99 memory */ + int factorizePart1 ( int numberRows, + int numberColumns, + CoinBigIndex estimateNumberElements, + int * indicesRow[], + int * indicesColumn[], + CoinFactorizationDouble * elements[], + double areaFactor = 0.0); + /** This is part two of factorization + Arrays belong to factorization and were returned by part 1 + If status okay, permutation has pivot rows - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -99 memory */ + int factorizePart2 (int permutation[],int exactNumberElements); + /// Condition number - product of pivots after factorization + double conditionNumber() const; + + //@} + + /**@name general stuff such as permutation or status */ + //@{ + /// Returns status + inline int status ( ) const { + return status_; + } + /// Sets status + inline void setStatus ( int value) + { status_=value; } + /// Returns number of pivots since factorization + inline int pivots ( ) const { + return numberPivots_; + } + /// Sets number of pivots since factorization + inline void setPivots ( int value ) + { numberPivots_=value; } + /// Returns address of permute region + inline int *permute ( ) const { + return permute_.array(); + } + /// Returns address of pivotColumn region (also used for permuting) + inline int *pivotColumn ( ) const { + return pivotColumn_.array(); + } + /// Returns address of pivot region + inline CoinFactorizationDouble *pivotRegion ( ) const { + return pivotRegion_.array(); + } + /// Returns address of permuteBack region + inline int *permuteBack ( ) const { + return permuteBack_.array(); + } + /// Returns address of lastRow region + inline int *lastRow ( ) const { + return lastRow_.array(); + } + /** Returns address of pivotColumnBack region (also used for permuting) + Now uses firstCount to save memory allocation */ + inline int *pivotColumnBack ( ) const { + //return firstCount_.array(); + return pivotColumnBack_.array(); + } + /// Start of each row in L + inline CoinBigIndex * startRowL() const + { return startRowL_.array();} + + /// Start of each column in L + inline CoinBigIndex * startColumnL() const + { return startColumnL_.array();} + + /// Index of column in row for L + inline int * indexColumnL() const + { return indexColumnL_.array();} + + /// Row indices of L + inline int * indexRowL() const + { return indexRowL_.array();} + + /// Elements in L (row copy) + inline CoinFactorizationDouble * elementByRowL() const + { return elementByRowL_.array();} + + /// Number of Rows after iterating + inline int numberRowsExtra ( ) const { + return numberRowsExtra_; + } + /// Set number of Rows after factorization + inline void setNumberRows(int value) + { numberRows_ = value; } + /// Number of Rows after factorization + inline int numberRows ( ) const { + return numberRows_; + } + /// Number in L + inline CoinBigIndex numberL() const + { return numberL_;} + + /// Base of L + inline CoinBigIndex baseL() const + { return baseL_;} + /// Maximum of Rows after iterating + inline int maximumRowsExtra ( ) const { + return maximumRowsExtra_; + } + /// Total number of columns in factorization + inline int numberColumns ( ) const { + return numberColumns_; + } + /// Total number of elements in factorization + inline int numberElements ( ) const { + return totalElements_; + } + /// Length of FT vector + inline int numberForrestTomlin ( ) const { + return numberInColumn_.array()[numberColumnsExtra_]; + } + /// Number of good columns in factorization + inline int numberGoodColumns ( ) const { + return numberGoodU_; + } + /// Whether larger areas needed + inline double areaFactor ( ) const { + return areaFactor_; + } + inline void areaFactor ( double value ) { + areaFactor_=value; + } + /// Returns areaFactor but adjusted for dense + double adjustedAreaFactor() const; + /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed + inline void relaxAccuracyCheck(double value) + { relaxCheck_ = value;} + inline double getAccuracyCheck() const + { return relaxCheck_;} + /// Level of detail of messages + inline int messageLevel ( ) const { + return messageLevel_ ; + } + void messageLevel ( int value ); + /// Maximum number of pivots between factorizations + inline int maximumPivots ( ) const { + return maximumPivots_ ; + } + void maximumPivots ( int value ); + + /// Gets dense threshold + inline int denseThreshold() const + { return denseThreshold_;} + /// Sets dense threshold + inline void setDenseThreshold(int value) + { denseThreshold_ = value;} + /// Pivot tolerance + inline double pivotTolerance ( ) const { + return pivotTolerance_ ; + } + void pivotTolerance ( double value ); + /// Zero tolerance + inline double zeroTolerance ( ) const { + return zeroTolerance_ ; + } + void zeroTolerance ( double value ); +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + inline double slackValue ( ) const { + return slackValue_ ; + } + void slackValue ( double value ); +#endif + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + /// true if Forrest Tomlin update, false if PFI + inline bool forrestTomlin() const + { return doForrestTomlin_;} + inline void setForrestTomlin(bool value) + { doForrestTomlin_=value;} + /// True if FT update and space + inline bool spaceForForrestTomlin() const + { + CoinBigIndex start = startColumnU_.array()[maximumColumnsExtra_]; + CoinBigIndex space = lengthAreaU_ - ( start + numberRowsExtra_ ); + return (space>=0)&&doForrestTomlin_; + } + //@} + + /**@name some simple stuff */ + //@{ + + /// Returns number of dense rows + inline int numberDense() const + { return numberDense_;} + + /// Returns number in U area + inline CoinBigIndex numberElementsU ( ) const { + return lengthU_; + } + /// Setss number in U area + inline void setNumberElementsU(CoinBigIndex value) + { lengthU_ = value; } + /// Returns length of U area + inline CoinBigIndex lengthAreaU ( ) const { + return lengthAreaU_; + } + /// Returns number in L area + inline CoinBigIndex numberElementsL ( ) const { + return lengthL_; + } + /// Returns length of L area + inline CoinBigIndex lengthAreaL ( ) const { + return lengthAreaL_; + } + /// Returns number in R area + inline CoinBigIndex numberElementsR ( ) const { + return lengthR_; + } + /// Number of compressions done + inline CoinBigIndex numberCompressions() const + { return numberCompressions_;} + /// Number of entries in each row + inline int * numberInRow() const + { return numberInRow_.array();} + /// Number of entries in each column + inline int * numberInColumn() const + { return numberInColumn_.array();} + /// Elements of U + inline CoinFactorizationDouble * elementU() const + { return elementU_.array();} + /// Row indices of U + inline int * indexRowU() const + { return indexRowU_.array();} + /// Start of each column in U + inline CoinBigIndex * startColumnU() const + { return startColumnU_.array();} + /// Maximum number of Columns after iterating + inline int maximumColumnsExtra() + { return maximumColumnsExtra_;} + /** L to U bias + 0 - U bias, 1 - some U bias, 2 some L bias, 3 L bias + */ + inline int biasLU() const + { return biasLU_;} + inline void setBiasLU(int value) + { biasLU_=value;} + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + inline int persistenceFlag() const + { return persistenceFlag_;} + void setPersistenceFlag(int value); + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + int replaceColumn ( CoinIndexedVector * regionSparse, + int pivotRow, + double pivotCheck , + bool checkBeforeModifying=false, + double acceptablePivot=1.0e-8); + /** Combines BtranU and delete elements + If deleted is NULL then delete elements + otherwise store where elements are + */ + void replaceColumnU ( CoinIndexedVector * regionSparse, + CoinBigIndex * deleted, + int internalPivotRow); +#ifdef ABC_USE_COIN_FACTORIZATION + /** returns empty fake vector carved out of existing + later - maybe use associated arrays */ + CoinIndexedVector * fakeVector(CoinIndexedVector * vector, + int already=0) const; + void deleteFakeVector(CoinIndexedVector * vector, + CoinIndexedVector * fakeVector) const; + /** Checks if can replace one Column to basis, + returns update alpha + Fills in region for use later + partial update already in U */ + double checkReplacePart1 ( CoinIndexedVector * regionSparse, + int pivotRow); + /** Checks if can replace one Column to basis, + returns update alpha + Fills in region for use later + partial update in vector */ + double checkReplacePart1 ( CoinIndexedVector * regionSparse, + CoinIndexedVector * partialUpdate, + int pivotRow); + /** Checks if can replace one Column in basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ + int checkReplacePart2 ( int pivotRow, + double btranAlpha, + double ftranAlpha, + double ftAlpha, + double acceptablePivot = 1.0e-8); + /** Replaces one Column to basis, + partial update already in U */ + void replaceColumnPart3 ( CoinIndexedVector * regionSparse, + int pivotRow, + double alpha ); + /** Replaces one Column to basis, + partial update in vector */ + void replaceColumnPart3 ( CoinIndexedVector * regionSparse, + CoinIndexedVector * partialUpdate, + int pivotRow, + double alpha ); + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + long regions + */ + int updateColumnFT ( CoinIndexedVector & regionSparse); + int updateColumnFTPart1 ( CoinIndexedVector & regionSparse) ; + void updateColumnFTPart2 ( CoinIndexedVector & regionSparse) ; + /** Updates one column (FTRAN) - long region + Tries to do FT update + puts partial update in vector */ + void updateColumnFT ( CoinIndexedVector & regionSparseFT, + CoinIndexedVector & partialUpdate, + int which); + /** Updates one column (FTRAN) long region */ + int updateColumn ( CoinIndexedVector & regionSparse) const; + /** Updates one column (FTRAN) from regionFT + Tries to do FT update + number returned is negative if no room. + Also updates regionOther - long region*/ + int updateTwoColumnsFT ( CoinIndexedVector & regionSparseFT, + CoinIndexedVector & regionSparseOther); + /** Updates one column (BTRAN) - long region*/ + int updateColumnTranspose ( CoinIndexedVector & regionSparse) const; + /** Updates one column (FTRAN) - long region */ + void updateColumnCpu ( CoinIndexedVector & regionSparse,int whichCpu) const; + /** Updates one column (BTRAN) - long region */ + void updateColumnTransposeCpu ( CoinIndexedVector & regionSparse,int whichCpu) const; + /** Updates one full column (FTRAN) - long region */ + void updateFullColumn ( CoinIndexedVector & regionSparse) const; + /** Updates one full column (BTRAN) - long region */ + void updateFullColumnTranspose ( CoinIndexedVector & regionSparse) const; + /** Updates one column for dual steepest edge weights (FTRAN) - long region */ + void updateWeights ( CoinIndexedVector & regionSparse) const; + /// Returns true if wants tableauColumn in replaceColumn + inline bool wantsTableauColumn() const + {return false;} + /// Pivot tolerance + inline double minimumPivotTolerance ( ) const { + return pivotTolerance_ ; + } + inline void minimumPivotTolerance ( double value ) + { pivotTolerance(value);} + /// Says parallel + inline void setParallelMode(int value) + { parallelMode_=value;} + /// Sets solve mode + inline void setSolveMode(int value) + { parallelMode_ &= 3;parallelMode_ |= (value<<2);} + /// Sets solve mode + inline int solveMode() const + { return parallelMode_ >> 2;} + /// Update partial Ftran by R update + void updatePartialUpdate(CoinIndexedVector & partialUpdate); + /// Makes a non-singular basis by replacing variables + void makeNonSingular(int * COIN_RESTRICT sequence); +#endif + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + int updateColumnFT ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2); + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + int updateColumn ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false) const; + /** Updates one column (FTRAN) from region2 + Tries to do FT update + number returned is negative if no room. + Also updates region3 + region1 starts as zero and is zero at end */ + int updateTwoColumnsFT ( CoinIndexedVector * regionSparse1, + CoinIndexedVector * regionSparse2, + CoinIndexedVector * regionSparse3, + bool noPermuteRegion3=false) ; + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + int updateColumnTranspose ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2) const; + /** makes a row copy of L for speed and to allow very sparse problems */ + void goSparse(); + /** get sparse threshold */ + inline int sparseThreshold ( ) const + { return sparseThreshold_;} + /** set sparse threshold */ + void sparseThreshold ( int value ); + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization (return code number elements) + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + inline void clearArrays() + { gutsOfDestructor();} + //@} + + /**@name various updates - none of which have been written! */ + //@{ + + /** Adds given elements to Basis and updates factorization, + can increase size of basis. Returns rank */ + int add ( CoinBigIndex numberElements, + int indicesRow[], + int indicesColumn[], double elements[] ); + + /** Adds one Column to basis, + can increase size of basis. Returns rank */ + int addColumn ( CoinBigIndex numberElements, + int indicesRow[], double elements[] ); + + /** Adds one Row to basis, + can increase size of basis. Returns rank */ + int addRow ( CoinBigIndex numberElements, + int indicesColumn[], double elements[] ); + + /// Deletes one Column from basis, returns rank + int deleteColumn ( int Row ); + /// Deletes one Row from basis, returns rank + int deleteRow ( int Row ); + + /** Replaces one Row in basis, + At present assumes just a singleton on row is in basis + returns 0=OK, 1=Probably OK, 2=singular, 3 no space */ + int replaceRow ( int whichRow, int numberElements, + const int indicesColumn[], const double elements[] ); + /// Takes out all entries for given rows + void emptyRows(int numberToEmpty, const int which[]); + //@} + /**@name used by ClpFactorization */ + /// See if worth going sparse + void checkSparse(); + /// For statistics +#if 0 //def CLP_FACTORIZATION_INSTRUMENT + inline bool collectStatistics() const + { return collectStatistics_;} + /// For statistics + inline void setCollectStatistics(bool onOff) const + { collectStatistics_ = onOff;} +#else + inline bool collectStatistics() const + { return true;} + /// For statistics + inline void setCollectStatistics(bool onOff) const + { } +#endif + /// The real work of constructors etc 0 just scalars, 1 bit normal + void gutsOfDestructor(int type=1); + /// 1 bit - tolerances etc, 2 more, 4 dummy arrays + void gutsOfInitialize(int type); + void gutsOfCopy(const CoinFactorization &other); + + /// Reset all sparsity etc statistics + void resetStatistics(); + + + //@} + + /**@name used by factorization */ + /// Gets space for a factorization, called by constructors + void getAreas ( int numberRows, + int numberColumns, + CoinBigIndex maximumL, + CoinBigIndex maximumU ); + + /** PreProcesses raw triplet data. + state is 0 - triplets, 1 - some counts etc , 2 - .. */ + void preProcess ( int state, + int possibleDuplicates = -1 ); + /// Does most of factorization + int factor ( ); +protected: + /** Does sparse phase of factorization + return code is <0 error, 0= finished */ + int factorSparse ( ); + /** Does sparse phase of factorization (for smaller problems) + return code is <0 error, 0= finished */ + int factorSparseSmall ( ); + /** Does sparse phase of factorization (for larger problems) + return code is <0 error, 0= finished */ + int factorSparseLarge ( ); + /** Does dense phase of factorization + return code is <0 error, 0= finished */ + int factorDense ( ); + + /// Pivots when just one other row so faster? + bool pivotOneOtherRow ( int pivotRow, + int pivotColumn ); + /// Does one pivot on Row Singleton in factorization + bool pivotRowSingleton ( int pivotRow, + int pivotColumn ); + /// Does one pivot on Column Singleton in factorization + bool pivotColumnSingleton ( int pivotRow, + int pivotColumn ); + + /** Gets space for one Column with given length, + may have to do compression (returns True if successful), + also moves existing vector, + extraNeeded is over and above present */ + bool getColumnSpace ( int iColumn, + int extraNeeded ); + + /** Reorders U so contiguous and in order (if there is space) + Returns true if it could */ + bool reorderU(); + /** getColumnSpaceIterateR. Gets space for one extra R element in Column + may have to do compression (returns true) + also moves existing vector */ + bool getColumnSpaceIterateR ( int iColumn, double value, + int iRow); + /** getColumnSpaceIterate. Gets space for one extra U element in Column + may have to do compression (returns true) + also moves existing vector. + Returns -1 if no memory or where element was put + Used by replaceRow (turns off R version) */ + CoinBigIndex getColumnSpaceIterate ( int iColumn, double value, + int iRow); + /** Gets space for one Row with given length, + may have to do compression (returns True if successful), + also moves existing vector */ + bool getRowSpace ( int iRow, int extraNeeded ); + + /** Gets space for one Row with given length while iterating, + may have to do compression (returns True if successful), + also moves existing vector */ + bool getRowSpaceIterate ( int iRow, + int extraNeeded ); + /// Checks that row and column copies look OK + void checkConsistency ( ); + /// Adds a link in chain of equal counts + inline void addLink ( int index, int count ) { + int *nextCount = nextCount_.array(); + int *firstCount = firstCount_.array(); + int *lastCount = lastCount_.array(); + int next = firstCount[count]; + lastCount[index] = -2 - count; + if ( next < 0 ) { + //first with that count + firstCount[count] = index; + nextCount[index] = -1; + } else { + firstCount[count] = index; + nextCount[index] = next; + lastCount[next] = index; + }} + /// Deletes a link in chain of equal counts + inline void deleteLink ( int index ) { + int *nextCount = nextCount_.array(); + int *firstCount = firstCount_.array(); + int *lastCount = lastCount_.array(); + int next = nextCount[index]; + int last = lastCount[index]; + if ( last >= 0 ) { + nextCount[last] = next; + } else { + int count = -last - 2; + + firstCount[count] = next; + } + if ( next >= 0 ) { + lastCount[next] = last; + } + nextCount[index] = -2; + lastCount[index] = -2; + return; + } + /// Separate out links with same row/column count + void separateLinks(int count,bool rowsFirst); + /// Cleans up at end of factorization + void cleanup ( ); + + /// Updates part of column (FTRANL) + void updateColumnL ( CoinIndexedVector * region, int * indexIn ) const; + /// Updates part of column (FTRANL) when densish + void updateColumnLDensish ( CoinIndexedVector * region, int * indexIn ) const; + /// Updates part of column (FTRANL) when sparse + void updateColumnLSparse ( CoinIndexedVector * region, int * indexIn ) const; + /// Updates part of column (FTRANL) when sparsish + void updateColumnLSparsish ( CoinIndexedVector * region, int * indexIn ) const; + + /// Updates part of column (FTRANR) without FT update + void updateColumnR ( CoinIndexedVector * region ) const; + /** Updates part of column (FTRANR) with FT update. + Also stores update after L and R */ + void updateColumnRFT ( CoinIndexedVector * region, int * indexIn ); + + /// Updates part of column (FTRANU) + void updateColumnU ( CoinIndexedVector * region, int * indexIn) const; + + /// Updates part of column (FTRANU) when sparse + void updateColumnUSparse ( CoinIndexedVector * regionSparse, + int * indexIn) const; + /// Updates part of column (FTRANU) when sparsish + void updateColumnUSparsish ( CoinIndexedVector * regionSparse, + int * indexIn) const; + /// Updates part of column (FTRANU) + int updateColumnUDensish ( double * COIN_RESTRICT region, + int * COIN_RESTRICT regionIndex) const; + /// Updates part of 2 columns (FTRANU) real work + void updateTwoColumnsUDensish ( + int & numberNonZero1, + double * COIN_RESTRICT region1, + int * COIN_RESTRICT index1, + int & numberNonZero2, + double * COIN_RESTRICT region2, + int * COIN_RESTRICT index2) const; + /// Updates part of column PFI (FTRAN) (after rest) + void updateColumnPFI ( CoinIndexedVector * regionSparse) const; + /// Permutes back at end of updateColumn + void permuteBack ( CoinIndexedVector * regionSparse, + CoinIndexedVector * outVector) const; + + /// Updates part of column transpose PFI (BTRAN) (before rest) + void updateColumnTransposePFI ( CoinIndexedVector * region) const; + /** Updates part of column transpose (BTRANU), + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeU ( CoinIndexedVector * region, + int smallestIndex) const; + /** Updates part of column transpose (BTRANU) when sparsish, + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUSparsish ( CoinIndexedVector * region, + int smallestIndex) const; + /** Updates part of column transpose (BTRANU) when densish, + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUDensish ( CoinIndexedVector * region, + int smallestIndex) const; + /** Updates part of column transpose (BTRANU) when sparse, + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUSparse ( CoinIndexedVector * region) const; + /** Updates part of column transpose (BTRANU) by column + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUByColumn ( CoinIndexedVector * region, + int smallestIndex) const; + + /// Updates part of column transpose (BTRANR) + void updateColumnTransposeR ( CoinIndexedVector * region ) const; + /// Updates part of column transpose (BTRANR) when dense + void updateColumnTransposeRDensish ( CoinIndexedVector * region ) const; + /// Updates part of column transpose (BTRANR) when sparse + void updateColumnTransposeRSparse ( CoinIndexedVector * region ) const; + + /// Updates part of column transpose (BTRANL) + void updateColumnTransposeL ( CoinIndexedVector * region ) const; + /// Updates part of column transpose (BTRANL) when densish by column + void updateColumnTransposeLDensish ( CoinIndexedVector * region ) const; + /// Updates part of column transpose (BTRANL) when densish by row + void updateColumnTransposeLByRow ( CoinIndexedVector * region ) const; + /// Updates part of column transpose (BTRANL) when sparsish by row + void updateColumnTransposeLSparsish ( CoinIndexedVector * region ) const; + /// Updates part of column transpose (BTRANL) when sparse (by Row) + void updateColumnTransposeLSparse ( CoinIndexedVector * region ) const; +public: + /** Replaces one Column to basis for PFI + returns 0=OK, 1=Probably OK, 2=singular, 3=no room. + In this case region is not empty - it is incoming variable (updated) + */ + int replaceColumnPFI ( CoinIndexedVector * regionSparse, + int pivotRow, double alpha); +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; + /********************************* START LARGE TEMPLATE ********/ +#ifdef INT_IS_8 +#define COINFACTORIZATION_BITS_PER_INT 64 +#define COINFACTORIZATION_SHIFT_PER_INT 6 +#define COINFACTORIZATION_MASK_PER_INT 0x3f +#else +#define COINFACTORIZATION_BITS_PER_INT 32 +#define COINFACTORIZATION_SHIFT_PER_INT 5 +#define COINFACTORIZATION_MASK_PER_INT 0x1f +#endif + template <class T> inline bool + pivot ( int pivotRow, + int pivotColumn, + CoinBigIndex pivotRowPosition, + CoinBigIndex pivotColumnPosition, + CoinFactorizationDouble work[], + unsigned int workArea2[], + int increment2, + T markRow[] , + int largeInteger) +{ + int *indexColumnU = indexColumnU_.array(); + CoinBigIndex *startColumnU = startColumnU_.array(); + int *numberInColumn = numberInColumn_.array(); + CoinFactorizationDouble *elementU = elementU_.array(); + int *indexRowU = indexRowU_.array(); + CoinBigIndex *startRowU = startRowU_.array(); + int *numberInRow = numberInRow_.array(); + CoinFactorizationDouble *elementL = elementL_.array(); + int *indexRowL = indexRowL_.array(); + int *saveColumn = saveColumn_.array(); + int *nextRow = nextRow_.array(); + int *lastRow = lastRow_.array() ; + + //store pivot columns (so can easily compress) + int numberInPivotRow = numberInRow[pivotRow] - 1; + CoinBigIndex startColumn = startColumnU[pivotColumn]; + int numberInPivotColumn = numberInColumn[pivotColumn] - 1; + CoinBigIndex endColumn = startColumn + numberInPivotColumn + 1; + int put = 0; + CoinBigIndex startRow = startRowU[pivotRow]; + CoinBigIndex endRow = startRow + numberInPivotRow + 1; + + if ( pivotColumnPosition < 0 ) { + for ( pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++ ) { + int iColumn = indexColumnU[pivotColumnPosition]; + if ( iColumn != pivotColumn ) { + saveColumn[put++] = iColumn; + } else { + break; + } + } + } else { + for (CoinBigIndex i = startRow ; i < pivotColumnPosition ; i++ ) { + saveColumn[put++] = indexColumnU[i]; + } + } + assert (pivotColumnPosition<endRow); + assert (indexColumnU[pivotColumnPosition]==pivotColumn); + pivotColumnPosition++; + for ( ; pivotColumnPosition < endRow; pivotColumnPosition++ ) { + saveColumn[put++] = indexColumnU[pivotColumnPosition]; + } + //take out this bit of indexColumnU + int next = nextRow[pivotRow]; + int last = lastRow[pivotRow]; + + nextRow[last] = next; + lastRow[next] = last; + nextRow[pivotRow] = numberGoodU_; //use for permute + lastRow[pivotRow] = -2; + numberInRow[pivotRow] = 0; + //store column in L, compress in U and take column out + CoinBigIndex l = lengthL_; + + if ( l + numberInPivotColumn > lengthAreaL_ ) { + //need more memory + if ((messageLevel_&4)!=0) + printf("more memory needed in middle of invert\n"); + return false; + } + //l+=currentAreaL_->elementByColumn-elementL; + CoinBigIndex lSave = l; + + CoinBigIndex * startColumnL = startColumnL_.array(); + startColumnL[numberGoodL_] = l; //for luck and first time + numberGoodL_++; + startColumnL[numberGoodL_] = l + numberInPivotColumn; + lengthL_ += numberInPivotColumn; + if ( pivotRowPosition < 0 ) { + for ( pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++ ) { + int iRow = indexRowU[pivotRowPosition]; + if ( iRow != pivotRow ) { + indexRowL[l] = iRow; + elementL[l] = elementU[pivotRowPosition]; + markRow[iRow] = static_cast<T>(l - lSave); + l++; + //take out of row list + CoinBigIndex start = startRowU[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumnU[where] != pivotColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + } else { + break; + } + } + } else { + CoinBigIndex i; + + for ( i = startColumn; i < pivotRowPosition; i++ ) { + int iRow = indexRowU[i]; + + markRow[iRow] = static_cast<T>(l - lSave); + indexRowL[l] = iRow; + elementL[l] = elementU[i]; + l++; + //take out of row list + CoinBigIndex start = startRowU[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumnU[where] != pivotColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + assert (numberInRow[iRow]>=0); + } + } + assert (pivotRowPosition<endColumn); + assert (indexRowU[pivotRowPosition]==pivotRow); + CoinFactorizationDouble pivotElement = elementU[pivotRowPosition]; + CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement; + + pivotRegion_.array()[numberGoodU_] = pivotMultiplier; + pivotRowPosition++; + for ( ; pivotRowPosition < endColumn; pivotRowPosition++ ) { + int iRow = indexRowU[pivotRowPosition]; + + markRow[iRow] = static_cast<T>(l - lSave); + indexRowL[l] = iRow; + elementL[l] = elementU[pivotRowPosition]; + l++; + //take out of row list + CoinBigIndex start = startRowU[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumnU[where] != pivotColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + assert (numberInRow[iRow]>=0); + } + markRow[pivotRow] = static_cast<T>(largeInteger); + //compress pivot column (move pivot to front including saved) + numberInColumn[pivotColumn] = 0; + //use end of L for temporary space + int *indexL = &indexRowL[lSave]; + CoinFactorizationDouble *multipliersL = &elementL[lSave]; + + //adjust + int j; + + for ( j = 0; j < numberInPivotColumn; j++ ) { + multipliersL[j] *= pivotMultiplier; + } + //zero out fill + CoinBigIndex iErase; + for ( iErase = 0; iErase < increment2 * numberInPivotRow; + iErase++ ) { + workArea2[iErase] = 0; + } + CoinBigIndex added = numberInPivotRow * numberInPivotColumn; + unsigned int *temp2 = workArea2; + int * nextColumn = nextColumn_.array(); + + //pack down and move to work + int jColumn; + for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { + int iColumn = saveColumn[jColumn]; + CoinBigIndex startColumn = startColumnU[iColumn]; + CoinBigIndex endColumn = startColumn + numberInColumn[iColumn]; + int iRow = indexRowU[startColumn]; + CoinFactorizationDouble value = elementU[startColumn]; + double largest; + CoinBigIndex put = startColumn; + CoinBigIndex positionLargest = -1; + CoinFactorizationDouble thisPivotValue = 0.0; + + //compress column and find largest not updated + bool checkLargest; + int mark = markRow[iRow]; + + if ( mark == largeInteger+1 ) { + largest = fabs ( value ); + positionLargest = put; + put++; + checkLargest = false; + } else { + //need to find largest + largest = 0.0; + checkLargest = true; + if ( mark != largeInteger ) { + //will be updated + work[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + CoinBigIndex i; + for ( i = startColumn + 1; i < endColumn; i++ ) { + iRow = indexRowU[i]; + value = elementU[i]; + int mark = markRow[iRow]; + + if ( mark == largeInteger+1 ) { + //keep + indexRowU[put] = iRow; + elementU[put] = value; + if ( checkLargest ) { + double absValue = fabs ( value ); + + if ( absValue > largest ) { + largest = absValue; + positionLargest = put; + } + } + put++; + } else if ( mark != largeInteger ) { + //will be updated + work[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + //slot in pivot + elementU[put] = elementU[startColumn]; + indexRowU[put] = indexRowU[startColumn]; + if ( positionLargest == startColumn ) { + positionLargest = put; //follow if was largest + } + put++; + elementU[startColumn] = thisPivotValue; + indexRowU[startColumn] = pivotRow; + //clean up counts + startColumn++; + numberInColumn[iColumn] = put - startColumn; + int * numberInColumnPlus = numberInColumnPlus_.array(); + numberInColumnPlus[iColumn]++; + startColumnU[iColumn]++; + //how much space have we got + int next = nextColumn[iColumn]; + CoinBigIndex space; + + space = startColumnU[next] - put - numberInColumnPlus[next]; + //assume no zero elements + if ( numberInPivotColumn > space ) { + //getColumnSpace also moves fixed part + if ( !getColumnSpace ( iColumn, numberInPivotColumn ) ) { + return false; + } + //redo starts + if (positionLargest >= 0) + positionLargest = positionLargest + startColumnU[iColumn] - startColumn; + startColumn = startColumnU[iColumn]; + put = startColumn + numberInColumn[iColumn]; + } + double tolerance = zeroTolerance_; + + int *nextCount = nextCount_.array(); + for ( j = 0; j < numberInPivotColumn; j++ ) { + value = work[j] - thisPivotValue * multipliersL[j]; + double absValue = fabs ( value ); + + if ( absValue > tolerance ) { + work[j] = 0.0; + assert (put<lengthAreaU_); + elementU[put] = value; + indexRowU[put] = indexL[j]; + if ( absValue > largest ) { + largest = absValue; + positionLargest = put; + } + put++; + } else { + work[j] = 0.0; + added--; + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + if ( temp2[word] & ( 1 << bit ) ) { + //take out of row list + iRow = indexL[j]; + CoinBigIndex start = startRowU[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumnU[where] != iColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + } else { + //make sure won't be added + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts + } + } + } + numberInColumn[iColumn] = put - startColumn; + //move largest + if ( positionLargest >= 0 ) { + value = elementU[positionLargest]; + iRow = indexRowU[positionLargest]; + elementU[positionLargest] = elementU[startColumn]; + indexRowU[positionLargest] = indexRowU[startColumn]; + elementU[startColumn] = value; + indexRowU[startColumn] = iRow; + } + //linked list for column + if ( nextCount[iColumn + numberRows_] != -2 ) { + //modify linked list + deleteLink ( iColumn + numberRows_ ); + addLink ( iColumn + numberRows_, numberInColumn[iColumn] ); + } + temp2 += increment2; + } + //get space for row list + unsigned int *putBase = workArea2; + int bigLoops = numberInPivotColumn >> COINFACTORIZATION_SHIFT_PER_INT; + int i = 0; + + // do linked lists and update counts + while ( bigLoops ) { + bigLoops--; + int bit; + for ( bit = 0; bit < COINFACTORIZATION_BITS_PER_INT; i++, bit++ ) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + number += test; + } + int next = nextRow[iRow]; + CoinBigIndex space; + + space = startRowU[next] - startRowU[iRow]; + number += numberInRow[iRow]; + if ( space < number ) { + if ( !getRowSpace ( iRow, number ) ) { + return false; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + CoinBigIndex end = startRowU[iRow] + number; + int saveIndex = indexColumnU[startRowU[next]]; + + //add in + for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + indexColumnU[end] = saveColumn[jColumn]; + end += test; + } + //put back next one in case zapped + indexColumnU[startRowU[next]] = saveIndex; + markRow[iRow] = static_cast<T>(largeInteger+1); + number = end - startRowU[iRow]; + numberInRow[iRow] = number; + deleteLink ( iRow ); + addLink ( iRow, number ); + } + putBase++; + } /* endwhile */ + int bit; + + for ( bit = 0; i < numberInPivotColumn; i++, bit++ ) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + number += test; + } + int next = nextRow[iRow]; + CoinBigIndex space; + + space = startRowU[next] - startRowU[iRow]; + number += numberInRow[iRow]; + if ( space < number ) { + if ( !getRowSpace ( iRow, number ) ) { + return false; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + CoinBigIndex end = startRowU[iRow] + number; + int saveIndex; + + saveIndex = indexColumnU[startRowU[next]]; + + //add in + for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + + indexColumnU[end] = saveColumn[jColumn]; + end += test; + } + indexColumnU[startRowU[next]] = saveIndex; + markRow[iRow] = static_cast<T>(largeInteger+1); + number = end - startRowU[iRow]; + numberInRow[iRow] = number; + deleteLink ( iRow ); + addLink ( iRow, number ); + } + markRow[pivotRow] = static_cast<T>(largeInteger+1); + //modify linked list for pivots + deleteLink ( pivotRow ); + deleteLink ( pivotColumn + numberRows_ ); + totalElements_ += added; + return true; +} + + /********************************* END LARGE TEMPLATE ********/ + //@} +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + /// Pivot tolerance + double pivotTolerance_; + /// Zero tolerance + double zeroTolerance_; +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + double slackValue_; +#else +#ifndef slackValue_ +#define slackValue_ -1.0 +#endif +#endif + /// How much to multiply areas by + double areaFactor_; + /// Relax check on accuracy in replaceColumn + double relaxCheck_; + /// Number of Rows in factorization + int numberRows_; + /// Number of Rows after iterating + int numberRowsExtra_; + /// Maximum number of Rows after iterating + int maximumRowsExtra_; + /// Number of Columns in factorization + int numberColumns_; + /// Number of Columns after iterating + int numberColumnsExtra_; + /// Maximum number of Columns after iterating + int maximumColumnsExtra_; + /// Number factorized in U (not row singletons) + int numberGoodU_; + /// Number factorized in L + int numberGoodL_; + /// Maximum number of pivots before factorization + int maximumPivots_; + /// Number pivots since last factorization + int numberPivots_; + /// Number of elements in U (to go) + /// or while iterating total overall + CoinBigIndex totalElements_; + /// Number of elements after factorization + CoinBigIndex factorElements_; + /// Pivot order for each Column + CoinIntArrayWithLength pivotColumn_; + /// Permutation vector for pivot row order + CoinIntArrayWithLength permute_; + /// DePermutation vector for pivot row order + CoinIntArrayWithLength permuteBack_; + /// Inverse Pivot order for each Column + CoinIntArrayWithLength pivotColumnBack_; + /// Status of factorization + int status_; + + /** 0 - no increasing rows - no permutations, + 1 - no increasing rows but permutations + 2 - increasing rows + - taken out as always 2 */ + //int increasingRows_; + + /// Number of trials before rejection + int numberTrials_; + /// Start of each Row as pointer + CoinBigIndexArrayWithLength startRowU_; + + /// Number in each Row + CoinIntArrayWithLength numberInRow_; + + /// Number in each Column + CoinIntArrayWithLength numberInColumn_; + + /// Number in each Column including pivoted + CoinIntArrayWithLength numberInColumnPlus_; + + /** First Row/Column with count of k, + can tell which by offset - Rows then Columns */ + CoinIntArrayWithLength firstCount_; + + /// Next Row/Column with count + CoinIntArrayWithLength nextCount_; + + /// Previous Row/Column with count + CoinIntArrayWithLength lastCount_; + + /// Next Column in memory order + CoinIntArrayWithLength nextColumn_; + + /// Previous Column in memory order + CoinIntArrayWithLength lastColumn_; + + /// Next Row in memory order + CoinIntArrayWithLength nextRow_; + + /// Previous Row in memory order + CoinIntArrayWithLength lastRow_; + + /// Columns left to do in a single pivot + CoinIntArrayWithLength saveColumn_; + + /// Marks rows to be updated + CoinIntArrayWithLength markRow_; + + /// Detail in messages + int messageLevel_; + + /// Larger of row and column size + int biggerDimension_; + + /// Base address for U (may change) + CoinIntArrayWithLength indexColumnU_; + + /// Pivots for L + CoinIntArrayWithLength pivotRowL_; + + /// Inverses of pivot values + CoinFactorizationDoubleArrayWithLength pivotRegion_; + + /// Number of slacks at beginning of U + int numberSlacks_; + + /// Number in U + int numberU_; + + /// Maximum space used in U + CoinBigIndex maximumU_; + + /// Base of U is always 0 + //int baseU_; + + /// Length of U + CoinBigIndex lengthU_; + + /// Length of area reserved for U + CoinBigIndex lengthAreaU_; + +/// Elements of U + CoinFactorizationDoubleArrayWithLength elementU_; + +/// Row indices of U + CoinIntArrayWithLength indexRowU_; + +/// Start of each column in U + CoinBigIndexArrayWithLength startColumnU_; + +/// Converts rows to columns in U + CoinBigIndexArrayWithLength convertRowToColumnU_; + + /// Number in L + CoinBigIndex numberL_; + +/// Base of L + CoinBigIndex baseL_; + + /// Length of L + CoinBigIndex lengthL_; + + /// Length of area reserved for L + CoinBigIndex lengthAreaL_; + + /// Elements of L + CoinFactorizationDoubleArrayWithLength elementL_; + + /// Row indices of L + CoinIntArrayWithLength indexRowL_; + + /// Start of each column in L + CoinBigIndexArrayWithLength startColumnL_; + + /// true if Forrest Tomlin update, false if PFI + bool doForrestTomlin_; + + /// Number in R + int numberR_; + + /// Length of R stuff + CoinBigIndex lengthR_; + + /// length of area reserved for R + CoinBigIndex lengthAreaR_; + + /// Elements of R + CoinFactorizationDouble *elementR_; + + /// Row indices for R + int *indexRowR_; + + /// Start of columns for R + CoinBigIndexArrayWithLength startColumnR_; + + /// Dense area + double * denseArea_; + + /// Dense area - actually used (for alignment etc) + double * denseAreaAddress_; + + /// Dense permutation + int * densePermute_; + + /// Number of dense rows + int numberDense_; + + /// Dense threshold + int denseThreshold_; + + /// First work area + CoinFactorizationDoubleArrayWithLength workArea_; + + /// Second work area + CoinUnsignedIntArrayWithLength workArea2_; + + /// Number of compressions done + CoinBigIndex numberCompressions_; + +public: + /// Below are all to collect + mutable double ftranCountInput_; + mutable double ftranCountAfterL_; + mutable double ftranCountAfterR_; + mutable double ftranCountAfterU_; + mutable double btranCountInput_; + mutable double btranCountAfterU_; + mutable double btranCountAfterR_; + mutable double btranCountAfterL_; + + /// We can roll over factorizations + mutable int numberFtranCounts_; + mutable int numberBtranCounts_; + + /// While these are average ratios collected over last period + double ftranAverageAfterL_; + double ftranAverageAfterR_; + double ftranAverageAfterU_; + double btranAverageAfterU_; + double btranAverageAfterR_; + double btranAverageAfterL_; +protected: + + /// For statistics +#if 0 + mutable bool collectStatistics_; +#else +#define collectStatistics_ 1 +#endif + + /// Below this use sparse technology - if 0 then no L row copy + int sparseThreshold_; + + /// And one for "sparsish" + int sparseThreshold2_; + + /// Start of each row in L + CoinBigIndexArrayWithLength startRowL_; + + /// Index of column in row for L + CoinIntArrayWithLength indexColumnL_; + + /// Elements in L (row copy) + CoinFactorizationDoubleArrayWithLength elementByRowL_; + + /// Sparse regions + mutable CoinIntArrayWithLength sparse_; + /** L to U bias + 0 - U bias, 1 - some U bias, 2 some L bias, 3 L bias + */ + int biasLU_; + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + int persistenceFlag_; +#ifdef ABC_USE_COIN_FACTORIZATION + /// Says if parallel + int parallelMode_; +#endif + //@} +}; +// Dense coding +#ifdef COIN_HAS_LAPACK +#ifndef COIN_FACTORIZATION_DENSE_CODE +#define COIN_FACTORIZATION_DENSE_CODE 1 +#endif +#endif +#ifdef COIN_FACTORIZATION_DENSE_CODE +/* Type of Fortran integer translated into C */ +#ifndef ipfint +//typedef ipfint FORTRAN_INTEGER_TYPE ; +typedef int ipfint; +typedef const int cipfint; +#endif +#endif +#endif +// Extra for ugly include +#ifdef UGLY_COIN_FACTOR_CODING +#define FAC_UNSET (FAC_SET+1) +{ + goodPivot=false; + //store pivot columns (so can easily compress) + CoinBigIndex startColumnThis = startColumn[iPivotColumn]; + CoinBigIndex endColumn = startColumnThis + numberDoColumn + 1; + int put = 0; + CoinBigIndex startRowThis = startRow[iPivotRow]; + CoinBigIndex endRow = startRowThis + numberDoRow + 1; + if ( pivotColumnPosition < 0 ) { + for ( pivotColumnPosition = startRowThis; pivotColumnPosition < endRow; pivotColumnPosition++ ) { + int iColumn = indexColumn[pivotColumnPosition]; + if ( iColumn != iPivotColumn ) { + saveColumn[put++] = iColumn; + } else { + break; + } + } + } else { + for (CoinBigIndex i = startRowThis ; i < pivotColumnPosition ; i++ ) { + saveColumn[put++] = indexColumn[i]; + } + } + assert (pivotColumnPosition<endRow); + assert (indexColumn[pivotColumnPosition]==iPivotColumn); + pivotColumnPosition++; + for ( ; pivotColumnPosition < endRow; pivotColumnPosition++ ) { + saveColumn[put++] = indexColumn[pivotColumnPosition]; + } + //take out this bit of indexColumn + int next = nextRow[iPivotRow]; + int last = lastRow[iPivotRow]; + + nextRow[last] = next; + lastRow[next] = last; + nextRow[iPivotRow] = numberGoodU_; //use for permute + lastRow[iPivotRow] = -2; + numberInRow[iPivotRow] = 0; + //store column in L, compress in U and take column out + CoinBigIndex l = lengthL_; + // **** HORRID coding coming up but a goto seems best! + { + if ( l + numberDoColumn > lengthAreaL_ ) { + //need more memory + if ((messageLevel_&4)!=0) + printf("more memory needed in middle of invert\n"); + goto BAD_PIVOT; + } + //l+=currentAreaL_->elementByColumn-elementL; + CoinBigIndex lSave = l; + + CoinBigIndex * startColumnL = startColumnL_.array(); + startColumnL[numberGoodL_] = l; //for luck and first time + numberGoodL_++; + startColumnL[numberGoodL_] = l + numberDoColumn; + lengthL_ += numberDoColumn; + if ( pivotRowPosition < 0 ) { + for ( pivotRowPosition = startColumnThis; pivotRowPosition < endColumn; pivotRowPosition++ ) { + int iRow = indexRow[pivotRowPosition]; + if ( iRow != iPivotRow ) { + indexRowL[l] = iRow; + elementL[l] = element[pivotRowPosition]; + markRow[iRow] = l - lSave; + l++; + //take out of row list + CoinBigIndex start = startRow[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumn[where] != iPivotColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + } else { + break; + } + } + } else { + CoinBigIndex i; + + for ( i = startColumnThis; i < pivotRowPosition; i++ ) { + int iRow = indexRow[i]; + + markRow[iRow] = l - lSave; + indexRowL[l] = iRow; + elementL[l] = element[i]; + l++; + //take out of row list + CoinBigIndex start = startRow[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumn[where] != iPivotColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + assert (numberInRow[iRow]>=0); + } + } + assert (pivotRowPosition<endColumn); + assert (indexRow[pivotRowPosition]==iPivotRow); + CoinFactorizationDouble pivotElement = element[pivotRowPosition]; + CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement; + + pivotRegion_.array()[numberGoodU_] = pivotMultiplier; + pivotRowPosition++; + for ( ; pivotRowPosition < endColumn; pivotRowPosition++ ) { + int iRow = indexRow[pivotRowPosition]; + + markRow[iRow] = l - lSave; + indexRowL[l] = iRow; + elementL[l] = element[pivotRowPosition]; + l++; + //take out of row list + CoinBigIndex start = startRow[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumn[where] != iPivotColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + assert (numberInRow[iRow]>=0); + } + markRow[iPivotRow] = FAC_SET; + //compress pivot column (move pivot to front including saved) + numberInColumn[iPivotColumn] = 0; + //use end of L for temporary space + int *indexL = &indexRowL[lSave]; + CoinFactorizationDouble *multipliersL = &elementL[lSave]; + + //adjust + int j; + + for ( j = 0; j < numberDoColumn; j++ ) { + multipliersL[j] *= pivotMultiplier; + } + //zero out fill + CoinBigIndex iErase; + for ( iErase = 0; iErase < increment2 * numberDoRow; + iErase++ ) { + workArea2[iErase] = 0; + } + CoinBigIndex added = numberDoRow * numberDoColumn; + unsigned int *temp2 = workArea2; + int * nextColumn = nextColumn_.array(); + + //pack down and move to work + int jColumn; + for ( jColumn = 0; jColumn < numberDoRow; jColumn++ ) { + int iColumn = saveColumn[jColumn]; + CoinBigIndex startColumnThis = startColumn[iColumn]; + CoinBigIndex endColumn = startColumnThis + numberInColumn[iColumn]; + int iRow = indexRow[startColumnThis]; + CoinFactorizationDouble value = element[startColumnThis]; + double largest; + CoinBigIndex put = startColumnThis; + CoinBigIndex positionLargest = -1; + CoinFactorizationDouble thisPivotValue = 0.0; + + //compress column and find largest not updated + bool checkLargest; + int mark = markRow[iRow]; + + if ( mark == FAC_UNSET ) { + largest = fabs ( value ); + positionLargest = put; + put++; + checkLargest = false; + } else { + //need to find largest + largest = 0.0; + checkLargest = true; + if ( mark != FAC_SET ) { + //will be updated + workArea[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + CoinBigIndex i; + for ( i = startColumnThis + 1; i < endColumn; i++ ) { + iRow = indexRow[i]; + value = element[i]; + int mark = markRow[iRow]; + + if ( mark == FAC_UNSET ) { + //keep + indexRow[put] = iRow; + element[put] = value; + if ( checkLargest ) { + double absValue = fabs ( value ); + + if ( absValue > largest ) { + largest = absValue; + positionLargest = put; + } + } + put++; + } else if ( mark != FAC_SET ) { + //will be updated + workArea[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + //slot in pivot + element[put] = element[startColumnThis]; + indexRow[put] = indexRow[startColumnThis]; + if ( positionLargest == startColumnThis ) { + positionLargest = put; //follow if was largest + } + put++; + element[startColumnThis] = thisPivotValue; + indexRow[startColumnThis] = iPivotRow; + //clean up counts + startColumnThis++; + numberInColumn[iColumn] = put - startColumnThis; + int * numberInColumnPlus = numberInColumnPlus_.array(); + numberInColumnPlus[iColumn]++; + startColumn[iColumn]++; + //how much space have we got + int next = nextColumn[iColumn]; + CoinBigIndex space; + + space = startColumn[next] - put - numberInColumnPlus[next]; + //assume no zero elements + if ( numberDoColumn > space ) { + //getColumnSpace also moves fixed part + if ( !getColumnSpace ( iColumn, numberDoColumn ) ) { + goto BAD_PIVOT; + } + //redo starts + positionLargest = positionLargest + startColumn[iColumn] - startColumnThis; + startColumnThis = startColumn[iColumn]; + put = startColumnThis + numberInColumn[iColumn]; + } + double tolerance = zeroTolerance_; + + int *nextCount = nextCount_.array(); + for ( j = 0; j < numberDoColumn; j++ ) { + value = workArea[j] - thisPivotValue * multipliersL[j]; + double absValue = fabs ( value ); + + if ( absValue > tolerance ) { + workArea[j] = 0.0; + element[put] = value; + indexRow[put] = indexL[j]; + if ( absValue > largest ) { + largest = absValue; + positionLargest = put; + } + put++; + } else { + workArea[j] = 0.0; + added--; + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + if ( temp2[word] & ( 1 << bit ) ) { + //take out of row list + iRow = indexL[j]; + CoinBigIndex start = startRow[iRow]; + CoinBigIndex end = start + numberInRow[iRow]; + CoinBigIndex where = start; + + while ( indexColumn[where] != iColumn ) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if ( where >= end ) { + abort ( ); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + } else { + //make sure won't be added + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts + } + } + } + numberInColumn[iColumn] = put - startColumnThis; + //move largest + if ( positionLargest >= 0 ) { + value = element[positionLargest]; + iRow = indexRow[positionLargest]; + element[positionLargest] = element[startColumnThis]; + indexRow[positionLargest] = indexRow[startColumnThis]; + element[startColumnThis] = value; + indexRow[startColumnThis] = iRow; + } + //linked list for column + if ( nextCount[iColumn + numberRows_] != -2 ) { + //modify linked list + deleteLink ( iColumn + numberRows_ ); + addLink ( iColumn + numberRows_, numberInColumn[iColumn] ); + } + temp2 += increment2; + } + //get space for row list + unsigned int *putBase = workArea2; + int bigLoops = numberDoColumn >> COINFACTORIZATION_SHIFT_PER_INT; + int i = 0; + + // do linked lists and update counts + while ( bigLoops ) { + bigLoops--; + int bit; + for ( bit = 0; bit < COINFACTORIZATION_BITS_PER_INT; i++, bit++ ) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for ( jColumn = 0; jColumn < numberDoRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + number += test; + } + int next = nextRow[iRow]; + CoinBigIndex space; + + space = startRow[next] - startRow[iRow]; + number += numberInRow[iRow]; + if ( space < number ) { + if ( !getRowSpace ( iRow, number ) ) { + goto BAD_PIVOT; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + CoinBigIndex end = startRow[iRow] + number; + int saveIndex = indexColumn[startRow[next]]; + + //add in + for ( jColumn = 0; jColumn < numberDoRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + indexColumn[end] = saveColumn[jColumn]; + end += test; + } + //put back next one in case zapped + indexColumn[startRow[next]] = saveIndex; + markRow[iRow] = FAC_UNSET; + number = end - startRow[iRow]; + numberInRow[iRow] = number; + deleteLink ( iRow ); + addLink ( iRow, number ); + } + putBase++; + } /* endwhile */ + int bit; + + for ( bit = 0; i < numberDoColumn; i++, bit++ ) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for ( jColumn = 0; jColumn < numberDoRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + number += test; + } + int next = nextRow[iRow]; + CoinBigIndex space; + + space = startRow[next] - startRow[iRow]; + number += numberInRow[iRow]; + if ( space < number ) { + if ( !getRowSpace ( iRow, number ) ) { + goto BAD_PIVOT; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + CoinBigIndex end = startRow[iRow] + number; + int saveIndex; + + saveIndex = indexColumn[startRow[next]]; + + //add in + for ( jColumn = 0; jColumn < numberDoRow; jColumn++ ) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ( ( test >> bit ) & 1 ); + + indexColumn[end] = saveColumn[jColumn]; + end += test; + } + indexColumn[startRow[next]] = saveIndex; + markRow[iRow] = FAC_UNSET; + number = end - startRow[iRow]; + numberInRow[iRow] = number; + deleteLink ( iRow ); + addLink ( iRow, number ); + } + markRow[iPivotRow] = FAC_UNSET; + //modify linked list for pivots + deleteLink ( iPivotRow ); + deleteLink ( iPivotColumn + numberRows_ ); + totalElements_ += added; + goodPivot= true; + // **** UGLY UGLY UGLY + } + BAD_PIVOT: + + ; +} +#undef FAC_UNSET +#endif diff --git a/thirdparty/linux/include/coin/CoinFileIO.hpp b/thirdparty/linux/include/coin/CoinFileIO.hpp new file mode 100644 index 0000000..20be1a9 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinFileIO.hpp @@ -0,0 +1,166 @@ +/* $Id: CoinFileIO.hpp 1439 2011-06-13 16:31:21Z stefan $ */ +// Copyright (C) 2005, COIN-OR. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinFileIO_H +#define CoinFileIO_H + +#include <string> + +/// Base class for FileIO classes. +class CoinFileIOBase +{ +public: + /// Constructor. + /// @param fileName The name of the file used by this object. + CoinFileIOBase (const std::string &fileName); + + /// Destructor. + ~CoinFileIOBase (); + + /// Return the name of the file used by this object. + const char *getFileName () const; + + /// Return the method of reading being used + inline std::string getReadType () const + { return readType_.c_str();} +protected: + std::string readType_; +private: + CoinFileIOBase (); + CoinFileIOBase (const CoinFileIOBase &); + + std::string fileName_; +}; + +/// Abstract base class for file input classes. +class CoinFileInput: public CoinFileIOBase +{ +public: + /// indicates whether CoinFileInput supports gzip'ed files + static bool haveGzipSupport(); + /// indicates whether CoinFileInput supports bzip2'ed files + static bool haveBzip2Support(); + + /// Factory method, that creates a CoinFileInput (more precisely + /// a subclass of it) for the file specified. This method reads the + /// first few bytes of the file and determines if this is a compressed + /// or a plain file and returns the correct subclass to handle it. + /// If the file does not exist or uses a compression not compiled in + /// an exception is thrown. + /// @param fileName The file that should be read. + static CoinFileInput *create (const std::string &fileName); + + /// Constructor (don't use this, use the create method instead). + /// @param fileName The name of the file used by this object. + CoinFileInput (const std::string &fileName); + + /// Destructor. + virtual ~CoinFileInput (); + + /// Read a block of data from the file, similar to fread. + /// @param buffer Address of a buffer to store the data into. + /// @param size Number of bytes to read (buffer should be large enough). + /// @return Number of bytes read. + virtual int read (void *buffer, int size) = 0; + + /// Reads up to (size-1) characters an stores them into the buffer, + /// similar to fgets. + /// Reading ends, when EOF or a newline occurs or (size-1) characters have + /// been read. The resulting string is terminated with '\0'. If reading + /// ends due to an encoutered newline, the '\n' is put into the buffer, + /// before the '\0' is appended. + /// @param buffer The buffer to put the string into. + /// @param size The size of the buffer in characters. + /// @return buffer on success, or 0 if no characters have been read. + virtual char *gets (char *buffer, int size) = 0; +}; + +/// Abstract base class for file output classes. +class CoinFileOutput: public CoinFileIOBase +{ +public: + + /// The compression method. + enum Compression { + COMPRESS_NONE = 0, ///< No compression. + COMPRESS_GZIP = 1, ///< gzip compression. + COMPRESS_BZIP2 = 2 ///< bzip2 compression. + }; + + /// Returns whether the specified compression method is supported + /// (i.e. was compiled into COIN). + static bool compressionSupported (Compression compression); + + /// Factory method, that creates a CoinFileOutput (more precisely + /// a subclass of it) for the file specified. If the compression method + /// is not supported an exception is thrown (so use compressionSupported + /// first, if this is a problem). The reason for not providing direct + /// access to the subclasses (and using such a method instead) is that + /// depending on the build configuration some of the classes are not + /// available (or functional). This way we can handle all required ifdefs + /// here instead of polluting other files. + /// @param fileName The file that should be read. + /// @param compression Compression method used. + static CoinFileOutput *create (const std::string &fileName, + Compression compression); + + /// Constructor (don't use this, use the create method instead). + /// @param fileName The name of the file used by this object. + CoinFileOutput (const std::string &fileName); + + /// Destructor. + virtual ~CoinFileOutput (); + + /// Write a block of data to the file, similar to fwrite. + /// @param buffer Address of a buffer containing the data to be written. + /// @param size Number of bytes to write. + /// @return Number of bytes written. + virtual int write (const void * buffer, int size) = 0; + + /// Write a string to the file (like fputs). + /// Just as with fputs no trailing newline is inserted! + /// The terminating '\0' is not written to the file. + /// The default implementation determines the length of the string + /// and calls write on it. + /// @param s The zero terminated string to be written. + /// @return true on success, false on error. + virtual bool puts (const char *s); + + /// Convenience method: just a 'puts(s.c_str())'. + inline bool puts (const std::string &s) + { + return puts (s.c_str ()); + } +}; + +/*! \relates CoinFileInput + \brief Test if the given string looks like an absolute file path + + The criteria are: + - unix: string begins with `/' + - windows: string begins with `\' or with `drv:' (drive specifier) +*/ +bool fileAbsPath (const std::string &path) ; + +/*! \relates CoinFileInput + \brief Test if the file is readable, using likely versions of the file + name, and return the name that worked. + + The file name is constructed from \p name using the following rules: + <ul> + <li> An absolute path is not modified. + <li> If the name begins with `~', an attempt is made to replace `~' + with the value of the environment variable HOME. + <li> If a default prefix (\p dfltPrefix) is provided, it is + prepended to the name. + </ul> + If the constructed file name cannot be opened, and CoinUtils was built + with support for compressed files, fileCoinReadable will try any + standard extensions for supported compressed files. + + The value returned in \p name is the file name that actually worked. +*/ +bool fileCoinReadable(std::string &name, + const std::string &dfltPrefix = std::string("")); +#endif diff --git a/thirdparty/linux/include/coin/CoinFinite.hpp b/thirdparty/linux/include/coin/CoinFinite.hpp new file mode 100644 index 0000000..71b5b65 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinFinite.hpp @@ -0,0 +1,34 @@ +/* $Id: CoinFinite.hpp 1762 2014-12-29 20:37:12Z tkr $ */ +// 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). + +/* Defines COIN_DBL_MAX and relatives and provides CoinFinite and CoinIsnan. */ + +#ifndef CoinFinite_H +#define CoinFinite_H + +#include <limits> + +//============================================================================= +// Smallest positive double value and Plus infinity (double and int) + +#if 1 +const double COIN_DBL_MIN = (std::numeric_limits<double>::min)(); +const double COIN_DBL_MAX = (std::numeric_limits<double>::max)(); +const int COIN_INT_MAX = (std::numeric_limits<int>::max)(); +const double COIN_INT_MAX_AS_DOUBLE = (std::numeric_limits<int>::max)(); +#else +#define COIN_DBL_MIN (std::numeric_limits<double>::min()) +#define COIN_DBL_MAX (std::numeric_limits<double>::max()) +#define COIN_INT_MAX (std::numeric_limits<int>::max()) +#define COIN_INT_MAX_AS_DOUBLE (std::numeric_limits<int>::max()) +#endif + +/** checks if a double value is finite (not infinity and not NaN) */ +extern bool CoinFinite(double val); + +/** checks if a double value is not a number */ +extern bool CoinIsnan(double val); + +#endif diff --git a/thirdparty/linux/include/coin/CoinFloatEqual.hpp b/thirdparty/linux/include/coin/CoinFloatEqual.hpp new file mode 100644 index 0000000..d5edfff --- /dev/null +++ b/thirdparty/linux/include/coin/CoinFloatEqual.hpp @@ -0,0 +1,177 @@ +/* $Id: CoinFloatEqual.hpp 1416 2011-04-17 09:57:29Z stefan $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinFloatEqual_H +#define CoinFloatEqual_H + +#include <algorithm> +#include <cmath> + +#include "CoinFinite.hpp" + +/*! \file CoinFloatEqual.hpp + \brief Function objects for testing equality of real numbers. + + Two objects are provided; one tests for equality to an absolute tolerance, + one to a scaled tolerance. The tests will handle IEEE floating point, but + note that infinity == infinity. Mathematicians are rolling in their graves, + but this matches the behaviour for the common practice of using + <code>DBL_MAX</code> (<code>numeric_limits<double>::max()</code>, or similar + large finite number) as infinity. + + <p> + Example usage: + @verbatim + double d1 = 3.14159 ; + double d2 = d1 ; + double d3 = d1+.0001 ; + + CoinAbsFltEq eq1 ; + CoinAbsFltEq eq2(.001) ; + + assert( eq1(d1,d2) ) ; + assert( !eq1(d1,d3) ) ; + assert( eq2(d1,d3) ) ; + @endverbatim + CoinRelFltEq follows the same pattern. */ + +/*! \brief Equality to an absolute tolerance + + Operands are considered equal if their difference is within an epsilon ; + the test does not consider the relative magnitude of the operands. +*/ + +class CoinAbsFltEq +{ + public: + + //! Compare function + + inline bool operator() (const double f1, const double f2) const + + { if (CoinIsnan(f1) || CoinIsnan(f2)) return false ; + if (f1 == f2) return true ; + return (fabs(f1-f2) < epsilon_) ; } + + /*! \name Constructors and destructors */ + //@{ + + /*! \brief Default constructor + + Default tolerance is 1.0e-10. + */ + + CoinAbsFltEq () : epsilon_(1.e-10) {} + + //! Alternate constructor with epsilon as a parameter + + CoinAbsFltEq (const double epsilon) : epsilon_(epsilon) {} + + //! Destructor + + virtual ~CoinAbsFltEq () {} + + //! Copy constructor + + CoinAbsFltEq (const CoinAbsFltEq& src) : epsilon_(src.epsilon_) {} + + //! Assignment + + CoinAbsFltEq& operator= (const CoinAbsFltEq& rhs) + + { if (this != &rhs) epsilon_ = rhs.epsilon_ ; + return (*this) ; } + + //@} + + private: + + /*! \name Private member data */ + //@{ + + //! Equality tolerance. + + double epsilon_ ; + + //@} + +} ; + + + +/*! \brief Equality to a scaled tolerance + + Operands are considered equal if their difference is within a scaled + epsilon calculated as epsilon_*(1+CoinMax(|f1|,|f2|)). +*/ + +class CoinRelFltEq +{ + public: + + //! Compare function + + inline bool operator() (const double f1, const double f2) const + + { if (CoinIsnan(f1) || CoinIsnan(f2)) return false ; + if (f1 == f2) return true ; + if (!CoinFinite(f1) || !CoinFinite(f2)) return false ; + + double tol = (fabs(f1)>fabs(f2))?fabs(f1):fabs(f2) ; + + return (fabs(f1-f2) <= epsilon_*(1+tol)) ; } + + /*! \name Constructors and destructors */ + //@{ + +#ifndef COIN_FLOAT + /*! Default constructor + + Default tolerance is 1.0e-10. + */ + CoinRelFltEq () : epsilon_(1.e-10) {} +#else + /*! Default constructor + + Default tolerance is 1.0e-6. + */ + CoinRelFltEq () : epsilon_(1.e-6) {} ; // as float +#endif + + //! Alternate constructor with epsilon as a parameter + + CoinRelFltEq (const double epsilon) : epsilon_(epsilon) {} + + //! Destructor + + virtual ~CoinRelFltEq () {} + + //! Copy constructor + + CoinRelFltEq (const CoinRelFltEq & src) : epsilon_(src.epsilon_) {} + + //! Assignment + + CoinRelFltEq& operator= (const CoinRelFltEq& rhs) + + { if (this != &rhs) epsilon_ = rhs.epsilon_ ; + return (*this) ; } + + //@} + +private: + + /*! \name Private member data */ + //@{ + + //! Base equality tolerance + + double epsilon_ ; + + //@} + +} ; + +#endif diff --git a/thirdparty/linux/include/coin/CoinHelperFunctions.hpp b/thirdparty/linux/include/coin/CoinHelperFunctions.hpp new file mode 100644 index 0000000..3409bbc --- /dev/null +++ b/thirdparty/linux/include/coin/CoinHelperFunctions.hpp @@ -0,0 +1,1111 @@ +/* $Id: CoinHelperFunctions.hpp 1679 2013-12-05 11:27:45Z forrest $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinHelperFunctions_H +#define CoinHelperFunctions_H + +#include "CoinUtilsConfig.h" + +#if defined(_MSC_VER) +# include <direct.h> +# include <cctype> +# define getcwd _getcwd +# include <cctype> +#else +# include <unistd.h> +#endif +//#define USE_MEMCPY + +#include <cstdlib> +#include <cstdio> +#include <algorithm> +#include "CoinTypes.hpp" +#include "CoinError.hpp" + +// Compilers can produce better code if they know about __restrict +#ifndef COIN_RESTRICT +#ifdef COIN_USE_RESTRICT +#define COIN_RESTRICT __restrict +#else +#define COIN_RESTRICT +#endif +#endif + +//############################################################################# + +/** This helper function copies an array to another location using Duff's + device (for a speedup of ~2). The arrays are given by pointers to their + first entries and by the size of the source array. Overlapping arrays are + handled correctly. */ + +template <class T> inline void +CoinCopyN(register const T* from, const int size, register T* to) +{ + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinCopyN", ""); +#endif + + register int n = (size + 7) / 8; + if (to > from) { + register const T* downfrom = from + size; + register T* downto = to + size; + // Use Duff's device to copy + switch (size % 8) { + case 0: do{ *--downto = *--downfrom; + case 7: *--downto = *--downfrom; + case 6: *--downto = *--downfrom; + case 5: *--downto = *--downfrom; + case 4: *--downto = *--downfrom; + case 3: *--downto = *--downfrom; + case 2: *--downto = *--downfrom; + case 1: *--downto = *--downfrom; + }while(--n>0); + } + } else { + // Use Duff's device to copy + --from; + --to; + switch (size % 8) { + case 0: do{ *++to = *++from; + case 7: *++to = *++from; + case 6: *++to = *++from; + case 5: *++to = *++from; + case 4: *++to = *++from; + case 3: *++to = *++from; + case 2: *++to = *++from; + case 1: *++to = *++from; + }while(--n>0); + } + } +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location using Duff's + device (for a speedup of ~2). The source array is given by its first and + "after last" entry; the target array is given by its first entry. + Overlapping arrays are handled correctly. + + All of the various CoinCopyN variants use an int for size. On 64-bit + architectures, the address diff last-first will be a 64-bit quantity. + Given that everything else uses an int, I'm going to choose to kick + the difference down to int. -- lh, 100823 -- +*/ +template <class T> inline void +CoinCopy(register const T* first, register const T* last, register T* to) +{ + CoinCopyN(first, static_cast<int>(last-first), to); +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The arrays are given by pointers to their first + entries and by the size of the source array. + + Note JJF - the speed claim seems to be false on IA32 so I have added + CoinMemcpyN which can be used for atomic data */ +template <class T> inline void +CoinDisjointCopyN(register const T* from, const int size, register T* to) +{ +#ifndef _MSC_VER + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinDisjointCopyN", ""); +#endif + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinDisjointCopyN", ""); +#endif + + for (register int n = size / 8; n > 0; --n, from += 8, to += 8) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to[4] = from[4]; + to[5] = from[5]; + to[6] = from[6]; + to[7] = from[7]; + } + switch (size % 8) { + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + } +#else + CoinCopyN(from, size, to); +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The source array is given by its first and "after + last" entry; the target array is given by its first entry. */ +template <class T> inline void +CoinDisjointCopy(register const T* first, register const T* last, + register T* to) +{ + CoinDisjointCopyN(first, static_cast<int>(last - first), to); +} + +//----------------------------------------------------------------------------- + +/*! \brief Return an array of length \p size filled with input from \p array, + or null if \p array is null. +*/ + +template <class T> inline T* +CoinCopyOfArray( const T * array, const int size) +{ + if (array) { + T * arrayNew = new T[size]; + std::memcpy(arrayNew,array,size*sizeof(T)); + return arrayNew; + } else { + return NULL; + } +} + + +/*! \brief Return an array of length \p size filled with first copySize from \p array, + or null if \p array is null. +*/ + +template <class T> inline T* +CoinCopyOfArrayPartial( const T * array, const int size,const int copySize) +{ + if (array||size) { + T * arrayNew = new T[size]; + assert (copySize<=size); + std::memcpy(arrayNew,array,copySize*sizeof(T)); + return arrayNew; + } else { + return NULL; + } +} + +/*! \brief Return an array of length \p size filled with input from \p array, + or filled with (scalar) \p value if \p array is null +*/ + +template <class T> inline T* +CoinCopyOfArray( const T * array, const int size, T value) +{ + T * arrayNew = new T[size]; + if (array) { + std::memcpy(arrayNew,array,size*sizeof(T)); + } else { + int i; + for (i=0;i<size;i++) + arrayNew[i] = value; + } + return arrayNew; +} + + +/*! \brief Return an array of length \p size filled with input from \p array, + or filled with zero if \p array is null +*/ + +template <class T> inline T* +CoinCopyOfArrayOrZero( const T * array , const int size) +{ + T * arrayNew = new T[size]; + if (array) { + std::memcpy(arrayNew,array,size*sizeof(T)); + } else { + std::memset(arrayNew,0,size*sizeof(T)); + } + return arrayNew; +} + + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The arrays are given by pointers to their first + entries and by the size of the source array. + + Note JJF - the speed claim seems to be false on IA32 so I have added + alternative coding if USE_MEMCPY defined*/ +#ifndef COIN_USE_RESTRICT +template <class T> inline void +CoinMemcpyN(register const T* from, const int size, register T* to) +{ +#ifndef _MSC_VER +#ifdef USE_MEMCPY + // Use memcpy - seems a lot faster on Intel with gcc +#ifndef NDEBUG + // Some debug so check + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinMemcpyN", ""); + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinMemcpyN", ""); +#endif +#endif + std::memcpy(to,from,size*sizeof(T)); +#else + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinMemcpyN", ""); +#endif + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinMemcpyN", ""); +#endif + + for (register int n = size / 8; n > 0; --n, from += 8, to += 8) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to[4] = from[4]; + to[5] = from[5]; + to[6] = from[6]; + to[7] = from[7]; + } + switch (size % 8) { + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + } +#endif +#else + CoinCopyN(from, size, to); +#endif +} +#else +template <class T> inline void +CoinMemcpyN(const T * COIN_RESTRICT from, int size, T* COIN_RESTRICT to) +{ +#ifdef USE_MEMCPY + std::memcpy(to,from,size*sizeof(T)); +#else + T * COIN_RESTRICT put = to; + const T * COIN_RESTRICT get = from; + for ( ; 0<size ; --size) + *put++ = *get++; +#endif +} +#endif + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The source array is given by its first and "after + last" entry; the target array is given by its first entry. */ +template <class T> inline void +CoinMemcpy(register const T* first, register const T* last, + register T* to) +{ + CoinMemcpyN(first, static_cast<int>(last - first), to); +} + +//############################################################################# + +/** This helper function fills an array with a given value. For speed 8 entries + are filled at a time. The array is given by a pointer to its first entry + and its size. + + Note JJF - the speed claim seems to be false on IA32 so I have added + CoinZero to allow for memset. */ +template <class T> inline void +CoinFillN(register T* to, const int size, register const T value) +{ + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinFillN", ""); +#endif +#if 1 + for (register int n = size / 8; n > 0; --n, to += 8) { + to[0] = value; + to[1] = value; + to[2] = value; + to[3] = value; + to[4] = value; + to[5] = value; + to[6] = value; + to[7] = value; + } + switch (size % 8) { + case 7: to[6] = value; + case 6: to[5] = value; + case 5: to[4] = value; + case 4: to[3] = value; + case 3: to[2] = value; + case 2: to[1] = value; + case 1: to[0] = value; + case 0: break; + } +#else + // Use Duff's device to fill + register int n = (size + 7) / 8; + --to; + switch (size % 8) { + case 0: do{ *++to = value; + case 7: *++to = value; + case 6: *++to = value; + case 5: *++to = value; + case 4: *++to = value; + case 3: *++to = value; + case 2: *++to = value; + case 1: *++to = value; + }while(--n>0); + } +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with a given value. For speed 8 + entries are filled at a time. The array is given by its first and "after + last" entry. */ +template <class T> inline void +CoinFill(register T* first, register T* last, const T value) +{ + CoinFillN(first, last - first, value); +} + +//############################################################################# + +/** This helper function fills an array with zero. For speed 8 entries + are filled at a time. The array is given by a pointer to its first entry + and its size. + + Note JJF - the speed claim seems to be false on IA32 so I have allowed + for memset as an alternative */ +template <class T> inline void +CoinZeroN(register T* to, const int size) +{ +#ifdef USE_MEMCPY + // Use memset - seems faster on Intel with gcc +#ifndef NDEBUG + // Some debug so check + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinZeroN", ""); +#endif + memset(to,0,size*sizeof(T)); +#else + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinZeroN", ""); +#endif +#if 1 + for (register int n = size / 8; n > 0; --n, to += 8) { + to[0] = 0; + to[1] = 0; + to[2] = 0; + to[3] = 0; + to[4] = 0; + to[5] = 0; + to[6] = 0; + to[7] = 0; + } + switch (size % 8) { + case 7: to[6] = 0; + case 6: to[5] = 0; + case 5: to[4] = 0; + case 4: to[3] = 0; + case 3: to[2] = 0; + case 2: to[1] = 0; + case 1: to[0] = 0; + case 0: break; + } +#else + // Use Duff's device to fill + register int n = (size + 7) / 8; + --to; + switch (size % 8) { + case 0: do{ *++to = 0; + case 7: *++to = 0; + case 6: *++to = 0; + case 5: *++to = 0; + case 4: *++to = 0; + case 3: *++to = 0; + case 2: *++to = 0; + case 1: *++to = 0; + }while(--n>0); + } +#endif +#endif +} +/// This Debug helper function checks an array is all zero +inline void +CoinCheckDoubleZero(double * to, const int size) +{ + int n=0; + for (int j=0;j<size;j++) { + if (to[j]) + n++; + } + if (n) { + printf("array of length %d should be zero has %d nonzero\n",size,n); + } +} +/// This Debug helper function checks an array is all zero +inline void +CoinCheckIntZero(int * to, const int size) +{ + int n=0; + for (int j=0;j<size;j++) { + if (to[j]) + n++; + } + if (n) { + printf("array of length %d should be zero has %d nonzero\n",size,n); + } +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with a given value. For speed 8 + entries are filled at a time. The array is given by its first and "after + last" entry. */ +template <class T> inline void +CoinZero(register T* first, register T* last) +{ + CoinZeroN(first, last - first); +} + +//############################################################################# + +/** Returns strdup or NULL if original NULL */ +inline char * CoinStrdup(const char * name) +{ + char* dup = NULL; + if (name) { + const int len = static_cast<int>(strlen(name)); + dup = static_cast<char*>(malloc(len+1)); + CoinMemcpyN(name, len, dup); + dup[len] = 0; + } + return dup; +} + +//############################################################################# + +/** Return the larger (according to <code>operator<()</code> of the arguments. + This function was introduced because for some reason compiler tend to + handle the <code>max()</code> function differently. */ +template <class T> inline T +CoinMax(register const T x1, register const T x2) +{ + return (x1 > x2) ? x1 : x2; +} + +//----------------------------------------------------------------------------- + +/** Return the smaller (according to <code>operator<()</code> of the arguments. + This function was introduced because for some reason compiler tend to + handle the min() function differently. */ +template <class T> inline T +CoinMin(register const T x1, register const T x2) +{ + return (x1 < x2) ? x1 : x2; +} + +//----------------------------------------------------------------------------- + +/** Return the absolute value of the argument. This function was introduced + because for some reason compiler tend to handle the abs() function + differently. */ +template <class T> inline T +CoinAbs(const T value) +{ + return value<0 ? -value : value; +} + +//############################################################################# + +/** This helper function tests whether the entries of an array are sorted + according to operator<. The array is given by a pointer to its first entry + and by its size. */ +template <class T> inline bool +CoinIsSorted(register const T* first, const int size) +{ + if (size == 0) + return true; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("negative number of entries", "CoinIsSorted", ""); +#endif +#if 1 + // size1 is the number of comparisons to be made + const int size1 = size - 1; + for (register int n = size1 / 8; n > 0; --n, first += 8) { + if (first[8] < first[7]) return false; + if (first[7] < first[6]) return false; + if (first[6] < first[5]) return false; + if (first[5] < first[4]) return false; + if (first[4] < first[3]) return false; + if (first[3] < first[2]) return false; + if (first[2] < first[1]) return false; + if (first[1] < first[0]) return false; + } + + switch (size1 % 8) { + case 7: if (first[7] < first[6]) return false; + case 6: if (first[6] < first[5]) return false; + case 5: if (first[5] < first[4]) return false; + case 4: if (first[4] < first[3]) return false; + case 3: if (first[3] < first[2]) return false; + case 2: if (first[2] < first[1]) return false; + case 1: if (first[1] < first[0]) return false; + case 0: break; + } +#else + register const T* next = first; + register const T* last = first + size; + for (++next; next != last; first = next, ++next) + if (*next < *first) + return false; +#endif + return true; +} + +//----------------------------------------------------------------------------- + +/** This helper function tests whether the entries of an array are sorted + according to operator<. The array is given by its first and "after + last" entry. */ +template <class T> inline bool +CoinIsSorted(register const T* first, register const T* last) +{ + return CoinIsSorted(first, static_cast<int>(last - first)); +} + +//############################################################################# + +/** This helper function fills an array with the values init, init+1, init+2, + etc. For speed 8 entries are filled at a time. The array is given by a + pointer to its first entry and its size. */ +template <class T> inline void +CoinIotaN(register T* first, const int size, register T init) +{ + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("negative number of entries", "CoinIotaN", ""); +#endif +#if 1 + for (register int n = size / 8; n > 0; --n, first += 8, init += 8) { + first[0] = init; + first[1] = init + 1; + first[2] = init + 2; + first[3] = init + 3; + first[4] = init + 4; + first[5] = init + 5; + first[6] = init + 6; + first[7] = init + 7; + } + switch (size % 8) { + case 7: first[6] = init + 6; + case 6: first[5] = init + 5; + case 5: first[4] = init + 4; + case 4: first[3] = init + 3; + case 3: first[2] = init + 2; + case 2: first[1] = init + 1; + case 1: first[0] = init; + case 0: break; + } +#else + // Use Duff's device to fill + register int n = (size + 7) / 8; + --first; + --init; + switch (size % 8) { + case 0: do{ *++first = ++init; + case 7: *++first = ++init; + case 6: *++first = ++init; + case 5: *++first = ++init; + case 4: *++first = ++init; + case 3: *++first = ++init; + case 2: *++first = ++init; + case 1: *++first = ++init; + }while(--n>0); + } +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with the values init, init+1, init+2, + etc. For speed 8 entries are filled at a time. The array is given by its + first and "after last" entry. */ +template <class T> inline void +CoinIota(T* first, const T* last, T init) +{ + CoinIotaN(first, last-first, init); +} + +//############################################################################# + +/** This helper function deletes certain entries from an array. The array is + given by pointers to its first and "after last" entry (first two + arguments). The positions of the entries to be deleted are given in the + integer array specified by the last two arguments (again, first and "after + last" entry). */ +template <class T> inline T * +CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast, + const int * firstDelPos, const int * lastDelPos) +{ + int delNum = static_cast<int>(lastDelPos - firstDelPos); + if (delNum == 0) + return arrayLast; + + if (delNum < 0) + throw CoinError("trying to delete negative number of entries", + "CoinDeleteEntriesFromArray", ""); + + int * delSortedPos = NULL; + if (! (CoinIsSorted(firstDelPos, lastDelPos) && + std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) { + // the positions of the to be deleted is either not sorted or not unique + delSortedPos = new int[delNum]; + CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos); + std::sort(delSortedPos, delSortedPos + delNum); + delNum = static_cast<int>(std::unique(delSortedPos, + delSortedPos+delNum) - delSortedPos); + } + const int * delSorted = delSortedPos ? delSortedPos : firstDelPos; + + const int last = delNum - 1; + int size = delSorted[0]; + for (int i = 0; i < last; ++i) { + const int copyFirst = delSorted[i] + 1; + const int copyLast = delSorted[i+1]; + CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, + arrayFirst + size); + size += copyLast - copyFirst; + } + const int copyFirst = delSorted[last] + 1; + const int copyLast = static_cast<int>(arrayLast - arrayFirst); + CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, + arrayFirst + size); + size += copyLast - copyFirst; + + if (delSortedPos) + delete[] delSortedPos; + + return arrayFirst + size; +} + +//############################################################################# + +#define COIN_OWN_RANDOM_32 + +#if defined COIN_OWN_RANDOM_32 +/* Thanks to Stefano Gliozzi for providing an operating system + independent random number generator. */ + +/*! \brief Return a random number between 0 and 1 + + A platform-independent linear congruential generator. For a given seed, the + generated sequence is always the same regardless of the (32-bit) + architecture. This allows to build & test in different environments, getting + in most cases the same optimization path. + + Set \p isSeed to true and supply an integer seed to set the seed + (vid. #CoinSeedRandom) + + \todo Anyone want to volunteer an upgrade for 64-bit architectures? +*/ +inline double CoinDrand48 (bool isSeed = false, unsigned int seed = 1) +{ + static unsigned int last = 123456; + if (isSeed) { + last = seed; + } else { + last = 1664525*last+1013904223; + return ((static_cast<double> (last))/4294967296.0); + } + return (0.0); +} + +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) +{ + CoinDrand48(true, iseed); +} + +#else // COIN_OWN_RANDOM_32 + +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) + +/// Return a random number between 0 and 1 +inline double CoinDrand48() { return rand() / (double) RAND_MAX; } +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); } + +#else + +/// Return a random number between 0 and 1 +inline double CoinDrand48() { return drand48(); } +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); } + +#endif + +#endif // COIN_OWN_RANDOM_32 + +//############################################################################# + +/** This function figures out whether file names should contain slashes or + backslashes as directory separator */ +inline char CoinFindDirSeparator() +{ + int size = 1000; + char* buf = 0; + while (true) { + buf = new char[size]; + if (getcwd(buf, size)) + break; + delete[] buf; + buf = 0; + size = 2*size; + } + // if first char is '/' then it's unix and the dirsep is '/'. otherwise we + // assume it's dos and the dirsep is '\' + char dirsep = buf[0] == '/' ? '/' : '\\'; + delete[] buf; + return dirsep; +} +//############################################################################# + +inline int CoinStrNCaseCmp(const char* s0, const char* s1, + const size_t len) +{ + for (size_t i = 0; i < len; ++i) { + if (s0[i] == 0) { + return s1[i] == 0 ? 0 : -1; + } + if (s1[i] == 0) { + return 1; + } + const int c0 = std::tolower(s0[i]); + const int c1 = std::tolower(s1[i]); + if (c0 < c1) + return -1; + if (c0 > c1) + return 1; + } + return 0; +} + +//############################################################################# + +/// Swap the arguments. +template <class T> inline void CoinSwap (T &x, T &y) +{ + T t = x; + x = y; + y = t; +} + +//############################################################################# + +/** This helper function copies an array to file + Returns 0 if OK, 1 if bad write. +*/ + +template <class T> inline int +CoinToFile( const T* array, CoinBigIndex size, FILE * fp) +{ + CoinBigIndex numberWritten; + if (array&&size) { + numberWritten = + static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp)); + if (numberWritten!=1) + return 1; + numberWritten = + static_cast<CoinBigIndex>(fwrite(array,sizeof(T),size_t(size),fp)); + if (numberWritten!=size) + return 1; + } else { + size = 0; + numberWritten = + static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp)); + if (numberWritten!=1) + return 1; + } + return 0; +} + +//############################################################################# + +/** This helper function copies an array from file and creates with new. + Passed in array is ignored i.e. not deleted. + But if NULL and size does not match and newSize 0 then leaves as NULL and 0 + Returns 0 if OK, 1 if bad read, 2 if size did not match. +*/ + +template <class T> inline int +CoinFromFile( T* &array, CoinBigIndex size, FILE * fp, CoinBigIndex & newSize) +{ + CoinBigIndex numberRead; + numberRead = + static_cast<CoinBigIndex>(fread(&newSize,sizeof(int),1,fp)); + if (numberRead!=1) + return 1; + int returnCode=0; + if (size!=newSize&&(newSize||array)) + returnCode=2; + if (newSize) { + array = new T [newSize]; + numberRead = + static_cast<CoinBigIndex>(fread(array,sizeof(T),newSize,fp)); + if (numberRead!=newSize) + returnCode=1; + } else { + array = NULL; + } + return returnCode; +} + +//############################################################################# + +/// Cube Root +#if 0 +inline double CoinCbrt(double x) +{ +#if defined(_MSC_VER) + return pow(x,(1./3.)); +#else + return cbrt(x); +#endif +} +#endif + +//----------------------------------------------------------------------------- + +/// This helper returns "sizeof" as an int +#define CoinSizeofAsInt(type) (static_cast<int>(sizeof(type))) +/// This helper returns "strlen" as an int +inline int +CoinStrlenAsInt(const char * string) +{ + return static_cast<int>(strlen(string)); +} + +/** Class for thread specific random numbers +*/ +#if defined COIN_OWN_RANDOM_32 +class CoinThreadRandom { +public: + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + CoinThreadRandom() + { seed_=12345678;} + /** Constructor wih seed. */ + CoinThreadRandom(int seed) + { + seed_ = seed; + } + /** Destructor */ + ~CoinThreadRandom() {} + // Copy + CoinThreadRandom(const CoinThreadRandom & rhs) + { seed_ = rhs.seed_;} + // Assignment + CoinThreadRandom& operator=(const CoinThreadRandom & rhs) + { + if (this != &rhs) { + seed_ = rhs.seed_; + } + return *this; + } + + //@} + + /**@name Sets/gets */ + + //@{ + /** Set seed. */ + inline void setSeed(int seed) + { + seed_ = seed; + } + /** Get seed. */ + inline unsigned int getSeed() const + { + return seed_; + } + /// return a random number + inline double randomDouble() const + { + double retVal; + seed_ = 1664525*(seed_)+1013904223; + retVal = ((static_cast<double> (seed_))/4294967296.0); + return retVal; + } + /// make more random (i.e. for startup) + inline void randomize(int n=0) + { + if (!n) + n=seed_ & 255; + for (int i=0;i<n;i++) + randomDouble(); + } + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Current seed + mutable unsigned int seed_; + //@} +}; +#else +class CoinThreadRandom { +public: + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + CoinThreadRandom() + { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;} + /** Constructor wih seed. */ + CoinThreadRandom(const unsigned short seed[3]) + { memcpy(seed_,seed,3*sizeof(unsigned short));} + /** Constructor wih seed. */ + CoinThreadRandom(int seed) + { + union { int i[2]; unsigned short int s[4];} put; + put.i[0]=seed; + put.i[1]=seed; + memcpy(seed_,put.s,3*sizeof(unsigned short)); + } + /** Destructor */ + ~CoinThreadRandom() {} + // Copy + CoinThreadRandom(const CoinThreadRandom & rhs) + { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));} + // Assignment + CoinThreadRandom& operator=(const CoinThreadRandom & rhs) + { + if (this != &rhs) { + memcpy(seed_,rhs.seed_,3*sizeof(unsigned short)); + } + return *this; + } + + //@} + + /**@name Sets/gets */ + + //@{ + /** Set seed. */ + inline void setSeed(const unsigned short seed[3]) + { memcpy(seed_,seed,3*sizeof(unsigned short));} + /** Set seed. */ + inline void setSeed(int seed) + { + union { int i[2]; unsigned short int s[4];} put; + put.i[0]=seed; + put.i[1]=seed; + memcpy(seed_,put.s,3*sizeof(unsigned short)); + } + /// return a random number + inline double randomDouble() const + { + double retVal; +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) + retVal=rand(); + retVal=retVal/(double) RAND_MAX; +#else + retVal = erand48(seed_); +#endif + return retVal; + } + /// make more random (i.e. for startup) + inline void randomize(int n=0) + { + if (!n) { + n=seed_[0]+seed_[1]+seed_[2]; + n &= 255; + } + for (int i=0;i<n;i++) + randomDouble(); + } + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Current seed + mutable unsigned short seed_[3]; + //@} +}; +#endif +#ifndef COIN_DETAIL +#define COIN_DETAIL_PRINT(s) {} +#else +#define COIN_DETAIL_PRINT(s) s +#endif +#endif diff --git a/thirdparty/linux/include/coin/CoinIndexedVector.hpp b/thirdparty/linux/include/coin/CoinIndexedVector.hpp new file mode 100644 index 0000000..9c386c5 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinIndexedVector.hpp @@ -0,0 +1,1164 @@ +/* $Id: CoinIndexedVector.hpp 1767 2015-01-05 12:36:13Z forrest $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinIndexedVector_H +#define CoinIndexedVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +#endif + +#include <map> +#include "CoinFinite.hpp" +#ifndef CLP_NO_VECTOR +#include "CoinPackedVectorBase.hpp" +#endif +#include "CoinSort.hpp" +#include "CoinHelperFunctions.hpp" +#include <cassert> + +#ifndef COIN_FLOAT +#define COIN_INDEXED_TINY_ELEMENT 1.0e-50 +#define COIN_INDEXED_REALLY_TINY_ELEMENT 1.0e-100 +#else +#define COIN_INDEXED_TINY_ELEMENT 1.0e-35 +#define COIN_INDEXED_REALLY_TINY_ELEMENT 1.0e-39 +#endif + +/** Indexed Vector + +This stores values unpacked but apart from that is a bit like CoinPackedVector. +It is designed to be lightweight in normal use. + +It now has a "packed" mode when it is even more like CoinPackedVector + +Indices array has capacity_ extra chars which are zeroed and can +be used for any purpose - but must be re-zeroed + +Stores vector of indices and associated element values. +Supports sorting of indices. + +Does not support negative indices. + +Does NOT support testing for duplicates + +*** getElements is no longer supported + +Here is a sample usage: +@verbatim + const int ne = 4; + int inx[ne] = { 1, 4, 0, 2 } + double el[ne] = { 10., 40., 1., 50. } + + // Create vector and set its valuex1 + CoinIndexedVector r(ne,inx,el); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // sort Elements in increasing order + r.sortIncrElement(); + + // access each index and element + assert( r.getIndices ()[0]== 0 ); + assert( r.getIndices ()[1]== 1 ); + assert( r.getIndices ()[2]== 4 ); + assert( r.getIndices ()[3]== 2 ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // Tests for equality and equivalence + CoinIndexedVector r1; + r1=r; + assert( r==r1 ); + assert( r.equivalent(r1) ); + r.sortIncrElement(); + assert( r!=r1 ); + assert( r.equivalent(r1) ); + + // Add indexed vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinIndexedVector add = r + r1; + assert( add[0] == 1.+ 1. ); + assert( add[1] == 10.+10. ); + assert( add[2] == 50.+50. ); + assert( add[3] == 0.+ 0. ); + assert( add[4] == 40.+40. ); + + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +class CoinIndexedVector { + friend void CoinIndexedVectorUnitTest(); + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getNumElements() const { return nElements_; } + /// Get indices of elements + inline const int * getIndices() const { return indices_; } + /// Get element values + // ** No longer supported virtual const double * getElements() const ; + /// Get indices of elements + inline int * getIndices() { return indices_; } + /** Get the vector as a dense vector. This is normal storage method. + The user should not not delete [] this. + */ + inline double * denseVector() const { return elements_; } + /// For very temporary use when user needs to borrow a dense vector + inline void setDenseVector(double * array) + { elements_ = array;} + /// For very temporary use when user needs to borrow an index vector + inline void setIndexVector(int * array) + { indices_ = array;} + /** Access the i'th element of the full storage vector. + */ + double & operator[](int i) const; + + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Set the size + inline void setNumElements(int value) { nElements_ = value; + if (!nElements_) packedMode_=false;} + /// Reset the vector (as if were just created an empty vector). This leaves arrays! + void clear(); + /// Reset the vector (as if were just created an empty vector) + void empty(); + /** Assignment operator. */ + CoinIndexedVector & operator=(const CoinIndexedVector &); +#ifndef CLP_NO_VECTOR + /** Assignment operator from a CoinPackedVectorBase. <br> + <strong>NOTE</strong>: This assumes no duplicates */ + CoinIndexedVector & operator=(const CoinPackedVectorBase & rhs); +#endif + /** Copy the contents of one vector into another. If multiplier is 1 + It is the equivalent of = but if vectors are same size does + not re-allocate memory just clears and copies */ + void copy(const CoinIndexedVector & rhs, double multiplier=1.0); + + /** Borrow ownership of the arguments to this vector. + Size is the length of the unpacked elements vector. */ + void borrowVector(int size, int numberIndices, int* inds, double* elems); + + /** Return ownership of the arguments to this vector. + State after is empty . + */ + void returnVector(); + + /** Set vector numberIndices, indices, and elements. + NumberIndices is the length of both the indices and elements vectors. + The indices and elements vectors are copied into this class instance's + member data. Assumed to have no duplicates */ + void setVector(int numberIndices, const int * inds, const double * elems); + + /** Set vector size, indices, and elements. + Size is the length of the unpacked elements vector. + The indices and elements vectors are copied into this class instance's + member data. We do not check for duplicate indices */ + void setVector(int size, int numberIndices, const int * inds, const double * elems); + + /** Elements set to have the same scalar value */ + void setConstant(int size, const int * inds, double elems); + + /** Indices are not specified and are taken to be 0,1,...,size-1 */ + void setFull(int size, const double * elems); + + /** Set an existing element in the indexed vector + The first argument is the "index" into the elements() array + */ + void setElement(int index, double element); + + /// Insert an element into the vector + void insert(int index, double element); + /// Insert a nonzero element into the vector + inline void quickInsert(int index, double element) + { + assert (!elements_[index]); + indices_[nElements_++] = index; + assert (nElements_<=capacity_); + elements_[index] = element; + } + /** Insert or if exists add an element into the vector + Any resulting zero elements will be made tiny */ + void add(int index, double element); + /** Insert or if exists add an element into the vector + Any resulting zero elements will be made tiny. + This version does no checking */ + inline void quickAdd(int index, double element) + { + if (elements_[index]) { + element += elements_[index]; + if ((element > 0 ? element : -element) >= COIN_INDEXED_TINY_ELEMENT) { + elements_[index] = element; + } else { + elements_[index] = 1.0e-100; + } + } else if ((element > 0 ? element : -element) >= COIN_INDEXED_TINY_ELEMENT) { + indices_[nElements_++] = index; + assert (nElements_<=capacity_); + elements_[index] = element; + } + } + /** Insert or if exists add an element into the vector + Any resulting zero elements will be made tiny. + This knows element is nonzero + This version does no checking */ + inline void quickAddNonZero(int index, double element) + { + assert (element); + if (elements_[index]) { + element += elements_[index]; + if ((element > 0 ? element : -element) >= COIN_INDEXED_TINY_ELEMENT) { + elements_[index] = element; + } else { + elements_[index] = COIN_DBL_MIN; + } + } else { + indices_[nElements_++] = index; + assert (nElements_<=capacity_); + elements_[index] = element; + } + } + /** Makes nonzero tiny. + This version does no checking */ + inline void zero(int index) + { + if (elements_[index]) + elements_[index] = COIN_DBL_MIN; + } + /** set all small values to zero and return number remaining + - < tolerance => 0.0 */ + int clean(double tolerance); + /// Same but packs down + int cleanAndPack(double tolerance); + /// Same but packs down and is safe (i.e. if order is odd) + int cleanAndPackSafe(double tolerance); + /// Mark as packed + inline void setPacked() + { packedMode_ = true;} +#ifndef NDEBUG + /// For debug check vector is clear i.e. no elements + void checkClear(); + /// For debug check vector is clean i.e. elements match indices + void checkClean(); +#else + inline void checkClear() {}; + inline void checkClean() {}; +#endif + /// Scan dense region and set up indices (returns number found) + int scan(); + /** Scan dense region from start to < end and set up indices + returns number found + */ + int scan(int start, int end); + /** Scan dense region and set up indices (returns number found). + Only ones >= tolerance */ + int scan(double tolerance); + /** Scan dense region from start to < end and set up indices + returns number found. Only >= tolerance + */ + int scan(int start, int end, double tolerance); + /// These are same but pack down + int scanAndPack(); + int scanAndPack(int start, int end); + int scanAndPack(double tolerance); + int scanAndPack(int start, int end, double tolerance); + /// Create packed array + void createPacked(int number, const int * indices, + const double * elements); + /// Create unpacked array + void createUnpacked(int number, const int * indices, + const double * elements); + /// Create unpacked singleton + void createOneUnpackedElement(int index, double element); + /// This is mainly for testing - goes from packed to indexed + void expand(); +#ifndef CLP_NO_VECTOR + /// Append a CoinPackedVector to the end + void append(const CoinPackedVectorBase & caboose); +#endif + /// Append a CoinIndexedVector to the end (with extra space) + void append(const CoinIndexedVector & caboose); + /// Append a CoinIndexedVector to the end and modify indices + void append(CoinIndexedVector & other,int adjustIndex,bool zapElements=false); + + /// Swap values in positions i and j of indices and elements + void swap(int i, int j); + + /// Throw away all entries in rows >= newSize + void truncate(int newSize); + /// Print out + void print() const; + //@} + /**@name Arithmetic operators. */ + //@{ + /// add <code>value</code> to every entry + void operator+=(double value); + /// subtract <code>value</code> from every entry + void operator-=(double value); + /// multiply every entry by <code>value</code> + void operator*=(double value); + /// divide every entry by <code>value</code> (** 0 vanishes) + void operator/=(double value); + //@} + + /**@name Comparison operators on two indexed vectors */ + //@{ +#ifndef CLP_NO_VECTOR + /** Equal. Returns true if vectors have same length and corresponding + element of each vector is equal. */ + bool operator==(const CoinPackedVectorBase & rhs) const; + /// Not equal + bool operator!=(const CoinPackedVectorBase & rhs) const; +#endif + /** Equal. Returns true if vectors have same length and corresponding + element of each vector is equal. */ + bool operator==(const CoinIndexedVector & rhs) const; + /// Not equal + bool operator!=(const CoinIndexedVector & rhs) const; + /// Equal with a tolerance (returns -1 or position of inequality). + int isApproximatelyEqual(const CoinIndexedVector & rhs, double tolerance=1.0e-8) const; + //@} + + /**@name Index methods */ + //@{ + /// Get value of maximum index + int getMaxIndex() const; + /// Get value of minimum index + int getMinIndex() const; + //@} + + + /**@name Sorting */ + //@{ + /** Sort the indexed storage vector (increasing indices). */ + void sort() + { std::sort(indices_,indices_+nElements_); } + + void sortIncrIndex() + { std::sort(indices_,indices_+nElements_); } + + void sortDecrIndex(); + + void sortIncrElement(); + + void sortDecrElement(); + void sortPacked(); + + //@} + + //############################################################################# + + /**@name Arithmetic operators on packed vectors. + + <strong>NOTE</strong>: These methods operate on those positions where at + least one of the arguments has a value listed. At those positions the + appropriate operation is executed, Otherwise the result of the operation is + considered 0.<br> + <strong>NOTE 2</strong>: Because these methods return an object (they can't + return a reference, though they could return a pointer...) they are + <em>very</em> inefficient... + */ +//@{ +/// Return the sum of two indexed vectors +CoinIndexedVector operator+( + const CoinIndexedVector& op2); + +/// Return the difference of two indexed vectors +CoinIndexedVector operator-( + const CoinIndexedVector& op2); + +/// Return the element-wise product of two indexed vectors +CoinIndexedVector operator*( + const CoinIndexedVector& op2); + +/// Return the element-wise ratio of two indexed vectors (0.0/0.0 => 0.0) (0 vanishes) +CoinIndexedVector operator/( + const CoinIndexedVector& op2); +/// The sum of two indexed vectors +void operator+=(const CoinIndexedVector& op2); + +/// The difference of two indexed vectors +void operator-=( const CoinIndexedVector& op2); + +/// The element-wise product of two indexed vectors +void operator*=(const CoinIndexedVector& op2); + +/// The element-wise ratio of two indexed vectors (0.0/0.0 => 0.0) (0 vanishes) +void operator/=(const CoinIndexedVector& op2); +//@} + + /**@name Memory usage */ + //@{ + /** Reserve space. + If one knows the eventual size of the indexed vector, + then it may be more efficient to reserve the space. + */ + void reserve(int n); + /** capacity returns the size which could be accomodated without + having to reallocate storage. + */ + inline int capacity() const { return capacity_; } + inline void setCapacity(int value) + { capacity_ = value; } + /// Sets packed mode + inline void setPackedMode(bool yesNo) + { packedMode_=yesNo;} + /// Gets packed mode + inline bool packedMode() const + { return packedMode_;} + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor */ + CoinIndexedVector(); + /** Alternate Constructors - set elements to vector of doubles */ + CoinIndexedVector(int size, const int * inds, const double * elems); + /** Alternate Constructors - set elements to same scalar value */ + CoinIndexedVector(int size, const int * inds, double element); + /** Alternate Constructors - construct full storage with indices 0 through + size-1. */ + CoinIndexedVector(int size, const double * elements); + /** Alternate Constructors - just size */ + CoinIndexedVector(int size); + /** Copy constructor. */ + CoinIndexedVector(const CoinIndexedVector &); + /** Copy constructor.2 */ + CoinIndexedVector(const CoinIndexedVector *); +#ifndef CLP_NO_VECTOR + /** Copy constructor <em>from a PackedVectorBase</em>. */ + CoinIndexedVector(const CoinPackedVectorBase & rhs); +#endif + /** Destructor */ + ~CoinIndexedVector (); + //@} + +private: + /**@name Private methods */ + //@{ + /// Copy internal data + void gutsOfSetVector(int size, + const int * inds, const double * elems); + void gutsOfSetVector(int size, int numberIndices, + const int * inds, const double * elems); + void gutsOfSetPackedVector(int size, int numberIndices, + const int * inds, const double * elems); + /// + void gutsOfSetConstant(int size, + const int * inds, double value); + //@} + +protected: + /**@name Private member data */ + //@{ + /// Vector indices + int * indices_; + ///Vector elements + double * elements_; + /// Size of indices and packed elements vectors + int nElements_; + /// Amount of memory allocated for indices_, and elements_. + int capacity_; + /// Offset to get where new allocated array + int offset_; + /// If true then is operating in packed mode + bool packedMode_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CoinIndexedVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void +CoinIndexedVectorUnitTest(); +/** Pointer with length in bytes + + This has a pointer to an array and the number of bytes in array. + If number of bytes==-1 then + CoinConditionalNew deletes existing pointer and returns new pointer + of correct size (and number bytes still -1). + CoinConditionalDelete deletes existing pointer and NULLs it. + So behavior is as normal (apart from New deleting pointer which will have + no effect with good coding practices. + If number of bytes >=0 then + CoinConditionalNew just returns existing pointer if array big enough + otherwise deletes existing pointer, allocates array with spare 1%+64 bytes + and updates number of bytes + CoinConditionalDelete sets number of bytes = -size-2 and then array + returns NULL +*/ +class CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_; } + /// Get the size + inline int rawSize() const + { return size_; } + /// See if persistence already on + inline bool switchedOn() const + { return size_!=-1; } + /// Get the capacity (just read it) + inline int capacity() const + { return (size_>-2) ? size_ : (-size_)-2; } + /// Set the capacity to >=0 if <=-2 + inline void setCapacity() + { if (size_<=-2) size_ = (-size_)-2; } + /// Get Array + inline const char * array() const + { return (size_>-2) ? array_ : NULL; } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value; } + /// Set the size to -1 + inline void switchOff() + { size_ = -1; } + /// Set the size to -2 and alignment + inline void switchOn(int alignment=3) + { size_ = -2; alignment_=alignment;} + /// Does what is needed to set persistence + void setPersistence(int flag,int currentLength); + /// Zero out array + void clear(); + /// Swaps memory between two members + void swap(CoinArrayWithLength & other); + /// Extend a persistent array keeping data (size in bytes) + void extend(int newSize); + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + char * conditionalNew(long sizeWanted); + /// Conditionally deletes + void conditionalDelete(); + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinArrayWithLength() + : array_(NULL),size_(-1),offset_(0),alignment_(0) + { } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinArrayWithLength(int size) + : size_(-1),offset_(0),alignment_(0) + { array_=new char [size];} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + mode>0 size_ set to size and zeroed + if size<=0 just does alignment + If abs(mode) >2 then align on that as power of 2 + */ + CoinArrayWithLength(int size, int mode); + /** Copy constructor. */ + CoinArrayWithLength(const CoinArrayWithLength & rhs); + /** Copy constructor.2 */ + CoinArrayWithLength(const CoinArrayWithLength * rhs); + /** Assignment operator. */ + CoinArrayWithLength& operator=(const CoinArrayWithLength & rhs); + /** Assignment with length (if -1 use internal length) */ + void copy(const CoinArrayWithLength & rhs, int numberBytes=-1); + /** Assignment with length - does not copy */ + void allocate(const CoinArrayWithLength & rhs, int numberBytes); + /** Destructor */ + ~CoinArrayWithLength (); + /// Get array with alignment + void getArray(int size); + /// Really get rid of array with alignment + void reallyFreeArray(); + /// Get enough space (if more needed then do at least needed) + void getCapacity(int numberBytes,int numberIfNeeded=-1); + //@} + +protected: + /**@name Private member data */ + //@{ + /// Array + char * array_; + /// Size of array in bytes + CoinBigIndex size_; + /// Offset of array + int offset_; + /// Alignment wanted (power of 2) + int alignment_; + //@} +}; +/// double * version + +class CoinDoubleArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/CoinSizeofAsInt(double); } + /// Get Array + inline double * array() const + { return reinterpret_cast<double *> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*CoinSizeofAsInt(double); } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline double * conditionalNew(int sizeWanted) + { return reinterpret_cast<double *> ( CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> ((sizeWanted)*CoinSizeofAsInt(double)) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinDoubleArrayWithLength() + { array_=NULL; size_=-1;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinDoubleArrayWithLength(int size) + { array_=new char [size*CoinSizeofAsInt(double)]; size_=-1;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinDoubleArrayWithLength(int size, int mode) + : CoinArrayWithLength(size*CoinSizeofAsInt(double),mode) {} + /** Copy constructor. */ + inline CoinDoubleArrayWithLength(const CoinDoubleArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinDoubleArrayWithLength(const CoinDoubleArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinDoubleArrayWithLength& operator=(const CoinDoubleArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} +}; +/// CoinFactorizationDouble * version + +class CoinFactorizationDoubleArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/CoinSizeofAsInt(CoinFactorizationDouble); } + /// Get Array + inline CoinFactorizationDouble * array() const + { return reinterpret_cast<CoinFactorizationDouble *> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*CoinSizeofAsInt(CoinFactorizationDouble); } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline CoinFactorizationDouble * conditionalNew(int sizeWanted) + { return reinterpret_cast<CoinFactorizationDouble *> (CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> (( sizeWanted)*CoinSizeofAsInt(CoinFactorizationDouble)) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinFactorizationDoubleArrayWithLength() + { array_=NULL; size_=-1;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinFactorizationDoubleArrayWithLength(int size) + { array_=new char [size*CoinSizeofAsInt(CoinFactorizationDouble)]; size_=-1;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinFactorizationDoubleArrayWithLength(int size, int mode) + : CoinArrayWithLength(size*CoinSizeofAsInt(CoinFactorizationDouble),mode) {} + /** Copy constructor. */ + inline CoinFactorizationDoubleArrayWithLength(const CoinFactorizationDoubleArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinFactorizationDoubleArrayWithLength(const CoinFactorizationDoubleArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinFactorizationDoubleArrayWithLength& operator=(const CoinFactorizationDoubleArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} +}; +/// CoinFactorizationLongDouble * version + +class CoinFactorizationLongDoubleArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/CoinSizeofAsInt(long double); } + /// Get Array + inline long double * array() const + { return reinterpret_cast<long double *> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*CoinSizeofAsInt(long double); } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline long double * conditionalNew(int sizeWanted) + { return reinterpret_cast<long double *> (CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> (( sizeWanted)*CoinSizeofAsInt(long double)) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinFactorizationLongDoubleArrayWithLength() + { array_=NULL; size_=-1;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinFactorizationLongDoubleArrayWithLength(int size) + { array_=new char [size*CoinSizeofAsInt(long double)]; size_=-1;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinFactorizationLongDoubleArrayWithLength(int size, int mode) + : CoinArrayWithLength(size*CoinSizeofAsInt(long double),mode) {} + /** Copy constructor. */ + inline CoinFactorizationLongDoubleArrayWithLength(const CoinFactorizationLongDoubleArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinFactorizationLongDoubleArrayWithLength(const CoinFactorizationLongDoubleArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinFactorizationLongDoubleArrayWithLength& operator=(const CoinFactorizationLongDoubleArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} +}; +/// int * version + +class CoinIntArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/CoinSizeofAsInt(int); } + /// Get Array + inline int * array() const + { return reinterpret_cast<int *> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*CoinSizeofAsInt(int); } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline int * conditionalNew(int sizeWanted) + { return reinterpret_cast<int *> (CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> (( sizeWanted)*CoinSizeofAsInt(int)) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinIntArrayWithLength() + { array_=NULL; size_=-1;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinIntArrayWithLength(int size) + { array_=new char [size*CoinSizeofAsInt(int)]; size_=-1;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinIntArrayWithLength(int size, int mode) + : CoinArrayWithLength(size*CoinSizeofAsInt(int),mode) {} + /** Copy constructor. */ + inline CoinIntArrayWithLength(const CoinIntArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinIntArrayWithLength(const CoinIntArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinIntArrayWithLength& operator=(const CoinIntArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} +}; +/// CoinBigIndex * version + +class CoinBigIndexArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/CoinSizeofAsInt(CoinBigIndex); } + /// Get Array + inline CoinBigIndex * array() const + { return reinterpret_cast<CoinBigIndex *> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*CoinSizeofAsInt(CoinBigIndex); } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline CoinBigIndex * conditionalNew(int sizeWanted) + { return reinterpret_cast<CoinBigIndex *> (CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> (( sizeWanted)*CoinSizeofAsInt(CoinBigIndex)) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinBigIndexArrayWithLength() + { array_=NULL; size_=-1;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinBigIndexArrayWithLength(int size) + { array_=new char [size*CoinSizeofAsInt(CoinBigIndex)]; size_=-1;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinBigIndexArrayWithLength(int size, int mode) + : CoinArrayWithLength(size*CoinSizeofAsInt(CoinBigIndex),mode) {} + /** Copy constructor. */ + inline CoinBigIndexArrayWithLength(const CoinBigIndexArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinBigIndexArrayWithLength(const CoinBigIndexArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinBigIndexArrayWithLength& operator=(const CoinBigIndexArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} +}; +/// unsigned int * version + +class CoinUnsignedIntArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/CoinSizeofAsInt(unsigned int); } + /// Get Array + inline unsigned int * array() const + { return reinterpret_cast<unsigned int *> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*CoinSizeofAsInt(unsigned int); } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline unsigned int * conditionalNew(int sizeWanted) + { return reinterpret_cast<unsigned int *> (CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> (( sizeWanted)*CoinSizeofAsInt(unsigned int)) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinUnsignedIntArrayWithLength() + { array_=NULL; size_=-1;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinUnsignedIntArrayWithLength(int size) + { array_=new char [size*CoinSizeofAsInt(unsigned int)]; size_=-1;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinUnsignedIntArrayWithLength(int size, int mode) + : CoinArrayWithLength(size*CoinSizeofAsInt(unsigned int),mode) {} + /** Copy constructor. */ + inline CoinUnsignedIntArrayWithLength(const CoinUnsignedIntArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinUnsignedIntArrayWithLength(const CoinUnsignedIntArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinUnsignedIntArrayWithLength& operator=(const CoinUnsignedIntArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} +}; +/// void * version + +class CoinVoidStarArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/CoinSizeofAsInt(void *); } + /// Get Array + inline void ** array() const + { return reinterpret_cast<void **> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*CoinSizeofAsInt(void *); } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline void ** conditionalNew(int sizeWanted) + { return reinterpret_cast<void **> ( CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> ((sizeWanted)*CoinSizeofAsInt(void *)) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinVoidStarArrayWithLength() + { array_=NULL; size_=-1;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinVoidStarArrayWithLength(int size) + { array_=new char [size*CoinSizeofAsInt(void *)]; size_=-1;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinVoidStarArrayWithLength(int size, int mode) + : CoinArrayWithLength(size*CoinSizeofAsInt(void *),mode) {} + /** Copy constructor. */ + inline CoinVoidStarArrayWithLength(const CoinVoidStarArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinVoidStarArrayWithLength(const CoinVoidStarArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinVoidStarArrayWithLength& operator=(const CoinVoidStarArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} +}; +/// arbitrary version + +class CoinArbitraryArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getSize() const + { return size_/lengthInBytes_; } + /// Get Array + inline void ** array() const + { return reinterpret_cast<void **> ((size_>-2) ? array_ : NULL); } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { size_ = value*lengthInBytes_; } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline char * conditionalNew(int length, int sizeWanted) + { lengthInBytes_=length;return reinterpret_cast<char *> ( CoinArrayWithLength::conditionalNew(sizeWanted>=0 ? static_cast<long> + ((sizeWanted)*lengthInBytes_) : -1)); } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinArbitraryArrayWithLength(int length=1) + { array_=NULL; size_=-1;lengthInBytes_=length;} + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinArbitraryArrayWithLength(int length, int size) + { array_=new char [size*length]; size_=-1; lengthInBytes_=length;} + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinArbitraryArrayWithLength(int length, int size, int mode) + : CoinArrayWithLength(size*length,mode) {lengthInBytes_=length;} + /** Copy constructor. */ + inline CoinArbitraryArrayWithLength(const CoinArbitraryArrayWithLength & rhs) + : CoinArrayWithLength(rhs) {} + /** Copy constructor.2 */ + inline CoinArbitraryArrayWithLength(const CoinArbitraryArrayWithLength * rhs) + : CoinArrayWithLength(rhs) {} + /** Assignment operator. */ + inline CoinArbitraryArrayWithLength& operator=(const CoinArbitraryArrayWithLength & rhs) + { CoinArrayWithLength::operator=(rhs); return *this;} + //@} + +protected: + /**@name Private member data */ + //@{ + /// Length in bytes + int lengthInBytes_; + //@} +}; +class CoinPartitionedVector : public CoinIndexedVector { + +public: +#ifndef COIN_PARTITIONS +#define COIN_PARTITIONS 8 +#endif + /**@name Get methods. */ + //@{ + /// Get the size of a partition + inline int getNumElements(int partition) const { assert (partition<COIN_PARTITIONS); + return numberElementsPartition_[partition]; } + /// Get number of partitions + inline int getNumPartitions() const + { return numberPartitions_; } + /// Get the size + inline int getNumElements() const { return nElements_; } + /// Get starts + inline int startPartition(int partition) const { assert (partition<=COIN_PARTITIONS); + return startPartition_[partition]; } + /// Get starts + inline const int * startPartitions() const + { return startPartition_; } + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Set the size of a partition + inline void setNumElementsPartition(int partition, int value) { assert (partition<COIN_PARTITIONS); + if (numberPartitions_) numberElementsPartition_[partition]=value; } + /// Set the size of a partition (just for a tiny while) + inline void setTempNumElementsPartition(int partition, int value) { assert (partition<COIN_PARTITIONS); + numberElementsPartition_[partition]=value; } + /// Add up number of elements in partitions + void computeNumberElements(); + /// Add up number of elements in partitions and pack and get rid of partitions + void compact(); + /** Reserve space. + */ + void reserve(int n); + /// Setup partitions (needs end as well) + void setPartitions(int number,const int * starts); + /// Reset the vector (as if were just created an empty vector). Gets rid of partitions + void clearAndReset(); + /// Reset the vector (as if were just created an empty vector). Keeps partitions + void clearAndKeep(); + /// Clear a partition. + void clearPartition(int partition); +#ifndef NDEBUG + /// For debug check vector is clear i.e. no elements + void checkClear(); + /// For debug check vector is clean i.e. elements match indices + void checkClean(); +#else + inline void checkClear() {}; + inline void checkClean() {}; +#endif + /// Scan dense region and set up indices (returns number found) + int scan(int partition, double tolerance=0.0); + /** Scan dense region from start to < end and set up indices + returns number found + */ + /// Print out + void print() const; + //@} + + /**@name Sorting */ + //@{ + /** Sort the indexed storage vector (increasing indices). */ + void sort(); + //@} + + /**@name Constructors and destructors (not all wriiten) */ + //@{ + /** Default constructor */ + CoinPartitionedVector(); + /** Alternate Constructors - set elements to vector of doubles */ + CoinPartitionedVector(int size, const int * inds, const double * elems); + /** Alternate Constructors - set elements to same scalar value */ + CoinPartitionedVector(int size, const int * inds, double element); + /** Alternate Constructors - construct full storage with indices 0 through + size-1. */ + CoinPartitionedVector(int size, const double * elements); + /** Alternate Constructors - just size */ + CoinPartitionedVector(int size); + /** Copy constructor. */ + CoinPartitionedVector(const CoinPartitionedVector &); + /** Copy constructor.2 */ + CoinPartitionedVector(const CoinPartitionedVector *); + /** Assignment operator. */ + CoinPartitionedVector & operator=(const CoinPartitionedVector &); + /** Destructor */ + ~CoinPartitionedVector (); + //@} +protected: + /**@name Private member data */ + //@{ + /// Starts + int startPartition_[COIN_PARTITIONS+1]; + /// Size of indices in a partition + int numberElementsPartition_[COIN_PARTITIONS]; + /// Number of partitions (0 means off) + int numberPartitions_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CoinLpIO.hpp b/thirdparty/linux/include/coin/CoinLpIO.hpp new file mode 100644 index 0000000..43c0e20 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinLpIO.hpp @@ -0,0 +1,805 @@ +/* $Id: CoinLpIO.hpp 1749 2014-10-24 20:00:14Z tkr $ */ +// Last edit: 11/5/08 +// +// Name: CoinLpIO.hpp; Support for Lp files +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 12/28/03 +//----------------------------------------------------------------------------- +// Copyright (C) 2003, Francois Margot, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinLpIO_H +#define CoinLpIO_H + +#include <cstdio> + +#include "CoinPackedMatrix.hpp" +#include "CoinMessage.hpp" +class CoinSet; + +const int MAX_OBJECTIVES = 2; + +typedef int COINColumnIndex; + + /** Class to read and write Lp files + + Lp file format: + +/ this is a comment <BR> +\ this too <BR> + Min<BR> + obj: x0 + x1 + 3 x2 - 4.5 xyr + 1 <BR> + s.t. <BR> + cons1: x0 - x2 - 2.3 x4 <= 4.2 / this is another comment <BR> + c2: x1 + x2 >= 1 <BR> + cc: x1 + x2 + xyr = 2 <BR> + Bounds <BR> + 0 <= x1 <= 3 <BR> + 1 >= x2 <BR> + x3 = 1 <BR> + -2 <= x4 <= Inf <BR> + xyr free <BR> + Integers <BR> + x0 <BR> + Generals <BR> + x1 xyr <BR> + Binaries <BR> + x2 <BR> + End + +Notes: <UL> + <LI> Keywords are: Min, Max, Minimize, Maximize, s.t., Subject To, + Bounds, Integers, Generals, Binaries, End, Free, Inf. + <LI> Keywords are not case sensitive and may be in plural or singular form. + They should not be used as objective, row or column names. + <LI> Bounds, Integers, Generals, Binaries sections are optional. + <LI> Generals and Integers are synonymous. + <LI> Bounds section (if any) must come before Integers, Generals, and + Binaries sections. + <LI> Row names must be followed by ':' without blank space. + Row names are optional. If row names are present, + they must be distinct (if the k-th constraint has no given name, its name + is set automatically to "consk" for k=0,...,). + For valid row names, see the method is_invalid_name(). + <LI> Column names must be followed by a blank space. They must be distinct. + For valid column names, see the method is_invalid_name(). + <LI> Multiple objectives may be specified, but when there are multiple + objectives, they must have names (to indicate where each one starts). + <LI> The objective function names must be followed by ':' without blank space. + If there is a single objective, the objective function name is optional. + If no name is given, the name is set to "obj" by default. + For valid objective function names, see the method is_invalid_name(). + <LI> Ranged constraints are written as two constraints. + If a name is given for a ranged constraint, the upper bound constraint + has that name and the lower bound constraint has that name with "_low" + as suffix. This should be kept in mind when assigning names to ranged + constraint, as the resulting name must be distinct from all the other + names and be considered valid by the method is_invalid_name(). + <LI> At most one term related to any single variable may appear in the + objective function; if more than one term are present, only the last + one is taken into account. + At most one constant term may appear in the objective function; + if present, it must appear last. + <LI> Default bounds are 0 for lower bound and +infinity for upper bound. + <LI> Free variables get default lower bound -infinity and + default upper bound +infinity. Writing "x0 Free" in an + LP file means "set lower bound on x0 to -infinity". + <LI> If more than one upper (resp. lower) bound on a variable appears in + the Bounds section, the last one is the one taken into + account. The bounds for a binary variable are set to 0/1 only if this + bound is stronger than the bound obtained from the Bounds section. + <LI> Numbers larger than DBL_MAX (or larger than 1e+400) in the input file + might crash the code. + <LI> A comment must start with '\' or '/'. That symbol must either be + the first character of a line or be preceded by a blank space. The + comment ends at the end of the + line. Comments are skipped while reading an Lp file and they may be + inserted anywhere. +</UL> +*/ +class CoinLpIO { + friend void CoinLpIOUnitTest(const std::string & lpDir); +public: + + /**@name Constructor and Destructor */ + //@{ + /// Default Constructor + CoinLpIO(); + + /// Does the heavy lifting for destruct and assignment. + void gutsOfDestructor(); + + /// Does the heavy lifting for copy and assignment + void gutsOfCopy(const CoinLpIO &); + + /// assignment operator + CoinLpIO & operator = (const CoinLpIO& rhs) ; + + /// Copy constructor + CoinLpIO (const CoinLpIO &); + + /// Destructor + ~CoinLpIO(); + + /** Free the vector previous_names_[section] and set + card_previous_names_[section] to 0. + section = 0 for row names, + section = 1 for column names. + */ + void freePreviousNames(const int section); + + /// Free all memory (except memory related to hash tables and objName_). + void freeAll(); + //@} + + /** A quick inlined function to convert from lb/ub style constraint + definition to sense/rhs/range style */ + inline void + convertBoundToSense(const double lower, const double upper, + char& sense, double& right, double& range) const; + + /**@name Queries */ + //@{ + + /// Get the problem name + const char * getProblemName() const; + + /// Set problem name + void setProblemName(const char *name); + + /// Get number of columns + int getNumCols() const; + + /// Get number of rows + int getNumRows() const; + + /// Get number of nonzero elements + int getNumElements() const; + + /// Get pointer to array[getNumCols()] of column lower bounds + const double * getColLower() const; + + /// Get pointer to array[getNumCols()] of column upper bounds + const double * getColUpper() const; + + /// Get pointer to array[getNumRows()] of row lower bounds + const double * getRowLower() const; + + /// Get pointer to array[getNumRows()] of row upper bounds + const double * getRowUpper() const; + /** Get pointer to array[getNumRows()] of constraint senses. + <ul> + <li>'L': <= constraint + <li>'E': = constraint + <li>'G': >= constraint + <li>'R': ranged constraint + <li>'N': free constraint + </ul> + */ + const char * getRowSense() const; + + /** Get pointer to array[getNumRows()] of constraint right-hand sides. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint right-hand side (rhs) is set as + <ul> + <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] + <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] + <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] + <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0 + </ul> + */ + const double * getRightHandSide() const; + + /** Get pointer to array[getNumRows()] of row ranges. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint range (rowrange) is set as + <ul> + <li> if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] + <li> if rowsense()[i] != 'R' then + rowrange()[i] is 0.0 + </ul> + Put another way, only ranged constraints have a nontrivial value for + rowrange. + */ + const double * getRowRange() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + const int getNumObjectives() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + const double * getObjCoefficients() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients for objective j + const double * getObjCoefficients(int j) const; + + /// Get pointer to row-wise copy of the coefficient matrix + const CoinPackedMatrix * getMatrixByRow() const; + + /// Get pointer to column-wise copy of the coefficient matrix + const CoinPackedMatrix * getMatrixByCol() const; + + /// Get objective function name + const char * getObjName() const; + + /// Get objective function name for objective j + const char * getObjName(int j) const; + + /// Get pointer to array[*card_prev] of previous row names. + /// The value of *card_prev might be different than getNumRows()+1 if + /// non distinct + /// row names were present or if no previous names were saved or if + /// the object was holding a different problem before. + void getPreviousRowNames(char const * const * prev, + int *card_prev) const; + + /// Get pointer to array[*card_prev] of previous column names. + /// The value of *card_prev might be different than getNumCols() if non + /// distinct column names were present of if no previous names were saved, + /// or if the object was holding a different problem before. + void getPreviousColNames(char const * const * prev, + int *card_prev) const; + + /// Get pointer to array[getNumRows()+1] of row names, including + /// objective function name as last entry. + char const * const * getRowNames() const; + + /// Get pointer to array[getNumCols()] of column names + char const * const *getColNames() const; + + /// Return the row name for the specified index. + /// Return the objective function name if index = getNumRows(). + /// Return 0 if the index is out of range or if row names are not defined. + const char * rowName(int index) const; + + /// Return the column name for the specified index. + /// Return 0 if the index is out of range or if column names are not + /// defined. + const char * columnName(int index) const; + + /// Return the index for the specified row name. + /// Return getNumRows() for the objective function name. + /// Return -1 if the name is not found. + int rowIndex(const char * name) const; + + /// Return the index for the specified column name. + /// Return -1 if the name is not found. + int columnIndex(const char * name) const; + + ///Returns the (constant) objective offset + double objectiveOffset() const; + + ///Returns the (constant) objective offset for objective j + double objectiveOffset(int j) const; + + /// Set objective offset + inline void setObjectiveOffset(double value) + { objectiveOffset_[0] = value;} + + /// Set objective offset + inline void setObjectiveOffset(double value, int j) + { objectiveOffset_[j] = value;} + + /// Return true if a column is an integer (binary or general + /// integer) variable + bool isInteger(int columnNumber) const; + + /// Get characteristic vector of integer variables + const char * integerColumns() const; + //@} + + /**@name Parameters */ + //@{ + /// Get infinity + double getInfinity() const; + + /// Set infinity. Any number larger is considered infinity. + /// Default: DBL_MAX + void setInfinity(const double); + + /// Get epsilon + double getEpsilon() const; + + /// Set epsilon. + /// Default: 1e-5. + void setEpsilon(const double); + + /// Get numberAcross, the number of monomials to be printed per line + int getNumberAcross() const; + + /// Set numberAcross. + /// Default: 10. + void setNumberAcross(const int); + + /// Get decimals, the number of digits to write after the decimal point + int getDecimals() const; + + /// Set decimals. + /// Default: 5 + void setDecimals(const int); + //@} + + /**@name Public methods */ + //@{ + /** Set the data of the object. + Set it from the coefficient matrix m, the lower bounds + collb, the upper bounds colub, objective function obj_coeff, + integrality vector integrality, lower/upper bounds on the constraints. + The sense of optimization of the objective function is assumed to be + a minimization. + Numbers larger than DBL_MAX (or larger than 1e+400) + might crash the code. There are two version. The second one is for + setting multiple objectives. + */ + void setLpDataWithoutRowAndColNames( + const CoinPackedMatrix& m, + const double* collb, const double* colub, + const double* obj_coeff, + const char* integrality, + const double* rowlb, const double* rowub); + + void setLpDataWithoutRowAndColNames( + const CoinPackedMatrix& m, + const double* collb, const double* colub, + const double* obj_coeff[MAX_OBJECTIVES], + int num_objectives, + const char* integrality, + const double* rowlb, const double* rowub); + + /** Return 0 if buff is a valid name for a row, a column or objective + function, return a positive number otherwise. + If parameter ranged = true, the name is intended for a ranged + constraint. <BR> + Return 1 if the name has more than 100 characters (96 characters + for a ranged constraint name, as "_low" will be added to the name).<BR> + Return 2 if the name starts with a number.<BR> + Return 3 if the name is not built with + the letters a to z, A to Z, the numbers 0 to 9 or the characters + " ! # $ % & ( ) . ; ? @ _ ' ` { } ~ <BR> + Return 4 if the name is a keyword.<BR> + Return 5 if the name is empty or NULL. */ + int is_invalid_name(const char *buff, const bool ranged) const; + + /** Return 0 if each of the card_vnames entries of vnames is a valid name, + return a positive number otherwise. The return value, if not 0, is the + return value of is_invalid_name() for the last invalid name + in vnames. If check_ranged = true, the names are row names and + names for ranged constaints must be checked for additional restrictions + since "_low" will be added to the name if an Lp file is written. + When check_ranged = true, card_vnames must have getNumRows()+1 entries, + with entry vnames[getNumRows()] being the + name of the objective function. + For a description of valid names and return values, see the method + is_invalid_name(). + + This method must not be called with check_ranged = true before + setLpDataWithoutRowAndColNames() has been called, since access + to the indices of all the ranged constraints is required. + */ + int are_invalid_names(char const * const *vnames, + const int card_vnames, + const bool check_ranged) const; + + /// Set objective function name to the default "obj" and row + /// names to the default "cons0", "cons1", ... + void setDefaultRowNames(); + + /// Set column names to the default "x0", "x1", ... + void setDefaultColNames(); + + /** Set the row and column names. + The array rownames must either be NULL or have exactly getNumRows()+1 + distinct entries, + each of them being a valid name (see is_invalid_name()) and the + last entry being the intended name for the objective function. + If rownames is NULL, existing row names and objective function + name are not changed. + If rownames is deemed invalid, default row names and objective function + name are used (see setDefaultRowNames()). The memory location of + array rownames (or its entries) should not be related + to the memory location of the array (or entries) obtained from + getRowNames() or getPreviousRowNames(), as the call to + setLpDataRowAndColNames() modifies the corresponding arrays. + Unpredictable results + are obtained if this requirement is ignored. + + Similar remarks apply to the array colnames, which must either be + NULL or have exactly getNumCols() entries. + */ + void setLpDataRowAndColNames(char const * const * const rownames, + char const * const * const colnames); + + /** Write the data in Lp format in the file with name filename. + Coefficients with value less than epsilon away from an integer value + are written as integers. + Write at most numberAcross monomials on a line. + Write non integer numbers with decimals digits after the decimal point. + Write objective function name and row names if useRowNames = true. + + Ranged constraints are written as two constraints. + If row names are used, the upper bound constraint has the + name of the original ranged constraint and the + lower bound constraint has for name the original name with + "_low" as suffix. If doing so creates two identical row names, + default row names are used (see setDefaultRowNames()). + */ + int writeLp(const char *filename, + const double epsilon, + const int numberAcross, + const int decimals, + const bool useRowNames = true); + + /** Write the data in Lp format in the file pointed to by the paramater fp. + Coefficients with value less than epsilon away from an integer value + are written as integers. + Write at most numberAcross monomials on a line. + Write non integer numbers with decimals digits after the decimal point. + Write objective function name and row names if useRowNames = true. + + Ranged constraints are written as two constraints. + If row names are used, the upper bound constraint has the + name of the original ranged constraint and the + lower bound constraint has for name the original name with + "_low" as suffix. If doing so creates two identical row names, + default row names are used (see setDefaultRowNames()). + */ + int writeLp(FILE *fp, + const double epsilon, + const int numberAcross, + const int decimals, + const bool useRowNames = true); + + /// Write the data in Lp format in the file with name filename. + /// Write objective function name and row names if useRowNames = true. + int writeLp(const char *filename, const bool useRowNames = true); + + /// Write the data in Lp format in the file pointed to by the parameter fp. + /// Write objective function name and row names if useRowNames = true. + int writeLp(FILE *fp, const bool useRowNames = true); + + /// Read the data in Lp format from the file with name filename, using + /// the given value for epsilon. If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(const char *filename, const double epsilon); + + /// Read the data in Lp format from the file with name filename. + /// If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(const char *filename); + + /// Read the data in Lp format from the file stream, using + /// the given value for epsilon. + /// If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(FILE *fp, const double epsilon); + + /// Read the data in Lp format from the file stream. + /// If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(FILE *fp); + + /// Dump the data. Low level method for debugging. + void print() const; + + /// Load in SOS stuff + void loadSOS(int numberSets,const CoinSet * sets); + + /// Load in SOS stuff + void loadSOS(int numberSets,const CoinSet ** sets); + + /// Number of SOS sets + inline int numberSets() const + { return numberSets_;} + + /// Set information + inline CoinSet ** setInformation() const + { return set_;} + //@} +/**@name Message handling */ +//@{ + /** Pass in Message handler + + Supply a custom message handler. It will not be destroyed when the + CoinMpsIO object is destroyed. + */ + void passInMessageHandler(CoinMessageHandler * handler); + + /// Set the language for messages. + void newLanguage(CoinMessages::Language language); + + /// Set the language for messages. + inline void setLanguage(CoinMessages::Language language) {newLanguage(language);} + + /// Return the message handler + inline CoinMessageHandler * messageHandler() const {return handler_;} + + /// Return the messages + inline CoinMessages messages() {return messages_;} + /// Return the messages pointer + inline CoinMessages * messagesPointer() {return & messages_;} +//@} + +protected: + /// Problem name + char * problemName_; + + /// Message handler + CoinMessageHandler * handler_; + /** Flag to say if the message handler is the default handler. + + If true, the handler will be destroyed when the CoinMpsIO + object is destroyed; if false, it will not be destroyed. + */ + bool defaultHandler_; + /// Messages + CoinMessages messages_; + + /// Number of rows + int numberRows_; + + /// Number of columns + int numberColumns_; + + /// Number of elements + int numberElements_; + + /// Pointer to column-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByColumn_; + + /// Pointer to row-wise copy of problem matrix coefficients. + CoinPackedMatrix *matrixByRow_; + + /// Pointer to dense vector of row lower bounds + double * rowlower_; + + /// Pointer to dense vector of row upper bounds + double * rowupper_; + + /// Pointer to dense vector of column lower bounds + double * collower_; + + /// Pointer to dense vector of column upper bounds + double * colupper_; + + /// Pointer to dense vector of row rhs + mutable double * rhs_; + + /** Pointer to dense vector of slack variable upper bounds for ranged + constraints (undefined for non-ranged constraints) + */ + mutable double *rowrange_; + + /// Pointer to dense vector of row senses + mutable char * rowsense_; + + /// Pointer to dense vector of objective coefficients + double * objective_[MAX_OBJECTIVES]; + + /// Number of objectives + int num_objectives_; + + /// Constant offset for objective value + double objectiveOffset_[MAX_OBJECTIVES]; + + /// Pointer to dense vector specifying if a variable is continuous + /// (0) or integer (1). + char * integerType_; + + /// Pointer to sets + CoinSet ** set_; + + /// Number of sets + int numberSets_; + + /// Current file name + char * fileName_; + + /// Value to use for infinity + double infinity_; + + /// Value to use for epsilon + double epsilon_; + + /// Number of monomials printed in a row + int numberAcross_; + + /// Number of decimals printed for coefficients + int decimals_; + + /// Objective function name + char *objName_[MAX_OBJECTIVES]; + + /** Row names (including objective function name) + and column names when stopHash() for the corresponding + section was last called or for initial names (deemed invalid) + read from a file.<BR> + section = 0 for row names, + section = 1 for column names. */ + char **previous_names_[2]; + + /// card_previous_names_[section] holds the number of entries in the vector + /// previous_names_[section]. + /// section = 0 for row names, + /// section = 1 for column names. + int card_previous_names_[2]; + + /// Row names (including objective function name) + /// and column names (linked to Hash tables). + /// section = 0 for row names, + /// section = 1 for column names. + char **names_[2]; + + typedef struct { + int index, next; + } CoinHashLink; + + /// Maximum number of entries in a hash table section. + /// section = 0 for row names, + /// section = 1 for column names. + int maxHash_[2]; + + /// Number of entries in a hash table section. + /// section = 0 for row names, + /// section = 1 for column names. + int numberHash_[2]; + + /// Hash tables with two sections. + /// section = 0 for row names (including objective function name), + /// section = 1 for column names. + mutable CoinHashLink *hash_[2]; + + /// Build the hash table for the given names. The parameter number is + /// the cardinality of parameter names. Remove duplicate names. + /// + /// section = 0 for row names, + /// section = 1 for column names. + void startHash(char const * const * const names, + const COINColumnIndex number, + int section); + + /// Delete hash storage. If section = 0, it also frees objName_. + /// section = 0 for row names, + /// section = 1 for column names. + void stopHash(int section); + + /// Return the index of the given name, return -1 if the name is not found. + /// Return getNumRows() for the objective function name. + /// section = 0 for row names (including objective function name), + /// section = 1 for column names. + COINColumnIndex findHash(const char *name, int section) const; + + /// Insert thisName in the hash table if not present yet; does nothing + /// if the name is already in. + /// section = 0 for row names, + /// section = 1 for column names. + void insertHash(const char *thisName, int section); + + /// Write a coefficient. + /// print_1 = 0 : do not print the value 1. + void out_coeff(FILE *fp, double v, int print_1) const; + + /// Locate the objective function. + /// Return 1 if found the keyword "Minimize" or one of its variants, + /// -1 if found keyword "Maximize" or one of its variants. + int find_obj(FILE *fp) const; + + /// Return an integer indicating if the keyword "subject to" or one + /// of its variants has been read. + /// Return 1 if buff is the keyword "s.t" or one of its variants. + /// Return 2 if buff is the keyword "subject" or one of its variants. + /// Return 0 otherwise. + int is_subject_to(const char *buff) const; + + /// Return 1 if the first character of buff is a number. + /// Return 0 otherwise. + int first_is_number(const char *buff) const; + + /// Return 1 if the first character of buff is '/' or '\'. + /// Return 0 otherwise. + int is_comment(const char *buff) const; + + /// Read the file fp until buff contains an end of line + void skip_comment(char *buff, FILE *fp) const; + + /// Put in buff the next string that is not part of a comment + void scan_next(char *buff, FILE *fp) const; + + /// Return 1 if buff is the keyword "free" or one of its variants. + /// Return 0 otherwise. + int is_free(const char *buff) const; + + /// Return 1 if buff is the keyword "inf" or one of its variants. + /// Return 0 otherwise. + int is_inf(const char *buff) const; + + /// Return an integer indicating the inequality sense read. + /// Return 0 if buff is '<='. + /// Return 1 if buff is '='. + /// Return 2 if buff is '>='. + /// Return -1 otherwise. + int is_sense(const char *buff) const; + + /// Return an integer indicating if one of the keywords "Bounds", "Integers", + /// "Generals", "Binaries", "Semi-continuous", "Sos", "End", or one + /// of their variants has been read. (note Semi-continuous not coded) + /// Return 1 if buff is the keyword "Bounds" or one of its variants. + /// Return 2 if buff is the keyword "Integers" or "Generals" or one of their + /// variants. + /// Return 3 if buff is the keyword "Binaries" or one of its variants. + /// Return 4 if buff is the keyword "Semi-continuous" or one of its variants. + /// Return 5 if buff is the keyword "Sos" or one of its variants. + /// Return 6 if buff is the keyword "End" or one of its variants. + /// Return 0 otherwise. + int is_keyword(const char *buff) const; + + /// Read a monomial of the objective function. + /// Return 1 if "subject to" or one of its variants has been read. + int read_monom_obj(FILE *fp, double *coeff, char **name, int *cnt, + char **obj_name, int *num_objectives, int *obj_starts); + + /// Read a monomial of a constraint. + /// Return a positive number if the sense of the inequality has been + /// read (see method is_sense() for the return code). + /// Return -1 otherwise. + int read_monom_row(FILE *fp, char *start_str, double *coeff, char **name, + int cnt_coeff) const; + + /// Reallocate vectors related to number of coefficients. + void realloc_coeff(double **coeff, char ***colNames, int *maxcoeff) const; + + /// Reallocate vectors related to rows. + void realloc_row(char ***rowNames, int **start, double **rhs, + double **rowlow, double **rowup, int *maxrow) const; + + /// Reallocate vectors related to columns. + void realloc_col(double **collow, double **colup, char **is_int, + int *maxcol) const; + + /// Read a constraint. + void read_row(FILE *fp, char *buff, double **pcoeff, char ***pcolNames, + int *cnt_coeff, int *maxcoeff, + double *rhs, double *rowlow, double *rowup, + int *cnt_row, double inf) const; + + /** Check that current objective name and all row names are distinct + including row names obtained by adding "_low" for ranged constraints. + If there is a conflict in the names, they are replaced by default + row names (see setDefaultRowNames()). + + This method must not be called before + setLpDataWithoutRowAndColNames() has been called, since access + to the indices of all the ranged constraints is required. + + This method must not be called before + setLpDataRowAndColNames() has been called, since access + to all the row names is required. + */ + void checkRowNames(); + + /** Check that current column names are distinct. + If not, they are replaced by default + column names (see setDefaultColNames()). + + This method must not be called before + setLpDataRowAndColNames() has been called, since access + to all the column names is required. + */ + void checkColNames(); + +}; + +void +CoinLpIOUnitTest(const std::string& lpDir); + + +#endif diff --git a/thirdparty/linux/include/coin/CoinMessage.hpp b/thirdparty/linux/include/coin/CoinMessage.hpp new file mode 100644 index 0000000..cfdcd49 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinMessage.hpp @@ -0,0 +1,96 @@ +/* $Id: CoinMessage.hpp 1691 2014-03-19 12:43:56Z 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). + +#ifndef CoinMessage_H +#define CoinMessage_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +#endif + +/*! \file + + This file contains the enum for the standard set of Coin messages and a + class definition whose sole purpose is to supply a constructor. The text + ot the messages is defined in CoinMessage.cpp, + + CoinMessageHandler.hpp contains the generic facilities for message + handling. +*/ + +#include "CoinMessageHandler.hpp" + +/*! \brief Symbolic names for the standard set of COIN messages */ + +enum COIN_Message +{ + COIN_MPS_LINE=0, + COIN_MPS_STATS, + COIN_MPS_ILLEGAL, + COIN_MPS_BADIMAGE, + COIN_MPS_DUPOBJ, + COIN_MPS_DUPROW, + COIN_MPS_NOMATCHROW, + COIN_MPS_NOMATCHCOL, + COIN_MPS_FILE, + COIN_MPS_BADFILE1, + COIN_MPS_BADFILE2, + COIN_MPS_EOF, + COIN_MPS_RETURNING, + COIN_MPS_CHANGED, + COIN_SOLVER_MPS, + COIN_PRESOLVE_COLINFEAS, + COIN_PRESOLVE_ROWINFEAS, + COIN_PRESOLVE_COLUMNBOUNDA, + COIN_PRESOLVE_COLUMNBOUNDB, + COIN_PRESOLVE_NONOPTIMAL, + COIN_PRESOLVE_STATS, + COIN_PRESOLVE_INFEAS, + COIN_PRESOLVE_UNBOUND, + COIN_PRESOLVE_INFEASUNBOUND, + COIN_PRESOLVE_INTEGERMODS, + COIN_PRESOLVE_POSTSOLVE, + COIN_PRESOLVE_NEEDS_CLEANING, + COIN_PRESOLVE_PASS, +# if PRESOLVE_DEBUG + COIN_PRESOLDBG_FIRSTCHECK, + COIN_PRESOLDBG_RCOSTACC, + COIN_PRESOLDBG_RCOSTSTAT, + COIN_PRESOLDBG_STATSB, + COIN_PRESOLDBG_DUALSTAT, +# endif + COIN_GENERAL_INFO, + COIN_GENERAL_INFO2, + COIN_GENERAL_WARNING, + COIN_DUMMY_END +}; + + +/*! \class CoinMessage + \brief The standard set of Coin messages + + This class provides convenient access to the standard set of Coin messages. + In a nutshell, it's a CoinMessages object with a constructor that + preloads the standard Coin messages. +*/ + +class CoinMessage : public CoinMessages { + +public: + + /**@name Constructors etc */ + //@{ + /*! \brief Constructor + + Build a CoinMessages object and load it with the standard set of + Coin messages. + */ + CoinMessage(Language language=us_en); + //@} + +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinMessageHandler.hpp b/thirdparty/linux/include/coin/CoinMessageHandler.hpp new file mode 100644 index 0000000..7922630 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinMessageHandler.hpp @@ -0,0 +1,666 @@ +/* $Id: CoinMessageHandler.hpp 1514 2011-12-10 23:35:23Z lou $ */ +// 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). + +#ifndef CoinMessageHandler_H +#define CoinMessageHandler_H + +#include "CoinUtilsConfig.h" +#include "CoinPragma.hpp" + +#include <iostream> +#include <cstdio> +#include <string> +#include <vector> + +/** \file CoinMessageHandler.hpp + \brief This is a first attempt at a message handler. + + The COIN Project is in favo(u)r of multi-language support. This implementation + of a message handler tries to make it as lightweight as possible in the sense + that only a subset of messages need to be defined --- the rest default to US + English. + + The default handler at present just prints to stdout or to a FILE pointer + + \todo + This needs to be worked over for correct operation with ISO character codes. +*/ + +/* + I (jjf) am strongly in favo(u)r of language support for an open + source project, but I have tried to make it as lightweight as + possible in the sense that only a subset of messages need to be + defined - the rest default to US English. There will be different + sets of messages for each component - so at present there is a + Clp component and a Coin component. + + Because messages are only used in a controlled environment and have no + impact on code and are tested by other tests I have included tests such + as language and derivation in other unit tests. +*/ +/* + Where there are derived classes I (jjf) have started message numbers at 1001. +*/ + + +/** \brief Class for one massaged message. + + A message consists of a text string with formatting codes (#message_), + an integer identifier (#externalNumber_) which also determines the severity + level (#severity_) of the message, and a detail (logging) level (#detail_). + + CoinOneMessage is just a container to hold this information. The + interpretation is set by CoinMessageHandler, which see. + */ + +class CoinOneMessage { + +public: + /**@name Constructors etc */ + //@{ + /** Default constructor. */ + CoinOneMessage(); + /** Normal constructor */ + CoinOneMessage(int externalNumber, char detail, + const char * message); + /** Destructor */ + ~CoinOneMessage(); + /** The copy constructor */ + CoinOneMessage(const CoinOneMessage&); + /** assignment operator. */ + CoinOneMessage& operator=(const CoinOneMessage&); + //@} + + /**@name Useful stuff */ + //@{ + /// Replace message text (<i>e.g.</i>, text in a different language) + void replaceMessage(const char * message); + //@} + + /**@name Get and set methods */ + //@{ + /** Get message ID number */ + inline int externalNumber() const + {return externalNumber_;} + /** \brief Set message ID number + + In the default CoinMessageHandler, this number is printed in the message + prefix and is used to determine the message severity level. + */ + inline void setExternalNumber(int number) + {externalNumber_=number;} + /// Severity + inline char severity() const + {return severity_;} + /// Set detail level + inline void setDetail(int level) + {detail_=static_cast<char> (level);} + /// Get detail level + inline int detail() const + {return detail_;} + /// Return the message text + inline char * message() const + {return message_;} + //@} + + /**@name member data */ + //@{ + /// number to print out (also determines severity) + int externalNumber_; + /// Will only print if detail matches + char detail_; + /// Severity + char severity_; + /// Messages (in correct language) (not all 400 may exist) + mutable char message_[400]; + //@} +}; + +/** \brief Class to hold and manipulate an array of massaged messages. + + Note that the message index used to reference a message in the array of + messages is completely distinct from the external ID number stored with the + message. +*/ + +class CoinMessages { + +public: + /** \brief Supported languages + + These are the languages that are supported. At present only + us_en is serious and the rest are for testing. + */ + enum Language { + us_en = 0, + uk_en, + it + }; + + /**@name Constructors etc */ + //@{ + /** Constructor with number of messages. */ + CoinMessages(int numberMessages=0); + /** Destructor */ + ~CoinMessages(); + /** The copy constructor */ + CoinMessages(const CoinMessages&); + /** assignment operator. */ + CoinMessages& operator=(const CoinMessages&); + //@} + + /**@name Useful stuff */ + //@{ + /*! \brief Installs a new message in the specified index position + + Any existing message is replaced, and a copy of the specified message is + installed. + */ + void addMessage(int messageNumber, const CoinOneMessage & message); + /*! \brief Replaces the text of the specified message + + Any existing text is deleted and the specified text is copied into the + specified message. + */ + void replaceMessage(int messageNumber, const char * message); + /** Language. Need to think about iso codes */ + inline Language language() const + {return language_;} + /** Set language */ + void setLanguage(Language newlanguage) + {language_ = newlanguage;} + /// Change detail level for one message + void setDetailMessage(int newLevel, int messageNumber); + /** \brief Change detail level for several messages + + messageNumbers is expected to contain the indices of the messages to be + changed. + If numberMessages >= 10000 or messageNumbers is NULL, the detail level + is changed on all messages. + */ + void setDetailMessages(int newLevel, int numberMessages, + int * messageNumbers); + /** Change detail level for all messages with low <= ID number < high */ + void setDetailMessages(int newLevel, int low, int high); + + /// Returns class + inline int getClass() const + { return class_;} + /// Moves to compact format + void toCompact(); + /// Moves from compact format + void fromCompact(); + //@} + + /**@name member data */ + //@{ + /// Number of messages + int numberMessages_; + /// Language + Language language_; + /// Source (null-terminated string, maximum 4 characters). + char source_[5]; + /// Class - see later on before CoinMessageHandler + int class_; + /** Length of fake CoinOneMessage array. + First you get numberMessages_ pointers which point to stuff + */ + int lengthMessages_; + /// Messages + CoinOneMessage ** message_; + //@} +}; + +// for convenience eol +enum CoinMessageMarker { + CoinMessageEol = 0, + CoinMessageNewline = 1 +}; + +/** Base class for message handling + + The default behavior is described here: messages are printed, and (if the + severity is sufficiently high) execution will be aborted. Inherit and + redefine the methods #print and #checkSeverity to augment the behaviour. + + Messages can be printed with or without a prefix; the prefix will consist + of a source string, the external ID number, and a letter code, + <i>e.g.</i>, Clp6024W. + A prefix makes the messages look less nimble but is very useful + for "grep" <i>etc</i>. + + <h3> Usage </h3> + + The general approach to using the COIN messaging facility is as follows: + <ul> + <li> Define your messages. For each message, you must supply an external + ID number, a log (detail) level, and a format string. Typically, you + define a convenience structure for this, something that's easy to + use to create an array of initialised message definitions at compile + time. + <li> Create a CoinMessages object, sized to accommodate the number of + messages you've defined. (Incremental growth will happen if + necessary as messages are loaded, but it's inefficient.) + <li> Load the messages into the CoinMessages object. Typically this + entails creating a CoinOneMessage object for each message and + passing it as a parameter to CoinMessages::addMessage(). You specify + the message's internal ID as the other parameter to addMessage. + <li> Create and use a CoinMessageHandler object to print messages. + </ul> + See, for example, CoinMessage.hpp and CoinMessage.cpp for an example of + the first three steps. `Format codes' below has a simple example of + printing a message. + + <h3> External ID numbers and severity </h3> + + CoinMessageHandler assumes the following relationship between the + external ID number of a message and the severity of the message: + \li <3000 are informational ('I') + \li <6000 warnings ('W') + \li <9000 non-fatal errors ('E') + \li >=9000 aborts the program (after printing the message) ('S') + + <h3> Log (detail) levels </h3> + + The default behaviour is that a message will print if its detail level + is less than or equal to the handler's log level. If all you want to + do is set a single log level for the handler, use #setLogLevel(int). + + If you want to get fancy, here's how it really works: There's an array, + #logLevels_, which you can manipulate with #setLogLevel(int,int). Each + entry logLevels_[i] specifies the log level for messages of class i (see + CoinMessages::class_). If logLevels_[0] is set to the magic number -1000 + you get the simple behaviour described above, whatever the class of the + messages. If logLevels_[0] is set to a valid log level (>= 0), then + logLevels_[i] really is the log level for messages of class i. + + <h3> Format codes </h3> + + CoinMessageHandler can print integers (normal, long, and long long), + doubles, characters, and strings. See the descriptions of the + various << operators. + + When processing a standard message with a format string, the formatting + codes specified in the format string will be passed to the sprintf + function, along with the argument. When generating a message with no + format string, each << operator uses a simple format code appropriate for + its argument. Consult the documentation for the standard printf facility + for further information on format codes. + + The special format code `%?' provides a hook to enable or disable + printing. For each `%?' code, there must be a corresponding call to + printing(bool). This provides a way to define optional parts in + messages, delineated by the code `%?' in the format string. Printing can + be suppressed for these optional parts, but any operands must still be + supplied. For example, given the message string + \verbatim + "A message with%? an optional integer %d and%? a double %g." + \endverbatim + installed in CoinMessages \c exampleMsgs with index 5, and + \c CoinMessageHandler \c hdl, the code + \code + hdl.message(5,exampleMsgs) ; + hdl.printing(true) << 42 ; + hdl.printing(true) << 53.5 << CoinMessageEol ; + \endcode + will print + \verbatim + A message with an optional integer 42 and a double 53.5. + \endverbatim + while + \code + hdl.message(5,exampleMsgs) ; + hdl.printing(false) << 42 ; + hdl.printing(true) << 53.5 << CoinMessageEol ; + \endcode + will print + \verbatim + A message with a double 53.5. + \endverbatim + + For additional examples of usage, see CoinMessageHandlerUnitTest in + CoinMessageHandlerTest.cpp. +*/ + +class CoinMessageHandler { + +friend bool CoinMessageHandlerUnitTest () ; + +public: + /**@name Virtual methods that the derived classes may provide */ + //@{ + /** Print message, return 0 normally. + */ + virtual int print() ; + /** Check message severity - if too bad then abort + */ + virtual void checkSeverity() ; + //@} + + /**@name Constructors etc */ + //@{ + /// Constructor + CoinMessageHandler(); + /// Constructor to put to file pointer (won't be closed) + CoinMessageHandler(FILE *fp); + /** Destructor */ + virtual ~CoinMessageHandler(); + /** The copy constructor */ + CoinMessageHandler(const CoinMessageHandler&); + /** Assignment operator. */ + CoinMessageHandler& operator=(const CoinMessageHandler&); + /// Clone + virtual CoinMessageHandler * clone() const; + //@} + /**@name Get and set methods */ + //@{ + /// Get detail level of a message. + inline int detail(int messageNumber, const CoinMessages &normalMessage) const + { return normalMessage.message_[messageNumber]->detail();} + /** Get current log (detail) level. */ + inline int logLevel() const + { return logLevel_;} + /** \brief Set current log (detail) level. + + If the log level is equal or greater than the detail level of a message, + the message will be printed. A rough convention for the amount of output + expected is + - 0 - none + - 1 - minimal + - 2 - normal low + - 3 - normal high + - 4 - verbose + + Please assign log levels to messages accordingly. Log levels of 8 and + above (8,16,32, <i>etc</i>.) are intended for selective debugging. + The logical AND of the log level specified in the message and the current + log level is used to determine if the message is printed. (In other words, + you're using individual bits to determine which messages are printed.) + */ + void setLogLevel(int value); + /** Get alternative log level. */ + inline int logLevel(int which) const + { return logLevels_[which];} + /*! \brief Set alternative log level value. + + Can be used to store alternative log level information within the handler. + */ + void setLogLevel(int which, int value); + + /// Set the number of significant digits for printing floating point numbers + void setPrecision(unsigned int new_precision); + /// Current number of significant digits for printing floating point numbers + inline int precision() { return (g_precision_) ; } + + /// Switch message prefix on or off. + void setPrefix(bool yesNo); + /// Current setting for printing message prefix. + bool prefix() const; + /*! \brief Values of double fields already processed. + + As the parameter for a double field is processed, the value is saved + and can be retrieved using this function. + */ + inline double doubleValue(int position) const + { return doubleValue_[position];} + /*! \brief Number of double fields already processed. + + Incremented each time a field of type double is processed. + */ + inline int numberDoubleFields() const + {return static_cast<int>(doubleValue_.size());} + /*! \brief Values of integer fields already processed. + + As the parameter for a integer field is processed, the value is saved + and can be retrieved using this function. + */ + inline int intValue(int position) const + { return longValue_[position];} + /*! \brief Number of integer fields already processed. + + Incremented each time a field of type integer is processed. + */ + inline int numberIntFields() const + {return static_cast<int>(longValue_.size());} + /*! \brief Values of char fields already processed. + + As the parameter for a char field is processed, the value is saved + and can be retrieved using this function. + */ + inline char charValue(int position) const + { return charValue_[position];} + /*! \brief Number of char fields already processed. + + Incremented each time a field of type char is processed. + */ + inline int numberCharFields() const + {return static_cast<int>(charValue_.size());} + /*! \brief Values of string fields already processed. + + As the parameter for a string field is processed, the value is saved + and can be retrieved using this function. + */ + inline std::string stringValue(int position) const + { return stringValue_[position];} + /*! \brief Number of string fields already processed. + + Incremented each time a field of type string is processed. + */ + inline int numberStringFields() const + {return static_cast<int>(stringValue_.size());} + + /// Current message + inline CoinOneMessage currentMessage() const + {return currentMessage_;} + /// Source of current message + inline std::string currentSource() const + {return source_;} + /// Output buffer + inline const char * messageBuffer() const + {return messageBuffer_;} + /// Highest message number (indicates any errors) + inline int highestNumber() const + {return highestNumber_;} + /// Get current file pointer + inline FILE * filePointer() const + { return fp_;} + /// Set new file pointer + inline void setFilePointer(FILE * fp) + { fp_ = fp;} + //@} + + /**@name Actions to create a message */ + //@{ + /*! \brief Start a message + + Look up the specified message. A prefix will be generated if enabled. + The message will be printed if the current log level is equal or greater + than the log level of the message. + */ + CoinMessageHandler &message(int messageNumber, + const CoinMessages &messages) ; + + /*! \brief Start or continue a message + + With detail = -1 (default), does nothing except return a reference to the + handler. (I.e., msghandler.message() << "foo" is precisely equivalent + to msghandler << "foo".) If \p msgDetail is >= 0, is will be used + as the detail level to determine whether the message should print + (assuming class 0). + + This can be used with any of the << operators. One use is to start + a message which will be constructed entirely from scratch. Another + use is continuation of a message after code that interrupts the usual + sequence of << operators. + */ + CoinMessageHandler & message(int detail = -1) ; + + /*! \brief Print a complete message + + Generate a standard prefix and append \c msg `as is'. This is intended as + a transition mechanism. The standard prefix is generated (if enabled), + and \c msg is appended. The message must be ended with a CoinMessageEol + marker. Attempts to add content with << will have no effect. + + The default value of \p detail will not change printing status. If + \p detail is >= 0, it will be used as the detail level to determine + whether the message should print (assuming class 0). + + */ + CoinMessageHandler &message(int externalNumber, const char *source, + const char *msg, + char severity, int detail = -1) ; + + /*! \brief Process an integer parameter value. + + The default format code is `%d'. + */ + CoinMessageHandler & operator<< (int intvalue); +#if COIN_BIG_INDEX==1 + /*! \brief Process a long integer parameter value. + + The default format code is `%ld'. + */ + CoinMessageHandler & operator<< (long longvalue); +#endif +#if COIN_BIG_INDEX==2 + /*! \brief Process a long long integer parameter value. + + The default format code is `%ld'. + */ + CoinMessageHandler & operator<< (long long longvalue); +#endif + /*! \brief Process a double parameter value. + + The default format code is `%d'. + */ + CoinMessageHandler & operator<< (double doublevalue); + /*! \brief Process a STL string parameter value. + + The default format code is `%g'. + */ + CoinMessageHandler & operator<< (const std::string& stringvalue); + /*! \brief Process a char parameter value. + + The default format code is `%s'. + */ + CoinMessageHandler & operator<< (char charvalue); + /*! \brief Process a C-style string parameter value. + + The default format code is `%c'. + */ + CoinMessageHandler & operator<< (const char *stringvalue); + /*! \brief Process a marker. + + The default format code is `%s'. + */ + CoinMessageHandler & operator<< (CoinMessageMarker); + /** Finish (and print) the message. + + Equivalent to using the CoinMessageEol marker. + */ + int finish(); + /*! \brief Enable or disable printing of an optional portion of a message. + + Optional portions of a message are delimited by `%?' markers, and + printing processes one %? marker. If \c onOff is true, the subsequent + portion of the message (to the next %? marker or the end of the format + string) will be printed. If \c onOff is false, printing is suppressed. + Parameters must still be supplied, whether printing is suppressed or not. + See the class documentation for an example. + */ + CoinMessageHandler & printing(bool onOff); + + //@} + + /** Log levels will be by type and will then use type + given in CoinMessage::class_ + + - 0 - Branch and bound code or similar + - 1 - Solver + - 2 - Stuff in Coin directory + - 3 - Cut generators + */ +#define COIN_NUM_LOG 4 +/// Maximum length of constructed message (characters) +#define COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE 1000 +protected: + /**@name Protected member data */ + //@{ + /// values in message + std::vector<double> doubleValue_; + std::vector<int> longValue_; + std::vector<char> charValue_; + std::vector<std::string> stringValue_; + /// Log level + int logLevel_; + /// Log levels + int logLevels_[COIN_NUM_LOG]; + /// Whether we want prefix (may get more subtle so is int) + int prefix_; + /// Current message + CoinOneMessage currentMessage_; + /// Internal number for use with enums + int internalNumber_; + /// Format string for message (remainder) + char * format_; + /// Output buffer + char messageBuffer_[COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE]; + /// Position in output buffer + char * messageOut_; + /// Current source of message + std::string source_; + /** 0 - Normal. + 1 - Put in values, move along format, but don't print. + 2 - A complete message was provided; nothing more to do but print + when CoinMessageEol is processed. Any << operators are treated + as noops. + 3 - do nothing except look for CoinMessageEol (i.e., the message + detail level was not sufficient to cause it to print). + */ + int printStatus_; + /// Highest message number (indicates any errors) + int highestNumber_; + /// File pointer + FILE * fp_; + /// Current format for floating point numbers + char g_format_[8]; + /// Current number of significant digits for floating point numbers + int g_precision_ ; + //@} + +private: + + /** The body of the copy constructor and the assignment operator */ + void gutsOfCopy(const CoinMessageHandler &rhs) ; + + /*! \brief Internal function to locate next format code. + + Intended for internal use. Side effects modify the format string. + */ + char *nextPerCent(char *start, const bool initial = false) ; + + /*! \brief Internal printing function. + + Makes it easier to split up print into clean, print and check severity + */ + int internalPrint() ; + + /// Decide if this message should print. + void calcPrintStatus(int msglvl, int msgclass) ; + + +}; + +//############################################################################# +/** A function that tests the methods in the CoinMessageHandler class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +bool +CoinMessageHandlerUnitTest(); + +#endif diff --git a/thirdparty/linux/include/coin/CoinModel.hpp b/thirdparty/linux/include/coin/CoinModel.hpp new file mode 100644 index 0000000..6d1ff5b --- /dev/null +++ b/thirdparty/linux/include/coin/CoinModel.hpp @@ -0,0 +1,1054 @@ +/* $Id: CoinModel.hpp 1691 2014-03-19 12:43:56Z forrest $ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinModel_H +#define CoinModel_H + +#include "CoinModelUseful.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinPackedMatrix.hpp" +#include "CoinFinite.hpp" +class CoinBaseModel { + +public: + + + /**@name Constructors, destructor */ + //@{ + /// Default Constructor + CoinBaseModel (); + + /// Copy constructor + CoinBaseModel ( const CoinBaseModel &rhs); + + /// Assignment operator + CoinBaseModel & operator=( const CoinBaseModel& rhs); + + /// Clone + virtual CoinBaseModel * clone() const=0; + + /// Destructor + virtual ~CoinBaseModel () ; + //@} + + /**@name For getting information */ + //@{ + /// Return number of rows + inline int numberRows() const + { return numberRows_;} + /// Return number of columns + inline int numberColumns() const + { return numberColumns_;} + /// Return number of elements + virtual CoinBigIndex numberElements() const = 0; + /** Returns the (constant) objective offset + This is the RHS entry for the objective row + */ + inline double objectiveOffset() const + { return objectiveOffset_;} + /// Set objective offset + inline void setObjectiveOffset(double value) + { objectiveOffset_=value;} + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const { + return optimizationDirection_; + } + /// Set direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline void setOptimizationDirection(double value) + { optimizationDirection_=value;} + /// Get print level 0 - off, 1 - errors, 2 - more + inline int logLevel() const + { return logLevel_;} + /// Set print level 0 - off, 1 - errors, 2 - more + void setLogLevel(int value); + /// Return the problem name + inline const char * getProblemName() const + { return problemName_.c_str();} + /// Set problem name + void setProblemName(const char *name) ; + /// Set problem name + void setProblemName(const std::string &name) ; + /// Return the row block name + inline const std::string & getRowBlock() const + { return rowBlockName_;} + /// Set row block name + inline void setRowBlock(const std::string &name) + { rowBlockName_ = name;} + /// Return the column block name + inline const std::string & getColumnBlock() const + { return columnBlockName_;} + /// Set column block name + inline void setColumnBlock(const std::string &name) + { columnBlockName_ = name;} + /// Pass in message handler + void setMessageHandler(CoinMessageHandler * handler); + //@} + +protected: + /**@name Data members */ + //@{ + /// Current number of rows + int numberRows_; + /// Current number of columns + int numberColumns_; + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + double optimizationDirection_; + /// Objective offset to be passed on + double objectiveOffset_; + /// Problem name + std::string problemName_; + /// Rowblock name + std::string rowBlockName_; + /// Columnblock name + std::string columnBlockName_; + /// Message handler (Passed in) + CoinMessageHandler * handler_; + /// Messages + CoinMessages messages_; + + /** Print level. + I could have gone for full message handling but this should normally + be silent and lightweight. + -1 - use passed in message handler + 0 - no output + 1 - on errors + 2 - more detailed + */ + int logLevel_; + //@} + /// data + +}; + +/** + This is a simple minded model which is stored in a format which makes + it easier to construct and modify but not efficient for algorithms. It has + to be passed across to ClpModel or OsiSolverInterface by addRows, addCol(umn)s + or loadProblem. + + It may have up to four parts - + 1) A matrix of doubles (or strings - see note A) + 2) Column information including integer information and names + 3) Row information including names + 4) Quadratic objective (not implemented - but see A) + + This class is meant to make it more efficient to build a model. It is at + its most efficient when all additions are done as addRow or as addCol but + not mixed. If only 1 and 2 exist then solver.addColumns may be used to pass to solver, + if only 1 and 3 exist then solver.addRows may be used. Otherwise solver.loadProblem + must be used. + + If addRows and addColumns are mixed or if individual elements are set then the + speed will drop to some extent and more memory will be used. + + It is also possible to iterate over existing elements and to access columns and rows + by name. Again each of these use memory and cpu time. However memory is unlikely + to be critical as most algorithms will use much more. + + Notes: + A) Although this could be used to pass nonlinear information around the + only use at present is to have named values e.g. value1 which can then be + set to a value after model is created. I have no idea whether that could + be useful but I thought it might be fun. + Quadratic terms are allowed in strings! A solver could try and use this + if so - the convention is that 0.5* quadratic is stored + + B) This class could be useful for modeling. +*/ + +class CoinModel : public CoinBaseModel { + +public: + /**@name Useful methods for building model */ + //@{ + /** add a row - numberInRow may be zero */ + void addRow(int numberInRow, const int * columns, + const double * elements, double rowLower=-COIN_DBL_MAX, + double rowUpper=COIN_DBL_MAX, const char * name=NULL); + /// add a column - numberInColumn may be zero */ + void addColumn(int numberInColumn, const int * rows, + const double * elements, + double columnLower=0.0, + double columnUpper=COIN_DBL_MAX, double objectiveValue=0.0, + const char * name=NULL, bool isInteger=false); + /// add a column - numberInColumn may be zero */ + inline void addCol(int numberInColumn, const int * rows, + const double * elements, + double columnLower=0.0, + double columnUpper=COIN_DBL_MAX, double objectiveValue=0.0, + const char * name=NULL, bool isInteger=false) + { addColumn(numberInColumn, rows, elements, columnLower, columnUpper, objectiveValue, + name,isInteger);} + /// Sets value for row i and column j + inline void operator() (int i,int j,double value) + { setElement(i,j,value);} + /// Sets value for row i and column j + void setElement(int i,int j,double value) ; + /** Gets sorted row - user must provide enough space + (easiest is allocate number of columns). + If column or element NULL then just returns number + Returns number of elements + */ + int getRow(int whichRow, int * column, double * element); + /** Gets sorted column - user must provide enough space + (easiest is allocate number of rows). + If row or element NULL then just returns number + Returns number of elements + */ + int getColumn(int whichColumn, int * column, double * element); + /// Sets quadratic value for column i and j + void setQuadraticElement(int i,int j,double value) ; + /// Sets value for row i and column j as string + inline void operator() (int i,int j,const char * value) + { setElement(i,j,value);} + /// Sets value for row i and column j as string + void setElement(int i,int j,const char * value) ; + /// Associates a string with a value. Returns string id (or -1 if does not exist) + int associateElement(const char * stringValue, double value); + /** Sets rowLower (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowLower(int whichRow,double rowLower); + /** Sets rowUpper (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowUpper(int whichRow,double rowUpper); + /** Sets rowLower and rowUpper (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowBounds(int whichRow,double rowLower,double rowUpper); + /** Sets name (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowName(int whichRow,const char * rowName); + /** Sets columnLower (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnLower(int whichColumn,double columnLower); + /** Sets columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnUpper(int whichColumn,double columnUpper); + /** Sets columnLower and columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnBounds(int whichColumn,double columnLower,double columnUpper); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnObjective(int whichColumn,double columnObjective); + /** Sets name (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnName(int whichColumn,const char * columnName); + /** Sets integer state (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnIsInteger(int whichColumn,bool columnIsInteger); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setObjective(int whichColumn,double columnObjective) + { setColumnObjective( whichColumn, columnObjective);} + /** Sets integer state (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setIsInteger(int whichColumn,bool columnIsInteger) + { setColumnIsInteger( whichColumn, columnIsInteger);} + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setInteger(int whichColumn) + { setColumnIsInteger( whichColumn, true);} + /** Sets continuous (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setContinuous(int whichColumn) + { setColumnIsInteger( whichColumn, false);} + /** Sets columnLower (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColLower(int whichColumn,double columnLower) + { setColumnLower( whichColumn, columnLower);} + /** Sets columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColUpper(int whichColumn,double columnUpper) + { setColumnUpper( whichColumn, columnUpper);} + /** Sets columnLower and columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColBounds(int whichColumn,double columnLower,double columnUpper) + { setColumnBounds( whichColumn, columnLower, columnUpper);} + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColObjective(int whichColumn,double columnObjective) + { setColumnObjective( whichColumn, columnObjective);} + /** Sets name (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColName(int whichColumn,const char * columnName) + { setColumnName( whichColumn, columnName);} + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColIsInteger(int whichColumn,bool columnIsInteger) + { setColumnIsInteger( whichColumn, columnIsInteger);} + /** Sets rowLower (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowLower(int whichRow,const char * rowLower); + /** Sets rowUpper (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowUpper(int whichRow,const char * rowUpper); + /** Sets columnLower (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnLower(int whichColumn,const char * columnLower); + /** Sets columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnUpper(int whichColumn,const char * columnUpper); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnObjective(int whichColumn,const char * columnObjective); + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnIsInteger(int whichColumn,const char * columnIsInteger); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setObjective(int whichColumn,const char * columnObjective) + { setColumnObjective( whichColumn, columnObjective);} + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setIsInteger(int whichColumn,const char * columnIsInteger) + { setColumnIsInteger( whichColumn, columnIsInteger);} + /** Deletes all entries in row and bounds. Will be ignored by + writeMps etc and will be packed down if asked for. */ + void deleteRow(int whichRow); + /** Deletes all entries in column and bounds and objective. Will be ignored by + writeMps etc and will be packed down if asked for. */ + void deleteColumn(int whichColumn); + /** Deletes all entries in column and bounds. If last column the number of columns + will be decremented and true returned. */ + inline void deleteCol(int whichColumn) + { deleteColumn(whichColumn);} + /// Takes element out of matrix - returning position (<0 if not there); + int deleteElement(int row, int column); + /// Takes element out of matrix when position known + void deleteThisElement(int row, int column,int position); + /** Packs down all rows i.e. removes empty rows permanently. Empty rows + have no elements and feasible bounds. returns number of rows deleted. */ + int packRows(); + /** Packs down all columns i.e. removes empty columns permanently. Empty columns + have no elements and no objective. returns number of columns deleted. */ + int packColumns(); + /** Packs down all columns i.e. removes empty columns permanently. Empty columns + have no elements and no objective. returns number of columns deleted. */ + inline int packCols() + { return packColumns();} + /** Packs down all rows and columns. i.e. removes empty rows and columns permanently. + Empty rows have no elements and feasible bounds. + Empty columns have no elements and no objective. + returns number of rows+columns deleted. */ + int pack(); + + /** Sets columnObjective array + */ + void setObjective(int numberColumns,const double * objective) ; + /** Sets columnLower array + */ + void setColumnLower(int numberColumns,const double * columnLower); + /** Sets columnLower array + */ + inline void setColLower(int numberColumns,const double * columnLower) + { setColumnLower( numberColumns, columnLower);} + /** Sets columnUpper array + */ + void setColumnUpper(int numberColumns,const double * columnUpper); + /** Sets columnUpper array + */ + inline void setColUpper(int numberColumns,const double * columnUpper) + { setColumnUpper( numberColumns, columnUpper);} + /** Sets rowLower array + */ + void setRowLower(int numberRows,const double * rowLower); + /** Sets rowUpper array + */ + void setRowUpper(int numberRows,const double * rowUpper); + + /** Write the problem in MPS format to a file with the given filename. + + \param compression can be set to three values to indicate what kind + of file should be written + <ul> + <li> 0: plain text (default) + <li> 1: gzip compressed (.gz is appended to \c filename) + <li> 2: bzip2 compressed (.bz2 is appended to \c filename) (TODO) + </ul> + If the library was not compiled with the requested compression then + writeMps falls back to writing a plain text file. + + \param formatType specifies the precision to used for values in the + MPS file + <ul> + <li> 0: normal precision (default) + <li> 1: extra accuracy + <li> 2: IEEE hex + </ul> + + \param numberAcross specifies whether 1 or 2 (default) values should be + specified on every data line in the MPS file. + + not const as may change model e.g. fill in default bounds + */ + int writeMps(const char *filename, int compression = 0, + int formatType = 0, int numberAcross = 2, bool keepStrings=false) ; + + /** Check two models against each other. Return nonzero if different. + Ignore names if that set. + May modify both models by cleaning up + */ + int differentModel(CoinModel & other, bool ignoreNames); + //@} + + + /**@name For structured models */ + //@{ + /// Pass in CoinPackedMatrix (and switch off element updates) + void passInMatrix(const CoinPackedMatrix & matrix); + /** Convert elements to CoinPackedMatrix (and switch off element updates). + Returns number of errors */ + int convertMatrix(); + /// Return a pointer to CoinPackedMatrix (or NULL) + inline const CoinPackedMatrix * packedMatrix() const + { return packedMatrix_;} + /// Return pointers to original rows (for decomposition) + inline const int * originalRows() const + { return rowType_;} + /// Return pointers to original columns (for decomposition) + inline const int * originalColumns() const + { return columnType_;} + //@} + + + /**@name For getting information */ + //@{ + /// Return number of elements + inline CoinBigIndex numberElements() const + { return numberElements_;} + /// Return elements as triples + inline const CoinModelTriple * elements() const + { return elements_;} + /// Returns value for row i and column j + inline double operator() (int i,int j) const + { return getElement(i,j);} + /// Returns value for row i and column j + double getElement(int i,int j) const; + /// Returns value for row rowName and column columnName + inline double operator() (const char * rowName,const char * columnName) const + { return getElement(rowName,columnName);} + /// Returns value for row rowName and column columnName + double getElement(const char * rowName,const char * columnName) const; + /// Returns quadratic value for columns i and j + double getQuadraticElement(int i,int j) const; + /** Returns value for row i and column j as string. + Returns NULL if does not exist. + Returns "Numeric" if not a string + */ + const char * getElementAsString(int i,int j) const; + /** Returns pointer to element for row i column j. + Only valid until next modification. + NULL if element does not exist */ + double * pointer (int i,int j) const; + /** Returns position in elements for row i column j. + Only valid until next modification. + -1 if element does not exist */ + int position (int i,int j) const; + + + /** Returns first element in given row - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink firstInRow(int whichRow) const ; + /** Returns last element in given row - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink lastInRow(int whichRow) const ; + /** Returns first element in given column - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink firstInColumn(int whichColumn) const ; + /** Returns last element in given column - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink lastInColumn(int whichColumn) const ; + /** Returns next element in current row or column - index is -1 if none. + Index is given by .index and value by .value. + User could also tell because input.next would be NULL + */ + CoinModelLink next(CoinModelLink & current) const ; + /** Returns previous element in current row or column - index is -1 if none. + Index is given by .index and value by .value. + User could also tell because input.previous would be NULL + May not be correct if matrix updated. + */ + CoinModelLink previous(CoinModelLink & current) const ; + /** Returns first element in given quadratic column - index is -1 if none. + Index is given by .index and value by .value + May not be correct if matrix updated. + */ + CoinModelLink firstInQuadraticColumn(int whichColumn) const ; + /** Returns last element in given quadratic column - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink lastInQuadraticColumn(int whichColumn) const ; + /** Gets rowLower (if row does not exist then -COIN_DBL_MAX) + */ + double getRowLower(int whichRow) const ; + /** Gets rowUpper (if row does not exist then +COIN_DBL_MAX) + */ + double getRowUpper(int whichRow) const ; + /** Gets name (if row does not exist then NULL) + */ + const char * getRowName(int whichRow) const ; + inline double rowLower(int whichRow) const + { return getRowLower(whichRow);} + /** Gets rowUpper (if row does not exist then COIN_DBL_MAX) + */ + inline double rowUpper(int whichRow) const + { return getRowUpper(whichRow) ;} + /** Gets name (if row does not exist then NULL) + */ + inline const char * rowName(int whichRow) const + { return getRowName(whichRow);} + /** Gets columnLower (if column does not exist then 0.0) + */ + double getColumnLower(int whichColumn) const ; + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + double getColumnUpper(int whichColumn) const ; + /** Gets columnObjective (if column does not exist then 0.0) + */ + double getColumnObjective(int whichColumn) const ; + /** Gets name (if column does not exist then NULL) + */ + const char * getColumnName(int whichColumn) const ; + /** Gets if integer (if column does not exist then false) + */ + bool getColumnIsInteger(int whichColumn) const ; + /** Gets columnLower (if column does not exist then 0.0) + */ + inline double columnLower(int whichColumn) const + { return getColumnLower(whichColumn);} + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + inline double columnUpper(int whichColumn) const + { return getColumnUpper(whichColumn) ;} + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline double columnObjective(int whichColumn) const + { return getColumnObjective(whichColumn);} + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline double objective(int whichColumn) const + { return getColumnObjective(whichColumn);} + /** Gets name (if column does not exist then NULL) + */ + inline const char * columnName(int whichColumn) const + { return getColumnName(whichColumn);} + /** Gets if integer (if column does not exist then false) + */ + inline bool columnIsInteger(int whichColumn) const + { return getColumnIsInteger(whichColumn);} + /** Gets if integer (if column does not exist then false) + */ + inline bool isInteger(int whichColumn) const + { return getColumnIsInteger(whichColumn);} + /** Gets columnLower (if column does not exist then 0.0) + */ + inline double getColLower(int whichColumn) const + { return getColumnLower(whichColumn);} + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + inline double getColUpper(int whichColumn) const + { return getColumnUpper(whichColumn) ;} + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline double getColObjective(int whichColumn) const + { return getColumnObjective(whichColumn);} + /** Gets name (if column does not exist then NULL) + */ + inline const char * getColName(int whichColumn) const + { return getColumnName(whichColumn);} + /** Gets if integer (if column does not exist then false) + */ + inline bool getColIsInteger(int whichColumn) const + { return getColumnIsInteger(whichColumn);} + /** Gets rowLower (if row does not exist then -COIN_DBL_MAX) + */ + const char * getRowLowerAsString(int whichRow) const ; + /** Gets rowUpper (if row does not exist then +COIN_DBL_MAX) + */ + const char * getRowUpperAsString(int whichRow) const ; + inline const char * rowLowerAsString(int whichRow) const + { return getRowLowerAsString(whichRow);} + /** Gets rowUpper (if row does not exist then COIN_DBL_MAX) + */ + inline const char * rowUpperAsString(int whichRow) const + { return getRowUpperAsString(whichRow) ;} + /** Gets columnLower (if column does not exist then 0.0) + */ + const char * getColumnLowerAsString(int whichColumn) const ; + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + const char * getColumnUpperAsString(int whichColumn) const ; + /** Gets columnObjective (if column does not exist then 0.0) + */ + const char * getColumnObjectiveAsString(int whichColumn) const ; + /** Gets if integer (if column does not exist then false) + */ + const char * getColumnIsIntegerAsString(int whichColumn) const ; + /** Gets columnLower (if column does not exist then 0.0) + */ + inline const char * columnLowerAsString(int whichColumn) const + { return getColumnLowerAsString(whichColumn);} + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + inline const char * columnUpperAsString(int whichColumn) const + { return getColumnUpperAsString(whichColumn) ;} + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline const char * columnObjectiveAsString(int whichColumn) const + { return getColumnObjectiveAsString(whichColumn);} + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline const char * objectiveAsString(int whichColumn) const + { return getColumnObjectiveAsString(whichColumn);} + /** Gets if integer (if column does not exist then false) + */ + inline const char * columnIsIntegerAsString(int whichColumn) const + { return getColumnIsIntegerAsString(whichColumn);} + /** Gets if integer (if column does not exist then false) + */ + inline const char * isIntegerAsString(int whichColumn) const + { return getColumnIsIntegerAsString(whichColumn);} + /// Row index from row name (-1 if no names or no match) + int row(const char * rowName) const; + /// Column index from column name (-1 if no names or no match) + int column(const char * columnName) const; + /// Returns type + inline int type() const + { return type_;} + /// returns unset value + inline double unsetValue() const + { return -1.23456787654321e-97;} + /// Creates a packed matrix - return number of errors + int createPackedMatrix(CoinPackedMatrix & matrix, + const double * associated); + /** Fills in startPositive and startNegative with counts for +-1 matrix. + If not +-1 then startPositive[0]==-1 otherwise counts and + startPositive[numberColumns]== size + - return number of errors + */ + int countPlusMinusOne(CoinBigIndex * startPositive, CoinBigIndex * startNegative, + const double * associated); + /** Creates +-1 matrix given startPositive and startNegative counts for +-1 matrix. + */ + void createPlusMinusOne(CoinBigIndex * startPositive, CoinBigIndex * startNegative, + int * indices, + const double * associated); + /// Creates copies of various arrays - return number of errors + int createArrays(double * & rowLower, double * & rowUpper, + double * & columnLower, double * & columnUpper, + double * & objective, int * & integerType, + double * & associated); + /// Says if strings exist + inline bool stringsExist() const + { return string_.numberItems()!=0;} + /// Return string array + inline const CoinModelHash * stringArray() const + { return &string_;} + /// Returns associated array + inline double * associatedArray() const + { return associated_;} + /// Return rowLower array + inline double * rowLowerArray() const + { return rowLower_;} + /// Return rowUpper array + inline double * rowUpperArray() const + { return rowUpper_;} + /// Return columnLower array + inline double * columnLowerArray() const + { return columnLower_;} + /// Return columnUpper array + inline double * columnUpperArray() const + { return columnUpper_;} + /// Return objective array + inline double * objectiveArray() const + { return objective_;} + /// Return integerType array + inline int * integerTypeArray() const + { return integerType_;} + /// Return row names array + inline const CoinModelHash * rowNames() const + { return &rowName_;} + /// Return column names array + inline const CoinModelHash * columnNames() const + { return &columnName_;} + /// Reset row names + inline void zapRowNames() + { rowName_=CoinModelHash();} + /// Reset column names + inline void zapColumnNames() + { columnName_=CoinModelHash();} + /// Returns array of 0 or nonzero if can be a cut (or returns NULL) + inline const int * cutMarker() const + { return cut_;} + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const { + return optimizationDirection_; + } + /// Set direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline void setOptimizationDirection(double value) + { optimizationDirection_=value;} + /// Return pointer to more information + inline void * moreInfo() const + { return moreInfo_;} + /// Set pointer to more information + inline void setMoreInfo(void * info) + { moreInfo_ = info;} + /** Returns which parts of model are set + 1 - matrix + 2 - rhs + 4 - row names + 8 - column bounds and/or objective + 16 - column names + 32 - integer types + */ + int whatIsSet() const; + //@} + + /**@name for block models - matrix will be CoinPackedMatrix */ + //@{ + /*! \brief Load in a problem by copying the arguments. The constraints on + the rows are given by lower and upper bounds. + + If a pointer is 0 then the following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + + Note that the default values for rowub and rowlb produce the + constraint -infty <= ax <= infty. This is probably not what you want. + */ + void loadBlock (const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub) ; + /*! \brief Load in a problem by copying the arguments. + The constraints on the rows are given by sense/rhs/range triplets. + + If a pointer is 0 then the following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>obj</code>: all variables have 0 objective coefficient + <li> <code>rowsen</code>: all rows are >= + <li> <code>rowrhs</code>: all right hand sides are 0 + <li> <code>rowrng</code>: 0 for the ranged rows + </ul> + + Note that the default values for rowsen, rowrhs, and rowrng produce the + constraint ax >= 0. + */ + void loadBlock (const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng) ; + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by lower and upper bounds. + + The matrix vectors must be gap-free. Note that <code>start</code> must + have <code>numcols+1</code> entries so that the length of the last column + can be calculated as <code>start[numcols]-start[numcols-1]</code>. + + See the previous loadBlock method using rowlb and rowub for default + argument values. + */ + void loadBlock (const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub) ; + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by sense/rhs/range triplets. + + The matrix vectors must be gap-free. Note that <code>start</code> must + have <code>numcols+1</code> entries so that the length of the last column + can be calculated as <code>start[numcols]-start[numcols-1]</code>. + + See the previous loadBlock method using sense/rhs/range for default + argument values. + */ + void loadBlock (const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng) ; + + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModel(); + /** Constructor with sizes. */ + CoinModel(int firstRows, int firstColumns, int firstElements,bool noNames=false); + /** Read a problem in MPS or GAMS format from the given filename. + */ + CoinModel(const char *fileName, int allowStrings=0); + /** Read a problem from AMPL nl file + NOTE - as I can't work out configure etc the source code is in Cbc_ampl.cpp! + */ + CoinModel( int nonLinear, const char * fileName,const void * info); + /// From arrays + CoinModel(int numberRows, int numberColumns, + const CoinPackedMatrix * matrix, + const double * rowLower, const double * rowUpper, + const double * columnLower, const double * columnUpper, + const double * objective); + /// Clone + virtual CoinBaseModel * clone() const; + + /** Destructor */ + virtual ~CoinModel(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModel(const CoinModel&); + /// = + CoinModel& operator=(const CoinModel&); + //@} + + /**@name For debug */ + //@{ + /// Checks that links are consistent + void validateLinks() const; + //@} +private: + /// Resize + void resize(int maximumRows, int maximumColumns, int maximumElements); + /// Fill in default row information + void fillRows(int which,bool forceCreation,bool fromAddRow=false); + /// Fill in default column information + void fillColumns(int which,bool forceCreation,bool fromAddColumn=false); + /** Fill in default linked list information (1= row, 2 = column) + Marked as const as list is mutable */ + void fillList(int which, CoinModelLinkedList & list,int type) const ; + /** Create a linked list and synchronize free + type 1 for row 2 for column + Marked as const as list is mutable */ + void createList(int type) const; + /// Adds one string, returns index + int addString(const char * string); + /** Gets a double from a string possibly containing named strings, + returns unset if not found + */ + double getDoubleFromString(CoinYacc & info, const char * string); + /// Frees value memory + void freeStringMemory(CoinYacc & info); +public: + /// Fills in all associated - returning number of errors + int computeAssociated(double * associated); + /** Gets correct form for a quadratic row - user to delete + If row is not quadratic then returns which other variables are involved + with tiny (1.0e-100) elements and count of total number of variables which could not + be put in quadratic form + */ + CoinPackedMatrix * quadraticRow(int rowNumber,double * linear, + int & numberBad) const; + /// Replaces a quadratic row + void replaceQuadraticRow(int rowNumber,const double * linear, const CoinPackedMatrix * quadraticPart); + /** If possible return a model where if all variables marked nonzero are fixed + the problem will be linear. At present may only work if quadratic. + Returns NULL if not possible + */ + CoinModel * reorder(const char * mark) const; + /** Expands out all possible combinations for a knapsack + If buildObj NULL then just computes space needed - returns number elements + On entry numberOutput is maximum allowed, on exit it is number needed or + -1 (as will be number elements) if maximum exceeded. numberOutput will have at + least space to return values which reconstruct input. + Rows returned will be original rows but no entries will be returned for + any rows all of whose entries are in knapsack. So up to user to allow for this. + If reConstruct >=0 then returns number of entrie which make up item "reConstruct" + in expanded knapsack. Values in buildRow and buildElement; + */ + int expandKnapsack(int knapsackRow, int & numberOutput,double * buildObj, CoinBigIndex * buildStart, + int * buildRow, double * buildElement,int reConstruct=-1) const; + /// Sets cut marker array + void setCutMarker(int size,const int * marker); + /// Sets priority array + void setPriorities(int size,const int * priorities); + /// priorities (given for all columns (-1 if not integer) + inline const int * priorities() const + { return priority_;} + /// For decomposition set original row and column indices + void setOriginalIndices(const int * row, const int * column); + +private: + /** Read a problem from AMPL nl file + so not constructor so gdb will work + */ + void gdb( int nonLinear, const char * fileName, const void * info); + /// returns jColumn (-2 if linear term, -1 if unknown) and coefficient + int decodeBit(char * phrase, char * & nextPhrase, double & coefficient, bool ifFirst) const; + /// Aborts with message about packedMatrix + void badType() const; + /**@name Data members */ + //@{ + /// Maximum number of rows + int maximumRows_; + /// Maximum number of columns + int maximumColumns_; + /// Current number of elements + int numberElements_; + /// Maximum number of elements + int maximumElements_; + /// Current number of quadratic elements + int numberQuadraticElements_; + /// Maximum number of quadratic elements + int maximumQuadraticElements_; + /// Row lower + double * rowLower_; + /// Row upper + double * rowUpper_; + /// Row names + CoinModelHash rowName_; + /** Row types. + Has information - at present + bit 0 - rowLower is a string + bit 1 - rowUpper is a string + NOTE - if converted to CoinPackedMatrix - may be indices of + original rows (i.e. when decomposed) + */ + int * rowType_; + /// Objective + double * objective_; + /// Column Lower + double * columnLower_; + /// Column Upper + double * columnUpper_; + /// Column names + CoinModelHash columnName_; + /// Integer information + int * integerType_; + /// Strings + CoinModelHash string_; + /** Column types. + Has information - at present + bit 0 - columnLower is a string + bit 1 - columnUpper is a string + bit 2 - objective is a string + bit 3 - integer setting is a string + NOTE - if converted to CoinPackedMatrix - may be indices of + original columns (i.e. when decomposed) + */ + int * columnType_; + /// If simple then start of each row/column + int * start_; + /// Actual elements + CoinModelTriple * elements_; + /// Actual elements as CoinPackedMatrix + CoinPackedMatrix * packedMatrix_; + /// Hash for elements + mutable CoinModelHash2 hashElements_; + /// Linked list for rows + mutable CoinModelLinkedList rowList_; + /// Linked list for columns + mutable CoinModelLinkedList columnList_; + /// Actual quadratic elements (always linked lists) + CoinModelTriple * quadraticElements_; + /// Hash for quadratic elements + mutable CoinModelHash2 hashQuadraticElements_; + /// Array for sorting indices + int * sortIndices_; + /// Array for sorting elements + double * sortElements_; + /// Size of sort arrays + int sortSize_; + /// Linked list for quadratic rows + mutable CoinModelLinkedList quadraticRowList_; + /// Linked list for quadratic columns + mutable CoinModelLinkedList quadraticColumnList_; + /// Size of associated values + int sizeAssociated_; + /// Associated values + double * associated_; + /// Number of SOS - all these are done in one go e.g. from ampl + int numberSOS_; + /// SOS starts + int * startSOS_; + /// SOS members + int * memberSOS_; + /// SOS type + int * typeSOS_; + /// SOS priority + int * prioritySOS_; + /// SOS reference + double * referenceSOS_; + /// priorities (given for all columns (-1 if not integer) + int * priority_; + /// Nonzero if row is cut - done in one go e.g. from ampl + int * cut_; + /// Pointer to more information + void * moreInfo_; + /** Type of build - + -1 unset, + 0 for row, + 1 for column, + 2 linked. + 3 matrix is CoinPackedMatrix (and at present can't be modified); + */ + mutable int type_; + /// True if no names EVER being used (for users who know what they are doing) + bool noNames_; + /** Links present (could be tested by sizes of objects) + 0 - none, + 1 - row links, + 2 - column links, + 3 - both + */ + mutable int links_; + //@} +}; +/// Just function of single variable x +double getFunctionValueFromString(const char * string, const char * x, double xValue); +/// faster version +double getDoubleFromString(CoinYacc & info, const char * string, const char * x, double xValue); +#endif diff --git a/thirdparty/linux/include/coin/CoinModelUseful.hpp b/thirdparty/linux/include/coin/CoinModelUseful.hpp new file mode 100644 index 0000000..f9eeea3 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinModelUseful.hpp @@ -0,0 +1,441 @@ +/* $Id: CoinModelUseful.hpp 1416 2011-04-17 09:57:29Z stefan $ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinModelUseful_H +#define CoinModelUseful_H + + +#include <cstdlib> +#include <cmath> +#include <cassert> +#include <cfloat> +#include <cstring> +#include <cstdio> +#include <iostream> + + +#include "CoinPragma.hpp" + +/** + This is for various structures/classes needed by CoinModel. + + CoinModelLink + CoinModelLinkedList + CoinModelHash +*/ +/// for going through row or column + +class CoinModelLink { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelLink(); + /** Destructor */ + ~CoinModelLink(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelLink(const CoinModelLink&); + /// = + CoinModelLink& operator=(const CoinModelLink&); + //@} + + /**@name Sets and gets method */ + //@{ + /// Get row + inline int row() const + { return row_;} + /// Get column + inline int column() const + { return column_;} + /// Get value + inline double value() const + { return value_;} + /// Get value + inline double element() const + { return value_;} + /// Get position + inline int position() const + { return position_;} + /// Get onRow + inline bool onRow() const + { return onRow_;} + /// Set row + inline void setRow(int row) + { row_=row;} + /// Set column + inline void setColumn(int column) + { column_=column;} + /// Set value + inline void setValue(double value) + { value_=value;} + /// Set value + inline void setElement(double value) + { value_=value;} + /// Set position + inline void setPosition(int position) + { position_=position;} + /// Set onRow + inline void setOnRow(bool onRow) + { onRow_=onRow;} + //@} + +private: + /**@name Data members */ + //@{ + /// Row + int row_; + /// Column + int column_; + /// Value as double + double value_; + /// Position in data + int position_; + /// If on row chain + bool onRow_; + //@} +}; + +/// for linked lists +// for specifying triple +typedef struct { + // top bit is nonzero if string + // rest is row + unsigned int row; + //CoinModelRowIndex row; + int column; + double value; // If string then index into strings +} CoinModelTriple; +inline int rowInTriple(const CoinModelTriple & triple) +{ return triple.row&0x7fffffff;} +inline void setRowInTriple(CoinModelTriple & triple,int iRow) +{ triple.row = iRow|(triple.row&0x80000000);} +inline bool stringInTriple(const CoinModelTriple & triple) +{ return (triple.row&0x80000000)!=0;} +inline void setStringInTriple(CoinModelTriple & triple,bool string) +{ triple.row = (string ? 0x80000000 : 0)|(triple.row&0x7fffffff);} +inline void setRowAndStringInTriple(CoinModelTriple & triple, + int iRow,bool string) +{ triple.row = (string ? 0x80000000 : 0)|iRow;} +/// for names and hashing +// for hashing +typedef struct { + int index, next; +} CoinModelHashLink; + +/* Function type. */ +typedef double (*func_t) (double); + +/// For string evaluation +/* Data type for links in the chain of symbols. */ +struct symrec +{ + char *name; /* name of symbol */ + int type; /* type of symbol: either VAR or FNCT */ + union + { + double var; /* value of a VAR */ + func_t fnctptr; /* value of a FNCT */ + } value; + struct symrec *next; /* link field */ +}; + +typedef struct symrec symrec; + +class CoinYacc { +private: + CoinYacc(const CoinYacc& rhs); + CoinYacc& operator=(const CoinYacc& rhs); + +public: + CoinYacc() : symtable(NULL), symbuf(NULL), length(0), unsetValue(0) {} + ~CoinYacc() + { + if (length) { + free(symbuf); + symbuf = NULL; + } + symrec* s = symtable; + while (s) { + free(s->name); + symtable = s; + s = s->next; + free(symtable); + } + } + +public: + symrec * symtable; + char * symbuf; + int length; + double unsetValue; +}; + +class CoinModelHash { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelHash(); + /** Destructor */ + ~CoinModelHash(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelHash(const CoinModelHash&); + /// = + CoinModelHash& operator=(const CoinModelHash&); + //@} + + /**@name sizing (just increases) */ + //@{ + /// Resize hash (also re-hashs) + void resize(int maxItems,bool forceReHash=false); + /// Number of items i.e. rows if just row names + inline int numberItems() const + { return numberItems_;} + /// Set number of items + void setNumberItems(int number); + /// Maximum number of items + inline int maximumItems() const + { return maximumItems_;} + /// Names + inline const char *const * names() const + { return names_;} + //@} + + /**@name hashing */ + //@{ + /// Returns index or -1 + int hash(const char * name) const; + /// Adds to hash + void addHash(int index, const char * name); + /// Deletes from hash + void deleteHash(int index); + /// Returns name at position (or NULL) + const char * name(int which) const; + /// Returns non const name at position (or NULL) + char * getName(int which) const; + /// Sets name at position (does not create) + void setName(int which,char * name ) ; + /// Validates + void validateHash() const; +private: + /// Returns a hash value + int hashValue(const char * name) const; +public: + //@} +private: + /**@name Data members */ + //@{ + /// Names + char ** names_; + /// hash + CoinModelHashLink * hash_; + /// Number of items + int numberItems_; + /// Maximum number of items + int maximumItems_; + /// Last slot looked at + int lastSlot_; + //@} +}; +/// For int,int hashing +class CoinModelHash2 { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelHash2(); + /** Destructor */ + ~CoinModelHash2(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelHash2(const CoinModelHash2&); + /// = + CoinModelHash2& operator=(const CoinModelHash2&); + //@} + + /**@name sizing (just increases) */ + //@{ + /// Resize hash (also re-hashs) + void resize(int maxItems, const CoinModelTriple * triples,bool forceReHash=false); + /// Number of items + inline int numberItems() const + { return numberItems_;} + /// Set number of items + void setNumberItems(int number); + /// Maximum number of items + inline int maximumItems() const + { return maximumItems_;} + //@} + + /**@name hashing */ + //@{ + /// Returns index or -1 + int hash(int row, int column, const CoinModelTriple * triples) const; + /// Adds to hash + void addHash(int index, int row, int column, const CoinModelTriple * triples); + /// Deletes from hash + void deleteHash(int index, int row, int column); +private: + /// Returns a hash value + int hashValue(int row, int column) const; +public: + //@} +private: + /**@name Data members */ + //@{ + /// hash + CoinModelHashLink * hash_; + /// Number of items + int numberItems_; + /// Maximum number of items + int maximumItems_; + /// Last slot looked at + int lastSlot_; + //@} +}; +class CoinModelLinkedList { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelLinkedList(); + /** Destructor */ + ~CoinModelLinkedList(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelLinkedList(const CoinModelLinkedList&); + /// = + CoinModelLinkedList& operator=(const CoinModelLinkedList&); + //@} + + /**@name sizing (just increases) */ + //@{ + /** Resize list - for row list maxMajor is maximum rows. + */ + void resize(int maxMajor,int maxElements); + /** Create list - for row list maxMajor is maximum rows. + type 0 row list, 1 column list + */ + void create(int maxMajor,int maxElements, + int numberMajor, int numberMinor, + int type, + int numberElements, const CoinModelTriple * triples); + /// Number of major items i.e. rows if just row links + inline int numberMajor() const + { return numberMajor_;} + /// Maximum number of major items i.e. rows if just row links + inline int maximumMajor() const + { return maximumMajor_;} + /// Number of elements + inline int numberElements() const + { return numberElements_;} + /// Maximum number of elements + inline int maximumElements() const + { return maximumElements_;} + /// First on free chain + inline int firstFree() const + { return first_[maximumMajor_];} + /// Last on free chain + inline int lastFree() const + { return last_[maximumMajor_];} + /// First on chain + inline int first(int which) const + { return first_[which];} + /// Last on chain + inline int last(int which) const + { return last_[which];} + /// Next array + inline const int * next() const + { return next_;} + /// Previous array + inline const int * previous() const + { return previous_;} + //@} + + /**@name does work */ + //@{ + /** Adds to list - easy case i.e. add row to row list + Returns where chain starts + */ + int addEasy(int majorIndex, int numberOfElements, const int * indices, + const double * elements, CoinModelTriple * triples, + CoinModelHash2 & hash); + /** Adds to list - hard case i.e. add row to column list + */ + void addHard(int minorIndex, int numberOfElements, const int * indices, + const double * elements, CoinModelTriple * triples, + CoinModelHash2 & hash); + /** Adds to list - hard case i.e. add row to column list + This is when elements have been added to other copy + */ + void addHard(int first, const CoinModelTriple * triples, + int firstFree, int lastFree,const int * nextOther); + /** Deletes from list - same case i.e. delete row from row list + */ + void deleteSame(int which, CoinModelTriple * triples, + CoinModelHash2 & hash, bool zapTriples); + /** Deletes from list - other case i.e. delete row from column list + This is when elements have been deleted from other copy + */ + void updateDeleted(int which, CoinModelTriple * triples, + CoinModelLinkedList & otherList); + /** Deletes one element from Row list + */ + void deleteRowOne(int position, CoinModelTriple * triples, + CoinModelHash2 & hash); + /** Update column list for one element when + one element deleted from row copy + */ + void updateDeletedOne(int position, const CoinModelTriple * triples); + /// Fills first,last with -1 + void fill(int first,int last); + /** Puts in free list from other list */ + void synchronize(CoinModelLinkedList & other); + /// Checks that links are consistent + void validateLinks(const CoinModelTriple * triples) const; + //@} +private: + /**@name Data members */ + //@{ + /// Previous - maximumElements long + int * previous_; + /// Next - maximumElements long + int * next_; + /// First - maximumMajor+1 long (last free element chain) + int * first_; + /// Last - maximumMajor+1 long (last free element chain) + int * last_; + /// Number of major items i.e. rows if just row links + int numberMajor_; + /// Maximum number of major items i.e. rows if just row links + int maximumMajor_; + /// Number of elements + int numberElements_; + /// Maximum number of elements + int maximumElements_; + /// 0 row list, 1 column list + int type_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinMpsIO.hpp b/thirdparty/linux/include/coin/CoinMpsIO.hpp new file mode 100644 index 0000000..8f0226a --- /dev/null +++ b/thirdparty/linux/include/coin/CoinMpsIO.hpp @@ -0,0 +1,1056 @@ +/* $Id: CoinMpsIO.hpp 1642 2013-10-16 00:43:14Z tkr $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinMpsIO_H +#define CoinMpsIO_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +#endif + +#include <vector> +#include <string> + +#include "CoinUtilsConfig.h" +#include "CoinPackedMatrix.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinFileIO.hpp" +class CoinModel; + +/// The following lengths are in decreasing order (for 64 bit etc) +/// Large enough to contain element index +/// This is already defined as CoinBigIndex +/// Large enough to contain column index +typedef int COINColumnIndex; + +/// Large enough to contain row index (or basis) +typedef int COINRowIndex; + +// We are allowing free format - but there is a limit! +// User can override by using CXXFLAGS += -DCOIN_MAX_FIELD_LENGTH=nnn +#ifndef COIN_MAX_FIELD_LENGTH +#define COIN_MAX_FIELD_LENGTH 160 +#endif +#define MAX_CARD_LENGTH 5*COIN_MAX_FIELD_LENGTH+80 + +enum COINSectionType { COIN_NO_SECTION, COIN_NAME_SECTION, COIN_ROW_SECTION, + COIN_COLUMN_SECTION, + COIN_RHS_SECTION, COIN_RANGES_SECTION, COIN_BOUNDS_SECTION, + COIN_ENDATA_SECTION, COIN_EOF_SECTION, COIN_QUADRATIC_SECTION, + COIN_CONIC_SECTION,COIN_QUAD_SECTION,COIN_SOS_SECTION, + COIN_BASIS_SECTION,COIN_UNKNOWN_SECTION +}; + +enum COINMpsType { COIN_N_ROW, COIN_E_ROW, COIN_L_ROW, COIN_G_ROW, + COIN_BLANK_COLUMN, COIN_S1_COLUMN, COIN_S2_COLUMN, COIN_S3_COLUMN, + COIN_INTORG, COIN_INTEND, COIN_SOSEND, COIN_UNSET_BOUND, + COIN_UP_BOUND, COIN_FX_BOUND, COIN_LO_BOUND, COIN_FR_BOUND, + COIN_MI_BOUND, COIN_PL_BOUND, COIN_BV_BOUND, + COIN_UI_BOUND, COIN_LI_BOUND, COIN_BOTH_BOUNDS_SET, + COIN_SC_BOUND, COIN_S1_BOUND, COIN_S2_BOUND, + COIN_BS_BASIS, COIN_XL_BASIS, COIN_XU_BASIS, + COIN_LL_BASIS, COIN_UL_BASIS, COIN_UNKNOWN_MPS_TYPE +}; +class CoinMpsIO; +/// Very simple code for reading MPS data +class CoinMpsCardReader { + +public: + + /**@name Constructor and destructor */ + //@{ + /// Constructor expects file to be open + /// This one takes gzFile if fp null + CoinMpsCardReader ( CoinFileInput *input, CoinMpsIO * reader ); + + /// Destructor + ~CoinMpsCardReader ( ); + //@} + + + /**@name card stuff */ + //@{ + /// Read to next section + COINSectionType readToNextSection ( ); + /// Gets next field and returns section type e.g. COIN_COLUMN_SECTION + COINSectionType nextField ( ); + /** Gets next field for .gms file and returns type. + -1 - EOF + 0 - what we expected (and processed so pointer moves past) + 1 - not what we expected + leading blanks always ignored + input types + 0 - anything - stops on non blank card + 1 - name (in columnname) + 2 - value + 3 - value name pair + 4 - equation type + 5 - ; + */ + int nextGmsField ( int expectedType ); + /// Returns current section type + inline COINSectionType whichSection ( ) const { + return section_; + } + /// Sets current section type + inline void setWhichSection(COINSectionType section ) { + section_=section; + } + /// Sees if free format. + inline bool freeFormat() const + { return freeFormat_;} + /// Sets whether free format. Mainly for blank RHS etc + inline void setFreeFormat(bool yesNo) + { freeFormat_=yesNo;} + /// Only for first field on card otherwise BLANK_COLUMN + /// e.g. COIN_E_ROW + inline COINMpsType mpsType ( ) const { + return mpsType_; + } + /// Reads and cleans card - taking out trailing blanks - return 1 if EOF + int cleanCard(); + /// Returns row name of current field + inline const char *rowName ( ) const { + return rowName_; + } + /// Returns column name of current field + inline const char *columnName ( ) const { + return columnName_; + } + /// Returns value in current field + inline double value ( ) const { + return value_; + } + /// Returns value as string in current field + inline const char *valueString ( ) const { + return valueString_; + } + /// Whole card (for printing) + inline const char *card ( ) const { + return card_; + } + /// Whole card - so we look at it (not const so nextBlankOr will work for gms reader) + inline char *mutableCard ( ) { + return card_; + } + /// set position (again so gms reader will work) + inline void setPosition(char * position) + { position_=position;} + /// get position (again so gms reader will work) + inline char * getPosition() const + { return position_;} + /// Returns card number + inline CoinBigIndex cardNumber ( ) const { + return cardNumber_; + } + /// Returns file input + inline CoinFileInput * fileInput ( ) const { + return input_; + } + /// Sets whether strings allowed + inline void setStringsAllowed() + { stringsAllowed_=true;} + //@} + +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + /// Current value + double value_; + /// Current card image + char card_[MAX_CARD_LENGTH]; + /// Current position within card image + char *position_; + /// End of card + char *eol_; + /// Current COINMpsType + COINMpsType mpsType_; + /// Current row name + char rowName_[COIN_MAX_FIELD_LENGTH]; + /// Current column name + char columnName_[COIN_MAX_FIELD_LENGTH]; + /// File input + CoinFileInput *input_; + /// Which section we think we are in + COINSectionType section_; + /// Card number + CoinBigIndex cardNumber_; + /// Whether free format. Just for blank RHS etc + bool freeFormat_; + /// Whether IEEE - 0 no, 1 INTEL, 2 not INTEL + int ieeeFormat_; + /// If all names <= 8 characters then allow embedded blanks + bool eightChar_; + /// MpsIO + CoinMpsIO * reader_; + /// Message handler + CoinMessageHandler * handler_; + /// Messages + CoinMessages messages_; + /// Current element as characters (only if strings allowed) + char valueString_[COIN_MAX_FIELD_LENGTH]; + /// Whether strings allowed + bool stringsAllowed_; + //@} +public: + /**@name methods */ + //@{ + /// type - 0 normal, 1 INTEL IEEE, 2 other IEEE + double osi_strtod(char * ptr, char ** output, int type); + /// remove blanks + static void strcpyAndCompress ( char *to, const char *from ); + /// + static char * nextBlankOr ( char *image ); + /// For strings + double osi_strtod(char * ptr, char ** output); + //@} + +}; + +//############################################################################# +#ifdef USE_SBB +class SbbObject; +class SbbModel; +#endif +/// Very simple class for containing data on set +class CoinSet { + +public: + + /**@name Constructor and destructor */ + //@{ + /// Default constructor + CoinSet ( ); + /// Constructor + CoinSet ( int numberEntries, const int * which); + + /// Copy constructor + CoinSet (const CoinSet &); + + /// Assignment operator + CoinSet & operator=(const CoinSet& rhs); + + /// Destructor + virtual ~CoinSet ( ); + //@} + + + /**@name gets */ + //@{ + /// Returns number of entries + inline int numberEntries ( ) const + { return numberEntries_; } + /// Returns type of set - 1 =SOS1, 2 =SOS2 + inline int setType ( ) const + { return setType_; } + /// Returns list of variables + inline const int * which ( ) const + { return which_; } + /// Returns weights + inline const double * weights ( ) const + { return weights_; } + //@} + +#ifdef USE_SBB + /**@name Use in sbb */ + //@{ + /// returns an object of type SbbObject + virtual SbbObject * sbbObject(SbbModel * model) const + { return NULL;} + //@} +#endif + +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + /// Number of entries + int numberEntries_; + /// type of set + int setType_; + /// Which variables are in set + int * which_; + /// Weights + double * weights_; + //@} +}; + +//############################################################################# +/// Very simple class for containing SOS set +class CoinSosSet : public CoinSet{ + +public: + + /**@name Constructor and destructor */ + //@{ + /// Constructor + CoinSosSet ( int numberEntries, const int * which, const double * weights, int type); + + /// Destructor + virtual ~CoinSosSet ( ); + //@} + + +#ifdef USE_SBB + /**@name Use in sbb */ + //@{ + /// returns an object of type SbbObject + virtual SbbObject * sbbObject(SbbModel * model) const ; + //@} +#endif + +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + //@} +}; + +//############################################################################# + +/** MPS IO Interface + + This class can be used to read in mps files without a solver. After + reading the file, the CoinMpsIO object contains all relevant data, which + may be more than a particular OsiSolverInterface allows for. Items may + be deleted to allow for flexibility of data storage. + + The implementation makes the CoinMpsIO object look very like a dummy solver, + as the same conventions are used. +*/ + +class CoinMpsIO { + friend void CoinMpsIOUnitTest(const std::string & mpsDir); + +public: + +/** @name Methods to retrieve problem information + + These methods return information about the problem held by the CoinMpsIO + object. + + Querying an object that has no data associated with it result in zeros for + the number of rows and columns, and NULL pointers from the methods that + return vectors. Const pointers returned from any data-query method are + always valid +*/ +//@{ + /// Get number of columns + int getNumCols() const; + + /// Get number of rows + int getNumRows() const; + + /// Get number of nonzero elements + int getNumElements() const; + + /// Get pointer to array[getNumCols()] of column lower bounds + const double * getColLower() const; + + /// Get pointer to array[getNumCols()] of column upper bounds + const double * getColUpper() const; + + /** Get pointer to array[getNumRows()] of constraint senses. + <ul> + <li>'L': <= constraint + <li>'E': = constraint + <li>'G': >= constraint + <li>'R': ranged constraint + <li>'N': free constraint + </ul> + */ + const char * getRowSense() const; + + /** Get pointer to array[getNumRows()] of constraint right-hand sides. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint right-hand side (rhs) is set as + <ul> + <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] + <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] + <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] + <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0 + </ul> + */ + const double * getRightHandSide() const; + + /** Get pointer to array[getNumRows()] of row ranges. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint range (rowrange) is set as + <ul> + <li> if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] + <li> if rowsense()[i] != 'R' then + rowrange()[i] is 0.0 + </ul> + Put another way, only range constraints have a nontrivial value for + rowrange. + */ + const double * getRowRange() const; + + /// Get pointer to array[getNumRows()] of row lower bounds + const double * getRowLower() const; + + /// Get pointer to array[getNumRows()] of row upper bounds + const double * getRowUpper() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + const double * getObjCoefficients() const; + + /// Get pointer to row-wise copy of the coefficient matrix + const CoinPackedMatrix * getMatrixByRow() const; + + /// Get pointer to column-wise copy of the coefficient matrix + const CoinPackedMatrix * getMatrixByCol() const; + + /// Return true if column is a continuous variable + bool isContinuous(int colNumber) const; + + /** Return true if a column is an integer variable + + Note: This function returns true if the the column + is a binary or general integer variable. + */ + bool isInteger(int columnNumber) const; + + /** Returns array[getNumCols()] specifying if a variable is integer. + + At present, simply coded as zero (continuous) and non-zero (integer) + May be extended at a later date. + */ + const char * integerColumns() const; + + /** Returns the row name for the specified index. + + Returns 0 if the index is out of range. + */ + const char * rowName(int index) const; + + /** Returns the column name for the specified index. + + Returns 0 if the index is out of range. + */ + const char * columnName(int index) const; + + /** Returns the index for the specified row name + + Returns -1 if the name is not found. + Returns numberRows for the objective row and > numberRows for + dropped free rows. + */ + int rowIndex(const char * name) const; + + /** Returns the index for the specified column name + + Returns -1 if the name is not found. + */ + int columnIndex(const char * name) const; + + /** Returns the (constant) objective offset + + This is the RHS entry for the objective row + */ + double objectiveOffset() const; + /// Set objective offset + inline void setObjectiveOffset(double value) + { objectiveOffset_=value;} + + /// Return the problem name + const char * getProblemName() const; + + /// Return the objective name + const char * getObjectiveName() const; + + /// Return the RHS vector name + const char * getRhsName() const; + + /// Return the range vector name + const char * getRangeName() const; + + /// Return the bound vector name + const char * getBoundName() const; + /// Number of string elements + inline int numberStringElements() const + { return numberStringElements_;} + /// String element + inline const char * stringElement(int i) const + { return stringElements_[i];} +//@} + + +/** @name Methods to set problem information + + Methods to load a problem into the CoinMpsIO object. +*/ +//@{ + + /// Set the problem data + void setMpsData(const CoinPackedMatrix& m, const double infinity, + const double* collb, const double* colub, + const double* obj, const char* integrality, + const double* rowlb, const double* rowub, + char const * const * const colnames, + char const * const * const rownames); + void setMpsData(const CoinPackedMatrix& m, const double infinity, + const double* collb, const double* colub, + const double* obj, const char* integrality, + const double* rowlb, const double* rowub, + const std::vector<std::string> & colnames, + const std::vector<std::string> & rownames); + void setMpsData(const CoinPackedMatrix& m, const double infinity, + const double* collb, const double* colub, + const double* obj, const char* integrality, + const char* rowsen, const double* rowrhs, + const double* rowrng, + char const * const * const colnames, + char const * const * const rownames); + void setMpsData(const CoinPackedMatrix& m, const double infinity, + const double* collb, const double* colub, + const double* obj, const char* integrality, + const char* rowsen, const double* rowrhs, + const double* rowrng, + const std::vector<std::string> & colnames, + const std::vector<std::string> & rownames); + + /** Pass in an array[getNumCols()] specifying if a variable is integer. + + At present, simply coded as zero (continuous) and non-zero (integer) + May be extended at a later date. + */ + void copyInIntegerInformation(const char * integerInformation); + + /// Set problem name + void setProblemName(const char *name) ; + + /// Set objective name + void setObjectiveName(const char *name) ; + +//@} + +/** @name Parameter set/get methods + + Methods to set and retrieve MPS IO parameters. +*/ + +//@{ + /// Set infinity + void setInfinity(double value); + + /// Get infinity + double getInfinity() const; + + /// Set default upper bound for integer variables + void setDefaultBound(int value); + + /// Get default upper bound for integer variables + int getDefaultBound() const; + /// Whether to allow string elements + inline int allowStringElements() const + { return allowStringElements_;} + /// Whether to allow string elements (0 no, 1 yes, 2 yes and try flip) + inline void setAllowStringElements(int yesNo) + { allowStringElements_ = yesNo;} + /** Small element value - elements less than this set to zero on input + default is 1.0e-14 */ + inline double getSmallElementValue() const + { return smallElement_;} + inline void setSmallElementValue(double value) + { smallElement_=value;} +//@} + + +/** @name Methods for problem input and output + + Methods to read and write MPS format problem files. + + The read and write methods return the number of errors that occurred during + the IO operation, or -1 if no file is opened. + + \note + If the CoinMpsIO class was compiled with support for libz then + readMps will automatically try to append .gz to the file name and open it as + a compressed file if the specified file name cannot be opened. + (Automatic append of the .bz2 suffix when libbz is used is on the TODO list.) + + \todo + Allow for file pointers and positioning +*/ + +//@{ + /// Set the current file name for the CoinMpsIO object + void setFileName(const char * name); + + /// Get the current file name for the CoinMpsIO object + const char * getFileName() const; + + /** Read a problem in MPS format from the given filename. + + Use "stdin" or "-" to read from stdin. + */ + int readMps(const char *filename, const char *extension = "mps"); + + /** Read a problem in MPS format from the given filename. + + Use "stdin" or "-" to read from stdin. + But do sets as well + */ + int readMps(const char *filename, const char *extension , + int & numberSets, CoinSet **& sets); + + /** Read a problem in MPS format from a previously opened file + + More precisely, read a problem using a CoinMpsCardReader object already + associated with this CoinMpsIO object. + + \todo + Provide an interface that will allow a client to associate a + CoinMpsCardReader object with a CoinMpsIO object by setting the + cardReader_ field. + */ + int readMps(); + /// and + int readMps(int & numberSets, CoinSet **& sets); + /** Read a basis in MPS format from the given filename. + If VALUES on NAME card and solution not NULL fills in solution + status values as for CoinWarmStartBasis (but one per char) + -1 file error, 0 normal, 1 has solution values + + Use "stdin" or "-" to read from stdin. + + If sizes of names incorrect - read without names + */ + int readBasis(const char *filename, const char *extension , + double * solution, unsigned char *rowStatus, unsigned char *columnStatus, + const std::vector<std::string> & colnames,int numberColumns, + const std::vector<std::string> & rownames, int numberRows); + + /** Read a problem in GAMS format from the given filename. + + Use "stdin" or "-" to read from stdin. + if convertObjective then massages objective column + */ + int readGms(const char *filename, const char *extension = "gms",bool convertObjective=false); + + /** Read a problem in GAMS format from the given filename. + + Use "stdin" or "-" to read from stdin. + But do sets as well + */ + int readGms(const char *filename, const char *extension , + int & numberSets, CoinSet **& sets); + + /** Read a problem in GAMS format from a previously opened file + + More precisely, read a problem using a CoinMpsCardReader object already + associated with this CoinMpsIO object. + + */ + // Not for now int readGms(); + /// and + int readGms(int & numberSets, CoinSet **& sets); + /** Read a problem in GMPL (subset of AMPL) format from the given filenames. + */ + int readGMPL(const char *modelName, const char * dataName=NULL, bool keepNames=false); + + /** Write the problem in MPS format to a file with the given filename. + + \param compression can be set to three values to indicate what kind + of file should be written + <ul> + <li> 0: plain text (default) + <li> 1: gzip compressed (.gz is appended to \c filename) + <li> 2: bzip2 compressed (.bz2 is appended to \c filename) (TODO) + </ul> + If the library was not compiled with the requested compression then + writeMps falls back to writing a plain text file. + + \param formatType specifies the precision to used for values in the + MPS file + <ul> + <li> 0: normal precision (default) + <li> 1: extra accuracy + <li> 2: IEEE hex + </ul> + + \param numberAcross specifies whether 1 or 2 (default) values should be + specified on every data line in the MPS file. + + \param quadratic specifies quadratic objective to be output + */ + int writeMps(const char *filename, int compression = 0, + int formatType = 0, int numberAcross = 2, + CoinPackedMatrix * quadratic = NULL, + int numberSOS=0,const CoinSet * setInfo=NULL) const; + + /// Return card reader object so can see what last card was e.g. QUADOBJ + inline const CoinMpsCardReader * reader() const + { return cardReader_;} + + /** Read in a quadratic objective from the given filename. + + If filename is NULL (or the same as the currently open file) then + reading continues from the current file. + If not, the file is closed and the specified file is opened. + + Code should be added to + general MPS reader to read this if QSECTION + Data is assumed to be Q and objective is c + 1/2 xT Q x + No assumption is made for symmetry, positive definite, etc. + No check is made for duplicates or non-triangular if checkSymmetry==0. + If 1 checks lower triangular (so off diagonal should be 2*Q) + if 2 makes lower triangular and assumes full Q (but adds off diagonals) + + Arrays should be deleted by delete [] + + Returns number of errors: + <ul> + <li> -1: bad file + <li> -2: no Quadratic section + <li> -3: an empty section + <li> +n: then matching errors etc (symmetry forced) + <li> -4: no matching errors but fails triangular test + (triangularity forced) + </ul> + columnStart is numberColumns+1 long, others numberNonZeros + */ + int readQuadraticMps(const char * filename, + int * &columnStart, int * &column, double * &elements, + int checkSymmetry); + + /** Read in a list of cones from the given filename. + + If filename is NULL (or the same as the currently open file) then + reading continues from the current file. + If not, the file is closed and the specified file is opened. + + Code should be added to + general MPS reader to read this if CSECTION + No checking is done that in unique cone + + Arrays should be deleted by delete [] + + Returns number of errors, -1 bad file, -2 no conic section, + -3 empty section + + columnStart is numberCones+1 long, other number of columns in matrix + + coneType is 1 for QUAD, 2 for RQUAD (numberCones long) +*/ + int readConicMps(const char * filename, + int * &columnStart, int * &column, int * &coneType, int & numberCones); + /// Set whether to move objective from matrix + inline void setConvertObjective(bool trueFalse) + { convertObjective_=trueFalse;} + /// copies in strings from a CoinModel - returns number + int copyStringElements(const CoinModel * model); + //@} + +/** @name Constructors and destructors */ +//@{ + /// Default Constructor + CoinMpsIO(); + + /// Copy constructor + CoinMpsIO (const CoinMpsIO &); + + /// Assignment operator + CoinMpsIO & operator=(const CoinMpsIO& rhs); + + /// Destructor + ~CoinMpsIO (); +//@} + + +/**@name Message handling */ +//@{ + /** Pass in Message handler + + Supply a custom message handler. It will not be destroyed when the + CoinMpsIO object is destroyed. + */ + void passInMessageHandler(CoinMessageHandler * handler); + + /// Set the language for messages. + void newLanguage(CoinMessages::Language language); + + /// Set the language for messages. + inline void setLanguage(CoinMessages::Language language) {newLanguage(language);} + + /// Return the message handler + inline CoinMessageHandler * messageHandler() const {return handler_;} + + /// Return the messages + inline CoinMessages messages() {return messages_;} + /// Return the messages pointer + inline CoinMessages * messagesPointer() {return & messages_;} +//@} + + +/**@name Methods to release storage + + These methods allow the client to reduce the storage used by the CoinMpsIO + object be selectively releasing unneeded problem information. +*/ +//@{ + /** Release all information which can be re-calculated. + + E.g., row sense, copies of rows, hash tables for names. + */ + void releaseRedundantInformation(); + + /// Release all row information (lower, upper) + void releaseRowInformation(); + + /// Release all column information (lower, upper, objective) + void releaseColumnInformation(); + + /// Release integer information + void releaseIntegerInformation(); + + /// Release row names + void releaseRowNames(); + + /// Release column names + void releaseColumnNames(); + + /// Release matrix information + void releaseMatrixInformation(); + //@} + +protected: + +/**@name Miscellaneous helper functions */ + //@{ + + /// Utility method used several times to implement public methods + void + setMpsDataWithoutRowAndColNames( + const CoinPackedMatrix& m, const double infinity, + const double* collb, const double* colub, + const double* obj, const char* integrality, + const double* rowlb, const double* rowub); + void + setMpsDataColAndRowNames( + const std::vector<std::string> & colnames, + const std::vector<std::string> & rownames); + void + setMpsDataColAndRowNames( + char const * const * const colnames, + char const * const * const rownames); + + + /// Does the heavy lifting for destruct and assignment. + void gutsOfDestructor(); + + /// Does the heavy lifting for copy and assignment. + void gutsOfCopy(const CoinMpsIO &); + + /// Clears problem data from the CoinMpsIO object. + void freeAll(); + + + /** A quick inlined function to convert from lb/ub style constraint + definition to sense/rhs/range style */ + inline void + convertBoundToSense(const double lower, const double upper, + char& sense, double& right, double& range) const; + /** A quick inlined function to convert from sense/rhs/range stryle + constraint definition to lb/ub style */ + inline void + convertSenseToBound(const char sense, const double right, + const double range, + double& lower, double& upper) const; + + /** Deal with a filename + + As the name says. + Returns +1 if the file name is new, 0 if it's the same as before + (i.e., matches fileName_), and -1 if there's an error and the file + can't be opened. + Handles automatic append of .gz suffix when compiled with libz. + + \todo + Add automatic append of .bz2 suffix when compiled with libbz. + */ + + int dealWithFileName(const char * filename, const char * extension, + CoinFileInput * &input); + /** Add string to list + iRow==numberRows is objective, nr+1 is lo, nr+2 is up + iColumn==nc is rhs (can't cope with ranges at present) + */ + void addString(int iRow,int iColumn, const char * value); + /// Decode string + void decodeString(int iString, int & iRow, int & iColumn, const char * & value) const; + //@} + + + // for hashing + typedef struct { + int index, next; + } CoinHashLink; + + /**@name Hash table methods */ + //@{ + /// Creates hash list for names (section = 0 for rows, 1 columns) + void startHash ( char **names, const int number , int section ); + /// This one does it when names are already in + void startHash ( int section ) const; + /// Deletes hash storage + void stopHash ( int section ); + /// Finds match using hash, -1 not found + int findHash ( const char *name , int section ) const; + //@} + + /**@name Cached problem information */ + //@{ + /// Problem name + char * problemName_; + + /// Objective row name + char * objectiveName_; + + /// Right-hand side vector name + char * rhsName_; + + /// Range vector name + char * rangeName_; + + /// Bounds vector name + char * boundName_; + + /// Number of rows + int numberRows_; + + /// Number of columns + int numberColumns_; + + /// Number of coefficients + CoinBigIndex numberElements_; + + /// Pointer to dense vector of row sense indicators + mutable char *rowsense_; + + /// Pointer to dense vector of row right-hand side values + mutable double *rhs_; + + /** Pointer to dense vector of slack variable upper bounds for range + constraints (undefined for non-range rows) + */ + mutable double *rowrange_; + + /// Pointer to row-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByRow_; + + /// Pointer to column-wise copy of problem matrix coefficients. + CoinPackedMatrix *matrixByColumn_; + + /// Pointer to dense vector of row lower bounds + double * rowlower_; + + /// Pointer to dense vector of row upper bounds + double * rowupper_; + + /// Pointer to dense vector of column lower bounds + double * collower_; + + /// Pointer to dense vector of column upper bounds + double * colupper_; + + /// Pointer to dense vector of objective coefficients + double * objective_; + + /// Constant offset for objective value (i.e., RHS value for OBJ row) + double objectiveOffset_; + + + /** Pointer to dense vector specifying if a variable is continuous + (0) or integer (1). + */ + char * integerType_; + + /** Row and column names + Linked to hash table sections (0 - row names, 1 column names) + */ + char **names_[2]; + //@} + + /** @name Hash tables */ + //@{ + /// Current file name + char * fileName_; + + /// Number of entries in a hash table section + int numberHash_[2]; + + /// Hash tables (two sections, 0 - row names, 1 - column names) + mutable CoinHashLink *hash_[2]; + //@} + + /** @name CoinMpsIO object parameters */ + //@{ + /// Upper bound when no bounds for integers + int defaultBound_; + + /// Value to use for infinity + double infinity_; + /// Small element value + double smallElement_; + + /// Message handler + CoinMessageHandler * handler_; + /** Flag to say if the message handler is the default handler. + + If true, the handler will be destroyed when the CoinMpsIO + object is destroyed; if false, it will not be destroyed. + */ + bool defaultHandler_; + /// Messages + CoinMessages messages_; + /// Card reader + CoinMpsCardReader * cardReader_; + /// If .gms file should it be massaged to move objective + bool convertObjective_; + /// Whether to allow string elements + int allowStringElements_; + /// Maximum number of string elements + int maximumStringElements_; + /// Number of string elements + int numberStringElements_; + /// String elements + char ** stringElements_; + //@} + +}; + +//############################################################################# +/** A function that tests the methods in the CoinMpsIO class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. Also, if this method is compiled with + optimization, the compilation takes 10-15 minutes and the machine pages + (has 256M core memory!)... */ +void +CoinMpsIOUnitTest(const std::string & mpsDir); +// Function to return number in most efficient way +// section is 0 for columns, 1 for rhs,ranges and 2 for bounds +/* formatType is + 0 - normal and 8 character names + 1 - extra accuracy + 2 - IEEE hex - INTEL + 3 - IEEE hex - not INTEL +*/ +void +CoinConvertDouble(int section, int formatType, double value, char outputValue[24]); + +#endif + diff --git a/thirdparty/linux/include/coin/CoinOslFactorization.hpp b/thirdparty/linux/include/coin/CoinOslFactorization.hpp new file mode 100644 index 0000000..0b51b01 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinOslFactorization.hpp @@ -0,0 +1,280 @@ +/* $Id: CoinOslFactorization.hpp 1416 2011-04-17 09:57:29Z stefan $ */ +// Copyright (C) 1987, 2009, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/* + Authors + + John Forrest + + */ +#ifndef CoinOslFactorization_H +#define CoinOslFactorization_H +#include <iostream> +#include <string> +#include <cassert> +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinDenseFactorization.hpp" +class CoinPackedMatrix; +/** This deals with Factorization and Updates + This is ripped off from OSL!!!!!!!!! + + I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex + may be redefined to get 64 bits. + */ + +typedef struct {int suc, pre;} EKKHlink; +typedef struct _EKKfactinfo { + double drtpiv; + double demark; + double zpivlu; + double zeroTolerance; + double areaFactor; + int *xrsadr; + int *xcsadr; + int *xrnadr; + int *xcnadr; + int *krpadr; + int *kcpadr; + int *mpermu; + int *bitArray; + int * back; + char * nonzero; + double * trueStart; + mutable double *kadrpm; + int *R_etas_index; + int *R_etas_start; + double *R_etas_element; + + int *xecadr; + int *xeradr; + double *xeeadr; + double *xe2adr; + EKKHlink * kp1adr; + EKKHlink * kp2adr; + double * kw1adr; + double * kw2adr; + double * kw3adr; + int * hpivcoR; + int nrow; + int nrowmx; + int firstDoRow; + int firstLRow; + int maxinv; + int nnetas; + int iterin; + int iter0; + int invok; + int nbfinv; + int num_resets; + int nnentl; + int nnentu; +#ifdef CLP_REUSE_ETAS + int save_nnentu; +#endif + int ndenuc; + int npivots; /* use as xpivsq in factorization */ + int kmxeta; + int xnetal; + int first_dense; + int last_dense; + int iterno; + int numberSlacks; + int lastSlack; + int firstNonSlack; + int xnetalval; + int lstart; + int if_sparse_update; + mutable int packedMode; + int switch_off_sparse_update; + int nuspike; + bool rows_ok; /* replaces test using mrstrt[1] */ +#ifdef CLP_REUSE_ETAS + mutable int reintro; +#endif + int nR_etas; + int sortedEta; /* if vector for F-T is sorted */ + int lastEtaCount; + int ifvsol; + int eta_size; + int last_eta_size; + int maxNNetas; +} EKKfactinfo; + +class CoinOslFactorization : public CoinOtherFactorization { + friend void CoinOslFactorizationUnitTest( const std::string & mpsDir ); + +public: + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinOslFactorization ( ); + /// Copy constructor + CoinOslFactorization ( const CoinOslFactorization &other); + + /// Destructor + virtual ~CoinOslFactorization ( ); + /// = copy + CoinOslFactorization & operator = ( const CoinOslFactorization & other ); + /// Clone + virtual CoinOtherFactorization * clone() const ; + //@} + + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas ( int numberRows, + int numberColumns, + CoinBigIndex maximumL, + CoinBigIndex maximumU ); + + /// PreProcesses column ordered copy of basis + virtual void preProcess ( ); + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor ( ); + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int * sequence, int * pivotVariable); + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int * sequence, int numberColumns); + /** When part of LP - given by basic variables. + Actually does factorization. + Arrays passed in have non negative value to say basic. + If status is okay, basic variables have pivot row - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ + int factorize ( const CoinPackedMatrix & matrix, + int rowIsBasic[], int columnIsBasic[] , + double areaFactor = 0.0 ); + //@} + + /**@name general stuff such as number of elements */ + //@{ + /// Total number of elements in factorization + virtual inline int numberElements ( ) const { + return numberRows_*(numberColumns_+numberPivots_); + } + /// Returns array to put basis elements in + virtual CoinFactorizationDouble * elements() const; + /// Returns pivot row + virtual int * pivotRow() const; + /// Returns work area + virtual CoinFactorizationDouble * workArea() const; + /// Returns int work area + virtual int * intWorkArea() const; + /// Number of entries in each row + virtual int * numberInRow() const; + /// Number of entries in each column + virtual int * numberInColumn() const; + /// Returns array to put basis starts in + virtual CoinBigIndex * starts() const; + /// Returns permute back + virtual int * permuteBack() const; + /// Returns true if wants tableauColumn in replaceColumn + virtual bool wantsTableauColumn() const; + /** Useful information for factorization + 0 - iteration number + whereFrom is 0 for factorize and 1 for replaceColumn + */ + virtual void setUsefulInformation(const int * info,int whereFrom); + /// Set maximum pivots + virtual void maximumPivots ( int value ); + + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + /// Condition number - product of pivots after factorization + double conditionNumber() const; + /// Get rid of all memory + virtual void clearArrays(); + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn ( CoinIndexedVector * regionSparse, + int pivotRow, + double pivotCheck , + bool checkBeforeModifying=false, + double acceptablePivot=1.0e-8); + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnFT ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false); + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false) const; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, + CoinIndexedVector * regionSparse2, + CoinIndexedVector * regionSparse3, + bool noPermute=false); + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2) const; + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + //inline void clearArrays() + //{ gutsOfDestructor();} + /// Returns array to put basis indices in + virtual int * indices() const; + /// Returns permute in + virtual inline int * permute() const + { return NULL;/*pivotRow_*/;} + //@} + + /// The real work of desstructor + void gutsOfDestructor(bool clearFact=true); + /// The real work of constructor + void gutsOfInitialize(bool zapFact=true); + /// The real work of copy + void gutsOfCopy(const CoinOslFactorization &other); + + //@} +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + /// Osl factorization data + EKKfactinfo factInfo_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CoinPackedMatrix.hpp b/thirdparty/linux/include/coin/CoinPackedMatrix.hpp new file mode 100644 index 0000000..c6837ac --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPackedMatrix.hpp @@ -0,0 +1,947 @@ +/* $Id: CoinPackedMatrix.hpp 1560 2012-11-24 00:29:01Z lou $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPackedMatrix_H +#define CoinPackedMatrix_H + +#include "CoinError.hpp" +#include "CoinTypes.hpp" +#ifndef CLP_NO_VECTOR +#include "CoinPackedVectorBase.hpp" +#include "CoinShallowPackedVector.hpp" +#else +class CoinRelFltEq; +#endif + +/** Sparse Matrix Base Class + + This class is intended to represent sparse matrices using row-major + or column-major ordering. The representation is very efficient for + adding, deleting, or retrieving major-dimension vectors. Adding + a minor-dimension vector is less efficient, but can be helped by + providing "extra" space as described in the next paragraph. Deleting + a minor-dimension vector requires inspecting all coefficients in the + matrix. Retrieving a minor-dimension vector would incur the same cost + and is not supported (except in the sense that you can write a loop to + retrieve all coefficients one at a time). Consider physically transposing + the matrix, or keeping a second copy with the other major-vector ordering. + + The sparse represention can be completely compact or it can have "extra" + space available at the end of each major vector. Incorporating extra + space into the sparse matrix representation can improve performance in + cases where new data needs to be inserted into the packed matrix against + the major-vector orientation (e.g, inserting a row into a matrix stored + in column-major order). + + For example if the matrix: + @verbatim + 3 1 0 -2 -1 0 0 -1 + 0 2 1.1 0 0 0 0 0 + 0 0 1 0 0 1 0 0 + 0 0 0 2.8 0 0 -1.2 0 + 5.6 0 0 0 1 0 0 1.9 + + was stored by rows (with no extra space) in + CoinPackedMatrix r then: + r.getElements() returns a vector containing: + 3 1 -2 -1 -1 2 1.1 1 1 2.8 -1.2 5.6 1 1.9 + r.getIndices() returns a vector containing: + 0 1 3 4 7 1 2 2 5 3 6 0 4 7 + r.getVectorStarts() returns a vector containing: + 0 5 7 9 11 14 + r.getNumElements() returns 14. + r.getMajorDim() returns 5. + r.getVectorSize(0) returns 5. + r.getVectorSize(1) returns 2. + r.getVectorSize(2) returns 2. + r.getVectorSize(3) returns 2. + r.getVectorSize(4) returns 3. + + If stored by columns (with no extra space) then: + c.getElements() returns a vector containing: + 3 5.6 1 2 1.1 1 -2 2.8 -1 1 1 -1.2 -1 1.9 + c.getIndices() returns a vector containing: + 0 4 0 1 1 2 0 3 0 4 2 3 0 4 + c.getVectorStarts() returns a vector containing: + 0 2 4 6 8 10 11 12 14 + c.getNumElements() returns 14. + c.getMajorDim() returns 8. + @endverbatim + + Compiling this class with CLP_NO_VECTOR defined will excise all methods + which use CoinPackedVectorBase, CoinPackedVector, or CoinShallowPackedVector + as parameters or return types. + + Compiling this class with COIN_FAST_CODE defined removes index range checks. +*/ +class CoinPackedMatrix { + friend void CoinPackedMatrixUnitTest(); + +public: + + + //--------------------------------------------------------------------------- + /**@name Query members */ + //@{ + /** Return the current setting of the extra gap. */ + inline double getExtraGap() const { return extraGap_; } + /** Return the current setting of the extra major. */ + inline double getExtraMajor() const { return extraMajor_; } + + /** Reserve sufficient space for appending major-ordered vectors. + If create is true, empty columns are created (for column generation) */ + void reserve(const int newMaxMajorDim, const CoinBigIndex newMaxSize, + bool create=false); + /** Clear the data, but do not free any arrays */ + void clear(); + + /** Whether the packed matrix is column major ordered or not. */ + inline bool isColOrdered() const { return colOrdered_; } + + /** Whether the packed matrix has gaps or not. */ + inline bool hasGaps() const { return (size_<start_[majorDim_]) ; } + + /** Number of entries in the packed matrix. */ + inline CoinBigIndex getNumElements() const { return size_; } + + /** Number of columns. */ + inline int getNumCols() const + { return colOrdered_ ? majorDim_ : minorDim_; } + + /** Number of rows. */ + inline int getNumRows() const + { return colOrdered_ ? minorDim_ : majorDim_; } + + /*! \brief A vector containing the elements in the packed matrix. + + Returns #elements_. Note that there might be gaps in this vector, + entries that do not belong to any major-dimension vector. To get + the actual elements one should look at this vector together with + vectorStarts (#start_) and vectorLengths (#length_). + */ + inline const double * getElements() const { return element_; } + + /*! \brief A vector containing the minor indices of the elements in + the packed matrix. + + Returns #index_. Note that there might be gaps in this list, + entries that do not belong to any major-dimension vector. To get + the actual elements one should look at this vector together with + vectorStarts (#start_) and vectorLengths (#length_). + */ + inline const int * getIndices() const { return index_; } + + /*! \brief The size of the <code>vectorStarts</code> array + + See #start_. + */ + inline int getSizeVectorStarts() const + { return ((majorDim_ > 0)?(majorDim_+1):(0)) ; } + + /*! \brief The size of the <code>vectorLengths</code> array + + See #length_. + */ + inline int getSizeVectorLengths() const { return majorDim_; } + + /*! \brief The positions where the major-dimension vectors start in + elements and indices. + + See #start_. + */ + inline const CoinBigIndex * getVectorStarts() const { return start_; } + + /*! \brief The lengths of the major-dimension vectors. + + See #length_. + */ + inline const int * getVectorLengths() const { return length_; } + + /** The position of the first element in the i'th major-dimension vector. + */ + CoinBigIndex getVectorFirst(const int i) const { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vectorFirst", "CoinPackedMatrix"); +#endif + return start_[i]; + } + /** The position of the last element (well, one entry <em>past</em> the + last) in the i'th major-dimension vector. */ + CoinBigIndex getVectorLast(const int i) const { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vectorLast", "CoinPackedMatrix"); +#endif + return start_[i] + length_[i]; + } + /** The length of i'th vector. */ + inline int getVectorSize(const int i) const { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vectorSize", "CoinPackedMatrix"); +#endif + return length_[i]; + } +#ifndef CLP_NO_VECTOR + /** Return the i'th vector in matrix. */ + const CoinShallowPackedVector getVector(int i) const { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vector", "CoinPackedMatrix"); +#endif + return CoinShallowPackedVector(length_[i], + index_ + start_[i], + element_ + start_[i], + false); + } +#endif + /** Returns an array containing major indices. The array is + getNumElements long and if getVectorStarts() is 0,2,5 then + the array would start 0,0,1,1,1,2... + This method is provided to go back from a packed format + to a triple format. It returns NULL if there are gaps in + matrix so user should use removeGaps() if there are any gaps. + It does this as this array has to match getElements() and + getIndices() and because it makes no sense otherwise. + The returned array is allocated with <code>new int[]</code>, + free it with <code>delete[]</code>. */ + int * getMajorIndices() const; + //@} + + //--------------------------------------------------------------------------- + /**@name Modifying members */ + //@{ + /*! \brief Set the dimensions of the matrix. + + The method name is deceptive; the effect is to append empty columns + and/or rows to the matrix to reach the specified dimensions. + A negative number for either dimension means that that dimension + doesn't change. An exception will be thrown if the specified dimensions + are smaller than the current dimensions. + */ + void setDimensions(int numrows, int numcols); + + /** Set the extra gap to be allocated to the specified value. */ + void setExtraGap(const double newGap); + /** Set the extra major to be allocated to the specified value. */ + void setExtraMajor(const double newMajor); +#ifndef CLP_NO_VECTOR + /*! Append a column to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the column vector specifies a nonexistent row index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendCol(const CoinPackedVectorBase& vec); +#endif + /*! Append a column to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the column vector specifies a nonexistent row index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendCol(const int vecsize, + const int *vecind, const double *vecelem); +#ifndef CLP_NO_VECTOR + /*! Append a set of columns to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if any of the column vectors specify a nonexistent row index. Otherwise + the method assumes that every index fits into the matrix. + */ + void appendCols(const int numcols, + const CoinPackedVectorBase * const * cols); +#endif + /*! Append a set of columns to the end of the matrix. + + Returns the number of errors (nonexistent or duplicate row index). + No error checking is performed if \p numberRows < 0. + */ + int appendCols(const int numcols, + const CoinBigIndex * columnStarts, const int * row, + const double * element, int numberRows=-1); +#ifndef CLP_NO_VECTOR + /*! Append a row to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the row vector specifies a nonexistent column index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendRow(const CoinPackedVectorBase& vec); +#endif + /*! Append a row to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the row vector specifies a nonexistent column index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendRow(const int vecsize, + const int *vecind, const double *vecelem); +#ifndef CLP_NO_VECTOR + /*! Append a set of rows to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if any of the row vectors specify a nonexistent column index. Otherwise + the method assumes that every index fits into the matrix. + */ + void appendRows(const int numrows, + const CoinPackedVectorBase * const * rows); +#endif + /*! Append a set of rows to the end of the matrix. + + Returns the number of errors (nonexistent or duplicate column index). + No error checking is performed if \p numberColumns < 0. + */ + int appendRows(const int numrows, + const CoinBigIndex * rowStarts, const int * column, + const double * element, int numberColumns=-1); + + /** Append the argument to the "right" of the current matrix. Imagine this + as adding new columns (don't worry about how the matrices are ordered, + that is taken care of). An exception is thrown if the number of rows + is different in the matrices. */ + void rightAppendPackedMatrix(const CoinPackedMatrix& matrix); + /** Append the argument to the "bottom" of the current matrix. Imagine this + as adding new rows (don't worry about how the matrices are ordered, + that is taken care of). An exception is thrown if the number of columns + is different in the matrices. */ + void bottomAppendPackedMatrix(const CoinPackedMatrix& matrix); + + /** Delete the columns whose indices are listed in <code>indDel</code>. */ + void deleteCols(const int numDel, const int * indDel); + /** Delete the rows whose indices are listed in <code>indDel</code>. */ + void deleteRows(const int numDel, const int * indDel); + + /** Replace the elements of a vector. The indices remain the same. + At most the number specified will be replaced. + The index is between 0 and major dimension of matrix */ + void replaceVector(const int index, + const int numReplace, const double * newElements); + /** Modify one element of packed matrix. An element may be added. + This works for either ordering + If the new element is zero it will be deleted unless + keepZero true */ + void modifyCoefficient(int row, int column, double newElement, + bool keepZero=false); + /** Return one element of packed matrix. + This works for either ordering + If it is not present will return 0.0 */ + double getCoefficient(int row, int column) const; + + /** Eliminate all elements in matrix whose + absolute value is less than threshold. + The column starts are not affected. Returns number of elements + eliminated. Elements eliminated are at end of each vector + */ + int compress(double threshold); + /** Eliminate all duplicate AND small elements in matrix + The column starts are not affected. Returns number of elements + eliminated. + */ + int eliminateDuplicates(double threshold); + /** Sort all columns so indices are increasing.in each column */ + void orderMatrix(); + /** Really clean up matrix. + a) eliminate all duplicate AND small elements in matrix + b) remove all gaps and set extraGap_ and extraMajor_ to 0.0 + c) reallocate arrays and make max lengths equal to lengths + d) orders elements + returns number of elements eliminated + */ + int cleanMatrix(double threshold=1.0e-20); + //@} + + //--------------------------------------------------------------------------- + /**@name Methods that reorganize the whole matrix */ + //@{ + /** Remove the gaps from the matrix if there were any + Can also remove small elements fabs() <= removeValue*/ + void removeGaps(double removeValue=-1.0); + + /** Extract a submatrix from matrix. Those major-dimension vectors of + the matrix comprise the submatrix whose indices are given in the + arguments. Does not allow duplicates. */ + void submatrixOf(const CoinPackedMatrix& matrix, + const int numMajor, const int * indMajor); + /** Extract a submatrix from matrix. Those major-dimension vectors of + the matrix comprise the submatrix whose indices are given in the + arguments. Allows duplicates and keeps order. */ + void submatrixOfWithDuplicates(const CoinPackedMatrix& matrix, + const int numMajor, const int * indMajor); +#if 0 + /** Extract a submatrix from matrix. Those major/minor-dimension vectors of + the matrix comprise the submatrix whose indices are given in the + arguments. */ + void submatrixOf(const CoinPackedMatrix& matrix, + const int numMajor, const int * indMajor, + const int numMinor, const int * indMinor); +#endif + + /** Copy method. This method makes an exact replica of the argument, + including the extra space parameters. */ + void copyOf(const CoinPackedMatrix& rhs); + /** Copy the arguments to the matrix. If <code>len</code> is a NULL pointer + then the matrix is assumed to have no gaps in it and <code>len</code> + will be created accordingly. */ + void copyOf(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double * elem, const int * ind, + const CoinBigIndex * start, const int * len, + const double extraMajor=0.0, const double extraGap=0.0); + /** Copy method. This method makes an exact replica of the argument, + including the extra space parameters. + If there is room it will re-use arrays */ + void copyReuseArrays(const CoinPackedMatrix& rhs); + + /*! \brief Make a reverse-ordered copy. + + This method makes an exact replica of the argument with the major + vector orientation changed from row (column) to column (row). + The extra space parameters are also copied and reversed. + (Cf. #reverseOrdering, which does the same thing in place.) + */ + void reverseOrderedCopyOf(const CoinPackedMatrix& rhs); + + /** Assign the arguments to the matrix. If <code>len</code> is a NULL + pointer then the matrix is assumed to have no gaps in it and + <code>len</code> will be created accordingly. <br> + <strong>NOTE 1</strong>: After this method returns the pointers + passed to the method will be NULL pointers! <br> + <strong>NOTE 2</strong>: When the matrix is eventually destructed the + arrays will be deleted by <code>delete[]</code>. Hence one should use + this method ONLY if all array swere allocated by <code>new[]</code>! */ + void assignMatrix(const bool colordered, + const int minor, const int major, + const CoinBigIndex numels, + double *& elem, int *& ind, + CoinBigIndex *& start, int *& len, + const int maxmajor = -1, const CoinBigIndex maxsize = -1); + + + + /** Assignment operator. This copies out the data, but uses the current + matrix's extra space parameters. */ + CoinPackedMatrix & operator=(const CoinPackedMatrix& rhs); + + /*! \brief Reverse the ordering of the packed matrix. + + Change the major vector orientation of the matrix data structures from + row (column) to column (row). (Cf. #reverseOrderedCopyOf, which does + the same thing but produces a new matrix.) + */ + void reverseOrdering(); + + /*! \brief Transpose the matrix. + + \note + If you start with a column-ordered matrix and invoke transpose, you + will have a row-ordered transposed matrix. To change the major vector + orientation (e.g., to transform a column-ordered matrix to a + column-ordered transposed matrix), invoke transpose() followed by + #reverseOrdering(). + */ + void transpose(); + + /*! \brief Swap the content of two packed matrices. */ + void swap(CoinPackedMatrix& matrix); + + //@} + + //--------------------------------------------------------------------------- + /**@name Matrix times vector methods */ + //@{ + /** Return <code>A * x</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numColumns()</code> + @pre <code>y</code> must be of size <code>numRows()</code> */ + void times(const double * x, double * y) const; +#ifndef CLP_NO_VECTOR + /** Return <code>A * x</code> in <code>y</code>. Same as the previous + method, just <code>x</code> is given in the form of a packed vector. */ + void times(const CoinPackedVectorBase& x, double * y) const; +#endif + /** Return <code>x * A</code> in <code>y</code>. + @pre <code>x</code> must be of size <code>numRows()</code> + @pre <code>y</code> must be of size <code>numColumns()</code> */ + void transposeTimes(const double * x, double * y) const; +#ifndef CLP_NO_VECTOR + /** Return <code>x * A</code> in <code>y</code>. Same as the previous + method, just <code>x</code> is given in the form of a packed vector. */ + void transposeTimes(const CoinPackedVectorBase& x, double * y) const; +#endif + //@} + + //--------------------------------------------------------------------------- + /**@name Helper functions used internally, but maybe useful externally. + + These methods do not worry about testing whether the packed matrix is + row or column major ordered; they operate under the assumption that the + correct version is invoked. In fact, a number of other methods simply + just call one of these after testing the ordering of the matrix. */ + //@{ + + //------------------------------------------------------------------------- + /**@name Queries */ + //@{ + /** Count the number of entries in every minor-dimension vector and + return an array containing these lengths. The returned array is + allocated with <code>new int[]</code>, free it with + <code>delete[]</code>. */ + int * countOrthoLength() const; + /** Count the number of entries in every minor-dimension vector and + fill in an array containing these lengths. */ + void countOrthoLength(int * counts) const; + /** Major dimension. For row ordered matrix this would be the number of + rows. */ + inline int getMajorDim() const { return majorDim_; } + /** Set major dimension. For row ordered matrix this would be the number of + rows. Use with great care.*/ + inline void setMajorDim(int value) { majorDim_ = value; } + /** Minor dimension. For row ordered matrix this would be the number of + columns. */ + inline int getMinorDim() const { return minorDim_; } + /** Set minor dimension. For row ordered matrix this would be the number of + columns. Use with great care.*/ + inline void setMinorDim(int value) { minorDim_ = value; } + /** Current maximum for major dimension. For row ordered matrix this many + rows can be added without reallocating the vector related to the + major dimension (<code>start_</code> and <code>length_</code>). */ + inline int getMaxMajorDim() const { return maxMajorDim_; } + + /** Dump the matrix on stdout. When in dire straits this method can + help. */ + void dumpMatrix(const char* fname = NULL) const; + + /// Print a single matrix element. + void printMatrixElement(const int row_val, const int col_val) const; + //@} + + //------------------------------------------------------------------------- + /*! @name Append vectors + + \details + When compiled with COIN_DEBUG defined these methods throw an exception + if the major (minor) vector contains an index that's invalid for the + minor (major) dimension. Otherwise the methods assume that every index + fits into the matrix. + */ + //@{ +#ifndef CLP_NO_VECTOR + /** Append a major-dimension vector to the end of the matrix. */ + void appendMajorVector(const CoinPackedVectorBase& vec); +#endif + /** Append a major-dimension vector to the end of the matrix. */ + void appendMajorVector(const int vecsize, const int *vecind, + const double *vecelem); +#ifndef CLP_NO_VECTOR + /** Append several major-dimensonvectors to the end of the matrix */ + void appendMajorVectors(const int numvecs, + const CoinPackedVectorBase * const * vecs); + + /** Append a minor-dimension vector to the end of the matrix. */ + void appendMinorVector(const CoinPackedVectorBase& vec); +#endif + /** Append a minor-dimension vector to the end of the matrix. */ + void appendMinorVector(const int vecsize, const int *vecind, + const double *vecelem); +#ifndef CLP_NO_VECTOR + /** Append several minor-dimension vectors to the end of the matrix */ + void appendMinorVectors(const int numvecs, + const CoinPackedVectorBase * const * vecs); +#endif + /*! \brief Append a set of rows (columns) to the end of a column (row) + ordered matrix. + + This case is when we know there are no gaps and majorDim_ will not + change. + + \todo + This method really belongs in the group of protected methods with + #appendMinor; there are no safeties here even with COIN_DEBUG. + Apparently this method was needed in ClpPackedMatrix and giving it + proper visibility was too much trouble. Should be moved. + */ + void appendMinorFast(const int number, + const CoinBigIndex * starts, const int * index, + const double * element); + //@} + + //------------------------------------------------------------------------- + /*! \name Append matrices + + \details + We'll document these methods assuming that the current matrix is + column major ordered (Hence in the <code>...SameOrdered()</code> + methods the argument is column ordered, in the + <code>OrthoOrdered()</code> methods the argument is row ordered.) + */ + //@{ + /** Append the columns of the argument to the right end of this matrix. + @pre <code>minorDim_ == matrix.minorDim_</code> <br> + This method throws an exception if the minor dimensions are not the + same. */ + void majorAppendSameOrdered(const CoinPackedMatrix& matrix); + /** Append the columns of the argument to the bottom end of this matrix. + @pre <code>majorDim_ == matrix.majorDim_</code> <br> + This method throws an exception if the major dimensions are not the + same. */ + void minorAppendSameOrdered(const CoinPackedMatrix& matrix); + /** Append the rows of the argument to the right end of this matrix. + @pre <code>minorDim_ == matrix.majorDim_</code> <br> + This method throws an exception if the minor dimension of the + current matrix is not the same as the major dimension of the + argument matrix. */ + void majorAppendOrthoOrdered(const CoinPackedMatrix& matrix); + /** Append the rows of the argument to the bottom end of this matrix. + @pre <code>majorDim_ == matrix.minorDim_</code> <br> + This method throws an exception if the major dimension of the + current matrix is not the same as the minor dimension of the + argument matrix. */ + void minorAppendOrthoOrdered(const CoinPackedMatrix& matrix); + //@} + + //----------------------------------------------------------------------- + /**@name Delete vectors */ + //@{ + /** Delete the major-dimension vectors whose indices are listed in + <code>indDel</code>. */ + void deleteMajorVectors(const int numDel, const int * indDel); + /** Delete the minor-dimension vectors whose indices are listed in + <code>indDel</code>. */ + void deleteMinorVectors(const int numDel, const int * indDel); + //@} + + //----------------------------------------------------------------------- + /**@name Various dot products. */ + //@{ + /** Return <code>A * x</code> (multiplied from the "right" direction) in + <code>y</code>. + @pre <code>x</code> must be of size <code>majorDim()</code> + @pre <code>y</code> must be of size <code>minorDim()</code> */ + void timesMajor(const double * x, double * y) const; +#ifndef CLP_NO_VECTOR + /** Return <code>A * x</code> (multiplied from the "right" direction) in + <code>y</code>. Same as the previous method, just <code>x</code> is + given in the form of a packed vector. */ + void timesMajor(const CoinPackedVectorBase& x, double * y) const; +#endif + /** Return <code>A * x</code> (multiplied from the "right" direction) in + <code>y</code>. + @pre <code>x</code> must be of size <code>minorDim()</code> + @pre <code>y</code> must be of size <code>majorDim()</code> */ + void timesMinor(const double * x, double * y) const; +#ifndef CLP_NO_VECTOR + /** Return <code>A * x</code> (multiplied from the "right" direction) in + <code>y</code>. Same as the previous method, just <code>x</code> is + given in the form of a packed vector. */ + void timesMinor(const CoinPackedVectorBase& x, double * y) const; +#endif + //@} + //@} + + //-------------------------------------------------------------------------- + /**@name Logical Operations. */ + //@{ +#ifndef CLP_NO_VECTOR + /*! \brief Test for equivalence. + + Two matrices are equivalent if they are both row- or column-ordered, + they have the same dimensions, and each (major) vector is equivalent. + The operator used to test for equality can be specified using the + \p FloatEqual template parameter. + */ + template <class FloatEqual> bool + isEquivalent(const CoinPackedMatrix& rhs, const FloatEqual& eq) const + { + // Both must be column order or both row ordered and must be of same size + if ((isColOrdered() ^ rhs.isColOrdered()) || + (getNumCols() != rhs.getNumCols()) || + (getNumRows() != rhs.getNumRows()) || + (getNumElements() != rhs.getNumElements())) + return false; + + for (int i=getMajorDim()-1; i >= 0; --i) { + CoinShallowPackedVector pv = getVector(i); + CoinShallowPackedVector rhsPv = rhs.getVector(i); + if ( !pv.isEquivalent(rhsPv,eq) ) + return false; + } + return true; + } + + /*! \brief Test for equivalence and report differences + + Equivalence is defined as for #isEquivalent. In addition, this method will + print differences to std::cerr. Intended for use in unit tests and + for debugging. + */ + bool isEquivalent2(const CoinPackedMatrix& rhs) const; +#else + /*! \brief Test for equivalence. + + Two matrices are equivalent if they are both row- or column-ordered, + they have the same dimensions, and each (major) vector is equivalent. + This method is optimised for speed. CoinPackedVector#isEquivalent is + replaced with more efficient code for repeated comparison of + equal-length vectors. The CoinRelFltEq operator is used. + */ + bool isEquivalent(const CoinPackedMatrix& rhs, const CoinRelFltEq & eq) const; +#endif + /*! \brief Test for equivalence. + + The test for element equality is the default CoinRelFltEq operator. + */ + bool isEquivalent(const CoinPackedMatrix& rhs) const; + //@} + + //-------------------------------------------------------------------------- + /*! \name Non-const methods + + These are to be used with great care when doing column generation, etc. + */ + //@{ + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with #start_ and #length_. */ + inline double * getMutableElements() const { return element_; } + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with #start_ and + #length_. */ + inline int * getMutableIndices() const { return index_; } + + /** The positions where the major-dimension vectors start in #element_ and + #index_. */ + inline CoinBigIndex * getMutableVectorStarts() const { return start_; } + /** The lengths of the major-dimension vectors. */ + inline int * getMutableVectorLengths() const { return length_; } + /// Change the size of the bulk store after modifying - be careful + inline void setNumElements(CoinBigIndex value) + { size_ = value;} + /*! NULLify element array + + Used when space is very tight. Does not free the space! + */ + inline void nullElementArray() {element_=NULL;} + + /*! NULLify start array + + Used when space is very tight. Does not free the space! + */ + inline void nullStartArray() {start_=NULL;} + + /*! NULLify length array + + Used when space is very tight. Does not free the space! + */ + inline void nullLengthArray() {length_=NULL;} + + /*! NULLify index array + + Used when space is very tight. Does not free the space! + */ + inline void nullIndexArray() {index_=NULL;} + //@} + + //-------------------------------------------------------------------------- + /*! \name Constructors and destructors */ + //@{ + /// Default Constructor creates an empty column ordered packed matrix + CoinPackedMatrix(); + + /// A constructor where the ordering and the gaps are specified + CoinPackedMatrix(const bool colordered, + const double extraMajor, const double extraGap); + + CoinPackedMatrix(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double * elem, const int * ind, + const CoinBigIndex * start, const int * len, + const double extraMajor, const double extraGap); + + CoinPackedMatrix(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double * elem, const int * ind, + const CoinBigIndex * start, const int * len); + + /** Create packed matrix from triples. + If colordered is true then the created matrix will be column ordered. + Duplicate matrix elements are allowed. The created matrix will have + the sum of the duplicates. <br> + For example if: <br> + rowIndices[0]=2; colIndices[0]=5; elements[0]=2.0 <br> + rowIndices[1]=2; colIndices[1]=5; elements[1]=0.5 <br> + then the created matrix will contain a value of 2.5 in row 2 and column 5.<br> + The matrix is created without gaps. + */ + CoinPackedMatrix(const bool colordered, + const int * rowIndices, + const int * colIndices, + const double * elements, + CoinBigIndex numels ); + + /// Copy constructor + CoinPackedMatrix(const CoinPackedMatrix& m); + + /*! \brief Copy constructor with fine tuning + + This constructor allows for the specification of an exact amount of extra + space and/or reverse ordering. + + \p extraForMajor is the exact number of spare major vector slots after + any possible reverse ordering. If \p extraForMajor < 0, all gaps and small + elements will be removed from the copy, otherwise gaps and small elements + are preserved. + + \p extraElements is the exact number of spare element entries. + + The usual multipliers, #extraMajor_ and #extraGap_, are set to zero. + */ + CoinPackedMatrix(const CoinPackedMatrix &m, + int extraForMajor, int extraElements, + bool reverseOrdering = false) ; + + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + CoinPackedMatrix (const CoinPackedMatrix & wholeModel, + int numberRows, const int * whichRows, + int numberColumns, const int * whichColumns); + + /// Destructor + virtual ~CoinPackedMatrix(); + //@} + + /*! \name Debug Utilities */ + //@{ + /*! \brief Scan the matrix for anomalies. + + Returns the number of anomalies. Scans the structure for gaps, + obviously bogus indices and coefficients, and inconsistencies. Gaps + are not an error unless #hasGaps() says the matrix should be + gap-free. Zeroes are not an error unless \p zeroesAreError is set to + true. + + Values for verbosity are: + - 0: No messages, just the return value + - 1: Messages about errors + - 2: If there are no errors, a message indicating the matrix was + checked is printed (positive confirmation). + - 3: Adds a bit more information about the matrix. + - 4: Prints warnings about zeroes even if they're not considered + errors. + + Obviously bogus coefficients are coefficients that are NaN or have + absolute value greater than 1e50. Zeros have absolute value less + than 1e-50. + */ + int verifyMtx(int verbosity = 1, bool zeroesAreError = false) const ; + //@} + + //-------------------------------------------------------------------------- +protected: + void gutsOfDestructor(); + void gutsOfCopyOf(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double * elem, const int * ind, + const CoinBigIndex * start, const int * len, + const double extraMajor=0.0, const double extraGap=0.0); + /// When no gaps we can do faster + void gutsOfCopyOfNoGaps(const bool colordered, + const int minor, const int major, + const double * elem, const int * ind, + const CoinBigIndex * start); + void gutsOfOpEqual(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double * elem, const int * ind, + const CoinBigIndex * start, const int * len); + void resizeForAddingMajorVectors(const int numVec, const int * lengthVec); + void resizeForAddingMinorVectors(const int * addedEntries); + + /*! \brief Append a set of rows (columns) to the end of a row (colum) + ordered matrix. + + If \p numberOther > 0 the method will check if any of the new rows + (columns) contain duplicate indices or invalid indices and return the + number of errors. A valid minor index must satisfy + \code 0 <= k < numberOther \endcode + If \p numberOther < 0 no checking is performed. + */ + int appendMajor(const int number, + const CoinBigIndex * starts, const int * index, + const double * element, int numberOther=-1); + /*! \brief Append a set of rows (columns) to the end of a column (row) + ordered matrix. + + If \p numberOther > 0 the method will check if any of the new rows + (columns) contain duplicate indices or indices outside the current + range for the major dimension and return the number of violations. + If \p numberOther <= 0 the major dimension will be expanded as + necessary and there are no checks for duplicate indices. + */ + int appendMinor(const int number, + const CoinBigIndex * starts, const int * index, + const double * element, int numberOther=-1); + +private: + inline CoinBigIndex getLastStart() const { + return majorDim_ == 0 ? 0 : start_[majorDim_]; + } + + //-------------------------------------------------------------------------- +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /** A flag indicating whether the matrix is column or row major ordered. */ + bool colOrdered_; + /** This much times more space should be allocated for each major-dimension + vector (with respect to the number of entries in the vector) when the + matrix is resized. The purpose of these gaps is to allow fast insertion + of new minor-dimension vectors. */ + double extraGap_; + /** his much times more space should be allocated for major-dimension + vectors when the matrix is resized. The purpose of these gaps is to + allow fast addition of new major-dimension vectors. */ + double extraMajor_; + + /** List of nonzero element values. The entries in the gaps between + major-dimension vectors are undefined. */ + double *element_; + /** List of nonzero element minor-dimension indices. The entries in the gaps + between major-dimension vectors are undefined. */ + int *index_; + /** Starting positions of major-dimension vectors. */ + CoinBigIndex *start_; + /** Lengths of major-dimension vectors. */ + int *length_; + + /// number of vectors in matrix + int majorDim_; + /// size of other dimension + int minorDim_; + /// the number of nonzero entries + CoinBigIndex size_; + + /// max space allocated for major-dimension + int maxMajorDim_; + /// max space allocated for entries + CoinBigIndex maxSize_; + //@} +}; + +//############################################################################# +/*! \brief Test the methods in the CoinPackedMatrix class. + + The only reason for it not to be a member method is that this way + it doesn't have to be compiled into the library. And that's a gain, + because the library should be compiled with optimization on, but this + method should be compiled with debugging. +*/ +void +CoinPackedMatrixUnitTest(); + +#endif diff --git a/thirdparty/linux/include/coin/CoinPackedVector.hpp b/thirdparty/linux/include/coin/CoinPackedVector.hpp new file mode 100644 index 0000000..9ea1feb --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPackedVector.hpp @@ -0,0 +1,657 @@ +/* $Id: CoinPackedVector.hpp 1509 2011-12-05 13:50:48Z forrest $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPackedVector_H +#define CoinPackedVector_H + +#include <map> + +#include "CoinPragma.hpp" +#include "CoinPackedVectorBase.hpp" +#include "CoinSort.hpp" + +#ifdef COIN_FAST_CODE +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_NOTEST_DUPLICATE +#endif +#endif + +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE true +#else +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE false +#endif +/** Sparse Vector + +Stores vector of indices and associated element values. +Supports sorting of vector while maintaining the original indices. + +Here is a sample usage: +@verbatim + const int ne = 4; + int inx[ne] = { 1, 4, 0, 2 } + double el[ne] = { 10., 40., 1., 50. } + + // Create vector and set its value + CoinPackedVector r(ne,inx,el); + + // access each index and element + assert( r.indices ()[0]== 1 ); + assert( r.elements()[0]==10. ); + assert( r.indices ()[1]== 4 ); + assert( r.elements()[1]==40. ); + assert( r.indices ()[2]== 0 ); + assert( r.elements()[2]== 1. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // access original position of index + assert( r.originalPosition()[0]==0 ); + assert( r.originalPosition()[1]==1 ); + assert( r.originalPosition()[2]==2 ); + assert( r.originalPosition()[3]==3 ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // sort Elements in increasing order + r.sortIncrElement(); + + // access each index and element + assert( r.indices ()[0]== 0 ); + assert( r.elements()[0]== 1. ); + assert( r.indices ()[1]== 1 ); + assert( r.elements()[1]==10. ); + assert( r.indices ()[2]== 4 ); + assert( r.elements()[2]==40. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // access original position of index + assert( r.originalPosition()[0]==2 ); + assert( r.originalPosition()[1]==0 ); + assert( r.originalPosition()[2]==1 ); + assert( r.originalPosition()[3]==3 ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // Restore orignal sort order + r.sortOriginalOrder(); + + assert( r.indices ()[0]== 1 ); + assert( r.elements()[0]==10. ); + assert( r.indices ()[1]== 4 ); + assert( r.elements()[1]==40. ); + assert( r.indices ()[2]== 0 ); + assert( r.elements()[2]== 1. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // Tests for equality and equivalence + CoinPackedVector r1; + r1=r; + assert( r==r1 ); + assert( r.equivalent(r1) ); + r.sortIncrElement(); + assert( r!=r1 ); + assert( r.equivalent(r1) ); + + // Add packed vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinPackedVector add = r + r1; + assert( add[0] == 1.+ 1. ); + assert( add[1] == 10.+10. ); + assert( add[2] == 50.+50. ); + assert( add[3] == 0.+ 0. ); + assert( add[4] == 40.+40. ); + + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +class CoinPackedVector : public CoinPackedVectorBase { + friend void CoinPackedVectorUnitTest(); + +public: + /**@name Get methods. */ + //@{ + /// Get the size + virtual int getNumElements() const { return nElements_; } + /// Get indices of elements + virtual const int * getIndices() const { return indices_; } + /// Get element values + virtual const double * getElements() const { return elements_; } + /// Get indices of elements + int * getIndices() { return indices_; } + /// Get the size + inline int getVectorNumElements() const { return nElements_; } + /// Get indices of elements + inline const int * getVectorIndices() const { return indices_; } + /// Get element values + inline const double * getVectorElements() const { return elements_; } + /// Get element values + double * getElements() { return elements_; } + /** Get pointer to int * vector of original postions. + If the packed vector has not been sorted then this + function returns the vector: 0, 1, 2, ..., size()-1. */ + const int * getOriginalPosition() const { return origIndices_; } + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Reset the vector (as if were just created an empty vector) + void clear(); + /** Assignment operator. <br> + <strong>NOTE</strong>: This operator keeps the current + <code>testForDuplicateIndex</code> setting, and affter copying the data + it acts accordingly. */ + CoinPackedVector & operator=(const CoinPackedVector &); + /** Assignment operator from a CoinPackedVectorBase. <br> + <strong>NOTE</strong>: This operator keeps the current + <code>testForDuplicateIndex</code> setting, and affter copying the data + it acts accordingly. */ + CoinPackedVector & operator=(const CoinPackedVectorBase & rhs); + + /** Assign the ownership of the arguments to this vector. + Size is the length of both the indices and elements vectors. + The indices and elements vectors are copied into this class instance's + member data. The last argument indicates whether this vector will have + to be tested for duplicate indices. + */ + void assignVector(int size, int*& inds, double*& elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Set vector size, indices, and elements. + Size is the length of both the indices and elements vectors. + The indices and elements vectors are copied into this class instance's + member data. The last argument specifies whether this vector will have + to be checked for duplicate indices whenever that can happen. */ + void setVector(int size, const int * inds, const double * elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Elements set to have the same scalar value */ + void setConstant(int size, const int * inds, double elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Indices are not specified and are taken to be 0,1,...,size-1 */ + void setFull(int size, const double * elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Indices are not specified and are taken to be 0,1,...,size-1, + but only where non zero*/ + void setFullNonZero(int size, const double * elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Set an existing element in the packed vector + The first argument is the "index" into the elements() array + */ + void setElement(int index, double element); + + /// Insert an element into the vector + void insert(int index, double element); + /// Append a CoinPackedVector to the end + void append(const CoinPackedVectorBase & caboose); + + /// Swap values in positions i and j of indices and elements + void swap(int i, int j); + + /** Resize the packed vector to be the first newSize elements. + Problem with truncate: what happens with origIndices_ ??? */ + void truncate(int newSize); + //@} + + /**@name Arithmetic operators. */ + //@{ + /// add <code>value</code> to every entry + void operator+=(double value); + /// subtract <code>value</code> from every entry + void operator-=(double value); + /// multiply every entry by <code>value</code> + void operator*=(double value); + /// divide every entry by <code>value</code> + void operator/=(double value); + //@} + + /**@name Sorting */ + //@{ + /** Sort the packed storage vector. + Typcical usages: + <pre> + packedVector.sort(CoinIncrIndexOrdered()); //increasing indices + packedVector.sort(CoinIncrElementOrdered()); // increasing elements + </pre> + */ + template <class CoinCompare3> + void sort(const CoinCompare3 & tc) + { CoinSort_3(indices_, indices_ + nElements_, origIndices_, elements_, + tc); } + + void sortIncrIndex() + { CoinSort_3(indices_, indices_ + nElements_, origIndices_, elements_, + CoinFirstLess_3<int, int, double>()); } + + void sortDecrIndex() + { CoinSort_3(indices_, indices_ + nElements_, origIndices_, elements_, + CoinFirstGreater_3<int, int, double>()); } + + void sortIncrElement() + { CoinSort_3(elements_, elements_ + nElements_, origIndices_, indices_, + CoinFirstLess_3<double, int, int>()); } + + void sortDecrElement() + { CoinSort_3(elements_, elements_ + nElements_, origIndices_, indices_, + CoinFirstGreater_3<double, int, int>()); } + + + /** Sort in original order. + If the vector has been sorted, then this method restores + to its orignal sort order. + */ + void sortOriginalOrder(); + //@} + + /**@name Memory usage */ + //@{ + /** Reserve space. + If one knows the eventual size of the packed vector, + then it may be more efficient to reserve the space. + */ + void reserve(int n); + /** capacity returns the size which could be accomodated without + having to reallocate storage. + */ + int capacity() const { return capacity_; } + //@} + /**@name Constructors and destructors */ + //@{ + /** Default constructor */ + CoinPackedVector(bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** \brief Alternate Constructors - set elements to vector of doubles + + This constructor copies the vectors provided as parameters. + */ + CoinPackedVector(int size, const int * inds, const double * elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** \brief Alternate Constructors - set elements to vector of doubles + + This constructor takes ownership of the vectors passed as parameters. + \p inds and \p elems will be NULL on return. + */ + CoinPackedVector(int capacity, int size, int *&inds, double *&elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** Alternate Constructors - set elements to same scalar value */ + CoinPackedVector(int size, const int * inds, double element, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** Alternate Constructors - construct full storage with indices 0 through + size-1. */ + CoinPackedVector(int size, const double * elements, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** Copy constructor. */ + CoinPackedVector(const CoinPackedVector &); + /** Copy constructor <em>from a PackedVectorBase</em>. */ + CoinPackedVector(const CoinPackedVectorBase & rhs); + /** Destructor */ + virtual ~CoinPackedVector (); + //@} + +private: + /**@name Private methods */ + //@{ + /// Copy internal date + void gutsOfSetVector(int size, + const int * inds, const double * elems, + bool testForDuplicateIndex, + const char * method); + /// + void gutsOfSetConstant(int size, + const int * inds, double value, + bool testForDuplicateIndex, + const char * method); + //@} + +private: + /**@name Private member data */ + //@{ + /// Vector indices + int * indices_; + ///Vector elements + double * elements_; + /// Size of indices and elements vectors + int nElements_; + /// original unsorted indices + int * origIndices_; + /// Amount of memory allocated for indices_, origIndices_, and elements_. + int capacity_; + //@} +}; + +//############################################################################# + +/**@name Arithmetic operators on packed vectors. + + <strong>NOTE</strong>: These methods operate on those positions where at + least one of the arguments has a value listed. At those positions the + appropriate operation is executed, Otherwise the result of the operation is + considered 0.<br> + <strong>NOTE 2</strong>: There are two kind of operators here. One is used + like "c = binaryOp(a, b)", the other is used like "binaryOp(c, a, b)", but + they are really the same. The first is much more natural to use, but it + involves the creation of a temporary object (the function *must* return an + object), while the second form puts the result directly into the argument + "c". Therefore, depending on the circumstances, the second form can be + significantly faster. + */ +//@{ +template <class BinaryFunction> void +binaryOp(CoinPackedVector& retVal, + const CoinPackedVectorBase& op1, double value, + BinaryFunction bf) +{ + retVal.clear(); + const int s = op1.getNumElements(); + if (s > 0) { + retVal.reserve(s); + const int * inds = op1.getIndices(); + const double * elems = op1.getElements(); + for (int i=0; i<s; ++i ) { + retVal.insert(inds[i], bf(value, elems[i])); + } + } +} + +template <class BinaryFunction> inline void +binaryOp(CoinPackedVector& retVal, + double value, const CoinPackedVectorBase& op2, + BinaryFunction bf) +{ + binaryOp(retVal, op2, value, bf); +} + +template <class BinaryFunction> void +binaryOp(CoinPackedVector& retVal, + const CoinPackedVectorBase& op1, const CoinPackedVectorBase& op2, + BinaryFunction bf) +{ + retVal.clear(); + const int s1 = op1.getNumElements(); + const int s2 = op2.getNumElements(); +/* + Replaced || with &&, in response to complaint from Sven deVries, who + rightly points out || is not appropriate for additive operations. && + should be ok as long as binaryOp is understood not to create something + from nothing. -- lh, 04.06.11 +*/ + if (s1 == 0 && s2 == 0) + return; + + retVal.reserve(s1+s2); + + const int * inds1 = op1.getIndices(); + const double * elems1 = op1.getElements(); + const int * inds2 = op2.getIndices(); + const double * elems2 = op2.getElements(); + + int i; + // loop once for each element in op1 + for ( i=0; i<s1; ++i ) { + const int index = inds1[i]; + const int pos2 = op2.findIndex(index); + const double val = bf(elems1[i], pos2 == -1 ? 0.0 : elems2[pos2]); + // if (val != 0.0) // *THINK* : should we put in only nonzeros? + retVal.insert(index, val); + } + // loop once for each element in operand2 + for ( i=0; i<s2; ++i ) { + const int index = inds2[i]; + // if index exists in op1, then element was processed in prior loop + if ( op1.isExistingIndex(index) ) + continue; + // Index does not exist in op1, so the element value must be zero + const double val = bf(0.0, elems2[i]); + // if (val != 0.0) // *THINK* : should we put in only nonzeros? + retVal.insert(index, val); + } +} + +//----------------------------------------------------------------------------- + +template <class BinaryFunction> CoinPackedVector +binaryOp(const CoinPackedVectorBase& op1, double value, + BinaryFunction bf) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, value, bf); + return retVal; +} + +template <class BinaryFunction> CoinPackedVector +binaryOp(double value, const CoinPackedVectorBase& op2, + BinaryFunction bf) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op2, value, bf); + return retVal; +} + +template <class BinaryFunction> CoinPackedVector +binaryOp(const CoinPackedVectorBase& op1, const CoinPackedVectorBase& op2, + BinaryFunction bf) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, bf); + return retVal; +} + +//----------------------------------------------------------------------------- +/// Return the sum of two packed vectors +inline CoinPackedVector operator+(const CoinPackedVectorBase& op1, + const CoinPackedVectorBase& op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::plus<double>()); + return retVal; +} + +/// Return the difference of two packed vectors +inline CoinPackedVector operator-(const CoinPackedVectorBase& op1, + const CoinPackedVectorBase& op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::minus<double>()); + return retVal; +} + +/// Return the element-wise product of two packed vectors +inline CoinPackedVector operator*(const CoinPackedVectorBase& op1, + const CoinPackedVectorBase& op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::multiplies<double>()); + return retVal; +} + +/// Return the element-wise ratio of two packed vectors +inline CoinPackedVector operator/(const CoinPackedVectorBase& op1, + const CoinPackedVectorBase& op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::divides<double>()); + return retVal; +} +//@} + +/// Returns the dot product of two CoinPackedVector objects whose elements are +/// doubles. Use this version if the vectors are *not* guaranteed to be sorted. +inline double sparseDotProduct(const CoinPackedVectorBase& op1, + const CoinPackedVectorBase& op2){ + int len, i; + double acc = 0.0; + CoinPackedVector retVal; + + CoinPackedVector retval = op1*op2; + len = retval.getNumElements(); + double * CParray = retval.getElements(); + + for(i = 0; i < len; i++){ + acc += CParray[i]; + } +return acc; +} + + +/// Returns the dot product of two sorted CoinPackedVector objects. +/// The vectors should be sorted in ascending order of indices. +inline double sortedSparseDotProduct(const CoinPackedVectorBase& op1, + const CoinPackedVectorBase& op2){ + int i, j, len1, len2; + double acc = 0.0; + + const double* v1val = op1.getElements(); + const double* v2val = op2.getElements(); + const int* v1ind = op1.getIndices(); + const int* v2ind = op2.getIndices(); + + len1 = op1.getNumElements(); + len2 = op2.getNumElements(); + + i = 0; + j = 0; + + while(i < len1 && j < len2){ + if(v1ind[i] == v2ind[j]){ + acc += v1val[i] * v2val[j]; + i++; + j++; + } + else if(v2ind[j] < v1ind[i]){ + j++; + } + else{ + i++; + } // end if-else-elseif + } // end while + return acc; + } + + +//----------------------------------------------------------------------------- + +/**@name Arithmetic operators on packed vector and a constant. <br> + These functions create a packed vector as a result. That packed vector will + have the same indices as <code>op1</code> and the specified operation is + done entry-wise with the given value. */ +//@{ +/// Return the sum of a packed vector and a constant +inline CoinPackedVector +operator+(const CoinPackedVectorBase& op1, double value) +{ + CoinPackedVector retVal(op1); + retVal += value; + return retVal; +} + +/// Return the difference of a packed vector and a constant +inline CoinPackedVector +operator-(const CoinPackedVectorBase& op1, double value) +{ + CoinPackedVector retVal(op1); + retVal -= value; + return retVal; +} + +/// Return the element-wise product of a packed vector and a constant +inline CoinPackedVector +operator*(const CoinPackedVectorBase& op1, double value) +{ + CoinPackedVector retVal(op1); + retVal *= value; + return retVal; +} + +/// Return the element-wise ratio of a packed vector and a constant +inline CoinPackedVector +operator/(const CoinPackedVectorBase& op1, double value) +{ + CoinPackedVector retVal(op1); + retVal /= value; + return retVal; +} + +//----------------------------------------------------------------------------- + +/// Return the sum of a constant and a packed vector +inline CoinPackedVector +operator+(double value, const CoinPackedVectorBase& op1) +{ + CoinPackedVector retVal(op1); + retVal += value; + return retVal; +} + +/// Return the difference of a constant and a packed vector +inline CoinPackedVector +operator-(double value, const CoinPackedVectorBase& op1) +{ + CoinPackedVector retVal(op1); + const int size = retVal.getNumElements(); + double* elems = retVal.getElements(); + for (int i = 0; i < size; ++i) { + elems[i] = value - elems[i]; + } + return retVal; +} + +/// Return the element-wise product of a constant and a packed vector +inline CoinPackedVector +operator*(double value, const CoinPackedVectorBase& op1) +{ + CoinPackedVector retVal(op1); + retVal *= value; + return retVal; +} + +/// Return the element-wise ratio of a a constant and packed vector +inline CoinPackedVector +operator/(double value, const CoinPackedVectorBase& op1) +{ + CoinPackedVector retVal(op1); + const int size = retVal.getNumElements(); + double* elems = retVal.getElements(); + for (int i = 0; i < size; ++i) { + elems[i] = value / elems[i]; + } + return retVal; +} +//@} + +//############################################################################# +/** A function that tests the methods in the CoinPackedVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void +CoinPackedVectorUnitTest(); + +#endif diff --git a/thirdparty/linux/include/coin/CoinPackedVectorBase.hpp b/thirdparty/linux/include/coin/CoinPackedVectorBase.hpp new file mode 100644 index 0000000..dccc1cd --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPackedVectorBase.hpp @@ -0,0 +1,269 @@ +/* $Id: CoinPackedVectorBase.hpp 1416 2011-04-17 09:57:29Z stefan $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPackedVectorBase_H +#define CoinPackedVectorBase_H + +#include <set> +#include <map> +#include "CoinPragma.hpp" +#include "CoinError.hpp" + +class CoinPackedVector; + +/** Abstract base class for various sparse vectors. + + Since this class is abstract, no object of this type can be created. The + sole purpose of this class is to provide access to a <em>constant</em> + packed vector. All members of this class are const methods, they can't + change the object. */ + +class CoinPackedVectorBase { + +public: + /**@name Virtual methods that the derived classes must provide */ + //@{ + /// Get length of indices and elements vectors + virtual int getNumElements() const = 0; + /// Get indices of elements + virtual const int * getIndices() const = 0; + /// Get element values + virtual const double * getElements() const = 0; + //@} + + /**@name Methods related to whether duplicate-index checking is performed. + + If the checking for duplicate indices is turned off, then + some CoinPackedVector methods may not work correctly if there + are duplicate indices. + Turning off the checking for duplicate indices may result in + better run time performance. + */ + //@{ + /** \brief Set to the argument value whether to test for duplicate indices + in the vector whenever they can occur. + + Calling this method with \p test set to true will trigger an immediate + check for duplicate indices. + */ + void setTestForDuplicateIndex(bool test) const; + /** \brief Set to the argument value whether to test for duplicate indices + in the vector whenever they can occur BUT we know that right + now the vector has no duplicate indices. + + Calling this method with \p test set to true will <em>not</em> trigger + an immediate check for duplicate indices; instead, it's assumed that + the result of the test will be true. + */ + void setTestForDuplicateIndexWhenTrue(bool test) const; + /** Returns true if the vector should be tested for duplicate indices when + they can occur. */ + bool testForDuplicateIndex() const { return testForDuplicateIndex_; } + /// Just sets test stuff false without a try etc + inline void setTestsOff() const + { testForDuplicateIndex_=false; testedDuplicateIndex_=false;} + //@} + + /**@name Methods for getting info on the packed vector as a full vector */ + //@{ + /** Get the vector as a dense vector. The argument specifies how long this + dense vector is. <br> + <strong>NOTE</strong>: The user needs to <code>delete[]</code> this + pointer after it's not needed anymore. + */ + double * denseVector(int denseSize) const; + /** Access the i'th element of the full storage vector. + If the i'th is not stored, then zero is returned. The initial use of + this method has some computational and storage overhead associated with + it.<br> + <strong>NOTE</strong>: This is <em>very</em> expensive. It is probably + much better to use <code>denseVector()</code>. + */ + double operator[](int i) const; + //@} + + /**@name Index methods */ + //@{ + /// Get value of maximum index + int getMaxIndex() const; + /// Get value of minimum index + int getMinIndex() const; + + /// Throw an exception if there are duplicate indices + void duplicateIndex(const char* methodName = NULL, + const char * className = NULL) const; + + /** Return true if the i'th element of the full storage vector exists in + the packed storage vector.*/ + bool isExistingIndex(int i) const; + + /** Return the position of the i'th element of the full storage vector. + If index does not exist then -1 is returned */ + int findIndex(int i) const; + + //@} + + /**@name Comparison operators on two packed vectors */ + //@{ + /** Equal. Returns true if vectors have same length and corresponding + element of each vector is equal. */ + bool operator==(const CoinPackedVectorBase & rhs) const; + /// Not equal + bool operator!=(const CoinPackedVectorBase & rhs) const; + +#if 0 + // LL: This should be implemented eventually. It is useful to have. + /** Lexicographic comparisons of two packed vectors. Returns + negative/0/positive depending on whether \c this is + smaller/equal.greater than \c rhs */ + int lexCompare(const CoinPackedVectorBase& rhs); +#endif + + /** This method establishes an ordering on packed vectors. It is complete + ordering, but not the same as lexicographic ordering. However, it is + quick and dirty to compute and thus it is useful to keep packed vectors + in a heap when all we care is to quickly check whether a particular + vector is already in the heap or not. Returns negative/0/positive + depending on whether \c this is smaller/equal.greater than \c rhs. */ + int compare(const CoinPackedVectorBase& rhs) const; + + /** equivalent - If shallow packed vector A & B are equivalent, then they + are still equivalent no matter how they are sorted. + In this method the FloatEqual function operator can be specified. The + default equivalence test is that the entries are relatively equal.<br> + <strong>NOTE</strong>: This is a relatively expensive method as it + sorts the two shallow packed vectors. + */ + template <class FloatEqual> bool + isEquivalent(const CoinPackedVectorBase& rhs, const FloatEqual& eq) const + { + if (getNumElements() != rhs.getNumElements()) + return false; + + duplicateIndex("equivalent", "CoinPackedVector"); + rhs.duplicateIndex("equivalent", "CoinPackedVector"); + + std::map<int,double> mv; + const int * inds = getIndices(); + const double * elems = getElements(); + int i; + for ( i = getNumElements() - 1; i >= 0; --i) { + mv.insert(std::make_pair(inds[i], elems[i])); + } + + std::map<int,double> mvRhs; + inds = rhs.getIndices(); + elems = rhs.getElements(); + for ( i = getNumElements() - 1; i >= 0; --i) { + mvRhs.insert(std::make_pair(inds[i], elems[i])); + } + + std::map<int,double>::const_iterator mvI = mv.begin(); + std::map<int,double>::const_iterator mvIlast = mv.end(); + std::map<int,double>::const_iterator mvIrhs = mvRhs.begin(); + while (mvI != mvIlast) { + if (mvI->first != mvIrhs->first || ! eq(mvI->second, mvIrhs->second)) + return false; + ++mvI; + ++mvIrhs; + } + return true; + } + + bool isEquivalent(const CoinPackedVectorBase& rhs) const; + //@} + + + /**@name Arithmetic operators. */ + //@{ + /// Create the dot product with a full vector + double dotProduct(const double* dense) const; + + /// Return the 1-norm of the vector + double oneNorm() const; + + /// Return the square of the 2-norm of the vector + double normSquare() const; + + /// Return the 2-norm of the vector + double twoNorm() const; + + /// Return the infinity-norm of the vector + double infNorm() const; + + /// Sum elements of vector. + double sum() const; + //@} + +protected: + + /**@name Constructors, destructor + <strong>NOTE</strong>: All constructors are protected. There's no need + to expose them, after all, this is an abstract class. */ + //@{ + /** Default constructor. */ + CoinPackedVectorBase(); + +public: + /** Destructor */ + virtual ~CoinPackedVectorBase(); + //@} + +private: + /**@name Disabled methods */ + //@{ + /** The copy constructor. <br> + This must be at least protected, but we make it private. The reason is + that when, say, a shallow packed vector is created, first the + underlying class, it this one is constructed. However, at that point we + don't know how much of the data members of this class we need to copy + over. Therefore the copy constructor is not used. */ + CoinPackedVectorBase(const CoinPackedVectorBase&); + /** This class provides <em>const</em> access to packed vectors, so there's + no need to provide an assignment operator. */ + CoinPackedVectorBase& operator=(const CoinPackedVectorBase&); + //@} + +protected: + + /**@name Protected methods */ + //@{ + /// Find Maximum and Minimum Indices + void findMaxMinIndices() const; + + /// Return indexSetPtr_ (create it if necessary). + std::set<int> * indexSet(const char* methodName = NULL, + const char * className = NULL) const; + + /// Delete the indexSet + void clearIndexSet() const; + void clearBase() const; + void copyMaxMinIndex(const CoinPackedVectorBase & x) const { + maxIndex_ = x.maxIndex_; + minIndex_ = x.minIndex_; + } + //@} + +private: + /**@name Protected member data */ + //@{ + /// Contains max index value or -infinity + mutable int maxIndex_; + /// Contains minimum index value or infinity + mutable int minIndex_; + /** Store the indices in a set. This set is only created if it is needed. + Its primary use is testing for duplicate indices. + */ + mutable std::set<int> * indexSetPtr_; + /** True if the vector should be tested for duplicate indices when they can + occur. */ + mutable bool testForDuplicateIndex_; + /** True if the vector has already been tested for duplicate indices. Most + of the operations in CoinPackedVector preserves this flag. */ + mutable bool testedDuplicateIndex_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinParam.hpp b/thirdparty/linux/include/coin/CoinParam.hpp new file mode 100644 index 0000000..30cccc2 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinParam.hpp @@ -0,0 +1,644 @@ +/* $Id: CoinParam.hpp 1493 2011-11-01 16:56:07Z tkr $ */ +#ifndef CoinParam_H +#define CoinParam_H + +/* + 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). +*/ + +/*! \file CoinParam.hpp + \brief Declaration of a class for command line parameters. +*/ + +#include <vector> +#include <string> +#include <cstdio> + +/*! \class CoinParam + \brief A base class for `keyword value' command line parameters. + + The underlying paradigm is that a parameter specifies an action to be + performed on a target object. The base class provides two function + pointers, a `push' function and a `pull' function. By convention, a push + function will set some value in the target object or perform some action + using the target object. A `pull' function will retrieve some value from + the target object. This is only a convention, however; CoinParam and + associated utilities make no use of these functions and have no hardcoded + notion of how they should be used. + + The action to be performed, and the target object, will be specific to a + particular application. It is expected that users will derive + application-specific parameter classes from this base class. A derived + class will typically add fields and methods to set/get a code for the + action to be performed (often, an enum class) and the target object (often, + a pointer or reference). + + Facilities provided by the base class and associated utility routines + include: + <ul> + <li> Support for common parameter types with numeric, string, or + keyword values. + <li> Support for short and long help messages. + <li> Pointers to `push' and `pull' functions as described above. + <li> Command line parsing and keyword matching. + </ul> + All utility routines are declared in the #CoinParamUtils namespace. + + The base class recognises five types of parameters: actions (which require + no value); numeric parameters with integer or real (double) values; keyword + parameters, where the value is one of a defined set of value-keywords; + and string parameters (where the value is a string). + The base class supports the definition of a valid range, a default value, + and short and long help messages for a parameter. + + As defined by the #CoinParamFunc typedef, push and pull functions + should take a single parameter, a pointer to a CoinParam. Typically this + object will actually be a derived class as described above, and the + implementation function will have access to all capabilities of CoinParam and + of the derived class. + + When specified as command line parameters, the expected syntax is `-keyword + value' or `-keyword=value'. You can also use the Gnu double-dash style, + `--keyword'. Spaces around the `=' will \e not work. + + The keyword (name) for a parameter can be defined with an `!' to mark the + minimal match point. For example, allow!ableGap will be considered matched + by the strings `allow', `allowa', `allowab', \e etc. Similarly, the + value-keyword strings for keyword parameters can be defined with `!' to + mark the minimal match point. Matching of keywords and value-keywords is + \e not case sensitive. +*/ + +class CoinParam +{ + +public: + +/*! \name Subtypes */ +//@{ + + /*! \brief Enumeration for the types of parameters supported by CoinParam + + CoinParam provides support for several types of parameters: + <ul> + <li> Action parameters, which require no value. + <li> Integer and double numeric parameters, with upper and lower bounds. + <li> String parameters that take an arbitrary string value. + <li> Keyword parameters that take a defined set of string (value-keyword) + values. Value-keywords are associated with integers in the order in + which they are added, starting from zero. + </ul> + */ + typedef enum { coinParamInvalid = 0, + coinParamAct, coinParamInt, coinParamDbl, + coinParamStr, coinParamKwd } CoinParamType ; + + /*! \brief Type declaration for push and pull functions. + + By convention, a return code of 0 indicates execution without error, >0 + indicates nonfatal error, and <0 indicates fatal error. This is only + convention, however; the base class makes no use of the push and pull + functions and has no hardcoded interpretation of the return code. + */ + typedef int (*CoinParamFunc)(CoinParam *param) ; + +//@} + +/*! \name Constructors and Destructors + + Be careful how you specify parameters for the constructors! Some compilers + are entirely too willing to convert almost anything to bool. +*/ +//@{ + + /*! \brief Default constructor */ + + CoinParam() ; + + /*! \brief Constructor for a parameter with a double value + + The default value is 0.0. Be careful to clearly indicate that \p lower and + \p upper are real (double) values to distinguish this constructor from the + constructor for an integer parameter. + */ + CoinParam(std::string name, std::string help, + double lower, double upper, double dflt = 0.0, + bool display = true) ; + + /*! \brief Constructor for a parameter with an integer value + + The default value is 0. + */ + CoinParam(std::string name, std::string help, + int lower, int upper, int dflt = 0, + bool display = true) ; + + /*! \brief Constructor for a parameter with keyword values + + The string supplied as \p firstValue becomes the first value-keyword. + Additional value-keywords can be added using appendKwd(). It's necessary + to specify both the first value-keyword (\p firstValue) and the default + value-keyword index (\p dflt) in order to distinguish this constructor + from the constructors for string and action parameters. + + Value-keywords are associated with an integer, starting with zero and + increasing as each keyword is added. The value-keyword given as \p + firstValue will be associated with the integer zero. The integer supplied + for \p dflt can be any value, as long as it will be valid once all + value-keywords have been added. + */ + CoinParam(std::string name, std::string help, + std::string firstValue, int dflt, bool display = true) ; + + /*! \brief Constructor for a string parameter + + For some compilers, the default value (\p dflt) must be specified + explicitly with type std::string to distinguish the constructor for a + string parameter from the constructor for an action parameter. For + example, use std::string("default") instead of simply "default", or use a + variable of type std::string. + */ + CoinParam(std::string name, std::string help, + std::string dflt, bool display = true) ; + + /*! \brief Constructor for an action parameter */ + + CoinParam(std::string name, std::string help, + bool display = true) ; + + /*! \brief Copy constructor */ + + CoinParam(const CoinParam &orig) ; + + /*! \brief Clone */ + + virtual CoinParam *clone() ; + + /*! \brief Assignment */ + + CoinParam &operator=(const CoinParam &rhs) ; + + /*! \brief Destructor */ + + virtual ~CoinParam() ; + +//@} + +/*! \name Methods to query and manipulate the value(s) of a parameter */ +//@{ + + /*! \brief Add an additional value-keyword to a keyword parameter */ + + void appendKwd(std::string kwd) ; + + /*! \brief Return the integer associated with the specified value-keyword + + Returns -1 if no value-keywords match the specified string. + */ + int kwdIndex(std::string kwd) const ; + + /*! \brief Return the value-keyword that is the current value of the + keyword parameter + */ + std::string kwdVal() const ; + + /*! \brief Set the value of the keyword parameter using the integer + associated with a value-keyword. + + If \p printIt is true, the corresponding value-keyword string will be + echoed to std::cout. + */ + void setKwdVal(int value, bool printIt = false) ; + + /*! \brief Set the value of the keyword parameter using a value-keyword + string. + + The given string will be tested against the set of value-keywords for + the parameter using the shortest match rules. + */ + void setKwdVal(const std::string value ) ; + + /*! \brief Prints the set of value-keywords defined for this keyword + parameter + */ + void printKwds() const ; + + + /*! \brief Set the value of a string parameter */ + + void setStrVal(std::string value) ; + + /*! \brief Get the value of a string parameter */ + + std::string strVal() const ; + + + /*! \brief Set the value of a double parameter */ + + void setDblVal(double value) ; + + /*! \brief Get the value of a double parameter */ + + double dblVal() const ; + + + /*! \brief Set the value of a integer parameter */ + + void setIntVal(int value) ; + + /*! \brief Get the value of a integer parameter */ + + int intVal() const ; + + + /*! \brief Add a short help string to a parameter */ + + inline void setShortHelp(const std::string help) { shortHelp_ = help ; } + + /*! \brief Retrieve the short help string */ + + inline std::string shortHelp() const { return (shortHelp_) ; } + + /*! \brief Add a long help message to a parameter + + See printLongHelp() for a description of how messages are broken into + lines. + */ + inline void setLongHelp(const std::string help) { longHelp_ = help ; } + + /*! \brief Retrieve the long help message */ + + inline std::string longHelp() const { return (longHelp_) ; } + + /*! \brief Print long help + + Prints the long help string, plus the valid range and/or keywords if + appropriate. The routine makes a best effort to break the message into + lines appropriate for an 80-character line. Explicit line breaks in the + message will be observed. The short help string will be used if + long help is not available. + */ + void printLongHelp() const ; + +//@} + +/*! \name Methods to query and manipulate a parameter object */ +//@{ + + /*! \brief Return the type of the parameter */ + + inline CoinParamType type() const { return (type_) ; } + + /*! \brief Set the type of the parameter */ + + inline void setType(CoinParamType type) { type_ = type ; } + + /*! \brief Return the parameter keyword (name) string */ + + inline std::string name() const { return (name_) ; } + + /*! \brief Set the parameter keyword (name) string */ + + inline void setName(std::string name) { name_ = name ; processName() ; } + + /*! \brief Check if the specified string matches the parameter keyword (name) + string + + Returns 1 if the string matches and meets the minimum match length, + 2 if the string matches but doesn't meet the minimum match length, + and 0 if the string doesn't match. Matches are \e not case-sensitive. + */ + int matches (std::string input) const ; + + /*! \brief Return the parameter keyword (name) string formatted to show + the minimum match length + + For example, if the parameter name was defined as allow!ableGap, the + string returned by matchName would be allow(ableGap). + */ + std::string matchName() const ; + + /*! \brief Set visibility of parameter + + Intended to control whether the parameter is shown when a list of + parameters is processed. Used by CoinParamUtils::printHelp when printing + help messages for a list of parameters. + */ + inline void setDisplay(bool display) { display_ = display ; } + + /*! \brief Get visibility of parameter */ + + inline bool display() const { return (display_) ; } + + /*! \brief Get push function */ + + inline CoinParamFunc pushFunc() { return (pushFunc_) ; } + + /*! \brief Set push function */ + + inline void setPushFunc(CoinParamFunc func) { pushFunc_ = func ; } + + /*! \brief Get pull function */ + + inline CoinParamFunc pullFunc() { return (pullFunc_) ; } + + /*! \brief Set pull function */ + + inline void setPullFunc(CoinParamFunc func) { pullFunc_ = func ; } + +//@} + +private: + +/*! \name Private methods */ +//@{ + + /*! Process a name for efficient matching */ + void processName() ; + +//@} + +/*! \name Private parameter data */ +//@{ + /// Parameter type (see #CoinParamType) + CoinParamType type_ ; + + /// Parameter name + std::string name_ ; + + /// Length of parameter name + size_t lengthName_ ; + + /*! \brief Minimum length required to declare a match for the parameter + name. + */ + size_t lengthMatch_ ; + + /// Lower bound on value for a double parameter + double lowerDblValue_ ; + + /// Upper bound on value for a double parameter + double upperDblValue_ ; + + /// Double parameter - current value + double dblValue_ ; + + /// Lower bound on value for an integer parameter + int lowerIntValue_ ; + + /// Upper bound on value for an integer parameter + int upperIntValue_ ; + + /// Integer parameter - current value + int intValue_ ; + + /// String parameter - current value + std::string strValue_ ; + + /// Set of valid value-keywords for a keyword parameter + std::vector<std::string> definedKwds_ ; + + /*! \brief Current value for a keyword parameter (index into #definedKwds_) + */ + int currentKwd_ ; + + /// Push function + CoinParamFunc pushFunc_ ; + + /// Pull function + CoinParamFunc pullFunc_ ; + + /// Short help + std::string shortHelp_ ; + + /// Long help + std::string longHelp_ ; + + /// Display when processing lists of parameters? + bool display_ ; +//@} + +} ; + +/*! \relatesalso CoinParam + \brief A type for a parameter vector. +*/ +typedef std::vector<CoinParam*> CoinParamVec ; + +/*! \relatesalso CoinParam + \brief A stream output function for a CoinParam object. +*/ +std::ostream &operator<< (std::ostream &s, const CoinParam ¶m) ; + +/* + Bring in the utility functions for parameter handling (CbcParamUtils). +*/ + +/*! \brief Utility functions for processing CoinParam parameters. + + The functions in CoinParamUtils support command line or interactive + parameter processing and a help facility. Consult the `Related Functions' + section of the CoinParam class documentation for individual function + documentation. +*/ +namespace CoinParamUtils { + /*! \relatesalso CoinParam + \brief Take command input from the file specified by src. + + Use stdin for \p src to specify interactive prompting for commands. + */ + void setInputSrc(FILE *src) ; + + /*! \relatesalso CoinParam + \brief Returns true if command line parameters are being processed. + */ + bool isCommandLine() ; + + /*! \relatesalso CoinParam + \brief Returns true if parameters are being obtained from stdin. + */ + bool isInteractive() ; + + /*! \relatesalso CoinParam + \brief Attempt to read a string from the input. + + \p argc and \p argv are used only if isCommandLine() would return true. + If \p valid is supplied, it will be set to 0 if a string is parsed + without error, 2 if no field is present. + */ + std::string getStringField(int argc, const char *argv[], int *valid) ; + + /*! \relatesalso CoinParam + \brief Attempt to read an integer from the input. + + \p argc and \p argv are used only if isCommandLine() would return true. + If \p valid is supplied, it will be set to 0 if an integer is parsed + without error, 1 if there's a parse error, and 2 if no field is present. + */ + int getIntField(int argc, const char *argv[], int *valid) ; + + /*! \relatesalso CoinParam + \brief Attempt to read a real (double) from the input. + + \p argc and \p argv are used only if isCommandLine() would return true. + If \p valid is supplied, it will be set to 0 if a real number is parsed + without error, 1 if there's a parse error, and 2 if no field is present. + */ + double getDoubleField(int argc, const char *argv[], int *valid) ; + + /*! \relatesalso CoinParam + \brief Scan a parameter vector for parameters whose keyword (name) string + matches \p name using minimal match rules. + + \p matchNdx is set to the index of the last parameter that meets the + minimal match criteria (but note there should be at most one matching + parameter if the parameter vector is properly configured). \p shortCnt + is set to the number of short matches (should be zero for a properly + configured parameter vector if a minimal match is found). The return + value is the number of matches satisfying the minimal match requirement + (should be 0 or 1 in a properly configured vector). + */ + int matchParam(const CoinParamVec ¶mVec, std::string name, + int &matchNdx, int &shortCnt) ; + + /*! \relatesalso CoinParam + \brief Get the next command keyword (name) + + To be precise, return the next field from the current command input + source, after a bit of processing. In command line mode (isCommandLine() + returns true) the next field will normally be of the form `-keyword' or + `--keyword' (\e i.e., a parameter keyword), and the string returned would + be `keyword'. In interactive mode (isInteractive() returns true), the + user will be prompted if necessary. It is assumed that the user knows + not to use the `-' or `--' prefixes unless specifying parameters on the + command line. + + There are a number of special cases if we're in command line mode. The + order of processing of the raw string goes like this: + <ul> + <li> A stand-alone `-' is forced to `stdin'. + <li> A stand-alone '--' is returned as a word; interpretation is up to + the client. + <li> A prefix of '-' or '--' is stripped from the string. + </ul> + If the result is the string `stdin', command processing shifts to + interactive mode and the user is immediately prompted for a new command. + + Whatever results from the above sequence is returned to the user as the + return value of the function. An empty string indicates end of input. + + \p prompt will be used only if it's necessary to prompt the user in + interactive mode. + */ + + std::string getCommand(int argc, const char *argv[], + const std::string prompt, std::string *pfx = 0) ; + + /*! \relatesalso CoinParam + \brief Look up the command keyword (name) in the parameter vector. + Print help if requested. + + In the most straightforward use, \p name is a string without `?', and the + value returned is the index in \p paramVec of the single parameter that + matched \p name. One or more '?' characters at the end of \p name is a + query for information. The routine prints short (one '?') or long (more + than one '?') help messages for a query. Help is also printed in the case + where the name is ambiguous (some of the matches did not meet the minimal + match length requirement). + + Note that multiple matches meeting the minimal match requirement is a + configuration error. The mimimal match length for the parameters + involved is too short. + + If provided as parameters, on return + <ul> + <li> \p matchCnt will be set to the number of matches meeting the + minimal match requirement + <li> \p shortCnt will be set to the number of matches that did not + meet the miminal match requirement + <li> \p queryCnt will be set to the number of '?' characters at the + end of the name + </ul> + + The return values are: + <ul> + <li> >0: index in \p paramVec of the single unique match for \p name + <li> -1: a query was detected (one or more '?' characters at the end + of \p name + <li> -2: one or more short matches, not a query + <li> -3: no matches, not a query + <li> -4: multiple matches meeting the minimal match requirement + (configuration error) + </ul> + */ + int lookupParam(std::string name, CoinParamVec ¶mVec, + int *matchCnt = 0, int *shortCnt = 0, int *queryCnt = 0) ; + + /*! \relatesalso CoinParam + \brief Utility to print a long message as filled lines of text + + The routine makes a best effort to break lines without exceeding the + standard 80 character line length. Explicit newlines in \p msg will + be obeyed. + */ + void printIt(const char *msg) ; + + /*! \relatesalso CoinParam + \brief Utility routine to print help given a short match or explicit + request for help. + + The two really are related, in that a query (a string that ends with + one or more `?' characters) will often result in a short match. The + routine expects that \p name matches a single parameter, and does not + look for multiple matches. + + If called with \p matchNdx < 0, the routine will look up \p name in \p + paramVec and print the full name from the parameter. If called with \p + matchNdx > 0, it just prints the name from the specified parameter. If + the name is a query, short (one '?') or long (more than one '?') help + is printed. + + */ void shortOrHelpOne(CoinParamVec ¶mVec,int matchNdx, std::string + name, int numQuery) ; + + /*! \relatesalso CoinParam + \brief Utility routine to print help given multiple matches. + + If the name is not a query, or asks for short help (\e i.e., contains + zero or one '?' characters), the list of matching names is printed. If + the name asks for long help (contains two or more '?' characters), + short help is printed for each matching name. + */ + void shortOrHelpMany(CoinParamVec ¶mVec, + std::string name, int numQuery) ; + + /*! \relatesalso CoinParam + \brief Print a generic `how to use the command interface' help message. + + The message is hard coded to match the behaviour of the parsing utilities. + */ + void printGenericHelp() ; + + /*! \relatesalso CoinParam + \brief Utility routine to print help messages for one or more + parameters. + + Intended as a utility to implement explicit `help' commands. Help will be + printed for all parameters in \p paramVec from \p firstParam to \p + lastParam, inclusive. If \p shortHelp is true, short help messages will + be printed. If \p longHelp is true, long help messages are printed. \p + shortHelp overrules \p longHelp. If neither is true, only command + keywords are printed. \p prefix is printed before each line; it's an + imperfect attempt at indentation. + */ + void printHelp(CoinParamVec ¶mVec, int firstParam, int lastParam, + std::string prefix, + bool shortHelp, bool longHelp, bool hidden) ; +} + + +#endif /* CoinParam_H */ + diff --git a/thirdparty/linux/include/coin/CoinPragma.hpp b/thirdparty/linux/include/coin/CoinPragma.hpp new file mode 100644 index 0000000..b9f8cd2 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPragma.hpp @@ -0,0 +1,26 @@ +/* $Id: CoinPragma.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPragma_H +#define CoinPragma_H + +//------------------------------------------------------------------- +// +// This is a file which can contain Pragma's that are +// generally applicable to any source file. +// +//------------------------------------------------------------------- + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +// Turn off compiler warning: +// "empty controlled statement found; is this the intent?" +# pragma warning(disable:4390) +// Turn off compiler warning about deprecated functions +# pragma warning(disable:4996) +#endif + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveDoubleton.hpp b/thirdparty/linux/include/coin/CoinPresolveDoubleton.hpp new file mode 100644 index 0000000..3ad8cd2 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveDoubleton.hpp @@ -0,0 +1,73 @@ +/* $Id: CoinPresolveDoubleton.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// 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). + +#ifndef CoinPresolveDoubleton_H +#define CoinPresolveDoubleton_H + +#define DOUBLETON 5 + +/*! \class doubleton_action + \brief Solve ax+by=c for y and substitute y out of the problem. + + This moves the bounds information for y onto x, making y free and allowing + us to substitute it away. + \verbatim + a x + b y = c + l1 <= x <= u1 + l2 <= y <= u2 ==> + + l2 <= (c - a x) / b <= u2 + b/-a > 0 ==> (b l2 - c) / -a <= x <= (b u2 - c) / -a + b/-a < 0 ==> (b u2 - c) / -a <= x <= (b l2 - c) / -a + \endverbatim +*/ +class doubleton_action : public CoinPresolveAction { + public: + struct action { + + double clox; + double cupx; + double costx; + + double costy; + + double rlo; + + double coeffx; + double coeffy; + + double *colel; + + int icolx; + int icoly; + int row; + int ncolx; + int ncoly; + }; + + const int nactions_; + const action *const actions_; + + private: + doubleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) +{} + + public: + const char *name() const { return ("doubleton_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~doubleton_action(); +}; +#endif + + diff --git a/thirdparty/linux/include/coin/CoinPresolveDual.hpp b/thirdparty/linux/include/coin/CoinPresolveDual.hpp new file mode 100644 index 0000000..b021ce0 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveDual.hpp @@ -0,0 +1,85 @@ +/* $Id: CoinPresolveDual.hpp 1510 2011-12-08 23:56:01Z lou $ */ + +// 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). + +#ifndef CoinPresolveDual_H +#define CoinPresolveDual_H + +/*! \class remove_dual_action + \brief Attempt to fix variables by bounding reduced costs + + The reduced cost of x_j is d_j = c_j - y*a_j (1). Assume minimization, + so that at optimality d_j >= 0 for x_j nonbasic at lower bound, and + d_j <= 0 for x_j nonbasic at upper bound. + + For a slack variable s_i, c_(n+i) = 0 and a_(n+i) is a unit vector, hence + d_(n+i) = -y_i. If s_i has a finite lower bound and no upper bound, we + must have y_i <= 0 at optimality. Similarly, if s_i has no lower bound and a + finite upper bound, we must have y_i >= 0. + + For a singleton variable x_j, d_j = c_j - y_i*a_ij. Given x_j with a + single finite bound, we can bound d_j greater or less than 0 at + optimality, and that allows us to calculate an upper or lower bound on y_i + (depending on the bound on d_j and the sign of a_ij). + + Now we have bounds on some subset of the y_i, and we can use these to + calculate upper and lower bounds on the d_j, using bound propagation on + (1). If we can manage to bound some d_j as strictly positive or strictly + negative, then at optimality the corresponding variable must be nonbasic + at its lower or upper bound, respectively. If the required bound is lacking, + the problem is unbounded. +*/ + +class remove_dual_action : public CoinPresolveAction { + + public: + + /// Destructor + ~remove_dual_action () ; + + /// Name + inline const char *name () const { return ("remove_dual_action") ; } + + /*! \brief Attempt to fix variables by bounding reduced costs + + Always scans all variables. Propagates bounds on reduced costs until there's + no change or until some set of variables can be fixed. + */ + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next) ; + + /*! \brief Postsolve + + In addition to fixing variables (handled by make_fixed_action), we may + need use our own postsolve to restore constraint bounds. + */ + void postsolve (CoinPostsolveMatrix *prob) const ; + + private: + + /// Postsolve (bound restore) instruction + struct action { + double rlo_ ; ///< restored row lower bound + double rup_ ; ///< restored row upper bound + int ndx_ ; ///< row index + } ; + + /// Constructor with postsolve actions. + remove_dual_action(int nactions, const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next), + nactions_(nactions), + actions_(actions) + {} + + /// Count of bound restore entries + const int nactions_ ; + /// Bound restore entries + const action *actions_ ; + +} ; +#endif + + diff --git a/thirdparty/linux/include/coin/CoinPresolveDupcol.hpp b/thirdparty/linux/include/coin/CoinPresolveDupcol.hpp new file mode 100644 index 0000000..16d3c91 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveDupcol.hpp @@ -0,0 +1,226 @@ +/* $Id: CoinPresolveDupcol.hpp 1817 2015-03-22 16:43:28Z 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). + +#ifndef CoinPresolveDupcol_H +#define CoinPresolveDupcol_H + +#include "CoinPresolveMatrix.hpp" + +/*! + \file +*/ + +#define DUPCOL 10 + +/*! \class dupcol_action + \brief Detect and remove duplicate columns + + The general technique is to sum the coefficients a_(*,j) of each column. + Columns with identical sums are duplicates. The obvious problem is that, + <i>e.g.</i>, [1 0 1 0] and [0 1 0 1] both add to 2. To minimize the + chances of false positives, the coefficients of each row are multipled by + a random number r_i, so that we sum r_i*a_ij. + + Candidate columns are checked to confirm they are identical. Where the + columns have the same objective coefficient, the two are combined. If the + columns have different objective coefficients, complications ensue. In order + to remove the duplicate, it must be possible to fix the variable at a bound. +*/ + +class dupcol_action : public CoinPresolveAction { + dupcol_action(); + dupcol_action(const dupcol_action& rhs); + dupcol_action& operator=(const dupcol_action& rhs); + + struct action { + double thislo; + double thisup; + double lastlo; + double lastup; + int ithis; + int ilast; + + double *colels; + int nincol; + }; + + const int nactions_; + // actions_ is owned by the class and must be deleted at destruction + const action *const actions_; + + dupcol_action(int nactions, const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), + actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~dupcol_action(); + +}; + + +/*! \class duprow_action + \brief Detect and remove duplicate rows + + The algorithm to detect duplicate rows is as outlined for dupcol_action. + + If the feasible interval for one constraint is strictly contained in the + other, the tighter (contained) constraint is kept. If the feasible + intervals are disjoint, the problem is infeasible. If the feasible + intervals overlap, both constraints are kept. + + duprow_action is definitely a work in progress; #postsolve is + unimplemented. + This doesn't matter as it uses useless_constraint. +*/ + +class duprow_action : public CoinPresolveAction { + struct action { + int row; + double lbound; + double ubound; + }; + + const int nactions_; + const action *const actions_; + + duprow_action():CoinPresolveAction(NULL),nactions_(0),actions_(NULL) {} + duprow_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + //~duprow_action() { delete[]actions_; } +}; + +class duprow3_action : public CoinPresolveAction { + struct action { + int row; + double lbound; + double ubound; + }; + + const int nactions_; + const action *const actions_; + + duprow3_action():CoinPresolveAction(NULL),nactions_(0),actions_(NULL) {} + duprow3_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + //~duprow_action() { delete[]actions_; } +}; + +/*! \class gubrow_action + \brief Detect and remove entries whose sum is known + + If we have an equality row where all entries same then + For other rows where all entries for that equality row are same + then we can delete entries and modify rhs + gubrow_action is definitely a work in progress; #postsolve is + unimplemented. +*/ + +class gubrow_action : public CoinPresolveAction { + struct action { + int row; + double lbound; + double ubound; + }; + + const int nactions_; + const action *const actions_; + + gubrow_action():CoinPresolveAction(NULL),nactions_(0),actions_(NULL) {} + gubrow_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + //~gubrow_action() { delete[]actions_; } +}; + +/*! \class twoxtwo_action + \brief Detect interesting 2 by 2 blocks + + If a variable has two entries and for each row there are only + two entries with same other variable then we can get rid of + one constraint and modify costs. + + This is a work in progress - I need more examples +*/ + +class twoxtwo_action : public CoinPresolveAction { + struct action { + double lbound_row; + double ubound_row; + double lbound_col; + double ubound_col; + double cost_col; + double cost_othercol; + int row; + int col; + int othercol; + }; + + const int nactions_; + const action *const actions_; + + twoxtwo_action():CoinPresolveAction(NULL),nactions_(0),actions_(NULL) {} + twoxtwo_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + ~twoxtwo_action() { delete [] actions_; } +}; + +#endif + diff --git a/thirdparty/linux/include/coin/CoinPresolveEmpty.hpp b/thirdparty/linux/include/coin/CoinPresolveEmpty.hpp new file mode 100644 index 0000000..336f1fd --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveEmpty.hpp @@ -0,0 +1,116 @@ +/* $Id: CoinPresolveEmpty.hpp 1561 2012-11-24 00:32:16Z lou $ */ +// 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). + +#ifndef CoinPresolveEmpty_H +#define CoinPresolveEmpty_H + +/*! \file + + Drop/reinsert empty rows/columns. +*/ + +const int DROP_ROW = 3; +const int DROP_COL = 4; + +/*! \class drop_empty_cols_action + \brief Physically removes empty columns in presolve, and reinserts + empty columns in postsolve. + + Physical removal of rows and columns should be the last activities + performed during presolve. Do them exactly once. The row-major matrix + is <b>not</b> maintained by this transform. + + To physically drop the columns, CoinPrePostsolveMatrix::mcstrt_ and + CoinPrePostsolveMatrix::hincol_ are compressed, along with column bounds, + objective, and (if present) the column portions of the solution. This + renumbers the columns. drop_empty_cols_action::presolve will reconstruct + CoinPresolveMatrix::clink_. + + \todo Confirm correct behaviour with solution in presolve. +*/ + +class drop_empty_cols_action : public CoinPresolveAction { +private: + const int nactions_; + + struct action { + double clo; + double cup; + double cost; + double sol; + int jcol; + }; + const action *const actions_; + + drop_empty_cols_action(int nactions, + const action *const actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), + actions_(actions) + {} + + public: + const char *name() const { return ("drop_empty_cols_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *, + const int *ecols, + int necols, + const CoinPresolveAction*); + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~drop_empty_cols_action() { deleteAction(actions_,action*); } +}; + + +/*! \class drop_empty_rows_action + \brief Physically removes empty rows in presolve, and reinserts + empty rows in postsolve. + + Physical removal of rows and columns should be the last activities + performed during presolve. Do them exactly once. The row-major matrix + is <b>not</b> maintained by this transform. + + To physically drop the rows, the rows are renumbered, excluding empty + rows. This involves rewriting CoinPrePostsolveMatrix::hrow_ and compressing + the row bounds and (if present) the row portions of the solution. + + \todo Confirm behaviour when a solution is present in presolve. +*/ +class drop_empty_rows_action : public CoinPresolveAction { +private: + struct action { + double rlo; + double rup; + int row; + int fill_row; // which row was moved into position row to fill it + }; + + const int nactions_; + const action *const actions_; + + drop_empty_rows_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) +{} + + public: + const char *name() const { return ("drop_empty_rows_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~drop_empty_rows_action() { deleteAction(actions_,action*); } +}; +#endif + diff --git a/thirdparty/linux/include/coin/CoinPresolveFixed.hpp b/thirdparty/linux/include/coin/CoinPresolveFixed.hpp new file mode 100644 index 0000000..dc59207 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveFixed.hpp @@ -0,0 +1,181 @@ +/* $Id: CoinPresolveFixed.hpp 1510 2011-12-08 23:56:01Z lou $ */ +// 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). + +#ifndef CoinPresolveFixed_H +#define CoinPresolveFixed_H +#define FIXED_VARIABLE 1 + +/*! \class remove_fixed_action + \brief Excise fixed variables from the model. + + Implements the action of virtually removing one or more fixed variables + x_j from the model by substituting the value sol_j in each constraint. + Specifically, for each constraint i where a_ij != 0, rlo_i and rup_i + are adjusted by -a_ij*sol_j and a_ij is set to 0. + + There is an implicit assumption that the variable already has the correct + value. If this isn't true, corrections to row activity may be incorrect. + If you want to guard against this possibility, consider make_fixed_action. + + Actual removal of the empty column from the matrix is handled by + drop_empty_cols_action. Correction of the objective function is done there. +*/ +class remove_fixed_action : public CoinPresolveAction { + public: + /*! \brief Structure to hold information necessary to reintroduce a + column into the problem representation. + */ + struct action { + int col; ///< column index of variable + int start; ///< start of coefficients in #colels_ and #colrows_ + double sol; ///< value of variable + }; + /// Array of row indices for coefficients of excised columns + int *colrows_; + /// Array of coefficients of excised columns + double *colels_; + /// Number of entries in #actions_ + int nactions_; + /// Vector specifying variable(s) affected by this object + action *actions_; + + private: + /*! \brief Constructor */ + remove_fixed_action(int nactions, + action *actions, + double * colels, + int * colrows, + const CoinPresolveAction *next); + + public: + /// Returns string "remove_fixed_action". + const char *name() const; + + /*! \brief Excise the specified columns. + + Remove the specified columns (\p nfcols, \p fcols) from the problem + representation (\p prob), leaving the appropriate postsolve object + linked as the head of the list of postsolve objects (currently headed + by \p next). + */ + static const remove_fixed_action *presolve(CoinPresolveMatrix *prob, + int *fcols, + int nfcols, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + /// Destructor + virtual ~remove_fixed_action(); +}; + + +/*! \relates remove_fixed_action + \brief Scan the problem for fixed columns and remove them. + + A front end to collect a list of columns with equal bounds and hand them to + remove_fixed_action::presolve() for processing. +*/ + +const CoinPresolveAction *remove_fixed(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + +/*! \class make_fixed_action + \brief Fix a variable at a specified bound. + + Implements the action of fixing a variable by forcing both bounds to the same + value and forcing the value of the variable to match. + + If the bounds are already equal, and the value of the variable is already + correct, consider remove_fixed_action. +*/ +class make_fixed_action : public CoinPresolveAction { + + /// Structure to preserve the bound overwritten when fixing a variable + struct action { + double bound; ///< Value of bound overwritten to fix variable. + int col ; ///< column index of variable + }; + + /// Number of preserved bounds + int nactions_; + /// Vector of preserved bounds, one for each variable fixed in this object + const action *actions_; + + /*! \brief True to fix at lower bound, false to fix at upper bound. + + Note that this applies to all variables fixed in this object. + */ + const bool fix_to_lower_; + + /*! \brief The postsolve object with the information required to repopulate + the fixed columns. + */ + const remove_fixed_action *faction_; + + /*! \brief Constructor */ + make_fixed_action(int nactions, const action *actions, bool fix_to_lower, + const remove_fixed_action *faction, + const CoinPresolveAction *next) + : CoinPresolveAction(next), + nactions_(nactions), actions_(actions), + fix_to_lower_(fix_to_lower), + faction_(faction) + {} + + public: + /// Returns string "make_fixed_action". + const char *name() const; + + /*! \brief Perform actions to fix variables and return postsolve object + + For each specified variable (\p nfcols, \p fcols), fix the variable to + the specified bound (\p fix_to_lower) by setting the variable's bounds + to be equal in \p prob. Create a postsolve object, link it at the head of + the list of postsolve objects (\p next), and return the object. + */ + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + int *fcols, + int nfcols, + bool fix_to_lower, + const CoinPresolveAction *next); + + /*! \brief Postsolve (unfix variables) + + Back out the variables fixed by the presolve side of this object. + */ + void postsolve(CoinPostsolveMatrix *prob) const; + + /// Destructor + virtual ~make_fixed_action() { + deleteAction(actions_,action*); + delete faction_; + } +}; + +/*! \relates make_fixed_action + \brief Scan variables and fix any with equal bounds + + A front end to collect a list of columns with equal bounds and hand them to + make_fixed_action::presolve() for processing. +*/ + +const CoinPresolveAction *make_fixed(CoinPresolveMatrix *prob, + const CoinPresolveAction *next) ; + +/*! \brief Transfer costs from singleton variables + \relates make_fixed_action + + Transfers costs from singleton variables in equalities onto the other + variables. Will also transfer costs from one integer variable to other + integer variables with zero cost if there's a net gain in integer variables + with non-zero cost. + + The relation to make_fixed_action is tenuous, but this transform should be + attempted before the initial round of variable fixing. +*/ +void transferCosts(CoinPresolveMatrix * prob); +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveForcing.hpp b/thirdparty/linux/include/coin/CoinPresolveForcing.hpp new file mode 100644 index 0000000..ee5a641 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveForcing.hpp @@ -0,0 +1,61 @@ +/* $Id: CoinPresolveForcing.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// 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). + +#ifndef CoinPresolveForcing_H +#define CoinPresolveForcing_H + +#include "CoinPresolveMatrix.hpp" + +/*! + \file +*/ + +#define IMPLIED_BOUND 7 + +/*! \class forcing_constraint_action + \brief Detect and process forcing constraints and useless constraints + + A constraint is useless if the bounds on the variables prevent the constraint + from ever being violated. + + A constraint is a forcing constraint if the bounds on the constraint force + the value of an involved variable to one of its bounds. A constraint can + force more than one variable. +*/ +class forcing_constraint_action : public CoinPresolveAction { + forcing_constraint_action(); + forcing_constraint_action(const forcing_constraint_action& rhs); + forcing_constraint_action& operator=(const forcing_constraint_action& rhs); +public: + struct action { + const int *rowcols; + const double *bounds; + int row; + int nlo; + int nup; + }; +private: + const int nactions_; + // actions_ is owned by the class and must be deleted at destruction + const action *const actions_; + +public: + forcing_constraint_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix * prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~forcing_constraint_action(); +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveImpliedFree.hpp b/thirdparty/linux/include/coin/CoinPresolveImpliedFree.hpp new file mode 100644 index 0000000..8215b98 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveImpliedFree.hpp @@ -0,0 +1,60 @@ +/* $Id: CoinPresolveImpliedFree.hpp 1694 2014-04-29 02:08:35Z tkr $ */ +// 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). + +#ifndef CoinPresolveImpliedFree_H +#define CoinPresolveImpliedFree_H + +/*! + \file +*/ + +#define IMPLIED_FREE 9 + +/*! \class implied_free_action + \brief Detect and process implied free variables + + Consider a singleton variable x (<i>i.e.</i>, a variable involved in only + one constraint). Suppose that the bounds on that constraint, combined with + the bounds on the other variables involved in the constraint, are such that + even the worst case values of the other variables still imply bounds for x + which are tighter than the variable's original bounds. Since x can never + reach its upper or lower bounds, it is an implied free variable. Both x and + the constraint can be deleted from the problem. + + A similar transform for the case where the variable is not a natural column + singleton is handled by #subst_constraint_action. +*/ +class implied_free_action : public CoinPresolveAction { + struct action { + int row, col; + double clo, cup; + double rlo, rup; + const double *rowels; + const double *costs; + int ninrow; + }; + + const int nactions_; + const action *const actions_; + + implied_free_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix * prob, + const CoinPresolveAction *next, + int & fillLevel); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~implied_free_action(); +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveIsolated.hpp b/thirdparty/linux/include/coin/CoinPresolveIsolated.hpp new file mode 100644 index 0000000..38c700f --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveIsolated.hpp @@ -0,0 +1,51 @@ +/* $Id: CoinPresolveIsolated.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// 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). + +#ifndef CoinPresolveIsolated_H +#define CoinPresolveIsolated_H + +#include "CoinPresolveMatrix.hpp" + +class isolated_constraint_action : public CoinPresolveAction { + isolated_constraint_action(); + isolated_constraint_action(const isolated_constraint_action& rhs); + isolated_constraint_action& operator=(const isolated_constraint_action& rhs); + + double rlo_; + double rup_; + int row_; + int ninrow_; + // the arrays are owned by the class and must be deleted at destruction + const int *rowcols_; + const double *rowels_; + const double *costs_; + + isolated_constraint_action(double rlo, + double rup, + int row, + int ninrow, + const int *rowcols, + const double *rowels, + const double *costs, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + rlo_(rlo), rup_(rup), row_(row), ninrow_(ninrow), + rowcols_(rowcols), rowels_(rowels), costs_(costs) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix * prob, + int row, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~isolated_constraint_action(); +}; + + + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveMatrix.hpp b/thirdparty/linux/include/coin/CoinPresolveMatrix.hpp new file mode 100644 index 0000000..e608738 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveMatrix.hpp @@ -0,0 +1,1842 @@ +/* $Id: CoinPresolveMatrix.hpp 1761 2014-12-10 09:43:07Z 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). + +#ifndef CoinPresolveMatrix_H +#define CoinPresolveMatrix_H + +#include "CoinPragma.hpp" +#include "CoinPackedMatrix.hpp" +#include "CoinMessage.hpp" +#include "CoinTime.hpp" + +#include <cmath> +#include <cassert> +#include <cfloat> +#include <cassert> +#include <cstdlib> + +#if PRESOLVE_DEBUG > 0 +#include "CoinFinite.hpp" +#endif + +/*! \file + + Declarations for CoinPresolveMatrix and CoinPostsolveMatrix and their + common base class CoinPrePostsolveMatrix. Also declarations for + CoinPresolveAction and a number of non-member utility functions. +*/ + + +#if defined(_MSC_VER) +// Avoid MS Compiler problem in recognizing type to delete +// by casting to type. +// Is this still necessary? -- lh, 111202 -- +#define deleteAction(array,type) delete [] ((type) array) +#else +#define deleteAction(array,type) delete [] array +#endif + +/* + Define PRESOLVE_DEBUG and PRESOLVE_CONSISTENCY on the configure command + line or in a Makefile! See comments in CoinPresolvePsdebug.hpp. +*/ +#if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 + +#define PRESOLVE_STMT(s) s + +#define PRESOLVEASSERT(x) \ + ((x) ? 1 : ((std::cerr << "FAILED ASSERTION at line " \ + << __LINE__ << ": " #x "\n"), abort(), 0)) + +inline void DIE(const char *s) { std::cout << s ; abort() ; } + +/*! \brief Indicate column or row present at start of postsolve + + This code is used during postsolve in [cr]done to indicate columns and rows + that are present in the presolved system (i.e., present at the start of + postsolve processing). + + \todo + There are a bunch of these code definitions, scattered through presolve + files. They should be collected in one place. +*/ +#define PRESENT_IN_REDUCED '\377' + +#else + +#define PRESOLVEASSERT(x) {} +#define PRESOLVE_STMT(s) {} + +inline void DIE(const char *) {} + +#endif + +/* + Unclear why these are separate from standard debug. +*/ +#ifndef PRESOLVE_DETAIL +#define PRESOLVE_DETAIL_PRINT(s) {} +#else +#define PRESOLVE_DETAIL_PRINT(s) s +#endif + +/*! \brief Zero tolerance + + OSL had a fixed zero tolerance; we still use that here. +*/ +const double ZTOLDP = 1e-12 ; +/*! \brief Alternate zero tolerance + + Use a different one if we are doing doubletons, etc. +*/ +const double ZTOLDP2 = 1e-10 ; + +/// The usual finite infinity +#define PRESOLVE_INF COIN_DBL_MAX +/// And a small infinity +#define PRESOLVE_SMALL_INF 1.0e20 +/// Check for infinity using finite infinity +#define PRESOLVEFINITE(n) (-PRESOLVE_INF < (n) && (n) < PRESOLVE_INF) + + +class CoinPostsolveMatrix ; + +/*! \class CoinPresolveAction + \brief Abstract base class of all presolve routines. + + The details will make more sense after a quick overview of the grand plan: + A presolve object is handed a problem object, which it is expected to + modify in some useful way. Assuming that it succeeds, the presolve object + should create a postsolve object, <i>i.e.</i>, an object that contains + instructions for backing out the presolve transform to recover the original + problem. These postsolve objects are accumulated in a linked list, with each + successive presolve action adding its postsolve action to the head of the + list. The end result of all this is a presolved problem object, and a list + of postsolve objects. The presolved problem object is then handed to a + solver for optimization, and the problem object augmented with the + results. The list of postsolve objects is then traversed. Each of them + (un)modifies the problem object, with the end result being the original + problem, augmented with solution information. + + The problem object representation is CoinPrePostsolveMatrix and subclasses. + Check there for details. The \c CoinPresolveAction class and subclasses + represent the presolve and postsolve objects. + + In spite of the name, the only information held in a \c CoinPresolveAction + object is the information needed to postsolve (<i>i.e.</i>, the information + needed to back out the presolve transformation). This information is not + expected to change, so the fields are all \c const. + + A subclass of \c CoinPresolveAction, implementing a specific pre/postsolve + action, is expected to declare a static function that attempts to perform a + presolve transformation. This function will be handed a CoinPresolveMatrix + to transform, and a pointer to the head of the list of postsolve objects. + If the transform is successful, the function will create a new + \c CoinPresolveAction object, link it at the head of the list of postsolve + objects, and return a pointer to the postsolve object it has just created. + Otherwise, it should return 0. It is expected that these static functions + will be the only things that can create new \c CoinPresolveAction objects; + this is expressed by making each subclass' constructor(s) private. + + Every subclass must also define a \c postsolve method. + This function will be handed a CoinPostsolveMatrix to transform. + + It is the client's responsibility to implement presolve and postsolve driver + routines. See OsiPresolve for examples. + + \note Since the only fields in a \c CoinPresolveAction are \c const, anything + one can do with a variable declared \c CoinPresolveAction* can also be + done with a variable declared \c const \c CoinPresolveAction* It is + expected that all derived subclasses of \c CoinPresolveAction also have + this property. +*/ +class CoinPresolveAction +{ + public: + /*! \brief Stub routine to throw exceptions. + + Exceptions are inefficient, particularly with g++. Even with xlC, the + use of exceptions adds a long prologue to a routine. Therefore, rather + than use throw directly in the routine, I use it in a stub routine. + */ + static void throwCoinError(const char *error, const char *ps_routine) + { throw CoinError(error, ps_routine, "CoinPresolve"); } + + /*! \brief The next presolve transformation + + Set at object construction. + */ + const CoinPresolveAction *next; + + /*! \brief Construct a postsolve object and add it to the transformation list. + + This is an `add to head' operation. This object will point to the + one passed as the parameter. + */ + CoinPresolveAction(const CoinPresolveAction *next) : next(next) {} + /// modify next (when building rather than passing) + inline void setNext(const CoinPresolveAction *nextAction) + { next = nextAction;} + + /*! \brief A name for debug printing. + + It is expected that the name is not stored in the transform itself. + */ + virtual const char *name() const = 0; + + /*! \brief Apply the postsolve transformation for this particular + presolve action. + */ + virtual void postsolve(CoinPostsolveMatrix *prob) const = 0; + + /*! \brief Virtual destructor. */ + virtual ~CoinPresolveAction() {} +}; + +/* + These are needed for OSI-aware constructors associated with + CoinPrePostsolveMatrix, CoinPresolveMatrix, and CoinPostsolveMatrix. +*/ +class ClpSimplex; +class OsiSolverInterface; + +/* + CoinWarmStartBasis is required for methods in CoinPrePostsolveMatrix + that accept/return a CoinWarmStartBasis object. +*/ +class CoinWarmStartBasis ; + +/*! \class CoinPrePostsolveMatrix + \brief Collects all the information about the problem that is needed + in both presolve and postsolve. + + In a bit more detail, a column-major representation of the constraint + matrix and upper and lower bounds on variables and constraints, plus row + and column solutions, reduced costs, and status. There's also a set of + arrays holding the original row and column numbers. + + As presolve and postsolve transform the matrix, it will occasionally be + necessary to expand the number of entries in a column. There are two + aspects: + <ul> + <li> During postsolve, the constraint system is expected to grow as + the smaller presolved system is transformed back to the original + system. + <li> During both pre- and postsolve, transforms can increase the number + of coefficients in a row or column. (See the + variable substitution, doubleton, and tripleton transforms.) + </ul> + + The first is addressed by the members #ncols0_, #nrows0_, and #nelems0_. + These should be set (via constructor parameters) to values large enough + for the largest size taken on by the constraint system. Typically, this + will be the size of the original constraint system. + + The second is addressed by a generous allocation of extra (empty) space + for the arrays used to hold coefficients and row indices. When columns + must be expanded, they are moved into the empty space. When it is used up, + the arrays are compacted. When compaction fails to produce sufficient + space, presolve/postsolve will fail. + + CoinPrePostsolveMatrix isn't really intended to be used `bare' --- the + expectation is that it'll be used through CoinPresolveMatrix or + CoinPostsolveMatrix. Some of the functions needed to load a problem are + defined in the derived classes. + + When CoinPresolve is applied when reoptimising, we need to be prepared to + accept a basis and modify it in step with the presolve actions (otherwise + we throw away all the advantages of warm start for reoptimization). But + other solution components (#acts_, #rowduals_, #sol_, and #rcosts_) are + needed only for postsolve, where they're used in places to determine the + proper action(s) when restoring rows or columns. If presolve is provided + with a solution, it will modify it in step with the presolve actions. + Moving the solution components from CoinPrePostsolveMatrix to + CoinPostsolveMatrix would break a lot of code. It's not clear that it's + worth it, and it would preclude upgrades to the presolve side that might + make use of any of these. -- lh, 080501 -- + + The constructors that take an OSI or ClpSimplex as a parameter really should + not be here, but for historical reasons they will likely remain for the + forseeable future. -- lh, 111202 -- +*/ + +class CoinPrePostsolveMatrix +{ + public: + + /*! \name Constructors & Destructors */ + + //@{ + /*! \brief `Native' constructor + + This constructor creates an empty object which must then be loaded. On + the other hand, it doesn't assume that the client is an + OsiSolverInterface. + */ + CoinPrePostsolveMatrix(int ncols_alloc, int nrows_alloc, + CoinBigIndex nelems_alloc) ; + + /*! \brief Generic OSI constructor + + See OSI code for the definition. + */ + CoinPrePostsolveMatrix(const OsiSolverInterface * si, + int ncols_, + int nrows_, + CoinBigIndex nelems_); + + /*! ClpOsi constructor + + See Clp code for the definition. + */ + CoinPrePostsolveMatrix(const ClpSimplex * si, + int ncols_, + int nrows_, + CoinBigIndex nelems_, + double bulkRatio); + + /// Destructor + ~CoinPrePostsolveMatrix(); + //@} + + /*! \brief Enum for status of various sorts + + Matches CoinWarmStartBasis::Status and adds superBasic. Most code that + converts between CoinPrePostsolveMatrix::Status and + CoinWarmStartBasis::Status will break if this correspondence is broken. + + superBasic is an unresolved problem: there's no analogue in + CoinWarmStartBasis::Status. + */ + enum Status { + isFree = 0x00, + basic = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03, + superBasic = 0x04 + }; + + /*! \name Functions to work with variable status + + Functions to work with the CoinPrePostsolveMatrix::Status enum and + related vectors. + + \todo + Why are we futzing around with three bit status? A holdover from the + packed arrays of CoinWarmStartBasis? Big swaths of the presolve code + manipulates colstat_ and rowstat_ as unsigned char arrays using simple + assignment to set values. + */ + //@{ + + /// Set row status (<i>i.e.</i>, status of artificial for this row) + inline void setRowStatus(int sequence, Status status) + { + unsigned char & st_byte = rowstat_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & (~7)) ; + st_byte = static_cast<unsigned char>(st_byte | status) ; + } + /// Get row status + inline Status getRowStatus(int sequence) const + {return static_cast<Status> (rowstat_[sequence]&7);} + /// Check if artificial for this row is basic + inline bool rowIsBasic(int sequence) const + {return (static_cast<Status> (rowstat_[sequence]&7)==basic);} + /// Set column status (<i>i.e.</i>, status of primal variable) + inline void setColumnStatus(int sequence, Status status) + { + unsigned char & st_byte = colstat_[sequence]; + st_byte = static_cast<unsigned char>(st_byte & (~7)) ; + st_byte = static_cast<unsigned char>(st_byte | status) ; + +# ifdef PRESOLVE_DEBUG + switch (status) + { case isFree: + { if (clo_[sequence] > -PRESOLVE_INF || cup_[sequence] < PRESOLVE_INF) + { std::cout << "Bad status: Var " << sequence + << " isFree, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl ; } + break ; } + case basic: + { break ; } + case atUpperBound: + { if (cup_[sequence] >= PRESOLVE_INF) + { std::cout << "Bad status: Var " << sequence + << " atUpperBound, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl ; } + break ; } + case atLowerBound: + { if (clo_[sequence] <= -PRESOLVE_INF) + { std::cout << "Bad status: Var " << sequence + << " atLowerBound, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl ; } + break ; } + case superBasic: + { if (clo_[sequence] <= -PRESOLVE_INF && cup_[sequence] >= PRESOLVE_INF) + { std::cout << "Bad status: Var " << sequence + << " superBasic, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl ; } + break ; } + default: + { assert(false) ; + break ; } } +# endif + } + /// Get column (structural variable) status + inline Status getColumnStatus(int sequence) const + {return static_cast<Status> (colstat_[sequence]&7);} + /// Check if column (structural variable) is basic + inline bool columnIsBasic(int sequence) const + {return (static_cast<Status> (colstat_[sequence]&7)==basic);} + /*! \brief Set status of row (artificial variable) to the correct nonbasic + status given bounds and current value + */ + void setRowStatusUsingValue(int iRow); + /*! \brief Set status of column (structural variable) to the correct + nonbasic status given bounds and current value + */ + void setColumnStatusUsingValue(int iColumn); + /*! \brief Set column (structural variable) status vector */ + void setStructuralStatus(const char *strucStatus, int lenParam) ; + /*! \brief Set row (artificial variable) status vector */ + void setArtificialStatus(const char *artifStatus, int lenParam) ; + /*! \brief Set the status of all variables from a basis */ + void setStatus(const CoinWarmStartBasis *basis) ; + /*! \brief Get status in the form of a CoinWarmStartBasis */ + CoinWarmStartBasis *getStatus() ; + /*! \brief Return a print string for status of a column (structural + variable) + */ + const char *columnStatusString(int j) const ; + /*! \brief Return a print string for status of a row (artificial + variable) + */ + const char *rowStatusString(int i) const ; + //@} + + /*! \name Functions to load problem and solution information + + These functions can be used to load portions of the problem definition + and solution. See also the CoinPresolveMatrix and CoinPostsolveMatrix + classes. + */ + //@{ + /// Set the objective function offset for the original system. + void setObjOffset(double offset) ; + /*! \brief Set the objective sense (max/min) + + Coded as 1.0 for min, -1.0 for max. + Yes, there's a method, and a matching attribute. No, you really + don't want to set this to maximise. + */ + void setObjSense(double objSense) ; + /// Set the primal feasibility tolerance + void setPrimalTolerance(double primTol) ; + /// Set the dual feasibility tolerance + void setDualTolerance(double dualTol) ; + /// Set column lower bounds + void setColLower(const double *colLower, int lenParam) ; + /// Set column upper bounds + void setColUpper(const double *colUpper, int lenParam) ; + /// Set column solution + void setColSolution(const double *colSol, int lenParam) ; + /// Set objective coefficients + void setCost(const double *cost, int lenParam) ; + /// Set reduced costs + void setReducedCost(const double *redCost, int lenParam) ; + /// Set row lower bounds + void setRowLower(const double *rowLower, int lenParam) ; + /// Set row upper bounds + void setRowUpper(const double *rowUpper, int lenParam) ; + /// Set row solution + void setRowPrice(const double *rowSol, int lenParam) ; + /// Set row activity + void setRowActivity(const double *rowAct, int lenParam) ; + //@} + + /*! \name Functions to retrieve problem and solution information */ + //@{ + /// Get current number of columns + inline int getNumCols() const + { return (ncols_) ; } + /// Get current number of rows + inline int getNumRows() const + { return (nrows_) ; } + /// Get current number of non-zero coefficients + inline int getNumElems() const + { return (nelems_) ; } + /// Get column start vector for column-major packed matrix + inline const CoinBigIndex *getColStarts() const + { return (mcstrt_) ; } + /// Get column length vector for column-major packed matrix + inline const int *getColLengths() const + { return (hincol_) ; } + /// Get vector of row indices for column-major packed matrix + inline const int *getRowIndicesByCol() const + { return (hrow_) ; } + /// Get vector of elements for column-major packed matrix + inline const double *getElementsByCol() const + { return (colels_) ; } + /// Get column lower bounds + inline const double *getColLower() const + { return (clo_) ; } + /// Get column upper bounds + inline const double *getColUpper() const + { return (cup_) ; } + /// Get objective coefficients + inline const double *getCost() const + { return (cost_) ; } + /// Get row lower bounds + inline const double *getRowLower() const + { return (rlo_) ; } + /// Get row upper bounds + inline const double *getRowUpper() const + { return (rup_) ; } + /// Get column solution (primal variable values) + inline const double *getColSolution() const + { return (sol_) ; } + /// Get row activity (constraint lhs values) + inline const double *getRowActivity() const + { return (acts_) ; } + /// Get row solution (dual variables) + inline const double *getRowPrice() const + { return (rowduals_) ; } + /// Get reduced costs + inline const double *getReducedCost() const + { return (rcosts_) ; } + /// Count empty columns + inline int countEmptyCols() + { int empty = 0 ; + for (int i = 0 ; i < ncols_ ; i++) if (hincol_[i] == 0) empty++ ; + return (empty) ; } + //@} + + + /*! \name Message handling */ + //@{ + /// Return message handler + inline CoinMessageHandler *messageHandler() const + { return handler_; } + /*! \brief Set message handler + + The client retains responsibility for the handler --- it will not be + destroyed with the \c CoinPrePostsolveMatrix object. + */ + inline void setMessageHandler(CoinMessageHandler *handler) + { if (defaultHandler_ == true) + { delete handler_ ; + defaultHandler_ = false ; } + handler_ = handler ; } + /// Return messages + inline CoinMessages messages() const + { return messages_; } + //@} + + /*! \name Current and Allocated Size + + During pre- and postsolve, the matrix will change in size. During presolve + it will shrink; during postsolve it will grow. Hence there are two sets of + size variables, one for the current size and one for the allocated size. + (See the general comments for the CoinPrePostsolveMatrix class for more + information.) + */ + //@{ + + /// current number of columns + int ncols_; + /// current number of rows + int nrows_; + /// current number of coefficients + CoinBigIndex nelems_; + + /// Allocated number of columns + int ncols0_; + /// Allocated number of rows + int nrows0_ ; + /// Allocated number of coefficients + CoinBigIndex nelems0_ ; + /*! \brief Allocated size of bulk storage for row indices and coefficients + + This is the space allocated for hrow_ and colels_. This must be large + enough to allow columns to be copied into empty space when they need to + be expanded. For efficiency (to minimize the number of times the + representation must be compressed) it's recommended that this be at least + 2*nelems0_. + */ + CoinBigIndex bulk0_ ; + /// Ratio of bulk0_ to nelems0_; default is 2. + double bulkRatio_; + //@} + + /*! \name Problem representation + + The matrix is the common column-major format: A pair of vectors with + positional correspondence to hold coefficients and row indices, and a + second pair of vectors giving the starting position and length of each + column in the first pair. + */ + //@{ + /// Vector of column start positions in #hrow_, #colels_ + CoinBigIndex *mcstrt_; + /// Vector of column lengths + int *hincol_; + /// Row indices (positional correspondence with #colels_) + int *hrow_; + /// Coefficients (positional correspondence with #hrow_) + double *colels_; + + /// Objective coefficients + double *cost_; + /// Original objective offset + double originalOffset_; + + /// Column (primal variable) lower bounds + double *clo_; + /// Column (primal variable) upper bounds + double *cup_; + + /// Row (constraint) lower bounds + double *rlo_; + /// Row (constraint) upper bounds + double *rup_; + + /*! \brief Original column numbers + + Over the current range of column numbers in the presolved problem, + the entry for column j will contain the index of the corresponding + column in the original problem. + */ + int * originalColumn_; + /*! \brief Original row numbers + + Over the current range of row numbers in the presolved problem, the + entry for row i will contain the index of the corresponding row in + the original problem. + */ + int * originalRow_; + + /// Primal feasibility tolerance + double ztolzb_; + /// Dual feasibility tolerance + double ztoldj_; + + /*! \brief Maximization/minimization + + Yes, there's a variable here. No, you really don't want to set this to + maximise. See the main notes for CoinPresolveMatrix. + */ + double maxmin_; + //@} + + /*! \name Problem solution information + + The presolve phase will work without any solution information + (appropriate for initial optimisation) or with solution information + (appropriate for reoptimisation). When solution information is supplied, + presolve will maintain it to the best of its ability. #colstat_ is + checked to determine the presence/absence of status information. #sol_ is + checked for primal solution information, and #rowduals_ for dual solution + information. + + The postsolve phase requires the complete solution information from the + presolved problem (status, primal and dual solutions). It will be + transformed into a correct solution for the original problem. + */ + //@{ + /*! \brief Vector of primal variable values + + If #sol_ exists, it is assumed that primal solution information should be + updated and that #acts_ also exists. + */ + double *sol_; + /*! \brief Vector of dual variable values + + If #rowduals_ exists, it is assumed that dual solution information should + be updated and that #rcosts_ also exists. + */ + double *rowduals_; + /*! \brief Vector of constraint left-hand-side values (row activity) + + Produced by evaluating constraints according to #sol_. Updated iff + #sol_ exists. + */ + double *acts_; + /*! \brief Vector of reduced costs + + Produced by evaluating dual constraints according to #rowduals_. Updated + iff #rowduals_ exists. + */ + double *rcosts_; + + /*! \brief Status of primal variables + + Coded with CoinPrePostSolveMatrix::Status, one code per char. colstat_ and + #rowstat_ <b>MUST</b> be allocated as a single vector. This is to maintain + compatibility with ClpPresolve and OsiPresolve, which do it this way. + */ + unsigned char *colstat_; + + /*! \brief Status of constraints + + More accurately, the status of the logical variable associated with the + constraint. Coded with CoinPrePostSolveMatrix::Status, one code per char. + Note that this must be allocated as a single vector with #colstat_. + */ + unsigned char *rowstat_; + //@} + + /*! \name Message handling + + Uses the standard COIN approach: a default handler is installed, and the + CoinPrePostsolveMatrix object takes responsibility for it. If the client + replaces the handler with one of their own, it becomes their + responsibility. + */ + //@{ + /// Message handler + CoinMessageHandler *handler_; + /// Indicates if the current #handler_ is default (true) or not (false). + bool defaultHandler_; + /// Standard COIN messages + CoinMessage messages_; + //@} + +}; + +/*! \relates CoinPrePostsolveMatrix + \brief Generate a print string for a status code. +*/ +const char *statusName (CoinPrePostsolveMatrix::Status status) ; + + +/*! \class presolvehlink + \brief Links to aid in packed matrix modification + + Currently, the matrices held by the CoinPrePostsolveMatrix and + CoinPresolveMatrix objects are represented in the same way as a + CoinPackedMatrix. In the course of presolve and postsolve transforms, it + will happen that a major-dimension vector needs to increase in size. In + order to check whether there is enough room to add another coefficient in + place, it helps to know the next vector (in memory order) in the bulk + storage area. To do that, a linked list of major-dimension vectors is + maintained; the "pre" and "suc" fields give the previous and next vector, + in memory order (that is, the vector whose mcstrt_ or mrstrt_ entry is + next smaller or larger). + + Consider a column-major matrix with ncols columns. By definition, + presolvehlink[ncols].pre points to the column in the last occupied + position of the bulk storage arrays. There is no easy way to find the + column which occupies the first position (there is no presolvehlink[-1] to + consult). If the column that initially occupies the first position is + moved for expansion, there is no way to reclaim the space until the bulk + storage is compacted. The same holds for the last and first rows of a + row-major matrix, of course. +*/ + +class presolvehlink +{ public: + int pre, suc; +} ; + +#define NO_LINK -66666666 + +/*! \relates presolvehlink + \brief unlink vector i + + Remove vector i from the ordering. +*/ +inline void PRESOLVE_REMOVE_LINK(presolvehlink *link, int i) +{ + int ipre = link[i].pre; + int isuc = link[i].suc; + if (ipre >= 0) { + link[ipre].suc = isuc; + } + if (isuc >= 0) { + link[isuc].pre = ipre; + } + link[i].pre = NO_LINK, link[i].suc = NO_LINK; +} + +/*! \relates presolvehlink + \brief insert vector i after vector j + + Insert vector i between j and j.suc. +*/ +inline void PRESOLVE_INSERT_LINK(presolvehlink *link, int i, int j) +{ + int isuc = link[j].suc; + link[j].suc = i; + link[i].pre = j; + if (isuc >= 0) { + link[isuc].pre = i; + } + link[i].suc = isuc; +} + +/*! \relates presolvehlink + \brief relink vector j in place of vector i + + Replace vector i in the ordering with vector j. This is equivalent to + <pre> + int pre = link[i].pre; + PRESOLVE_REMOVE_LINK(link,i); + PRESOLVE_INSERT_LINK(link,j,pre); + </pre> + But, this routine will work even if i happens to be first in the order. +*/ +inline void PRESOLVE_MOVE_LINK(presolvehlink *link, int i, int j) +{ + int ipre = link[i].pre; + int isuc = link[i].suc; + if (ipre >= 0) { + link[ipre].suc = j; + } + if (isuc >= 0) { + link[isuc].pre = j; + } + link[i].pre = NO_LINK, link[i].suc = NO_LINK; +} + + +/*! \class CoinPresolveMatrix + \brief Augments CoinPrePostsolveMatrix with information about the problem + that is only needed during presolve. + + For problem manipulation, this class adds a row-major matrix + representation, linked lists that allow for easy manipulation of the matrix + when applying presolve transforms, and vectors to track row and column + processing status (changed, needs further processing, change prohibited) + + For problem representation, this class adds information about variable type + (integer or continuous), an objective offset, and a feasibility tolerance. + + <b>NOTE</b> that the #anyInteger_ and #anyProhibited_ flags are independent + of the vectors used to track this information for individual variables + (#integerType_ and #rowChanged_ and #colChanged_, respectively). + + <b>NOTE</b> also that at the end of presolve the column-major and row-major + matrix representations are loosely packed (<i>i.e.</i>, there may be gaps + between columns in the bulk storage arrays). + + <b>NOTE</b> that while you might think that CoinPresolve is prepared to + handle minimisation or maximisation, it's unlikely that this still works. + This is a good thing: better to convert objective coefficients and duals + once, before starting presolve, rather than doing it over and over in + each transform that considers dual variables. + + The constructors that take an OSI or ClpSimplex as a parameter really should + not be here, but for historical reasons they will likely remain for the + forseeable future. -- lh, 111202 -- +*/ + +class CoinPresolveMatrix : public CoinPrePostsolveMatrix +{ + public: + + /*! \brief `Native' constructor + + This constructor creates an empty object which must then be loaded. + On the other hand, it doesn't assume that the client is an + OsiSolverInterface. + */ + CoinPresolveMatrix(int ncols_alloc, int nrows_alloc, + CoinBigIndex nelems_alloc) ; + + /*! \brief Clp OSI constructor + + See Clp code for the definition. + */ + CoinPresolveMatrix(int ncols0, + double maxmin, + // end prepost members + + ClpSimplex * si, + + // rowrep + int nrows, + CoinBigIndex nelems, + bool doStatus, + double nonLinearVariable, + double bulkRatio); + + /*! \brief Update the model held by a Clp OSI */ + void update_model(ClpSimplex * si, + int nrows0, + int ncols0, + CoinBigIndex nelems0); + /*! \brief Generic OSI constructor + + See OSI code for the definition. + */ + CoinPresolveMatrix(int ncols0, + double maxmin, + // end prepost members + OsiSolverInterface * si, + // rowrep + int nrows, + CoinBigIndex nelems, + bool doStatus, + double nonLinearVariable, + const char * prohibited, + const char * rowProhibited=NULL); + + /*! \brief Update the model held by a generic OSI */ + void update_model(OsiSolverInterface * si, + int nrows0, + int ncols0, + CoinBigIndex nelems0); + + /// Destructor + ~CoinPresolveMatrix(); + + /*! \brief Initialize a CoinPostsolveMatrix object, destroying the + CoinPresolveMatrix object. + + See CoinPostsolveMatrix::assignPresolveToPostsolve. + */ + friend void assignPresolveToPostsolve (CoinPresolveMatrix *&preObj) ; + + /*! \name Functions to load the problem representation + */ + //@{ + /*! \brief Load the cofficient matrix. + + Load the coefficient matrix before loading the other vectors (bounds, + objective, variable type) required to define the problem. + */ + void setMatrix(const CoinPackedMatrix *mtx) ; + + /// Count number of empty rows + inline int countEmptyRows() + { int empty = 0 ; + for (int i = 0 ; i < nrows_ ; i++) if (hinrow_[i] == 0) empty++ ; + return (empty) ; } + + /*! \brief Set variable type information for a single variable + + Set \p variableType to 0 for continous, 1 for integer. + Does not manipulate the #anyInteger_ flag. + */ + inline void setVariableType(int i, int variableType) + { if (integerType_ == 0) integerType_ = new unsigned char [ncols0_] ; + integerType_[i] = static_cast<unsigned char>(variableType) ; } + + /*! \brief Set variable type information for all variables + + Set \p variableType[i] to 0 for continuous, 1 for integer. + Does not manipulate the #anyInteger_ flag. + */ + void setVariableType(const unsigned char *variableType, int lenParam) ; + + /*! \brief Set the type of all variables + + allIntegers should be true to set the type to integer, false to set the + type to continuous. + */ + void setVariableType (bool allIntegers, int lenParam) ; + + /// Set a flag for presence (true) or absence (false) of integer variables + inline void setAnyInteger (bool anyInteger = true) + { anyInteger_ = anyInteger ; } + //@} + + /*! \name Functions to retrieve problem information + */ + //@{ + + /// Get row start vector for row-major packed matrix + inline const CoinBigIndex *getRowStarts() const + { return (mrstrt_) ; } + /// Get vector of column indices for row-major packed matrix + inline const int *getColIndicesByRow() const + { return (hcol_) ; } + /// Get vector of elements for row-major packed matrix + inline const double *getElementsByRow() const + { return (rowels_) ; } + + /*! \brief Check for integrality of the specified variable. + + Consults the #integerType_ vector if present; fallback is the + #anyInteger_ flag. + */ + inline bool isInteger (int i) const + { if (integerType_ == 0) + { return (anyInteger_) ; } + else + if (integerType_[i] == 1) + { return (true) ; } + else + { return (false) ; } } + + /*! \brief Check if there are any integer variables + + Consults the #anyInteger_ flag + */ + inline bool anyInteger () const + { return (anyInteger_) ; } + /// Picks up any special options + inline int presolveOptions() const + { return presolveOptions_;} + /// Sets any special options (see #presolveOptions_) + inline void setPresolveOptions(int value) + { presolveOptions_=value;} + //@} + + /*! \name Matrix storage management links + + Linked lists, modelled after the linked lists used in OSL + factorization. They are used for management of the bulk coefficient + and minor index storage areas. + */ + //@{ + /// Linked list for the column-major representation. + presolvehlink *clink_; + /// Linked list for the row-major representation. + presolvehlink *rlink_; + //@} + + /// Objective function offset introduced during presolve + double dobias_ ; + + /// Adjust objective function constant offset + inline void change_bias(double change_amount) + { + dobias_ += change_amount ; + # if PRESOLVE_DEBUG > 2 + assert(fabs(change_amount)<1.0e50) ; + if (change_amount) + PRESOLVE_STMT(printf("changing bias by %g to %g\n", + change_amount, dobias_)) ; + # endif + } + + /*! \name Row-major representation + + Common row-major format: A pair of vectors with positional + correspondence to hold coefficients and column indices, and a second pair + of vectors giving the starting position and length of each row in + the first pair. + */ + //@{ + /// Vector of row start positions in #hcol, #rowels_ + CoinBigIndex *mrstrt_; + /// Vector of row lengths + int *hinrow_; + /// Coefficients (positional correspondence with #hcol_) + double *rowels_; + /// Column indices (positional correspondence with #rowels_) + int *hcol_; + //@} + + /// Tracks integrality of columns (1 for integer, 0 for continuous) + unsigned char *integerType_; + /*! \brief Flag to say if any variables are integer + + Note that this flag is <i>not</i> manipulated by the various + \c setVariableType routines. + */ + bool anyInteger_ ; + /// Print statistics for tuning + bool tuning_; + /// Say we want statistics - also set time + void statistics(); + /// Start time of presolve + double startTime_; + + /// Bounds can be moved by this to retain feasibility + double feasibilityTolerance_; + /// Return feasibility tolerance + inline double feasibilityTolerance() + { return (feasibilityTolerance_) ; } + /// Set feasibility tolerance + inline void setFeasibilityTolerance (double val) + { feasibilityTolerance_ = val ; } + + /*! \brief Output status: 0 = feasible, 1 = infeasible, 2 = unbounded + + Actually implemented as single bit flags: 1^0 = infeasible, 1^1 = + unbounded. + */ + int status_; + /// Returns problem status (0 = feasible, 1 = infeasible, 2 = unbounded) + inline int status() + { return (status_) ; } + /// Set problem status + inline void setStatus(int status) + { status_ = (status&0x3) ; } + + /*! \brief Presolve pass number + + Should be incremented externally by the method controlling application of + presolve transforms. + Used to control the execution of testRedundant (evoked by the + implied_free transform). + */ + int pass_; + /// Set pass number + inline void setPass (int pass = 0) + { pass_ = pass ; } + + /*! \brief Maximum substitution level + + Used to control the execution of subst from implied_free + */ + int maxSubstLevel_; + /// Set Maximum substitution level (normally 3) + inline void setMaximumSubstitutionLevel (int level) + { maxSubstLevel_ = level ; } + + + /*! \name Row and column processing status + + Information used to determine if rows or columns can be changed and + if they require further processing due to changes. + + There are four major lists: the [row,col]ToDo list, and the + [row,col]NextToDo list. In general, a transform processes entries from + the ToDo list and adds entries to the NextToDo list. + + There are two vectors, [row,col]Changed, which track the status of + individual rows and columns. + */ + //@{ + /*! \brief Column change status information + + Coded using the following bits: + <ul> + <li> 0x01: Column has changed + <li> 0x02: preprocessing prohibited + <li> 0x04: Column has been used + <li> 0x08: Column originally had infinite ub + </ul> + */ + unsigned char * colChanged_; + /// Input list of columns to process + int * colsToDo_; + /// Length of #colsToDo_ + int numberColsToDo_; + /// Output list of columns to process next + int * nextColsToDo_; + /// Length of #nextColsToDo_ + int numberNextColsToDo_; + + /*! \brief Row change status information + + Coded using the following bits: + <ul> + <li> 0x01: Row has changed + <li> 0x02: preprocessing prohibited + <li> 0x04: Row has been used + </ul> + */ + unsigned char * rowChanged_; + /// Input list of rows to process + int * rowsToDo_; + /// Length of #rowsToDo_ + int numberRowsToDo_; + /// Output list of rows to process next + int * nextRowsToDo_; + /// Length of #nextRowsToDo_ + int numberNextRowsToDo_; + /*! \brief Fine control over presolve actions + + Set/clear the following bits to allow or suppress actions: + - 0x01 allow duplicate column tests for integer variables + - 0x02 not used + - 0x04 set to inhibit x+y+z=1 mods + - 0x08 not used + - 0x10 set to allow stuff which won't unroll easily (overlapping + duplicate rows; opportunistic fixing of variables from bound + propagation). + - 0x04000 allow presolve transforms to arbitrarily ignore infeasibility + and set arbitrary feasible bounds. + - 0x10000 instructs implied_free_action to be `more lightweight'; will + return without doing anything after 15 presolve passes. + - 0x(2,4,6)0000 instructs implied_free_action to remove small created elements + - 0x80000000 set by presolve to say dupcol_action compressed columns + */ + int presolveOptions_; + /*! Flag to say if any rows or columns are marked as prohibited + + Note that this flag is <i>not</i> manipulated by any of the + various \c set*Prohibited routines. + */ + bool anyProhibited_; + //@} + + /*! \name Scratch work arrays + + Preallocated work arrays are useful to avoid having to allocate and free + work arrays in individual presolve methods. + + All are allocated from #setMatrix by #initializeStuff, freed from + #~CoinPresolveMatrix. You can use #deleteStuff followed by + #initializeStuff to remove and recreate them. + */ + //@{ + /// Preallocated scratch work array, 3*nrows_ + int *usefulRowInt_ ; + /// Preallocated scratch work array, 2*nrows_ + double *usefulRowDouble_ ; + /// Preallocated scratch work array, 2*ncols_ + int *usefulColumnInt_ ; + /// Preallocated scratch work array, ncols_ + double *usefulColumnDouble_ ; + /// Array of random numbers (max row,column) + double *randomNumber_ ; + + /// Work array for count of infinite contributions to row lhs upper bound + int *infiniteUp_ ; + /// Work array for sum of finite contributions to row lhs upper bound + double *sumUp_ ; + /// Work array for count of infinite contributions to row lhs lower bound + int *infiniteDown_ ; + /// Work array for sum of finite contributions to row lhs lower bound + double *sumDown_ ; + //@} + + /*! \brief Recompute row lhs bounds + + Calculate finite contributions to row lhs upper and lower bounds + and count infinite contributions. Returns the number of rows found + to be infeasible. + + If \p whichRow < 0, bounds are recomputed for all rows. + + As of 110611, this seems to be a work in progress in the sense that it's + barely used by the existing presolve code. + */ + int recomputeSums(int whichRow) ; + + /// Allocate scratch arrays + void initializeStuff() ; + /// Free scratch arrays + void deleteStuff() ; + + /*! \name Functions to manipulate row and column processing status */ + //@{ + + /*! \brief Initialise the column ToDo lists + + Places all columns in the #colsToDo_ list except for columns marked + as prohibited (<i>viz.</i> #colChanged_). + */ + void initColsToDo () ; + + /*! \brief Step column ToDo lists + + Moves columns on the #nextColsToDo_ list to the #colsToDo_ list, emptying + #nextColsToDo_. Returns the number of columns transferred. + */ + int stepColsToDo () ; + + /// Return the number of columns on the #colsToDo_ list + inline int numberColsToDo() + { return (numberColsToDo_) ; } + + /// Has column been changed? + inline bool colChanged(int i) const { + return (colChanged_[i]&1)!=0; + } + /// Mark column as not changed + inline void unsetColChanged(int i) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] & (~1)) ; + } + /// Mark column as changed. + inline void setColChanged(int i) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] | (1)) ; + } + /// Mark column as changed and add to list of columns to process next + inline void addCol(int i) { + if ((colChanged_[i]&1)==0) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] | (1)) ; + nextColsToDo_[numberNextColsToDo_++] = i; + } + } + /// Test if column is eligible for preprocessing + inline bool colProhibited(int i) const { + return (colChanged_[i]&2)!=0; + } + /*! \brief Test if column is eligible for preprocessing + + The difference between this method and #colProhibited() is that this + method first tests #anyProhibited_ before examining the specific entry + for the specified column. + */ + inline bool colProhibited2(int i) const { + if (!anyProhibited_) + return false; + else + return (colChanged_[i]&2)!=0; + } + /// Mark column as ineligible for preprocessing + inline void setColProhibited(int i) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] | (2)) ; + } + /*! \brief Test if column is marked as used + + This is for doing faster lookups to see where two columns have entries + in common. + */ + inline bool colUsed(int i) const { + return (colChanged_[i]&4)!=0; + } + /// Mark column as used + inline void setColUsed(int i) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] | (4)) ; + } + /// Mark column as unused + inline void unsetColUsed(int i) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] & (~4)) ; + } + /// Has column infinite ub (originally) + inline bool colInfinite(int i) const { + return (colChanged_[i]&8)!=0; + } + /// Mark column as not infinite ub (originally) + inline void unsetColInfinite(int i) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] & (~8)) ; + } + /// Mark column as infinite ub (originally) + inline void setColInfinite(int i) { + colChanged_[i] = static_cast<unsigned char>(colChanged_[i] | (8)) ; + } + + /*! \brief Initialise the row ToDo lists + + Places all rows in the #rowsToDo_ list except for rows marked + as prohibited (<i>viz.</i> #rowChanged_). + */ + void initRowsToDo () ; + + /*! \brief Step row ToDo lists + + Moves rows on the #nextRowsToDo_ list to the #rowsToDo_ list, emptying + #nextRowsToDo_. Returns the number of rows transferred. + */ + int stepRowsToDo () ; + + /// Return the number of rows on the #rowsToDo_ list + inline int numberRowsToDo() + { return (numberRowsToDo_) ; } + + /// Has row been changed? + inline bool rowChanged(int i) const { + return (rowChanged_[i]&1)!=0; + } + /// Mark row as not changed + inline void unsetRowChanged(int i) { + rowChanged_[i] = static_cast<unsigned char>(rowChanged_[i] & (~1)) ; + } + /// Mark row as changed + inline void setRowChanged(int i) { + rowChanged_[i] = static_cast<unsigned char>(rowChanged_[i] | (1)) ; + } + /// Mark row as changed and add to list of rows to process next + inline void addRow(int i) { + if ((rowChanged_[i]&1)==0) { + rowChanged_[i] = static_cast<unsigned char>(rowChanged_[i] | (1)) ; + nextRowsToDo_[numberNextRowsToDo_++] = i; + } + } + /// Test if row is eligible for preprocessing + inline bool rowProhibited(int i) const { + return (rowChanged_[i]&2)!=0; + } + /*! \brief Test if row is eligible for preprocessing + + The difference between this method and #rowProhibited() is that this + method first tests #anyProhibited_ before examining the specific entry + for the specified row. + */ + inline bool rowProhibited2(int i) const { + if (!anyProhibited_) + return false; + else + return (rowChanged_[i]&2)!=0; + } + /// Mark row as ineligible for preprocessing + inline void setRowProhibited(int i) { + rowChanged_[i] = static_cast<unsigned char>(rowChanged_[i] | (2)) ; + } + /*! \brief Test if row is marked as used + + This is for doing faster lookups to see where two rows have entries + in common. It can be used anywhere as long as it ends up zeroed out. + */ + inline bool rowUsed(int i) const { + return (rowChanged_[i]&4)!=0; + } + /// Mark row as used + inline void setRowUsed(int i) { + rowChanged_[i] = static_cast<unsigned char>(rowChanged_[i] | (4)) ; + } + /// Mark row as unused + inline void unsetRowUsed(int i) { + rowChanged_[i] = static_cast<unsigned char>(rowChanged_[i] & (~4)) ; + } + + + /// Check if there are any prohibited rows or columns + inline bool anyProhibited() const + { return anyProhibited_;} + /// Set a flag for presence of prohibited rows or columns + inline void setAnyProhibited(bool val = true) + { anyProhibited_ = val ; } + //@} + +}; + +/*! \class CoinPostsolveMatrix + \brief Augments CoinPrePostsolveMatrix with information about the problem + that is only needed during postsolve. + + The notable point is that the matrix representation is threaded. The + representation is column-major and starts with the standard two pairs of + arrays: one pair to hold the row indices and coefficients, the second pair + to hold the column starting positions and lengths. But the row indices and + coefficients for a column do not necessarily occupy a contiguous block in + their respective arrays. Instead, a link array gives the position of the + next (row index,coefficient) pair. If the row index and value of a + coefficient a<p,j> occupy position kp in their arrays, then the position of + the next coefficient a<q,j> is found as kq = link[kp]. + + This threaded representation allows for efficient expansion of columns as + rows are reintroduced during postsolve transformations. The basic packed + structures are allocated to the expected size of the postsolved matrix, + and as new coefficients are added, their location is simply added to the + thread for the column. + + There is no provision to convert the threaded representation to a packed + representation. In the context of postsolve, it's not required. (You did + keep a copy of the original matrix, eh?) + + The constructors that take an OSI or ClpSimplex as a parameter really should + not be here, but for historical reasons they will likely remain for the + forseeable future. -- lh, 111202 -- +*/ +class CoinPostsolveMatrix : public CoinPrePostsolveMatrix +{ + public: + + /*! \brief `Native' constructor + + This constructor creates an empty object which must then be loaded. + On the other hand, it doesn't assume that the client is an + OsiSolverInterface. + */ + CoinPostsolveMatrix(int ncols_alloc, int nrows_alloc, + CoinBigIndex nelems_alloc) ; + + + /*! \brief Clp OSI constructor + + See Clp code for the definition. + */ + CoinPostsolveMatrix(ClpSimplex * si, + + int ncols0, + int nrows0, + CoinBigIndex nelems0, + + double maxmin_, + // end prepost members + + double *sol, + double *acts, + + unsigned char *colstat, + unsigned char *rowstat); + + /*! \brief Generic OSI constructor + + See OSI code for the definition. + */ + CoinPostsolveMatrix(OsiSolverInterface * si, + + int ncols0, + int nrows0, + CoinBigIndex nelems0, + + double maxmin_, + // end prepost members + + double *sol, + double *acts, + + unsigned char *colstat, + unsigned char *rowstat); + + /*! \brief Load an empty CoinPostsolveMatrix from a CoinPresolveMatrix + + This routine transfers the contents of the CoinPrePostsolveMatrix + object from the CoinPresolveMatrix object to the CoinPostsolveMatrix + object and completes initialisation of the CoinPostsolveMatrix object. + The empty shell of the CoinPresolveMatrix object is destroyed. + + The routine expects an empty CoinPostsolveMatrix object. If handed a loaded + object, a lot of memory will leak. + */ + void assignPresolveToPostsolve (CoinPresolveMatrix *&preObj) ; + + /// Destructor + ~CoinPostsolveMatrix(); + + /*! \name Column thread structures + + As mentioned in the class documentation, the entries for a given column + do not necessarily occupy a contiguous block of space. The #link_ array + is used to maintain the threading. There is one thread for each column, + and a single thread for all free entries in #hrow_ and #colels_. + + The allocated size of #link_ must be at least as large as the allocated + size of #hrow_ and #colels_. + */ + //@{ + + /*! \brief First entry in free entries thread */ + CoinBigIndex free_list_; + /// Allocated size of #link_ + int maxlink_; + /*! \brief Thread array + + Within a thread, link_[k] points to the next entry in the thread. + */ + CoinBigIndex *link_; + + //@} + + /*! \name Debugging aids + + These arrays are allocated only when CoinPresolve is compiled with + PRESOLVE_DEBUG defined. They hold codes which track the reason that + a column or row is added to the problem during postsolve. + */ + //@{ + char *cdone_; + char *rdone_; + //@} + + /// debug + void check_nbasic(); + +}; + + +/*! \defgroup MtxManip Presolve Matrix Manipulation Functions + + Functions to work with the loosely packed and threaded packed matrix + structures used during presolve and postsolve. +*/ +//@{ + +/*! \relates CoinPrePostsolveMatrix + \brief Initialise linked list for major vector order in bulk storage +*/ + +void presolve_make_memlists(/*CoinBigIndex *starts,*/ int *lengths, + presolvehlink *link, int n); + +/*! \relates CoinPrePostsolveMatrix + \brief Make sure a major-dimension vector k has room for one more + coefficient. + + You can use this directly, or use the inline wrappers presolve_expand_col + and presolve_expand_row +*/ +bool presolve_expand_major(CoinBigIndex *majstrts, double *majels, + int *minndxs, int *majlens, + presolvehlink *majlinks, int nmaj, int k) ; + +/*! \relates CoinPrePostsolveMatrix + \brief Make sure a column (colx) in a column-major matrix has room for + one more coefficient +*/ + +inline bool presolve_expand_col(CoinBigIndex *mcstrt, double *colels, + int *hrow, int *hincol, + presolvehlink *clink, int ncols, int colx) +{ return presolve_expand_major(mcstrt,colels, + hrow,hincol,clink,ncols,colx) ; } + +/*! \relates CoinPrePostsolveMatrix + \brief Make sure a row (rowx) in a row-major matrix has room for one + more coefficient +*/ + +inline bool presolve_expand_row(CoinBigIndex *mrstrt, double *rowels, + int *hcol, int *hinrow, + presolvehlink *rlink, int nrows, int rowx) +{ return presolve_expand_major(mrstrt,rowels, + hcol,hinrow,rlink,nrows,rowx) ; } + + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a minor index in a major vector. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. It will abort if the entry does not exist. Can be + used directly or via the inline wrappers presolve_find_row and + presolve_find_col. +*/ +inline CoinBigIndex presolve_find_minor(int tgt, + CoinBigIndex ks, CoinBigIndex ke, + const int *minndxs) +{ CoinBigIndex k ; + for (k = ks ; k < ke ; k++) +#ifndef NDEBUG + { if (minndxs[k] == tgt) + return (k) ; } + DIE("FIND_MINOR") ; + + abort () ; return -1; +#else + { if (minndxs[k] == tgt) + break ; } + return (k) ; +#endif +} + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a row in a column in a column-major matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + It will abort if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row(int row, CoinBigIndex kcs, + CoinBigIndex kce, const int *hrow) +{ return presolve_find_minor(row,kcs,kce,hrow) ; } + +/*! \relates CoinPostsolveMatrix + \brief Find position of a column in a row in a row-major matrix. + + The routine returns the position \c k in \p hcol for the specified \p col. + It will abort if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_col(int col, CoinBigIndex krs, + CoinBigIndex kre, const int *hcol) +{ return presolve_find_minor(col,krs,kre,hcol) ; } + + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a minor index in a major vector. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. A return value of \p ke means the entry does not + exist. Can be used directly or via the inline wrappers + presolve_find_row1 and presolve_find_col1. +*/ +CoinBigIndex presolve_find_minor1(int tgt, CoinBigIndex ks, CoinBigIndex ke, + const int *minndxs); + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a row in a column in a column-major matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + A return value of \p kce means the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row1(int row, CoinBigIndex kcs, + CoinBigIndex kce, const int *hrow) +{ return presolve_find_minor1(row,kcs,kce,hrow) ; } + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a column in a row in a row-major matrix. + + The routine returns the position \c k in \p hcol for the specified \p col. + A return value of \p kre means the entry does not exist. +*/ +inline CoinBigIndex presolve_find_col1(int col, CoinBigIndex krs, + CoinBigIndex kre, const int *hcol) +{ return presolve_find_minor1(col,krs,kre,hcol) ; } + +/*! \relates CoinPostsolveMatrix + \brief Find position of a minor index in a major vector in a threaded + matrix. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. It will abort if the entry does not exist. Can be + used directly or via the inline wrapper presolve_find_row2. +*/ +CoinBigIndex presolve_find_minor2(int tgt, CoinBigIndex ks, int majlen, + const int *minndxs, + const CoinBigIndex *majlinks) ; + +/*! \relates CoinPostsolveMatrix + \brief Find position of a row in a column in a column-major threaded + matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + It will abort if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row2(int row, CoinBigIndex kcs, int collen, + const int *hrow, + const CoinBigIndex *clinks) +{ return presolve_find_minor2(row,kcs,collen,hrow,clinks) ; } + +/*! \relates CoinPostsolveMatrix + \brief Find position of a minor index in a major vector in a threaded + matrix. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. It will return -1 if the entry does not exist. + Can be used directly or via the inline wrappers presolve_find_row3. +*/ +CoinBigIndex presolve_find_minor3(int tgt, CoinBigIndex ks, int majlen, + const int *minndxs, + const CoinBigIndex *majlinks) ; + +/*! \relates CoinPostsolveMatrix + \brief Find position of a row in a column in a column-major threaded + matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + It will return -1 if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row3(int row, CoinBigIndex kcs, int collen, + const int *hrow, + const CoinBigIndex *clinks) +{ return presolve_find_minor3(row,kcs,collen,hrow,clinks) ; } + +/*! \relates CoinPrePostsolveMatrix + \brief Delete the entry for a minor index from a major vector. + + Deletes the entry for \p minndx from the major vector \p majndx. + Specifically, the relevant entries are removed from the minor index + (\p minndxs) and coefficient (\p els) arrays and the vector length (\p + majlens) is decremented. Loose packing is maintained by swapping the last + entry in the row into the position occupied by the deleted entry. +*/ +inline void presolve_delete_from_major(int majndx, int minndx, + const CoinBigIndex *majstrts, + int *majlens, int *minndxs, double *els) +{ + const CoinBigIndex ks = majstrts[majndx] ; + const CoinBigIndex ke = ks+majlens[majndx] ; + + const CoinBigIndex kmi = presolve_find_minor(minndx,ks,ke,minndxs) ; + + minndxs[kmi] = minndxs[ke-1] ; + els[kmi] = els[ke-1] ; + majlens[majndx]-- ; + + return ; +} + +/*! \relates CoinPrePostsolveMatrix + \brief Delete marked entries + + Removes the entries specified in \p marked, compressing the major vector + to maintain loose packing. \p marked is cleared in the process. +*/ +inline void presolve_delete_many_from_major(int majndx, char *marked, + const CoinBigIndex *majstrts, + int *majlens, int *minndxs, double *els) +{ + const CoinBigIndex ks = majstrts[majndx] ; + const CoinBigIndex ke = ks+majlens[majndx] ; + CoinBigIndex put = ks ; + for (CoinBigIndex k = ks ; k < ke ; k++) { + int iMinor = minndxs[k] ; + if (!marked[iMinor]) { + minndxs[put] = iMinor ; + els[put++] = els[k] ; + } else { + marked[iMinor] = 0 ; + } + } + majlens[majndx] = put-ks ; + return ; +} + +/*! \relates CoinPrePostsolveMatrix + \brief Delete the entry for row \p row from column \p col in a + column-major matrix + + Deletes the entry for \p row from the major vector for \p col. + Specifically, the relevant entries are removed from the row index (\p + hrow) and coefficient (\p colels) arrays and the vector length (\p + hincol) is decremented. Loose packing is maintained by swapping the last + entry in the row into the position occupied by the deleted entry. +*/ +inline void presolve_delete_from_col(int row, int col, + const CoinBigIndex *mcstrt, + int *hincol, int *hrow, double *colels) +{ presolve_delete_from_major(col,row,mcstrt,hincol,hrow,colels) ; } + +/*! \relates CoinPrePostsolveMatrix + \brief Delete the entry for column \p col from row \p row in a + row-major matrix + + Deletes the entry for \p col from the major vector for \p row. + Specifically, the relevant entries are removed from the column index (\p + hcol) and coefficient (\p rowels) arrays and the vector length (\p + hinrow) is decremented. Loose packing is maintained by swapping the last + entry in the column into the position occupied by the deleted entry. +*/ +inline void presolve_delete_from_row(int row, int col, + const CoinBigIndex *mrstrt, + int *hinrow, int *hcol, double *rowels) +{ presolve_delete_from_major(row,col,mrstrt,hinrow,hcol,rowels) ; } + +/*! \relates CoinPostsolveMatrix + \brief Delete the entry for a minor index from a major vector in a + threaded matrix. + + Deletes the entry for \p minndx from the major vector \p majndx. + Specifically, the relevant entries are removed from the minor index (\p + minndxs) and coefficient (\p els) arrays and the vector length (\p + majlens) is decremented. The thread for the major vector is relinked + around the deleted entry and the space is returned to the free list. +*/ +void presolve_delete_from_major2 (int majndx, int minndx, + CoinBigIndex *majstrts, int *majlens, + int *minndxs, int *majlinks, + CoinBigIndex *free_listp) ; + +/*! \relates CoinPostsolveMatrix + \brief Delete the entry for row \p row from column \p col in a + column-major threaded matrix + + Deletes the entry for \p row from the major vector for \p col. + Specifically, the relevant entries are removed from the row index (\p + hrow) and coefficient (\p colels) arrays and the vector length (\p + hincol) is decremented. The thread for the major vector is relinked + around the deleted entry and the space is returned to the free list. +*/ +inline void presolve_delete_from_col2(int row, int col, CoinBigIndex *mcstrt, + int *hincol, int *hrow, + int *clinks, CoinBigIndex *free_listp) +{ presolve_delete_from_major2(col,row,mcstrt,hincol,hrow,clinks,free_listp) ; } + +//@} + +/*! \defgroup PresolveUtilities Presolve Utility Functions + + Utilities used by multiple presolve transform objects. +*/ +//@{ + +/*! \brief Duplicate a major-dimension vector; optionally omit the entry + with minor index \p tgt. + + Designed to copy a major-dimension vector from the paired coefficient + (\p elems) and minor index (\p indices) arrays used in the standard + packed matrix representation. Copies \p length entries starting at + \p offset. + + If \p tgt is specified, the entry with minor index == \p tgt is + omitted from the copy. +*/ +double *presolve_dupmajor(const double *elems, const int *indices, + int length, CoinBigIndex offset, int tgt = -1); + +/// Initialize a vector with random numbers +void coin_init_random_vec(double *work, int n); + +//@} + + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveMonitor.hpp b/thirdparty/linux/include/coin/CoinPresolveMonitor.hpp new file mode 100644 index 0000000..cef7a41 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveMonitor.hpp @@ -0,0 +1,105 @@ + +#ifndef CoinPresolveMonitor_H +#define CoinPresolveMonitor_H + +/*! + \brief Monitor a row or column for modification + + The purpose of this class is to monitor a row or column for modifications + during presolve and postsolve. Each object can monitor one row or + column. The initial copy of the row or column is loaded by the constructor. + Each subsequent call to checkAndTell() compares the current state of the row + or column with the stored state and reports any modifications. + + Internally the row or column is held as a CoinPackedVector so that it's + possible to follow a row or column through presolve (CoinPresolveMatrix) + and postsolve (CoinPostsolveMatrix). + + Do not underestimate the amount of work required here. Extracting a row from + the CoinPostsolve matrix requires a scan of every element in the matrix. + That's one scan by the constructor and one scan with every call to modify. + But that's precisely why it's virtually impossible to debug presolve without + aids. + + Parameter overloads for CoinPresolveMatrix and CoinPostsolveMatrix are a + little clumsy, but not a problem in use. The alternative is to add methods + to the CoinPresolveMatrix and CoinPostsolveMatrix classes that will only be + used for debugging. That's not too attractive either. +*/ +class CoinPresolveMonitor +{ + public: + + /*! \brief Default constructor + + Creates an empty monitor. + */ + CoinPresolveMonitor() ; + + /*! \brief Initialise from a CoinPresolveMatrix + + Load the initial row or column from a CoinPresolveMatrix. Set \p isRow + true for a row, false for a column. + */ + CoinPresolveMonitor(const CoinPresolveMatrix *mtx, bool isRow, int k) ; + + /*! \brief Initialise from a CoinPostsolveMatrix + + Load the initial row or column from a CoinPostsolveMatrix. Set \p isRow + true for a row, false for a column. + */ + CoinPresolveMonitor(const CoinPostsolveMatrix *mtx, bool isRow, int k) ; + + /*! \brief Compare the present row or column against the stored copy and + report differences. + + Load the current row or column from a CoinPresolveMatrix and compare. + Differences are printed to std::cout. + */ + void checkAndTell(const CoinPresolveMatrix *mtx) ; + + /*! \brief Compare the present row or column against the stored copy and + report differences. + + Load the current row or column from a CoinPostsolveMatrix and compare. + Differences are printed to std::cout. + */ + void checkAndTell(const CoinPostsolveMatrix *mtx) ; + + private: + + /// Extract a row from a CoinPresolveMatrix + CoinPackedVector *extractRow(int i, const CoinPresolveMatrix *mtx) const ; + + /// Extract a column from a CoinPresolveMatrix + CoinPackedVector *extractCol(int j, const CoinPresolveMatrix *mtx) const ; + + /// Extract a row from a CoinPostsolveMatrix + CoinPackedVector *extractRow(int i, const CoinPostsolveMatrix *mtx) const ; + + /// Extract a column from a CoinPostsolveMatrix + CoinPackedVector *extractCol(int j, const CoinPostsolveMatrix *mtx) const ; + + /// Worker method underlying the public checkAndTell methods. + void checkAndTell(CoinPackedVector *curVec, double lb, double ub) ; + + /// True to monitor a row, false to monitor a column + bool isRow_ ; + + /// Row or column index + int ndx_ ; + + /*! The original row or column + + Sorted in increasing order of indices. + */ + CoinPackedVector *origVec_ ; + + /// Original row or column lower bound + double lb_ ; + + /// Original row or column upper bound + double ub_ ; +} ; + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolvePsdebug.hpp b/thirdparty/linux/include/coin/CoinPresolvePsdebug.hpp new file mode 100644 index 0000000..d72479a --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolvePsdebug.hpp @@ -0,0 +1,166 @@ +/* $Id: CoinPresolvePsdebug.hpp 1560 2012-11-24 00:29:01Z lou $ */ +// 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). + +#ifndef CoinPresolvePsdebug_H +#define CoinPresolvePsdebug_H + +/* + The current idea of the relation between PRESOLVE_DEBUG and + PRESOLVE_CONSISTENCY is that PRESOLVE_CONSISTENCY triggers the consistency + checks and PRESOLVE_DEBUG triggers consistency checks and output. + This isn't always true in the code, but that's the goal. Really, + the whole compile-time scheme should be replaced with something more + user-friendly (control variables that can be changed during the run). + + Also floating about are PRESOLVE_SUMMARY and COIN_PRESOLVE_TUNING. + -- lh, 111208 -- +*/ +/*! \defgroup PresolveDebugFunctions Presolve Debug Functions + + These functions implement consistency checks on data structures involved + in presolve and postsolve and on the components of the lp solution. + + To use these functions, include CoinPresolvePsdebug.hpp in your file and + define the compile-time constants PRESOLVE_SUMMARY, PRESOLVE_DEBUG, and + PRESOLVE_CONSISTENCY. A value is needed (<i>i.e.</i>, PRESOLVE_DEBUG=1). + In a few places, higher values will get you a bit more output. + + ******** + + Define the symbols PRESOLVE_DEBUG and PRESOLVE_CONSISTENCY on the configure + command line (use ADD_CXXFLAGS), in a Makefile, or similar and do a full + rebuild (including any presolve driver code). If the symbols are not + consistently nonzero across *all* presolve code, you'll get something + between garbage and a core dump! Debugging adds messages to CoinMessage + and allocates and maintains arrays that hold debug information. + + That said, given that you've configured and built with PRESOLVE_DEBUG and + PRESOLVE_CONSISTENCY nonzero everywhere, it's safe to adjust PRESOLVE_DEBUG + to values in the range 1..n in individual files to increase or decrease the + amount of output. + + The suggested approach for PRESOLVE_DEBUG is to define it to 1 in the build + and then increase it in individual presolve code files to get more detail. + + ******** +*/ +//@{ + +/*! \relates CoinPresolveMatrix + \brief Check column-major and/or row-major matrices for duplicate + entries in the major vectors. + + By default, scans both the column- and row-major matrices. Set doCol (doRow) + to false to suppress the column (row) scan. +*/ +void presolve_no_dups(const CoinPresolveMatrix *preObj, + bool doCol = true, bool doRow = true) ; + +/*! \relates CoinPresolveMatrix + \brief Check the links which track storage order for major vectors in + the bulk storage area. + + By default, scans both the column- and row-major matrix. Set doCol = false to + suppress the column-major scan. Set doRow = false to suppres the row-major + scan. +*/ +void presolve_links_ok(const CoinPresolveMatrix *preObj, + bool doCol = true, bool doRow = true) ; + +/*! \relates CoinPresolveMatrix + \brief Check for explicit zeros in the column- and/or row-major matrices. + + By default, scans both the column- and row-major matrices. Set doCol (doRow) + to false to suppress the column (row) scan. +*/ +void presolve_no_zeros(const CoinPresolveMatrix *preObj, + bool doCol = true, bool doRow = true) ; + +/*! \relates CoinPresolveMatrix + \brief Checks for equivalence of the column- and row-major matrices. + + Normally the routine will test for coefficient presence and value. Set + \p chkvals to false to suppress the check for equal value. +*/ +void presolve_consistent(const CoinPresolveMatrix *preObj, + bool chkvals = true) ; + +/*! \relates CoinPostsolveMatrix + \brief Checks that column threads agree with column lengths +*/ +void presolve_check_threads(const CoinPostsolveMatrix *obj) ; + +/*! \relates CoinPostsolveMatrix + \brief Checks the free list + + Scans the thread of free locations in the bulk store and checks that all + entries are reasonable (0 <= index < bulk0_). If chkElemCnt is true, it + also checks that the total number of entries in the matrix plus the + locations on the free list total to the size of the bulk store. Postsolve + routines do not maintain an accurate element count, but this is useful + for checking a newly constructed postsolve matrix. +*/ +void presolve_check_free_list(const CoinPostsolveMatrix *obj, + bool chkElemCnt = false) ; + +/*! \relates CoinPostsolveMatrix + \brief Check stored reduced costs for accuracy and consistency with + variable status. + + The routine will check the value of the reduced costs for architectural + variables (CoinPrePostsolveMatrix::rcosts_). It performs an accuracy check + by recalculating the reduced cost from scratch. It will also check the + value for consistency with the status information in + CoinPrePostsolveMatrix::colstat_. +*/ +void presolve_check_reduced_costs(const CoinPostsolveMatrix *obj) ; + +/*! \relates CoinPostsolveMatrix + \brief Check the dual variables for consistency with row activity. + + The routine checks that the value of the dual variable is consistent + with the state of the constraint (loose, tight at lower bound, or tight at + upper bound). +*/ +void presolve_check_duals(const CoinPostsolveMatrix *postObj) ; + +/*! \relates CoinPresolveMatrix + \brief Check primal solution and architectural variable status. + + The architectural variables can be checked for bogus values, feasibility, + and valid status. The row activity is checked for bogus values, accuracy, + and feasibility. By default, row activity is not checked (presolve is + sloppy about maintaining it). See the definitions in + CoinPresolvePsdebug.cpp for more information. +*/ +void presolve_check_sol(const CoinPresolveMatrix *preObj, + int chkColSol = 2, int chkRowAct = 1, + int chkStatus = 1) ; + +/*! \relates CoinPostsolveMatrix + \brief Check primal solution and architectural variable status. + + The architectural variables can be checked for bogus values, feasibility, + and valid status. The row activity is checked for bogus values, accuracy, + and feasibility. See the definitions in CoinPresolvePsdebug.cpp for more + information. +*/ +void presolve_check_sol(const CoinPostsolveMatrix *postObj, + int chkColSol = 2, int chkRowAct = 2, + int chkStatus = 1) ; + +/*! \relates CoinPresolveMatrix + \brief Check for the proper number of basic variables. +*/ +void presolve_check_nbasic(const CoinPresolveMatrix *preObj) ; + +/*! \relates CoinPostsolveMatrix + \brief Check for the proper number of basic variables. +*/ +void presolve_check_nbasic(const CoinPostsolveMatrix *postObj) ; + +//@} + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveSingleton.hpp b/thirdparty/linux/include/coin/CoinPresolveSingleton.hpp new file mode 100644 index 0000000..10bc1cc --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveSingleton.hpp @@ -0,0 +1,112 @@ +/* $Id: CoinPresolveSingleton.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// 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). + +#ifndef CoinPresolveSingleton_H +#define CoinPresolveSingleton_H +#define SLACK_DOUBLETON 2 +#define SLACK_SINGLETON 8 + +/*! + \file +*/ + +//const int MAX_SLACK_DOUBLETONS = 1000; + +/*! \class slack_doubleton_action + \brief Convert an explicit bound constraint to a column bound + + This transform looks for explicit bound constraints for a variable and + transfers the bound to the appropriate column bound array. + The constraint is removed from the constraint system. +*/ +class slack_doubleton_action : public CoinPresolveAction { + struct action { + double clo; + double cup; + + double rlo; + double rup; + + double coeff; + + int col; + int row; + }; + + const int nactions_; + const action *const actions_; + + slack_doubleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), + actions_(actions) +{} + + public: + const char *name() const { return ("slack_doubleton_action"); } + + /*! \brief Convert explicit bound constraints to column bounds. + + Not now There is a hard limit (#MAX_SLACK_DOUBLETONS) on the number of + constraints processed in a given call. \p notFinished is set to true + if candidates remain. + */ + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next, + bool ¬Finished); + + void postsolve(CoinPostsolveMatrix *prob) const; + + + virtual ~slack_doubleton_action() { deleteAction(actions_,action*); } +}; +/*! \class slack_singleton_action + \brief For variables with one entry + + If we have a variable with one entry and no cost then we can + transform the row from E to G etc. + If there is a row objective region then we may be able to do + this even with a cost. +*/ +class slack_singleton_action : public CoinPresolveAction { + struct action { + double clo; + double cup; + + double rlo; + double rup; + + double coeff; + + int col; + int row; + }; + + const int nactions_; + const action *const actions_; + + slack_singleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), + actions_(actions) +{} + + public: + const char *name() const { return ("slack_singleton_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next, + double * rowObjective); + + void postsolve(CoinPostsolveMatrix *prob) const; + + + virtual ~slack_singleton_action() { deleteAction(actions_,action*); } +}; +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveSubst.hpp b/thirdparty/linux/include/coin/CoinPresolveSubst.hpp new file mode 100644 index 0000000..93822a5 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveSubst.hpp @@ -0,0 +1,101 @@ +/* $Id: CoinPresolveSubst.hpp 1562 2012-11-24 00:36:15Z lou $ */ +// 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). + +#ifndef CoinPresolveSubst_H +#define CoinPresolveSubst_H + +/*! + \file +*/ + +#define SUBST_ROW 21 + +#include "CoinPresolveMatrix.hpp" + +/*! \class subst_constraint_action + \brief Detect and process implied free variables + + Consider a variable x. Suppose that we can find an equality such that the + bound on the equality, combined with + the bounds on the other variables involved in the equality, are such that + even the worst case values of the other variables still imply bounds for x + which are tighter than the variable's original bounds. Since x can never + reach its upper or lower bounds, it is an implied free variable. By solving + the equality for x and substituting for x in every other constraint + entangled with x, we can make x into a column singleton. Now x is an implied + free column singleton and both x and the equality can be removed. + + A similar transform for the case where the variable is a natural column + singleton is handled by #implied_free_action. In the current presolve + architecture, #implied_free_action is responsible for detecting implied free + variables that are natural column singletons or can be reduced to column + singletons. #implied_free_action calls subst_constraint_action to process + variables that must be reduced to column singletons. +*/ +class subst_constraint_action : public CoinPresolveAction { +private: + subst_constraint_action(); + subst_constraint_action(const subst_constraint_action& rhs); + subst_constraint_action& operator=(const subst_constraint_action& rhs); + + struct action { + double *rlos; + double *rups; + + double *coeffxs; + int *rows; + + int *ninrowxs; + int *rowcolsxs; + double *rowelsxs; + + const double *costsx; + int col; + int rowy; + + int nincol; + }; + + const int nactions_; + // actions_ is owned by the class and must be deleted at destruction + const action *const actions_; + + subst_constraint_action(int nactions, + action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix * prob, + const int *implied_free, + const int * which, + int numberFree, + const CoinPresolveAction *next, + int fill_level); + static const CoinPresolveAction *presolveX(CoinPresolveMatrix * prob, + const CoinPresolveAction *next, + int fillLevel); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~subst_constraint_action(); +}; + + + + + +/*static*/ void implied_bounds(const double *els, + const double *clo, const double *cup, + const int *hcol, + CoinBigIndex krs, CoinBigIndex kre, + double *maxupp, double *maxdownp, + int jcol, + double rlo, double rup, + double *iclb, double *icub); +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveTighten.hpp b/thirdparty/linux/include/coin/CoinPresolveTighten.hpp new file mode 100644 index 0000000..3a5319b --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveTighten.hpp @@ -0,0 +1,55 @@ +/* $Id: CoinPresolveTighten.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// 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). + +#ifndef CoinPresolveTighten_H +#define CoinPresolveTighten_H + +#include "CoinPresolveMatrix.hpp" + +// This action has no separate class; +// instead, it decides which columns can be made fixed +// and calls make_fixed_action::presolve. +const CoinPresolveAction *tighten_zero_cost(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + +#define DO_TIGHTEN 30 + +class do_tighten_action : public CoinPresolveAction { + do_tighten_action(); + do_tighten_action(const do_tighten_action& rhs); + do_tighten_action& operator=(const do_tighten_action& rhs); + + struct action { + int *rows; + double *lbound; + double *ubound; + int col; + int nrows; + int direction; // just for assertions + }; + + const int nactions_; + const action *const actions_; + + do_tighten_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) {} + + public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~do_tighten_action(); + +}; +#endif + + diff --git a/thirdparty/linux/include/coin/CoinPresolveTripleton.hpp b/thirdparty/linux/include/coin/CoinPresolveTripleton.hpp new file mode 100644 index 0000000..eaa79c5 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveTripleton.hpp @@ -0,0 +1,66 @@ +/* $Id: CoinPresolveTripleton.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveTripleton_H +#define CoinPresolveTripleton_H +#define TRIPLETON 11 +/** We are only going to do this if it does not increase number of elements?. + It could be generalized to more than three but it seems unlikely it would + help. + + As it is adapted from doubleton icoly is one dropped. + */ +class tripleton_action : public CoinPresolveAction { + public: + struct action { + int icolx; + int icolz; + int row; + + int icoly; + double cloy; + double cupy; + double costy; + double clox; + double cupx; + double costx; + + double rlo; + double rup; + + double coeffx; + double coeffy; + double coeffz; + + double *colel; + + int ncolx; + int ncoly; + }; + + const int nactions_; + const action *const actions_; + + private: + tripleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nactions_(nactions), actions_(actions) +{} + + public: + const char *name() const { return ("tripleton_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~tripleton_action(); +}; +#endif + + diff --git a/thirdparty/linux/include/coin/CoinPresolveUseless.hpp b/thirdparty/linux/include/coin/CoinPresolveUseless.hpp new file mode 100644 index 0000000..624a373 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveUseless.hpp @@ -0,0 +1,63 @@ +/* $Id: CoinPresolveUseless.hpp 1566 2012-11-29 19:33:56Z lou $ */ +// 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). + +#ifndef CoinPresolveUseless_H +#define CoinPresolveUseless_H +#define USELESS 20 + +class useless_constraint_action : public CoinPresolveAction { + struct action { + double rlo; + double rup; + const int *rowcols; + const double *rowels; + int row; + int ninrow; + }; + + const int nactions_; + const action *const actions_; + + useless_constraint_action(int nactions, + const action *actions, + const CoinPresolveAction *next); + + public: + const char *name() const; + + // These rows are asserted to be useless, + // that is, given a solution the row activity + // must be in range. + static const CoinPresolveAction *presolve(CoinPresolveMatrix * prob, + const int *useless_rows, + int nuseless_rows, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~useless_constraint_action(); + +}; + +/*! \relates useless_constraint_action + \brief Scan constraints looking for useless constraints + + A front end to identify useless constraints and hand them to + useless_constraint_action::presolve() for processing. + + In a bit more detail, the routine implements a greedy algorithm that + identifies a set of necessary constraints. A constraint is necessary if it + implies a tighter bound on a variable than the original column bound. These + tighter column bounds are then used to calculate row activity and identify + constraints that are useless given the presence of the necessary + constraints. +*/ + +const CoinPresolveAction *testRedundant(CoinPresolveMatrix *prob, + const CoinPresolveAction *next) ; + + + +#endif diff --git a/thirdparty/linux/include/coin/CoinPresolveZeros.hpp b/thirdparty/linux/include/coin/CoinPresolveZeros.hpp new file mode 100644 index 0000000..219e613 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinPresolveZeros.hpp @@ -0,0 +1,60 @@ +/* $Id: CoinPresolveZeros.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// 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). + +#ifndef CoinPresolveZeros_H +#define CoinPresolveZeros_H + +/*! \file + + Drop/reintroduce explicit zeros. +*/ + +#define DROP_ZERO 8 + +/*! \brief Tracking information for an explicit zero coefficient + + \todo Why isn't this a nested class in drop_zero_coefficients_action? + That would match the structure of other presolve classes. +*/ + +struct dropped_zero { + int row; + int col; +}; + +/*! \brief Removal of explicit zeros + + The presolve action for this class removes explicit zeros from the constraint + matrix. The postsolve action puts them back. +*/ +class drop_zero_coefficients_action : public CoinPresolveAction { + + const int nzeros_; + const dropped_zero *const zeros_; + + drop_zero_coefficients_action(int nzeros, + const dropped_zero *zeros, + const CoinPresolveAction *next) : + CoinPresolveAction(next), + nzeros_(nzeros), zeros_(zeros) +{} + + public: + const char *name() const { return ("drop_zero_coefficients_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + int *checkcols, + int ncheckcols, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~drop_zero_coefficients_action() { deleteAction(zeros_,dropped_zero*); } +}; + +const CoinPresolveAction *drop_zero_coefficients(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + +#endif diff --git a/thirdparty/linux/include/coin/CoinRational.hpp b/thirdparty/linux/include/coin/CoinRational.hpp new file mode 100644 index 0000000..bfbfa5f --- /dev/null +++ b/thirdparty/linux/include/coin/CoinRational.hpp @@ -0,0 +1,44 @@ +// Authors: Matthew Saltzman and Ted Ralphs +// Copyright 2015, Matthew Saltzman and Ted Ralphs +// Licensed under the Eclipse Public License 1.0 + +#ifndef CoinRational_H +#define CoinRational_H + +#include <cmath> + +//Small class for rational numbers +class CoinRational +{ + +public : + long getDenominator() { return denominator_; } + long getNumerator() { return numerator_; } + + CoinRational(): + numerator_(0), + denominator_(1) + {}; + + CoinRational(long n, long d): + numerator_(n), + denominator_(d) + {}; + + CoinRational(double val, double maxdelta, long maxdnom) + { + if (!nearestRational_(val, maxdelta, maxdnom)){ + numerator_ = 0; + denominator_ = 1; + } + }; + +private : + + long numerator_; + long denominator_; + + bool nearestRational_(double val, double maxdelta, long maxdnom); +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinSearchTree.hpp b/thirdparty/linux/include/coin/CoinSearchTree.hpp new file mode 100644 index 0000000..a0ce8e3 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinSearchTree.hpp @@ -0,0 +1,465 @@ +/* $Id: CoinSearchTree.hpp 1685 2014-01-27 03:05:07Z tkr $ */ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinSearchTree_H +#define CoinSearchTree_H + +#include <vector> +#include <algorithm> +#include <cmath> +#include <string> + +#include "CoinFinite.hpp" +#include "CoinHelperFunctions.hpp" + +// #define DEBUG_PRINT + +//############################################################################# + +class BitVector128 { + friend bool operator<(const BitVector128& b0, const BitVector128& b1); +private: + unsigned int bits_[4]; +public: + BitVector128(); + BitVector128(unsigned int bits[4]); + ~BitVector128() {} + void set(unsigned int bits[4]); + void setBit(int i); + void clearBit(int i); + std::string str() const; +}; + +bool operator<(const BitVector128& b0, const BitVector128& b1); + +//############################################################################# + +/** A class from which the real tree nodes should be derived from. Some of the + data that undoubtedly exist in the real tree node is replicated here for + fast access. This class is used in the various comparison functions. */ +class CoinTreeNode { +protected: + CoinTreeNode() : + depth_(-1), + fractionality_(-1), + quality_(-COIN_DBL_MAX), + true_lower_bound_(-COIN_DBL_MAX), + preferred_() {} + CoinTreeNode(int d, + int f = -1, + double q = -COIN_DBL_MAX, + double tlb = -COIN_DBL_MAX, + BitVector128 p = BitVector128()) : + depth_(d), + fractionality_(f), + quality_(q), + true_lower_bound_(tlb), + preferred_(p) {} + CoinTreeNode(const CoinTreeNode& x) : + depth_(x.depth_), + fractionality_(x.fractionality_), + quality_(x.quality_), + true_lower_bound_(x.true_lower_bound_), + preferred_(x.preferred_) {} + CoinTreeNode& operator=(const CoinTreeNode& x) { + if (this != &x) { + depth_ = x.depth_; + fractionality_ = x.fractionality_; + quality_ = x.quality_; + true_lower_bound_ = x.true_lower_bound_; + preferred_ = x.preferred_; + } + return *this; + } +private: + /// The depth of the node in the tree + int depth_; + /** A measure of fractionality, e.g., the number of unsatisfied + integrality requirements */ + int fractionality_; + /** Some quality for the node. For normal branch-and-cut problems the LP + relaxation value will do just fine. It is probably an OK approximation + even if column generation is done. */ + double quality_; + /** A true lower bound on the node. May be -infinity. For normal + branch-and-cut problems the LP relaxation value is OK. It is different + when column generation is done. */ + double true_lower_bound_; + /** */ + BitVector128 preferred_; +public: + virtual ~CoinTreeNode() {} + + inline int getDepth() const { return depth_; } + inline int getFractionality() const { return fractionality_; } + inline double getQuality() const { return quality_; } + inline double getTrueLB() const { return true_lower_bound_; } + inline BitVector128 getPreferred() const { return preferred_; } + + inline void setDepth(int d) { depth_ = d; } + inline void setFractionality(int f) { fractionality_ = f; } + inline void setQuality(double q) { quality_ = q; } + inline void setTrueLB(double tlb) { true_lower_bound_ = tlb; } + inline void setPreferred(BitVector128 p) { preferred_ = p; } +}; + +//============================================================================== + +class CoinTreeSiblings { +private: + CoinTreeSiblings(); + CoinTreeSiblings& operator=(const CoinTreeSiblings&); +private: + int current_; + int numSiblings_; + CoinTreeNode** siblings_; +public: + CoinTreeSiblings(const int n, CoinTreeNode** nodes) : + current_(0), numSiblings_(n), siblings_(new CoinTreeNode*[n]) + { + CoinDisjointCopyN(nodes, n, siblings_); + } + CoinTreeSiblings(const CoinTreeSiblings& s) : + current_(s.current_), + numSiblings_(s.numSiblings_), + siblings_(new CoinTreeNode*[s.numSiblings_]) + { + CoinDisjointCopyN(s.siblings_, s.numSiblings_, siblings_); + } + ~CoinTreeSiblings() { delete[] siblings_; } + inline CoinTreeNode* currentNode() const { return siblings_[current_]; } + /** returns false if cannot be advanced */ + inline bool advanceNode() { return ++current_ != numSiblings_; } + inline int toProcess() const { return numSiblings_ - current_; } + inline int size() const { return numSiblings_; } + inline void printPref() const { + for (int i = 0; i < numSiblings_; ++i) { + std::string pref = siblings_[i]->getPreferred().str(); + printf("prefs of sibligs: sibling[%i]: %s\n", i, pref.c_str()); + } + } +}; + +//############################################################################# + +/** Function objects to compare search tree nodes. The comparison function + must return true if the first argument is "better" than the second one, + i.e., it should be processed first. */ +/*@{*/ +/** Depth First Search. */ +struct CoinSearchTreeComparePreferred { + static inline const char* name() { return "CoinSearchTreeComparePreferred"; } + inline bool operator()(const CoinTreeSiblings* x, + const CoinTreeSiblings* y) const { + register const CoinTreeNode* xNode = x->currentNode(); + register const CoinTreeNode* yNode = y->currentNode(); + const BitVector128 xPref = xNode->getPreferred(); + const BitVector128 yPref = yNode->getPreferred(); + bool retval = true; + if (xPref < yPref) { + retval = true; + } else if (yPref < xPref) { + retval = false; + } else { + retval = xNode->getQuality() < yNode->getQuality(); + } +#ifdef DEBUG_PRINT + printf("Comparing xpref (%s) and ypref (%s) : %s\n", + xpref.str().c_str(), ypref.str().c_str(), retval ? "T" : "F"); +#endif + return retval; + } +}; + +//----------------------------------------------------------------------------- +/** Depth First Search. */ +struct CoinSearchTreeCompareDepth { + static inline const char* name() { return "CoinSearchTreeCompareDepth"; } + inline bool operator()(const CoinTreeSiblings* x, + const CoinTreeSiblings* y) const { +#if 1 + return x->currentNode()->getDepth() >= y->currentNode()->getDepth(); +#else + if(x->currentNode()->getDepth() > y->currentNode()->getDepth()) + return 1; + if(x->currentNode()->getDepth() == y->currentNode()->getDepth() && + x->currentNode()->getQuality() <= y->currentNode()->getQuality()) + return 1; + return 0; +#endif + } +}; + +//----------------------------------------------------------------------------- +/* Breadth First Search */ +struct CoinSearchTreeCompareBreadth { + static inline const char* name() { return "CoinSearchTreeCompareBreadth"; } + inline bool operator()(const CoinTreeSiblings* x, + const CoinTreeSiblings* y) const { + return x->currentNode()->getDepth() < y->currentNode()->getDepth(); + } +}; + +//----------------------------------------------------------------------------- +/** Best first search */ +struct CoinSearchTreeCompareBest { + static inline const char* name() { return "CoinSearchTreeCompareBest"; } + inline bool operator()(const CoinTreeSiblings* x, + const CoinTreeSiblings* y) const { + return x->currentNode()->getQuality() < y->currentNode()->getQuality(); + } +}; + +//############################################################################# + +class CoinSearchTreeBase +{ +private: + CoinSearchTreeBase(const CoinSearchTreeBase&); + CoinSearchTreeBase& operator=(const CoinSearchTreeBase&); + +protected: + std::vector<CoinTreeSiblings*> candidateList_; + int numInserted_; + int size_; + +protected: + CoinSearchTreeBase() : candidateList_(), numInserted_(0), size_(0) {} + + virtual void realpop() = 0; + virtual void realpush(CoinTreeSiblings* s) = 0; + virtual void fixTop() = 0; + +public: + virtual ~CoinSearchTreeBase() {} + virtual const char* compName() const = 0; + + inline const std::vector<CoinTreeSiblings*>& getCandidates() const { + return candidateList_; + } + inline bool empty() const { return candidateList_.empty(); } + inline int size() const { return size_; } + inline int numInserted() const { return numInserted_; } + inline CoinTreeNode* top() const { + if (size_ == 0) + return NULL; +#ifdef DEBUG_PRINT + char output[44]; + output[43] = 0; + candidateList_.front()->currentNode()->getPreferred().print(output); + printf("top's pref: %s\n", output); +#endif + return candidateList_.front()->currentNode(); + } + /** pop will advance the \c next pointer among the siblings on the top and + then moves the top to its correct position. #realpop is the method + that actually removes the element from the heap */ + inline void pop() { + CoinTreeSiblings* s = candidateList_.front(); + if (!s->advanceNode()) { + realpop(); + delete s; + } else { + fixTop(); + } + --size_; + } + inline void push(int numNodes, CoinTreeNode** nodes, + const bool incrInserted = true) { + CoinTreeSiblings* s = new CoinTreeSiblings(numNodes, nodes); + realpush(s); + if (incrInserted) { + numInserted_ += numNodes; + } + size_ += numNodes; + } + inline void push(const CoinTreeSiblings& sib, + const bool incrInserted = true) { + CoinTreeSiblings* s = new CoinTreeSiblings(sib); +#ifdef DEBUG_PRINT + s->printPref(); +#endif + realpush(s); + if (incrInserted) { + numInserted_ += sib.toProcess(); + } + size_ += sib.toProcess(); + } +}; + +//############################################################################# + +// #define CAN_TRUST_STL_HEAP +#ifdef CAN_TRUST_STL_HEAP + +template <class Comp> +class CoinSearchTree : public CoinSearchTreeBase +{ +private: + Comp comp_; +protected: + virtual void realpop() { + candidateList_.pop_back(); + } + virtual void fixTop() { + CoinTreeSiblings* s = top(); + realpop(); + push(s, false); + } + virtual void realpush(CoinTreeSiblings* s) { + nodes_.push_back(s); + std::push_heap(candidateList_.begin(), candidateList_.end(), comp_); + } +public: + CoinSearchTree() : CoinSearchTreeBase(), comp_() {} + CoinSearchTree(const CoinSearchTreeBase& t) : + CoinSearchTreeBase(), comp_() { + candidateList_ = t.getCandidates(); + std::make_heap(candidateList_.begin(), candidateList_.end(), comp_); + numInserted_ = t.numInserted_; + size_ = t.size_; + } + ~CoinSearchTree() {} + const char* compName() const { return Comp::name(); } +}; + +#else + +template <class Comp> +class CoinSearchTree : public CoinSearchTreeBase +{ +private: + Comp comp_; + +protected: + virtual void realpop() { + candidateList_[0] = candidateList_.back(); + candidateList_.pop_back(); + fixTop(); + } + /** After changing data in the top node, fix the heap */ + virtual void fixTop() { + const size_t size = candidateList_.size(); + if (size > 1) { + CoinTreeSiblings** candidates = &candidateList_[0]; + CoinTreeSiblings* s = candidates[0]; + --candidates; + size_t pos = 1; + size_t ch; + for (ch = 2; ch < size; pos = ch, ch *= 2) { + if (comp_(candidates[ch+1], candidates[ch])) + ++ch; + if (comp_(s, candidates[ch])) + break; + candidates[pos] = candidates[ch]; + } + if (ch == size) { + if (comp_(candidates[ch], s)) { + candidates[pos] = candidates[ch]; + pos = ch; + } + } + candidates[pos] = s; + } + } + virtual void realpush(CoinTreeSiblings* s) { + candidateList_.push_back(s); + CoinTreeSiblings** candidates = &candidateList_[0]; + --candidates; + size_t pos = candidateList_.size(); + size_t ch; + for (ch = pos/2; ch != 0; pos = ch, ch /= 2) { + if (comp_(candidates[ch], s)) + break; + candidates[pos] = candidates[ch]; + } + candidates[pos] = s; + } + +public: + CoinSearchTree() : CoinSearchTreeBase(), comp_() {} + CoinSearchTree(const CoinSearchTreeBase& t) : + CoinSearchTreeBase(), comp_() { + candidateList_ = t.getCandidates(); + std::sort(candidateList_.begin(), candidateList_.end(), comp_); + numInserted_ = t.numInserted(); + size_ = t.size(); + } + virtual ~CoinSearchTree() {} + const char* compName() const { return Comp::name(); } +}; + +#endif + +//############################################################################# + +enum CoinNodeAction { + CoinAddNodeToCandidates, + CoinTestNodeForDiving, + CoinDiveIntoNode +}; + +class CoinSearchTreeManager +{ +private: + CoinSearchTreeManager(const CoinSearchTreeManager&); + CoinSearchTreeManager& operator=(const CoinSearchTreeManager&); +private: + CoinSearchTreeBase* candidates_; + int numSolution; + /** Whether there is an upper bound or not. The upper bound may have come + as input, not necessarily from a solution */ + bool hasUB_; + + /** variable used to test whether we need to reevaluate search strategy */ + bool recentlyReevaluatedSearchStrategy_; + +public: + CoinSearchTreeManager() : + candidates_(NULL), + numSolution(0), + recentlyReevaluatedSearchStrategy_(true) + {} + virtual ~CoinSearchTreeManager() { + delete candidates_; + } + + inline void setTree(CoinSearchTreeBase* t) { + delete candidates_; + candidates_ = t; + } + inline CoinSearchTreeBase* getTree() const { + return candidates_; + } + + inline bool empty() const { return candidates_->empty(); } + inline size_t size() const { return candidates_->size(); } + inline size_t numInserted() const { return candidates_->numInserted(); } + inline CoinTreeNode* top() const { return candidates_->top(); } + inline void pop() { candidates_->pop(); } + inline void push(CoinTreeNode* node, const bool incrInserted = true) { + candidates_->push(1, &node, incrInserted); + } + inline void push(const CoinTreeSiblings& s, const bool incrInserted=true) { + candidates_->push(s, incrInserted); + } + inline void push(const int n, CoinTreeNode** nodes, + const bool incrInserted = true) { + candidates_->push(n, nodes, incrInserted); + } + + inline CoinTreeNode* bestQualityCandidate() const { + return candidates_->top(); + } + inline double bestQuality() const { + return candidates_->top()->getQuality(); + } + void newSolution(double solValue); + void reevaluateSearchStrategy(); +}; + +//############################################################################# + +#endif diff --git a/thirdparty/linux/include/coin/CoinShallowPackedVector.hpp b/thirdparty/linux/include/coin/CoinShallowPackedVector.hpp new file mode 100644 index 0000000..07c1870 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinShallowPackedVector.hpp @@ -0,0 +1,148 @@ +/* $Id: CoinShallowPackedVector.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinShallowPackedVector_H +#define CoinShallowPackedVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +#endif + +#include "CoinError.hpp" +#include "CoinPackedVectorBase.hpp" + +/** Shallow Sparse Vector + +This class is for sparse vectors where the indices and +elements are stored elsewhere. This class only maintains +pointers to the indices and elements. Since this class +does not own the index and element data it provides +read only access to to the data. An CoinSparsePackedVector +must be used when the sparse vector's data will be altered. + +This class stores pointers to the vectors. +It does not actually contain the vectors. + +Here is a sample usage: +@verbatim + const int ne = 4; + int inx[ne] = { 1, 4, 0, 2 }; + double el[ne] = { 10., 40., 1., 50. }; + + // Create vector and set its value + CoinShallowPackedVector r(ne,inx,el); + + // access each index and element + assert( r.indices ()[0]== 1 ); + assert( r.elements()[0]==10. ); + assert( r.indices ()[1]== 4 ); + assert( r.elements()[1]==40. ); + assert( r.indices ()[2]== 0 ); + assert( r.elements()[2]== 1. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // Tests for equality and equivalence + CoinShallowPackedVector r1; + r1=r; + assert( r==r1 ); + r.sort(CoinIncrElementOrdered()); + assert( r!=r1 ); + + // Add packed vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinPackedVector add = r + r1; + assert( add[0] == 1.+ 1. ); + assert( add[1] == 10.+10. ); + assert( add[2] == 50.+50. ); + assert( add[3] == 0.+ 0. ); + assert( add[4] == 40.+40. ); + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +class CoinShallowPackedVector : public CoinPackedVectorBase { + friend void CoinShallowPackedVectorUnitTest(); + +public: + + /**@name Get methods */ + //@{ + /// Get length of indices and elements vectors + virtual int getNumElements() const { return nElements_; } + /// Get indices of elements + virtual const int * getIndices() const { return indices_; } + /// Get element values + virtual const double * getElements() const { return elements_; } + //@} + + /**@name Set methods */ + //@{ + /// Reset the vector (as if were just created an empty vector) + void clear(); + /** Assignment operator. */ + CoinShallowPackedVector& operator=(const CoinShallowPackedVector & x); + /** Assignment operator from a CoinPackedVectorBase. */ + CoinShallowPackedVector& operator=(const CoinPackedVectorBase & x); + /** just like the explicit constructor */ + void setVector(int size, const int * indices, const double * elements, + bool testForDuplicateIndex = true); + //@} + + /**@name Methods to create, set and destroy */ + //@{ + /** Default constructor. */ + CoinShallowPackedVector(bool testForDuplicateIndex = true); + /** Explicit Constructor. + Set vector size, indices, and elements. Size is the length of both the + indices and elements vectors. The indices and elements vectors are not + copied into this class instance. The ShallowPackedVector only maintains + the pointers to the indices and elements vectors. <br> + The last argument specifies whether the creator of the object knows in + advance that there are no duplicate indices. + */ + CoinShallowPackedVector(int size, + const int * indices, const double * elements, + bool testForDuplicateIndex = true); + /** Copy constructor from the base class. */ + CoinShallowPackedVector(const CoinPackedVectorBase &); + /** Copy constructor. */ + CoinShallowPackedVector(const CoinShallowPackedVector &); + /** Destructor. */ + virtual ~CoinShallowPackedVector() {} + /// Print vector information. + void print(); + //@} + +private: + /**@name Private member data */ + //@{ + /// Vector indices + const int * indices_; + ///Vector elements + const double * elements_; + /// Size of indices and elements vectors + int nElements_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CoinShallowPackedVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void +CoinShallowPackedVectorUnitTest(); + +#endif diff --git a/thirdparty/linux/include/coin/CoinSignal.hpp b/thirdparty/linux/include/coin/CoinSignal.hpp new file mode 100644 index 0000000..2bbf0d0 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinSignal.hpp @@ -0,0 +1,117 @@ +/* $Id: CoinSignal.hpp 1810 2015-03-13 20:16:34Z tkr $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _CoinSignal_hpp +#define _CoinSignal_hpp + +// This file is fully docified. +// There's nothing to docify... + +//############################################################################# + +#include <csignal> + +//############################################################################# + +#if defined(_MSC_VER) + typedef void (__cdecl *CoinSighandler_t) (int); +# define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if (defined(__GNUC__) && defined(__linux__)) + typedef sighandler_t CoinSighandler_t; +# define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__CYGWIN__) && defined(__GNUC__) + typedef __decltype(SIG_DFL) CoinSighandler_t; +# define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__MINGW32__) && defined(__GNUC__) + typedef __decltype(SIG_DFL) CoinSighandler_t; +# define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__FreeBSD__) && defined(__GNUC__) + typedef __decltype(SIG_DFL) CoinSighandler_t; +# define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__NetBSD__) && defined(__GNUC__) + typedef __decltype(SIG_DFL) CoinSighandler_t; +# define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(_AIX) +# if defined(__GNUC__) + typedef __decltype(SIG_DFL) CoinSighandler_t; +# define CoinSighandler_t_defined +# endif +#endif + +//----------------------------------------------------------------------------- + +#if defined (__hpux) +# define CoinSighandler_t_defined +# if defined(__GNUC__) + typedef __decltype(SIG_DFL) CoinSighandler_t; +# else + extern "C" { + typedef void (*CoinSighandler_t) (int); + } +# endif +#endif + +//----------------------------------------------------------------------------- + +#if defined(__sun) +# if defined(__SUNPRO_CC) +# include <signal.h> + extern "C" { + typedef void (*CoinSighandler_t) (int); + } +# define CoinSighandler_t_defined +# endif +# if defined(__GNUC__) + typedef __decltype(SIG_DFL) CoinSighandler_t; +# define CoinSighandler_t_defined +# endif +#endif + +//----------------------------------------------------------------------------- + +#if defined(__MACH__) && defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +# define CoinSighandler_t_defined +#endif + +//############################################################################# + +#ifndef CoinSighandler_t_defined +# warning("OS and/or compiler is not recognized. Defaulting to:"); +# warning("extern 'C' {") +# warning(" typedef void (*CoinSighandler_t) (int);") +# warning("}") + extern "C" { + typedef void (*CoinSighandler_t) (int); + } +#endif + +//############################################################################# + +#endif diff --git a/thirdparty/linux/include/coin/CoinSimpFactorization.hpp b/thirdparty/linux/include/coin/CoinSimpFactorization.hpp new file mode 100644 index 0000000..242b6cd --- /dev/null +++ b/thirdparty/linux/include/coin/CoinSimpFactorization.hpp @@ -0,0 +1,431 @@ +/* $Id: CoinSimpFactorization.hpp 1416 2011-04-17 09:57:29Z stefan $ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/* + This is a simple factorization of the LP Basis + */ +#ifndef CoinSimpFactorization_H +#define CoinSimpFactorization_H + +#include <iostream> +#include <string> +#include <cassert> +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinDenseFactorization.hpp" +class CoinPackedMatrix; + + +/// pointers used during factorization +class FactorPointers{ +public: + double *rowMax; + int *firstRowKnonzeros; + int *prevRow; + int *nextRow; + int *firstColKnonzeros; + int *prevColumn; + int *nextColumn; + int *newCols; + //constructor + FactorPointers( int numRows, int numCols, int *UrowLengths_, int *UcolLengths_ ); + // destructor + ~ FactorPointers(); +}; + +class CoinSimpFactorization : public CoinOtherFactorization { + friend void CoinSimpFactorizationUnitTest( const std::string & mpsDir ); + +public: + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinSimpFactorization ( ); + /// Copy constructor + CoinSimpFactorization ( const CoinSimpFactorization &other); + + /// Destructor + virtual ~CoinSimpFactorization ( ); + /// = copy + CoinSimpFactorization & operator = ( const CoinSimpFactorization & other ); + /// Clone + virtual CoinOtherFactorization * clone() const ; + //@} + + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas ( int numberRows, + int numberColumns, + CoinBigIndex maximumL, + CoinBigIndex maximumU ); + + /// PreProcesses column ordered copy of basis + virtual void preProcess ( ); + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor ( ); + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int * sequence, int * pivotVariable); + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int * sequence, int numberColumns); + //@} + + /**@name general stuff such as status */ + //@{ + /// Total number of elements in factorization + virtual inline int numberElements ( ) const { + return numberRows_*(numberColumns_+numberPivots_); + } + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn ( CoinIndexedVector * regionSparse, + int pivotRow, + double pivotCheck , + bool checkBeforeModifying=false, + double acceptablePivot=1.0e-8); + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + + virtual int updateColumnFT ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false); + + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false) const; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, + CoinIndexedVector * regionSparse2, + CoinIndexedVector * regionSparse3, + bool noPermute=false); + /// does updatecolumn if save==true keeps column for replace column + int upColumn ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2, + bool noPermute=false, bool save=false) const; + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2) const; + /// does updateColumnTranspose, the other is a wrapper + int upColumnTranspose ( CoinIndexedVector * regionSparse, + CoinIndexedVector * regionSparse2) const; + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + inline void clearArrays() + { gutsOfDestructor();} + /// Returns array to put basis indices in + inline int * indices() const + { return reinterpret_cast<int *> (elements_+numberRows_*numberRows_);} + /// Returns permute in + virtual inline int * permute() const + { return pivotRow_;} + //@} + + /// The real work of destructor + void gutsOfDestructor(); + /// The real work of constructor + void gutsOfInitialize(); + /// The real work of copy + void gutsOfCopy(const CoinSimpFactorization &other); + + + /// calls factorization + void factorize(int numberOfRows, + int numberOfColumns, + const int colStarts[], + const int indicesRow[], + const double elements[]); + /// main loop of factorization + int mainLoopFactor (FactorPointers &pointers ); + /// copies L by rows + void copyLbyRows(); + /// copies U by columns + void copyUbyColumns(); + /// finds a pivot element using Markowitz count + int findPivot(FactorPointers &pointers, int &r, int &s, bool &ifSlack); + /// finds a pivot in a shortest column + int findPivotShCol(FactorPointers &pointers, int &r, int &s); + /// finds a pivot in the first column available + int findPivotSimp(FactorPointers &pointers, int &r, int &s); + /// does Gauss elimination + void GaussEliminate(FactorPointers &pointers, int &r, int &s); + /// finds short row that intersects a given column + int findShortRow(const int column, const int length, int &minRow, + int &minRowLength, FactorPointers &pointers); + /// finds short column that intersects a given row + int findShortColumn(const int row, const int length, int &minCol, + int &minColLength, FactorPointers &pointers); + /// finds maximum absolute value in a row + double findMaxInRrow(const int row, FactorPointers &pointers); + /// does pivoting + void pivoting(const int pivotRow, const int pivotColumn, + const double invPivot, FactorPointers &pointers); + /// part of pivoting + void updateCurrentRow(const int pivotRow, const int row, + const double multiplier, FactorPointers &pointers, + int &newNonZeros); + /// allocates more space for L + void increaseLsize(); + /// allocates more space for a row of U + void increaseRowSize(const int row, const int newSize); + /// allocates more space for a column of U + void increaseColSize(const int column, const int newSize, const bool b); + /// allocates more space for rows of U + void enlargeUrow(const int numNewElements); + /// allocates more space for columns of U + void enlargeUcol(const int numNewElements, const bool b); + /// finds a given row in a column + int findInRow(const int row, const int column); + /// finds a given column in a row + int findInColumn(const int column, const int row); + /// declares a row inactive + void removeRowFromActSet(const int row, FactorPointers &pointers); + /// declares a column inactive + void removeColumnFromActSet(const int column, FactorPointers &pointers); + /// allocates space for U + void allocateSpaceForU(); + /// allocates several working arrays + void allocateSomeArrays(); + /// initializes some numbers + void initialSomeNumbers(); + /// solves L x = b + void Lxeqb(double *b) const; + /// same as above but with two rhs + void Lxeqb2(double *b1, double *b2) const; + /// solves U x = b + void Uxeqb(double *b, double *sol) const; + /// same as above but with two rhs + void Uxeqb2(double *b1, double *sol1, double *sol2, double *b2) const; + /// solves x L = b + void xLeqb(double *b) const; + /// solves x U = b + void xUeqb(double *b, double *sol) const; + /// updates factorization after a Simplex iteration + int LUupdate(int newBasicCol); + /// creates a new eta vector + void newEta(int row, int numNewElements); + /// makes a copy of row permutations + void copyRowPermutations(); + /// solves H x = b, where H is a product of eta matrices + void Hxeqb(double *b) const; + /// same as above but with two rhs + void Hxeqb2(double *b1, double *b2) const; + /// solves x H = b + void xHeqb(double *b) const; + /// does FTRAN + void ftran(double *b, double *sol, bool save) const; + /// same as above but with two columns + void ftran2(double *b1, double *sol1, double *b2, double *sol2) const; + /// does BTRAN + void btran(double *b, double *sol) const; + ///--------------------------------------- + + + + //@} +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; +////////////////// data ////////////////// +protected: + + /**@name data */ + //@{ + /// work array (should be initialized to zero) + double *denseVector_; + /// work array + double *workArea2_; + /// work array + double *workArea3_; + /// array of labels (should be initialized to zero) + int *vecLabels_; + /// array of indices + int *indVector_; + + /// auxiliary vector + double *auxVector_; + /// auxiliary vector + int *auxInd_; + + /// vector to keep for LUupdate + double *vecKeep_; + /// indices of this vector + int *indKeep_; + /// number of nonzeros + mutable int keepSize_; + + + + /// Starts of the rows of L + int *LrowStarts_; + /// Lengths of the rows of L + int *LrowLengths_; + /// L by rows + double *Lrows_; + /// indices in the rows of L + int *LrowInd_; + /// Size of Lrows_; + int LrowSize_; + /// Capacity of Lrows_ + int LrowCap_; + + /// Starts of the columns of L + int *LcolStarts_; + /// Lengths of the columns of L + int *LcolLengths_; + /// L by columns + double *Lcolumns_; + /// indices in the columns of L + int *LcolInd_; + /// numbers of elements in L + int LcolSize_; + /// maximum capacity of L + int LcolCap_; + + + /// Starts of the rows of U + int *UrowStarts_; + /// Lengths of the rows of U + int *UrowLengths_; +#ifdef COIN_SIMP_CAPACITY + /// Capacities of the rows of U + int *UrowCapacities_; +#endif + /// U by rows + double *Urows_; + /// Indices in the rows of U + int *UrowInd_; + /// maximum capacity of Urows + int UrowMaxCap_; + /// number of used places in Urows + int UrowEnd_; + /// first row in U + int firstRowInU_; + /// last row in U + int lastRowInU_; + /// previous row in U + int *prevRowInU_; + /// next row in U + int *nextRowInU_; + + /// Starts of the columns of U + int *UcolStarts_; + /// Lengths of the columns of U + int *UcolLengths_; +#ifdef COIN_SIMP_CAPACITY + /// Capacities of the columns of U + int *UcolCapacities_; +#endif + /// U by columns + double *Ucolumns_; + /// Indices in the columns of U + int *UcolInd_; + /// previous column in U + int *prevColInU_; + /// next column in U + int *nextColInU_; + /// first column in U + int firstColInU_; + /// last column in U + int lastColInU_; + /// maximum capacity of Ucolumns_ + int UcolMaxCap_; + /// last used position in Ucolumns_ + int UcolEnd_; + /// indicator of slack variables + int *colSlack_; + + /// inverse values of the elements of diagonal of U + double *invOfPivots_; + + /// permutation of columns + int *colOfU_; + /// position of column after permutation + int *colPosition_; + /// permutations of rows + int *rowOfU_; + /// position of row after permutation + int *rowPosition_; + /// permutations of rows during LUupdate + int *secRowOfU_; + /// position of row after permutation during LUupdate + int *secRowPosition_; + + /// position of Eta vector + int *EtaPosition_; + /// Starts of eta vectors + int *EtaStarts_; + /// Lengths of eta vectors + int *EtaLengths_; + /// columns of eta vectors + int *EtaInd_; + /// elements of eta vectors + double *Eta_; + /// number of elements in Eta_ + int EtaSize_; + /// last eta row + int lastEtaRow_; + /// maximum number of eta vectors + int maxEtaRows_; + /// Capacity of Eta_ + int EtaMaxCap_; + + /// minimum storage increase + int minIncrease_; + /// maximum size for the diagonal of U after update + double updateTol_; + /// do Shul heuristic + bool doSuhlHeuristic_; + /// maximum of U + double maxU_; + /// bound on the growth rate + double maxGrowth_; + /// maximum of A + double maxA_; + /// maximum number of candidates for pivot + int pivotCandLimit_; + /// number of slacks in basis + int numberSlacks_; + /// number of slacks in irst basis + int firstNumberSlacks_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CoinSmartPtr.hpp b/thirdparty/linux/include/coin/CoinSmartPtr.hpp new file mode 100644 index 0000000..93366a2 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinSmartPtr.hpp @@ -0,0 +1,528 @@ +// Copyright (C) 2004, 2006 International Business Machines and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. +// +// $Id: CoinSmartPtr.hpp 1520 2012-01-29 00:43:31Z tkr $ +// +// Authors: Carl Laird, Andreas Waechter IBM 2004-08-13 +// Removed lots of debugging stuff and reformatted: Laszlo Ladanyi, IBM +#ifndef CoinSmartPtr_hpp +#define CoinSmartPtr_hpp + +#include <list> +#include <cassert> +#include <cstddef> +#include <cstring> + +namespace Coin { + + //######################################################################### + + /** ReferencedObject class. + * This is part of the implementation of an intrusive smart pointer + * design. This class stores the reference count of all the smart + * pointers that currently reference it. See the documentation for + * the SmartPtr class for more details. + * + * A SmartPtr behaves much like a raw pointer, but manages the lifetime + * of an object, deleting the object automatically. This class implements + * a reference-counting, intrusive smart pointer design, where all + * objects pointed to must inherit off of ReferencedObject, which + * stores the reference count. Although this is intrusive (native types + * and externally authored classes require wrappers to be referenced + * by smart pointers), it is a safer design. A more detailed discussion of + * these issues follows after the usage information. + * + * Usage Example: + * Note: to use the SmartPtr, all objects to which you point MUST + * inherit off of ReferencedObject. + * + * \verbatim + * + * In MyClass.hpp... + * + * #include "CoinSmartPtr.hpp" + + * + * class MyClass : public Coin::ReferencedObject // must derive from ReferencedObject + * { + * ... + * } + * + * In my_usage.cpp... + * + * #include "CoinSmartPtr.hpp" + * #include "MyClass.hpp" + * + * void func(AnyObject& obj) + * { + * Coin::SmartPtr<MyClass> ptr_to_myclass = new MyClass(...); + * // ptr_to_myclass now points to a new MyClass, + * // and the reference count is 1 + * + * ... + * + * obj.SetMyClass(ptr_to_myclass); + * // Here, let's assume that AnyObject uses a + * // SmartPtr<MyClass> internally here. + * // Now, both ptr_to_myclass and the internal + * // SmartPtr in obj point to the same MyClass object + * // and its reference count is 2. + * + * ... + * + * // No need to delete ptr_to_myclass, this + * // will be done automatically when the + * // reference count drops to zero. + * + * } + * + * \endverbatim + * + * Other Notes: + * The SmartPtr implements both dereference operators -> & *. + * The SmartPtr does NOT implement a conversion operator to + * the raw pointer. Use the GetRawPtr() method when this + * is necessary. Make sure that the raw pointer is NOT + * deleted. + * The SmartPtr implements the comparison operators == & != + * for a variety of types. Use these instead of + * \verbatim + * if (GetRawPtr(smrt_ptr) == ptr) // Don't use this + * \endverbatim + * SmartPtr's, as currently implemented, do NOT handle circular references. + * For example: consider a higher level object using SmartPtrs to point + * to A and B, but A and B also point to each other (i.e. A has a + * SmartPtr to B and B has a SmartPtr to A). In this scenario, when the + * higher level object is finished with A and B, their reference counts + * will never drop to zero (since they reference each other) and they + * will not be deleted. This can be detected by memory leak tools like + * valgrind. If the circular reference is necessary, the problem can be + * overcome by a number of techniques: + * + * 1) A and B can have a method that "releases" each other, that is + * they set their internal SmartPtrs to NULL. + * \verbatim + * void AClass::ReleaseCircularReferences() + * { + * smart_ptr_to_B = NULL; + * } + * \endverbatim + * Then, the higher level class can call these methods before + * it is done using A & B. + * + * 2) Raw pointers can be used in A and B to reference each other. + * Here, an implicit assumption is made that the lifetime is + * controlled by the higher level object and that A and B will + * both exist in a controlled manner. Although this seems + * dangerous, in many situations, this type of referencing + * is very controlled and this is reasonably safe. + * + * 3) This SmartPtr class could be redesigned with the Weak/Strong + * design concept. Here, the SmartPtr is identified as being + * Strong (controls lifetime of the object) or Weak (merely + * referencing the object). The Strong SmartPtr increments + * (and decrements) the reference count in ReferencedObject + * but the Weak SmartPtr does not. In the example above, + * the higher level object would have Strong SmartPtrs to + * A and B, but A and B would have Weak SmartPtrs to each + * other. Then, when the higher level object was done with + * A and B, they would be deleted. The Weak SmartPtrs in A + * and B would not decrement the reference count and would, + * of course, not delete the object. This idea is very similar + * to item (2), where it is implied that the sequence of events + * is controlled such that A and B will not call anything using + * their pointers following the higher level delete (i.e. in + * their destructors!). This is somehow safer, however, because + * code can be written (however expensive) to perform run-time + * detection of this situation. For example, the ReferencedObject + * could store pointers to all Weak SmartPtrs that are referencing + * it and, in its destructor, tell these pointers that it is + * dying. They could then set themselves to NULL, or set an + * internal flag to detect usage past this point. + * + * Comments on Non-Intrusive Design: + * In a non-intrusive design, the reference count is stored somewhere other + * than the object being referenced. This means, unless the reference + * counting pointer is the first referencer, it must get a pointer to the + * referenced object from another smart pointer (so it has access to the + * reference count location). In this non-intrusive design, if we are + * pointing to an object with a smart pointer (or a number of smart + * pointers), and we then give another smart pointer the address through + * a RAW pointer, we will have two independent, AND INCORRECT, reference + * counts. To avoid this pitfall, we use an intrusive reference counting + * technique where the reference count is stored in the object being + * referenced. + */ + class ReferencedObject { + public: + ReferencedObject() : reference_count_(0) {} + virtual ~ReferencedObject() { assert(reference_count_ == 0); } + inline int ReferenceCount() const { return reference_count_; } + inline void AddRef() const { ++reference_count_; } + inline void ReleaseRef() const { --reference_count_; } + + private: + mutable int reference_count_; + }; + + //######################################################################### + + +//#define IP_DEBUG_SMARTPTR +#if COIN_IPOPT_CHECKLEVEL > 2 +# define IP_DEBUG_SMARTPTR +#endif +#ifdef IP_DEBUG_SMARTPTR +# include "IpDebug.hpp" +#endif + + /** Template class for Smart Pointers. + * A SmartPtr behaves much like a raw pointer, but manages the lifetime + * of an object, deleting the object automatically. This class implements + * a reference-counting, intrusive smart pointer design, where all + * objects pointed to must inherit off of ReferencedObject, which + * stores the reference count. Although this is intrusive (native types + * and externally authored classes require wrappers to be referenced + * by smart pointers), it is a safer design. A more detailed discussion of + * these issues follows after the usage information. + * + * Usage Example: + * Note: to use the SmartPtr, all objects to which you point MUST + * inherit off of ReferencedObject. + * + * \verbatim + * + * In MyClass.hpp... + * + * #include "CoinSmartPtr.hpp" + * + * class MyClass : public Coin::ReferencedObject // must derive from ReferencedObject + * { + * ... + * } + * + * In my_usage.cpp... + * + * #include "CoinSmartPtr.hpp" + * #include "MyClass.hpp" + * + * void func(AnyObject& obj) + * { + * SmartPtr<MyClass> ptr_to_myclass = new MyClass(...); + * // ptr_to_myclass now points to a new MyClass, + * // and the reference count is 1 + * + * ... + * + * obj.SetMyClass(ptr_to_myclass); + * // Here, let's assume that AnyObject uses a + * // SmartPtr<MyClass> internally here. + * // Now, both ptr_to_myclass and the internal + * // SmartPtr in obj point to the same MyClass object + * // and its reference count is 2. + * + * ... + * + * // No need to delete ptr_to_myclass, this + * // will be done automatically when the + * // reference count drops to zero. + * + * } + * + * \endverbatim + * + * It is not necessary to use SmartPtr's in all cases where an + * object is used that has been allocated "into" a SmartPtr. It is + * possible to just pass objects by reference or regular pointers, + * even if lower down in the stack a SmartPtr is to be held on to. + * Everything should work fine as long as a pointer created by "new" + * is immediately passed into a SmartPtr, and if SmartPtr's are used + * to hold on to objects. + * + * Other Notes: + * The SmartPtr implements both dereference operators -> & *. + * The SmartPtr does NOT implement a conversion operator to + * the raw pointer. Use the GetRawPtr() method when this + * is necessary. Make sure that the raw pointer is NOT + * deleted. + * The SmartPtr implements the comparison operators == & != + * for a variety of types. Use these instead of + * \verbatim + * if (GetRawPtr(smrt_ptr) == ptr) // Don't use this + * \endverbatim + * SmartPtr's, as currently implemented, do NOT handle circular references. + * For example: consider a higher level object using SmartPtrs to point to + * A and B, but A and B also point to each other (i.e. A has a SmartPtr + * to B and B has a SmartPtr to A). In this scenario, when the higher + * level object is finished with A and B, their reference counts will + * never drop to zero (since they reference each other) and they + * will not be deleted. This can be detected by memory leak tools like + * valgrind. If the circular reference is necessary, the problem can be + * overcome by a number of techniques: + * + * 1) A and B can have a method that "releases" each other, that is + * they set their internal SmartPtrs to NULL. + * \verbatim + * void AClass::ReleaseCircularReferences() + * { + * smart_ptr_to_B = NULL; + * } + * \endverbatim + * Then, the higher level class can call these methods before + * it is done using A & B. + * + * 2) Raw pointers can be used in A and B to reference each other. + * Here, an implicit assumption is made that the lifetime is + * controlled by the higher level object and that A and B will + * both exist in a controlled manner. Although this seems + * dangerous, in many situations, this type of referencing + * is very controlled and this is reasonably safe. + * + * 3) This SmartPtr class could be redesigned with the Weak/Strong + * design concept. Here, the SmartPtr is identified as being + * Strong (controls lifetime of the object) or Weak (merely + * referencing the object). The Strong SmartPtr increments + * (and decrements) the reference count in ReferencedObject + * but the Weak SmartPtr does not. In the example above, + * the higher level object would have Strong SmartPtrs to + * A and B, but A and B would have Weak SmartPtrs to each + * other. Then, when the higher level object was done with + * A and B, they would be deleted. The Weak SmartPtrs in A + * and B would not decrement the reference count and would, + * of course, not delete the object. This idea is very similar + * to item (2), where it is implied that the sequence of events + * is controlled such that A and B will not call anything using + * their pointers following the higher level delete (i.e. in + * their destructors!). This is somehow safer, however, because + * code can be written (however expensive) to perform run-time + * detection of this situation. For example, the ReferencedObject + * could store pointers to all Weak SmartPtrs that are referencing + * it and, in its destructor, tell these pointers that it is + * dying. They could then set themselves to NULL, or set an + * internal flag to detect usage past this point. + * + * Comments on Non-Intrusive Design: + * In a non-intrusive design, the reference count is stored somewhere other + * than the object being referenced. This means, unless the reference + * counting pointer is the first referencer, it must get a pointer to the + * referenced object from another smart pointer (so it has access to the + * reference count location). In this non-intrusive design, if we are + * pointing to an object with a smart pointer (or a number of smart + * pointers), and we then give another smart pointer the address through + * a RAW pointer, we will have two independent, AND INCORRECT, reference + * counts. To avoid this pitfall, we use an intrusive reference counting + * technique where the reference count is stored in the object being + * referenced. + */ + template <class T> + class SmartPtr { + public: + /** Returns the raw pointer contained. Use to get the value of the + * raw ptr (i.e. to pass to other methods/functions, etc.) Note: This + * method does NOT copy, therefore, modifications using this value + * modify the underlying object contained by the SmartPtr, NEVER + * delete this returned value. + */ + T* GetRawPtr() const { return ptr_; } + + /** Returns true if the SmartPtr is NOT NULL. + * Use this to check if the SmartPtr is not null + * This is preferred to if(GetRawPtr(sp) != NULL) + */ + bool IsValid() const { return ptr_ != NULL; } + + /** Returns true if the SmartPtr is NULL. + * Use this to check if the SmartPtr IsNull. + * This is preferred to if(GetRawPtr(sp) == NULL) + */ + bool IsNull() const { return ptr_ == NULL; } + + private: + /**@name Private Data/Methods */ + //@{ + /** Actual raw pointer to the object. */ + T* ptr_; + + /** Release the currently referenced object. */ + void ReleasePointer_() { + if (ptr_) { + ptr_->ReleaseRef(); + if (ptr_->ReferenceCount() == 0) { + delete ptr_; + } + ptr_ = NULL; + } + } + + /** Set the value of the internal raw pointer from another raw + * pointer, releasing the previously referenced object if necessary. */ + SmartPtr<T>& SetFromRawPtr_(T* rhs){ + ReleasePointer_(); // Release any old pointer + if (rhs != NULL) { + rhs->AddRef(); + ptr_ = rhs; + } + return *this; + } + + /** Set the value of the internal raw pointer from a SmartPtr, + * releasing the previously referenced object if necessary. */ + inline SmartPtr<T>& SetFromSmartPtr_(const SmartPtr<T>& rhs) { + SetFromRawPtr_(rhs.GetRawPtr()); + return (*this); + } + + //@} + + public: +#define dbg_smartptr_verbosity 0 + + /**@name Constructors/Destructors */ + //@{ + /** Default constructor, initialized to NULL */ + SmartPtr() : ptr_(NULL) {} + + /** Copy constructor, initialized from copy */ + SmartPtr(const SmartPtr<T>& copy) : ptr_(NULL) { + (void) SetFromSmartPtr_(copy); + } + + /** Constructor, initialized from T* ptr */ + SmartPtr(T* ptr) : ptr_(NULL) { + (void) SetFromRawPtr_(ptr); + } + + /** Destructor, automatically decrements the reference count, deletes + * the object if necessary.*/ + ~SmartPtr() { + ReleasePointer_(); + } + //@} + + /**@name Overloaded operators. */ + //@{ + /** Overloaded arrow operator, allows the user to call + * methods using the contained pointer. */ + T* operator->() const { +#if COIN_COINUTILS_CHECKLEVEL > 0 + assert(ptr_); +#endif + return ptr_; + } + + /** Overloaded dereference operator, allows the user + * to dereference the contained pointer. */ + T& operator*() const { +#if COIN_IPOPT_CHECKLEVEL > 0 + assert(ptr_); +#endif + return *ptr_; + } + + /** Overloaded equals operator, allows the user to + * set the value of the SmartPtr from a raw pointer */ + SmartPtr<T>& operator=(T* rhs) { + return SetFromRawPtr_(rhs); + } + + /** Overloaded equals operator, allows the user to + * set the value of the SmartPtr from another + * SmartPtr */ + SmartPtr<T>& operator=(const SmartPtr<T>& rhs) { + return SetFromSmartPtr_(rhs); + } + + /** Overloaded equality comparison operator, allows the + * user to compare the value of two SmartPtrs */ + template <class U1, class U2> + friend + bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs); + + /** Overloaded equality comparison operator, allows the + * user to compare the value of a SmartPtr with a raw pointer. */ + template <class U1, class U2> + friend + bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs); + + /** Overloaded equality comparison operator, allows the + * user to compare the value of a raw pointer with a SmartPtr. */ + template <class U1, class U2> + friend + bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs); + + /** Overloaded in-equality comparison operator, allows the + * user to compare the value of two SmartPtrs */ + template <class U1, class U2> + friend + bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs); + + /** Overloaded in-equality comparison operator, allows the + * user to compare the value of a SmartPtr with a raw pointer. */ + template <class U1, class U2> + friend + bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs); + + /** Overloaded in-equality comparison operator, allows the + * user to compare the value of a SmartPtr with a raw pointer. */ + template <class U1, class U2> + friend + bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs); + //@} + + }; + + template <class U1, class U2> + bool ComparePointers(const U1* lhs, const U2* rhs) { + if (lhs == rhs) { + return true; + } + // If lhs and rhs point to the same object with different interfaces + // U1 and U2, we cannot guarantee that the value of the pointers will + // be equivalent. We can guarantee this if we convert to void*. + return static_cast<const void*>(lhs) == static_cast<const void*>(rhs); + } + +} // namespace Coin + +//############################################################################# + +/**@name SmartPtr friends that are overloaded operators, so they are not in + the Coin namespace. */ +//@{ +template <class U1, class U2> +bool operator==(const Coin::SmartPtr<U1>& lhs, const Coin::SmartPtr<U2>& rhs) { + return Coin::ComparePointers(lhs.GetRawPtr(), rhs.GetRawPtr()); +} + +template <class U1, class U2> +bool operator==(const Coin::SmartPtr<U1>& lhs, U2* raw_rhs) { + return Coin::ComparePointers(lhs.GetRawPtr(), raw_rhs); +} + +template <class U1, class U2> +bool operator==(U1* raw_lhs, const Coin::SmartPtr<U2>& rhs) { + return Coin::ComparePointers(raw_lhs, rhs.GetRawPtr()); +} + +template <class U1, class U2> +bool operator!=(const Coin::SmartPtr<U1>& lhs, const Coin::SmartPtr<U2>& rhs) { + return ! operator==(lhs, rhs); +} + +template <class U1, class U2> +bool operator!=(const Coin::SmartPtr<U1>& lhs, U2* raw_rhs) { + return ! operator==(lhs, raw_rhs); +} + +template <class U1, class U2> +bool operator!=(U1* raw_lhs, const Coin::SmartPtr<U2>& rhs) { + return ! operator==(raw_lhs, rhs); +} +//@} + +#define CoinReferencedObject Coin::ReferencedObject +#define CoinSmartPtr Coin::SmartPtr +#define CoinComparePointers Coin::ComparePointers + +#endif diff --git a/thirdparty/linux/include/coin/CoinSnapshot.hpp b/thirdparty/linux/include/coin/CoinSnapshot.hpp new file mode 100644 index 0000000..e928026 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinSnapshot.hpp @@ -0,0 +1,476 @@ +/* $Id: CoinSnapshot.hpp 1416 2011-04-17 09:57:29Z stefan $ */ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinSnapshot_H +#define CoinSnapshot_H + +class CoinPackedMatrix; +#include "CoinTypes.hpp" + +//############################################################################# + +/** NON Abstract Base Class for interfacing with cut generators or branching code or .. + It is designed to be snapshot of a problem at a node in tree + + The class may or may not own the arrays - see owned_ + + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return arrays. +*/ + +class CoinSnapshot { + +public: + + //--------------------------------------------------------------------------- + /**@name Problem query methods + + The Matrix pointers may be NULL + */ + //@{ + /// Get number of columns + inline int getNumCols() const + { return numCols_;} + + /// Get number of rows + inline int getNumRows() const + { return numRows_;} + + /// Get number of nonzero elements + inline int getNumElements() const + { return numElements_;} + + /// Get number of integer variables + inline int getNumIntegers() const + { return numIntegers_;} + + /// Get pointer to array[getNumCols()] of column lower bounds + inline const double * getColLower() const + { return colLower_;} + + /// Get pointer to array[getNumCols()] of column upper bounds + inline const double * getColUpper() const + { return colUpper_;} + + /// Get pointer to array[getNumRows()] of row lower bounds + inline const double * getRowLower() const + { return rowLower_;} + + /// Get pointer to array[getNumRows()] of row upper bounds + inline const double * getRowUpper() const + { return rowUpper_;} + + /** Get pointer to array[getNumRows()] of row right-hand sides + This gives same results as OsiSolverInterface for useful cases + If getRowUpper()[i] != infinity then + getRightHandSide()[i] == getRowUpper()[i] + else + getRightHandSide()[i] == getRowLower()[i] + */ + inline const double * getRightHandSide() const + { return rightHandSide_;} + + /// Get pointer to array[getNumCols()] of objective function coefficients + inline const double * getObjCoefficients() const + { return objCoefficients_;} + + /// Get objective function sense (1 for min (default), -1 for max) + inline double getObjSense() const + { return objSense_;} + + /// Return true if variable is continuous + inline bool isContinuous(int colIndex) const + { return colType_[colIndex]=='C';} + + /// Return true if variable is binary + inline bool isBinary(int colIndex) const + { return colType_[colIndex]=='B';} + + /// Return true if column is integer. + inline bool isInteger(int colIndex) const + { return colType_[colIndex]=='B'||colType_[colIndex]=='I';} + + /// Return true if variable is general integer + inline bool isIntegerNonBinary(int colIndex) const + { return colType_[colIndex]=='I';} + + /// Return true if variable is binary and not fixed at either bound + inline bool isFreeBinary(int colIndex) const + { return colType_[colIndex]=='B'&&colUpper_[colIndex]>colLower_[colIndex];} + + /// Get colType array ('B', 'I', or 'C' for Binary, Integer and Continuous) + inline const char * getColType() const + { return colType_;} + + /// Get pointer to row-wise copy of current matrix + inline const CoinPackedMatrix * getMatrixByRow() const + { return matrixByRow_;} + + /// Get pointer to column-wise copy of current matrix + inline const CoinPackedMatrix * getMatrixByCol() const + { return matrixByCol_;} + + /// Get pointer to row-wise copy of "original" matrix + inline const CoinPackedMatrix * getOriginalMatrixByRow() const + { return originalMatrixByRow_;} + + /// Get pointer to column-wise copy of "original" matrix + inline const CoinPackedMatrix * getOriginalMatrixByCol() const + { return originalMatrixByCol_;} + //@} + + /**@name Solution query methods */ + //@{ + /// Get pointer to array[getNumCols()] of primal variable values + inline const double * getColSolution() const + { return colSolution_;} + + /// Get pointer to array[getNumRows()] of dual variable values + inline const double * getRowPrice() const + { return rowPrice_;} + + /// Get a pointer to array[getNumCols()] of reduced costs + inline const double * getReducedCost() const + { return reducedCost_;} + + /// Get pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector). + inline const double * getRowActivity() const + { return rowActivity_;} + + /// Get pointer to array[getNumCols()] of primal variable values which should not be separated (for debug) + inline const double * getDoNotSeparateThis() const + { return doNotSeparateThis_;} + //@} + + /**@name Other scalar get methods */ + //@{ + /// Get solver's value for infinity + inline double getInfinity() const + { return infinity_;} + + /** Get objective function value - includinbg any offset i.e. + sum c sub j * x subj - objValue = objOffset */ + inline double getObjValue() const + { return objValue_;} + + /// Get objective offset i.e. sum c sub j * x subj -objValue = objOffset + inline double getObjOffset() const + { return objOffset_;} + + /// Get dual tolerance + inline double getDualTolerance() const + { return dualTolerance_;} + + /// Get primal tolerance + inline double getPrimalTolerance() const + { return primalTolerance_;} + + /// Get integer tolerance + inline double getIntegerTolerance() const + { return integerTolerance_;} + + /// Get integer upper bound i.e. best solution * getObjSense + inline double getIntegerUpperBound() const + { return integerUpperBound_;} + + /// Get integer lower bound i.e. best possible solution * getObjSense + inline double getIntegerLowerBound() const + { return integerLowerBound_;} + //@} + + //--------------------------------------------------------------------------- + + /**@name Method to input a problem */ + //@{ + /** Load in an problem by copying the arguments (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + All solution type arrays will be deleted + */ + void loadProblem(const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub, + bool makeRowCopy=false); + + //@} + + //--------------------------------------------------------------------------- + + /**@name Methods to set data */ + //@{ + /// Set number of columns + inline void setNumCols(int value) + { numCols_ = value;} + + /// Set number of rows + inline void setNumRows(int value) + { numRows_ = value;} + + /// Set number of nonzero elements + inline void setNumElements(int value) + { numElements_ = value;} + + /// Set number of integer variables + inline void setNumIntegers(int value) + { numIntegers_ = value;} + + /// Set pointer to array[getNumCols()] of column lower bounds + void setColLower(const double * array, bool copyIn=true); + + /// Set pointer to array[getNumCols()] of column upper bounds + void setColUpper(const double * array, bool copyIn=true); + + /// Set pointer to array[getNumRows()] of row lower bounds + void setRowLower(const double * array, bool copyIn=true); + + /// Set pointer to array[getNumRows()] of row upper bounds + void setRowUpper(const double * array, bool copyIn=true); + + /** Set pointer to array[getNumRows()] of row right-hand sides + This gives same results as OsiSolverInterface for useful cases + If getRowUpper()[i] != infinity then + getRightHandSide()[i] == getRowUpper()[i] + else + getRightHandSide()[i] == getRowLower()[i] + */ + void setRightHandSide(const double * array, bool copyIn=true); + + /** Create array[getNumRows()] of row right-hand sides + using existing information + This gives same results as OsiSolverInterface for useful cases + If getRowUpper()[i] != infinity then + getRightHandSide()[i] == getRowUpper()[i] + else + getRightHandSide()[i] == getRowLower()[i] + */ + void createRightHandSide(); + + /// Set pointer to array[getNumCols()] of objective function coefficients + void setObjCoefficients(const double * array, bool copyIn=true); + + /// Set objective function sense (1 for min (default), -1 for max) + inline void setObjSense(double value) + { objSense_ = value;} + + /// Set colType array ('B', 'I', or 'C' for Binary, Integer and Continuous) + void setColType(const char *array, bool copyIn=true); + + /// Set pointer to row-wise copy of current matrix + void setMatrixByRow(const CoinPackedMatrix * matrix, bool copyIn=true); + + /// Create row-wise copy from MatrixByCol + void createMatrixByRow(); + + /// Set pointer to column-wise copy of current matrix + void setMatrixByCol(const CoinPackedMatrix * matrix, bool copyIn=true); + + /// Set pointer to row-wise copy of "original" matrix + void setOriginalMatrixByRow(const CoinPackedMatrix * matrix, bool copyIn=true); + + /// Set pointer to column-wise copy of "original" matrix + void setOriginalMatrixByCol(const CoinPackedMatrix * matrix, bool copyIn=true); + + /// Set pointer to array[getNumCols()] of primal variable values + void setColSolution(const double * array, bool copyIn=true); + + /// Set pointer to array[getNumRows()] of dual variable values + void setRowPrice(const double * array, bool copyIn=true); + + /// Set a pointer to array[getNumCols()] of reduced costs + void setReducedCost(const double * array, bool copyIn=true); + + /// Set pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector). + void setRowActivity(const double * array, bool copyIn=true); + + /// Set pointer to array[getNumCols()] of primal variable values which should not be separated (for debug) + void setDoNotSeparateThis(const double * array, bool copyIn=true); + + /// Set solver's value for infinity + inline void setInfinity(double value) + { infinity_ = value;} + + /// Set objective function value (including any rhs offset) + inline void setObjValue(double value) + { objValue_ = value;} + + /// Set objective offset i.e. sum c sub j * x subj -objValue = objOffset + inline void setObjOffset(double value) + { objOffset_ = value;} + + /// Set dual tolerance + inline void setDualTolerance(double value) + { dualTolerance_ = value;} + + /// Set primal tolerance + inline void setPrimalTolerance(double value) + { primalTolerance_ = value;} + + /// Set integer tolerance + inline void setIntegerTolerance(double value) + { integerTolerance_ = value;} + + /// Set integer upper bound i.e. best solution * getObjSense + inline void setIntegerUpperBound(double value) + { integerUpperBound_ = value;} + + /// Set integer lower bound i.e. best possible solution * getObjSense + inline void setIntegerLowerBound(double value) + { integerLowerBound_ = value;} + //@} + + //--------------------------------------------------------------------------- + + ///@name Constructors and destructors + //@{ + /// Default Constructor + CoinSnapshot(); + + /// Copy constructor + CoinSnapshot(const CoinSnapshot &); + + /// Assignment operator + CoinSnapshot & operator=(const CoinSnapshot& rhs); + + /// Destructor + virtual ~CoinSnapshot (); + + //@} + +private: + ///@name private functions + //@{ + /** Does main work of destructor - type (or'ed) + 1 - NULLify pointers + 2 - delete pointers + 4 - initialize scalars (tolerances etc) + 8 - initialize scalars (objValue etc0 + */ + void gutsOfDestructor(int type); + /// Does main work of copy + void gutsOfCopy(const CoinSnapshot & rhs); + //@} + + ///@name Private member data + + /// objective function sense (1 for min (default), -1 for max) + double objSense_; + + /// solver's value for infinity + double infinity_; + + /// objective function value (including any rhs offset) + double objValue_; + + /// objective offset i.e. sum c sub j * x subj -objValue = objOffset + double objOffset_; + + /// dual tolerance + double dualTolerance_; + + /// primal tolerance + double primalTolerance_; + + /// integer tolerance + double integerTolerance_; + + /// integer upper bound i.e. best solution * getObjSense + double integerUpperBound_; + + /// integer lower bound i.e. best possible solution * getObjSense + double integerLowerBound_; + + /// pointer to array[getNumCols()] of column lower bounds + const double * colLower_; + + /// pointer to array[getNumCols()] of column upper bounds + const double * colUpper_; + + /// pointer to array[getNumRows()] of row lower bounds + const double * rowLower_; + + /// pointer to array[getNumRows()] of row upper bounds + const double * rowUpper_; + + /// pointer to array[getNumRows()] of rhs side values + const double * rightHandSide_; + + /// pointer to array[getNumCols()] of objective function coefficients + const double * objCoefficients_; + + /// colType array ('B', 'I', or 'C' for Binary, Integer and Continuous) + const char * colType_; + + /// pointer to row-wise copy of current matrix + const CoinPackedMatrix * matrixByRow_; + + /// pointer to column-wise copy of current matrix + const CoinPackedMatrix * matrixByCol_; + + /// pointer to row-wise copy of "original" matrix + const CoinPackedMatrix * originalMatrixByRow_; + + /// pointer to column-wise copy of "original" matrix + const CoinPackedMatrix * originalMatrixByCol_; + + /// pointer to array[getNumCols()] of primal variable values + const double * colSolution_; + + /// pointer to array[getNumRows()] of dual variable values + const double * rowPrice_; + + /// a pointer to array[getNumCols()] of reduced costs + const double * reducedCost_; + + /// pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector). + const double * rowActivity_; + + /// pointer to array[getNumCols()] of primal variable values which should not be separated (for debug) + const double * doNotSeparateThis_; + + /// number of columns + int numCols_; + + /// number of rows + int numRows_; + + /// number of nonzero elements + int numElements_; + + /// number of integer variables + int numIntegers_; + + /// To say whether arrays etc are owned by CoinSnapshot + typedef struct { + unsigned int colLower:1; + unsigned int colUpper:1; + unsigned int rowLower:1; + unsigned int rowUpper:1; + unsigned int rightHandSide:1; + unsigned int objCoefficients:1; + unsigned int colType:1; + unsigned int matrixByRow:1; + unsigned int matrixByCol:1; + unsigned int originalMatrixByRow:1; + unsigned int originalMatrixByCol:1; + unsigned int colSolution:1; + unsigned int rowPrice:1; + unsigned int reducedCost:1; + unsigned int rowActivity:1; + unsigned int doNotSeparateThis:1; + } coinOwned; + coinOwned owned_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CoinSort.hpp b/thirdparty/linux/include/coin/CoinSort.hpp new file mode 100644 index 0000000..259fb35 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinSort.hpp @@ -0,0 +1,678 @@ +/* $Id: CoinSort.hpp 1594 2013-04-19 14:33:00Z forrest $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinSort_H +#define CoinSort_H + +#include <functional> +#include <new> +#include <algorithm> +#include "CoinDistance.hpp" + +// Uncomment the next three lines to get thorough initialisation of memory. +// #ifndef ZEROFAULT +// #define ZEROFAULT +// #endif + +#ifdef COIN_FAST_CODE +#ifndef COIN_USE_EKK_SORT +#define COIN_USE_EKK_SORT +#endif +#endif + +//############################################################################# + +/** An ordered pair. It's the same as std::pair, just this way it'll have the + same look as the triple sorting. */ +template <class S, class T> +struct CoinPair { +public: + /// First member of pair + S first; + /// Second member of pair + T second; +public: + /// Construct from ordered pair + CoinPair(const S& s, const T& t) : first(s), second(t) {} +}; + +//############################################################################# + +/**@name Comparisons on first element of two ordered pairs */ +//@{ +/** Function operator. + Returns true if t1.first < t2.first (i.e., increasing). */ +template < class S, class T> +class CoinFirstLess_2 { +public: + /// Compare function + inline bool operator()(const CoinPair<S,T>& t1, + const CoinPair<S,T>& t2) const + { return t1.first < t2.first; } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if t1.first > t2.first (i.e, decreasing). */ +template < class S, class T> +class CoinFirstGreater_2 { +public: + /// Compare function + inline bool operator()(const CoinPair<S,T>& t1, + const CoinPair<S,T>& t2) const + { return t1.first > t2.first; } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) < abs(t2.first) (i.e., increasing). */ +template < class S, class T> +class CoinFirstAbsLess_2 { +public: + /// Compare function + inline bool operator()(const CoinPair<S,T>& t1, + const CoinPair<S,T>& t2) const + { + const T t1Abs = t1.first < static_cast<T>(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast<T>(0) ? -t2.first : t2.first; + return t1Abs < t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) > abs(t2.first) (i.e., decreasing). */ +template < class S, class T> +class CoinFirstAbsGreater_2 { +public: + /// Compare function + inline bool operator()(CoinPair<S,T> t1, CoinPair<S,T> t2) const + { + const T t1Abs = t1.first < static_cast<T>(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast<T>(0) ? -t2.first : t2.first; + return t1Abs > t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first < vec[t2.first] (i.e., increasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class V> +class CoinExternalVectorFirstLess_2 { +private: + CoinExternalVectorFirstLess_2(); +private: + const V* vec_; +public: + inline bool operator()(const CoinPair<S,T>& t1, + const CoinPair<S,T>& t2) const + { return vec_[t1.first] < vec_[t2.first]; } + CoinExternalVectorFirstLess_2(const V* v) : vec_(v) {} +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first > vec[t2.first] (i.e., decreasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class V> +class CoinExternalVectorFirstGreater_2 { +private: + CoinExternalVectorFirstGreater_2(); +private: + const V* vec_; +public: + inline bool operator()(const CoinPair<S,T>& t1, + const CoinPair<S,T>& t2) const + { return vec_[t1.first] > vec_[t2.first]; } + CoinExternalVectorFirstGreater_2(const V* v) : vec_(v) {} +}; +//@} + +//############################################################################# + +/** Sort a pair of containers.<br> + + Iter_S - iterator for first container<br> + Iter_T - iterator for 2nd container<br> + CoinCompare2 - class comparing CoinPairs<br> +*/ + +#ifdef COIN_SORT_ARBITRARY_CONTAINERS +template <class Iter_S, class Iter_T, class CoinCompare2> void +CoinSort_2(Iter_S sfirst, Iter_S slast, Iter_T tfirst, const CoinCompare2& pc) +{ + typedef typename std::iterator_traits<Iter_S>::value_type S; + typedef typename std::iterator_traits<Iter_T>::value_type T; + const size_t len = coinDistance(sfirst, slast); + if (len <= 1) + return; + + typedef CoinPair<S,T> ST_pair; + ST_pair* x = static_cast<ST_pair*>(::operator new(len * sizeof(ST_pair))); +# ifdef ZEROFAULT + memset(x,0,(len*sizeof(ST_pair))) ; +# endif + + int i = 0; + Iter_S scurrent = sfirst; + Iter_T tcurrent = tfirst; + while (scurrent != slast) { + new (x+i++) ST_pair(*scurrent++, *tcurrent++); + } + + std::sort(x.begin(), x.end(), pc); + + scurrent = sfirst; + tcurrent = tfirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + } + + ::operator delete(x); +} +//----------------------------------------------------------------------------- +template <class Iter_S, class Iter_T> void +CoinSort_2(Iter_S sfirst, Iter_S slast, Iter_T tfirst) +{ + typedef typename std::iterator_traits<Iter_S>::value_type S; + typedef typename std::iterator_traits<Iter_T>::value_type T; + CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2<S,T>()); +} + +#else //======================================================================= + +template <class S, class T, class CoinCompare2> void +CoinSort_2(S* sfirst, S* slast, T* tfirst, const CoinCompare2& pc) +{ + const size_t len = coinDistance(sfirst, slast); + if (len <= 1) + return; + + typedef CoinPair<S,T> ST_pair; + ST_pair* x = static_cast<ST_pair*>(::operator new(len * sizeof(ST_pair))); +# ifdef ZEROFAULT + // Can show RUI errors on some systems due to copy of ST_pair with gaps. + // E.g., <int, double> has 4 byte alignment gap on Solaris/SUNWspro. + memset(x,0,(len*sizeof(ST_pair))) ; +# endif + + size_t i = 0; + S* scurrent = sfirst; + T* tcurrent = tfirst; + while (scurrent != slast) { + new (x+i++) ST_pair(*scurrent++, *tcurrent++); + } + + std::sort(x, x + len, pc); + + scurrent = sfirst; + tcurrent = tfirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + } + + ::operator delete(x); +} +template <class S, class T> void +// This Always uses std::sort +CoinSort_2Std(S* sfirst, S* slast, T* tfirst) +{ + CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2<S,T>()); +} +#ifndef COIN_USE_EKK_SORT +//----------------------------------------------------------------------------- +template <class S, class T> void +CoinSort_2(S* sfirst, S* slast, T* tfirst) +{ + CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2<S,T>()); +} +#else +//----------------------------------------------------------------------------- +extern int boundary_sort; +extern int boundary_sort2; +extern int boundary_sort3; +/// Sort without new and delete +template <class S, class T> void +CoinSort_2(S* key, S* lastKey, T* array2) +{ + const size_t number = coinDistance(key, lastKey); + if (number <= 1) { + return; + } else if (number>10000) { + CoinSort_2Std(key, lastKey, array2); + return; + } +#if 0 + if (number==boundary_sort3) { + printf("before sort %d entries\n",number); + for (int j=0;j<number;j++) { + std::cout<<" ( "<<key[j]<<","<<array2[j]<<")"; + } + std::cout<<std::endl; + } +#endif + int minsize=10; + int n = static_cast<int>(number); + int sp; + S *v = key; + S *m, t; + S * ls[32] , * rs[32]; + S *l , *r , c; + T it; + int j; + /*check already sorted */ + S last=key[0]; + for (j=1;j<n;j++) { + if (key[j]>=last) { + last=key[j]; + } else { + break; + } /* endif */ + } /* endfor */ + if (j==n) { + return; + } /* endif */ + sp = 0 ; ls[sp] = v ; rs[sp] = v + (n-1) ; + while( sp >= 0 ) + { + if ( rs[sp] - ls[sp] > minsize ) + { + l = ls[sp] ; r = rs[sp] ; m = l + (r-l)/2 ; + if ( *l > *m ) + { + t = *l ; *l = *m ; *m = t ; + it = array2[l-v] ; array2[l-v] = array2[m-v] ; array2[m-v] = it ; + } + if ( *m > *r ) + { + t = *m ; *m = *r ; *r = t ; + it = array2[m-v] ; array2[m-v] = array2[r-v] ; array2[r-v] = it ; + if ( *l > *m ) + { + t = *l ; *l = *m ; *m = t ; + it = array2[l-v] ; array2[l-v] = array2[m-v] ; array2[m-v] = it ; + } + } + c = *m ; + while ( r - l > 1 ) + { + while ( *(++l) < c ) ; + while ( *(--r) > c ) ; + t = *l ; *l = *r ; *r = t ; + it = array2[l-v] ; array2[l-v] = array2[r-v] ; array2[r-v] = it ; + } + l = r - 1 ; + if ( l < m ) + { ls[sp+1] = ls[sp] ; + rs[sp+1] = l ; + ls[sp ] = r ; + } + else + { ls[sp+1] = r ; + rs[sp+1] = rs[sp] ; + rs[sp ] = l ; + } + sp++ ; + } + else sp-- ; + } + for ( l = v , m = v + (n-1) ; l < m ; l++ ) + { if ( *l > *(l+1) ) + { + c = *(l+1) ; + it = array2[(l-v)+1] ; + for ( r = l ; r >= v && *r > c ; r-- ) + { + *(r+1) = *r ; + array2[(r-v)+1] = array2[(r-v)] ; + } + *(r+1) = c ; + array2[(r-v)+1] = it ; + } + } +#if 0 + if (number==boundary_sort3) { + printf("after sort %d entries\n",number); + for (int j=0;j<number;j++) { + std::cout<<" ( "<<key[j]<<","<<array2[j]<<")"; + } + std::cout<<std::endl; + CoinSort_2Many(key, lastKey, array2); + printf("after2 sort %d entries\n",number); + for (int j=0;j<number;j++) { + std::cout<<" ( "<<key[j]<<","<<array2[j]<<")"; + } + std::cout<<std::endl; + } +#endif +} +#endif +#endif +/// Sort without new and delete +template <class S, class T> void +CoinShortSort_2(S* key, S* lastKey, T* array2) +{ + const size_t number = coinDistance(key, lastKey); + if (number <= 2) { + if (number == 2 && key[0] > key[1]) { + S tempS = key[0]; + T tempT = array2[0]; + key[0] = key[1]; + array2[0] = array2[1]; + key[1] = tempS; + array2[1] = tempT; + } + return; + } else if (number>10000) { + CoinSort_2Std(key, lastKey, array2); + return; + } + int minsize=10; + size_t n = number; + int sp; + S *v = key; + S *m, t; + S * ls[32] , * rs[32]; + S *l , *r , c; + T it; + size_t j; + /*check already sorted */ + S last=key[0]; + for (j=1;j<n;j++) { + if (key[j]>=last) { + last=key[j]; + } else { + break; + } /* endif */ + } /* endfor */ + if (j==n) { + return; + } /* endif */ + sp = 0 ; ls[sp] = v ; rs[sp] = v + (n-1) ; + while( sp >= 0 ) + { + if ( rs[sp] - ls[sp] > minsize ) + { + l = ls[sp] ; r = rs[sp] ; m = l + (r-l)/2 ; + if ( *l > *m ) + { + t = *l ; *l = *m ; *m = t ; + it = array2[l-v] ; array2[l-v] = array2[m-v] ; array2[m-v] = it ; + } + if ( *m > *r ) + { + t = *m ; *m = *r ; *r = t ; + it = array2[m-v] ; array2[m-v] = array2[r-v] ; array2[r-v] = it ; + if ( *l > *m ) + { + t = *l ; *l = *m ; *m = t ; + it = array2[l-v] ; array2[l-v] = array2[m-v] ; array2[m-v] = it ; + } + } + c = *m ; + while ( r - l > 1 ) + { + while ( *(++l) < c ) ; + while ( *(--r) > c ) ; + t = *l ; *l = *r ; *r = t ; + it = array2[l-v] ; array2[l-v] = array2[r-v] ; array2[r-v] = it ; + } + l = r - 1 ; + if ( l < m ) + { ls[sp+1] = ls[sp] ; + rs[sp+1] = l ; + ls[sp ] = r ; + } + else + { ls[sp+1] = r ; + rs[sp+1] = rs[sp] ; + rs[sp ] = l ; + } + sp++ ; + } + else sp-- ; + } + for ( l = v , m = v + (n-1) ; l < m ; l++ ) + { if ( *l > *(l+1) ) + { + c = *(l+1) ; + it = array2[(l-v)+1] ; + for ( r = l ; r >= v && *r > c ; r-- ) + { + *(r+1) = *r ; + array2[(r-v)+1] = array2[(r-v)] ; + } + *(r+1) = c ; + array2[(r-v)+1] = it ; + } + } +} +//############################################################################# +//############################################################################# + +/**@name Ordered Triple Struct */ +template <class S, class T, class U> +class CoinTriple { +public: + /// First member of triple + S first; + /// Second member of triple + T second; + /// Third member of triple + U third; +public: + /// Construct from ordered triple + CoinTriple(const S& s, const T& t, const U& u):first(s),second(t),third(u) {} +}; + +//############################################################################# +/**@name Comparisons on first element of two ordered triples */ +//@{ +/** Function operator. + Returns true if t1.first < t2.first (i.e., increasing). */ +template < class S, class T, class U > +class CoinFirstLess_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple<S,T,U>& t1, + const CoinTriple<S,T,U>& t2) const + { return t1.first < t2.first; } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if t1.first > t2.first (i.e, decreasing). */ +template < class S, class T, class U > +class CoinFirstGreater_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple<S,T,U>& t1, + const CoinTriple<S,T,U>& t2) const + { return t1.first>t2.first; } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) < abs(t2.first) (i.e., increasing). */ +template < class S, class T, class U > +class CoinFirstAbsLess_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple<S,T,U>& t1, + const CoinTriple<S,T,U>& t2) const + { + const T t1Abs = t1.first < static_cast<T>(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast<T>(0) ? -t2.first : t2.first; + return t1Abs < t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) > abs(t2.first) (i.e., decreasing). */ +template < class S, class T, class U > +class CoinFirstAbsGreater_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple<S,T,U>& t1, + const CoinTriple<S,T,U>& t2) const + { + const T t1Abs = t1.first < static_cast<T>(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast<T>(0) ? -t2.first : t2.first; + return t1Abs > t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first < vec[t2.first] (i.e., increasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class U, class V> +class CoinExternalVectorFirstLess_3 { +private: + CoinExternalVectorFirstLess_3(); +private: + const V* vec_; +public: + inline bool operator()(const CoinTriple<S,T,U>& t1, + const CoinTriple<S,T,U>& t2) const + { return vec_[t1.first] < vec_[t2.first]; } + CoinExternalVectorFirstLess_3(const V* v) : vec_(v) {} +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first > vec[t2.first] (i.e., decreasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class U, class V> +class CoinExternalVectorFirstGreater_3 { +private: + CoinExternalVectorFirstGreater_3(); +private: + const V* vec_; +public: + inline bool operator()(const CoinTriple<S,T,U>& t1, + const CoinTriple<S,T,U>& t2) const + { return vec_[t1.first] > vec_[t2.first]; } + CoinExternalVectorFirstGreater_3(const V* v) : vec_(v) {} +}; +//@} + +//############################################################################# + +/**@name Typedefs for sorting the entries of a packed vector based on an + external vector. */ +//@{ +/// Sort packed vector in increasing order of the external vector +typedef CoinExternalVectorFirstLess_3<int, int, double, double> +CoinIncrSolutionOrdered; +/// Sort packed vector in decreasing order of the external vector +typedef CoinExternalVectorFirstGreater_3<int, int, double, double> +CoinDecrSolutionOrdered; +//@} + +//############################################################################# + +/** Sort a triple of containers.<br> + + Iter_S - iterator for first container<br> + Iter_T - iterator for 2nd container<br> + Iter_U - iterator for 3rd container<br> + CoinCompare3 - class comparing CoinTriples<br> +*/ +#ifdef COIN_SORT_ARBITRARY_CONTAINERS +template <class Iter_S, class Iter_T, class Iter_U, class CoinCompare3> void +CoinSort_3(Iter_S sfirst, Iter_S slast, Iter_T tfirst, Iter_U, ufirst, + const CoinCompare3& tc) +{ + typedef typename std::iterator_traits<Iter_S>::value_type S; + typedef typename std::iterator_traits<Iter_T>::value_type T; + typedef typename std::iterator_traits<Iter_U>::value_type U; + const size_t len = coinDistance(sfirst, slast); + if (len <= 1) + return; + + typedef CoinTriple<S,T,U> STU_triple; + STU_triple* x = + static_cast<STU_triple*>(::operator new(len * sizeof(STU_triple))); + + int i = 0; + Iter_S scurrent = sfirst; + Iter_T tcurrent = tfirst; + Iter_U ucurrent = ufirst; + while (scurrent != slast) { + new (x+i++) STU_triple(*scurrent++, *tcurrent++, *ucurrent++); + } + + std::sort(x, x+len, tc); + + scurrent = sfirst; + tcurrent = tfirst; + ucurrent = ufirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + *ucurrent++ = x[i].third; + } + + ::operator delete(x); +} +//----------------------------------------------------------------------------- +template <class Iter_S, class Iter_T, class Iter_U> void +CoinSort_3(Iter_S sfirst, Iter_S slast, Iter_T tfirst, Iter_U, ufirst) +{ + typedef typename std::iterator_traits<Iter_S>::value_type S; + typedef typename std::iterator_traits<Iter_T>::value_type T; + typedef typename std::iterator_traits<Iter_U>::value_type U; + CoinSort_3(sfirts, slast, tfirst, ufirst, CoinFirstLess_3<S,T,U>()); +} + +#else //======================================================================= + +template <class S, class T, class U, class CoinCompare3> void +CoinSort_3(S* sfirst, S* slast, T* tfirst, U* ufirst, const CoinCompare3& tc) +{ + const size_t len = coinDistance(sfirst,slast); + if (len <= 1) + return; + + typedef CoinTriple<S,T,U> STU_triple; + STU_triple* x = + static_cast<STU_triple*>(::operator new(len * sizeof(STU_triple))); + + size_t i = 0; + S* scurrent = sfirst; + T* tcurrent = tfirst; + U* ucurrent = ufirst; + while (scurrent != slast) { + new (x+i++) STU_triple(*scurrent++, *tcurrent++, *ucurrent++); + } + + std::sort(x, x+len, tc); + + scurrent = sfirst; + tcurrent = tfirst; + ucurrent = ufirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + *ucurrent++ = x[i].third; + } + + ::operator delete(x); +} +//----------------------------------------------------------------------------- +template <class S, class T, class U> void +CoinSort_3(S* sfirst, S* slast, T* tfirst, U* ufirst) +{ + CoinSort_3(sfirst, slast, tfirst, ufirst, CoinFirstLess_3<S,T,U>()); +} + +#endif + +//############################################################################# + +#endif diff --git a/thirdparty/linux/include/coin/CoinStructuredModel.hpp b/thirdparty/linux/include/coin/CoinStructuredModel.hpp new file mode 100644 index 0000000..19659b8 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinStructuredModel.hpp @@ -0,0 +1,247 @@ +/* $Id: CoinStructuredModel.hpp 1691 2014-03-19 12:43:56Z forrest $ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinStructuredModel_H +#define CoinStructuredModel_H + +#include "CoinModel.hpp" +#include <vector> + +/** + This is a model which is made up of Coin(Structured)Model blocks. +*/ + typedef struct CoinModelInfo2 { + int rowBlock; // Which row block + int columnBlock; // Which column block + char matrix; // nonzero if matrix exists + char rhs; // nonzero if non default rhs exists + char rowName; // nonzero if row names exists + char integer; // nonzero if integer information exists + char bounds; // nonzero if non default bounds/objective exists + char columnName; // nonzero if column names exists + CoinModelInfo2() : + rowBlock(0), + columnBlock(0), + matrix(0), + rhs(0), + rowName(0), + integer(0), + bounds(0), + columnName(0) + {} +} CoinModelBlockInfo; + +class CoinStructuredModel : public CoinBaseModel { + +public: + /**@name Useful methods for building model */ + //@{ + /** add a block from a CoinModel using names given as parameters + returns number of errors (e.g. both have objectives but not same) + */ + int addBlock(const std::string & rowBlock, + const std::string & columnBlock, + const CoinBaseModel & block); + /** add a block from a CoinModel with names in model + returns number of errors (e.g. both have objectives but not same) + */ + int addBlock(const CoinBaseModel & block); + /** add a block from a CoinModel using names given as parameters + returns number of errors (e.g. both have objectives but not same) + This passes in block - structured model takes ownership + */ + int addBlock(const std::string & rowBlock, + const std::string & columnBlock, + CoinBaseModel * block); + /** add a block using names + */ + int addBlock(const std::string & rowBlock, + const std::string & columnBlock, + const CoinPackedMatrix & matrix, + const double * rowLower, const double * rowUpper, + const double * columnLower, const double * columnUpper, + const double * objective); + + /** Write the problem in MPS format to a file with the given filename. + + \param compression can be set to three values to indicate what kind + of file should be written + <ul> + <li> 0: plain text (default) + <li> 1: gzip compressed (.gz is appended to \c filename) + <li> 2: bzip2 compressed (.bz2 is appended to \c filename) (TODO) + </ul> + If the library was not compiled with the requested compression then + writeMps falls back to writing a plain text file. + + \param formatType specifies the precision to used for values in the + MPS file + <ul> + <li> 0: normal precision (default) + <li> 1: extra accuracy + <li> 2: IEEE hex + </ul> + + \param numberAcross specifies whether 1 or 2 (default) values should be + specified on every data line in the MPS file. + + not const as may change model e.g. fill in default bounds + */ + int writeMps(const char *filename, int compression = 0, + int formatType = 0, int numberAcross = 2, bool keepStrings=false) ; + /// Read SMPS model + int readSmps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + + /** Decompose a CoinModel + 1 - try D-W + 2 - try Benders + 3 - try Staircase + Returns number of blocks or zero if no structure + */ + int decompose(const CoinModel &model,int type, + int maxBlocks=50, const char ** starts=NULL); + /** Decompose a model specified as arrays + CoinPackedMatrix + 1 - try D-W + 2 - try Benders + 3 - try Staircase + Returns number of blocks or zero if no structure + */ + int decompose(const CoinPackedMatrix & matrix, + const double * rowLower, const double * rowUpper, + const double * columnLower, const double * columnUpper, + const double * objective, int type,int maxBlocks=50, + int * starts=NULL, + double objectiveOffset=0.0); + + //@} + + + /**@name For getting information */ + //@{ + /// Return number of row blocks + inline int numberRowBlocks() const + { return numberRowBlocks_;} + /// Return number of column blocks + inline int numberColumnBlocks() const + { return numberColumnBlocks_;} + /// Return number of elementBlocks + inline CoinBigIndex numberElementBlocks() const + { return numberElementBlocks_;} + /// Return number of elements + CoinBigIndex numberElements() const; + /// Return the i'th row block name + inline const std::string & getRowBlock(int i) const + { return rowBlockNames_[i];} + /// Set i'th row block name + inline void setRowBlock(int i,const std::string &name) + { rowBlockNames_[i] = name;} + /// Add or check a row block name and number of rows + int addRowBlock(int numberRows,const std::string &name) ; + /// Return a row block index given a row block name + int rowBlock(const std::string &name) const; + /// Return i'th the column block name + inline const std::string & getColumnBlock(int i) const + { return columnBlockNames_[i];} + /// Set i'th column block name + inline void setColumnBlock(int i,const std::string &name) + { columnBlockNames_[i] = name;} + /// Add or check a column block name and number of columns + int addColumnBlock(int numberColumns,const std::string &name) ; + /// Return a column block index given a column block name + int columnBlock(const std::string &name) const; + /// Return i'th block type + inline const CoinModelBlockInfo & blockType(int i) const + { return blockType_[i];} + /// Return i'th block + inline CoinBaseModel * block(int i) const + { return blocks_[i];} + /// Return block corresponding to row and column + const CoinBaseModel * block(int row,int column) const; + /// Return i'th block as CoinModel (or NULL) + CoinModel * coinBlock(int i) const; + /// Return block corresponding to row and column as CoinModel + const CoinBaseModel * coinBlock(int row,int column) const; + /// Return block number corresponding to row and column + int blockIndex(int row,int column) const; + /** Return model as a CoinModel block + and fill in info structure and update counts + */ + CoinModel * coinModelBlock(CoinModelBlockInfo & info) ; + /// Sets given block into coinModelBlocks_ + void setCoinModel(CoinModel * block, int iBlock); + /// Refresh info in blockType_ + void refresh(int iBlock); + /** Fill pointers corresponding to row and column */ + + CoinModelBlockInfo block(int row,int column, + const double * & rowLower, const double * & rowUpper, + const double * & columnLower, const double * & columnUpper, + const double * & objective) const; + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const { + return optimizationDirection_; + } + /// Set direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline void setOptimizationDirection(double value) + { optimizationDirection_=value;} + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinStructuredModel(); + /** Read a problem in MPS format from the given filename. + May try and decompose + */ + CoinStructuredModel(const char *fileName,int decompose=0, + int maxBlocks=50); + /** Destructor */ + virtual ~CoinStructuredModel(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinStructuredModel(const CoinStructuredModel&); + /// = + CoinStructuredModel& operator=(const CoinStructuredModel&); + /// Clone + virtual CoinBaseModel * clone() const; + //@} + +private: + + /** Fill in info structure and update counts + Returns number of inconsistencies on border + */ + int fillInfo(CoinModelBlockInfo & info,const CoinModel * block); + /** Fill in info structure and update counts + */ + void fillInfo(CoinModelBlockInfo & info,const CoinStructuredModel * block); + /**@name Data members */ + //@{ + /// Current number of row blocks + int numberRowBlocks_; + /// Current number of column blocks + int numberColumnBlocks_; + /// Current number of element blocks + int numberElementBlocks_; + /// Maximum number of element blocks + int maximumElementBlocks_; + /// Rowblock name + std::vector<std::string> rowBlockNames_; + /// Columnblock name + std::vector<std::string> columnBlockNames_; + /// Blocks + CoinBaseModel ** blocks_; + /// CoinModel copies of blocks or NULL if original CoinModel + CoinModel ** coinModelBlocks_; + /// Which parts of model are set in block + CoinModelBlockInfo * blockType_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/CoinTime.hpp b/thirdparty/linux/include/coin/CoinTime.hpp new file mode 100644 index 0000000..49e8507 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinTime.hpp @@ -0,0 +1,310 @@ +/* $Id: CoinTime.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// 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). + +#ifndef _CoinTime_hpp +#define _CoinTime_hpp + +// Uncomment the next three lines for thorough memory initialisation. +// #ifndef ZEROFAULT +// # define ZEROFAULT +// #endif + +//############################################################################# + +#include <ctime> +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +#else +// MacOS-X and FreeBSD needs sys/time.h +#if defined(__MACH__) || defined (__FreeBSD__) +#include <sys/time.h> +#endif +#if !defined(__MSVCRT__) +#include <sys/resource.h> +#endif +#endif + +//############################################################################# + +#if defined(_MSC_VER) + +#if 0 // change this to 1 if want to use the win32 API +#include <windows.h> +#ifdef small +/* for some unfathomable reason (to me) rpcndr.h (pulled in by windows.h) does a + '#define small char' */ +#undef small +#endif +#define TWO_TO_THE_THIRTYTWO 4294967296.0 +#define DELTA_EPOCH_IN_SECS 11644473600.0 +inline double CoinGetTimeOfDay() +{ + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + double t = ft.dwHighDateTime * TWO_TO_THE_THIRTYTWO + ft.dwLowDateTime; + t = t/10000000.0 - DELTA_EPOCH_IN_SECS; + return t; +} +#else +#include <sys/types.h> +#include <sys/timeb.h> +inline double CoinGetTimeOfDay() +{ + struct _timeb timebuffer; +#pragma warning(disable:4996) + _ftime( &timebuffer ); // C4996 +#pragma warning(default:4996) + return timebuffer.time + timebuffer.millitm/1000.0; +} +#endif + +#else + +#include <sys/time.h> + +inline double CoinGetTimeOfDay() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return static_cast<double>(tv.tv_sec) + static_cast<int>(tv.tv_usec)/1000000.0; +} + +#endif // _MSC_VER + +/** + Query the elapsed wallclock time since the first call to this function. If + a positive argument is passed to the function then the time of the first + call is set to that value (this kind of argument is allowed only at the + first call!). If a negative argument is passed to the function then it + returns the time when it was set. +*/ + +inline double CoinWallclockTime(double callType = 0) +{ + double callTime = CoinGetTimeOfDay(); + static const double firstCall = callType > 0 ? callType : callTime; + return callType < 0 ? firstCall : callTime - firstCall; +} + +//############################################################################# + +//#define HAVE_SDK // if SDK under Win32 is installed, for CPU instead of elapsed time under Win +#ifdef HAVE_SDK +#include <windows.h> +#ifdef small +/* for some unfathomable reason (to me) rpcndr.h (pulled in by windows.h) does a + '#define small char' */ +#undef small +#endif +#define TWO_TO_THE_THIRTYTWO 4294967296.0 +#endif + +static inline double CoinCpuTime() +{ + double cpu_temp; +#if defined(_MSC_VER) || defined(__MSVCRT__) +#ifdef HAVE_SDK + FILETIME creation; + FILETIME exit; + FILETIME kernel; + FILETIME user; + GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user); + double t = user.dwHighDateTime * TWO_TO_THE_THIRTYTWO + user.dwLowDateTime; + return t/10000000.0; +#else + unsigned int ticksnow; /* clock_t is same as int */ + ticksnow = (unsigned int)clock(); + cpu_temp = (double)((double)ticksnow/CLOCKS_PER_SEC); +#endif + +#else + struct rusage usage; +# ifdef ZEROFAULT + usage.ru_utime.tv_sec = 0 ; + usage.ru_utime.tv_usec = 0 ; +# endif + getrusage(RUSAGE_SELF,&usage); + cpu_temp = static_cast<double>(usage.ru_utime.tv_sec); + cpu_temp += 1.0e-6*(static_cast<double> (usage.ru_utime.tv_usec)); +#endif + return cpu_temp; +} + +//############################################################################# + + + +static inline double CoinSysTime() +{ + double sys_temp; +#if defined(_MSC_VER) || defined(__MSVCRT__) + sys_temp = 0.0; +#else + struct rusage usage; +# ifdef ZEROFAULT + usage.ru_utime.tv_sec = 0 ; + usage.ru_utime.tv_usec = 0 ; +# endif + getrusage(RUSAGE_SELF,&usage); + sys_temp = static_cast<double>(usage.ru_stime.tv_sec); + sys_temp += 1.0e-6*(static_cast<double> (usage.ru_stime.tv_usec)); +#endif + return sys_temp; +} + +//############################################################################# +// On most systems SELF seems to include children threads, This is for when it doesn't +static inline double CoinCpuTimeJustChildren() +{ + double cpu_temp; +#if defined(_MSC_VER) || defined(__MSVCRT__) + cpu_temp = 0.0; +#else + struct rusage usage; +# ifdef ZEROFAULT + usage.ru_utime.tv_sec = 0 ; + usage.ru_utime.tv_usec = 0 ; +# endif + getrusage(RUSAGE_CHILDREN,&usage); + cpu_temp = static_cast<double>(usage.ru_utime.tv_sec); + cpu_temp += 1.0e-6*(static_cast<double> (usage.ru_utime.tv_usec)); +#endif + return cpu_temp; +} +//############################################################################# + +#include <fstream> + +/** + This class implements a timer that also implements a tracing functionality. + + The timer stores the start time of the timer, for how much time it was set to + and when does it expire (start + limit = end). Queries can be made that tell + whether the timer is expired, is past an absolute time, is past a percentage + of the length of the timer. All times are given in seconds, but as double + numbers, so there can be fractional values. + + The timer can also be initialized with a stream and a specification whether + to write to or read from the stream. In the former case the result of every + query is written into the stream, in the latter case timing is not tested at + all, rather the supposed result is read out from the stream. This makes it + possible to exactly retrace time sensitive program execution. +*/ +class CoinTimer +{ +private: + /// When the timer was initialized/reset/restarted + double start; + /// + double limit; + double end; +#ifdef COIN_COMPILE_WITH_TRACING + std::fstream* stream; + bool write_stream; +#endif + +private: +#ifdef COIN_COMPILE_WITH_TRACING + inline bool evaluate(bool b_tmp) const { + int i_tmp = b_tmp; + if (stream) { + if (write_stream) + (*stream) << i_tmp << "\n"; + else + (*stream) >> i_tmp; + } + return i_tmp; + } + inline double evaluate(double d_tmp) const { + if (stream) { + if (write_stream) + (*stream) << d_tmp << "\n"; + else + (*stream) >> d_tmp; + } + return d_tmp; + } +#else + inline bool evaluate(const bool b_tmp) const { + return b_tmp; + } + inline double evaluate(const double d_tmp) const { + return d_tmp; + } +#endif + +public: + /// Default constructor creates a timer with no time limit and no tracing + CoinTimer() : + start(0), limit(1e100), end(1e100) +#ifdef COIN_COMPILE_WITH_TRACING + , stream(0), write_stream(true) +#endif + {} + + /// Create a timer with the given time limit and with no tracing + CoinTimer(double lim) : + start(CoinCpuTime()), limit(lim), end(start+lim) +#ifdef COIN_COMPILE_WITH_TRACING + , stream(0), write_stream(true) +#endif + {} + +#ifdef COIN_COMPILE_WITH_TRACING + /** Create a timer with no time limit and with writing/reading the trace + to/from the given stream, depending on the argument \c write. */ + CoinTimer(std::fstream* s, bool write) : + start(0), limit(1e100), end(1e100), + stream(s), write_stream(write) {} + + /** Create a timer with the given time limit and with writing/reading the + trace to/from the given stream, depending on the argument \c write. */ + CoinTimer(double lim, std::fstream* s, bool w) : + start(CoinCpuTime()), limit(lim), end(start+lim), + stream(s), write_stream(w) {} +#endif + + /// Restart the timer (keeping the same time limit) + inline void restart() { start=CoinCpuTime(); end=start+limit; } + /// An alternate name for \c restart() + inline void reset() { restart(); } + /// Reset (and restart) the timer and change its time limit + inline void reset(double lim) { limit=lim; restart(); } + + /** Return whether the given percentage of the time limit has elapsed since + the timer was started */ + inline bool isPastPercent(double pct) const { + return evaluate(start + limit * pct < CoinCpuTime()); + } + /** Return whether the given amount of time has elapsed since the timer was + started */ + inline bool isPast(double lim) const { + return evaluate(start + lim < CoinCpuTime()); + } + /** Return whether the originally specified time limit has passed since the + timer was started */ + inline bool isExpired() const { + return evaluate(end < CoinCpuTime()); + } + + /** Return how much time is left on the timer */ + inline double timeLeft() const { + return evaluate(end - CoinCpuTime()); + } + + /** Return how much time has elapsed */ + inline double timeElapsed() const { + return evaluate(CoinCpuTime() - start); + } + + inline void setLimit(double l) { + limit = l; + return; + } +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinTypes.hpp b/thirdparty/linux/include/coin/CoinTypes.hpp new file mode 100644 index 0000000..3adee2e --- /dev/null +++ b/thirdparty/linux/include/coin/CoinTypes.hpp @@ -0,0 +1,64 @@ +/* $Id: CoinTypes.hpp 1762 2014-12-29 20:37:12Z tkr $ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _CoinTypes_hpp +#define _CoinTypes_hpp + +#include "CoinUtilsConfig.h" +/* On some systems, we require stdint.h to have the 64bit integer type defined. */ +#ifdef COINUTILS_HAS_STDINT_H +#include <stdint.h> +#endif +#ifdef COINUTILS_HAS_CSTDINT +#include <cstdint> +#endif + +#define CoinInt64 COIN_INT64_T +#define CoinUInt64 COIN_UINT64_T +#define CoinIntPtr COIN_INTPTR_T + +//============================================================================= +#ifndef COIN_BIG_INDEX +#define COIN_BIG_INDEX 0 +#endif + +#if COIN_BIG_INDEX==0 +typedef int CoinBigIndex; +#elif COIN_BIG_INDEX==1 +typedef long CoinBigIndex; +#else +typedef long long CoinBigIndex; +#endif + +//============================================================================= +#ifndef COIN_BIG_DOUBLE +#define COIN_BIG_DOUBLE 0 +#endif + +// See if we want the ability to have long double work arrays +#if COIN_BIG_DOUBLE==2 +#undef COIN_BIG_DOUBLE +#define COIN_BIG_DOUBLE 0 +#define COIN_LONG_WORK 1 +typedef long double CoinWorkDouble; +#elif COIN_BIG_DOUBLE==3 +#undef COIN_BIG_DOUBLE +#define COIN_BIG_DOUBLE 1 +#define COIN_LONG_WORK 1 +typedef long double CoinWorkDouble; +#else +#define COIN_LONG_WORK 0 +typedef double CoinWorkDouble; +#endif + +#if COIN_BIG_DOUBLE==0 +typedef double CoinFactorizationDouble; +#elif COIN_BIG_DOUBLE==1 +typedef long double CoinFactorizationDouble; +#else +typedef double CoinFactorizationDouble; +#endif + +#endif diff --git a/thirdparty/linux/include/coin/CoinUtility.hpp b/thirdparty/linux/include/coin/CoinUtility.hpp new file mode 100644 index 0000000..49a30e2 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinUtility.hpp @@ -0,0 +1,19 @@ +/* $Id: CoinUtility.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinUtility_h_ +#define CoinUtility_h_ + +#include "CoinSort.hpp" + +template <typename S, typename T> +CoinPair<S,T> CoinMakePair(const S& s, const T& t) +{ return CoinPair<S,T>(s, t); } + +template <typename S, typename T, typename U> +CoinTriple<S,T,U> CoinMakeTriple(const S& s, const T& t, const U& u) +{ return CoinTriple<S,T,U>(s, t, u); } + +#endif diff --git a/thirdparty/linux/include/coin/CoinUtilsConfig.h b/thirdparty/linux/include/coin/CoinUtilsConfig.h new file mode 100644 index 0000000..8d656d5 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinUtilsConfig.h @@ -0,0 +1,34 @@ +/* src/config_coinutils.h. Generated by configure. */ +/* inc/config_coinutils.h.in. */ + +#ifndef __CONFIG_COINUTILS_H__ +#define __CONFIG_COINUTILS_H__ + +/* Define to 1 if stdint.h is available for CoinUtils */ +#define COINUTILS_HAS_STDINT_H 1 + +/* Define to 1 if stdint.h is available for CoinUtils */ +/* #undef COINUTILS_HAS_CSTDINT */ + +/* Version number of project */ +#define COINUTILS_VERSION "2.10.6" + +/* Major Version number of project */ +#define COINUTILS_VERSION_MAJOR 2 + +/* Minor Version number of project */ +#define COINUTILS_VERSION_MINOR 10 + +/* Release Version number of project */ +#define COINUTILS_VERSION_RELEASE 6 + +/* Define to 64bit integer type */ +#define COIN_INT64_T int64_t + +/* Define to integer type capturing pointer */ +#define COIN_INTPTR_T intptr_t + +/* Define to 64bit unsigned integer type */ +#define COIN_UINT64_T int64_t + +#endif diff --git a/thirdparty/linux/include/coin/CoinWarmStart.hpp b/thirdparty/linux/include/coin/CoinWarmStart.hpp new file mode 100644 index 0000000..a7e28c8 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinWarmStart.hpp @@ -0,0 +1,58 @@ +/* $Id: CoinWarmStart.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStart_H +#define CoinWarmStart_H + +//############################################################################# + +class CoinWarmStartDiff; + +/** Abstract base class for warm start information. + + Really nothing can be generalized for warm start information --- all we + know is that it exists. Hence the abstract base class contains only a + virtual destructor and a virtual clone function (a virtual constructor), + so that derived classes can provide these functions. +*/ + +class CoinWarmStart { +public: + + /// Abstract destructor + virtual ~CoinWarmStart() {} + + /// `Virtual constructor' + virtual CoinWarmStart *clone() const = 0 ; + + virtual CoinWarmStartDiff* + generateDiff (const CoinWarmStart *const ) const { return 0; } + + + virtual void + applyDiff (const CoinWarmStartDiff *const ) {} + +}; + + +/*! \class CoinWarmStartDiff + \brief Abstract base class for warm start `diff' objects + + For those types of warm start objects where the notion of a `diff' makes + sense, this virtual base class is provided. As with CoinWarmStart, its sole + reason for existence is to make it possible to write solver-independent code. +*/ + +class CoinWarmStartDiff { +public: + + /// Abstract destructor + virtual ~CoinWarmStartDiff() {} + + /// `Virtual constructor' + virtual CoinWarmStartDiff *clone() const = 0 ; +}; + +#endif diff --git a/thirdparty/linux/include/coin/CoinWarmStartBasis.hpp b/thirdparty/linux/include/coin/CoinWarmStartBasis.hpp new file mode 100644 index 0000000..272d393 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinWarmStartBasis.hpp @@ -0,0 +1,456 @@ +/* $Id: CoinWarmStartBasis.hpp 1515 2011-12-10 23:38:04Z lou $ */ +/*! \legal + Copyright (C) 2000 -- 2003, International Business Machines Corporation + and others. All Rights Reserved. + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ + +/*! \file CoinWarmStart.hpp + \brief Declaration of the generic simplex (basis-oriented) warm start + class. Also contains a basis diff class. +*/ + +#ifndef CoinWarmStartBasis_H +#define CoinWarmStartBasis_H + +#include <vector> + +#include "CoinSort.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" + +//############################################################################# + +/*! \class CoinWarmStartBasis + \brief The default COIN simplex (basis-oriented) warm start class + + CoinWarmStartBasis provides for a warm start object which contains the + status of each variable (structural and artificial). + + \todo Modify this class so that the number of status entries per byte + and bytes per status vector allocation unit are not hardcoded. + At the least, collect this into a couple of macros. + + \todo Consider separate fields for allocated capacity and actual basis + size. We could avoid some reallocation, at the price of retaining + more space than we need. Perhaps more important, we could do much + better sanity checks. +*/ + +class CoinWarmStartBasis : public virtual CoinWarmStart { +public: + + /*! \brief Enum for status of variables + + Matches CoinPrePostsolveMatrix::Status, without superBasic. Most code that + converts between CoinPrePostsolveMatrix::Status and + CoinWarmStartBasis::Status will break if this correspondence is broken. + + The status vectors are currently packed using two bits per status code, + four codes per byte. The location of the status information for + variable \c i is in byte <code>i>>2</code> and occupies bits 0:1 + if <code>i\%4 == 0</code>, bits 2:3 if <code>i\%4 == 1</code>, etc. + The non-member functions getStatus(const char*,int) and + setStatus(char*,int,CoinWarmStartBasis::Status) are provided to hide + details of the packing. + */ + enum Status { + isFree = 0x00, ///< Nonbasic free variable + basic = 0x01, ///< Basic variable + atUpperBound = 0x02, ///< Nonbasic at upper bound + atLowerBound = 0x03 ///< Nonbasic at lower bound + }; + + /** \brief Transfer vector entry for + mergeBasis(const CoinWarmStartBasis*,const XferVec*,const XferVec*) + */ + typedef CoinTriple<int,int,int> XferEntry ; + + /** \brief Transfer vector for + mergeBasis(const CoinWarmStartBasis*,const XferVec*,const XferVec*) + */ + typedef std::vector<XferEntry> XferVec ; + +public: + +/*! \name Methods to get and set basis information. + + The status of variables is kept in a pair of arrays, one for structural + variables, and one for artificials (aka logicals and slacks). The status + is coded using the values of the Status enum. + + \sa CoinWarmStartBasis::Status for a description of the packing used in + the status arrays. +*/ +//@{ + /// Return the number of structural variables + inline int getNumStructural() const { return numStructural_; } + + /// Return the number of artificial variables + inline int getNumArtificial() const { return numArtificial_; } + + /** Return the number of basic structurals + + A fast test for an all-slack basis. + */ + int numberBasicStructurals() const ; + + /// Return the status of the specified structural variable. + inline Status getStructStatus(int i) const { + const int st = (structuralStatus_[i>>2] >> ((i&3)<<1)) & 3; + return static_cast<CoinWarmStartBasis::Status>(st); + } + + /// Set the status of the specified structural variable. + inline void setStructStatus(int i, Status st) { + char& st_byte = structuralStatus_[i>>2]; + st_byte = static_cast<char>(st_byte & ~(3 << ((i&3)<<1))) ; + st_byte = static_cast<char>(st_byte | (st << ((i&3)<<1))) ; + } + + /** Return the status array for the structural variables + + The status information is stored using the codes defined in the + Status enum, 2 bits per variable, packed 4 variables per byte. + */ + inline char * getStructuralStatus() { return structuralStatus_; } + + /** \c const overload for + \link CoinWarmStartBasis::getStructuralStatus() + getStructuralStatus() + \endlink + */ + inline const char * getStructuralStatus() const { return structuralStatus_; } + + /** As for \link getStructuralStatus() getStructuralStatus \endlink, + but returns the status array for the artificial variables. + */ + inline char * getArtificialStatus() { return artificialStatus_; } + + /// Return the status of the specified artificial variable. + inline Status getArtifStatus(int i) const { + const int st = (artificialStatus_[i>>2] >> ((i&3)<<1)) & 3; + return static_cast<CoinWarmStartBasis::Status>(st); + } + + /// Set the status of the specified artificial variable. + inline void setArtifStatus(int i, Status st) { + char& st_byte = artificialStatus_[i>>2]; + st_byte = static_cast<char>(st_byte & ~(3 << ((i&3)<<1))) ; + st_byte = static_cast<char>(st_byte | (st << ((i&3)<<1))) ; + } + + /** \c const overload for + \link CoinWarmStartBasis::getArtificialStatus() + getArtificialStatus() + \endlink + */ + inline const char * getArtificialStatus() const { return artificialStatus_; } + +//@} + +/*! \name Basis `diff' methods */ +//@{ + + /*! \brief Generate a `diff' that can convert the warm start basis passed as + a parameter to the warm start basis specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff* + generateDiff (const CoinWarmStart *const oldCWS) const ; + + /*! \brief Apply \p diff to this basis + + Update this basis by applying \p diff. It's assumed that the allocated + capacity of the basis is sufficiently large. + */ + + virtual void + applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; + +//@} + + +/*! \name Methods to modify the warm start object */ +//@{ + + /*! \brief Set basis capacity; existing basis is discarded. + + After execution of this routine, the warm start object does not describe + a valid basis: all structural and artificial variables have status isFree. + */ + virtual void setSize(int ns, int na) ; + + /*! \brief Set basis capacity; existing basis is maintained. + + After execution of this routine, the warm start object describes a valid + basis: the status of new structural variables (added columns) is set to + nonbasic at lower bound, and the status of new artificial variables + (added rows) is set to basic. (The basis can be invalid if new structural + variables do not have a finite lower bound.) + */ + virtual void resize (int newNumberRows, int newNumberColumns); + + /** \brief Delete a set of rows from the basis + + \warning + This routine assumes that the set of indices to be deleted is sorted in + ascending order and contains no duplicates. Use deleteRows() if this is + not the case. + + \warning + The resulting basis is guaranteed valid only if all deleted + constraints are slack (hence the associated logicals are basic). + + Removal of a tight constraint with a nonbasic logical implies that + some basic variable must be made nonbasic. This correction is left to + the client. + */ + + virtual void compressRows (int tgtCnt, const int *tgts) ; + + /** \brief Delete a set of rows from the basis + + \warning + The resulting basis is guaranteed valid only if all deleted + constraints are slack (hence the associated logicals are basic). + + Removal of a tight constraint with a nonbasic logical implies that + some basic variable must be made nonbasic. This correction is left to + the client. + */ + + virtual void deleteRows(int rawTgtCnt, const int *rawTgts) ; + + /** \brief Delete a set of columns from the basis + + \warning + The resulting basis is guaranteed valid only if all deleted variables + are nonbasic. + + Removal of a basic variable implies that some nonbasic variable must be + made basic. This correction is left to the client. + */ + + virtual void deleteColumns(int number, const int * which); + + /** \brief Merge entries from a source basis into this basis. + + \warning + It's the client's responsibility to ensure validity of the merged basis, + if that's important to the application. + + The vector xferCols (xferRows) specifies runs of entries to be taken from + the source basis and placed in this basis. Each entry is a CoinTriple, + with first specifying the starting source index of a run, second + specifying the starting destination index, and third specifying the run + length. + */ + virtual void mergeBasis(const CoinWarmStartBasis *src, + const XferVec *xferRows, + const XferVec *xferCols) ; + +//@} + +/*! \name Constructors, destructors, and related functions */ + +//@{ + + /** Default constructor + + Creates a warm start object representing an empty basis + (0 rows, 0 columns). + */ + CoinWarmStartBasis(); + + /** Constructs a warm start object with the specified status vectors. + + The parameters are copied. + Consider assignBasisStatus(int,int,char*&,char*&) if the object should + assume ownership. + + \sa CoinWarmStartBasis::Status for a description of the packing used in + the status arrays. + */ + CoinWarmStartBasis(int ns, int na, const char* sStat, const char* aStat) ; + + /** Copy constructor */ + CoinWarmStartBasis(const CoinWarmStartBasis& ws) ; + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const + { + return new CoinWarmStartBasis(*this); + } + + /** Destructor */ + virtual ~CoinWarmStartBasis(); + + /** Assignment */ + + virtual CoinWarmStartBasis& operator=(const CoinWarmStartBasis& rhs) ; + + /** Assign the status vectors to be the warm start information. + + In this method the CoinWarmStartBasis object assumes ownership of the + pointers and upon return the argument pointers will be NULL. + If copying is desirable, use the + \link CoinWarmStartBasis(int,int,const char*,const char*) + array constructor \endlink + or the + \link operator=(const CoinWarmStartBasis&) + assignment operator \endlink. + + \note + The pointers passed to this method will be + freed using delete[], so they must be created using new[]. + */ + virtual void assignBasisStatus(int ns, int na, char*& sStat, char*& aStat) ; +//@} + +/*! \name Miscellaneous methods */ +//@{ + + /// Prints in readable format (for debug) + virtual void print() const; + /// Returns true if full basis (for debug) + bool fullBasis() const; + /// Returns true if full basis and fixes up (for debug) + bool fixFullBasis(); + +//@} + +protected: + /** \name Protected data members + + \sa CoinWarmStartBasis::Status for a description of the packing used in + the status arrays. + */ + //@{ + /// The number of structural variables + int numStructural_; + /// The number of artificial variables + int numArtificial_; + /// The maximum sise (in ints - actually 4*char) (so resize does not need to do new) + int maxSize_; + /** The status of the structural variables. */ + char * structuralStatus_; + /** The status of the artificial variables. */ + char * artificialStatus_; + //@} +}; + + +/*! \relates CoinWarmStartBasis + \brief Get the status of the specified variable in the given status array. +*/ + +inline CoinWarmStartBasis::Status getStatus(const char *array, int i) { + const int st = (array[i>>2] >> ((i&3)<<1)) & 3; + return static_cast<CoinWarmStartBasis::Status>(st); +} + +/*! \relates CoinWarmStartBasis + \brief Set the status of the specified variable in the given status array. +*/ + +inline void setStatus(char * array, int i, CoinWarmStartBasis::Status st) { + char& st_byte = array[i>>2]; + st_byte = static_cast<char>(st_byte & ~(3 << ((i&3)<<1))) ; + st_byte = static_cast<char>(st_byte | (st << ((i&3)<<1))) ; +} + +/*! \relates CoinWarmStartBasis + \brief Generate a print string for a status code +*/ +const char *statusName(CoinWarmStartBasis::Status status) ; + + +/*! \class CoinWarmStartBasisDiff + \brief A `diff' between two CoinWarmStartBasis objects + + This class exists in order to hide from the world the details of + calculating and representing a `diff' between two CoinWarmStartBasis + objects. For convenience, assignment, cloning, and deletion are visible to + the world, and default and copy constructors are made available to derived + classes. Knowledge of the rest of this structure, and of generating and + applying diffs, is restricted to the friend functions + CoinWarmStartBasis::generateDiff() and CoinWarmStartBasis::applyDiff(). + + The actual data structure is an unsigned int vector, #difference_ which + starts with indices of changed and then has values starting after #sze_ + + \todo This is a pretty generic structure, and vector diff is a pretty generic + activity. We should be able to convert this to a template. + + \todo Using unsigned int as the data type for the diff vectors might help + to contain the damage when this code is inevitably compiled for 64 bit + architectures. But the notion of int as 4 bytes is hardwired into + CoinWarmStartBasis, so changes are definitely required. +*/ + +class CoinWarmStartBasisDiff : public virtual CoinWarmStartDiff +{ public: + + /*! \brief `Virtual constructor' */ + virtual CoinWarmStartDiff *clone() const + { CoinWarmStartBasisDiff *cwsbd = new CoinWarmStartBasisDiff(*this) ; + return (dynamic_cast<CoinWarmStartDiff *>(cwsbd)) ; } + + /*! \brief Assignment */ + virtual + CoinWarmStartBasisDiff &operator= (const CoinWarmStartBasisDiff &rhs) ; + + /*! \brief Destructor */ + virtual ~CoinWarmStartBasisDiff(); + + protected: + + /*! \brief Default constructor + + This is protected (rather than private) so that derived classes can + see it when they make <i>their</i> default constructor protected or + private. + */ + CoinWarmStartBasisDiff () : sze_(0), difference_(0) { } + + /*! \brief Copy constructor + + For convenience when copying objects containing CoinWarmStartBasisDiff + objects. But consider whether you should be using #clone() to retain + polymorphism. + + This is protected (rather than private) so that derived classes can + see it when they make <i>their</i> copy constructor protected or + private. + */ + CoinWarmStartBasisDiff (const CoinWarmStartBasisDiff &cwsbd) ; + + /*! \brief Standard constructor */ + CoinWarmStartBasisDiff (int sze, const unsigned int *const diffNdxs, + const unsigned int *const diffVals) ; + + /*! \brief Constructor when full is smaller than diff!*/ + CoinWarmStartBasisDiff (const CoinWarmStartBasis * rhs); + + private: + + friend CoinWarmStartDiff* + CoinWarmStartBasis::generateDiff(const CoinWarmStart *const oldCWS) const ; + friend void + CoinWarmStartBasis::applyDiff(const CoinWarmStartDiff *const diff) ; + + /*! \brief Number of entries (and allocated capacity), in units of \c int. */ + int sze_ ; + + /*! \brief Array of diff indices and diff values */ + + unsigned int *difference_ ; + +} ; + + +#endif diff --git a/thirdparty/linux/include/coin/CoinWarmStartDual.hpp b/thirdparty/linux/include/coin/CoinWarmStartDual.hpp new file mode 100644 index 0000000..3e60d11 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinWarmStartDual.hpp @@ -0,0 +1,166 @@ +/* $Id: CoinWarmStartDual.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStartDual_H +#define CoinWarmStartDual_H + +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" +#include "CoinWarmStartVector.hpp" + + +//############################################################################# + +/** WarmStart information that is only a dual vector */ + +class CoinWarmStartDual : public virtual CoinWarmStart { +public: + /// return the size of the dual vector + inline int size() const { return dual_.size(); } + /// return a pointer to the array of duals + inline const double * dual() const { return dual_.values(); } + + /** Assign the dual vector to be the warmstart information. In this method + the object assumes ownership of the pointer and upon return "dual" will + be a NULL pointer. If copying is desirable use the constructor. */ + inline void assignDual(int size, double *& dual) + { dual_.assignVector(size, dual); } + + CoinWarmStartDual() {} + + CoinWarmStartDual(int size, const double * dual) : dual_(size, dual) {} + + CoinWarmStartDual(const CoinWarmStartDual& rhs) : dual_(rhs.dual_) {} + + CoinWarmStartDual& operator=(const CoinWarmStartDual& rhs) { + if (this != &rhs) { + dual_ = rhs.dual_; + } + return *this; + } + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const { + return new CoinWarmStartDual(*this); + } + + virtual ~CoinWarmStartDual() {} + +/*! \name Dual warm start `diff' methods */ +//@{ + + /*! \brief Generate a `diff' that can convert the warm start passed as a + parameter to the warm start specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff* + generateDiff (const CoinWarmStart *const oldCWS) const ; + + /*! \brief Apply \p diff to this warm start. + + Update this warm start by applying \p diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. + */ + + virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; + +#if 0 +protected: + inline const CoinWarmStartVector<double>& warmStartVector() const { return dual_; } +#endif + +//@} + +private: + ///@name Private data members + CoinWarmStartVector<double> dual_; +}; + +//############################################################################# + +/*! \class CoinWarmStartDualDiff + \brief A `diff' between two CoinWarmStartDual objects + + This class exists in order to hide from the world the details of + calculating and representing a `diff' between two CoinWarmStartDual + objects. For convenience, assignment, cloning, and deletion are visible to + the world, and default and copy constructors are made available to derived + classes. Knowledge of the rest of this structure, and of generating and + applying diffs, is restricted to the friend functions + CoinWarmStartDual::generateDiff() and CoinWarmStartDual::applyDiff(). + + The actual data structure is a pair of vectors, #diffNdxs_ and #diffVals_. + +*/ + +class CoinWarmStartDualDiff : public virtual CoinWarmStartDiff +{ public: + + /*! \brief `Virtual constructor' */ + virtual CoinWarmStartDiff *clone() const + { + return new CoinWarmStartDualDiff(*this) ; + } + + /*! \brief Assignment */ + virtual CoinWarmStartDualDiff &operator= (const CoinWarmStartDualDiff &rhs) + { + if (this != &rhs) { + diff_ = rhs.diff_; + } + return *this; + } + + /*! \brief Destructor */ + virtual ~CoinWarmStartDualDiff() {} + + protected: + + /*! \brief Default constructor + + This is protected (rather than private) so that derived classes can + see it when they make <i>their</i> default constructor protected or + private. + */ + CoinWarmStartDualDiff () : diff_() {} + + /*! \brief Copy constructor + + For convenience when copying objects containing CoinWarmStartDualDiff + objects. But consider whether you should be using #clone() to retain + polymorphism. + + This is protected (rather than private) so that derived classes can + see it when the make <i>their</i> copy constructor protected or + private. + */ + CoinWarmStartDualDiff (const CoinWarmStartDualDiff &rhs) : + diff_(rhs.diff_) {} + + private: + + friend CoinWarmStartDiff* + CoinWarmStartDual::generateDiff(const CoinWarmStart *const oldCWS) const ; + friend void + CoinWarmStartDual::applyDiff(const CoinWarmStartDiff *const diff) ; + + /*! \brief Standard constructor */ + CoinWarmStartDualDiff (int sze, const unsigned int *const diffNdxs, + const double *const diffVals) : + diff_(sze, diffNdxs, diffVals) {} + + /*! + \brief The difference in the dual vector is simply the difference in a + vector. + */ + CoinWarmStartVectorDiff<double> diff_; +}; + + +#endif + diff --git a/thirdparty/linux/include/coin/CoinWarmStartPrimalDual.hpp b/thirdparty/linux/include/coin/CoinWarmStartPrimalDual.hpp new file mode 100644 index 0000000..c98d423 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinWarmStartPrimalDual.hpp @@ -0,0 +1,211 @@ +/* $Id: CoinWarmStartPrimalDual.hpp 1372 2011-01-03 23:31:00Z lou $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStartPrimalDual_H +#define CoinWarmStartPrimalDual_H + +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" +#include "CoinWarmStartVector.hpp" + + +//############################################################################# + +/** WarmStart information that is only a dual vector */ + +class CoinWarmStartPrimalDual : public virtual CoinWarmStart { +public: + /// return the size of the dual vector + inline int dualSize() const { return dual_.size(); } + /// return a pointer to the array of duals + inline const double * dual() const { return dual_.values(); } + + /// return the size of the primal vector + inline int primalSize() const { return primal_.size(); } + /// return a pointer to the array of primals + inline const double * primal() const { return primal_.values(); } + + /** Assign the primal/dual vectors to be the warmstart information. In this + method the object assumes ownership of the pointers and upon return \c + primal and \c dual will be a NULL pointers. If copying is desirable use + the constructor. + + NOTE: \c primal and \c dual must have been allocated by new double[], + because they will be freed by delete[] upon the desructtion of this + object... + */ + void assign(int primalSize, int dualSize, double*& primal, double *& dual) { + primal_.assignVector(primalSize, primal); + dual_.assignVector(dualSize, dual); + } + + CoinWarmStartPrimalDual() : primal_(), dual_() {} + + CoinWarmStartPrimalDual(int primalSize, int dualSize, + const double* primal, const double * dual) : + primal_(primalSize, primal), dual_(dualSize, dual) {} + + CoinWarmStartPrimalDual(const CoinWarmStartPrimalDual& rhs) : + primal_(rhs.primal_), dual_(rhs.dual_) {} + + CoinWarmStartPrimalDual& operator=(const CoinWarmStartPrimalDual& rhs) { + if (this != &rhs) { + primal_ = rhs.primal_; + dual_ = rhs.dual_; + } + return *this; + } + + /*! \brief Clear the data + + Make it appear as if the warmstart was just created using the default + constructor. + */ + inline void clear() { + primal_.clear(); + dual_.clear(); + } + + inline void swap(CoinWarmStartPrimalDual& rhs) { + if (this != &rhs) { + primal_.swap(rhs.primal_); + dual_.swap(rhs.dual_); + } + } + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const { + return new CoinWarmStartPrimalDual(*this); + } + + virtual ~CoinWarmStartPrimalDual() {} + + /*! \name PrimalDual warm start `diff' methods */ + //@{ + + /*! \brief Generate a `diff' that can convert the warm start passed as a + parameter to the warm start specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff* + generateDiff (const CoinWarmStart *const oldCWS) const ; + + /*! \brief Apply \p diff to this warm start. + + Update this warm start by applying \p diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. + */ + + virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; + + //@} + +#if 0 +protected: + inline const CoinWarmStartVector<double>& primalWarmStartVector() const + { return primal_; } + inline const CoinWarmStartVector<double>& dualWarmStartVector() const + { return dual_; } +#endif + +private: + ///@name Private data members + //@{ + CoinWarmStartVector<double> primal_; + CoinWarmStartVector<double> dual_; + //@} +}; + +//############################################################################# + +/*! \class CoinWarmStartPrimalDualDiff + \brief A `diff' between two CoinWarmStartPrimalDual objects + + This class exists in order to hide from the world the details of calculating + and representing a `diff' between two CoinWarmStartPrimalDual objects. For + convenience, assignment, cloning, and deletion are visible to the world, and + default and copy constructors are made available to derived classes. + Knowledge of the rest of this structure, and of generating and applying + diffs, is restricted to the friend functions + CoinWarmStartPrimalDual::generateDiff() and + CoinWarmStartPrimalDual::applyDiff(). + + The actual data structure is a pair of vectors, #diffNdxs_ and #diffVals_. + +*/ + +class CoinWarmStartPrimalDualDiff : public virtual CoinWarmStartDiff +{ + friend CoinWarmStartDiff* + CoinWarmStartPrimalDual::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartPrimalDual::applyDiff(const CoinWarmStartDiff *const diff) ; + +public: + + /*! \brief `Virtual constructor'. To be used when retaining polymorphism is + important */ + virtual CoinWarmStartDiff *clone() const + { + return new CoinWarmStartPrimalDualDiff(*this); + } + + /*! \brief Destructor */ + virtual ~CoinWarmStartPrimalDualDiff() {} + +protected: + + /*! \brief Default constructor + + This is protected (rather than private) so that derived classes can + see it when they make <i>their</i> default constructor protected or + private. + */ + CoinWarmStartPrimalDualDiff () : primalDiff_(), dualDiff_() {} + + /*! \brief Copy constructor + + For convenience when copying objects containing + CoinWarmStartPrimalDualDiff objects. But consider whether you should be + using #clone() to retain polymorphism. + + This is protected (rather than private) so that derived classes can + see it when the make <i>their</i> copy constructor protected or + private. + */ + CoinWarmStartPrimalDualDiff (const CoinWarmStartPrimalDualDiff &rhs) : + primalDiff_(rhs.primalDiff_), dualDiff_(rhs.dualDiff_) {} + + /*! \brief Clear the data + + Make it appear as if the diff was just created using the default + constructor. + */ + inline void clear() { + primalDiff_.clear(); + dualDiff_.clear(); + } + + inline void swap(CoinWarmStartPrimalDualDiff& rhs) { + if (this != &rhs) { + primalDiff_.swap(rhs.primalDiff_); + dualDiff_.swap(rhs.dualDiff_); + } + } + +private: + + /*! + \brief These two differences describe the differences in the primal and + in the dual vector. + */ + CoinWarmStartVectorDiff<double> primalDiff_; + CoinWarmStartVectorDiff<double> dualDiff_; +} ; + +#endif diff --git a/thirdparty/linux/include/coin/CoinWarmStartVector.hpp b/thirdparty/linux/include/coin/CoinWarmStartVector.hpp new file mode 100644 index 0000000..e43ea10 --- /dev/null +++ b/thirdparty/linux/include/coin/CoinWarmStartVector.hpp @@ -0,0 +1,488 @@ +/* $Id: CoinWarmStartVector.hpp 1498 2011-11-02 15:25:35Z mjs $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStartVector_H +#define CoinWarmStartVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +# pragma warning(disable:4786) +#endif + +#include <cassert> +#include <cmath> + +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" + + +//############################################################################# + +/** WarmStart information that is only a vector */ + +template <typename T> +class CoinWarmStartVector : public virtual CoinWarmStart +{ +protected: + inline void gutsOfDestructor() { + delete[] values_; + } + inline void gutsOfCopy(const CoinWarmStartVector<T>& rhs) { + size_ = rhs.size_; + values_ = new T[size_]; + CoinDisjointCopyN(rhs.values_, size_, values_); + } + +public: + /// return the size of the vector + int size() const { return size_; } + /// return a pointer to the array of vectors + const T* values() const { return values_; } + + /** Assign the vector to be the warmstart information. In this method + the object assumes ownership of the pointer and upon return #vector will + be a NULL pointer. If copying is desirable use the constructor. */ + void assignVector(int size, T*& vec) { + size_ = size; + delete[] values_; + values_ = vec; + vec = NULL; + } + + CoinWarmStartVector() : size_(0), values_(NULL) {} + + CoinWarmStartVector(int size, const T* vec) : + size_(size), values_(new T[size]) { + CoinDisjointCopyN(vec, size, values_); + } + + CoinWarmStartVector(const CoinWarmStartVector& rhs) { + gutsOfCopy(rhs); + } + + CoinWarmStartVector& operator=(const CoinWarmStartVector& rhs) { + if (this != &rhs) { + gutsOfDestructor(); + gutsOfCopy(rhs); + } + return *this; + } + + inline void swap(CoinWarmStartVector& rhs) { + if (this != &rhs) { + std::swap(size_, rhs.size_); + std::swap(values_, rhs.values_); + } + } + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const { + return new CoinWarmStartVector(*this); + } + + virtual ~CoinWarmStartVector() { + gutsOfDestructor(); + } + + /*! \brief Clear the data + + Make it appear as if the warmstart was just created using the default + constructor. + */ + inline void clear() { + size_ = 0; + delete[] values_; + values_ = NULL; + } + + /*! \name Vector warm start `diff' methods */ + //@{ + + /*! \brief Generate a `diff' that can convert the warm start passed as a + parameter to the warm start specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff* + generateDiff (const CoinWarmStart *const oldCWS) const ; + + /*! \brief Apply \p diff to this warm start. + + Update this warm start by applying \p diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. + */ + + virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; + + //@} + +private: + ///@name Private data members + //@{ + /// the size of the vector + int size_; + /// the vector itself + T* values_; + //@} +}; + +//============================================================================= + +/*! \class CoinWarmStartVectorDiff + \brief A `diff' between two CoinWarmStartVector objects + + This class exists in order to hide from the world the details of calculating + and representing a `diff' between two CoinWarmStartVector objects. For + convenience, assignment, cloning, and deletion are visible to the world, and + default and copy constructors are made available to derived classes. + Knowledge of the rest of this structure, and of generating and applying + diffs, is restricted to the friend functions + CoinWarmStartVector::generateDiff() and CoinWarmStartVector::applyDiff(). + + The actual data structure is a pair of vectors, #diffNdxs_ and #diffVals_. + +*/ + +template <typename T> +class CoinWarmStartVectorDiff : public virtual CoinWarmStartDiff +{ + friend CoinWarmStartDiff* + CoinWarmStartVector<T>::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartVector<T>::applyDiff(const CoinWarmStartDiff *const diff) ; + +public: + + /*! \brief `Virtual constructor' */ + virtual CoinWarmStartDiff * clone() const { + return new CoinWarmStartVectorDiff(*this) ; + } + + /*! \brief Assignment */ + virtual CoinWarmStartVectorDiff & + operator= (const CoinWarmStartVectorDiff<T>& rhs) ; + + /*! \brief Destructor */ + virtual ~CoinWarmStartVectorDiff() { + delete[] diffNdxs_ ; + delete[] diffVals_ ; + } + + inline void swap(CoinWarmStartVectorDiff& rhs) { + if (this != &rhs) { + std::swap(sze_, rhs.sze_); + std::swap(diffNdxs_, rhs.diffNdxs_); + std::swap(diffVals_, rhs.diffVals_); + } + } + + /*! \brief Default constructor + */ + CoinWarmStartVectorDiff () : sze_(0), diffNdxs_(0), diffVals_(NULL) {} + + /*! \brief Copy constructor + + For convenience when copying objects containing CoinWarmStartVectorDiff + objects. But consider whether you should be using #clone() to retain + polymorphism. + */ + CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff<T>& rhs) ; + + /*! \brief Standard constructor */ + CoinWarmStartVectorDiff(int sze, const unsigned int* const diffNdxs, + const T* const diffVals) ; + + /*! \brief Clear the data + + Make it appear as if the diff was just created using the default + constructor. + */ + inline void clear() { + sze_ = 0; + delete[] diffNdxs_; diffNdxs_ = NULL; + delete[] diffVals_; diffVals_ = NULL; + } + +private: + + /*! + \brief Number of entries (and allocated capacity), in units of \c T. + */ + int sze_ ; + + /*! \brief Array of diff indices */ + + unsigned int* diffNdxs_ ; + + /*! \brief Array of diff values */ + + T* diffVals_ ; +}; + +//############################################################################## + +template <typename T, typename U> +class CoinWarmStartVectorPair : public virtual CoinWarmStart +{ +private: + CoinWarmStartVector<T> t_; + CoinWarmStartVector<U> u_; + +public: + inline int size0() const { return t_.size(); } + inline int size1() const { return u_.size(); } + inline const T* values0() const { return t_.values(); } + inline const U* values1() const { return u_.values(); } + + inline void assignVector0(int size, T*& vec) { t_.assignVector(size, vec); } + inline void assignVector1(int size, U*& vec) { u_.assignVector(size, vec); } + + CoinWarmStartVectorPair() {} + CoinWarmStartVectorPair(int s0, const T* v0, int s1, const U* v1) : + t_(s0, v0), u_(s1, v1) {} + + CoinWarmStartVectorPair(const CoinWarmStartVectorPair<T,U>& rhs) : + t_(rhs.t_), u_(rhs.u_) {} + CoinWarmStartVectorPair& operator=(const CoinWarmStartVectorPair<T,U>& rhs) { + if (this != &rhs) { + t_ = rhs.t_; + u_ = rhs.u_; + } + return *this; + } + + inline void swap(CoinWarmStartVectorPair<T,U>& rhs) { + t_.swap(rhs.t_); + u_.swap(rhs.u_); + } + + virtual CoinWarmStart *clone() const { + return new CoinWarmStartVectorPair(*this); + } + + virtual ~CoinWarmStartVectorPair() {} + + inline void clear() { + t_.clear(); + u_.clear(); + } + + virtual CoinWarmStartDiff* + generateDiff (const CoinWarmStart *const oldCWS) const ; + + virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; +}; + +//============================================================================= + +template <typename T, typename U> +class CoinWarmStartVectorPairDiff : public virtual CoinWarmStartDiff +{ + friend CoinWarmStartDiff* + CoinWarmStartVectorPair<T,U>::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartVectorPair<T,U>::applyDiff(const CoinWarmStartDiff *const diff) ; + +private: + CoinWarmStartVectorDiff<T> tdiff_; + CoinWarmStartVectorDiff<U> udiff_; + +public: + CoinWarmStartVectorPairDiff() {} + CoinWarmStartVectorPairDiff(const CoinWarmStartVectorPairDiff<T,U>& rhs) : + tdiff_(rhs.tdiff_), udiff_(rhs.udiff_) {} + virtual ~CoinWarmStartVectorPairDiff() {} + + virtual CoinWarmStartVectorPairDiff& + operator=(const CoinWarmStartVectorPairDiff<T,U>& rhs) { + if (this != &rhs) { + tdiff_ = rhs.tdiff_; + udiff_ = rhs.udiff_; + } + return *this; + } + + virtual CoinWarmStartDiff * clone() const { + return new CoinWarmStartVectorPairDiff(*this) ; + } + + inline void swap(CoinWarmStartVectorPairDiff<T,U>& rhs) { + tdiff_.swap(rhs.tdiff_); + udiff_.swap(rhs.udiff_); + } + + inline void clear() { + tdiff_.clear(); + udiff_.clear(); + } +}; + +//############################################################################## +//############################################################################# + +/* + Generate a `diff' that can convert the warm start passed as a parameter to + the warm start specified by this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by this. +*/ + +template <typename T> CoinWarmStartDiff* +CoinWarmStartVector<T>::generateDiff(const CoinWarmStart *const oldCWS) const +{ +/* + Make sure the parameter is CoinWarmStartVector or derived class. +*/ + const CoinWarmStartVector<T>* oldVector = + dynamic_cast<const CoinWarmStartVector<T>*>(oldCWS); + if (!oldVector) + { throw CoinError("Old warm start not derived from CoinWarmStartVector.", + "generateDiff","CoinWarmStartVector") ; } + const CoinWarmStartVector<T>* newVector = this ; + /* + Make sure newVector is equal or bigger than oldVector. Calculate the worst + case number of diffs and allocate vectors to hold them. + */ + const int oldCnt = oldVector->size() ; + const int newCnt = newVector->size() ; + + assert(newCnt >= oldCnt) ; + + unsigned int *diffNdx = new unsigned int [newCnt]; + T* diffVal = new T[newCnt]; + /* + Scan the vector vectors. For the portion of the vectors which overlap, + create diffs. Then add any additional entries from newVector. + */ + const T*oldVal = oldVector->values() ; + const T*newVal = newVector->values() ; + int numberChanged = 0 ; + int i ; + for (i = 0 ; i < oldCnt ; i++) { + if (oldVal[i] != newVal[i]) { + diffNdx[numberChanged] = i ; + diffVal[numberChanged++] = newVal[i] ; + } + } + for ( ; i < newCnt ; i++) { + diffNdx[numberChanged] = i ; + diffVal[numberChanged++] = newVal[i] ; + } + /* + Create the object of our desire. + */ + CoinWarmStartVectorDiff<T> *diff = + new CoinWarmStartVectorDiff<T>(numberChanged,diffNdx,diffVal) ; + /* + Clean up and return. + */ + delete[] diffNdx ; + delete[] diffVal ; + + return diff; + // return (dynamic_cast<CoinWarmStartDiff<T>*>(diff)) ; +} + + +/* + Apply diff to this warm start. + + Update this warm start by applying diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. +*/ + +template <typename T> void +CoinWarmStartVector<T>::applyDiff (const CoinWarmStartDiff *const cwsdDiff) +{ + /* + Make sure we have a CoinWarmStartVectorDiff + */ + const CoinWarmStartVectorDiff<T>* diff = + dynamic_cast<const CoinWarmStartVectorDiff<T>*>(cwsdDiff) ; + if (!diff) { + throw CoinError("Diff not derived from CoinWarmStartVectorDiff.", + "applyDiff","CoinWarmStartVector") ; + } + /* + Application is by straighforward replacement of words in the vector vector. + */ + const int numberChanges = diff->sze_ ; + const unsigned int *diffNdxs = diff->diffNdxs_ ; + const T* diffVals = diff->diffVals_ ; + T* vals = this->values_ ; + + for (int i = 0 ; i < numberChanges ; i++) { + unsigned int diffNdx = diffNdxs[i] ; + T diffVal = diffVals[i] ; + vals[diffNdx] = diffVal ; + } +} + +//############################################################################# + + +// Assignment + +template <typename T> CoinWarmStartVectorDiff<T>& +CoinWarmStartVectorDiff<T>::operator=(const CoinWarmStartVectorDiff<T> &rhs) +{ + if (this != &rhs) { + if (sze_ > 0) { + delete[] diffNdxs_ ; + delete[] diffVals_ ; + } + sze_ = rhs.sze_ ; + if (sze_ > 0) { + diffNdxs_ = new unsigned int[sze_] ; + memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ; + diffVals_ = new T[sze_] ; + memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ; + } else { + diffNdxs_ = 0 ; + diffVals_ = 0 ; + } + } + + return (*this) ; +} + + +// Copy constructor + +template <typename T> +CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff<T> &rhs) + : sze_(rhs.sze_), + diffNdxs_(0), + diffVals_(0) +{ + if (sze_ > 0) { + diffNdxs_ = new unsigned int[sze_] ; + memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ; + diffVals_ = new T[sze_] ; + memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ; + } +} + +/// Standard constructor + +template <typename T> +CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff +(int sze, const unsigned int *const diffNdxs, const T *const diffVals) + : sze_(sze), + diffNdxs_(0), + diffVals_(0) +{ + if (sze > 0) { + diffNdxs_ = new unsigned int[sze] ; + memcpy(diffNdxs_,diffNdxs,sze*sizeof(unsigned int)) ; + diffVals_ = new T[sze] ; + memcpy(diffVals_,diffVals,sze*sizeof(T)) ; + } +} + +#endif diff --git a/thirdparty/linux/include/coin/Coin_C_defines.h b/thirdparty/linux/include/coin/Coin_C_defines.h new file mode 100644 index 0000000..5c43aaa --- /dev/null +++ b/thirdparty/linux/include/coin/Coin_C_defines.h @@ -0,0 +1,115 @@ +/* $Id: Coin_C_defines.h 1690 2014-03-13 17:45:21Z mlubin $ */ +/* + Copyright (C) 2002, 2003 International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ +#ifndef CoinCDefine_H +#define CoinCDefine_H + +/** This has #defines etc for the "C" interface to Coin. + If COIN_EXTERN_C defined then an extra extern C +*/ + +#if defined (CLP_EXTERN_C) +#define COIN_EXTERN_C +#define COIN_NO_SBB +#define COIN_NO_CBC +#endif +#if defined (SBB_EXTERN_C) +#define COIN_EXTERN_C +#define COIN_NO_CLP +#endif +#if defined (CBC_EXTERN_C) +#define COIN_EXTERN_C +#define COIN_NO_CLP +#endif +/* We need to allow for Microsoft */ +#ifndef COINLIBAPI + +#if defined(CBCCINTERFACEDLL_EXPORTS) || defined(CLPMSDLL) +#if defined (COIN_EXTERN_C) +# define COINLIBAPI __declspec(dllexport) +#else +# define COINLIBAPI __declspec(dllexport) +#endif +# define COINLINKAGE __stdcall +# define COINLINKAGE_CB __cdecl +#else +#if defined (COIN_EXTERN_C) +# define COINLIBAPI extern "C" +#else +# define COINLIBAPI +#endif +# define COINLINKAGE +# define COINLINKAGE_CB +#endif + +#endif +/** User does not need to see structure of model but C++ code does */ +#if defined (CLP_EXTERN_C) +/* Real typedef for structure */ +class CMessageHandler; +typedef struct { + ClpSimplex * model_; + CMessageHandler * handler_; +} Clp_Simplex; +#else +typedef void Clp_Simplex; +#endif + +#ifndef COIN_NO_CLP +/** typedef for user call back. + The cvec are constructed so don't need to be const*/ +typedef void (COINLINKAGE_CB *clp_callback) (Clp_Simplex * model,int msgno, int ndouble, + const double * dvec, int nint, const int * ivec, + int nchar, char ** cvec); +#endif +/** User does not need to see structure of model but C++ code does */ +#if defined (SBB_EXTERN_C) +/* Real typedef for structure */ +class Sbb_MessageHandler; +typedef struct { + OsiClpSolverInterface * solver_; + SbbModel * model_; + Sbb_MessageHandler * handler_; + char * information_; +} Sbb_Model; +#else +typedef void Sbb_Model; +#endif +#if defined (CBC_EXTERN_C) +/* Real typedef for structure */ +class Cbc_MessageHandler; +typedef struct { + OsiClpSolverInterface * solver_; + CbcModel * model_; + Cbc_MessageHandler * handler_; + std::vector<std::string> cmdargs_; +} Cbc_Model; +#else +typedef void Cbc_Model; +#endif +#ifndef COIN_NO_SBB +/** typedef for user call back. + The cvec are constructed so don't need to be const*/ +typedef void (COINLINKAGE_CB *sbb_callback) (Sbb_Model * model,int msgno, int ndouble, + const double * dvec, int nint, const int * ivec, + int nchar, char ** cvec); +typedef void (COINLINKAGE_CB *cbc_callback) (Cbc_Model * model,int msgno, int ndouble, + const double * dvec, int nint, const int * ivec, + int nchar, char ** cvec); +#endif +#if COIN_BIG_INDEX==0 +typedef int CoinBigIndex; +#elif COIN_BIG_INDEX==1 +typedef long CoinBigIndex; +#else +typedef long long CoinBigIndex; +#endif +/* just in case used somewhere */ +#undef COIN_NO_CLP +#undef COIN_NO_SBB +#undef COIN_NO_CBC +#endif diff --git a/thirdparty/linux/include/coin/Idiot.hpp b/thirdparty/linux/include/coin/Idiot.hpp new file mode 100644 index 0000000..a3d7891 --- /dev/null +++ b/thirdparty/linux/include/coin/Idiot.hpp @@ -0,0 +1,297 @@ +/* $Id: Idiot.hpp 2078 2015-01-05 12:39:49Z 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). + +// "Idiot" as the name of this algorithm is copylefted. If you want to change +// the name then it should be something equally stupid (but not "Stupid") or +// even better something witty. + +#ifndef Idiot_H +#define Idiot_H +#ifndef OSI_IDIOT +#include "ClpSimplex.hpp" +#define OsiSolverInterface ClpSimplex +#else +#include "OsiSolverInterface.hpp" +typedef int CoinBigIndex; +#endif +class CoinMessageHandler; +class CoinMessages; +/// for use internally +typedef struct { + double infeas; + double objval; + double dropThis; + double weighted; + double sumSquared; + double djAtBeginning; + double djAtEnd; + int iteration; +} IdiotResult; +/** This class implements a very silly algorithm. It has no merit + apart from the fact that it gets an approximate solution to + some classes of problems. Better if vaguely homogeneous. + It works on problems where volume algorithm works and often + gets a better primal solution but it has no dual solution. + + It can also be used as a "crash" to get a problem started. This + is probably its most useful function. + + It is based on the idea that algorithms with terrible convergence + properties may be okay at first. Throw in some random dubious tricks + and the resulting code may be worth keeping as long as you don't + look at it. + +*/ + +class Idiot { + +public: + + /**@name Constructors and destructor + Just a pointer to model is kept + */ + //@{ + /// Default constructor + Idiot ( ); + /// Constructor with model + Idiot ( OsiSolverInterface & model ); + + /// Copy constructor. + Idiot(const Idiot &); + /// Assignment operator. This copies the data + Idiot & operator=(const Idiot & rhs); + /// Destructor + ~Idiot ( ); + //@} + + + /**@name Algorithmic calls + */ + //@{ + /// Get an approximate solution with the idiot code + void solve(); + /// Lightweight "crash" + void crash(int numberPass, CoinMessageHandler * handler, + const CoinMessages * messages, bool doCrossover = true); + /** Use simplex to get an optimal solution + mode is how many steps the simplex crossover should take to + arrive to an extreme point: + 0 - chosen,all ever used, all + 1 - chosen, all + 2 - all + 3 - do not do anything - maybe basis + + 16 do presolves + */ + void crossOver(int mode); + //@} + + + /**@name Gets and sets of most useful data + */ + //@{ + /** Starting weight - small emphasizes feasibility, + default 1.0e-4 */ + inline double getStartingWeight() const { + return mu_; + } + inline void setStartingWeight(double value) { + mu_ = value; + } + /** Weight factor - weight multiplied by this when changes, + default 0.333 */ + inline double getWeightFactor() const { + return muFactor_; + } + inline void setWeightFactor(double value) { + muFactor_ = value; + } + /** Feasibility tolerance - problem essentially feasible if + individual infeasibilities less than this. + default 0.1 */ + inline double getFeasibilityTolerance() const { + return smallInfeas_; + } + inline void setFeasibilityTolerance(double value) { + smallInfeas_ = value; + } + /** Reasonably feasible. Dubious method concentrates more on + objective when sum of infeasibilities less than this. + Very dubious default value of (Number of rows)/20 */ + inline double getReasonablyFeasible() const { + return reasonableInfeas_; + } + inline void setReasonablyFeasible(double value) { + reasonableInfeas_ = value; + } + /** Exit infeasibility - exit if sum of infeasibilities less than this. + Default -1.0 (i.e. switched off) */ + inline double getExitInfeasibility() const { + return exitFeasibility_; + } + inline void setExitInfeasibility(double value) { + exitFeasibility_ = value; + } + /** Major iterations. stop after this number. + Default 30. Use 2-5 for "crash" 50-100 for serious crunching */ + inline int getMajorIterations() const { + return majorIterations_; + } + inline void setMajorIterations(int value) { + majorIterations_ = value; + } + /** Minor iterations. Do this number of tiny steps before + deciding whether to change weights etc. + Default - dubious sqrt(Number of Rows). + Good numbers 105 to 405 say (5 is dubious method of making sure + idiot is not trying to be clever which it may do every 10 minor + iterations) */ + inline int getMinorIterations() const { + return maxIts2_; + } + inline void setMinorIterations(int value) { + maxIts2_ = value; + } + // minor iterations for first time + inline int getMinorIterations0() const { + return maxIts_; + } + inline void setMinorIterations0(int value) { + maxIts_ = value; + } + /** Reduce weight after this many major iterations. It may + get reduced before this but this is a maximum. + Default 3. 3-10 plausible. */ + inline int getReduceIterations() const { + return maxBigIts_; + } + inline void setReduceIterations(int value) { + maxBigIts_ = value; + } + /// Amount of information - default of 1 should be okay + inline int getLogLevel() const { + return logLevel_; + } + inline void setLogLevel(int value) { + logLevel_ = value; + } + /// How lightweight - 0 not, 1 yes, 2 very lightweight + inline int getLightweight() const { + return lightWeight_; + } + inline void setLightweight(int value) { + lightWeight_ = value; + } + /// strategy + inline int getStrategy() const { + return strategy_; + } + inline void setStrategy(int value) { + strategy_ = value; + } + /// Fine tuning - okay if feasibility drop this factor + inline double getDropEnoughFeasibility() const { + return dropEnoughFeasibility_; + } + inline void setDropEnoughFeasibility(double value) { + dropEnoughFeasibility_ = value; + } + /// Fine tuning - okay if weighted obj drop this factor + inline double getDropEnoughWeighted() const { + return dropEnoughWeighted_; + } + inline void setDropEnoughWeighted(double value) { + dropEnoughWeighted_ = value; + } + /// Set model + inline void setModel(OsiSolverInterface * model) { + model_ = model; + }; + //@} + + +/// Stuff for internal use +private: + + /// Does actual work + // allow public! +public: + void solve2(CoinMessageHandler * handler, const CoinMessages *messages); +private: + IdiotResult IdiSolve( + int nrows, int ncols, double * rowsol , double * colsol, + double * pi, double * djs, const double * origcost , + double * rowlower, + double * rowupper, const double * lower, + const double * upper, const double * element, + const int * row, const CoinBigIndex * colcc, + const int * length, double * lambda, + int maxIts, double mu, double drop, + double maxmin, double offset, + int strategy, double djTol, double djExit, double djFlag, + CoinThreadRandom * randomNumberGenerator); + int dropping(IdiotResult result, + double tolerance, + double small, + int *nbad); + IdiotResult objval(int nrows, int ncols, double * rowsol , double * colsol, + double * pi, double * djs, const double * cost , + const double * rowlower, + const double * rowupper, const double * lower, + const double * upper, const double * elemnt, + const int * row, const CoinBigIndex * columnStart, + const int * length, int extraBlock, int * rowExtra, + double * solExtra, double * elemExtra, double * upperExtra, + double * costExtra, double weight); + // Deals with whenUsed and slacks + int cleanIteration(int iteration, int ordinaryStart, int ordinaryEnd, + double * colsol, const double * lower, const double * upper, + const double * rowLower, const double * rowUpper, + const double * cost, const double * element, double fixTolerance, double & objChange, + double & infChange, double & maxInfeasibility); +private: + /// Underlying model + OsiSolverInterface * model_; + + double djTolerance_; + double mu_; /* starting mu */ + double drop_; /* exit if drop over 5 checks less than this */ + double muFactor_; /* reduce mu by this */ + double stopMu_; /* exit if mu gets smaller than this */ + double smallInfeas_; /* feasibility tolerance */ + double reasonableInfeas_; /* use lambdas if feasibility less than this */ + double exitDrop_; /* candidate for stopping after a major iteration */ + double muAtExit_; /* mu on exit */ + double exitFeasibility_; /* exit if infeasibility less than this */ + double dropEnoughFeasibility_; /* okay if feasibility drop this factor */ + double dropEnoughWeighted_; /* okay if weighted obj drop this factor */ + int * whenUsed_; /* array to say what was used */ + int maxBigIts_; /* always reduce mu after this */ + int maxIts_; /* do this many iterations on first go */ + int majorIterations_; + int logLevel_; + int logFreq_; + int checkFrequency_; /* can exit after 5 * this iterations (on drop) */ + int lambdaIterations_; /* do at least this many lambda iterations */ + int maxIts2_; /* do this many iterations on subsequent goes */ + int strategy_; /* 0 - default strategy + 1 - do accelerator step but be cautious + 2 - do not do accelerator step + 4 - drop, exitDrop and djTolerance all relative + 8 - keep accelerator step to theta=10.0 + + 32 - Scale + 512 - crossover + 2048 - keep lambda across mu change + 4096 - return best solution (not last found) + 8192 - always do a presolve in crossover + 16384 - costed slacks found - so whenUsed_ longer + 32768 - experimental 1 + 65536 - experimental 2 + 131072 - experimental 3 + 262144 - just values pass etc */ + + int lightWeight_; // 0 - normal, 1 lightweight +}; +#endif diff --git a/thirdparty/linux/include/coin/OsiAuxInfo.hpp b/thirdparty/linux/include/coin/OsiAuxInfo.hpp new file mode 100644 index 0000000..182d981 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiAuxInfo.hpp @@ -0,0 +1,206 @@ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiAuxInfo_H +#define OsiAuxInfo_H + +class OsiSolverInterface; + +//############################################################################# +/** This class allows for a more structured use of algorithmic tweaking to + an OsiSolverInterface. It is designed to replace the simple use of + appData_ pointer. + + This has been done to make it easier to use NonLinear solvers and other + exotic beasts in a branch and bound mode. After this class definition + there is one for a derived class for just such a purpose. + +*/ + +class OsiAuxInfo { +public: + // Default Constructor + OsiAuxInfo (void * appData = NULL); + + // Copy Constructor + OsiAuxInfo (const OsiAuxInfo & rhs); + // Destructor + virtual ~OsiAuxInfo(); + + /// Clone + virtual OsiAuxInfo * clone() const; + /// Assignment operator + OsiAuxInfo & operator=(const OsiAuxInfo& rhs); + + /// Get application data + inline void * getApplicationData() const + { return appData_;} +protected: + /// Pointer to user-defined data structure + void * appData_; +}; +//############################################################################# +/** This class allows for the use of more exotic solvers e.g. Non-Linear or Volume. + + You can derive from this although at present I can't see the need. +*/ + +class OsiBabSolver : public OsiAuxInfo { +public: + // Default Constructor + OsiBabSolver (int solverType=0); + + // Copy Constructor + OsiBabSolver (const OsiBabSolver & rhs); + // Destructor + virtual ~OsiBabSolver(); + + /// Clone + virtual OsiAuxInfo * clone() const; + /// Assignment operator + OsiBabSolver & operator=(const OsiBabSolver& rhs); + + /// Update solver + inline void setSolver(const OsiSolverInterface * solver) + { solver_ = solver;} + /// Update solver + inline void setSolver(const OsiSolverInterface & solver) + { solver_ = &solver;} + + /** returns 0 if no heuristic solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value + numberColumns is size of newSolution + */ + int solution(double & objectiveValue, + double * newSolution, int numberColumns); + /** Set solution and objective value. + Number of columns and optimization direction taken from current solver. + Size of solution is numberColumns (may be padded or truncated in function) */ + void setSolution(const double * solution, int numberColumns, double objectiveValue); + + /** returns true if the object stores a solution, false otherwise. If there + is a solution then solutionValue and solution will be filled out as well. + In that case the user needs to allocate solution to be a big enough + array. + */ + bool hasSolution(double & solutionValue, double * solution); + + /** Sets solver type + 0 - normal LP solver + 1 - DW - may also return heuristic solutions + 2 - NLP solver or similar - can't compute objective value just from solution + check solver to see if feasible and what objective value is + - may also return heuristic solution + 3 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is. + Using Outer Approximation so called lp based + - may also return heuristic solution + 4 - normal solver but cuts are needed for integral solution + */ + inline void setSolverType(int value) + { solverType_=value;} + /** gets solver type + 0 - normal LP solver + 1 - DW - may also return heuristic solutions + 2 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is + - may also return heuristic solution + 3 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is. + Using Outer Approximation so called lp based + - may also return heuristic solution + 4 - normal solver but cuts are needed for integral solution + */ + inline int solverType() const + { return solverType_;} + /** Return true if getting solution may add cuts so hot start etc will + be obsolete */ + inline bool solutionAddsCuts() const + { return solverType_==3;} + /// Return true if we should try cuts at root even if looks satisfied + inline bool alwaysTryCutsAtRootNode() const + { return solverType_==4;} + /** Returns true if can use solver objective or feasible values, + otherwise use mipBound etc */ + inline bool solverAccurate() const + { return solverType_==0||solverType_==2||solverType_==4;} + /// Returns true if can use reduced costs for fixing + inline bool reducedCostsAccurate() const + { return solverType_==0||solverType_==4;} + /// Get objective (well mip bound) + double mipBound() const; + /// Returns true if node feasible + bool mipFeasible() const; + /// Set mip bound (only used for some solvers) + inline void setMipBound(double value) + { mipBound_ = value;} + /// Get objective value of saved solution + inline double bestObjectiveValue() const + { return bestObjectiveValue_;} + /// Says whether we want to try cuts at all + inline bool tryCuts() const + { return solverType_!=2;} + /// Says whether we have a warm start (so can do strong branching) + inline bool warmStart() const + { return solverType_!=2;} + /** Get bit mask for odd actions of solvers + 1 - solution or bound arrays may move in mysterious ways e.g. cplex + 2 - solver may want bounds before branch + */ + inline int extraCharacteristics() const + { return extraCharacteristics_;} + /** Set bit mask for odd actions of solvers + 1 - solution or bound arrays may move in mysterious ways e.g. cplex + 2 - solver may want bounds before branch + */ + inline void setExtraCharacteristics(int value) + { extraCharacteristics_=value;} + /// Pointer to lower bounds before branch (only if extraCharacteristics set) + inline const double * beforeLower() const + { return beforeLower_;} + /// Set pointer to lower bounds before branch (only if extraCharacteristics set) + inline void setBeforeLower(const double * array) + { beforeLower_ = array;} + /// Pointer to upper bounds before branch (only if extraCharacteristics set) + inline const double * beforeUpper() const + { return beforeUpper_;} + /// Set pointer to upper bounds before branch (only if extraCharacteristics set) + inline void setBeforeUpper(const double * array) + { beforeUpper_ = array;} +protected: + /// Objective value of best solution (if there is one) (minimization) + double bestObjectiveValue_; + /// Current lower bound on solution ( if > 1.0e50 infeasible) + double mipBound_; + /// Solver to use for getting/setting solutions etc + const OsiSolverInterface * solver_; + /// Best integer feasible solution + double * bestSolution_; + /// Pointer to lower bounds before branch (only if extraCharacteristics set) + const double * beforeLower_; + /// Pointer to upper bounds before branch (only if extraCharacteristics set) + const double * beforeUpper_; + /** Solver type + 0 - normal LP solver + 1 - DW - may also return heuristic solutions + 2 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is + - may also return heuristic solution + 3 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is. + Using Outer Approximation so called lp based + - may also return heuristic solution + */ + int solverType_; + /// Size of solution + int sizeSolution_; + /** Bit mask for odd actions of solvers + 1 - solution or bound arrays may move in mysterious ways e.g. cplex + 2 - solver may want bounds before branch + */ + int extraCharacteristics_; +}; + +#endif diff --git a/thirdparty/linux/include/coin/OsiBranchingObject.hpp b/thirdparty/linux/include/coin/OsiBranchingObject.hpp new file mode 100644 index 0000000..78b6984 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiBranchingObject.hpp @@ -0,0 +1,1005 @@ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiBranchingObject_H +#define OsiBranchingObject_H + +#include <cassert> +#include <string> +#include <vector> + +#include "CoinError.hpp" +#include "CoinTypes.hpp" + +class OsiSolverInterface; +class OsiSolverBranch; + +class OsiBranchingObject; +class OsiBranchingInformation; + +//############################################################################# +//This contains the abstract base class for an object and for branching. +//It also contains a simple integer class +//############################################################################# + +/** Abstract base class for `objects'. + + The branching model used in Osi is based on the idea of an <i>object</i>. + In the abstract, an object is something that has a feasible region, can be + evaluated for infeasibility, can be branched on (<i>i.e.</i>, there's some + constructive action to be taken to move toward feasibility), and allows + comparison of the effect of branching. + + This class (OsiObject) is the base class for an object. To round out the + branching model, the class OsiBranchingObject describes how to perform a + branch, and the class OsiBranchDecision describes how to compare two + OsiBranchingObjects. + + To create a new type of object you need to provide three methods: + #infeasibility(), #feasibleRegion(), and #createBranch(), described below. + + This base class is primarily virtual to allow for any form of structure. + Any form of discontinuity is allowed. + + As there is an overhead in getting information from solvers and because + other useful information is available there is also an OsiBranchingInformation + class which can contain pointers to information. + If used it must at minimum contain pointers to current value of objective, + maximum allowed objective and pointers to arrays for bounds and solution + and direction of optimization. Also integer and primal tolerance. + + Classes which inherit might have other information such as depth, number of + solutions, pseudo-shadow prices etc etc. + May be easier just to throw in here - as I keep doing +*/ +class OsiObject { + +public: + + /// Default Constructor + OsiObject (); + + /// Copy constructor + OsiObject ( const OsiObject &); + + /// Assignment operator + OsiObject & operator=( const OsiObject& rhs); + + /// Clone + virtual OsiObject * clone() const=0; + + /// Destructor + virtual ~OsiObject (); + + /** Infeasibility of the object + + This is some measure of the infeasibility of the object. 0.0 + indicates that the object is satisfied. + + The preferred branching direction is returned in whichWay, where for + normal two-way branching 0 is down, 1 is up + + This is used to prepare for strong branching but should also think of + case when no strong branching + + The object may also compute an estimate of cost of going "up" or "down". + This will probably be based on pseudo-cost ideas + + This should also set mutable infeasibility_ and whichWay_ + This is for instant re-use for speed + + Default for this just calls infeasibility with OsiBranchingInformation + NOTE - Convention says that an infeasibility of COIN_DBL_MAX means + object has worked out it can't be satisfied! + */ + double infeasibility(const OsiSolverInterface * solver,int &whichWay) const ; + // Faster version when more information available + virtual double infeasibility(const OsiBranchingInformation * info, int &whichWay) const =0; + // This does NOT set mutable stuff + virtual double checkInfeasibility(const OsiBranchingInformation * info) const; + + /** For the variable(s) referenced by the object, + look at the current solution and set bounds to match the solution. + Returns measure of how much it had to move solution to make feasible + */ + virtual double feasibleRegion(OsiSolverInterface * solver) const ; + /** For the variable(s) referenced by the object, + look at the current solution and set bounds to match the solution. + Returns measure of how much it had to move solution to make feasible + Faster version + */ + virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const =0; + + /** Create a branching object and indicate which way to branch first. + + The branching object has to know how to create branches (fix + variables, etc.) + */ + virtual OsiBranchingObject * createBranch(OsiSolverInterface * /*solver*/, + const OsiBranchingInformation * /*info*/, + int /*way*/) const {throw CoinError("Need code","createBranch","OsiBranchingObject"); return NULL; } + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + {return true;} + /** \brief Return true if object can take part in move to nearest heuristic + */ + virtual bool canMoveToNearest() const + {return false;} + /** Column number if single column object -1 otherwise, + Used by heuristics + */ + virtual int columnNumber() const; + /// Return Priority - note 1 is highest priority + inline int priority() const + { return priority_;} + /// Set priority + inline void setPriority(int priority) + { priority_ = priority;} + /** \brief Return true if branch should only bound variables + */ + virtual bool boundBranch() const + {return true;} + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { return false;} + /// Return maximum number of ways branch may have + inline int numberWays() const + { return numberWays_;} + /// Set maximum number of ways branch may have + inline void setNumberWays(int numberWays) + { numberWays_ = static_cast<short int>(numberWays) ; } + /** Return preferred way to branch. If two + then way=0 means down and 1 means up, otherwise + way points to preferred branch + */ + inline void setWhichWay(int way) + { whichWay_ = static_cast<short int>(way) ; } + /** Return current preferred way to branch. If two + then way=0 means down and 1 means up, otherwise + way points to preferred branch + */ + inline int whichWay() const + { return whichWay_;} + /// Get pre-emptive preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + virtual int preferredWay() const + { return -1;} + /// Return infeasibility + inline double infeasibility() const + { return infeasibility_;} + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + /** Reset variable bounds to their original values. + Bounds may be tightened, so it may be good to be able to reset them to + their original values. + */ + virtual void resetBounds(const OsiSolverInterface * ) {} + /** Change column numbers after preprocessing + */ + virtual void resetSequenceEtc(int , const int * ) {} + /// Updates stuff like pseudocosts before threads + virtual void updateBefore(const OsiObject * ) {} + /// Updates stuff like pseudocosts after threads finished + virtual void updateAfter(const OsiObject * , const OsiObject * ) {} + +protected: + /// data + + /// Computed infeasibility + mutable double infeasibility_; + /// Computed preferred way to branch + mutable short whichWay_; + /// Maximum number of ways on branch + short numberWays_; + /// Priority + int priority_; + +}; +/// Define a class to add a bit of complexity to OsiObject +/// This assumes 2 way branching + + +class OsiObject2 : public OsiObject { + +public: + + /// Default Constructor + OsiObject2 (); + + /// Copy constructor + OsiObject2 ( const OsiObject2 &); + + /// Assignment operator + OsiObject2 & operator=( const OsiObject2& rhs); + + /// Destructor + virtual ~OsiObject2 (); + + /// Set preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + inline void setPreferredWay(int value) + {preferredWay_=value;} + + /// Get preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + virtual int preferredWay() const + { return preferredWay_;} +protected: + /// Preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + int preferredWay_; + /// "Infeasibility" on other way + mutable double otherInfeasibility_; + +}; + +/** \brief Abstract branching object base class + + In the abstract, an OsiBranchingObject contains instructions for how to + branch. We want an abstract class so that we can describe how to branch on + simple objects (<i>e.g.</i>, integers) and more exotic objects + (<i>e.g.</i>, cliques or hyperplanes). + + The #branch() method is the crucial routine: it is expected to be able to + step through a set of branch arms, executing the actions required to create + each subproblem in turn. The base class is primarily virtual to allow for + a wide range of problem modifications. + + See OsiObject for an overview of the two classes (OsiObject and + OsiBranchingObject) which make up Osi's branching + model. +*/ + +class OsiBranchingObject { + +public: + + /// Default Constructor + OsiBranchingObject (); + + /// Constructor + OsiBranchingObject (OsiSolverInterface * solver, double value); + + /// Copy constructor + OsiBranchingObject ( const OsiBranchingObject &); + + /// Assignment operator + OsiBranchingObject & operator=( const OsiBranchingObject& rhs); + + /// Clone + virtual OsiBranchingObject * clone() const=0; + + /// Destructor + virtual ~OsiBranchingObject (); + + /// The number of branch arms created for this branching object + inline int numberBranches() const + {return numberBranches_;} + + /// The number of branch arms left for this branching object + inline int numberBranchesLeft() const + {return numberBranches_-branchIndex_;} + + /// Increment the number of branch arms left for this branching object + inline void incrementNumberBranchesLeft() + { numberBranches_ ++;} + + /** Set the number of branch arms left for this branching object + Just for forcing + */ + inline void setNumberBranchesLeft(int /*value*/) + {/*assert (value==1&&!branchIndex_);*/ numberBranches_=1;} + + /// Decrement the number of branch arms left for this branching object + inline void decrementNumberBranchesLeft() + {branchIndex_++;} + + /** \brief Execute the actions required to branch, as specified by the + current state of the branching object, and advance the object's + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface * solver)=0; + /** \brief Execute the actions required to branch, as specified by the + current state of the branching object, and advance the object's + state. + Returns change in guessed objective on next branch + */ + virtual double branch() {return branch(NULL);} + /** \brief Return true if branch should fix variables + */ + virtual bool boundBranch() const + {return true;} + /** Get the state of the branching object + This is just the branch index + */ + inline int branchIndex() const + {return branchIndex_;} + + /** Set the state of the branching object. + */ + inline void setBranchingIndex(int branchIndex) + { branchIndex_ = static_cast<short int>(branchIndex) ; } + + /// Current value + inline double value() const + {return value_;} + + /// Return pointer back to object which created + inline const OsiObject * originalObject() const + {return originalObject_;} + /// Set pointer back to object which created + inline void setOriginalObject(const OsiObject * object) + {originalObject_=object;} + /** Double checks in case node can change its mind! + Returns objective value + Can change objective etc */ + virtual void checkIsCutoff(double ) {} + /// For debug + int columnNumber() const; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface * =NULL) const {} + +protected: + + /// Current value - has some meaning about branch + double value_; + + /// Pointer back to object which created + const OsiObject * originalObject_; + + /** Number of branches + */ + int numberBranches_; + + /** The state of the branching object. i.e. branch index + This starts at 0 when created + */ + short branchIndex_; + +}; +/* This contains information + This could also contain pseudo shadow prices + or information for dealing with computing and trusting pseudo-costs +*/ +class OsiBranchingInformation { + +public: + + /// Default Constructor + OsiBranchingInformation (); + + /** Useful Constructor + (normalSolver true if has matrix etc etc) + copySolution true if constructot should make a copy + */ + OsiBranchingInformation (const OsiSolverInterface * solver, bool normalSolver,bool copySolution=false); + + /// Copy constructor + OsiBranchingInformation ( const OsiBranchingInformation &); + + /// Assignment operator + OsiBranchingInformation & operator=( const OsiBranchingInformation& rhs); + + /// Clone + virtual OsiBranchingInformation * clone() const; + + /// Destructor + virtual ~OsiBranchingInformation (); + + // Note public +public: + /// data + + /** State of search + 0 - no solution + 1 - only heuristic solutions + 2 - branched to a solution + 3 - no solution but many nodes + */ + int stateOfSearch_; + /// Value of objective function (in minimization sense) + double objectiveValue_; + /// Value of objective cutoff (in minimization sense) + double cutoff_; + /// Direction 1.0 for minimization, -1.0 for maximization + double direction_; + /// Integer tolerance + double integerTolerance_; + /// Primal tolerance + double primalTolerance_; + /// Maximum time remaining before stopping on time + double timeRemaining_; + /// Dual to use if row bound violated (if negative then pseudoShadowPrices off) + double defaultDual_; + /// Pointer to solver + mutable const OsiSolverInterface * solver_; + /// The number of columns + int numberColumns_; + /// Pointer to current lower bounds on columns + mutable const double * lower_; + /// Pointer to current solution + mutable const double * solution_; + /// Pointer to current upper bounds on columns + mutable const double * upper_; + /// Highly optional target (hot start) solution + const double * hotstartSolution_; + /// Pointer to duals + const double * pi_; + /// Pointer to row activity + const double * rowActivity_; + /// Objective + const double * objective_; + /// Pointer to current lower bounds on rows + const double * rowLower_; + /// Pointer to current upper bounds on rows + const double * rowUpper_; + /// Elements in column copy of matrix + const double * elementByColumn_; + /// Column starts + const CoinBigIndex * columnStart_; + /// Column lengths + const int * columnLength_; + /// Row indices + const int * row_; + /** Useful region of length CoinMax(numberColumns,2*numberRows) + This is allocated and deleted before OsiObject::infeasibility + It is zeroed on entry and should be so on exit + It only exists if defaultDual_>=0.0 + */ + double * usefulRegion_; + /// Useful index region to go with usefulRegion_ + int * indexRegion_; + /// Number of solutions found + int numberSolutions_; + /// Number of branching solutions found (i.e. exclude heuristics) + int numberBranchingSolutions_; + /// Depth in tree + int depth_; + /// TEMP + bool owningSolution_; +}; + +/// This just adds two-wayness to a branching object + +class OsiTwoWayBranchingObject : public OsiBranchingObject { + +public: + + /// Default constructor + OsiTwoWayBranchingObject (); + + /** Create a standard tw0-way branch object + + Specifies a simple two-way branch. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiTwoWayBranchingObject (OsiSolverInterface *solver,const OsiObject * originalObject, + int way , double value) ; + + /// Copy constructor + OsiTwoWayBranchingObject ( const OsiTwoWayBranchingObject &); + + /// Assignment operator + OsiTwoWayBranchingObject & operator= (const OsiTwoWayBranchingObject& rhs); + + /// Destructor + virtual ~OsiTwoWayBranchingObject (); + + using OsiBranchingObject::branch ; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface * solver)=0; + + inline int firstBranch() const { return firstBranch_; } + /// Way returns -1 on down +1 on up + inline int way() const + { return !branchIndex_ ? firstBranch_ : -firstBranch_;} +protected: + /// Which way was first branch -1 = down, +1 = up + int firstBranch_; +}; +/// Define a single integer class + + +class OsiSimpleInteger : public OsiObject2 { + +public: + + /// Default Constructor + OsiSimpleInteger (); + + /// Useful constructor - passed solver index + OsiSimpleInteger (const OsiSolverInterface * solver, int iColumn); + + /// Useful constructor - passed solver index and original bounds + OsiSimpleInteger (int iColumn, double lower, double upper); + + /// Copy constructor + OsiSimpleInteger ( const OsiSimpleInteger &); + + /// Clone + virtual OsiObject * clone() const; + + /// Assignment operator + OsiSimpleInteger & operator=( const OsiSimpleInteger& rhs); + + /// Destructor + virtual ~OsiSimpleInteger (); + + using OsiObject::infeasibility ; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const; + + using OsiObject::feasibleRegion ; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; + + + /// Set solver column number + inline void setColumnNumber(int value) + {columnNumber_=value;} + + /** Column number if single column object -1 otherwise, + so returns >= 0 + Used by heuristics + */ + virtual int columnNumber() const; + + /// Original bounds + inline double originalLowerBound() const + { return originalLower_;} + inline void setOriginalLowerBound(double value) + { originalLower_=value;} + inline double originalUpperBound() const + { return originalUpper_;} + inline void setOriginalUpperBound(double value) + { originalUpper_=value;} + /** Reset variable bounds to their original values. + Bounds may be tightened, so it may be good to be able to reset them to + their original values. + */ + virtual void resetBounds(const OsiSolverInterface * solver) ; + /** Change column numbers after preprocessing + */ + virtual void resetSequenceEtc(int numberColumns, const int * originalColumns); + + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { return false;} +protected: + /// data + /// Original lower bound + double originalLower_; + /// Original upper bound + double originalUpper_; + /// Column number in solver + int columnNumber_; + +}; +/** Simple branching object for an integer variable + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. 0 -> down, 1-> up. +*/ + +class OsiIntegerBranchingObject : public OsiTwoWayBranchingObject { + +public: + + /// Default constructor + OsiIntegerBranchingObject (); + + /** Create a standard floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiIntegerBranchingObject (OsiSolverInterface *solver,const OsiSimpleInteger * originalObject, + int way , double value) ; + /** Create a standard floor/ceiling branch object + + Specifies a simple two-way branch in a more flexible way. One arm of the + branch will be lb <= x <= downUpperBound, the other upLowerBound <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiIntegerBranchingObject (OsiSolverInterface *solver,const OsiSimpleInteger * originalObject, + int way , double value, double downUpperBound, double upLowerBound) ; + + /// Copy constructor + OsiIntegerBranchingObject ( const OsiIntegerBranchingObject &); + + /// Assignment operator + OsiIntegerBranchingObject & operator= (const OsiIntegerBranchingObject& rhs); + + /// Clone + virtual OsiBranchingObject * clone() const; + + /// Destructor + virtual ~OsiIntegerBranchingObject (); + + using OsiBranchingObject::branch ; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface * solver); + + using OsiBranchingObject::print ; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface * solver=NULL); + +protected: + // Probably could get away with just value which is already stored + /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) + double down_[2]; + /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) + double up_[2]; +}; + + +/** Define Special Ordered Sets of type 1 and 2. These do not have to be + integer - so do not appear in lists of integers. + + which_ points columns of matrix +*/ + + +class OsiSOS : public OsiObject2 { + +public: + + // Default Constructor + OsiSOS (); + + /** Useful constructor - which are indices + and weights are also given. If null then 0,1,2.. + type is SOS type + */ + OsiSOS (const OsiSolverInterface * solver, int numberMembers, + const int * which, const double * weights, int type=1); + + // Copy constructor + OsiSOS ( const OsiSOS &); + + /// Clone + virtual OsiObject * clone() const; + + // Assignment operator + OsiSOS & operator=( const OsiSOS& rhs); + + // Destructor + virtual ~OsiSOS (); + + using OsiObject::infeasibility ; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation * info,int & whichWay) const; + + using OsiObject::feasibleRegion ; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + + /// Redoes data when sequence numbers change + virtual void resetSequenceEtc(int numberColumns, const int * originalColumns); + + /// Number of members + inline int numberMembers() const + {return numberMembers_;} + + /// Members (indices in range 0 ... numberColumns-1) + inline const int * members() const + {return members_;} + + /// SOS type + inline int sosType() const + {return sosType_;} + + /// SOS type + inline int setType() const + {return sosType_;} + + /** Array of weights */ + inline const double * weights() const + { return weights_;} + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + {return (sosType_==1&&integerValued_);} + /// Set whether set is integer valued or not + inline void setIntegerValued(bool yesNo) + { integerValued_=yesNo;} + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { return true;} + /// Set number of members + inline void setNumberMembers(int value) + {numberMembers_=value;} + + /// Members (indices in range 0 ... numberColumns-1) + inline int * mutableMembers() const + {return members_;} + + /// Set SOS type + inline void setSosType(int value) + {sosType_=value;} + + /** Array of weights */ + inline double * mutableWeights() const + { return weights_;} +protected: + /// data + + /// Members (indices in range 0 ... numberColumns-1) + int * members_; + /// Weights + double * weights_; + + /// Number of members + int numberMembers_; + /// SOS type + int sosType_; + /// Whether integer valued + bool integerValued_; +}; + +/** Branching object for Special ordered sets + + */ +class OsiSOSBranchingObject : public OsiTwoWayBranchingObject { + +public: + + // Default Constructor + OsiSOSBranchingObject (); + + // Useful constructor + OsiSOSBranchingObject (OsiSolverInterface * solver, const OsiSOS * originalObject, + int way, + double separator); + + // Copy constructor + OsiSOSBranchingObject ( const OsiSOSBranchingObject &); + + // Assignment operator + OsiSOSBranchingObject & operator=( const OsiSOSBranchingObject& rhs); + + /// Clone + virtual OsiBranchingObject * clone() const; + + // Destructor + virtual ~OsiSOSBranchingObject (); + + using OsiBranchingObject::branch ; + /// Does next branch and updates state + virtual double branch(OsiSolverInterface * solver); + + using OsiBranchingObject::print ; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface * solver=NULL); +private: + /// data +}; +/** Lotsize class */ + + +class OsiLotsize : public OsiObject2 { + +public: + + // Default Constructor + OsiLotsize (); + + /* Useful constructor - passed model index. + Also passed valid values - if range then pairs + */ + OsiLotsize (const OsiSolverInterface * solver, int iColumn, + int numberPoints, const double * points, bool range=false); + + // Copy constructor + OsiLotsize ( const OsiLotsize &); + + /// Clone + virtual OsiObject * clone() const; + + // Assignment operator + OsiLotsize & operator=( const OsiLotsize& rhs); + + // Destructor + virtual ~OsiLotsize (); + + using OsiObject::infeasibility ; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const; + + using OsiObject::feasibleRegion ; + /** Set bounds to contain the current solution. + + More precisely, for the variable associated with this object, take the + value given in the current solution, force it within the current bounds + if required, then set the bounds to fix the variable at the integer + nearest the solution value. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; + + + /// Set solver column number + inline void setColumnNumber(int value) + {columnNumber_=value;} + + /** Column number if single column object -1 otherwise, + so returns >= 0 + Used by heuristics + */ + virtual int columnNumber() const; + /** Reset original upper and lower bound values from the solver. + + Handy for updating bounds held in this object after bounds held in the + solver have been tightened. + */ + virtual void resetBounds(const OsiSolverInterface * solver); + + /** Finds range of interest so value is feasible in range range_ or infeasible + between hi[range_] and lo[range_+1]. Returns true if feasible. + */ + bool findRange(double value, double integerTolerance) const; + + /** Returns floor and ceiling + */ + virtual void floorCeiling(double & floorLotsize, double & ceilingLotsize, double value, + double tolerance) const; + + /// Original bounds + inline double originalLowerBound() const + { return bound_[0];} + inline double originalUpperBound() const + { return bound_[rangeType_*numberRanges_-1];} + /// Type - 1 points, 2 ranges + inline int rangeType() const + { return rangeType_;} + /// Number of points + inline int numberRanges() const + { return numberRanges_;} + /// Ranges + inline double * bound() const + { return bound_;} + /** Change column numbers after preprocessing + */ + virtual void resetSequenceEtc(int numberColumns, const int * originalColumns); + + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { return true;} + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + {return false;} + +private: + /// data + + /// Column number in model + int columnNumber_; + /// Type - 1 points, 2 ranges + int rangeType_; + /// Number of points + int numberRanges_; + // largest gap + double largestGap_; + /// Ranges + double * bound_; + /// Current range + mutable int range_; +}; + + +/** Lotsize branching object + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. + + Variable_ holds the index of the integer variable in the integerVariable_ + array of the model. +*/ + +class OsiLotsizeBranchingObject : public OsiTwoWayBranchingObject { + +public: + + /// Default constructor + OsiLotsizeBranchingObject (); + + /** Create a lotsize floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be is lb <= x <= valid range below(x*), the other valid range above(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiLotsizeBranchingObject (OsiSolverInterface *solver,const OsiLotsize * originalObject, + int way , double value) ; + + /// Copy constructor + OsiLotsizeBranchingObject ( const OsiLotsizeBranchingObject &); + + /// Assignment operator + OsiLotsizeBranchingObject & operator= (const OsiLotsizeBranchingObject& rhs); + + /// Clone + virtual OsiBranchingObject * clone() const; + + /// Destructor + virtual ~OsiLotsizeBranchingObject (); + + using OsiBranchingObject::branch ; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface * solver); + + using OsiBranchingObject::print ; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface * solver=NULL); + +protected: + /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) + double down_[2]; + /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) + double up_[2]; +}; +#endif diff --git a/thirdparty/linux/include/coin/OsiChooseVariable.hpp b/thirdparty/linux/include/coin/OsiChooseVariable.hpp new file mode 100644 index 0000000..1613bca --- /dev/null +++ b/thirdparty/linux/include/coin/OsiChooseVariable.hpp @@ -0,0 +1,534 @@ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiChooseVariable_H +#define OsiChooseVariable_H + +#include <string> +#include <vector> + +#include "CoinWarmStartBasis.hpp" +#include "OsiBranchingObject.hpp" + +class OsiSolverInterface; +class OsiHotInfo; + +/** This class chooses a variable to branch on + + The base class just chooses the variable and direction without strong branching but it + has information which would normally be used by strong branching e.g. to re-enter + having fixed a variable but using same candidates for strong branching. + + The flow is : + a) initialize the process. This decides on strong branching list + and stores indices of all infeasible objects + b) do strong branching on list. If list is empty then just + choose one candidate and return without strong branching. If not empty then + go through list and return best. However we may find that the node is infeasible + or that we can fix a variable. If so we return and it is up to user to call + again (after fixing a variable). +*/ + +class OsiChooseVariable { + +public: + + /// Default Constructor + OsiChooseVariable (); + + /// Constructor from solver (so we can set up arrays etc) + OsiChooseVariable (const OsiSolverInterface * solver); + + /// Copy constructor + OsiChooseVariable (const OsiChooseVariable &); + + /// Assignment operator + OsiChooseVariable & operator= (const OsiChooseVariable& rhs); + + /// Clone + virtual OsiChooseVariable * clone() const; + + /// Destructor + virtual ~OsiChooseVariable (); + + /** Sets up strong list and clears all if initialize is true. + Returns number of infeasibilities. + If returns -1 then has worked out node is infeasible! + */ + virtual int setupList ( OsiBranchingInformation *info, bool initialize); + /** Choose a variable + Returns - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + We can pick up branch from bestObjectIndex() and bestWhichWay() + We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() + If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() + If fixVariables is true then 2,3,4 are all really same as problem changed + */ + virtual int chooseVariable( OsiSolverInterface * solver, OsiBranchingInformation *info, bool fixVariables); + /// Returns true if solution looks feasible against given objects + virtual bool feasibleSolution(const OsiBranchingInformation * info, + const double * solution, + int numberObjects, + const OsiObject ** objects); + /// Saves a good solution + void saveSolution(const OsiSolverInterface * solver); + /// Clears out good solution after use + void clearGoodSolution(); + /// Given a candidate fill in useful information e.g. estimates + virtual void updateInformation( const OsiBranchingInformation *info, + int branch, OsiHotInfo * hotInfo); +#if 1 + /// Given a branch fill in useful information e.g. estimates + virtual void updateInformation( int whichObject, int branch, + double changeInObjective, double changeInValue, + int status); +#endif + /// Objective value for feasible solution + inline double goodObjectiveValue() const + { return goodObjectiveValue_;} + /// Estimate of up change or change on chosen if n-way + inline double upChange() const + { return upChange_;} + /// Estimate of down change or max change on other possibilities if n-way + inline double downChange() const + { return downChange_;} + /// Good solution - deleted by finalize + inline const double * goodSolution() const + { return goodSolution_;} + /// Index of chosen object + inline int bestObjectIndex() const + { return bestObjectIndex_;} + /// Set index of chosen object + inline void setBestObjectIndex(int value) + { bestObjectIndex_ = value;} + /// Preferred way of chosen object + inline int bestWhichWay() const + { return bestWhichWay_;} + /// Set preferred way of chosen object + inline void setBestWhichWay(int value) + { bestWhichWay_ = value;} + /// Index of forced object + inline int firstForcedObjectIndex() const + { return firstForcedObjectIndex_;} + /// Set index of forced object + inline void setFirstForcedObjectIndex(int value) + { firstForcedObjectIndex_ = value;} + /// Preferred way of forced object + inline int firstForcedWhichWay() const + { return firstForcedWhichWay_;} + /// Set preferred way of forced object + inline void setFirstForcedWhichWay(int value) + { firstForcedWhichWay_ = value;} + /// Get the number of objects unsatisfied at this node - accurate on first pass + inline int numberUnsatisfied() const + {return numberUnsatisfied_;} + /// Number of objects to choose for strong branching + inline int numberStrong() const + { return numberStrong_;} + /// Set number of objects to choose for strong branching + inline void setNumberStrong(int value) + { numberStrong_ = value;} + /// Number left on strong list + inline int numberOnList() const + { return numberOnList_;} + /// Number of strong branches actually done + inline int numberStrongDone() const + { return numberStrongDone_;} + /// Number of strong iterations actually done + inline int numberStrongIterations() const + { return numberStrongIterations_;} + /// Number of strong branches which changed bounds + inline int numberStrongFixed() const + { return numberStrongFixed_;} + /// List of candidates + inline const int * candidates() const + { return list_;} + /// Trust results from strong branching for changing bounds + inline bool trustStrongForBound() const + { return trustStrongForBound_;} + /// Set trust results from strong branching for changing bounds + inline void setTrustStrongForBound(bool yesNo) + { trustStrongForBound_ = yesNo;} + /// Trust results from strong branching for valid solution + inline bool trustStrongForSolution() const + { return trustStrongForSolution_;} + /// Set trust results from strong branching for valid solution + inline void setTrustStrongForSolution(bool yesNo) + { trustStrongForSolution_ = yesNo;} + /// Set solver and redo arrays + void setSolver (const OsiSolverInterface * solver); + /** Return status - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + We can pick up branch from bestObjectIndex() and bestWhichWay() + We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() + If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() + */ + inline int status() const + { return status_;} + inline void setStatus(int value) + { status_ = value;} + + +protected: + // Data + /// Objective value for feasible solution + double goodObjectiveValue_; + /// Estimate of up change or change on chosen if n-way + double upChange_; + /// Estimate of down change or max change on other possibilities if n-way + double downChange_; + /// Good solution - deleted by finalize + double * goodSolution_; + /// List of candidates + int * list_; + /// Useful array (for sorting etc) + double * useful_; + /// Pointer to solver + const OsiSolverInterface * solver_; + /* Status - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + */ + int status_; + /// Index of chosen object + int bestObjectIndex_; + /// Preferred way of chosen object + int bestWhichWay_; + /// Index of forced object + int firstForcedObjectIndex_; + /// Preferred way of forced object + int firstForcedWhichWay_; + /// The number of objects unsatisfied at this node. + int numberUnsatisfied_; + /// Number of objects to choose for strong branching + int numberStrong_; + /// Number left on strong list + int numberOnList_; + /// Number of strong branches actually done + int numberStrongDone_; + /// Number of strong iterations actually done + int numberStrongIterations_; + /// Number of bound changes due to strong branching + int numberStrongFixed_; + /// List of unsatisfied objects - first numberOnList_ for strong branching + /// Trust results from strong branching for changing bounds + bool trustStrongForBound_; + /// Trust results from strong branching for valid solution + bool trustStrongForSolution_; +}; + +/** This class is the placeholder for the pseudocosts used by OsiChooseStrong. + It can also be used by any other pseudocost based strong branching + algorithm. +*/ + +class OsiPseudoCosts { +protected: + // Data + /// Total of all changes up + double * upTotalChange_; + /// Total of all changes down + double * downTotalChange_; + /// Number of times up + int * upNumber_; + /// Number of times down + int * downNumber_; + /// Number of objects (could be found from solver) + int numberObjects_; + /// Number before we trust + int numberBeforeTrusted_; + +private: + void gutsOfDelete(); + void gutsOfCopy(const OsiPseudoCosts& rhs); + +public: + OsiPseudoCosts(); + virtual ~OsiPseudoCosts(); + OsiPseudoCosts(const OsiPseudoCosts& rhs); + OsiPseudoCosts& operator=(const OsiPseudoCosts& rhs); + + /// Number of times before trusted + inline int numberBeforeTrusted() const + { return numberBeforeTrusted_; } + /// Set number of times before trusted + inline void setNumberBeforeTrusted(int value) + { numberBeforeTrusted_ = value; } + /// Initialize the pseudocosts with n entries + void initialize(int n); + /// Give the number of objects for which pseudo costs are stored + inline int numberObjects() const + { return numberObjects_; } + + /** @name Accessor methods to pseudo costs data */ + //@{ + inline double* upTotalChange() { return upTotalChange_; } + inline const double* upTotalChange() const { return upTotalChange_; } + + inline double* downTotalChange() { return downTotalChange_; } + inline const double* downTotalChange() const { return downTotalChange_; } + + inline int* upNumber() { return upNumber_; } + inline const int* upNumber() const { return upNumber_; } + + inline int* downNumber() { return downNumber_; } + inline const int* downNumber() const { return downNumber_; } + //@} + + /// Given a candidate fill in useful information e.g. estimates + virtual void updateInformation(const OsiBranchingInformation *info, + int branch, OsiHotInfo * hotInfo); +#if 1 + /// Given a branch fill in useful information e.g. estimates + virtual void updateInformation( int whichObject, int branch, + double changeInObjective, double changeInValue, + int status); +#endif +}; + +/** This class chooses a variable to branch on + + This chooses the variable and direction with reliability strong branching. + + The flow is : + a) initialize the process. This decides on strong branching list + and stores indices of all infeasible objects + b) do strong branching on list. If list is empty then just + choose one candidate and return without strong branching. If not empty then + go through list and return best. However we may find that the node is infeasible + or that we can fix a variable. If so we return and it is up to user to call + again (after fixing a variable). +*/ + +class OsiChooseStrong : public OsiChooseVariable { + +public: + + /// Default Constructor + OsiChooseStrong (); + + /// Constructor from solver (so we can set up arrays etc) + OsiChooseStrong (const OsiSolverInterface * solver); + + /// Copy constructor + OsiChooseStrong (const OsiChooseStrong &); + + /// Assignment operator + OsiChooseStrong & operator= (const OsiChooseStrong& rhs); + + /// Clone + virtual OsiChooseVariable * clone() const; + + /// Destructor + virtual ~OsiChooseStrong (); + + /** Sets up strong list and clears all if initialize is true. + Returns number of infeasibilities. + If returns -1 then has worked out node is infeasible! + */ + virtual int setupList ( OsiBranchingInformation *info, bool initialize); + /** Choose a variable + Returns - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + We can pick up branch from bestObjectIndex() and bestWhichWay() + We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() + If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() + If fixVariables is true then 2,3,4 are all really same as problem changed + */ + virtual int chooseVariable( OsiSolverInterface * solver, OsiBranchingInformation *info, bool fixVariables); + + /** Pseudo Shadow Price mode + 0 - off + 1 - use if no strong info + 2 - use if strong not trusted + 3 - use even if trusted + */ + inline int shadowPriceMode() const + { return shadowPriceMode_;} + /// Set Shadow price mode + inline void setShadowPriceMode(int value) + { shadowPriceMode_ = value;} + + /** Accessor method to pseudo cost object*/ + const OsiPseudoCosts& pseudoCosts() const + { return pseudoCosts_; } + + /** Accessor method to pseudo cost object*/ + OsiPseudoCosts& pseudoCosts() + { return pseudoCosts_; } + + /** A feww pass-through methods to access members of pseudoCosts_ as if they + were members of OsiChooseStrong object */ + inline int numberBeforeTrusted() const { + return pseudoCosts_.numberBeforeTrusted(); } + inline void setNumberBeforeTrusted(int value) { + pseudoCosts_.setNumberBeforeTrusted(value); } + inline int numberObjects() const { + return pseudoCosts_.numberObjects(); } + +protected: + + /** This is a utility function which does strong branching on + a list of objects and stores the results in OsiHotInfo.objects. + On entry the object sequence is stored in the OsiHotInfo object + and maybe more. + It returns - + -1 - one branch was infeasible both ways + 0 - all inspected - nothing can be fixed + 1 - all inspected - some can be fixed (returnCriterion==0) + 2 - may be returning early - one can be fixed (last one done) (returnCriterion==1) + 3 - returning because max time + + */ + int doStrongBranching( OsiSolverInterface * solver, + OsiBranchingInformation *info, + int numberToDo, int returnCriterion); + + /** Clear out the results array */ + void resetResults(int num); + +protected: + /** Pseudo Shadow Price mode + 0 - off + 1 - use and multiply by strong info + 2 - use + */ + int shadowPriceMode_; + + /** The pseudo costs for the chooser */ + OsiPseudoCosts pseudoCosts_; + + /** The results of the strong branching done on the candidates where the + pseudocosts were not sufficient */ + OsiHotInfo* results_; + /** The number of OsiHotInfo objetcs that contain information */ + int numResults_; +}; + +/** This class contains the result of strong branching on a variable + When created it stores enough information for strong branching +*/ + +class OsiHotInfo { + +public: + + /// Default Constructor + OsiHotInfo (); + + /// Constructor from useful information + OsiHotInfo ( OsiSolverInterface * solver, + const OsiBranchingInformation *info, + const OsiObject * const * objects, + int whichObject); + + /// Copy constructor + OsiHotInfo (const OsiHotInfo &); + + /// Assignment operator + OsiHotInfo & operator= (const OsiHotInfo& rhs); + + /// Clone + virtual OsiHotInfo * clone() const; + + /// Destructor + virtual ~OsiHotInfo (); + + /** Fill in useful information after strong branch. + Return status + */ + int updateInformation( const OsiSolverInterface * solver, const OsiBranchingInformation * info, + OsiChooseVariable * choose); + /// Original objective value + inline double originalObjectiveValue() const + { return originalObjectiveValue_;} + /// Up change - invalid if n-way + inline double upChange() const + { assert (branchingObject_->numberBranches()==2); return changes_[1];} + /// Down change - invalid if n-way + inline double downChange() const + { assert (branchingObject_->numberBranches()==2); return changes_[0];} + /// Set up change - invalid if n-way + inline void setUpChange(double value) + { assert (branchingObject_->numberBranches()==2); changes_[1] = value;} + /// Set down change - invalid if n-way + inline void setDownChange(double value) + { assert (branchingObject_->numberBranches()==2); changes_[0] = value;} + /// Change on way k + inline double change(int k) const + { return changes_[k];} + + /// Up iteration count - invalid if n-way + inline int upIterationCount() const + { assert (branchingObject_->numberBranches()==2); return iterationCounts_[1];} + /// Down iteration count - invalid if n-way + inline int downIterationCount() const + { assert (branchingObject_->numberBranches()==2); return iterationCounts_[0];} + /// Iteration count on way k + inline int iterationCount(int k) const + { return iterationCounts_[k];} + + /// Up status - invalid if n-way + inline int upStatus() const + { assert (branchingObject_->numberBranches()==2); return statuses_[1];} + /// Down status - invalid if n-way + inline int downStatus() const + { assert (branchingObject_->numberBranches()==2); return statuses_[0];} + /// Set up status - invalid if n-way + inline void setUpStatus(int value) + { assert (branchingObject_->numberBranches()==2); statuses_[1] = value;} + /// Set down status - invalid if n-way + inline void setDownStatus(int value) + { assert (branchingObject_->numberBranches()==2); statuses_[0] = value;} + /// Status on way k + inline int status(int k) const + { return statuses_[k];} + /// Branching object + inline OsiBranchingObject * branchingObject() const + { return branchingObject_;} + inline int whichObject() const + { return whichObject_;} + +protected: + // Data + /// Original objective value + double originalObjectiveValue_; + /// Objective changes + double * changes_; + /// Iteration counts + int * iterationCounts_; + /** Status + -1 - not done + 0 - feasible and finished + 1 - infeasible + 2 - not finished + */ + int * statuses_; + /// Branching object + OsiBranchingObject * branchingObject_; + /// Which object on list + int whichObject_; +}; + + +#endif diff --git a/thirdparty/linux/include/coin/OsiClpSolverInterface.hpp b/thirdparty/linux/include/coin/OsiClpSolverInterface.hpp new file mode 100644 index 0000000..ebc7e64 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiClpSolverInterface.hpp @@ -0,0 +1,1509 @@ +// $Id$ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + + +#ifndef OsiClpSolverInterface_H +#define OsiClpSolverInterface_H + +#include <string> +#include <cfloat> +#include <map> + +#include "ClpSimplex.hpp" +#include "ClpLinearObjective.hpp" +#include "CoinPackedMatrix.hpp" +#include "OsiSolverInterface.hpp" +#include "CoinWarmStartBasis.hpp" +#include "ClpEventHandler.hpp" +#include "ClpNode.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinFinite.hpp" + +class OsiRowCut; +class OsiClpUserSolver; +class OsiClpDisasterHandler; +class CoinSet; +static const double OsiClpInfinity = COIN_DBL_MAX; + +//############################################################################# + +/** Clp Solver Interface + +Instantiation of OsiClpSolverInterface for the Model Algorithm. + +*/ + +class OsiClpSolverInterface : + virtual public OsiSolverInterface { + friend void OsiClpSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); + +public: + //--------------------------------------------------------------------------- + /**@name Solve methods */ + //@{ + /// Solve initial LP relaxation + virtual void initialSolve(); + + /// Resolve an LP relaxation after problem modification + virtual void resolve(); + + /// Resolve an LP relaxation after problem modification (try GUB) + virtual void resolveGub(int needed); + + /// Invoke solver's built-in enumeration algorithm + virtual void branchAndBound(); + + /** Solve when primal column and dual row solutions are near-optimal + options - 0 no presolve (use primal and dual) + 1 presolve (just use primal) + 2 no presolve (just use primal) + basis - 0 use all slack basis + 1 try and put some in basis + */ + void crossover(int options,int basis); + //@} + + /*! @name OsiSimplexInterface methods + \brief Methods for the Osi Simplex API. + + The current implementation should work for both minimisation and + maximisation in mode 1 (tableau access). In mode 2 (single pivot), only + minimisation is supported as of 100907. + */ + //@{ + /** \brief Simplex API capability. + + Returns + - 0 if no simplex API + - 1 if can just do getBInv etc + - 2 if has all OsiSimplex methods + */ + virtual int canDoSimplexInterface() const; + + /*! \brief Enables simplex mode 1 (tableau access) + + Tells solver that calls to getBInv etc are about to take place. + Underlying code may need mutable as this may be called from + CglCut::generateCuts which is const. If that is too horrific then + each solver e.g. BCP or CBC will have to do something outside + main loop. + */ + virtual void enableFactorization() const; + + /*! \brief Undo any setting changes made by #enableFactorization */ + virtual void disableFactorization() const; + + /** Returns true if a basis is available + AND problem is optimal. This should be used to see if + the BInvARow type operations are possible and meaningful. + */ + virtual bool basisIsAvailable() const; + + /** The following two methods may be replaced by the + methods of OsiSolverInterface using OsiWarmStartBasis if: + 1. OsiWarmStartBasis resize operation is implemented + more efficiently and + 2. It is ensured that effects on the solver are the same + + Returns a basis status of the structural/artificial variables + At present as warm start i.e 0 free, 1 basic, 2 upper, 3 lower + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + */ + virtual void getBasisStatus(int* cstat, int* rstat) const; + + /** Set the status of structural/artificial variables and + factorize, update solution etc + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + Returns 0 if OK, 1 if problem is bad e.g. duplicate elements, too large ... + */ + virtual int setBasisStatus(const int* cstat, const int* rstat); + + ///Get the reduced gradient for the cost vector c + virtual void getReducedGradient(double* columnReducedCosts, + double * duals, + const double * c) const ; + + ///Get a row of the tableau (slack part in slack if not NULL) + virtual void getBInvARow(int row, double* z, double * slack=NULL) const; + + /** Get a row of the tableau (slack part in slack if not NULL) + If keepScaled is true then scale factors not applied after so + user has to use coding similar to what is in this method + */ + virtual void getBInvARow(int row, CoinIndexedVector * z, CoinIndexedVector * slack=NULL, + bool keepScaled=false) const; + + ///Get a row of the basis inverse + virtual void getBInvRow(int row, double* z) const; + + ///Get a column of the tableau + virtual void getBInvACol(int col, double* vec) const ; + + ///Get a column of the tableau + virtual void getBInvACol(int col, CoinIndexedVector * vec) const ; + + /** Update (i.e. ftran) the vector passed in. + Unscaling is applied after - can't be applied before + */ + + virtual void getBInvACol(CoinIndexedVector * vec) const ; + + ///Get a column of the basis inverse + virtual void getBInvCol(int col, double* vec) const ; + + /** Get basic indices (order of indices corresponds to the + order of elements in a vector retured by getBInvACol() and + getBInvCol()). + */ + virtual void getBasics(int* index) const; + + /*! \brief Enables simplex mode 2 (individual pivot control) + + This method is supposed to ensure that all typical things (like + reduced costs, etc.) are updated when individual pivots are executed + and can be queried by other methods. + */ + virtual void enableSimplexInterface(bool doingPrimal); + /// Copy across enabled stuff from one solver to another + void copyEnabledSuff(OsiClpSolverInterface & rhs); + + /*! \brief Undo setting changes made by #enableSimplexInterface */ + virtual void disableSimplexInterface(); + /// Copy across enabled stuff from one solver to another + void copyEnabledStuff(ClpSimplex & rhs); + + /** Perform a pivot by substituting a colIn for colOut in the basis. + The status of the leaving variable is given in statOut. Where + 1 is to upper bound, -1 to lower bound + Return code is 0 for okay, + 1 if inaccuracy forced re-factorization (should be okay) and + -1 for singular factorization + */ + virtual int pivot(int colIn, int colOut, int outStatus); + + /** Obtain a result of the primal pivot + Outputs: colOut -- leaving column, outStatus -- its status, + t -- step size, and, if dx!=NULL, *dx -- primal ray direction. + Inputs: colIn -- entering column, sign -- direction of its change (+/-1). + Both for colIn and colOut, artificial variables are index by + the negative of the row index minus 1. + Return code (for now): 0 -- leaving variable found, + -1 -- everything else? + Clearly, more informative set of return values is required + Primal and dual solutions are updated + */ + virtual int primalPivotResult(int colIn, int sign, + int& colOut, int& outStatus, + double& t, CoinPackedVector* dx); + + /** Obtain a result of the dual pivot (similar to the previous method) + Differences: entering variable and a sign of its change are now + the outputs, the leaving variable and its statuts -- the inputs + If dx!=NULL, then *dx contains dual ray + Return code: same + */ + virtual int dualPivotResult(int& colIn, int& sign, + int colOut, int outStatus, + double& t, CoinPackedVector* dx); + + + //@} + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. There can be various reasons for failure: the given + parameter is not applicable for the solver (e.g., refactorization + frequency for the clp algorithm), the parameter is not yet implemented + for the solver or simply the value of the parameter is out of the range + the solver accepts. If a parameter setting call returns false check the + details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + */ + //@{ + // Set an integer parameter + bool setIntParam(OsiIntParam key, int value); + // Set an double parameter + bool setDblParam(OsiDblParam key, double value); + // Set a string parameter + bool setStrParam(OsiStrParam key, const std::string & value); + // Get an integer parameter + bool getIntParam(OsiIntParam key, int& value) const; + // Get an double parameter + bool getDblParam(OsiDblParam key, double& value) const; + // Get a string parameter + bool getStrParam(OsiStrParam key, std::string& value) const; + // Set a hint parameter - overrides OsiSolverInterface + virtual bool setHintParam(OsiHintParam key, bool yesNo=true, + OsiHintStrength strength=OsiHintTry, + void * otherInformation=NULL); + //@} + + //--------------------------------------------------------------------------- + ///@name Methods returning info on how the solution process terminated + //@{ + /// Are there a numerical difficulties? + virtual bool isAbandoned() const; + /// Is optimality proven? + virtual bool isProvenOptimal() const; + /// Is primal infeasiblity proven? + virtual bool isProvenPrimalInfeasible() const; + /// Is dual infeasiblity proven? + virtual bool isProvenDualInfeasible() const; + /// Is the given primal objective limit reached? + virtual bool isPrimalObjectiveLimitReached() const; + /// Is the given dual objective limit reached? + virtual bool isDualObjectiveLimitReached() const; + /// Iteration limit reached? + virtual bool isIterationLimitReached() const; + //@} + + //--------------------------------------------------------------------------- + /**@name WarmStart related methods */ + //@{ + + /*! \brief Get an empty warm start object + + This routine returns an empty CoinWarmStartBasis object. Its purpose is + to provide a way to give a client a warm start basis object of the + appropriate type, which can resized and modified as desired. + */ + + virtual CoinWarmStart *getEmptyWarmStart () const; + + /// Get warmstarting information + virtual CoinWarmStart* getWarmStart() const; + /// Get warmstarting information + inline CoinWarmStartBasis* getPointerToWarmStart() + { return &basis_;} + /// Get warmstarting information + inline const CoinWarmStartBasis* getConstPointerToWarmStart() const + { return &basis_;} + /** Set warmstarting information. Return true/false depending on whether + the warmstart information was accepted or not. */ + virtual bool setWarmStart(const CoinWarmStart* warmstart); + /** \brief Get warm start information. + + Return warm start information for the current state of the solver + interface. If there is no valid warm start information, an empty warm + start object wil be returned. This does not necessarily create an + object - may just point to one. must Delete set true if user + should delete returned object. + OsiClp version always returns pointer and false. + */ + virtual CoinWarmStart* getPointerToWarmStart(bool & mustDelete) ; + + /// Set column status in ClpSimplex and warmStart + void setColumnStatus(int iColumn, ClpSimplex::Status status); + + //@} + + //--------------------------------------------------------------------------- + /**@name Hotstart related methods (primarily used in strong branching). + The user can create a hotstart (a snapshot) of the optimization process + then reoptimize over and over again always starting from there.<br> + <strong>NOTE</strong>: between hotstarted optimizations only + bound changes are allowed. */ + //@{ + /// Create a hotstart point of the optimization process + virtual void markHotStart(); + /// Optimize starting from the hotstart + virtual void solveFromHotStart(); + /// Delete the snapshot + virtual void unmarkHotStart(); + /** Start faster dual - returns negative if problems 1 if infeasible, + Options to pass to solver + 1 - create external reduced costs for columns + 2 - create external reduced costs for rows + 4 - create external row activity (columns always done) + Above only done if feasible + When set resolve does less work + */ + int startFastDual(int options); + /// Stop fast dual + void stopFastDual(); + /// Sets integer tolerance and increment + void setStuff(double tolerance,double increment); + /// Return a conflict analysis cut from small model + OsiRowCut * smallModelCut(const double * originalLower, const double * originalUpper, + int numberRowsAtContinuous,const int * whichGenerator, + int typeCut=0); + /** Return a conflict analysis cut from model + If type is 0 then genuine cut, if 1 then only partially processed + */ + OsiRowCut * modelCut(const double * originalLower, const double * originalUpper, + int numberRowsAtContinuous,const int * whichGenerator, + int typeCut=0); + //@} + + //--------------------------------------------------------------------------- + /**@name Problem information methods + + These methods call the solver's query routines to return + information about the problem referred to by the current object. + Querying a problem that has no data associated with it result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. + + Const pointers returned from any data-query method are valid as + long as the data is unchanged and the solver is not called. + */ + //@{ + /**@name Methods related to querying the input data */ + //@{ + /// Get number of columns + virtual int getNumCols() const { + return modelPtr_->numberColumns(); } + + /// Get number of rows + virtual int getNumRows() const { + return modelPtr_->numberRows(); } + + /// Get number of nonzero elements + virtual int getNumElements() const { + int retVal = 0; + const CoinPackedMatrix * matrix =modelPtr_->matrix(); + if ( matrix != NULL ) retVal=matrix->getNumElements(); + return retVal; } + + /// Return name of row if one exists or Rnnnnnnn + /// maxLen is currently ignored and only there to match the signature from the base class! + virtual std::string getRowName(int rowIndex, + unsigned maxLen = static_cast<unsigned>(std::string::npos)) const; + + /// Return name of column if one exists or Cnnnnnnn + /// maxLen is currently ignored and only there to match the signature from the base class! + virtual std::string getColName(int colIndex, + unsigned maxLen = static_cast<unsigned>(std::string::npos)) const; + + + /// Get pointer to array[getNumCols()] of column lower bounds + virtual const double * getColLower() const { return modelPtr_->columnLower(); } + + /// Get pointer to array[getNumCols()] of column upper bounds + virtual const double * getColUpper() const { return modelPtr_->columnUpper(); } + + /** Get pointer to array[getNumRows()] of row constraint senses. + <ul> + <li>'L' <= constraint + <li>'E' = constraint + <li>'G' >= constraint + <li>'R' ranged constraint + <li>'N' free constraint + </ul> + */ + virtual const char * getRowSense() const; + + /** Get pointer to array[getNumRows()] of rows right-hand sides + <ul> + <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] + <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] + <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] + <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0 + </ul> + */ + virtual const double * getRightHandSide() const ; + + /** Get pointer to array[getNumRows()] of row ranges. + <ul> + <li> if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] + <li> if rowsense()[i] != 'R' then + rowrange()[i] is undefined + </ul> + */ + virtual const double * getRowRange() const ; + + /// Get pointer to array[getNumRows()] of row lower bounds + virtual const double * getRowLower() const { return modelPtr_->rowLower(); } + + /// Get pointer to array[getNumRows()] of row upper bounds + virtual const double * getRowUpper() const { return modelPtr_->rowUpper(); } + + /// Get pointer to array[getNumCols()] of objective function coefficients + virtual const double * getObjCoefficients() const + { if (fakeMinInSimplex_) + return linearObjective_ ; + else + return modelPtr_->objective(); } + + /// Get objective function sense (1 for min (default), -1 for max) + virtual double getObjSense() const + { return ((fakeMinInSimplex_)?-modelPtr_->optimizationDirection(): + modelPtr_->optimizationDirection()); } + + /// Return true if column is continuous + virtual bool isContinuous(int colNumber) const; + /// Return true if variable is binary + virtual bool isBinary(int colIndex) const; + + /** Return true if column is integer. + Note: This function returns true if the the column + is binary or a general integer. + */ + virtual bool isInteger(int colIndex) const; + + /// Return true if variable is general integer + virtual bool isIntegerNonBinary(int colIndex) const; + + /// Return true if variable is binary and not fixed at either bound + virtual bool isFreeBinary(int colIndex) const; + /** Return array of column length + 0 - continuous + 1 - binary (may get fixed later) + 2 - general integer (may get fixed later) + */ + virtual const char * getColType(bool refresh=false) const; + + /** Return true if column is integer but does not have to + be declared as such. + Note: This function returns true if the the column + is binary or a general integer. + */ + bool isOptionalInteger(int colIndex) const; + /** Set the index-th variable to be an optional integer variable */ + void setOptionalInteger(int index); + + /// Get pointer to row-wise copy of matrix + virtual const CoinPackedMatrix * getMatrixByRow() const; + + /// Get pointer to column-wise copy of matrix + virtual const CoinPackedMatrix * getMatrixByCol() const; + + /// Get pointer to mutable column-wise copy of matrix + virtual CoinPackedMatrix * getMutableMatrixByCol() const; + + /// Get solver's value for infinity + virtual double getInfinity() const { return OsiClpInfinity; } + //@} + + /**@name Methods related to querying the solution */ + //@{ + /// Get pointer to array[getNumCols()] of primal solution vector + virtual const double * getColSolution() const; + + /// Get pointer to array[getNumRows()] of dual prices + virtual const double * getRowPrice() const; + + /// Get a pointer to array[getNumCols()] of reduced costs + virtual const double * getReducedCost() const; + + /** Get pointer to array[getNumRows()] of row activity levels (constraint + matrix times the solution vector */ + virtual const double * getRowActivity() const; + + /// Get objective function value + virtual double getObjValue() const; + + /** Get how many iterations it took to solve the problem (whatever + "iteration" mean to the solver. */ + virtual int getIterationCount() const + { return modelPtr_->numberIterations(); } + + /** Get as many dual rays as the solver can provide. (In case of proven + primal infeasibility there should be at least one.) + + The first getNumRows() ray components will always be associated with + the row duals (as returned by getRowPrice()). If \c fullRay is true, + the final getNumCols() entries will correspond to the ray components + associated with the nonbasic variables. If the full ray is requested + and the method cannot provide it, it will throw an exception. + + <strong>NOTE for implementers of solver interfaces:</strong> <br> + The double pointers in the vector should point to arrays of length + getNumRows() and they should be allocated via new[]. <br> + + <strong>NOTE for users of solver interfaces:</strong> <br> + It is the user's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector<double*> getDualRays(int maxNumRays, + bool fullRay = false) const; + /** Get as many primal rays as the solver can provide. (In case of proven + dual infeasibility there should be at least one.) + + <strong>NOTE for implementers of solver interfaces:</strong> <br> + The double pointers in the vector should point to arrays of length + getNumCols() and they should be allocated via new[]. <br> + + <strong>NOTE for users of solver interfaces:</strong> <br> + It is the user's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector<double*> getPrimalRays(int maxNumRays) const; + + //@} + //@} + + //--------------------------------------------------------------------------- + + /**@name Problem modifying methods */ + //@{ + //------------------------------------------------------------------------- + /**@name Changing bounds on variables and constraints */ + //@{ + /** Set an objective function coefficient */ + virtual void setObjCoeff( int elementIndex, double elementValue ); + + /** Set a single column lower bound<br> + Use -DBL_MAX for -infinity. */ + virtual void setColLower( int elementIndex, double elementValue ); + + /** Set a single column upper bound<br> + Use DBL_MAX for infinity. */ + virtual void setColUpper( int elementIndex, double elementValue ); + + /** Set a single column lower and upper bound */ + virtual void setColBounds( int elementIndex, + double lower, double upper ); + + /** Set the bounds on a number of columns simultaneously<br> + The default implementation just invokes setColLower() and + setColUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + virtual void setColSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + + /** Set a single row lower bound<br> + Use -DBL_MAX for -infinity. */ + virtual void setRowLower( int elementIndex, double elementValue ); + + /** Set a single row upper bound<br> + Use DBL_MAX for infinity. */ + virtual void setRowUpper( int elementIndex, double elementValue ) ; + + /** Set a single row lower and upper bound */ + virtual void setRowBounds( int elementIndex, + double lower, double upper ) ; + + /** Set the type of a single row<br> */ + virtual void setRowType(int index, char sense, double rightHandSide, + double range); + + /** Set the bounds on a number of rows simultaneously<br> + The default implementation just invokes setRowLower() and + setRowUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + <em>either</em> bound changes + @param boundList the new lower/upper bound pairs for the constraints + */ + virtual void setRowSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + + /** Set the type of a number of rows simultaneously<br> + The default implementation just invokes setRowType() + over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + <em>any</em> characteristics changes + @param senseList the new senses + @param rhsList the new right hand sides + @param rangeList the new ranges + */ + virtual void setRowSetTypes(const int* indexFirst, + const int* indexLast, + const char* senseList, + const double* rhsList, + const double* rangeList); + /** Set the objective coefficients for all columns + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setObjective(const double * array); + + /** Set the lower bounds for all columns + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColLower(const double * array); + + /** Set the upper bounds for all columns + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColUpper(const double * array); + +// using OsiSolverInterface::setRowName ; + /// Set name of row +// virtual void setRowName(int rowIndex, std::string & name) ; + virtual void setRowName(int rowIndex, std::string name) ; + +// using OsiSolverInterface::setColName ; + /// Set name of column +// virtual void setColName(int colIndex, std::string & name) ; + virtual void setColName(int colIndex, std::string name) ; + + //@} + + //------------------------------------------------------------------------- + /**@name Integrality related changing methods */ + //@{ + /** Set the index-th variable to be a continuous variable */ + virtual void setContinuous(int index); + /** Set the index-th variable to be an integer variable */ + virtual void setInteger(int index); + /** Set the variables listed in indices (which is of length len) to be + continuous variables */ + virtual void setContinuous(const int* indices, int len); + /** Set the variables listed in indices (which is of length len) to be + integer variables */ + virtual void setInteger(const int* indices, int len); + /// Number of SOS sets + inline int numberSOS() const + { return numberSOS_;} + /// SOS set info + inline const CoinSet * setInfo() const + { return setInfo_;} + /** \brief Identify integer variables and SOS and create corresponding objects. + + Record integer variables and create an OsiSimpleInteger object for each + one. All existing OsiSimpleInteger objects will be destroyed. + If the solver supports SOS then do the same for SOS. + If justCount then no objects created and we just store numberIntegers_ + Returns number of SOS + */ + + virtual int findIntegersAndSOS(bool justCount); + //@} + + //------------------------------------------------------------------------- + /// Set objective function sense (1 for min (default), -1 for max,) + virtual void setObjSense(double s ) + { modelPtr_->setOptimizationDirection( s < 0 ? -1 : 1); } + + /** Set the primal solution column values + + colsol[numcols()] is an array of values of the problem column + variables. These values are copied to memory owned by the + solver object or the solver. They will be returned as the + result of colsol() until changed by another call to + setColsol() or by a call to any solver routine. Whether the + solver makes use of the solution in any way is + solver-dependent. + */ + virtual void setColSolution(const double * colsol); + + /** Set dual solution vector + + rowprice[numrows()] is an array of values of the problem row + dual variables. These values are copied to memory owned by the + solver object or the solver. They will be returned as the + result of rowprice() until changed by another call to + setRowprice() or by a call to any solver routine. Whether the + solver makes use of the solution in any way is + solver-dependent. + */ + virtual void setRowPrice(const double * rowprice); + + //------------------------------------------------------------------------- + /**@name Methods to expand a problem.<br> + Note that if a column is added then by default it will correspond to a + continuous variable. */ + //@{ + + //using OsiSolverInterface::addCol ; + /** */ + virtual void addCol(const CoinPackedVectorBase& vec, + const double collb, const double colub, + const double obj); + /*! \brief Add a named column (primal variable) to the problem. + */ + virtual void addCol(const CoinPackedVectorBase& vec, + const double collb, const double colub, + const double obj, std::string name) ; + /** Add a column (primal variable) to the problem. */ + virtual void addCol(int numberElements, const int * rows, const double * elements, + const double collb, const double colub, + const double obj) ; + /*! \brief Add a named column (primal variable) to the problem. + */ + virtual void addCol(int numberElements, + const int* rows, const double* elements, + const double collb, const double colub, + const double obj, std::string name) ; + /** */ + virtual void addCols(const int numcols, + const CoinPackedVectorBase * const * cols, + const double* collb, const double* colub, + const double* obj); + /** */ + virtual void addCols(const int numcols, + const int * columnStarts, const int * rows, const double * elements, + const double* collb, const double* colub, + const double* obj); + /** */ + virtual void deleteCols(const int num, const int * colIndices); + + /** */ + virtual void addRow(const CoinPackedVectorBase& vec, + const double rowlb, const double rowub); + /** */ + /*! \brief Add a named row (constraint) to the problem. + + The default implementation adds the row, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addRow(const CoinPackedVectorBase& vec, + const double rowlb, const double rowub, + std::string name) ; + virtual void addRow(const CoinPackedVectorBase& vec, + const char rowsen, const double rowrhs, + const double rowrng); + /** Add a row (constraint) to the problem. */ + virtual void addRow(int numberElements, const int * columns, const double * element, + const double rowlb, const double rowub) ; + /*! \brief Add a named row (constraint) to the problem. + */ + virtual void addRow(const CoinPackedVectorBase& vec, + const char rowsen, const double rowrhs, + const double rowrng, std::string name) ; + /** */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase * const * rows, + const double* rowlb, const double* rowub); + /** */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase * const * rows, + const char* rowsen, const double* rowrhs, + const double* rowrng); + + /** */ + virtual void addRows(const int numrows, + const int * rowStarts, const int * columns, const double * element, + const double* rowlb, const double* rowub); + /// + void modifyCoefficient(int row, int column, double newElement, + bool keepZero=false) + {modelPtr_->modifyCoefficient(row,column,newElement, keepZero);} + + /** */ + virtual void deleteRows(const int num, const int * rowIndices); + /** If solver wants it can save a copy of "base" (continuous) model here + */ + virtual void saveBaseModel() ; + /** Strip off rows to get to this number of rows. + If solver wants it can restore a copy of "base" (continuous) model here + */ + virtual void restoreBaseModel(int numberRows); + + //----------------------------------------------------------------------- + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts); + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + This uses array of pointers + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts); + /** Apply a collection of cuts. + + Only cuts which have an <code>effectiveness >= effectivenessLb</code> + are applied. + <ul> + <li> ReturnCode.getNumineffective() -- number of cuts which were + not applied because they had an + <code>effectiveness < effectivenessLb</code> + <li> ReturnCode.getNuminconsistent() -- number of invalid cuts + <li> ReturnCode.getNuminconsistentWrtIntegerModel() -- number of + cuts that are invalid with respect to this integer model + <li> ReturnCode.getNuminfeasible() -- number of cuts that would + make this integer model infeasible + <li> ReturnCode.getNumApplied() -- number of integer cuts which + were applied to the integer model + <li> cs.size() == getNumineffective() + + getNuminconsistent() + + getNuminconsistentWrtIntegerModel() + + getNuminfeasible() + + getNumApplied() + </ul> + */ + virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs, + double effectivenessLb = 0.0); + + //@} + //@} + + //--------------------------------------------------------------------------- + +public: + + /**@name Methods to input a problem */ + //@{ + /** Load in an problem by copying the arguments (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + */ + virtual void loadProblem(const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by lower and upper bounds). For + default values see the previous method. <br> + <strong>WARNING</strong>: The arguments passed to this method will be + freed using the C++ <code>delete</code> and <code>delete[]</code> + functions. + */ + virtual void assignProblem(CoinPackedMatrix*& matrix, + double*& collb, double*& colub, double*& obj, + double*& rowlb, double*& rowub); + + /** Load in an problem by copying the arguments (the constraints on the + rows are given by sense/rhs/range triplets). If a pointer is NULL then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>obj</code>: all variables have 0 objective coefficient + <li> <code>rowsen</code>: all rows are >= + <li> <code>rowrhs</code>: all right hand sides are 0 + <li> <code>rowrng</code>: 0 for the ranged rows + </ul> + */ + virtual void loadProblem(const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by sense/rhs/range triplets). For + default values see the previous method. <br> + <strong>WARNING</strong>: The arguments passed to this method will be + freed using the C++ <code>delete</code> and <code>delete[]</code> + functions. + */ + virtual void assignProblem(CoinPackedMatrix*& matrix, + double*& collb, double*& colub, double*& obj, + char*& rowsen, double*& rowrhs, + double*& rowrng); + + /** Just like the other loadProblem() methods except that the matrix is + given as a ClpMatrixBase. */ + virtual void loadProblem(const ClpMatrixBase& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub) ; + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub); + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng); + /// This loads a model from a coinModel object - returns number of errors + virtual int loadFromCoinModel ( CoinModel & modelObject, bool keepSolution=false); + + using OsiSolverInterface::readMps ; + /** Read an mps file from the given filename (defaults to Osi reader) - returns + number of errors (see OsiMpsReader class) */ + virtual int readMps(const char *filename, + const char *extension = "mps") ; + /** Read an mps file from the given filename returns + number of errors (see OsiMpsReader class) */ + int readMps(const char *filename,bool keepNames,bool allowErrors); + /// Read an mps file + virtual int readMps (const char *filename, const char*extension, + int & numberSets, CoinSet ** & sets); + + /** Write the problem into an mps file of the given filename. + If objSense is non zero then -1.0 forces the code to write a + maximization objective and +1.0 to write a minimization one. + If 0.0 then solver can do what it wants */ + virtual void writeMps(const char *filename, + const char *extension = "mps", + double objSense=0.0) const; + /** Write the problem into an mps file of the given filename, + names may be null. formatType is + 0 - normal + 1 - extra accuracy + 2 - IEEE hex (later) + + Returns non-zero on I/O error + */ + virtual int writeMpsNative(const char *filename, + const char ** rowNames, const char ** columnNames, + int formatType=0,int numberAcross=2, + double objSense=0.0) const ; + /// Read file in LP format (with names) + virtual int readLp(const char *filename, const double epsilon = 1e-5); + /** Write the problem into an Lp file of the given filename. + If objSense is non zero then -1.0 forces the code to write a + maximization objective and +1.0 to write a minimization one. + If 0.0 then solver can do what it wants. + This version calls writeLpNative with names */ + virtual void writeLp(const char *filename, + const char *extension = "lp", + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + /** Write the problem into the file pointed to by the parameter fp. + Other parameters are similar to + those of writeLp() with first parameter filename. + */ + virtual void writeLp(FILE *fp, + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + /** + I (JJF) am getting annoyed because I can't just replace a matrix. + The default behavior of this is do nothing so only use where that would not matter + e.g. strengthening a matrix for MIP + */ + virtual void replaceMatrixOptional(const CoinPackedMatrix & matrix); + /// And if it does matter (not used at present) + virtual void replaceMatrix(const CoinPackedMatrix & matrix) ; + //@} + + /**@name Message handling (extra for Clp messages). + Normally I presume you would want the same language. + If not then you could use underlying model pointer */ + //@{ + /** Pass in a message handler + + It is the client's responsibility to destroy a message handler installed + by this routine; it will not be destroyed when the solver interface is + destroyed. + */ + virtual void passInMessageHandler(CoinMessageHandler * handler); + /// Set language + void newLanguage(CoinMessages::Language language); + void setLanguage(CoinMessages::Language language) + {newLanguage(language);} + /// Set log level (will also set underlying solver's log level) + void setLogLevel(int value); + /// Create C++ lines to get to current state + void generateCpp( FILE * fp); + //@} + //--------------------------------------------------------------------------- + + /**@name Clp specific public interfaces */ + //@{ + /// Get pointer to Clp model + ClpSimplex * getModelPtr() const ; + /// Set pointer to Clp model and return old + inline ClpSimplex * swapModelPtr(ClpSimplex * newModel) + { ClpSimplex * model = modelPtr_; modelPtr_=newModel;return model;} + /// Get special options + inline unsigned int specialOptions() const + { return specialOptions_;} + void setSpecialOptions(unsigned int value); + /// Last algorithm used , 1 = primal, 2 = dual other unknown + inline int lastAlgorithm() const + { return lastAlgorithm_;} + /// Set last algorithm used , 1 = primal, 2 = dual other unknown + inline void setLastAlgorithm(int value) + { lastAlgorithm_ = value;} + /// Get scaling action option + inline int cleanupScaling() const + { return cleanupScaling_;} + /** Set Scaling option + When scaling is on it is possible that the scaled problem + is feasible but the unscaled is not. Clp returns a secondary + status code to that effect. This option allows for a cleanup. + If you use it I would suggest 1. + This only affects actions when scaled optimal + 0 - no action + 1 - clean up using dual if primal infeasibility + 2 - clean up using dual if dual infeasibility + 3 - clean up using dual if primal or dual infeasibility + 11,12,13 - as 1,2,3 but use primal + */ + inline void setCleanupScaling(int value) + { cleanupScaling_=value;} + /** Get smallest allowed element in cut. + If smaller than this then ignored */ + inline double smallestElementInCut() const + { return smallestElementInCut_;} + /** Set smallest allowed element in cut. + If smaller than this then ignored */ + inline void setSmallestElementInCut(double value) + { smallestElementInCut_=value;} + /** Get smallest change in cut. + If (upper-lower)*element < this then element is + taken out and cut relaxed. + (upper-lower) is taken to be at least 1.0 and + this is assumed >= smallestElementInCut_ + */ + inline double smallestChangeInCut() const + { return smallestChangeInCut_;} + /** Set smallest change in cut. + If (upper-lower)*element < this then element is + taken out and cut relaxed. + (upper-lower) is taken to be at least 1.0 and + this is assumed >= smallestElementInCut_ + */ + inline void setSmallestChangeInCut(double value) + { smallestChangeInCut_=value;} + /// Pass in initial solve options + inline void setSolveOptions(const ClpSolve & options) + { solveOptions_ = options;} + /** Tighten bounds - lightweight or very lightweight + 0 - normal, 1 lightweight but just integers, 2 lightweight and all + */ + virtual int tightenBounds(int lightweight=0); + /// See if any integer variables make infeasible other way + int infeasibleOtherWay(char * whichWay); + /// Return number of entries in L part of current factorization + virtual CoinBigIndex getSizeL() const; + /// Return number of entries in U part of current factorization + virtual CoinBigIndex getSizeU() const; + /// Get disaster handler + const OsiClpDisasterHandler * disasterHandler() const + { return disasterHandler_;} + /// Pass in disaster handler + void passInDisasterHandler(OsiClpDisasterHandler * handler); + /// Get fake objective + ClpLinearObjective * fakeObjective() const + { return fakeObjective_;} + /// Set fake objective (and take ownership) + void setFakeObjective(ClpLinearObjective * fakeObjective); + /// Set fake objective + void setFakeObjective(double * fakeObjective); + /*! \brief Set up solver for repeated use by Osi interface. + + The normal usage does things like keeping factorization around so can be + used. Will also do things like keep scaling and row copy of matrix if + matrix does not change. + + \p senseOfAdventure: + - 0 - safe stuff as above + - 1 - will take more risks - if it does not work then bug which will be + fixed + - 2 - don't bother doing most extreme termination checks e.g. don't bother + re-factorizing if less than 20 iterations. + - 3 - Actually safer than 1 (mainly just keeps factorization) + + \p printOut + - -1 always skip round common messages instead of doing some work + - 0 skip if normal defaults + - 1 leaves + */ + void setupForRepeatedUse(int senseOfAdventure=0, int printOut=0); + /// Synchronize model (really if no cuts in tree) + virtual void synchronizeModel(); + /*! \brief Set special options in underlying clp solver. + + Safe as const because #modelPtr_ is mutable. + */ + void setSpecialOptionsMutable(unsigned int value) const; + + //@} + + //--------------------------------------------------------------------------- + + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiClpSolverInterface (); + + /// Clone + virtual OsiSolverInterface * clone(bool copyData = true) const; + + /// Copy constructor + OsiClpSolverInterface (const OsiClpSolverInterface &); + + /// Borrow constructor - only delete one copy + OsiClpSolverInterface (ClpSimplex * rhs, bool reallyOwn=false); + + /// Releases so won't error + void releaseClp(); + + /// Assignment operator + OsiClpSolverInterface & operator=(const OsiClpSolverInterface& rhs); + + /// Destructor + virtual ~OsiClpSolverInterface (); + + /// Resets as if default constructor + virtual void reset(); + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected methods + //@{ + /** Apply a row cut (append to constraint matrix). */ + virtual void applyRowCut(const OsiRowCut& rc); + + /** Apply a column cut (adjust one or more bounds). */ + virtual void applyColCut(const OsiColCut& cc); + //@} + + //--------------------------------------------------------------------------- + +protected: + /**@name Protected methods */ + //@{ + /// The real work of a copy constructor (used by copy and assignment) + void gutsOfDestructor(); + + /// Deletes all mutable stuff + void freeCachedResults() const; + + /// Deletes all mutable stuff for row ranges etc + void freeCachedResults0() const; + + /// Deletes all mutable stuff for matrix etc + void freeCachedResults1() const; + + /// A method that fills up the rowsense_, rhs_ and rowrange_ arrays + void extractSenseRhsRange() const; + + /// + void fillParamMaps(); + /** Warm start + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + */ + CoinWarmStartBasis getBasis(ClpSimplex * model) const; + /** Sets up working basis as a copy of input + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + */ + void setBasis( const CoinWarmStartBasis & basis, ClpSimplex * model); + /// Crunch down problem a bit + void crunch(); + /// Extend scale factors + void redoScaleFactors(int numberRows,const CoinBigIndex * starts, + const int * indices, const double * elements); +public: + /** Sets up working basis as a copy of input and puts in as basis + */ + void setBasis( const CoinWarmStartBasis & basis); + /// Just puts current basis_ into ClpSimplex model + inline void setBasis( ) + { setBasis(basis_,modelPtr_);} + /// Warm start difference from basis_ to statusArray + CoinWarmStartDiff * getBasisDiff(const unsigned char * statusArray) const ; + /// Warm start from statusArray + CoinWarmStartBasis * getBasis(const unsigned char * statusArray) const ; + /// Delete all scale factor stuff and reset option + void deleteScaleFactors(); + /// If doing fast hot start then ranges are computed + inline const double * upRange() const + { return rowActivity_;} + inline const double * downRange() const + { return columnActivity_;} + /// Pass in range array + inline void passInRanges(int * array) + { whichRange_=array;} + /// Pass in sos stuff from AMPl + void setSOSData(int numberSOS,const char * type, + const int * start,const int * indices, const double * weights=NULL); + /// Compute largest amount any at continuous away from bound + void computeLargestAway(); + /// Get largest amount continuous away from bound + inline double largestAway() const + { return largestAway_;} + /// Set largest amount continuous away from bound + inline void setLargestAway(double value) + { largestAway_ = value;} + /// Sort of lexicographic resolve + void lexSolve(); + //@} + +protected: + /**@name Protected member data */ + //@{ + /// Clp model represented by this class instance + mutable ClpSimplex * modelPtr_; + //@} + /**@name Cached information derived from the OSL model */ + //@{ + /// Pointer to dense vector of row sense indicators + mutable char *rowsense_; + + /// Pointer to dense vector of row right-hand side values + mutable double *rhs_; + + /** Pointer to dense vector of slack upper bounds for range + constraints (undefined for non-range rows) + */ + mutable double *rowrange_; + + /** A pointer to the warmstart information to be used in the hotstarts. + This is NOT efficient and more thought should be given to it... */ + mutable CoinWarmStartBasis* ws_; + /** also save row and column information for hot starts + only used in hotstarts so can be casual */ + mutable double * rowActivity_; + mutable double * columnActivity_; + /// Stuff for fast dual + ClpNodeStuff stuff_; + /// Number of SOS sets + int numberSOS_; + /// SOS set info + CoinSet * setInfo_; + /// Alternate model (hot starts) - but also could be permanent and used for crunch + ClpSimplex * smallModel_; + /// factorization for hot starts + ClpFactorization * factorization_; + /** Smallest allowed element in cut. + If smaller than this then ignored */ + double smallestElementInCut_; + /** Smallest change in cut. + If (upper-lower)*element < this then element is + taken out and cut relaxed. */ + double smallestChangeInCut_; + /// Largest amount continuous away from bound + double largestAway_; + /// Arrays for hot starts + char * spareArrays_; + /** Warmstart information to be used in resolves. */ + CoinWarmStartBasis basis_; + /** The original iteration limit before hotstarts started. */ + int itlimOrig_; + + /*! \brief Last algorithm used + + Coded as + - 0 invalid + - 1 primal + - 2 dual + - -911 disaster in the algorithm that was attempted + - 999 current solution no longer optimal due to change in problem or + basis + */ + mutable int lastAlgorithm_; + + /// To say if destructor should delete underlying model + bool notOwned_; + + /// Pointer to row-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByRow_; + + /// Pointer to row-wise copy of continuous problem matrix coefficients. + CoinPackedMatrix *matrixByRowAtContinuous_; + + /// Pointer to integer information + char * integerInformation_; + + /** Pointer to variables for which we want range information + The number is in [0] + memory is not owned by OsiClp + */ + int * whichRange_; + + //std::map<OsiIntParam, ClpIntParam> intParamMap_; + //std::map<OsiDblParam, ClpDblParam> dblParamMap_; + //std::map<OsiStrParam, ClpStrParam> strParamMap_; + + /*! \brief Faking min to get proper dual solution signs in simplex API */ + mutable bool fakeMinInSimplex_ ; + /*! \brief Linear objective + + Normally a pointer to the linear coefficient array in the clp objective. + An independent copy when #fakeMinInSimplex_ is true, because we need + something permanent to point to when #getObjCoefficients is called. + */ + mutable double *linearObjective_; + + /// To save data in OsiSimplex stuff + mutable ClpDataSave saveData_; + /// Options for initialSolve + ClpSolve solveOptions_; + /** Scaling option + When scaling is on it is possible that the scaled problem + is feasible but the unscaled is not. Clp returns a secondary + status code to that effect. This option allows for a cleanup. + If you use it I would suggest 1. + This only affects actions when scaled optimal + 0 - no action + 1 - clean up using dual if primal infeasibility + 2 - clean up using dual if dual infeasibility + 3 - clean up using dual if primal or dual infeasibility + 11,12,13 - as 1,2,3 but use primal + */ + int cleanupScaling_; + /** Special options + 0x80000000 off + 0 simple stuff for branch and bound + 1 try and keep work regions as much as possible + 2 do not use any perturbation + 4 allow exit before re-factorization + 8 try and re-use factorization if no cuts + 16 use standard strong branching rather than clp's + 32 Just go to first factorization in fast dual + 64 try and tighten bounds in crunch + 128 Model will only change in column bounds + 256 Clean up model before hot start + 512 Give user direct access to Clp regions in getBInvARow etc (i.e., + do not unscale, and do not return result in getBInv parameters; + you have to know where to look for the answer) + 1024 Don't "borrow" model in initialSolve + 2048 Don't crunch + 4096 quick check for optimality + Bits above 8192 give where called from in Cbc + At present 0 is normal, 1 doing fast hotstarts, 2 is can do quick check + 65536 Keep simple i.e. no crunch etc + 131072 Try and keep scaling factors around + 262144 Don't try and tighten bounds (funny global cuts) + 524288 Fake objective and 0-1 + 1048576 Don't recompute ray after crunch + 2097152 + */ + mutable unsigned int specialOptions_; + /// Copy of model when option 131072 set + ClpSimplex * baseModel_; + /// Number of rows when last "scaled" + int lastNumberRows_; + /// Continuous model + ClpSimplex * continuousModel_; + /// Possible disaster handler + OsiClpDisasterHandler * disasterHandler_ ; + /// Fake objective + ClpLinearObjective * fakeObjective_; + /// Row scale factors (has inverse at end) + CoinDoubleArrayWithLength rowScale_; + /// Column scale factors (has inverse at end) + CoinDoubleArrayWithLength columnScale_; + //@} +}; + +class OsiClpDisasterHandler : public ClpDisasterHandler { +public: + /**@name Virtual methods that the derived classe should provide. + */ + //@{ + /// Into simplex + virtual void intoSimplex(); + /// Checks if disaster + virtual bool check() const ; + /// saves information for next attempt + virtual void saveInfo(); + /// Type of disaster 0 can fix, 1 abort + virtual int typeOfDisaster(); + //@} + + + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + OsiClpDisasterHandler(OsiClpSolverInterface * model = NULL); + /** Destructor */ + virtual ~OsiClpDisasterHandler(); + // Copy + OsiClpDisasterHandler(const OsiClpDisasterHandler&); + // Assignment + OsiClpDisasterHandler& operator=(const OsiClpDisasterHandler&); + /// Clone + virtual ClpDisasterHandler * clone() const; + + //@} + + /**@name Sets/gets */ + + //@{ + /** set model. */ + void setOsiModel(OsiClpSolverInterface * model); + /// Get model + inline OsiClpSolverInterface * osiModel() const + { return osiModel_;} + /// Set where from + inline void setWhereFrom(int value) + { whereFrom_=value;} + /// Get where from + inline int whereFrom() const + { return whereFrom_;} + /// Set phase + inline void setPhase(int value) + { phase_=value;} + /// Get phase + inline int phase() const + { return phase_;} + /// are we in trouble + bool inTrouble() const; + + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer to model + OsiClpSolverInterface * osiModel_; + /** Where from + 0 dual (resolve) + 1 crunch + 2 primal (resolve) + 4 dual (initialSolve) + 6 primal (initialSolve) + */ + int whereFrom_; + /** phase + 0 initial + 1 trying continuing with back in and maybe different perturb + 2 trying continuing with back in and different scaling + 3 trying dual from all slack + 4 trying primal from previous stored basis + */ + int phase_; + /// Are we in trouble + bool inTrouble_; + //@} +}; +// So unit test can find out if NDEBUG set +bool OsiClpHasNDEBUG(); +//############################################################################# +/** A function that tests the methods in the OsiClpSolverInterface class. */ +void OsiClpSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); +#endif diff --git a/thirdparty/linux/include/coin/OsiColCut.hpp b/thirdparty/linux/include/coin/OsiColCut.hpp new file mode 100644 index 0000000..c98eb5c --- /dev/null +++ b/thirdparty/linux/include/coin/OsiColCut.hpp @@ -0,0 +1,324 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiColCut_H +#define OsiColCut_H + +#include <string> + +#include "CoinPackedVector.hpp" + +#include "OsiCollections.hpp" +#include "OsiCut.hpp" + +/** Column Cut Class + +Column Cut Class has: + <ul> + <li>a sparse vector of column lower bounds + <li>a sparse vector of column upper bounds + </ul> +*/ +class OsiColCut : public OsiCut { + friend void OsiColCutUnitTest(const OsiSolverInterface * baseSiP, + const std::string & mpsDir); + +public: + + //---------------------------------------------------------------- + + /**@name Setting column bounds */ + //@{ + /// Set column lower bounds + inline void setLbs( + int nElements, + const int * colIndices, + const double * lbElements ); + + /// Set column lower bounds from a packed vector + inline void setLbs( const CoinPackedVector & lbs ); + + /// Set column upper bounds + inline void setUbs( + int nElements, + const int * colIndices, + const double * ubElements ); + + /// Set column upper bounds from a packed vector + inline void setUbs( const CoinPackedVector & ubs ); + //@} + + //---------------------------------------------------------------- + + /**@name Getting column bounds */ + //@{ + /// Get column lower bounds + inline const CoinPackedVector & lbs() const; + /// Get column upper bounds + inline const CoinPackedVector & ubs() const; + //@} + + /**@name Comparison operators */ + //@{ +#if __GNUC__ != 2 + using OsiCut::operator== ; +#endif + /** equal - true if lower bounds, upper bounds, + and OsiCut are equal. + */ + inline virtual bool operator==(const OsiColCut& rhs) const; + +#if __GNUC__ != 2 + using OsiCut::operator!= ; +#endif + /// not equal + inline virtual bool operator!=(const OsiColCut& rhs) const; + //@} + + + //---------------------------------------------------------------- + + /**@name Sanity checks on cut */ + //@{ + /** Returns true if the cut is consistent with respect to itself. + This checks to ensure that: + <ul> + <li>The bound vectors do not have duplicate indices, + <li>The bound vectors indices are >=0 + </ul> + */ + inline virtual bool consistent() const; + + /** Returns true if cut is consistent with respect to the solver + interface's model. This checks to ensure that + the lower & upperbound packed vectors: + <ul> + <li>do not have an index >= the number of column is the model. + </ul> + */ + inline virtual bool consistent(const OsiSolverInterface& im) const; + + /** Returns true if the cut is infeasible with respect to its bounds and the + column bounds in the solver interface's models. + This checks whether: + <ul> + <li>the maximum of the new and existing lower bounds is strictly + greater than the minimum of the new and existing upper bounds. +</ul> + */ + inline virtual bool infeasible(const OsiSolverInterface &im) const; + /** Returns infeasibility of the cut with respect to solution + passed in i.e. is positive if cuts off that solution. + solution is getNumCols() long.. + */ + virtual double violated(const double * solution) const; + //@} + + //---------------------------------------------------------------- + + /**@name Constructors and destructors */ + //@{ + /// Assignment operator + OsiColCut & operator=( const OsiColCut& rhs); + + /// Copy constructor + OsiColCut ( const OsiColCut &); + + /// Default Constructor + OsiColCut (); + + /// Clone + virtual OsiColCut * clone() const; + + /// Destructor + virtual ~OsiColCut (); + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + virtual void print() const; + //@} + +private: + + /**@name Private member data */ + //@{ + /// Lower bounds + CoinPackedVector lbs_; + /// Upper bounds + CoinPackedVector ubs_; + //@} + +}; + + + +//------------------------------------------------------------------- +// Set lower & upper bound vectors +//------------------------------------------------------------------- +void OsiColCut::setLbs( + int size, + const int * colIndices, + const double * lbElements ) +{ + lbs_.setVector(size,colIndices,lbElements); +} +// +void OsiColCut::setUbs( + int size, + const int * colIndices, + const double * ubElements ) +{ + ubs_.setVector(size,colIndices,ubElements); +} +// +void OsiColCut::setLbs( const CoinPackedVector & lbs ) +{ + lbs_ = lbs; +} +// +void OsiColCut::setUbs( const CoinPackedVector & ubs ) +{ + ubs_ = ubs; +} + +//------------------------------------------------------------------- +// Get Column Lower Bounds and Column Upper Bounds +//------------------------------------------------------------------- +const CoinPackedVector & OsiColCut::lbs() const +{ + return lbs_; +} +// +const CoinPackedVector & OsiColCut::ubs() const +{ + return ubs_; +} + +//---------------------------------------------------------------- +// == operator +//------------------------------------------------------------------- +bool +OsiColCut::operator==( + const OsiColCut& rhs) const +{ + if ( this->OsiCut::operator!=(rhs) ) + return false; + if ( lbs() != rhs.lbs() ) + return false; + if ( ubs() != rhs.ubs() ) + return false; + return true; +} +// +bool +OsiColCut::operator!=( + const OsiColCut& rhs) const +{ + return !( (*this)==rhs ); +} + +//---------------------------------------------------------------- +// consistent & infeasible +//------------------------------------------------------------------- +bool OsiColCut::consistent() const +{ + const CoinPackedVector & lb = lbs(); + const CoinPackedVector & ub = ubs(); + // Test for consistent cut. + // Are packed vectors consistent? + lb.duplicateIndex("consistent", "OsiColCut"); + ub.duplicateIndex("consistent", "OsiColCut"); + if ( lb.getMinIndex() < 0 ) return false; + if ( ub.getMinIndex() < 0 ) return false; + return true; +} +// +bool OsiColCut::consistent(const OsiSolverInterface& im) const +{ + const CoinPackedVector & lb = lbs(); + const CoinPackedVector & ub = ubs(); + + // Test for consistent cut. + if ( lb.getMaxIndex() >= im.getNumCols() ) return false; + if ( ub.getMaxIndex() >= im.getNumCols() ) return false; + + return true; +} + +#if 0 +bool OsiColCut::feasible(const OsiSolverInterface &im) const +{ + const double * oldColLb = im.getColLower(); + const double * oldColUb = im.getColUpper(); + const CoinPackedVector & cutLbs = lbs(); + const CoinPackedVector & cutUbs = ubs(); + int i; + + for ( i=0; i<cutLbs.size(); i++ ) { + int colIndx = cutLbs.indices()[i]; + double newLb; + if ( cutLbs.elements()[i] > oldColLb[colIndx] ) + newLb = cutLbs.elements()[i]; + else + newLb = oldColLb[colIndx]; + + double newUb = oldColUb[colIndx]; + if ( cutUbs.indexExists(colIndx) ) + if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx]; + if ( newLb > newUb ) + return false; + } + + for ( i=0; i<cutUbs.size(); i++ ) { + int colIndx = cutUbs.indices()[i]; + double newUb = cutUbs.elements()[i] < oldColUb[colIndx] ? cutUbs.elements()[i] : oldColUb[colIndx]; + double newLb = oldColLb[colIndx]; + if ( cutLbs.indexExists(colIndx) ) + if ( cutLbs[colIndx] > newLb ) newLb = cutLbs[colIndx]; + if ( newUb < newLb ) + return false; + } + + return true; +} +#endif + + +bool OsiColCut::infeasible(const OsiSolverInterface &im) const +{ + const double * oldColLb = im.getColLower(); + const double * oldColUb = im.getColUpper(); + const CoinPackedVector & cutLbs = lbs(); + const CoinPackedVector & cutUbs = ubs(); + int i; + + for ( i=0; i<cutLbs.getNumElements(); i++ ) { + int colIndx = cutLbs.getIndices()[i]; + double newLb= cutLbs.getElements()[i] > oldColLb[colIndx] ? + cutLbs.getElements()[i] : oldColLb[colIndx]; + + double newUb = oldColUb[colIndx]; + if ( cutUbs.isExistingIndex(colIndx) ) + if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx]; + if ( newLb > newUb ) + return true; + } + + for ( i=0; i<cutUbs.getNumElements(); i++ ) { + int colIndx = cutUbs.getIndices()[i]; + double newUb = cutUbs.getElements()[i] < oldColUb[colIndx] ? + cutUbs.getElements()[i] : oldColUb[colIndx]; + double newLb = oldColLb[colIndx]; + if ( cutLbs.isExistingIndex(colIndx) ) + if ( cutLbs[colIndx] > newLb ) newLb = cutLbs[colIndx]; + if ( newUb < newLb ) + return true; + } + + return false; +} + +#endif diff --git a/thirdparty/linux/include/coin/OsiCollections.hpp b/thirdparty/linux/include/coin/OsiCollections.hpp new file mode 100644 index 0000000..d68df1a --- /dev/null +++ b/thirdparty/linux/include/coin/OsiCollections.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiCollections_H +#define OsiCollections_H + +#include <vector> + +//Forward declarations +class OsiColCut; +class OsiRowCut; +class OsiCut; + + + +/* Collection Classes */ + +/**@name Typedefs for Standard Template Library collections of Osi Objects. */ +//@{ +/// Vector of int +typedef std::vector<int> OsiVectorInt; +/// Vector of double +typedef std::vector<double> OsiVectorDouble; +/// Vector of OsiColCut pointers +typedef std::vector<OsiColCut *> OsiVectorColCutPtr; +/// Vector of OsiRowCut pointers +typedef std::vector<OsiRowCut *> OsiVectorRowCutPtr; +/// Vector of OsiCut pointers +typedef std::vector<OsiCut *> OsiVectorCutPtr; +//@} + + + +#endif diff --git a/thirdparty/linux/include/coin/OsiConfig.h b/thirdparty/linux/include/coin/OsiConfig.h new file mode 100644 index 0000000..2e42bb9 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiConfig.h @@ -0,0 +1,19 @@ +/* src/Osi/config_osi.h. Generated by configure. */ +/* src/Osi/config_osi.h.in. */ + +#ifndef __CONFIG_OSI_H__ +#define __CONFIG_OSI_H__ + +/* Version number of project */ +#define OSI_VERSION "0.107.4" + +/* Major Version number of project */ +#define OSI_VERSION_MAJOR 0 + +/* Minor Version number of project */ +#define OSI_VERSION_MINOR 107 + +/* Release Version number of project */ +#define OSI_VERSION_RELEASE 4 + +#endif diff --git a/thirdparty/linux/include/coin/OsiCut.hpp b/thirdparty/linux/include/coin/OsiCut.hpp new file mode 100644 index 0000000..0b2cc5c --- /dev/null +++ b/thirdparty/linux/include/coin/OsiCut.hpp @@ -0,0 +1,245 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiCut_H +#define OsiCut_H + +#include "OsiCollections.hpp" +#include "OsiSolverInterface.hpp" + +/** Base Class for cut. + +The Base cut class contains: + <ul> + <li>a measure of the cut's effectivness + </ul> +*/ + +/* + COIN_NOTEST_DUPLICATE is rooted in CoinUtils. Check there before you + meddle here. +*/ +#ifdef COIN_FAST_CODE +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_NOTEST_DUPLICATE +#endif +#endif + +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE true +#else +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE false +#endif + + +class OsiCut { + +public: + + //------------------------------------------------------------------- + /**@name Effectiveness */ + //@{ + /// Set effectiveness + inline void setEffectiveness( double e ); + /// Get effectiveness + inline double effectiveness() const; + //@} + + /**@name GloballyValid */ + //@{ + /// Set globallyValid (nonzero true) + inline void setGloballyValid( bool trueFalse ) + { globallyValid_=trueFalse ? 1 : 0;} + inline void setGloballyValid( ) + { globallyValid_=1;} + inline void setNotGloballyValid( ) + { globallyValid_=0;} + /// Get globallyValid + inline bool globallyValid() const + { return globallyValid_!=0;} + /// Set globallyValid as integer (nonzero true) + inline void setGloballyValidAsInteger( int trueFalse ) + { globallyValid_=trueFalse;} + /// Get globallyValid + inline int globallyValidAsInteger() const + { return globallyValid_;} + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + virtual void print() const {} + //@} + +#if 0 + / **@name Times used */ + / /@{ + / // Set times used + inline void setTimesUsed( int t ); + / // Increment times used + inline void incrementTimesUsed(); + / // Get times used + inline int timesUsed() const; + / /@} + + / **@name Times tested */ + / /@{ + / // Set times tested + inline void setTimesTested( int t ); + / // Increment times tested + inline void incrementTimesTested(); + / // Get times tested + inline int timesTested() const; + / /@} +#endif + + //---------------------------------------------------------------- + + /**@name Comparison operators */ + //@{ + ///equal. 2 cuts are equal if there effectiveness are equal + inline virtual bool operator==(const OsiCut& rhs) const; + /// not equal + inline virtual bool operator!=(const OsiCut& rhs) const; + /// less than. True if this.effectiveness < rhs.effectiveness + inline virtual bool operator< (const OsiCut& rhs) const; + /// less than. True if this.effectiveness > rhs.effectiveness + inline virtual bool operator> (const OsiCut& rhs) const; + //@} + + //---------------------------------------------------------------- + // consistent() - returns true if the cut is consistent with repect to itself. + // This might include checks to ensure that a packed vector + // itself does not have a negative index. + // consistent(const OsiSolverInterface& si) - returns true if cut is consistent with + // respect to the solver interface's model. This might include a check to + // make sure a column index is not greater than the number + // of columns in the problem. + // infeasible(const OsiSolverInterface& si) - returns true if the cut is infeasible + // "with respect to itself". This might include a check to ensure + // the lower bound is greater than the upper bound, or if the + // cut simply replaces bounds that the new bounds are feasible with + // respect to the old bounds. + //----------------------------------------------------------------- + /**@name Sanity checks on cut */ + //@{ + /** Returns true if the cut is consistent with respect to itself, + without considering any + data in the model. For example, it might check to ensure + that a column index is not negative. + */ + inline virtual bool consistent() const=0; + + /** Returns true if cut is consistent when considering the solver + interface's model. For example, it might check to ensure + that a column index is not greater than the number of columns + in the model. Assumes consistent() is true. + */ + inline virtual bool consistent(const OsiSolverInterface& si) const=0; + + /** Returns true if the cut is infeasible "with respect to itself" and + cannot be satisfied. This method does NOT check whether adding the + cut to the solver interface's model will make the -model- infeasble. + A cut which returns !infeasible(si) may very well make the model + infeasible. (Of course, adding a cut with returns infeasible(si) + will make the model infeasible.) + + The "with respect to itself" is in quotes becaues + in the case where the cut + simply replaces existing bounds, it may make + sense to test infeasibility with respect to the current bounds + held in the solver interface's model. For example, if the cut + has a single variable in it, it might check that the maximum + of new and existing lower bounds is greater than the minium of + the new and existing upper bounds. + + Assumes that consistent(si) is true.<br> + Infeasible cuts can be a useful mechanism for a cut generator to + inform the solver interface that its detected infeasibility of the + problem. + */ + inline virtual bool infeasible(const OsiSolverInterface &si) const=0; + + /** Returns infeasibility of the cut with respect to solution + passed in i.e. is positive if cuts off that solution. + solution is getNumCols() long.. + */ + virtual double violated(const double * solution) const=0; + //@} + +protected: + + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiCut (); + + /// Copy constructor + OsiCut ( const OsiCut &); + + /// Assignment operator + OsiCut & operator=( const OsiCut& rhs); + + /// Destructor + virtual ~OsiCut (); + //@} + +private: + + /**@name Private member data */ + //@{ + /// Effectiveness + double effectiveness_; + /// If cut has global validity i.e. can be used anywhere in tree + int globallyValid_; +#if 0 + /// Times used + int timesUsed_; + /// Times tested + int timesTested_; +#endif + //@} +}; + + +//------------------------------------------------------------------- +// Set/Get member data +//------------------------------------------------------------------- +void OsiCut::setEffectiveness(double e) { effectiveness_=e; } +double OsiCut::effectiveness() const { return effectiveness_; } + +#if 0 +void OsiCut::setTimesUsed( int t ) { timesUsed_=t; } +void OsiCut::incrementTimesUsed() { timesUsed_++; } +int OsiCut::timesUsed() const { return timesUsed_; } + +void OsiCut::setTimesTested( int t ) { timesTested_=t; } +void OsiCut::incrementTimesTested() { timesTested_++; } +int OsiCut::timesTested() const{ return timesTested_; } +#endif + +//---------------------------------------------------------------- +// == operator +//------------------------------------------------------------------- +bool +OsiCut::operator==(const OsiCut& rhs) const +{ + return effectiveness()==rhs.effectiveness(); +} +bool +OsiCut::operator!=(const OsiCut& rhs) const +{ + return !( (*this)==rhs ); +} +bool +OsiCut::operator< (const OsiCut& rhs) const +{ + return effectiveness()<rhs.effectiveness(); +} +bool +OsiCut::operator> (const OsiCut& rhs) const +{ + return effectiveness()>rhs.effectiveness(); +} +#endif diff --git a/thirdparty/linux/include/coin/OsiCuts.hpp b/thirdparty/linux/include/coin/OsiCuts.hpp new file mode 100644 index 0000000..d454402 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiCuts.hpp @@ -0,0 +1,474 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiCuts_H +#define OsiCuts_H + +#include "CoinPragma.hpp" + +#include <cmath> +#include <cfloat> +#include "OsiCollections.hpp" +#include "OsiRowCut.hpp" +#include "OsiColCut.hpp" +#include "CoinFloatEqual.hpp" + +/** Collections of row cuts and column cuts +*/ +class OsiCuts { + friend void OsiCutsUnitTest(); + +public: + /**@name Iterator classes + */ + //@{ + /** Iterator + + This is a class for iterating over the collection of cuts. + */ + class iterator { + friend class OsiCuts; + public: + iterator(OsiCuts& cuts); + iterator(const iterator & src); + iterator & operator=( const iterator& rhs); + ~iterator (); + OsiCut* operator*() const { return cutP_; } + iterator operator++(); + + iterator operator++(int) + { + iterator temp = *this; + ++*this; + return temp; + } + + bool operator==(const iterator& it) const { + return (colCutIndex_+rowCutIndex_)==(it.colCutIndex_+it.rowCutIndex_); + } + + bool operator!=(const iterator& it) const { + return !((*this)==it); + } + + bool operator<(const iterator& it) const { + return (colCutIndex_+rowCutIndex_)<(it.colCutIndex_+it.rowCutIndex_); + } + + private: + iterator(); + // *THINK* : how to inline these without sticking the code here (ugly...) + iterator begin(); + iterator end(); + OsiCuts& cuts_; + int rowCutIndex_; + int colCutIndex_; + OsiCut * cutP_; + }; + + /** Const Iterator + + This is a class for iterating over the collection of cuts. + */ + class const_iterator { + friend class OsiCuts; + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef OsiCut* value_type; + typedef size_t difference_type; + typedef OsiCut ** pointer; + typedef OsiCut *& reference; + + public: + const_iterator(const OsiCuts& cuts); + const_iterator(const const_iterator & src); + const_iterator & operator=( const const_iterator& rhs); + ~const_iterator (); + const OsiCut* operator*() const { return cutP_; } + + const_iterator operator++(); + + const_iterator operator++(int) + { + const_iterator temp = *this; + ++*this; + return temp; + } + + bool operator==(const const_iterator& it) const { + return (colCutIndex_+rowCutIndex_)==(it.colCutIndex_+it.rowCutIndex_); + } + + bool operator!=(const const_iterator& it) const { + return !((*this)==it); + } + + bool operator<(const const_iterator& it) const { + return (colCutIndex_+rowCutIndex_)<(it.colCutIndex_+it.rowCutIndex_); + } + private: + inline const_iterator(); + // *THINK* : how to inline these without sticking the code here (ugly...) + const_iterator begin(); + const_iterator end(); + const OsiCuts * cutsPtr_; + int rowCutIndex_; + int colCutIndex_; + const OsiCut * cutP_; + }; + //@} + + //------------------------------------------------------------------- + // + // Cuts class definition begins here: + // + //------------------------------------------------------------------- + + /** \name Inserting a cut into collection */ + //@{ + /** \brief Insert a row cut */ + inline void insert( const OsiRowCut & rc ); + /** \brief Insert a row cut unless it is a duplicate - cut may get sorted. + Duplicate is defined as CoinAbsFltEq says same*/ + void insertIfNotDuplicate( OsiRowCut & rc , CoinAbsFltEq treatAsSame=CoinAbsFltEq(1.0e-12) ); + /** \brief Insert a row cut unless it is a duplicate - cut may get sorted. + Duplicate is defined as CoinRelFltEq says same*/ + void insertIfNotDuplicate( OsiRowCut & rc , CoinRelFltEq treatAsSame ); + /** \brief Insert a column cut */ + inline void insert( const OsiColCut & cc ); + + /** \brief Insert a row cut. + + The OsiCuts object takes control of the cut object. + On return, \c rcPtr is NULL. + */ + inline void insert( OsiRowCut * & rcPtr ); + /** \brief Insert a column cut. + + The OsiCuts object takes control of the cut object. + On return \c ccPtr is NULL. + */ + inline void insert( OsiColCut * & ccPtr ); +#if 0 + inline void insert( OsiCut * & cPtr ); +#endif + + /** \brief Insert a set of cuts */ + inline void insert(const OsiCuts & cs); + + //@} + + /**@name Number of cuts in collection */ + //@{ + /// Number of row cuts in collection + inline int sizeRowCuts() const; + /// Number of column cuts in collection + inline int sizeColCuts() const; + /// Number of cuts in collection + inline int sizeCuts() const; + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + inline void printCuts() const; + //@} + + /**@name Get a cut from collection */ + //@{ + /// Get pointer to i'th row cut + inline OsiRowCut * rowCutPtr(int i); + /// Get const pointer to i'th row cut + inline const OsiRowCut * rowCutPtr(int i) const; + /// Get pointer to i'th column cut + inline OsiColCut * colCutPtr(int i); + /// Get const pointer to i'th column cut + inline const OsiColCut * colCutPtr(int i) const; + + /// Get reference to i'th row cut + inline OsiRowCut & rowCut(int i); + /// Get const reference to i'th row cut + inline const OsiRowCut & rowCut(int i) const; + /// Get reference to i'th column cut + inline OsiColCut & colCut(int i); + /// Get const reference to i'th column cut + inline const OsiColCut & colCut(int i) const; + + /// Get const pointer to the most effective cut + inline const OsiCut * mostEffectiveCutPtr() const; + /// Get pointer to the most effective cut + inline OsiCut * mostEffectiveCutPtr(); + //@} + + /**@name Deleting cut from collection */ + //@{ + /// Remove i'th row cut from collection + inline void eraseRowCut(int i); + /// Remove i'th column cut from collection + inline void eraseColCut(int i); + /// Get pointer to i'th row cut and remove ptr from collection + inline OsiRowCut * rowCutPtrAndZap(int i); + /*! \brief Clear all row cuts without deleting them + + Handy in case one wants to use CGL without managing cuts in one of + the OSI containers. Client is ultimately responsible for deleting the + data structures holding the row cuts. + */ + inline void dumpCuts() ; + /*! \brief Selective delete and clear for row cuts. + + Deletes the cuts specified in \p to_erase then clears remaining cuts + without deleting them. A hybrid of eraseRowCut(int) and dumpCuts(). + Client is ultimately responsible for deleting the data structures + for row cuts not specified in \p to_erase. + */ + inline void eraseAndDumpCuts(const std::vector<int> to_erase) ; + //@} + + /**@name Sorting collection */ + //@{ + /// Cuts with greatest effectiveness are first. + inline void sort(); + //@} + + + /**@name Iterators + Example of using an iterator to sum effectiveness + of all cuts in the collection. + <pre> + double sumEff=0.0; + for ( OsiCuts::iterator it=cuts.begin(); it!=cuts.end(); ++it ) + sumEff+= (*it)->effectiveness(); + </pre> + */ + //@{ + /// Get iterator to beginning of collection + inline iterator begin() { iterator it(*this); it.begin(); return it; } + /// Get const iterator to beginning of collection + inline const_iterator begin() const { const_iterator it(*this); it.begin(); return it; } + /// Get iterator to end of collection + inline iterator end() { iterator it(*this); it.end(); return it; } + /// Get const iterator to end of collection + inline const_iterator end() const { const_iterator it(*this); it.end(); return it; } + //@} + + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + OsiCuts (); + + /// Copy constructor + OsiCuts ( const OsiCuts &); + + /// Assignment operator + OsiCuts & operator=( const OsiCuts& rhs); + + /// Destructor + virtual ~OsiCuts (); + //@} + +private: + //*@name Function operator for sorting cuts by efectiveness */ + //@{ + class OsiCutCompare + { + public: + /// Function for sorting cuts by effectiveness + inline bool operator()(const OsiCut * c1P,const OsiCut * c2P) + { return c1P->effectiveness() > c2P->effectiveness(); } + }; + //@} + + /**@name Private methods */ + //@{ + /// Copy internal data + void gutsOfCopy( const OsiCuts & source ); + /// Delete internal data + void gutsOfDestructor(); + //@} + + /**@name Private member data */ + //@{ + /// Vector of row cuts pointers + OsiVectorRowCutPtr rowCutPtrs_; + /// Vector of column cuts pointers + OsiVectorColCutPtr colCutPtrs_; + //@} + +}; + + +//------------------------------------------------------------------- +// insert cuts into collection +//------------------------------------------------------------------- +void OsiCuts::insert( const OsiRowCut & rc ) +{ + OsiRowCut * newCutPtr = rc.clone(); + //assert(dynamic_cast<OsiRowCut*>(newCutPtr) != NULL ); + rowCutPtrs_.push_back(static_cast<OsiRowCut*>(newCutPtr)); +} +void OsiCuts::insert( const OsiColCut & cc ) +{ + OsiColCut * newCutPtr = cc.clone(); + //assert(dynamic_cast<OsiColCut*>(newCutPtr) != NULL ); + colCutPtrs_.push_back(static_cast<OsiColCut*>(newCutPtr)); +} + +void OsiCuts::insert( OsiRowCut* & rcPtr ) +{ + rowCutPtrs_.push_back(rcPtr); + rcPtr = NULL; +} +void OsiCuts::insert( OsiColCut* &ccPtr ) +{ + colCutPtrs_.push_back(ccPtr); + ccPtr = NULL; +} +#if 0 +void OsiCuts::insert( OsiCut* & cPtr ) +{ + OsiRowCut * rcPtr = dynamic_cast<OsiRowCut*>(cPtr); + if ( rcPtr != NULL ) { + insert( rcPtr ); + cPtr = rcPtr; + } + else { + OsiColCut * ccPtr = dynamic_cast<OsiColCut*>(cPtr); + assert( ccPtr != NULL ); + insert( ccPtr ); + cPtr = ccPtr; + } +} +#endif + +// LANNEZ SEBASTIEN added Thu May 25 01:22:51 EDT 2006 +void OsiCuts::insert(const OsiCuts & cs) +{ + for (OsiCuts::const_iterator it = cs.begin (); it != cs.end (); it++) + { + const OsiRowCut * rCut = dynamic_cast <const OsiRowCut * >(*it); + const OsiColCut * cCut = dynamic_cast <const OsiColCut * >(*it); + assert (rCut || cCut); + if (rCut) + insert (*rCut); + else + insert (*cCut); + } +} + +//------------------------------------------------------------------- +// sort +//------------------------------------------------------------------- +void OsiCuts::sort() +{ + std::sort(colCutPtrs_.begin(),colCutPtrs_.end(),OsiCutCompare()); + std::sort(rowCutPtrs_.begin(),rowCutPtrs_.end(),OsiCutCompare()); +} + + +//------------------------------------------------------------------- +// Get number of in collections +//------------------------------------------------------------------- +int OsiCuts::sizeRowCuts() const { + return static_cast<int>(rowCutPtrs_.size()); } +int OsiCuts::sizeColCuts() const { + return static_cast<int>(colCutPtrs_.size()); } +int OsiCuts::sizeCuts() const { + return static_cast<int>(sizeRowCuts()+sizeColCuts()); } + +//---------------------------------------------------------------- +// Get i'th cut from the collection +//---------------------------------------------------------------- +const OsiRowCut * OsiCuts::rowCutPtr(int i) const { return rowCutPtrs_[i]; } +const OsiColCut * OsiCuts::colCutPtr(int i) const { return colCutPtrs_[i]; } +OsiRowCut * OsiCuts::rowCutPtr(int i) { return rowCutPtrs_[i]; } +OsiColCut * OsiCuts::colCutPtr(int i) { return colCutPtrs_[i]; } + +const OsiRowCut & OsiCuts::rowCut(int i) const { return *rowCutPtr(i); } +const OsiColCut & OsiCuts::colCut(int i) const { return *colCutPtr(i); } +OsiRowCut & OsiCuts::rowCut(int i) { return *rowCutPtr(i); } +OsiColCut & OsiCuts::colCut(int i) { return *colCutPtr(i); } + +//---------------------------------------------------------------- +// Get most effective cut from collection +//---------------------------------------------------------------- +const OsiCut * OsiCuts::mostEffectiveCutPtr() const +{ + const_iterator b=begin(); + const_iterator e=end(); + return *(std::min_element(b,e,OsiCutCompare())); +} +OsiCut * OsiCuts::mostEffectiveCutPtr() +{ + iterator b=begin(); + iterator e=end(); + //return *(std::min_element(b,e,OsiCutCompare())); + OsiCut * retVal = NULL; + double maxEff = COIN_DBL_MIN; + for ( OsiCuts::iterator it=b; it!=e; ++it ) { + if (maxEff < (*it)->effectiveness() ) { + maxEff = (*it)->effectiveness(); + retVal = *it; + } + } + return retVal; +} + +//---------------------------------------------------------------- +// Print all cuts +//---------------------------------------------------------------- +void +OsiCuts::printCuts() const +{ + // do all column cuts first + int i; + int numberColCuts=sizeColCuts(); + for (i=0;i<numberColCuts;i++) { + const OsiColCut * cut = colCutPtr(i); + cut->print(); + } + int numberRowCuts=sizeRowCuts(); + for (i=0;i<numberRowCuts;i++) { + const OsiRowCut * cut = rowCutPtr(i); + cut->print(); + } +} + +//---------------------------------------------------------------- +// Erase i'th cut from the collection +//---------------------------------------------------------------- +void OsiCuts::eraseRowCut(int i) +{ + delete rowCutPtrs_[i]; + rowCutPtrs_.erase( rowCutPtrs_.begin()+i ); +} +void OsiCuts::eraseColCut(int i) +{ + delete colCutPtrs_[i]; + colCutPtrs_.erase( colCutPtrs_.begin()+i ); +} +/// Get pointer to i'th row cut and remove ptr from collection +OsiRowCut * +OsiCuts::rowCutPtrAndZap(int i) +{ + OsiRowCut * cut = rowCutPtrs_[i]; + rowCutPtrs_[i]=NULL; + rowCutPtrs_.erase( rowCutPtrs_.begin()+i ); + return cut; +} +void OsiCuts::dumpCuts() +{ + rowCutPtrs_.clear() ; +} +void OsiCuts::eraseAndDumpCuts(const std::vector<int> to_erase) +{ + for (unsigned i=0; i<to_erase.size(); i++) { + delete rowCutPtrs_[to_erase[i]]; + } + rowCutPtrs_.clear(); +} + + +#endif diff --git a/thirdparty/linux/include/coin/OsiPresolve.hpp b/thirdparty/linux/include/coin/OsiPresolve.hpp new file mode 100644 index 0000000..9ec3d2a --- /dev/null +++ b/thirdparty/linux/include/coin/OsiPresolve.hpp @@ -0,0 +1,252 @@ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiPresolve_H +#define OsiPresolve_H +#include "OsiSolverInterface.hpp" + +class CoinPresolveAction; +#include "CoinPresolveMatrix.hpp" + + +/*! \class OsiPresolve + \brief OSI interface to COIN problem simplification capabilities + + COIN provides a number of classes which implement problem simplification + algorithms (CoinPresolveAction, CoinPrePostsolveMatrix, and derived + classes). The model of operation is as follows: + <ul> + <li> + Create a copy of the original problem. + </li> + <li> + Subject the copy to a series of transformations (the <i>presolve</i> + methods) to produce a presolved model. Each transformation is also + expected to provide a method to reverse the transformation (the + <i>postsolve</i> method). The postsolve methods are collected in a + linked list; the postsolve method for the final presolve transformation + is at the head of the list. + </li> + <li> + Hand the presolved problem to the solver for optimization. + </li> + <li> + Apply the collected postsolve methods to the presolved problem + and solution, restating the solution in terms of the original problem. + </li> + </ul> + + The COIN presolve algorithms are unaware of OSI. The OsiPresolve class takes + care of the interface. Given an OsiSolverInterface \c origModel, it will take + care of creating a clone properly loaded with the presolved problem and ready + for optimization. After optimization, it will apply postsolve + transformations and load the result back into \c origModel. + + Assuming a problem has been loaded into an + \c OsiSolverInterface \c origModel, a bare-bones application looks like this: + \code + OsiPresolve pinfo ; + OsiSolverInterface *presolvedModel ; + // Return an OsiSolverInterface loaded with the presolved problem. + presolvedModel = pinfo.presolvedModel(*origModel,1.0e-8,false,numberPasses) ; + presolvedModel->initialSolve() ; + // Restate the solution and load it back into origModel. + pinfo.postsolve(true) ; + delete presolvedModel ; + \endcode +*/ + + + +class OsiPresolve { +public: + /// Default constructor (empty object) + OsiPresolve(); + + /// Virtual destructor + virtual ~OsiPresolve(); + + /*! \brief Create a new OsiSolverInterface loaded with the presolved problem. + + This method implements the first two steps described in the class + documentation. It clones \c origModel and applies presolve + transformations, storing the resulting list of postsolve + transformations. It returns a pointer to a new OsiSolverInterface loaded + with the presolved problem, or NULL if the problem is infeasible or + unbounded. If \c keepIntegers is true then bounds may be tightened in + the original. Bounds will be moved by up to \c feasibilityTolerance to + try and stay feasible. When \c doStatus is true, the current solution will + be transformed to match the presolved model. + + This should be paired with postsolve(). It is up to the client to + destroy the returned OsiSolverInterface, <i>after</i> calling postsolve(). + + This method is virtual. Override this method if you need to customize + the steps of creating a model to apply presolve transformations. + + In some sense, a wrapper for presolve(CoinPresolveMatrix*). + */ + virtual OsiSolverInterface *presolvedModel(OsiSolverInterface & origModel, + double feasibilityTolerance=0.0, + bool keepIntegers=true, + int numberPasses=5, + const char * prohibited=NULL, + bool doStatus=true, + const char * rowProhibited=NULL); + + /*! \brief Restate the solution to the presolved problem in terms of the + original problem and load it into the original model. + + postsolve() restates the solution in terms of the original problem and + updates the original OsiSolverInterface supplied to presolvedModel(). If + the problem has not been solved to optimality, there are no guarantees. + If you are using an algorithm like simplex that has a concept of a basic + solution, then set updateStatus + + The advantage of going back to the original problem is that it + will be exactly as it was, <i>i.e.</i>, 0.0 will not become 1.0e-19. + + Note that if you modified the original problem after presolving, then you + must ``undo'' these modifications before calling postsolve(). + + In some sense, a wrapper for postsolve(CoinPostsolveMatrix&). + */ + virtual void postsolve(bool updateStatus=true); + + /*! \brief Return a pointer to the presolved model. */ + OsiSolverInterface * model() const; + + /// Return a pointer to the original model + OsiSolverInterface * originalModel() const; + + /// Set the pointer to the original model + void setOriginalModel(OsiSolverInterface *model); + + /// Return a pointer to the original columns + const int * originalColumns() const; + + /// Return a pointer to the original rows + const int * originalRows() const; + + /// Return number of rows in original model + inline int getNumRows() const + { return nrows_;} + + /// Return number of columns in original model + inline int getNumCols() const + { return ncols_;} + + /** "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + */ + inline void setNonLinearValue(double value) + { nonLinearValue_ = value;} + inline double nonLinearValue() const + { return nonLinearValue_;} + /*! \brief Fine control over presolve actions + + Set/clear the following bits to allow or suppress actions: + - 0x01 allow duplicate column processing on integer columns + and dual stuff on integers + - 0x02 switch off actions which can change +1 to something else + (doubleton, tripleton, implied free) + - 0x04 allow transfer of costs from singletons and between integer + variables (when advantageous) + - 0x08 do not allow x+y+z=1 transform + - 0x10 allow actions that don't easily unroll + - 0x20 allow dubious gub element reduction + + GUB element reduction is only partially implemented in CoinPresolve (see + gubrow_action) and willl cause an abort at postsolve. It's not clear + what's meant by `dual stuff on integers'. + -- lh, 110605 -- + */ + inline void setPresolveActions(int action) + { presolveActions_ = (presolveActions_&0xffff0000)|(action&0xffff);} + +private: + /*! Original model (solver interface loaded with the original problem). + + Must not be destroyed until after postsolve(). + */ + OsiSolverInterface * originalModel_; + + /*! Presolved model (solver interface loaded with the presolved problem) + + Must be destroyed by the client (using delete) after postsolve(). + */ + OsiSolverInterface * presolvedModel_; + + /*! "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + One could also allow for cases where sign of coefficient is known. + */ + double nonLinearValue_; + + /// Original column numbers + int * originalColumn_; + + /// Original row numbers + int * originalRow_; + + /// The list of transformations applied. + const CoinPresolveAction *paction_; + + /*! \brief Number of columns in original model. + + The problem will expand back to its former size as postsolve + transformations are applied. It is efficient to allocate data structures + for the final size of the problem rather than expand them as needed. + */ + int ncols_; + + /*! \brief Number of rows in original model. */ + int nrows_; + + /*! \brief Number of nonzero matrix coefficients in the original model. */ + CoinBigIndex nelems_; + + /** Whether we want to skip dual part of presolve etc. + 1 bit allows duplicate column processing on integer columns + and dual stuff on integers + 4 transfers costs to integer variables + */ + int presolveActions_; + /// Number of major passes + int numberPasses_; + +protected: + /*! \brief Apply presolve transformations to the problem. + + Handles the core activity of applying presolve transformations. + + If you want to apply the individual presolve routines differently, or + perhaps add your own to the mix, define a derived class and override + this method + */ + virtual const CoinPresolveAction *presolve(CoinPresolveMatrix *prob); + + /*! \brief Reverse presolve transformations to recover the solution + to the original problem. + + Handles the core activity of applying postsolve transformations. + + Postsolving is pretty generic; just apply the transformations in reverse + order. You will probably only be interested in overriding this method if + you want to add code to test for consistency while debugging new presolve + techniques. + */ + virtual void postsolve(CoinPostsolveMatrix &prob); + + /*! \brief Destroys queued postsolve actions. + + <i>E.g.</i>, when presolve() determines the problem is infeasible, so that + it will not be necessary to actually solve the presolved problem and + convert the result back to the original problem. + */ + void gutsOfDestroy(); +}; +#endif diff --git a/thirdparty/linux/include/coin/OsiRowCut.hpp b/thirdparty/linux/include/coin/OsiRowCut.hpp new file mode 100644 index 0000000..1332802 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiRowCut.hpp @@ -0,0 +1,331 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiRowCut_H +#define OsiRowCut_H + +#include "CoinPackedVector.hpp" + +#include "OsiCollections.hpp" +#include "OsiCut.hpp" + +//#define OSI_INLINE_ROWCUT_METHODS +#ifdef OSI_INLINE_ROWCUT_METHODS +#define OsiRowCut_inline inline +#else +#define OsiRowCut_inline +#endif + +/** Row Cut Class + +A row cut has: + <ul> + <li>a lower bound<br> + <li>an upper bound<br> + <li>a vector of row elements + </ul> +*/ +class OsiRowCut : public OsiCut { + friend void OsiRowCutUnitTest(const OsiSolverInterface * baseSiP, + const std::string & mpsDir); + +public: + + /**@name Row bounds */ + //@{ + /// Get lower bound + OsiRowCut_inline double lb() const; + /// Set lower bound + OsiRowCut_inline void setLb(double lb); + /// Get upper bound + OsiRowCut_inline double ub() const; + /// Set upper bound + OsiRowCut_inline void setUb(double ub); + //@} + + /**@name Row rhs, sense, range */ + //@{ + /// Get sense ('E', 'G', 'L', 'N', 'R') + char sense() const; + /// Get right-hand side + double rhs() const; + /// Get range (ub - lb for 'R' rows, 0 otherwise) + double range() const; + //@} + + //------------------------------------------------------------------- + /**@name Row elements */ + //@{ + /// Set row elements + OsiRowCut_inline void setRow( + int size, + const int * colIndices, + const double * elements, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /// Set row elements from a packed vector + OsiRowCut_inline void setRow( const CoinPackedVector & v ); + /// Get row elements + OsiRowCut_inline const CoinPackedVector & row() const; + /// Get row elements for changing + OsiRowCut_inline CoinPackedVector & mutableRow() ; + //@} + + /**@name Comparison operators */ + //@{ +#if __GNUC__ != 2 + using OsiCut::operator== ; +#endif + /** equal - true if lower bound, upper bound, row elements, + and OsiCut are equal. + */ + OsiRowCut_inline bool operator==(const OsiRowCut& rhs) const; + +#if __GNUC__ != 2 + using OsiCut::operator!= ; +#endif + /// not equal + OsiRowCut_inline bool operator!=(const OsiRowCut& rhs) const; + //@} + + + //---------------------------------------------------------------- + /**@name Sanity checks on cut */ + //@{ + /** Returns true if the cut is consistent. + This checks to ensure that: + <ul> + <li>The row element vector does not have duplicate indices + <li>The row element vector indices are >= 0 + </ul> + */ + OsiRowCut_inline bool consistent() const; + + /** Returns true if cut is consistent with respect to the solver + interface's model. + This checks to ensure that + <ul> + <li>The row element vector indices are < the number of columns + in the model + </ul> + */ + OsiRowCut_inline bool consistent(const OsiSolverInterface& im) const; + + /** Returns true if the row cut itself is infeasible and cannot be satisfied. + This checks whether + <ul> + <li>the lower bound is strictly greater than the + upper bound. + </ul> + */ + OsiRowCut_inline bool infeasible(const OsiSolverInterface &im) const; + /** Returns infeasibility of the cut with respect to solution + passed in i.e. is positive if cuts off that solution. + solution is getNumCols() long.. + */ + virtual double violated(const double * solution) const; + //@} + + /**@name Arithmetic operators. Apply CoinPackedVector methods to the vector */ + //@{ + /// add <code>value</code> to every vector entry + void operator+=(double value) + { row_ += value; } + + /// subtract <code>value</code> from every vector entry + void operator-=(double value) + { row_ -= value; } + + /// multiply every vector entry by <code>value</code> + void operator*=(double value) + { row_ *= value; } + + /// divide every vector entry by <code>value</code> + void operator/=(double value) + { row_ /= value; } + //@} + + /// Allow access row sorting function + void sortIncrIndex() + {row_.sortIncrIndex();} + + /**@name Constructors and destructors */ + //@{ + /// Assignment operator + OsiRowCut & operator=( const OsiRowCut& rhs); + + /// Copy constructor + OsiRowCut ( const OsiRowCut &); + + /// Clone + virtual OsiRowCut * clone() const; + + /// Default Constructor + OsiRowCut (); + + /** \brief Ownership Constructor + + This constructor assumes ownership of the vectors passed as parameters + for indices and elements. \p colIndices and \p elements will be NULL + on return. + */ + OsiRowCut(double cutlb, double cutub, + int capacity, int size, + int *&colIndices, double *&elements); + + /// Destructor + virtual ~OsiRowCut (); + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + virtual void print() const ; + //@} + +private: + + + /**@name Private member data */ + //@{ + /// Row elements + CoinPackedVector row_; + /// Row lower bound + double lb_; + /// Row upper bound + double ub_; + //@} +}; + +#ifdef OSI_INLINE_ROWCUT_METHODS + +//------------------------------------------------------------------- +// Set/Get lower & upper bounds +//------------------------------------------------------------------- +double OsiRowCut::lb() const { return lb_; } +void OsiRowCut::setLb(double lb) { lb_ = lb; } +double OsiRowCut::ub() const { return ub_; } +void OsiRowCut::setUb(double ub) { ub_ = ub; } + +//------------------------------------------------------------------- +// Set row elements +//------------------------------------------------------------------- +void OsiRowCut::setRow(int size, + const int * colIndices, const double * elements) +{ + row_.setVector(size,colIndices,elements); +} +void OsiRowCut::setRow( const CoinPackedVector & v ) +{ + row_ = v; +} + +//------------------------------------------------------------------- +// Get the row +//------------------------------------------------------------------- +const CoinPackedVector & OsiRowCut::row() const +{ + return row_; +} + +//------------------------------------------------------------------- +// Get the row so we can change +//------------------------------------------------------------------- +CoinPackedVector & OsiRowCut::mutableRow() +{ + return row_; +} + +//---------------------------------------------------------------- +// == operator +//------------------------------------------------------------------- +bool +OsiRowCut::operator==(const OsiRowCut& rhs) const +{ + if ( this->OsiCut::operator!=(rhs) ) return false; + if ( row() != rhs.row() ) return false; + if ( lb() != rhs.lb() ) return false; + if ( ub() != rhs.ub() ) return false; + return true; +} +bool +OsiRowCut::operator!=(const OsiRowCut& rhs) const +{ + return !( (*this)==rhs ); +} + + +//---------------------------------------------------------------- +// consistent & infeasible +//------------------------------------------------------------------- +bool OsiRowCut::consistent() const +{ + const CoinPackedVector & r=row(); + r.duplicateIndex("consistent", "OsiRowCut"); + if ( r.getMinIndex() < 0 ) return false; + return true; +} +bool OsiRowCut::consistent(const OsiSolverInterface& im) const +{ + const CoinPackedVector & r=row(); + if ( r.getMaxIndex() >= im.getNumCols() ) return false; + + return true; +} +bool OsiRowCut::infeasible(const OsiSolverInterface &im) const +{ + if ( lb() > ub() ) return true; + + return false; +} + +#endif + +/** Row Cut Class which refers back to row which created it. + It may be useful to strengthen a row rather than add a cut. To do this + we need to know which row is strengthened. This trivial extension + to OsiRowCut does that. + +*/ +class OsiRowCut2 : public OsiRowCut { + +public: + + /**@name Which row */ + //@{ + /// Get row + inline int whichRow() const + { return whichRow_;} + /// Set row + inline void setWhichRow(int row) + { whichRow_=row;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Assignment operator + OsiRowCut2 & operator=( const OsiRowCut2& rhs); + + /// Copy constructor + OsiRowCut2 ( const OsiRowCut2 &); + + /// Clone + virtual OsiRowCut * clone() const; + + /// Default Constructor + OsiRowCut2 (int row=-1); + + /// Destructor + virtual ~OsiRowCut2 (); + //@} + +private: + + + /**@name Private member data */ + //@{ + /// Which row + int whichRow_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/OsiRowCutDebugger.hpp b/thirdparty/linux/include/coin/OsiRowCutDebugger.hpp new file mode 100644 index 0000000..548e8e3 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiRowCutDebugger.hpp @@ -0,0 +1,187 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiRowCutDebugger_H +#define OsiRowCutDebugger_H + +/*! \file OsiRowCutDebugger.hpp + + \brief Provides a facility to validate cut constraints to ensure that they + do not cut off a given solution. +*/ + +#include <string> + +#include "OsiCuts.hpp" +#include "OsiSolverInterface.hpp" + +/*! \brief Validate cuts against a known solution + + OsiRowCutDebugger provides a facility for validating cuts against a known + solution for a problem. The debugger knows an optimal solution for many of + the miplib3 problems. Check the source for + #activate(const OsiSolverInterface&,const char*) + in OsiRowCutDebugger.cpp for the full set of known problems. + + A full solution vector can be supplied as a parameter with + (#activate(const OsiSolverInterface&,const double*,bool)). + Only the integer values need to be valid. + The default behaviour is to solve an lp relaxation with the integer + variables fixed to the specified values and use the optimal solution to fill + in the continuous variables in the solution. + The debugger can be instructed to preserve the continuous variables (useful + when debugging solvers where the linear relaxation doesn't capture all the + constraints). + + Note that the solution must match the problem held in the solver interface. + If you want to use the row cut debugger on a problem after applying presolve + transformations, your solution must match the presolved problem. (But see + #redoSolution().) +*/ +class OsiRowCutDebugger { + friend void OsiRowCutDebuggerUnitTest(const OsiSolverInterface * siP, + const std::string & mpsDir); + +public: + + /*! @name Validate Row Cuts + + Check that the specified cuts do not cut off the known solution. + */ + //@{ + /*! \brief Check that the set of cuts does not cut off the solution known + to the debugger. + + Check if any generated cuts cut off the solution known to the debugger! + If so then print offending cuts. Return the number of invalid cuts. + */ + virtual int validateCuts(const OsiCuts & cs, int first, int last) const; + + /*! \brief Check that the cut does not cut off the solution known to the + debugger. + + Return true if cut is invalid + */ + virtual bool invalidCut(const OsiRowCut & rowcut) const; + + /*! \brief Returns true if the solution held in the solver is compatible + with the known solution. + + More specifically, returns true if the known solution satisfies the column + bounds held in the solver. + */ + bool onOptimalPath(const OsiSolverInterface &si) const; + //@} + + /*! @name Activate the Debugger + + The debugger is considered to be active when it holds a known solution. + */ + //@{ + /*! \brief Activate a debugger using the name of a problem. + + The debugger knows an optimal solution for most of miplib3. Check the + source code for the full list. Returns true if the debugger is + successfully activated. + */ + bool activate(const OsiSolverInterface &si, const char *model) ; + + /*! \brief Activate a debugger using a full solution array. + + The solution must have one entry for every variable, but only the entries + for integer values are used. By default the debugger will solve an lp + relaxation with the integer variables fixed and fill in values for the + continuous variables from this solution. If the debugger should preserve + the given values for the continuous variables, set \p keepContinuous to + \c true. + + Returns true if debugger activates successfully. + */ + bool activate(const OsiSolverInterface &si, const double* solution, + bool keepContinuous = false) ; + + /// Returns true if the debugger is active + bool active() const; + //@} + + /*! @name Query or Manipulate the Known Solution */ + //@{ + /// Return the known solution + inline const double * optimalSolution() const + { return knownSolution_;} + + /// Return the number of columns in the known solution + inline int numberColumns() const { return (numberColumns_) ; } + + /// Return the value of the objective for the known solution + inline double optimalValue() const { return knownValue_;} + + /*! \brief Edit the known solution to reflect column changes + + Given a translation array \p originalColumns[numberColumns] which can + translate current column indices to original column indices, this method + will edit the solution held in the debugger so that it matches the current + set of columns. + + Useful when the original problem is preprocessed prior to cut generation. + The debugger does keep a record of the changes. + */ + void redoSolution(int numberColumns, const int *originalColumns); + + /// Print optimal solution (returns -1 bad debug, 0 on optimal, 1 not) + int printOptimalSolution(const OsiSolverInterface & si) const; + //@} + + /**@name Constructors and Destructors */ + //@{ + /// Default constructor - no checking + OsiRowCutDebugger (); + + /*! \brief Constructor with name of model. + + See #activate(const OsiSolverInterface&,const char*). + */ + OsiRowCutDebugger(const OsiSolverInterface &si, const char *model) ; + + /*! \brief Constructor with full solution. + + See #activate(const OsiSolverInterface&,const double*,bool). + */ + OsiRowCutDebugger(const OsiSolverInterface &si, const double *solution, + bool enforceOptimality = false) ; + + /// Copy constructor + OsiRowCutDebugger(const OsiRowCutDebugger &); + + /// Assignment operator + OsiRowCutDebugger& operator=(const OsiRowCutDebugger& rhs); + + /// Destructor + virtual ~OsiRowCutDebugger (); + //@} + +private: + + // Private member data + + /**@name Private member data */ + //@{ + /// Value of known solution + double knownValue_; + + /*! \brief Number of columns in known solution + + This must match the number of columns reported by the solver. + */ + int numberColumns_; + + /// array specifying integer variables + bool * integerVariable_; + + /// array specifying known solution + double * knownSolution_; + //@} +}; + +#endif diff --git a/thirdparty/linux/include/coin/OsiSolverBranch.hpp b/thirdparty/linux/include/coin/OsiSolverBranch.hpp new file mode 100644 index 0000000..98c4343 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiSolverBranch.hpp @@ -0,0 +1,152 @@ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiSolverBranch_H +#define OsiSolverBranch_H + +class OsiSolverInterface; +#include "CoinWarmStartBasis.hpp" + +//############################################################################# + +/** Solver Branch Class + + This provides information on a branch as a set of tighter bounds on both ways +*/ + +class OsiSolverBranch { + +public: + ///@name Add and Get methods + //@{ + /// Add a simple branch (i.e. first sets ub of floor(value), second lb of ceil(value)) + void addBranch(int iColumn, double value); + + /// Add bounds - way =-1 is first , +1 is second + void addBranch(int way,int numberTighterLower, const int * whichLower, const double * newLower, + int numberTighterUpper, const int * whichUpper, const double * newUpper); + /// Add bounds - way =-1 is first , +1 is second + void addBranch(int way,int numberColumns,const double * oldLower, const double * newLower, + const double * oldUpper, const double * newUpper); + + /// Apply bounds + void applyBounds(OsiSolverInterface & solver,int way) const; + /// Returns true if current solution satsifies one side of branch + bool feasibleOneWay(const OsiSolverInterface & solver) const; + /// Starts + inline const int * starts() const + { return start_;} + /// Which variables + inline const int * which() const + { return indices_;} + /// Bounds + inline const double * bounds() const + { return bound_;} + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + OsiSolverBranch(); + + /// Copy constructor + OsiSolverBranch(const OsiSolverBranch & rhs); + + /// Assignment operator + OsiSolverBranch & operator=(const OsiSolverBranch & rhs); + + /// Destructor + ~OsiSolverBranch (); + + //@} + +private: + ///@name Private member data + //@{ + /// Start of lower first, upper first, lower second, upper second + int start_[5]; + /// Column numbers (if >= numberColumns treat as rows) + int * indices_; + /// New bounds + double * bound_; + //@} +}; +//############################################################################# + +/** Solver Result Class + + This provides information on a result as a set of tighter bounds on both ways +*/ + +class OsiSolverResult { + +public: + ///@name Add and Get methods + //@{ + /// Create result + void createResult(const OsiSolverInterface & solver,const double * lowerBefore, + const double * upperBefore); + + /// Restore result + void restoreResult(OsiSolverInterface & solver) const; + + /// Get basis + inline const CoinWarmStartBasis & basis() const + { return basis_;} + + /// Objective value (as minimization) + inline double objectiveValue() const + { return objectiveValue_;} + + /// Primal solution + inline const double * primalSolution() const + { return primalSolution_;} + + /// Dual solution + inline const double * dualSolution() const + { return dualSolution_;} + + /// Extra fixed + inline const OsiSolverBranch & fixed() const + { return fixed_;} + //@} + + + ///@name Constructors and destructors + //@{ + /// Default Constructor + OsiSolverResult(); + + /// Constructor from solver + OsiSolverResult(const OsiSolverInterface & solver,const double * lowerBefore, + const double * upperBefore); + + /// Copy constructor + OsiSolverResult(const OsiSolverResult & rhs); + + /// Assignment operator + OsiSolverResult & operator=(const OsiSolverResult & rhs); + + /// Destructor + ~OsiSolverResult (); + + //@} + +private: + ///@name Private member data + //@{ + /// Value of objective (if >= OsiSolverInterface::getInfinity() then infeasible) + double objectiveValue_; + /// Warm start information + CoinWarmStartBasis basis_; + /// Primal solution (numberColumns) + double * primalSolution_; + /// Dual solution (numberRows) + double * dualSolution_; + /// Which extra variables have been fixed (only way==-1 counts) + OsiSolverBranch fixed_; + //@} +}; +#endif diff --git a/thirdparty/linux/include/coin/OsiSolverInterface.hpp b/thirdparty/linux/include/coin/OsiSolverInterface.hpp new file mode 100644 index 0000000..a581961 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiSolverInterface.hpp @@ -0,0 +1,2143 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiSolverInterface_H +#define OsiSolverInterface_H + +#include <cstdlib> +#include <string> +#include <vector> + +#include "CoinTypes.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinPackedVectorBase.hpp" +#include "CoinPackedMatrix.hpp" +#include "CoinWarmStart.hpp" +#include "CoinFinite.hpp" +#include "CoinError.hpp" + +#include "OsiCollections.hpp" +#include "OsiSolverParameters.hpp" + +class CoinSnapshot; +class CoinLpIO; +class CoinMpsIO; + +class OsiCuts; +class OsiAuxInfo; +class OsiRowCut; +class OsiRowCutDebugger; +class CoinSet; +class CoinBuild; +class CoinModel; +class OsiSolverBranch; +class OsiSolverResult; +class OsiObject; + + +//############################################################################# + +/*! \brief Abstract Base Class for describing an interface to a solver. + + Many OsiSolverInterface query methods return a const pointer to the + requested read-only data. If the model data is changed or the solver + is called, these pointers may no longer be valid and should be + refreshed by invoking the member function to obtain an updated copy + of the pointer. + For example: + \code + OsiSolverInterface solverInterfacePtr ; + const double * ruBnds = solverInterfacePtr->getRowUpper(); + solverInterfacePtr->applyCuts(someSetOfCuts); + // ruBnds is no longer a valid pointer and must be refreshed + ruBnds = solverInterfacePtr->getRowUpper(); + \endcode + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. +*/ + +class OsiSolverInterface { + friend void OsiSolverInterfaceCommonUnitTest( + const OsiSolverInterface* emptySi, + const std::string & mpsDir, + const std::string & netlibDir); + friend void OsiSolverInterfaceMpsUnitTest( + const std::vector<OsiSolverInterface*> & vecSiP, + const std::string & mpsDir); + +public: + + /// Internal class for obtaining status from the applyCuts method + class ApplyCutsReturnCode { + friend class OsiSolverInterface; + friend class OsiClpSolverInterface; + friend class OsiGrbSolverInterface; + + public: + ///@name Constructors and desctructors + //@{ + /// Default constructor + ApplyCutsReturnCode(): + intInconsistent_(0), + extInconsistent_(0), + infeasible_(0), + ineffective_(0), + applied_(0) {} + /// Copy constructor + ApplyCutsReturnCode(const ApplyCutsReturnCode & rhs): + intInconsistent_(rhs.intInconsistent_), + extInconsistent_(rhs.extInconsistent_), + infeasible_(rhs.infeasible_), + ineffective_(rhs.ineffective_), + applied_(rhs.applied_) {} + /// Assignment operator + ApplyCutsReturnCode & operator=(const ApplyCutsReturnCode& rhs) + { + if (this != &rhs) { + intInconsistent_ = rhs.intInconsistent_; + extInconsistent_ = rhs.extInconsistent_; + infeasible_ = rhs.infeasible_; + ineffective_ = rhs.ineffective_; + applied_ = rhs.applied_; + } + return *this; + } + /// Destructor + ~ApplyCutsReturnCode(){} + //@} + + /**@name Accessing return code attributes */ + //@{ + /// Number of logically inconsistent cuts + inline int getNumInconsistent() const + {return intInconsistent_;} + /// Number of cuts inconsistent with the current model + inline int getNumInconsistentWrtIntegerModel() const + {return extInconsistent_;} + /// Number of cuts that cause obvious infeasibility + inline int getNumInfeasible() const + {return infeasible_;} + /// Number of redundant or ineffective cuts + inline int getNumIneffective() const + {return ineffective_;} + /// Number of cuts applied + inline int getNumApplied() const + {return applied_;} + //@} + + private: + /**@name Private methods */ + //@{ + /// Increment logically inconsistent cut counter + inline void incrementInternallyInconsistent(){intInconsistent_++;} + /// Increment model-inconsistent counter + inline void incrementExternallyInconsistent(){extInconsistent_++;} + /// Increment infeasible cut counter + inline void incrementInfeasible(){infeasible_++;} + /// Increment ineffective cut counter + inline void incrementIneffective(){ineffective_++;} + /// Increment applied cut counter + inline void incrementApplied(){applied_++;} + //@} + + ///@name Private member data + //@{ + /// Counter for logically inconsistent cuts + int intInconsistent_; + /// Counter for model-inconsistent cuts + int extInconsistent_; + /// Counter for infeasible cuts + int infeasible_; + /// Counter for ineffective cuts + int ineffective_; + /// Counter for applied cuts + int applied_; + //@} + }; + + //--------------------------------------------------------------------------- + + ///@name Solve methods + //@{ + /// Solve initial LP relaxation + virtual void initialSolve() = 0; + + /*! \brief Resolve an LP relaxation after problem modification + + Note the `re-' in `resolve'. initialSolve() should be used to solve the + problem for the first time. + */ + virtual void resolve() = 0; + + /// Invoke solver's built-in enumeration algorithm + virtual void branchAndBound() = 0; + +#ifdef CBC_NEXT_VERSION + /* + Would it make sense to collect all of these routines in a `MIP Helper' + section? It'd make it easier for users and implementors to find them. + */ + /** + Solve 2**N (N==depth) problems and return solutions and bases. + There are N branches each of which changes bounds on both sides + as given by branch. The user should provide an array of (empty) + results which will be filled in. See OsiSolveResult for more details + (in OsiSolveBranch.?pp) but it will include a basis and primal solution. + + The order of results is left to right at feasible leaf nodes so first one + is down, down, ..... + + Returns number of feasible leaves. Also sets number of solves done and number + of iterations. + + This is provided so a solver can do faster. + + If forceBranch true then branch done even if satisfied + */ + virtual int solveBranches(int depth,const OsiSolverBranch * branch, + OsiSolverResult * result, + int & numberSolves, int & numberIterations, + bool forceBranch=false); +#endif + //@} + + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. When a set method returns false, the original value (if + any) should be unchanged. There can be various reasons for failure: the + given parameter is not applicable for the solver (e.g., refactorization + frequency for the volume algorithm), the parameter is not yet + implemented for the solver or simply the value of the parameter is out + of the range the solver accepts. If a parameter setting call returns + false check the details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + + \note + There is a default implementation of the set/get + methods, namely to store/retrieve the given value using an array in the + base class. A specific solver implementation can use this feature, for + example, to store parameters that should be used later on. Implementors + of a solver interface should overload these functions to provide the + proper interface to and accurately reflect the capabilities of a + specific solver. + + The format for hints is slightly different in that a boolean specifies + the sense of the hint and an enum specifies the strength of the hint. + Hints should be initialised when a solver is instantiated. + (See OsiSolverParameters.hpp for defined hint parameters and strength.) + When specifying the sense of the hint, a value of true means to work with + the hint, false to work against it. For example, + <ul> + <li> \code setHintParam(OsiDoScale,true,OsiHintTry) \endcode + is a mild suggestion to the solver to scale the constraint + system. + <li> \code setHintParam(OsiDoScale,false,OsiForceDo) \endcode + tells the solver to disable scaling, or throw an exception if + it cannot comply. + </ul> + As another example, a solver interface could use the value and strength + of the \c OsiDoReducePrint hint to adjust the amount of information + printed by the interface and/or solver. The extent to which a solver + obeys hints is left to the solver. The value and strength returned by + \c getHintParam will match the most recent call to \c setHintParam, + and will not necessarily reflect the solver's ability to comply with the + hint. If the hint strength is \c OsiForceDo, the solver is required to + throw an exception if it cannot perform the specified action. + + \note + As with the other set/get methods, there is a default implementation + which maintains arrays in the base class for hint sense and strength. + The default implementation does not store the \c otherInformation + pointer, and always throws an exception for strength \c OsiForceDo. + Implementors of a solver interface should override these functions to + provide the proper interface to and accurately reflect the capabilities + of a specific solver. + */ + //@{ + //! Set an integer parameter + virtual bool setIntParam(OsiIntParam key, int value) { + if (key == OsiLastIntParam) return (false) ; + intParam_[key] = value; + return true; + } + //! Set a double parameter + virtual bool setDblParam(OsiDblParam key, double value) { + if (key == OsiLastDblParam) return (false) ; + dblParam_[key] = value; + return true; + } + //! Set a string parameter + virtual bool setStrParam(OsiStrParam key, const std::string & value) { + if (key == OsiLastStrParam) return (false) ; + strParam_[key] = value; + return true; + } + /*! \brief Set a hint parameter + + The \c otherInformation parameter can be used to pass in an arbitrary + block of information which is interpreted by the OSI and the underlying + solver. Users are cautioned that this hook is solver-specific. + + Implementors: + The default implementation completely ignores \c otherInformation and + always throws an exception for OsiForceDo. This is almost certainly not + the behaviour you want; you really should override this method. + */ + virtual bool setHintParam(OsiHintParam key, bool yesNo=true, + OsiHintStrength strength=OsiHintTry, + void * /*otherInformation*/ = NULL) { + if (key==OsiLastHintParam) + return false; + hintParam_[key] = yesNo; + hintStrength_[key] = strength; + if (strength == OsiForceDo) + throw CoinError("OsiForceDo illegal", + "setHintParam", "OsiSolverInterface"); + return true; + } + //! Get an integer parameter + virtual bool getIntParam(OsiIntParam key, int& value) const { + if (key == OsiLastIntParam) return (false) ; + value = intParam_[key]; + return true; + } + //! Get a double parameter + virtual bool getDblParam(OsiDblParam key, double& value) const { + if (key == OsiLastDblParam) return (false) ; + value = dblParam_[key]; + return true; + } + //! Get a string parameter + virtual bool getStrParam(OsiStrParam key, std::string& value) const { + if (key == OsiLastStrParam) return (false) ; + value = strParam_[key]; + return true; + } + /*! \brief Get a hint parameter (all information) + + Return all available information for the hint: sense, strength, + and any extra information associated with the hint. + + Implementors: The default implementation will always set + \c otherInformation to NULL. This is almost certainly not the + behaviour you want; you really should override this method. + */ + virtual bool getHintParam(OsiHintParam key, bool& yesNo, + OsiHintStrength& strength, + void *& otherInformation) const { + if (key==OsiLastHintParam) + return false; + yesNo = hintParam_[key]; + strength = hintStrength_[key]; + otherInformation=NULL; + return true; + } + /*! \brief Get a hint parameter (sense and strength only) + + Return only the sense and strength of the hint. + */ + virtual bool getHintParam(OsiHintParam key, bool& yesNo, + OsiHintStrength& strength) const { + if (key==OsiLastHintParam) + return false; + yesNo = hintParam_[key]; + strength = hintStrength_[key]; + return true; + } + /*! \brief Get a hint parameter (sense only) + + Return only the sense (true/false) of the hint. + */ + virtual bool getHintParam(OsiHintParam key, bool& yesNo) const { + if (key==OsiLastHintParam) + return false; + yesNo = hintParam_[key]; + return true; + } + /*! \brief Copy all parameters in this section from one solver to another + + Note that the current implementation also copies the appData block, + message handler, and rowCutDebugger. Arguably these should have + independent copy methods. + */ + void copyParameters(OsiSolverInterface & rhs); + + /** \brief Return the integrality tolerance of the underlying solver. + + We should be able to get an integrality tolerance, but + until that time just use the primal tolerance + + \todo + This method should be replaced; it's architecturally wrong. This + should be an honest dblParam with a keyword. Underlying solvers + that do not support integer variables should return false for set and + get on this parameter. Underlying solvers that support integrality + should add this to the parameters they support, using whatever + tolerance is appropriate. -lh, 091021- + */ + inline double getIntegerTolerance() const + { return dblParam_[OsiPrimalTolerance];} + //@} + + //--------------------------------------------------------------------------- + ///@name Methods returning info on how the solution process terminated + //@{ + /// Are there numerical difficulties? + virtual bool isAbandoned() const = 0; + /// Is optimality proven? + virtual bool isProvenOptimal() const = 0; + /// Is primal infeasibility proven? + virtual bool isProvenPrimalInfeasible() const = 0; + /// Is dual infeasibility proven? + virtual bool isProvenDualInfeasible() const = 0; + /// Is the given primal objective limit reached? + virtual bool isPrimalObjectiveLimitReached() const; + /// Is the given dual objective limit reached? + virtual bool isDualObjectiveLimitReached() const; + /// Iteration limit reached? + virtual bool isIterationLimitReached() const = 0; + //@} + + //--------------------------------------------------------------------------- + /** \name Warm start methods + + Note that the warm start methods return a generic CoinWarmStart object. + The precise characteristics of this object are solver-dependent. Clients + who wish to maintain a maximum degree of solver independence should take + care to avoid unnecessary assumptions about the properties of a warm start + object. + */ + //@{ + /*! \brief Get an empty warm start object + + This routine returns an empty warm start object. Its purpose is + to provide a way for a client to acquire a warm start object of the + appropriate type for the solver, which can then be resized and modified + as desired. + */ + + virtual CoinWarmStart *getEmptyWarmStart () const = 0 ; + + /** \brief Get warm start information. + + Return warm start information for the current state of the solver + interface. If there is no valid warm start information, an empty warm + start object wil be returned. + */ + virtual CoinWarmStart* getWarmStart() const = 0; + /** \brief Get warm start information. + + Return warm start information for the current state of the solver + interface. If there is no valid warm start information, an empty warm + start object wil be returned. This does not necessarily create an + object - may just point to one. must Delete set true if user + should delete returned object. + */ + virtual CoinWarmStart* getPointerToWarmStart(bool & mustDelete) ; + + /** \brief Set warm start information. + + Return true or false depending on whether the warm start information was + accepted or not. + By definition, a call to setWarmStart with a null parameter should + cause the solver interface to refresh its warm start information + from the underlying solver. + */ + virtual bool setWarmStart(const CoinWarmStart* warmstart) = 0; + //@} + + //--------------------------------------------------------------------------- + /**@name Hot start methods + + Primarily used in strong branching. The user can create a hot start + object --- a snapshot of the optimization process --- then reoptimize + over and over again, starting from the same point. + + \note + <ul> + <li> Between hot started optimizations only bound changes are allowed. + <li> The copy constructor and assignment operator should NOT copy any + hot start information. + <li> The default implementation simply extracts a warm start object in + \c markHotStart, resets to the warm start object in + \c solveFromHotStart, and deletes the warm start object in + \c unmarkHotStart. + <em>Actual solver implementations are encouraged to do better.</em> + </ul> + + */ + //@{ + /// Create a hot start snapshot of the optimization process. + virtual void markHotStart(); + /// Optimize starting from the hot start snapshot. + virtual void solveFromHotStart(); + /// Delete the hot start snapshot. + virtual void unmarkHotStart(); + //@} + + //--------------------------------------------------------------------------- + /**@name Problem query methods + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from the + methods that return vectors. + + Const pointers returned from any data-query method are valid as long as + the data is unchanged and the solver is not called. + */ + //@{ + /// Get the number of columns + virtual int getNumCols() const = 0; + + /// Get the number of rows + virtual int getNumRows() const = 0; + + /// Get the number of nonzero elements + virtual int getNumElements() const = 0; + + /// Get the number of integer variables + virtual int getNumIntegers() const ; + + /// Get a pointer to an array[getNumCols()] of column lower bounds + virtual const double * getColLower() const = 0; + + /// Get a pointer to an array[getNumCols()] of column upper bounds + virtual const double * getColUpper() const = 0; + + /*! \brief Get a pointer to an array[getNumRows()] of row constraint senses. + + <ul> + <li>'L': <= constraint + <li>'E': = constraint + <li>'G': >= constraint + <li>'R': ranged constraint + <li>'N': free constraint + </ul> + */ + virtual const char * getRowSense() const = 0; + + /*! \brief Get a pointer to an array[getNumRows()] of row right-hand sides + + <ul> + <li> if getRowSense()[i] == 'L' then + getRightHandSide()[i] == getRowUpper()[i] + <li> if getRowSense()[i] == 'G' then + getRightHandSide()[i] == getRowLower()[i] + <li> if getRowSense()[i] == 'R' then + getRightHandSide()[i] == getRowUpper()[i] + <li> if getRowSense()[i] == 'N' then + getRightHandSide()[i] == 0.0 + </ul> + */ + virtual const double * getRightHandSide() const = 0; + + /*! \brief Get a pointer to an array[getNumRows()] of row ranges. + + <ul> + <li> if getRowSense()[i] == 'R' then + getRowRange()[i] == getRowUpper()[i] - getRowLower()[i] + <li> if getRowSense()[i] != 'R' then + getRowRange()[i] is 0.0 + </ul> + */ + virtual const double * getRowRange() const = 0; + + /// Get a pointer to an array[getNumRows()] of row lower bounds + virtual const double * getRowLower() const = 0; + + /// Get a pointer to an array[getNumRows()] of row upper bounds + virtual const double * getRowUpper() const = 0; + + /*! \brief Get a pointer to an array[getNumCols()] of objective + function coefficients. + */ + virtual const double * getObjCoefficients() const = 0; + + /*! \brief Get the objective function sense + + - 1 for minimisation (default) + - -1 for maximisation + */ + virtual double getObjSense() const = 0; + + /// Return true if the variable is continuous + virtual bool isContinuous(int colIndex) const = 0; + + /// Return true if the variable is binary + virtual bool isBinary(int colIndex) const; + + /*! \brief Return true if the variable is integer. + + This method returns true if the variable is binary or general integer. + */ + virtual bool isInteger(int colIndex) const; + + /// Return true if the variable is general integer + virtual bool isIntegerNonBinary(int colIndex) const; + + /// Return true if the variable is binary and not fixed + virtual bool isFreeBinary(int colIndex) const; + + /*! \brief Return an array[getNumCols()] of column types + + \deprecated See #getColType + */ + inline const char *columnType(bool refresh=false) const + { return getColType(refresh); } + + /*! \brief Return an array[getNumCols()] of column types + + - 0 - continuous + - 1 - binary + - 2 - general integer + + If \p refresh is true, the classification of integer variables as + binary or general integer will be reevaluated. If the current bounds + are [0,1], or if the variable is fixed at 0 or 1, it will be classified + as binary, otherwise it will be classified as general integer. + */ + virtual const char * getColType(bool refresh=false) const; + + /// Get a pointer to a row-wise copy of the matrix + virtual const CoinPackedMatrix * getMatrixByRow() const = 0; + + /// Get a pointer to a column-wise copy of the matrix + virtual const CoinPackedMatrix * getMatrixByCol() const = 0; + + /*! \brief Get a pointer to a mutable row-wise copy of the matrix. + + Returns NULL if the request is not meaningful (i.e., the OSI will not + recognise any modifications to the matrix). + */ + virtual CoinPackedMatrix * getMutableMatrixByRow() const {return NULL;} + + /*! \brief Get a pointer to a mutable column-wise copy of the matrix + + Returns NULL if the request is not meaningful (i.e., the OSI will not + recognise any modifications to the matrix). + */ + virtual CoinPackedMatrix * getMutableMatrixByCol() const {return NULL;} + + /// Get the solver's value for infinity + virtual double getInfinity() const = 0; + //@} + + /**@name Solution query methods */ + //@{ + /// Get a pointer to an array[getNumCols()] of primal variable values + virtual const double * getColSolution() const = 0; + + /** Get a pointer to an array[getNumCols()] of primal variable values + guaranteed to be between the column lower and upper bounds. + */ + virtual const double * getStrictColSolution(); + + /// Get pointer to array[getNumRows()] of dual variable values + virtual const double * getRowPrice() const = 0; + + /// Get a pointer to an array[getNumCols()] of reduced costs + virtual const double * getReducedCost() const = 0; + + /** Get a pointer to array[getNumRows()] of row activity levels. + + The row activity for a row is the left-hand side evaluated at the + current solution. + */ + virtual const double * getRowActivity() const = 0; + + /// Get the objective function value. + virtual double getObjValue() const = 0; + + /** Get the number of iterations it took to solve the problem (whatever + `iteration' means to the solver). + */ + virtual int getIterationCount() const = 0; + + /** Get as many dual rays as the solver can provide. In case of proven + primal infeasibility there should (with high probability) be at least + one. + + The first getNumRows() ray components will always be associated with + the row duals (as returned by getRowPrice()). If \c fullRay is true, + the final getNumCols() entries will correspond to the ray components + associated with the nonbasic variables. If the full ray is requested + and the method cannot provide it, it will throw an exception. + + \note + Implementors of solver interfaces note that the double pointers in + the vector should point to arrays of length getNumRows() (fullRay = + false) or (getNumRows()+getNumCols()) (fullRay = true) and they should + be allocated with new[]. + + \note + Clients of solver interfaces note that it is the client's + responsibility to free the double pointers in the vector using + delete[]. Clients are reminded that a problem can be dual and primal + infeasible. + */ + virtual std::vector<double*> getDualRays(int maxNumRays, + bool fullRay = false) const = 0; + + /** Get as many primal rays as the solver can provide. In case of proven + dual infeasibility there should (with high probability) be at least + one. + + \note + Implementors of solver interfaces note that the double pointers in + the vector should point to arrays of length getNumCols() and they + should be allocated with new[]. + + \note + Clients of solver interfaces note that it is the client's + responsibility to free the double pointers in the vector using + delete[]. Clients are reminded that a problem can be dual and primal + infeasible. + */ + virtual std::vector<double*> getPrimalRays(int maxNumRays) const = 0; + + /** Get vector of indices of primal variables which are integer variables + but have fractional values in the current solution. */ + virtual OsiVectorInt getFractionalIndices(const double etol=1.e-05) + const; + //@} + + //------------------------------------------------------------------------- + /**@name Methods to modify the objective, bounds, and solution + + For functions which take a set of indices as parameters + (\c setObjCoeffSet(), \c setColSetBounds(), \c setRowSetBounds(), + \c setRowSetTypes()), the parameters follow the C++ STL iterator + convention: \c indexFirst points to the first index in the + set, and \c indexLast points to a position one past the last index + in the set. + + */ + //@{ + /** Set an objective function coefficient */ + virtual void setObjCoeff( int elementIndex, double elementValue ) = 0; + + /** Set a set of objective function coefficients */ + virtual void setObjCoeffSet(const int* indexFirst, + const int* indexLast, + const double* coeffList); + + /** Set the objective coefficients for all columns. + + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setObjective(const double * array); + + /** Set the objective function sense. + + Use 1 for minimisation (default), -1 for maximisation. + + \note + Implementors note that objective function sense is a parameter of + the OSI, not a property of the problem. Objective sense can be + set prior to problem load and should not be affected by loading a + new problem. + */ + virtual void setObjSense(double s) = 0; + + + /** Set a single column lower bound. + Use -getInfinity() for -infinity. */ + virtual void setColLower( int elementIndex, double elementValue ) = 0; + + /** Set the lower bounds for all columns. + + array [getNumCols()] is an array of values for the lower bounds. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColLower(const double * array); + + /** Set a single column upper bound. + Use getInfinity() for infinity. */ + virtual void setColUpper( int elementIndex, double elementValue ) = 0; + + /** Set the upper bounds for all columns. + + array [getNumCols()] is an array of values for the upper bounds. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColUpper(const double * array); + + + /** Set a single column lower and upper bound. + The default implementation just invokes setColLower() and + setColUpper() */ + virtual void setColBounds( int elementIndex, + double lower, double upper ) { + setColLower(elementIndex, lower); + setColUpper(elementIndex, upper); + } + + /** Set the upper and lower bounds of a set of columns. + + The default implementation just invokes setColBounds() over and over + again. For each column, boundList must contain both a lower and + upper bound, in that order. + */ + virtual void setColSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + + /** Set a single row lower bound. + Use -getInfinity() for -infinity. */ + virtual void setRowLower( int elementIndex, double elementValue ) = 0; + + /** Set a single row upper bound. + Use getInfinity() for infinity. */ + virtual void setRowUpper( int elementIndex, double elementValue ) = 0; + + /** Set a single row lower and upper bound. + The default implementation just invokes setRowLower() and + setRowUpper() */ + virtual void setRowBounds( int elementIndex, + double lower, double upper ) { + setRowLower(elementIndex, lower); + setRowUpper(elementIndex, upper); + } + + /** Set the bounds on a set of rows. + + The default implementation just invokes setRowBounds() over and over + again. For each row, boundList must contain both a lower and + upper bound, in that order. + */ + virtual void setRowSetBounds(const int* indexFirst, + const int* indexLast, + const double* boundList); + + + /** Set the type of a single row */ + virtual void setRowType(int index, char sense, double rightHandSide, + double range) = 0; + + /** Set the type of a set of rows. + The default implementation just invokes setRowType() + over and over again. + */ + virtual void setRowSetTypes(const int* indexFirst, + const int* indexLast, + const char* senseList, + const double* rhsList, + const double* rangeList); + + /** Set the primal solution variable values + + colsol[getNumCols()] is an array of values for the primal variables. + These values are copied to memory owned by the solver interface + object or the solver. They will be returned as the result of + getColSolution() until changed by another call to setColSolution() or + by a call to any solver routine. Whether the solver makes use of the + solution in any way is solver-dependent. + */ + virtual void setColSolution(const double *colsol) = 0; + + /** Set dual solution variable values + + rowprice[getNumRows()] is an array of values for the dual variables. + These values are copied to memory owned by the solver interface + object or the solver. They will be returned as the result of + getRowPrice() until changed by another call to setRowPrice() or by a + call to any solver routine. Whether the solver makes use of the + solution in any way is solver-dependent. + */ + virtual void setRowPrice(const double * rowprice) = 0; + + /** Fix variables at bound based on reduced cost + + For variables currently at bound, fix the variable at bound if the + reduced cost exceeds the gap. Return the number of variables fixed. + + If justInteger is set to false, the routine will also fix continuous + variables, but the test still assumes a delta of 1.0. + */ + virtual int reducedCostFix(double gap, bool justInteger=true); + //@} + + //------------------------------------------------------------------------- + /**@name Methods to set variable type */ + //@{ + /** Set the index-th variable to be a continuous variable */ + virtual void setContinuous(int index) = 0; + /** Set the index-th variable to be an integer variable */ + virtual void setInteger(int index) = 0; + /** Set the variables listed in indices (which is of length len) to be + continuous variables */ + virtual void setContinuous(const int* indices, int len); + /** Set the variables listed in indices (which is of length len) to be + integer variables */ + virtual void setInteger(const int* indices, int len); + //@} + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + + /*! \brief Data type for name vectors. */ + typedef std::vector<std::string> OsiNameVec ; + + /*! \name Methods for row and column names + + Osi defines three name management disciplines: `auto names' (0), `lazy + names' (1), and `full names' (2). See the description of + #OsiNameDiscipline for details. Changing the name discipline (via + setIntParam()) will not automatically add or remove name information, + but setting the discipline to auto will make existing information + inaccessible until the discipline is reset to lazy or full. + + By definition, a row index of getNumRows() (<i>i.e.</i>, one larger than + the largest valid row index) refers to the objective function. + + OSI users and implementors: While the OSI base class can define an + interface and provide rudimentary support, use of names really depends + on support by the OsiXXX class to ensure that names are managed + correctly. If an OsiXXX class does not support names, it should return + false for calls to getIntParam() or setIntParam() that reference + OsiNameDiscipline. + */ + //@{ + + /*! \brief Generate a standard name of the form Rnnnnnnn or Cnnnnnnn + + Set \p rc to 'r' for a row name, 'c' for a column name. + The `nnnnnnn' part is generated from ndx and will contain 7 digits + by default, padded with zeros if necessary. As a special case, + ndx = getNumRows() is interpreted as a request for the name of the + objective function. OBJECTIVE is returned, truncated to digits+1 + characters to match the row and column names. + */ + virtual std::string dfltRowColName(char rc, + int ndx, unsigned digits = 7) const ; + + /*! \brief Return the name of the objective function */ + + virtual std::string getObjName (unsigned maxLen = static_cast<unsigned>(std::string::npos)) const ; + + /*! \brief Set the name of the objective function */ + + virtual inline void setObjName (std::string name) + { objName_ = name ; } + + /*! \brief Return the name of the row. + + The routine will <i>always</i> return some name, regardless of the name + discipline or the level of support by an OsiXXX derived class. Use + maxLen to limit the length. + */ + virtual std::string getRowName(int rowIndex, + unsigned maxLen = static_cast<unsigned>(std::string::npos)) const ; + + /*! \brief Return a pointer to a vector of row names + + If the name discipline (#OsiNameDiscipline) is auto, the return value + will be a vector of length zero. If the name discipline is lazy, the + vector will contain only names supplied by the client and will be no + larger than needed to hold those names; entries not supplied will be + null strings. In particular, the objective name is <i>not</i> + included in the vector for lazy names. If the name discipline is + full, the vector will have getNumRows() names, either supplied or + generated, plus one additional entry for the objective name. + */ + virtual const OsiNameVec &getRowNames() ; + + /*! \brief Set a row name + + Quietly does nothing if the name discipline (#OsiNameDiscipline) is + auto. Quietly fails if the row index is invalid. + */ + virtual void setRowName(int ndx, std::string name) ; + + /*! \brief Set multiple row names + + The run of len entries starting at srcNames[srcStart] are installed as + row names starting at row index tgtStart. The base class implementation + makes repeated calls to setRowName. + */ + virtual void setRowNames(OsiNameVec &srcNames, + int srcStart, int len, int tgtStart) ; + + /*! \brief Delete len row names starting at index tgtStart + + The specified row names are removed and the remaining row names are + copied down to close the gap. + */ + virtual void deleteRowNames(int tgtStart, int len) ; + + /*! \brief Return the name of the column + + The routine will <i>always</i> return some name, regardless of the name + discipline or the level of support by an OsiXXX derived class. Use + maxLen to limit the length. + */ + virtual std::string getColName(int colIndex, + unsigned maxLen = static_cast<unsigned>(std::string::npos)) const ; + + /*! \brief Return a pointer to a vector of column names + + If the name discipline (#OsiNameDiscipline) is auto, the return value + will be a vector of length zero. If the name discipline is lazy, the + vector will contain only names supplied by the client and will be no + larger than needed to hold those names; entries not supplied will be + null strings. If the name discipline is full, the vector will have + getNumCols() names, either supplied or generated. + */ + virtual const OsiNameVec &getColNames() ; + + /*! \brief Set a column name + + Quietly does nothing if the name discipline (#OsiNameDiscipline) is + auto. Quietly fails if the column index is invalid. + */ + virtual void setColName(int ndx, std::string name) ; + + /*! \brief Set multiple column names + + The run of len entries starting at srcNames[srcStart] are installed as + column names starting at column index tgtStart. The base class + implementation makes repeated calls to setColName. + */ + virtual void setColNames(OsiNameVec &srcNames, + int srcStart, int len, int tgtStart) ; + + /*! \brief Delete len column names starting at index tgtStart + + The specified column names are removed and the remaining column names + are copied down to close the gap. + */ + virtual void deleteColNames(int tgtStart, int len) ; + + + /*! \brief Set row and column names from a CoinMpsIO object. + + Also sets the name of the objective function. If the name discipline + is auto, you get what you asked for. This routine does not use + setRowName or setColName. + */ + void setRowColNames(const CoinMpsIO &mps) ; + + /*! \brief Set row and column names from a CoinModel object. + + If the name discipline is auto, you get what you asked for. + This routine does not use setRowName or setColName. + */ + void setRowColNames(CoinModel &mod) ; + + /*! \brief Set row and column names from a CoinLpIO object. + + Also sets the name of the objective function. If the name discipline is + auto, you get what you asked for. This routine does not use setRowName + or setColName. + */ + void setRowColNames(CoinLpIO &mod) ; + + //@} + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + /**@name Methods to modify the constraint system. + + Note that new columns are added as continuous variables. + */ + //@{ + + /** Add a column (primal variable) to the problem. */ + virtual void addCol(const CoinPackedVectorBase& vec, + const double collb, const double colub, + const double obj) = 0; + + /*! \brief Add a named column (primal variable) to the problem. + + The default implementation adds the column, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addCol(const CoinPackedVectorBase& vec, + const double collb, const double colub, + const double obj, std::string name) ; + + /** Add a column (primal variable) to the problem. */ + virtual void addCol(int numberElements, + const int* rows, const double* elements, + const double collb, const double colub, + const double obj) ; + + /*! \brief Add a named column (primal variable) to the problem. + + The default implementation adds the column, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addCol(int numberElements, + const int* rows, const double* elements, + const double collb, const double colub, + const double obj, std::string name) ; + + /** Add a set of columns (primal variables) to the problem. + + The default implementation simply makes repeated calls to + addCol(). + */ + virtual void addCols(const int numcols, + const CoinPackedVectorBase * const * cols, + const double* collb, const double* colub, + const double* obj); + + /** Add a set of columns (primal variables) to the problem. + + The default implementation simply makes repeated calls to + addCol(). + */ + virtual void addCols(const int numcols, const int* columnStarts, + const int* rows, const double* elements, + const double* collb, const double* colub, + const double* obj); + + /// Add columns using a CoinBuild object + void addCols(const CoinBuild & buildObject); + + /** Add columns from a model object. returns + -1 if object in bad state (i.e. has row information) + otherwise number of errors + modelObject non const as can be regularized as part of build + */ + int addCols(CoinModel & modelObject); + +#if 0 + /** */ + virtual void addCols(const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj); +#endif + + /** \brief Remove a set of columns (primal variables) from the + problem. + + The solver interface for a basis-oriented solver will maintain valid + warm start information if all deleted variables are nonbasic. + */ + virtual void deleteCols(const int num, const int * colIndices) = 0; + + /*! \brief Add a row (constraint) to the problem. */ + virtual void addRow(const CoinPackedVectorBase& vec, + const double rowlb, const double rowub) = 0; + + /*! \brief Add a named row (constraint) to the problem. + + The default implementation adds the row, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addRow(const CoinPackedVectorBase& vec, + const double rowlb, const double rowub, + std::string name) ; + + /*! \brief Add a row (constraint) to the problem. */ + virtual void addRow(const CoinPackedVectorBase& vec, + const char rowsen, const double rowrhs, + const double rowrng) = 0; + + /*! \brief Add a named row (constraint) to the problem. + + The default implementation adds the row, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addRow(const CoinPackedVectorBase& vec, + const char rowsen, const double rowrhs, + const double rowrng, std::string name) ; + + /*! Add a row (constraint) to the problem. + + Converts to addRow(CoinPackedVectorBase&,const double,const double). + */ + virtual void addRow(int numberElements, + const int *columns, const double *element, + const double rowlb, const double rowub) ; + + /*! Add a set of rows (constraints) to the problem. + + The default implementation simply makes repeated calls to + addRow(). + */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase * const * rows, + const double* rowlb, const double* rowub); + + /** Add a set of rows (constraints) to the problem. + + The default implementation simply makes repeated calls to + addRow(). + */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase * const * rows, + const char* rowsen, const double* rowrhs, + const double* rowrng); + + /** Add a set of rows (constraints) to the problem. + + The default implementation simply makes repeated calls to + addRow(). + */ + virtual void addRows(const int numrows, const int *rowStarts, + const int *columns, const double *element, + const double *rowlb, const double *rowub); + + /// Add rows using a CoinBuild object + void addRows(const CoinBuild &buildObject); + + /*! Add rows from a CoinModel object. + + Returns -1 if the object is in the wrong state (<i>i.e.</i>, has + column-major information), otherwise the number of errors. + + The modelObject is not const as it can be regularized as part of + the build. + */ + int addRows(CoinModel &modelObject); + +#if 0 + /** */ + virtual void addRows(const CoinPackedMatrix& matrix, + const double* rowlb, const double* rowub); + /** */ + virtual void addRows(const CoinPackedMatrix& matrix, + const char* rowsen, const double* rowrhs, + const double* rowrng); +#endif + + /** \brief Delete a set of rows (constraints) from the problem. + + The solver interface for a basis-oriented solver will maintain valid + warm start information if all deleted rows are loose. + */ + virtual void deleteRows(const int num, const int * rowIndices) = 0; + + /** \brief Replace the constraint matrix + + I (JJF) am getting annoyed because I can't just replace a matrix. + The default behavior of this is do nothing so only use where that would + not matter, e.g. strengthening a matrix for MIP. + */ + virtual void replaceMatrixOptional(const CoinPackedMatrix & ) {} + + /** \brief Replace the constraint matrix + + And if it does matter (not used at present) + */ + virtual void replaceMatrix(const CoinPackedMatrix & ) {abort();} + + /** \brief Save a copy of the base model + + If solver wants it can save a copy of "base" (continuous) model here. + */ + virtual void saveBaseModel() {} + + /** \brief Reduce the constraint system to the specified number of + constraints. + + If solver wants it can restore a copy of "base" (continuous) model + here. + + \note + The name is somewhat misleading. Implementors should consider + the opportunity to optimise behaviour in the common case where + \p numberRows is exactly the number of original constraints. Do not, + however, neglect the possibility that \p numberRows does not equal + the number of original constraints. + */ + virtual void restoreBaseModel(int numberRows); + //----------------------------------------------------------------------- + /** Apply a collection of cuts. + + Only cuts which have an <code>effectiveness >= effectivenessLb</code> + are applied. + <ul> + <li> ReturnCode.getNumineffective() -- number of cuts which were + not applied because they had an + <code>effectiveness < effectivenessLb</code> + <li> ReturnCode.getNuminconsistent() -- number of invalid cuts + <li> ReturnCode.getNuminconsistentWrtIntegerModel() -- number of + cuts that are invalid with respect to this integer model + <li> ReturnCode.getNuminfeasible() -- number of cuts that would + make this integer model infeasible + <li> ReturnCode.getNumApplied() -- number of integer cuts which + were applied to the integer model + <li> cs.size() == getNumineffective() + + getNuminconsistent() + + getNuminconsistentWrtIntegerModel() + + getNuminfeasible() + + getNumApplied() + </ul> + */ + virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs, + double effectivenessLb = 0.0); + + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + Would be even more efficient to pass an array of pointers. + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts); + + /** Apply a collection of row cuts which are all effective. + This is passed in as an array of pointers. + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts); + + /// Deletes branching information before columns deleted + void deleteBranchingInfo(int numberDeleted, const int * which); + + //@} + + //--------------------------------------------------------------------------- + + /**@name Methods for problem input and output */ + //@{ + /*! \brief Load in a problem by copying the arguments. The constraints on + the rows are given by lower and upper bounds. + + If a pointer is 0 then the following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + + Note that the default values for rowub and rowlb produce the + constraint -infty <= ax <= infty. This is probably not what you want. + */ + virtual void loadProblem (const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub) = 0; + + /*! \brief Load in a problem by assuming ownership of the arguments. + The constraints on the rows are given by lower and upper bounds. + + For default argument values see the matching loadProblem method. + + \warning + The arguments passed to this method will be freed using the + C++ <code>delete</code> and <code>delete[]</code> functions. + */ + virtual void assignProblem (CoinPackedMatrix*& matrix, + double*& collb, double*& colub, double*& obj, + double*& rowlb, double*& rowub) = 0; + + /*! \brief Load in a problem by copying the arguments. + The constraints on the rows are given by sense/rhs/range triplets. + + If a pointer is 0 then the following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>obj</code>: all variables have 0 objective coefficient + <li> <code>rowsen</code>: all rows are >= + <li> <code>rowrhs</code>: all right hand sides are 0 + <li> <code>rowrng</code>: 0 for the ranged rows + </ul> + + Note that the default values for rowsen, rowrhs, and rowrng produce the + constraint ax >= 0. + */ + virtual void loadProblem (const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng) = 0; + + /*! \brief Load in a problem by assuming ownership of the arguments. + The constraints on the rows are given by sense/rhs/range triplets. + + For default argument values see the matching loadProblem method. + + \warning + The arguments passed to this method will be freed using the + C++ <code>delete</code> and <code>delete[]</code> functions. + */ + virtual void assignProblem (CoinPackedMatrix*& matrix, + double*& collb, double*& colub, double*& obj, + char*& rowsen, double*& rowrhs, + double*& rowrng) = 0; + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by lower and upper bounds. + + The matrix vectors must be gap-free. Note that <code>start</code> must + have <code>numcols+1</code> entries so that the length of the last column + can be calculated as <code>start[numcols]-start[numcols-1]</code>. + + See the previous loadProblem method using rowlb and rowub for default + argument values. + */ + virtual void loadProblem (const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub) = 0; + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by sense/rhs/range triplets. + + The matrix vectors must be gap-free. Note that <code>start</code> must + have <code>numcols+1</code> entries so that the length of the last column + can be calculated as <code>start[numcols]-start[numcols-1]</code>. + + See the previous loadProblem method using sense/rhs/range for default + argument values. + */ + virtual void loadProblem (const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng) = 0; + + /*! \brief Load a model from a CoinModel object. Return the number of + errors encountered. + + The modelObject parameter cannot be const as it may be changed as part + of process. If keepSolution is true will try and keep warmStart. + */ + virtual int loadFromCoinModel (CoinModel & modelObject, + bool keepSolution=false); + + /*! \brief Read a problem in MPS format from the given filename. + + The default implementation uses CoinMpsIO::readMps() to read + the MPS file and returns the number of errors encountered. + */ + virtual int readMps (const char *filename, + const char *extension = "mps") ; + + /*! \brief Read a problem in MPS format from the given full filename. + + This uses CoinMpsIO::readMps() to read the MPS file and returns the + number of errors encountered. It also may return an array of set + information + */ + virtual int readMps (const char *filename, const char*extension, + int & numberSets, CoinSet ** & sets); + + /*! \brief Read a problem in GMPL format from the given filenames. + + The default implementation uses CoinMpsIO::readGMPL(). This capability + is available only if the third-party package Glpk is installed. + */ + virtual int readGMPL (const char *filename, const char *dataname=NULL); + + /*! \brief Write the problem in MPS format to the specified file. + + If objSense is non-zero, a value of -1.0 causes the problem to be + written with a maximization objective; +1.0 forces a minimization + objective. If objSense is zero, the choice is left to the implementation. + */ + virtual void writeMps (const char *filename, + const char *extension = "mps", + double objSense=0.0) const = 0; + + /*! \brief Write the problem in MPS format to the specified file with + more control over the output. + + Row and column names may be null. + formatType is + <ul> + <li> 0 - normal + <li> 1 - extra accuracy + <li> 2 - IEEE hex + </ul> + + Returns non-zero on I/O error + */ + int writeMpsNative (const char *filename, + const char ** rowNames, const char ** columnNames, + int formatType=0,int numberAcross=2, + double objSense=0.0, int numberSOS=0, + const CoinSet * setInfo=NULL) const ; + +/***********************************************************************/ +// Lp files + + /** Write the problem into an Lp file of the given filename with the + specified extension. + Coefficients with value less than epsilon away from an integer value + are written as integers. + Write at most numberAcross monomials on a line. + Write non integer numbers with decimals digits after the decimal point. + + The written problem is always a minimization problem. + If the current problem is a maximization problem, the + intended objective function for the written problem is the current + objective function multiplied by -1. If the current problem is a + minimization problem, the intended objective function for the + written problem is the current objective function. + If objSense < 0, the intended objective function is multiplied by -1 + before writing the problem. It is left unchanged otherwise. + + Write objective function name and constraint names if useRowNames is + true. This version calls writeLpNative(). + */ + virtual void writeLp(const char *filename, + const char *extension = "lp", + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + + /** Write the problem into the file pointed to by the parameter fp. + Other parameters are similar to + those of writeLp() with first parameter filename. + */ + virtual void writeLp(FILE *fp, + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + + /** Write the problem into an Lp file. Parameters are similar to + those of writeLp(), but in addition row names and column names + may be given. + + Parameter rowNames may be NULL, in which case default row names + are used. If rowNames is not NULL, it must have exactly one entry + per row in the problem and one additional + entry (rowNames[getNumRows()] with the objective function name. + These getNumRows()+1 entries must be distinct. If this is not the + case, default row names + are used. In addition, format restrictions are imposed on names + (see CoinLpIO::is_invalid_name() for details). + + Similar remarks can be made for the parameter columnNames which + must either be NULL or have exactly getNumCols() distinct entries. + + Write objective function name and constraint names if + useRowNames is true. */ + int writeLpNative(const char *filename, + char const * const * const rowNames, + char const * const * const columnNames, + const double epsilon = 1.0e-5, + const int numberAcross = 10, + const int decimals = 5, + const double objSense = 0.0, + const bool useRowNames = true) const; + + /** Write the problem into the file pointed to by the parameter fp. + Other parameters are similar to + those of writeLpNative() with first parameter filename. + */ + int writeLpNative(FILE *fp, + char const * const * const rowNames, + char const * const * const columnNames, + const double epsilon = 1.0e-5, + const int numberAcross = 10, + const int decimals = 5, + const double objSense = 0.0, + const bool useRowNames = true) const; + + /// Read file in LP format from file with name filename. + /// See class CoinLpIO for description of this format. + virtual int readLp(const char *filename, const double epsilon = 1e-5); + + /// Read file in LP format from the file pointed to by fp. + /// See class CoinLpIO for description of this format. + int readLp(FILE *fp, const double epsilon = 1e-5); + + //@} + + //--------------------------------------------------------------------------- + + /**@name Miscellaneous */ + //@{ + /** Check two models against each other. Return nonzero if different. + Ignore names if that set. + (Note initial version does not check names) + May modify both models by cleaning up + */ + int differentModel(OsiSolverInterface & other, + bool ignoreNames=true); +#ifdef COIN_SNAPSHOT + /// Return a CoinSnapshot + virtual CoinSnapshot * snapshot(bool createArrays=true) const; +#endif +#ifdef COIN_FACTORIZATION_INFO + /// Return number of entries in L part of current factorization + virtual CoinBigIndex getSizeL() const; + /// Return number of entries in U part of current factorization + virtual CoinBigIndex getSizeU() const; +#endif + //@} + + //--------------------------------------------------------------------------- + + /**@name Setting/Accessing application data */ + //@{ + /** Set application data. + + This is a pointer that the application can store into and + retrieve from the solver interface. + This field is available for the application to optionally + define and use. + */ + void setApplicationData (void * appData); + /** Create a clone of an Auxiliary Information object. + The base class just stores an application data pointer + but can be more general. Application data pointer is + designed for one user while this can be extended to cope + with more general extensions. + */ + void setAuxiliaryInfo(OsiAuxInfo * auxiliaryInfo); + + /// Get application data + void * getApplicationData() const; + /// Get pointer to auxiliary info object + OsiAuxInfo * getAuxiliaryInfo() const; + //@} + //--------------------------------------------------------------------------- + + /**@name Message handling + + See the COIN library documentation for additional information about + COIN message facilities. + + */ + //@{ + /** Pass in a message handler + + It is the client's responsibility to destroy a message handler installed + by this routine; it will not be destroyed when the solver interface is + destroyed. + */ + virtual void passInMessageHandler(CoinMessageHandler * handler); + /// Set language + void newLanguage(CoinMessages::Language language); + inline void setLanguage(CoinMessages::Language language) + {newLanguage(language);} + /// Return a pointer to the current message handler + inline CoinMessageHandler * messageHandler() const + {return handler_;} + /// Return the current set of messages + inline CoinMessages messages() + {return messages_;} + /// Return a pointer to the current set of messages + inline CoinMessages * messagesPointer() + {return &messages_;} + /// Return true if default handler + inline bool defaultHandler() const + { return defaultHandler_;} + //@} + //--------------------------------------------------------------------------- + /**@name Methods for dealing with discontinuities other than integers. + + Osi should be able to know about SOS and other types. This is an optional + section where such information can be stored. + + */ + //@{ + /** \brief Identify integer variables and create corresponding objects. + + Record integer variables and create an OsiSimpleInteger object for each + one. All existing OsiSimpleInteger objects will be destroyed. + If justCount then no objects created and we just store numberIntegers_ + */ + + void findIntegers(bool justCount); + /** \brief Identify integer variables and SOS and create corresponding objects. + + Record integer variables and create an OsiSimpleInteger object for each + one. All existing OsiSimpleInteger objects will be destroyed. + If the solver supports SOS then do the same for SOS. + + If justCount then no objects created and we just store numberIntegers_ + Returns number of SOS + */ + + virtual int findIntegersAndSOS(bool justCount); + /// Get the number of objects + inline int numberObjects() const { return numberObjects_;} + /// Set the number of objects + inline void setNumberObjects(int number) + { numberObjects_=number;} + + /// Get the array of objects + inline OsiObject ** objects() const { return object_;} + + /// Get the specified object + const inline OsiObject * object(int which) const { return object_[which];} + /// Get the specified object + inline OsiObject * modifiableObject(int which) const { return object_[which];} + + /// Delete all object information + void deleteObjects(); + + /** Add in object information. + + Objects are cloned; the owner can delete the originals. + */ + void addObjects(int numberObjects, OsiObject ** objects); + /** Use current solution to set bounds so current integer feasible solution will stay feasible. + Only feasible bounds will be used, even if current solution outside bounds. The amount of + such violation will be returned (and if small can be ignored) + */ + double forceFeasible(); + //@} + //--------------------------------------------------------------------------- + + /*! @name Methods related to testing generated cuts + + See the documentation for OsiRowCutDebugger for additional details. + */ + //@{ + /*! \brief Activate the row cut debugger. + + If \p modelName is in the set of known models then all cuts are + checked to see that they do NOT cut off the optimal solution known + to the debugger. + */ + virtual void activateRowCutDebugger (const char *modelName); + + /*! \brief Activate the row cut debugger using a full solution array. + + + Activate the debugger for a model not included in the debugger's + internal database. Cuts will be checked to see that they do NOT + cut off the given solution. + + \p solution must be a full solution vector, but only the integer + variables need to be correct. The debugger will fill in the continuous + variables by solving an lp relaxation with the integer variables + fixed as specified. If the given values for the continuous variables + should be preserved, set \p keepContinuous to true. + */ + virtual void activateRowCutDebugger(const double *solution, + bool enforceOptimality = true); + + /*! \brief Get the row cut debugger provided the solution known to the + debugger is within the feasible region held in the solver. + + If there is a row cut debugger object associated with model AND if + the solution known to the debugger is within the solver's current + feasible region (i.e., the column bounds held in the solver are + compatible with the known solution) then a pointer to the debugger + is returned which may be used to test validity of cuts. + + Otherwise NULL is returned + */ + const OsiRowCutDebugger *getRowCutDebugger() const; + + /*! \brief Get the row cut debugger object + + Return the row cut debugger object if it exists. One common usage of + this method is to obtain a debugger object in order to execute + OsiRowCutDebugger::redoSolution (so that the stored solution is again + compatible with the problem held in the solver). + */ + OsiRowCutDebugger * getRowCutDebuggerAlways() const; + //@} + + /*! \name OsiSimplexInterface + \brief Simplex Interface + + Methods for an advanced interface to a simplex solver. The interface + comprises two groups of methods. Group 1 contains methods for tableau + access. Group 2 contains methods for dictating individual simplex pivots. + */ + //@{ + + /*! \brief Return the simplex implementation level. + + The return codes are: + - 0: the simplex interface is not implemented. + - 1: the Group 1 (tableau access) methods are implemented. + - 2: the Group 2 (pivoting) methods are implemented + + The codes are cumulative - a solver which implements Group 2 also + implements Group 1. + */ + virtual int canDoSimplexInterface() const ; + //@} + + /*! \name OsiSimplex Group 1 + \brief Tableau access methods. + + This group of methods provides access to rows and columns of the basis + inverse and to rows and columns of the tableau. + */ + //@{ + + /*! \brief Prepare the solver for the use of tableau access methods. + + Prepares the solver for the use of the tableau access methods, if + any such preparation is required. + + The \c const attribute is required due to the places this method + may be called (e.g., within CglCutGenerator::generateCuts()). + */ + virtual void enableFactorization() const ; + + /*! \brief Undo the effects of #enableFactorization. */ + virtual void disableFactorization() const ; + + /*! \brief Check if an optimal basis is available. + + Returns true if the problem has been solved to optimality and a + basis is available. This should be used to see if the tableau access + operations are possible and meaningful. + + \note + Implementors please note that this method may be called + before #enableFactorization. + */ + virtual bool basisIsAvailable() const ; + + /// Synonym for #basisIsAvailable + inline bool optimalBasisIsAvailable() const { return basisIsAvailable() ; } + + /*! \brief Retrieve status information for column and row variables. + + This method returns status as integer codes: + <ul> + <li> 0: free + <li> 1: basic + <li> 2: nonbasic at upper bound + <li> 3: nonbasic at lower bound + </ul> + + The #getWarmStart method provides essentially the same functionality + for a simplex-oriented solver, but the implementation details are very + different. + + \note + Logical variables associated with rows are all assumed to have +1 + coefficients, so for a <= constraint the logical will be at lower + bound if the constraint is tight. + + \note + Implementors may choose to implement this method as a wrapper which + converts a CoinWarmStartBasis to the requested representation. + */ + virtual void getBasisStatus(int* cstat, int* rstat) const ; + + /*! \brief Set the status of column and row variables and update + the basis factorization and solution. + + Status information should be coded as documented for #getBasisStatus. + Returns 0 if all goes well, 1 if something goes wrong. + + This method differs from #setWarmStart in the format of the input + and in its immediate effect. Think of it as #setWarmStart immediately + followed by #resolve, but no pivots are allowed. + + \note + Implementors may choose to implement this method as a wrapper that calls + #setWarmStart and #resolve if the no pivot requirement can be satisfied. + */ + virtual int setBasisStatus(const int* cstat, const int* rstat) ; + + /*! \brief Calculate duals and reduced costs for the given objective + coefficients. + + The solver's objective coefficient vector is not changed. + */ + virtual void getReducedGradient(double* columnReducedCosts, + double* duals, const double* c) const ; + + /*! \brief Get a row of the tableau + + If \p slack is not null, it will be loaded with the coefficients for + the artificial (logical) variables (i.e., the row of the basis inverse). + */ + virtual void getBInvARow(int row, double* z, double* slack = NULL) const ; + + /*! \brief Get a row of the basis inverse */ + virtual void getBInvRow(int row, double* z) const ; + + /*! \brief Get a column of the tableau */ + virtual void getBInvACol(int col, double* vec) const ; + + /*! \brief Get a column of the basis inverse */ + virtual void getBInvCol(int col, double* vec) const ; + + /*! \brief Get indices of basic variables + + If the logical (artificial) for row i is basic, the index should be coded + as (#getNumCols + i). + The order of indices must match the order of elements in the vectors + returned by #getBInvACol and #getBInvCol. + */ + virtual void getBasics(int* index) const ; + + //@} + + /*! \name OsiSimplex Group 2 + \brief Pivoting methods + + This group of methods provides for control of individual pivots by a + simplex solver. + */ + //@{ + + /**Enables normal operation of subsequent functions. + This method is supposed to ensure that all typical things (like + reduced costs, etc.) are updated when individual pivots are executed + and can be queried by other methods. says whether will be + doing primal or dual + */ + virtual void enableSimplexInterface(bool doingPrimal) ; + + ///Undo whatever setting changes the above method had to make + virtual void disableSimplexInterface() ; + /** Perform a pivot by substituting a colIn for colOut in the basis. + The status of the leaving variable is given in outStatus. Where + 1 is to upper bound, -1 to lower bound + Return code was undefined - now for OsiClp is 0 for okay, + 1 if inaccuracy forced re-factorization (should be okay) and + -1 for singular factorization + */ + virtual int pivot(int colIn, int colOut, int outStatus) ; + + /** Obtain a result of the primal pivot + Outputs: colOut -- leaving column, outStatus -- its status, + t -- step size, and, if dx!=NULL, *dx -- primal ray direction. + Inputs: colIn -- entering column, sign -- direction of its change (+/-1). + Both for colIn and colOut, artificial variables are index by + the negative of the row index minus 1. + Return code (for now): 0 -- leaving variable found, + -1 -- everything else? + Clearly, more informative set of return values is required + Primal and dual solutions are updated + */ + virtual int primalPivotResult(int colIn, int sign, + int& colOut, int& outStatus, + double& t, CoinPackedVector* dx); + + /** Obtain a result of the dual pivot (similar to the previous method) + Differences: entering variable and a sign of its change are now + the outputs, the leaving variable and its statuts -- the inputs + If dx!=NULL, then *dx contains dual ray + Return code: same + */ + virtual int dualPivotResult(int& colIn, int& sign, + int colOut, int outStatus, + double& t, CoinPackedVector* dx) ; + //@} + + //--------------------------------------------------------------------------- + + ///@name Constructors and destructors + //@{ + /// Default Constructor + OsiSolverInterface(); + + /** Clone + + The result of calling clone(false) is defined to be equivalent to + calling the default constructor OsiSolverInterface(). + */ + virtual OsiSolverInterface * clone(bool copyData = true) const = 0; + + /// Copy constructor + OsiSolverInterface(const OsiSolverInterface &); + + /// Assignment operator + OsiSolverInterface & operator=(const OsiSolverInterface& rhs); + + /// Destructor + virtual ~OsiSolverInterface (); + + /** Reset the solver interface. + + A call to reset() returns the solver interface to the same state as + it would have if it had just been constructed by calling the default + constructor OsiSolverInterface(). + */ + virtual void reset(); + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected methods + //@{ + /** Apply a row cut (append to the constraint matrix). */ + virtual void applyRowCut( const OsiRowCut & rc ) = 0; + + /** Apply a column cut (adjust the bounds of one or more variables). */ + virtual void applyColCut( const OsiColCut & cc ) = 0; + + /** A quick inlined function to convert from the lb/ub style of + constraint definition to the sense/rhs/range style */ + inline void + convertBoundToSense(const double lower, const double upper, + char& sense, double& right, double& range) const; + /** A quick inlined function to convert from the sense/rhs/range style + of constraint definition to the lb/ub style */ + inline void + convertSenseToBound(const char sense, const double right, + const double range, + double& lower, double& upper) const; + /** A quick inlined function to force a value to be between a minimum and + a maximum value */ + template <class T> inline T + forceIntoRange(const T value, const T lower, const T upper) const { + return value < lower ? lower : (value > upper ? upper : value); + } + /** Set OsiSolverInterface object state for default constructor + + This routine establishes the initial values of data fields in the + OsiSolverInterface object when the object is created using the + default constructor. + */ + void setInitialData(); + //@} + + ///@name Protected member data + //@{ + /*! \brief Pointer to row cut debugger object + + Mutable so that we can update the solution held in the debugger while + maintaining const'ness for the Osi object. + */ + mutable OsiRowCutDebugger * rowCutDebugger_; + // Why not just make useful stuff protected? + /// Message handler + CoinMessageHandler * handler_; + /** Flag to say if the currrent handler is the default handler. + Indicates if the solver interface object is responsible + for destruction of the handler (true) or if the client is + responsible (false). + */ + bool defaultHandler_; + /// Messages + CoinMessages messages_; + /// Number of integers + int numberIntegers_; + /// Total number of objects + int numberObjects_; + + /// Integer and ... information (integer info normally at beginning) + OsiObject ** object_; + /** Column type + 0 - continuous + 1 - binary (may get fixed later) + 2 - general integer (may get fixed later) + */ + mutable char * columnType_; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@{ + /// Pointer to user-defined data structure - and more if user wants + OsiAuxInfo * appDataEtc_; + /// Array of integer parameters + int intParam_[OsiLastIntParam]; + /// Array of double parameters + double dblParam_[OsiLastDblParam]; + /// Array of string parameters + std::string strParam_[OsiLastStrParam]; + /// Array of hint parameters + bool hintParam_[OsiLastHintParam]; + /// Array of hint strengths + OsiHintStrength hintStrength_[OsiLastHintParam]; + /** Warm start information used for hot starts when the default + hot start implementation is used. */ + CoinWarmStart* ws_; + /// Column solution satisfying lower and upper column bounds + std::vector<double> strictColSolution_; + + /// Row names + OsiNameVec rowNames_ ; + /// Column names + OsiNameVec colNames_ ; + /// Objective name + std::string objName_ ; + + //@} +}; + +//############################################################################# +/** A quick inlined function to convert from the lb/ub style of constraint + definition to the sense/rhs/range style */ +inline void +OsiSolverInterface::convertBoundToSense(const double lower, const double upper, + char& sense, double& right, + double& range) const +{ + double inf = getInfinity(); + range = 0.0; + if (lower > -inf) { + if (upper < inf) { + right = upper; + if (upper==lower) { + sense = 'E'; + } else { + sense = 'R'; + range = upper - lower; + } + } else { + sense = 'G'; + right = lower; + } + } else { + if (upper < inf) { + sense = 'L'; + right = upper; + } else { + sense = 'N'; + right = 0.0; + } + } +} + +//----------------------------------------------------------------------------- +/** A quick inlined function to convert from the sense/rhs/range style of + constraint definition to the lb/ub style */ +inline void +OsiSolverInterface::convertSenseToBound(const char sense, const double right, + const double range, + double& lower, double& upper) const +{ + double inf=getInfinity(); + switch (sense) { + case 'E': + lower = upper = right; + break; + case 'L': + lower = -inf; + upper = right; + break; + case 'G': + lower = right; + upper = inf; + break; + case 'R': + lower = right - range; + upper = right; + break; + case 'N': + lower = -inf; + upper = inf; + break; + } +} + +#endif diff --git a/thirdparty/linux/include/coin/OsiSolverParameters.hpp b/thirdparty/linux/include/coin/OsiSolverParameters.hpp new file mode 100644 index 0000000..5f607f5 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiSolverParameters.hpp @@ -0,0 +1,142 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiSolverParameters_H +#define OsiSolverParameters_H + +enum OsiIntParam { + /*! \brief Iteration limit for initial solve and resolve. + + The maximum number of iterations (whatever that means for the given + solver) the solver can execute in the OsiSolverinterface::initialSolve() + and OsiSolverinterface::resolve() methods before terminating. + */ + OsiMaxNumIteration = 0, + /*! \brief Iteration limit for hot start + + The maximum number of iterations (whatever that means for the given + solver) the solver can execute in the + OsiSolverinterface::solveFromHotStart() method before terminating. + */ + OsiMaxNumIterationHotStart, + /*! \brief Handling of row and column names. + + The name discipline specifies how the solver will handle row and column + names: + - 0: Auto names: Names cannot be set by the client. Names of the form + Rnnnnnnn or Cnnnnnnn are generated on demand when a name for a + specific row or column is requested; nnnnnnn is derived from the row + or column index. Requests for a vector of names return a vector with + zero entries. + - 1: Lazy names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to the largest index of a name supplied by the client; + some entries in the vector may be null strings. + - 2: Full names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to match the constraint system, and all entries will + contain either the name specified by the client or a generated name. + */ + OsiNameDiscipline, + /*! \brief End marker. + + Used by OsiSolverInterface to allocate a fixed-sized array to store + integer parameters. + */ + OsiLastIntParam +} ; + +enum OsiDblParam { + /*! \brief Dual objective limit. + + This is to be used as a termination criteria in algorithms where the dual + objective changes monotonically (e.g., dual simplex, volume algorithm). + */ + OsiDualObjectiveLimit = 0, + /*! \brief Primal objective limit. + + This is to be used as a termination criteria in algorithms where the + primal objective changes monotonically (e.g., primal simplex) + */ + OsiPrimalObjectiveLimit, + /*! \brief Dual feasibility tolerance. + + The maximum amount a dual constraint can be violated and still be + considered feasible. + */ + OsiDualTolerance, + /*! \brief Primal feasibility tolerance. + + The maximum amount a primal constraint can be violated and still be + considered feasible. + */ + OsiPrimalTolerance, + /** The value of any constant term in the objective function. */ + OsiObjOffset, + /*! \brief End marker. + + Used by OsiSolverInterface to allocate a fixed-sized array to store + double parameters. + */ + OsiLastDblParam +}; + + +enum OsiStrParam { + /*! \brief The name of the loaded problem. + + This is the string specified on the Name card of an mps file. + */ + OsiProbName = 0, + /*! \brief The name of the solver. + + This parameter is read-only. + */ + OsiSolverName, + /*! \brief End marker. + + Used by OsiSolverInterface to allocate a fixed-sized array to store + string parameters. + */ + OsiLastStrParam +}; + +enum OsiHintParam { + /** Whether to do a presolve in initialSolve */ + OsiDoPresolveInInitial = 0, + /** Whether to use a dual algorithm in initialSolve. + The reverse is to use a primal algorithm */ + OsiDoDualInInitial, + /** Whether to do a presolve in resolve */ + OsiDoPresolveInResolve, + /** Whether to use a dual algorithm in resolve. + The reverse is to use a primal algorithm */ + OsiDoDualInResolve, + /** Whether to scale problem */ + OsiDoScale, + /** Whether to create a non-slack basis (only in initialSolve) */ + OsiDoCrash, + /** Whether to reduce amount of printout, e.g., for branch and cut */ + OsiDoReducePrint, + /** Whether we are in branch and cut - so can modify behavior */ + OsiDoInBranchAndCut, + /** Just a marker, so that OsiSolverInterface can allocate a static sized + array to store parameters. */ + OsiLastHintParam +}; + +enum OsiHintStrength { + /** Ignore hint (default) */ + OsiHintIgnore = 0, + /** This means it is only a hint */ + OsiHintTry, + /** This means do hint if at all possible */ + OsiHintDo, + /** And this means throw an exception if not possible */ + OsiForceDo +}; + +#endif diff --git a/thirdparty/linux/include/coin/OsiSymSolverInterface.hpp b/thirdparty/linux/include/coin/OsiSymSolverInterface.hpp new file mode 100644 index 0000000..46f6514 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiSymSolverInterface.hpp @@ -0,0 +1,806 @@ +/*===========================================================================*/ +/* */ +/* This file is part of the SYMPHONY Branch, Cut, and Price Callable */ +/* Library. */ +/* */ +/* SYMPHONY was jointly developed by Ted Ralphs (tkralphs@lehigh.edu) and */ +/* Laci Ladanyi (ladanyi@us.ibm.com). */ +/* */ +/* (c) Copyright 2004-2006 Ted Ralphs and Lehigh University. */ +/* All Rights Reserved. */ +/* */ +/* The authors of this file are Menal Guzelsoy and Ted Ralphs */ +/* */ +/* This software is licensed under the Eclipse Public License. Please see */ +/* accompanying file for terms. */ +/* */ +/*===========================================================================*/ + +#ifndef OsiSymSolverInterface_hpp +#define OsiSymSolverInterface_hpp + +#include "OsiSolverInterface.hpp" +#include "OsiSymSolverParameters.hpp" +#include "SymWarmStart.hpp" + +#include <string> + +typedef struct SYM_ENVIRONMENT sym_environment; + +//############################################################################# + +/** OSI Solver Interface for SYMPHONY + + Many OsiSolverInterface query methods return a const pointer to the + requested read-only data. If the model data is changed or the solver + is called, these pointers may no longer be valid and should be + refreshed by invoking the member function to obtain an updated copy + of the pointer. + For example: + \code + OsiSolverInterface solverInterfacePtr ; + const double * ruBnds = solverInterfacePtr->getRowUpper(); + solverInterfacePtr->applyCuts(someSetOfCuts); + // ruBnds is no longer a valid pointer and must be refreshed + ruBnds = solverInterfacePtr->getRowUpper(); + \endcode + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. +*/ + +class OsiSymSolverInterface : virtual public OsiSolverInterface { + friend void OsiSymSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); + +public: + ///@name Solve methods + //@{ + /// Solve initial LP relaxation + virtual void initialSolve(); + + /// Resolve an IP problem modification + virtual void resolve(); + + /// Invoke solver's built-in enumeration algorithm + virtual void branchAndBound(); + + /// Invoke solver's multi-criteria enumeration algorithm + virtual void multiCriteriaBranchAndBound(); + + /// Get a lower bound for the new rhs problem using the warm start tree. + virtual double getLbForNewRhs(int cnt, int *index, + double * value); + /// Get an upper bound for the new rhs problem using the warm start tree. + virtual double getUbForNewRhs(int cnt, int *index, + double * value); +#if 0 + /// Get a lower bound for the new obj problem using the warm start tree. + virtual double getLbForNewObj(int cnt, int *index, + double * value); + /// Get an upper bound for the new obj problem using the warm start tree. +#endif + virtual double getUbForNewObj(int cnt, int *index, + double * value); + + //@} + + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. There can be various reasons for failure: the given + parameter is not applicable for the solver (e.g., refactorization + frequency for the volume algorithm), the parameter is not yet implemented + for the solver or simply the value of the parameter is out of the range + the solver accepts. If a parameter setting call returns false check the + details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + + */ + //@{ + // Set an integer parameter + virtual bool setIntParam(OsiIntParam key, int value); + + // Set SYMPHONY int parameter + virtual bool setSymParam(OsiSymIntParam key, int value); + + // Set SYMPHONY int parameter directly by the C interface parameter name + virtual bool setSymParam(const std::string key, int value); + + + // Set an double parameter + virtual bool setDblParam(OsiDblParam key, double value); + + // Set SYMPHONY double parameter + virtual bool setSymParam(OsiSymDblParam key, double value); + + // Set SYMPHONY double parameter directly by the C interface parameter name + virtual bool setSymParam(const std::string key, double value); + + + + // Set a string parameter + virtual bool setStrParam(OsiStrParam key, const std::string & value); + + // Set SYMPHONY string parameter + virtual bool setSymParam(OsiSymStrParam key, const std::string & value); + + // Set SYMPHONY string parameter directly by the C interface parameter name + virtual bool setSymParam(const std::string key, const std::string value); + + + + // Get an integer parameter + virtual bool getIntParam(OsiIntParam key, int& value) const; + + // Get SYMPHONY int parameter + virtual bool getSymParam(OsiSymIntParam key, int& value) const; + + // Get SYMPHONY int parameter directly by the C interface parameter name + virtual bool getSymParam(const std::string key, int& value) const; + + + // Get an double parameter + virtual bool getDblParam(OsiDblParam key, double& value) const; + + // Get SYMPHONY double parameter + virtual bool getSymParam(OsiSymDblParam key, double& value) const; + + // Get SYMPHONY double parameter directly by the C interface parameter name + virtual bool getSymParam(const std::string key, double& value) const; + + + + // Get a string parameter + virtual bool getStrParam(OsiStrParam key, std::string& value) const; + + // Get SYMPHONY string parameter + virtual bool getSymParam(OsiSymStrParam key, std::string& value) const; + + // Get SYMPHONY string parameter directly by the C interface parameter name + virtual bool getSymParam(const std::string key, std::string& value) const; + + //@} + + //--------------------------------------------------------------------------- + ///@name Methods returning info on how the solution process terminated + //@{ + /// Are there numerical difficulties? + virtual bool isAbandoned() const; + + /// Is optimality proven? + virtual bool isProvenOptimal() const; + + /// Is primal infeasiblity proven? + virtual bool isProvenPrimalInfeasible() const; + + /// Is dual infeasiblity proven? + virtual bool isProvenDualInfeasible() const { + throw CoinError("Error: Function not implemented", + "isProvenDualInfeasible", "OsiSymSolverInterface"); + } + /// Is the given primal objective limit reached? + //virtual bool isPrimalObjectiveLimitReached() const; + + /// Is the given dual objective limit reached? + //virtual bool isDualObjectiveLimitReached() const{ + // throw CoinError("Error: Function not implemented", + // "isDualObjectiveLimitReached", "OsiSymSolverInterface"); + //} + /// Iteration limit reached? + virtual bool isIterationLimitReached() const; + + /// Time limit reached? + virtual bool isTimeLimitReached() const; + + /// Target gap achieved? + virtual bool isTargetGapReached() const; + + //@} + + //--------------------------------------------------------------------------- + /**@name Warm start methods */ + //@{ + /*! \brief Get an empty warm start object + + This routine returns an empty warm start object. Its purpose is + to provide a way to give a client a warm start object of the + appropriate type, which can resized and modified as desired. + */ + + virtual CoinWarmStart *getEmptyWarmStart () const{ + throw CoinError("Error: Function not implemented", + "getEmptyWarmStart", "OsiSymSolverInterface"); + } + + /** Get warm start information. + + If there is no valid solution, an empty warm start object (0 rows, 0 + columns) wil be returned. + */ + + /* + virtual CoinWarmStart* getWarmStart(bool keepTreeInSymEnv = false) const; + */ + + virtual CoinWarmStart* getWarmStart() const; + + /** Set warm start information. + + Return true/false depending on whether the warm start information was + accepted or not. */ + virtual bool setWarmStart(const CoinWarmStart* warmstart); + //@} + + //--------------------------------------------------------------------------- + /**@name Problem query methods + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. + + Const pointers returned from any data-query method are valid as + long as the data is unchanged and the solver is not called. + */ + //@{ + /// Get pointer to SYMPHONY environment (eventually we won't need this) + sym_environment *getSymphonyEnvironment() const {return env_;} + + /// Get number of columns + virtual int getNumCols() const; + + /// Get number of rows + virtual int getNumRows() const; + + /// Get number of nonzero elements + virtual int getNumElements() const; + + /// Get pointer to array[getNumCols()] of column lower bounds + virtual const double * getColLower() const; + + /// Get pointer to array[getNumCols()] of column upper bounds + virtual const double * getColUpper() const; + + /** Get pointer to array[getNumRows()] of row constraint senses. + <ul> + <li>'L': <= constraint + <li>'E': = constraint + <li>'G': >= constraint + <li>'R': ranged constraint + <li>'N': free constraint + </ul> + */ + virtual const char * getRowSense() const; + + /** Get pointer to array[getNumRows()] of row right-hand sides + <ul> + <li> if getRowSense()[i] == 'L' then + getRightHandSide()[i] == getRowUpper()[i] + <li> if getRowSense()[i] == 'G' then + getRightHandSide()[i] == getRowLower()[i] + <li> if getRowSense()[i] == 'R' then + getRightHandSide()[i] == getRowUpper()[i] + <li> if getRowSense()[i] == 'N' then + getRightHandSide()[i] == 0.0 + </ul> + */ + virtual const double * getRightHandSide() const; + + /** Get pointer to array[getNumRows()] of row ranges. + <ul> + <li> if getRowSense()[i] == 'R' then + getRowRange()[i] == getRowUpper()[i] - getRowLower()[i] + <li> if getRowSense()[i] != 'R' then + getRowRange()[i] is 0.0 + </ul> + */ + virtual const double * getRowRange() const; + + /// Get pointer to array[getNumRows()] of row lower bounds + virtual const double * getRowLower() const; + + /// Get pointer to array[getNumRows()] of row upper bounds + virtual const double * getRowUpper() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + virtual const double * getObjCoefficients() const; + + /** Get pointer to array[getNumCols()] of second + objective function coefficients if loaded before. + */ + virtual const double * getObj2Coefficients() const; + + /// Get objective function sense (1 for min (default), -1 for max) + virtual double getObjSense() const; + + /// Return true if variable is continuous + virtual bool isContinuous(int colIndex) const; + + /// Return true if variable is binary + virtual bool isBinary(int colIndex) const; + + /** Return true if column is integer. + Note: This function returns true if the the column + is binary or a general integer. + */ + virtual bool isInteger(int colIndex) const; + + /// Return true if variable is general integer + virtual bool isIntegerNonBinary(int colIndex) const; + + /// Return true if variable is binary and not fixed at either bound + virtual bool isFreeBinary(int colIndex) const; + + /// Get pointer to row-wise copy of matrix + virtual const CoinPackedMatrix * getMatrixByRow() const; + + /// Get pointer to column-wise copy of matrix + virtual const CoinPackedMatrix * getMatrixByCol() const; + + /// Get solver's value for infinity + virtual double getInfinity() const; + + //@} + + /**@name Solution query methods */ + //@{ + /// Get pointer to array[getNumCols()] of primal variable values + virtual const double * getColSolution() const; + + /// Get pointer to array[getNumRows()] of dual variable values + virtual const double * getRowPrice() const; + + /// Get a pointer to array[getNumCols()] of reduced costs + virtual const double * getReducedCost() const; + + /** Get pointer to array[getNumRows()] of row activity levels (constraint + matrix times the solution vector). */ + virtual const double * getRowActivity() const; + + /// Get objective function value + virtual double getObjValue() const; + + /// Get the current upper/lower bound + virtual double getPrimalBound() const; + + /** Get the number of iterations it took to solve the problem (whatever + ``iteration'' means to the solver). */ + virtual int getIterationCount() const; + + /** Get as many dual rays as the solver can provide. In case of proven + primal infeasibility there should be at least one. + + \note + Implementors of solver interfaces note that + the double pointers in the vector should point to arrays of length + getNumRows() and they should be allocated via new[]. + + \note + Clients of solver interfaces note that + it is the client's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector<double*> getDualRays(int maxNumRays, + bool fullRay = false) const{ + throw CoinError("Error: Function not implemented", + "getDualRays", "OsiSymSolverInterface"); + } + /** Get as many primal rays as the solver can provide. (In case of proven + dual infeasibility there should be at least one.) + + <strong>NOTE for implementers of solver interfaces:</strong> <br> + The double pointers in the vector should point to arrays of length + getNumCols() and they should be allocated via new[]. <br> + + <strong>NOTE for users of solver interfaces:</strong> <br> + It is the user's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector<double*> getPrimalRays(int maxNumRays) const{ + throw CoinError("Error: Function not implemented", + "getPrimalRays", "OsiSymSolverInterface"); + } + + //@} + + //------------------------------------------------------------------------- + /**@name Methods to modify the objective, bounds, and solution + + For functions which take a set of indices as parameters + (\c setObjCoeffSet(), \c setColSetBounds(), \c setRowSetBounds(), + \c setRowSetTypes()), the parameters follow the C++ STL iterator + convention: \c indexFirst points to the first index in the + set, and \c indexLast points to a position one past the last index + in the set. + + */ + //@{ + /** Set an objective function coefficient */ + virtual void setObjCoeff( int elementIndex, double elementValue ); + + /** Set an objective function coefficient for the second objective */ + virtual void setObj2Coeff( int elementIndex, double elementValue ); + + using OsiSolverInterface::setColLower ; + /** Set a single column lower bound. + Use -getInfinity() for -infinity. */ + virtual void setColLower( int elementIndex, double elementValue ); + + using OsiSolverInterface::setColUpper ; + /** Set a single column upper bound. + Use getInfinity() for infinity. */ + virtual void setColUpper( int elementIndex, double elementValue ); + + /** Set a single row lower bound. + Use -getInfinity() for -infinity. */ + virtual void setRowLower( int elementIndex, double elementValue ); + + /** Set a single row upper bound. + Use getInfinity() for infinity. */ + virtual void setRowUpper( int elementIndex, double elementValue ); + + /** Set the type of a single row */ + virtual void setRowType(int index, char sense, double rightHandSide, + double range); + + /// Set the objective function sense. + /// (1 for min (default), -1 for max) + virtual void setObjSense(double s); + + /** Set the primal solution variable values + + colsol[getNumCols()] is an array of values for the primal variables. + These values are copied to memory owned by the solver interface object + or the solver. They will be returned as the result of getColSolution() + until changed by another call to setColSolution() or by a call to any + solver routine. Whether the solver makes use of the solution in any + way is solver-dependent. + */ + virtual void setColSolution(const double *colsol); + + /** Set the a priori upper/lower bound */ + + virtual void setPrimalBound(const double bound); + + /** Set dual solution variable values + + rowprice[getNumRows()] is an array of values for the dual + variables. These values are copied to memory owned by the solver + interface object or the solver. They will be returned as the result of + getRowPrice() until changed by another call to setRowPrice() or by a + call to any solver routine. Whether the solver makes use of the + solution in any way is solver-dependent. + */ + + virtual void setRowPrice(const double * rowprice); + + //@} + + //------------------------------------------------------------------------- + /**@name Methods to set variable type */ + //@{ + + using OsiSolverInterface::setContinuous ; + /** Set the index-th variable to be a continuous variable */ + virtual void setContinuous(int index); + + using OsiSolverInterface::setInteger ; + /** Set the index-th variable to be an integer variable */ + virtual void setInteger(int index); + + + using OsiSolverInterface::setColName ; + virtual void setColName(char **colname); + + //@} + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + /**@name Methods to expand a problem. + + Note that new columns are added as continuous variables. + + */ + //@{ + + using OsiSolverInterface::addCol ; + /** Add a column (primal variable) to the problem. */ + virtual void addCol(const CoinPackedVectorBase& vec, + const double collb, const double colub, + const double obj); + + /** Remove a set of columns (primal variables) from the problem. */ + virtual void deleteCols(const int num, const int * colIndices); + + using OsiSolverInterface::addRow ; + /** Add a row (constraint) to the problem. */ + virtual void addRow(const CoinPackedVectorBase& vec, + const double rowlb, const double rowub); + /** */ + virtual void addRow(const CoinPackedVectorBase& vec, + const char rowsen, const double rowrhs, + const double rowrng); + + /** Delete a set of rows (constraints) from the problem. */ + virtual void deleteRows(const int num, const int * rowIndices); + + //@} + + //--------------------------------------------------------------------------- + + /**@name Methods to input a problem */ + //@{ + + virtual void loadProblem(); + + /** Load in an problem by copying the arguments (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>rowub</code>: all rows have upper bound infinity + <li> <code>rowlb</code>: all rows have lower bound -infinity + <li> <code>obj</code>: all variables have 0 objective coefficient + </ul> + */ + virtual void loadProblem(const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by lower and upper bounds). + For default values see the previous method. + + \warning + The arguments passed to this method will be + freed using the C++ <code>delete</code> and <code>delete[]</code> + functions. + */ + virtual void assignProblem(CoinPackedMatrix*& matrix, + double*& collb, double*& colub, double*& obj, + double*& rowlb, double*& rowub); + + /** Load in an problem by copying the arguments (the constraints on the + rows are given by sense/rhs/range triplets). If a pointer is 0 then the + following values are the default: + <ul> + <li> <code>colub</code>: all columns have upper bound infinity + <li> <code>collb</code>: all columns have lower bound 0 + <li> <code>obj</code>: all variables have 0 objective coefficient + <li> <code>rowsen</code>: all rows are >= + <li> <code>rowrhs</code>: all right hand sides are 0 + <li> <code>rowrng</code>: 0 for the ranged rows + </ul> + */ + virtual void loadProblem(const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by sense/rhs/range triplets). For + default values see the previous method. + + \warning + The arguments passed to this method will be + freed using the C++ <code>delete</code> and <code>delete[]</code> + functions. + */ + virtual void assignProblem(CoinPackedMatrix*& matrix, + double*& collb, double*& colub, double*& obj, + char*& rowsen, double*& rowrhs, + double*& rowrng); + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const double* rowlb, const double* rowub); + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex * start, const int* index, + const double* value, + const double* collb, const double* colub, + const double* obj, + const char* rowsen, const double* rowrhs, + const double* rowrng); + + /** Write the problem in MPS format to the specified file. + + If objSense is non-zero, a value of -1.0 causes the problem to be + written with a maximization objective; +1.0 forces a minimization + objective. If objSense is zero, the choice is left to implementation. + */ + virtual void writeMps(const char *filename, + const char *extension = "mps", + double objSense=0.0) const; + + void parseCommandLine(int argc, char **argv); + + using OsiSolverInterface::readMps ; + virtual int readMps(const char * infile, const char *extension = "mps"); + + virtual int readGMPL(const char * modelFile, const char * dataFile=NULL); + + void findInitialBounds(); + + int createPermanentCutPools(); + + //@} + + //--------------------------------------------------------------------------- + + enum keepCachedFlag { + /// discard all cached data (default) + KEEPCACHED_NONE = 0, + /// column information: objective values, lower and upper bounds, variable types + KEEPCACHED_COLUMN = 1, + /// row information: right hand sides, ranges and senses, lower and upper bounds for row + KEEPCACHED_ROW = 2, + /// problem matrix: matrix ordered by column and by row + KEEPCACHED_MATRIX = 4, + /// LP solution: primal and dual solution, reduced costs, row activities + KEEPCACHED_RESULTS = 8, + /// only discard cached LP solution + KEEPCACHED_PROBLEM = KEEPCACHED_COLUMN | KEEPCACHED_ROW | KEEPCACHED_MATRIX, + /// keep all cached data (similar to getMutableLpPtr()) + KEEPCACHED_ALL = KEEPCACHED_PROBLEM | KEEPCACHED_RESULTS, + /// free only cached column and LP solution information + FREECACHED_COLUMN = KEEPCACHED_PROBLEM & ~KEEPCACHED_COLUMN, + /// free only cached row and LP solution information + FREECACHED_ROW = KEEPCACHED_PROBLEM & ~KEEPCACHED_ROW, + /// free only cached matrix and LP solution information + FREECACHED_MATRIX = KEEPCACHED_PROBLEM & ~KEEPCACHED_MATRIX, + /// free only cached LP solution information + FREECACHED_RESULTS = KEEPCACHED_ALL & ~KEEPCACHED_RESULTS + }; + + ///@name Constructors and destructors + //@{ + /// Default Constructor + OsiSymSolverInterface(); + + /** Clone + + The result of calling clone(false) is defined to be equivalent to + calling the default constructor OsiSolverInterface(). + */ + virtual OsiSolverInterface * clone(bool copyData = true) const; + + /// Copy constructor + OsiSymSolverInterface(const OsiSymSolverInterface &); + + /// Assignment operator + OsiSymSolverInterface & operator=(const OsiSymSolverInterface& rhs); + + /// Destructor + virtual ~OsiSymSolverInterface (); + + /** Reset the solver interface. + + A call to reset() returns the solver interface to the same state as + it would have if it had just been constructed by calling the default + constructor OsiSolverInterface(). + */ + virtual void reset(); + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected methods + //@{ + /** Apply a row cut (append to the constraint matrix). */ + virtual void applyRowCut( const OsiRowCut & rc ); + + /** Apply a column cut (adjust the bounds of one or more variables). */ + virtual void applyColCut( const OsiColCut & cc ); + + /** Set OsiSolverInterface object state for default constructor + + This routine establishes the initial values of data fields in the + OsiSolverInterface object when the object is created using the + default constructor. + */ + + void setInitialData(); + //@} + +private: + + /// The real work of the constructor + void gutsOfConstructor(); + + /// The real work of the destructor + void gutsOfDestructor(); + + /// free cached column rim vectors + void freeCachedColRim(); + + /// free cached row rim vectors + void freeCachedRowRim(); + + /// free cached result vectors + void freeCachedResults(); + + /// free cached matrices + void freeCachedMatrix(); + + /// free all cached data (except specified entries, see getLpPtr()) + void freeCachedData( int keepCached = KEEPCACHED_NONE ); + + /// free all allocated memory + void freeAllMemory(); + + /**@name Private member data */ + //@{ + /// The pointer to the SYMPHONY problem environment + sym_environment *env_; + //@} + + /// Pointer to objective vector + mutable double *obj_; + + /// Pointer to second objective vector to be used in bicriteria solver + mutable double *obj2_; + + /// Pointer to dense vector of variable lower bounds + mutable double *collower_; + + /// Pointer to dense vector of variable lower bounds + mutable double *colupper_; + + /// Pointer to dense vector of variable lower bounds + mutable double *colredcost_; + + /// Pointer to dense vector of row sense indicators + mutable char *rowsense_; + + /// Pointer to dense vector of row right-hand side values + mutable double *rhs_; + + /** Pointer to dense vector of slack upper bounds for range constraints + (undefined for non-range rows) + */ + mutable double *rowrange_; + + /// Pointer to dense vector of row lower bounds + mutable double *rowlower_; + + /// Pointer to dense vector of row upper bounds + mutable double *rowupper_; + + /// Pointer to dense vector of row prices + mutable double *rowprice_; + + /// Pointer to primal solution vector + mutable double *colsol_; + + /// Pointer to row activity (slack) vector + mutable double *rowact_; + + /// Pointer to row-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByRow_; + + /// Pointer to row-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByCol_; + +}; + +//############################################################################# +/** A function that tests the methods in the OsiSymSolverInterface class. */ +void OsiSymSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); + +#endif diff --git a/thirdparty/linux/include/coin/OsiSymSolverParameters.hpp b/thirdparty/linux/include/coin/OsiSymSolverParameters.hpp new file mode 100644 index 0000000..041acce --- /dev/null +++ b/thirdparty/linux/include/coin/OsiSymSolverParameters.hpp @@ -0,0 +1,64 @@ +/*===========================================================================*/ +/* */ +/* This file is part of the SYMPHONY Branch, Cut, and Price Callable */ +/* Library. */ +/* */ +/* SYMPHONY was jointly developed by Ted Ralphs (tkralphs@lehigh.edu) and */ +/* Laci Ladanyi (ladanyi@us.ibm.com). */ +/* */ +/* (c) Copyright 2004-2006 Ted Ralphs and Lehigh University. */ +/* All Rights Reserved. */ +/* */ +/* The authors of this file are Menal Guzelsoy and Ted Ralphs */ +/* */ +/* This software is licensed under the Eclipse Public License. Please see */ +/* accompanying file for terms. */ +/* */ +/*===========================================================================*/ + +#ifndef OsiSymSolverParameters_hpp +#define OsiSymSolverParameters_hpp + +enum OsiSymIntParam { + /** This controls the level of output */ + OsiSymMaxActiveNodes, + OsiSymVerbosity, + OsiSymNodeLimit, + OsiSymFindFirstFeasible, + OsiSymSearchStrategy, + OsiSymUsePermanentCutPools, + OsiSymKeepWarmStart, + OsiSymDoReducedCostFixing, + OsiSymMCFindSupportedSolutions, + OsiSymSensitivityAnalysis, + OsiSymRandomSeed, + OsiSymDivingStrategy, + OsiSymDivingK, + OsiSymDivingThreshold, + OsiSymTrimWarmTree, + OsiSymGenerateCglGomoryCuts, + OsiSymGenerateCglKnapsackCuts, + OsiSymGenerateCglOddHoleCuts, + OsiSymGenerateCglProbingCuts, + OsiSymGenerateCglFlowAndCoverCuts, + OsiSymGenerateCglRoundingCuts, + OsiSymGenerateCglLiftAndProjectCuts, + OsiSymGenerateCglCliqueCuts +}; + +enum OsiSymDblParam { + /** The granularity is the actual minimum difference in objective function + value for two solutions that actually have do different objective + function values. For integer programs with integral objective function + coefficients, this would be 1, for instance. */ + OsiSymGranularity, + OsiSymTimeLimit, + OsiSymGapLimit, + OsiSymUpperBound, + OsiSymLowerBound +}; + +enum OsiSymStrParam { +}; + +#endif diff --git a/thirdparty/linux/include/coin/OsiUnitTests.hpp b/thirdparty/linux/include/coin/OsiUnitTests.hpp new file mode 100644 index 0000000..fbb4fc1 --- /dev/null +++ b/thirdparty/linux/include/coin/OsiUnitTests.hpp @@ -0,0 +1,374 @@ +// Copyright (C) 2010 +// All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file OsiUnitTests.hpp + + Utility methods for OSI unit tests. +*/ + +#ifndef OSISOLVERINTERFACETEST_HPP_ +#define OSISOLVERINTERFACETEST_HPP_ + +#include <cstdio> +#include <cstdlib> +#include <iostream> +#include <string> +#include <sstream> +#include <vector> +#include <list> +#include <map> + +class OsiSolverInterface; +class CoinPackedVectorBase; + +/** A function that tests that a lot of problems given in MPS files (mostly the NETLIB problems) solve properly with all the specified solvers. + * + * The routine creates a vector of NetLib problems (problem name, objective, + * various other characteristics), and a vector of solvers to be tested. + * + * Each solver is run on each problem. The run is deemed successful if the + * solver reports the correct problem size after loading and returns the + * correct objective value after optimization. + + * If multiple solvers are available, the results are compared pairwise against + * the results reported by adjacent solvers in the solver vector. Due to + * limitations of the volume solver, it must be the last solver in vecEmptySiP. + */ +void OsiSolverInterfaceMpsUnitTest + (const std::vector<OsiSolverInterface*> & vecEmptySiP, + const std::string& mpsDir); + +/** A function that tests the methods in the OsiSolverInterface class. + * Some time ago, if this method is compiled with optimization, + * the compilation took 10-15 minutes and the machine pages (has 256M core memory!)... + */ +void OsiSolverInterfaceCommonUnitTest + (const OsiSolverInterface* emptySi, + const std::string& mpsDir, + const std::string& netlibDir); + +/** A function that tests the methods in the OsiColCut class. */ +void OsiColCutUnitTest + (const OsiSolverInterface * baseSiP, + const std::string & mpsDir); + +/** A function that tests the methods in the OsiRowCut class. */ +void OsiRowCutUnitTest + (const OsiSolverInterface * baseSiP, + const std::string & mpsDir); + +/** A function that tests the methods in the OsiRowCutDebugger class. */ +void OsiRowCutDebuggerUnitTest + (const OsiSolverInterface * siP, + const std::string & mpsDir); + +/** A function that tests the methods in the OsiCuts class. */ +void OsiCutsUnitTest(); + +/// A namespace so we can define a few `global' variables to use during tests. +namespace OsiUnitTest { + +class TestOutcomes; + +/*! \brief Verbosity level of unit tests + + 0 (default) for minimal output; larger numbers produce more output +*/ +extern unsigned int verbosity; + +/*! \brief Behaviour on failing a test + + - 0 (= default) continue + - 1 press any key to continue + - 2 stop with abort() +*/ +extern unsigned int haltonerror; + +/*! \brief Test outcomes + + A global TestOutcomes object to store test outcomes during the run of the unit test + for an OSI. + */ +extern TestOutcomes outcomes; + +/*! \brief Print an error message + + Formatted as "XxxSolverInterface testing issue: message" where Xxx is the string + provided as \p solverName. + + Flushes std::cout before printing to std::cerr. +*/ +void failureMessage(const std::string &solverName, + const std::string &message) ; +/// \overload +void failureMessage(const OsiSolverInterface &si, + const std::string &message) ; + +/*! \brief Print an error message, specifying the test name and condition + + Formatted as "XxxSolverInterface testing issue: testname failed: testcond" where + Xxx is the OsiStrParam::OsiSolverName parameter of the \p si. + Flushes std::cout before printing to std::cerr. +*/ +void failureMessage(const std::string &solverName, + const std::string &testname, const std::string &testcond) ; + +/// \overload +void failureMessage(const OsiSolverInterface &si, + const std::string &testname, const std::string &testcond) ; + +/*! \brief Print a message. + + Prints the message as given. Flushes std::cout before printing to std::cerr. +*/ +void testingMessage(const char *const msg) ; + +/*! \brief Utility method to check equality + + Tests for equality using CoinRelFltEq with tolerance \p tol. Understands the + notion of solver infinity and obtains the value for infinity from the solver + interfaces supplied as parameters. +*/ +bool equivalentVectors(const OsiSolverInterface * si1, + const OsiSolverInterface * si2, + double tol, const double * v1, const double * v2, int size) ; + +/*! \brief Compare two problems for equality + + Compares the problems held in the two solvers: constraint matrix, row and column + bounds, column type, and objective. Rows are checked using upper and lower bounds + and using sense, bound, and range. +*/ +bool compareProblems(OsiSolverInterface *osi1, OsiSolverInterface *osi2) ; + +/*! \brief Compare a packed vector with an expanded vector + + Checks that all values present in the packed vector are present in the full vector + and checks that there are no extra entries in the full vector. Uses CoinRelFltEq + with the default tolerance. +*/ +bool isEquivalent(const CoinPackedVectorBase &pv, int n, const double *fv) ; + +/*! \brief Process command line parameters. + + An unrecognised keyword which is not in the \p ignorekeywords map will trigger the + help message and a return value of false. For each keyword in \p ignorekeywords, you + can specify the number of following parameters that should be ignored. + + This should be replaced with the one of the standard CoinUtils parameter mechanisms. + */ +bool processParameters (int argc, const char **argv, + std::map<std::string,std::string>& parms, + const std::map<std::string,int>& ignorekeywords = std::map<std::string,int>()); + +/// A single test outcome record. +class TestOutcome { + public: + /// Test result + typedef enum { + NOTE = 0, + PASSED = 1, + WARNING = 2, + ERROR = 3, + LAST = 4 + } SeverityLevel; + /// Print strings for SeverityLevel + static std::string SeverityLevelName[LAST]; + /// Name of component under test + std::string component; + /// Name of test + std::string testname; + /// Condition being tested + std::string testcond; + /// Test result + SeverityLevel severity; + /// Set to true if problem is expected + bool expected; + /// Name of code file where test executed + std::string filename; + /// Line number in code file where test executed + int linenumber; + /// Standard constructor + TestOutcome(const std::string& comp, const std::string& tst, + const char* cond, SeverityLevel sev, + const char* file, int line, bool exp = false) + : component(comp),testname(tst),testcond(cond),severity(sev), + expected(exp),filename(file),linenumber(line) + { } + /// Print the test outcome + void print() const; +}; + +/// Utility class to maintain a list of test outcomes. +class TestOutcomes : public std::list<TestOutcome> { + public: + /// Add an outcome to the list + void add(std::string comp, std::string tst, const char* cond, + TestOutcome::SeverityLevel sev, const char* file, int line, + bool exp = false) + { push_back(TestOutcome(comp,tst,cond,sev,file,line,exp)); } + + /*! \brief Add an outcome to the list + + Get the component name from the solver interface. + */ + void add(const OsiSolverInterface& si, std::string tst, const char* cond, + TestOutcome::SeverityLevel sev, const char* file, int line, + bool exp = false); + /// Print the list of outcomes + void print() const; + /*! \brief Count total and expected outcomes at given severity level + + Given a severity level, walk the list of outcomes and count the total number + of outcomes at this severity level and the number expected. + */ + void getCountBySeverity(TestOutcome::SeverityLevel sev, + int& total, int& expected) const; +}; + +/// Convert parameter to a string (stringification) +#define OSIUNITTEST_QUOTEME_(x) #x +/// Convert to string with one level of expansion of the parameter +#define OSIUNITTEST_QUOTEME(x) OSIUNITTEST_QUOTEME_(x) + +template <typename Component> +bool OsiUnitTestAssertSeverityExpected( + bool condition, const char * condition_str, const char *filename, + int line, const Component& component, const std::string& testname, + TestOutcome::SeverityLevel severity, bool expected) +{ + if (condition) { + OsiUnitTest::outcomes.add(component, testname, condition_str, + OsiUnitTest::TestOutcome::PASSED, filename, line, false); + if (OsiUnitTest::verbosity >= 2) { + std::ostringstream successmsg; + successmsg << __FILE__ << ":" << __LINE__ << ": " << testname + << " (condition \'" << condition_str << "\') passed.\n"; + OsiUnitTest::testingMessage(successmsg.str().c_str()); + } + return true; + } + OsiUnitTest::outcomes.add(component, testname, condition_str, + severity, filename, line, expected); + OsiUnitTest::failureMessage(component, testname, condition_str); + switch (OsiUnitTest::haltonerror) { + case 2: + { if (severity >= OsiUnitTest::TestOutcome::ERROR ) std::abort(); break; } + case 1: + { std::cout << std::endl << "press any key to continue..." << std::endl; + std::getchar(); + break ; } + default: ; + } + return false; +} + +/// Add a test outcome to the list held in OsiUnitTest::outcomes +#define OSIUNITTEST_ADD_OUTCOME(component,testname,testcondition,severity,expected) \ + OsiUnitTest::outcomes.add(component,testname,testcondition,severity,\ + __FILE__,__LINE__,expected) +/*! \brief Test for a condition and record the result + + Test \p condition and record the result in OsiUnitTest::outcomes. + If it succeeds, record the result as OsiUnitTest::TestOutcome::PASSED and print + a message for OsiUnitTest::verbosity >= 2. + If it fails, record the test as failed with \p severity and \p expected and + react as specified by OsiUnitTest::haltonerror. + + \p failurecode is executed when failure is not fatal. +*/ +#define OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition,failurecode,component,\ + testname, severity, expected) \ +{ \ + if (!OsiUnitTestAssertSeverityExpected(condition, #condition, \ + __FILE__, __LINE__, component, testname, severity, expected)) { \ + failurecode; \ + } \ +} + +/*! \brief Perform a test with severity OsiUnitTest::TestOutcome::ERROR, failure not + expected. +*/ +#define OSIUNITTEST_ASSERT_ERROR(condition, failurecode, component, testname) \ + OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition,failurecode,component,testname,\ + OsiUnitTest::TestOutcome::ERROR,false) + +/*! \brief Perform a test with severity OsiUnitTest::TestOutcome::WARNING, failure + not expected. +*/ +#define OSIUNITTEST_ASSERT_WARNING(condition, failurecode, component, testname) \ + OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition,failurecode,component,testname,\ + OsiUnitTest::TestOutcome::WARNING,false) + +/*! \brief Perform a test surrounded by a try/catch block + + \p trycode is executed in a try/catch block; if there's no throw the test is deemed + to have succeeded and is recorded in OsiUnitTest::outcomes with status + OsiUnitTest::TestOutcome::PASSED. If the \p trycode throws a CoinError, the failure + is recorded with status \p severity and \p expected and the value of + OsiUnitTest::haltonerror is consulted. If the failure is not fatal, \p catchcode is + executed. If any other error is thrown, the failure is recorded as for a CoinError + and \p catchcode is executed (haltonerror is not consulted). +*/ +#define OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname,\ + severity, expected) \ +{ \ + try { \ + trycode; \ + OSIUNITTEST_ADD_OUTCOME(component,testname,#trycode " did not throw exception",\ + OsiUnitTest::TestOutcome::PASSED,false); \ + if (OsiUnitTest::verbosity >= 2) { \ + std::string successmsg( __FILE__ ":" OSIUNITTEST_QUOTEME(__LINE__) ": "); \ + successmsg = successmsg + testname; \ + successmsg = successmsg + " (code \'" #trycode "\') did not throw exception"; \ + successmsg = successmsg + ".\n" ; \ + OsiUnitTest::testingMessage(successmsg.c_str()); \ + } \ + } catch (CoinError& e) { \ + std::stringstream errmsg; \ + errmsg << #trycode " threw CoinError: " << e.message(); \ + if (e.className().length() > 0) \ + errmsg << " in " << e.className(); \ + if (e.methodName().length() > 0) \ + errmsg << " in " << e.methodName(); \ + if (e.lineNumber() >= 0) \ + errmsg << " at " << e.fileName() << ":" << e.lineNumber(); \ + OSIUNITTEST_ADD_OUTCOME(component,testname,errmsg.str().c_str(),\ + severity,expected); \ + OsiUnitTest::failureMessage(component,testname,errmsg.str().c_str()); \ + switch(OsiUnitTest::haltonerror) { \ + case 2: \ + { if (severity >= OsiUnitTest::TestOutcome::ERROR) abort(); break; } \ + case 1: \ + { std::cout << std::endl << "press any key to continue..." << std::endl; \ + getchar(); \ + break ; } \ + default: ; \ + } \ + catchcode; \ + } catch (...) { \ + std::string errmsg; \ + errmsg = #trycode; \ + errmsg = errmsg + " threw unknown exception"; \ + OSIUNITTEST_ADD_OUTCOME(component,testname,errmsg.c_str(),severity,false); \ + OsiUnitTest::failureMessage(component,testname,errmsg.c_str()); \ + catchcode; \ + } \ +} + +/*! \brief Perform a try/catch test with severity OsiUnitTest::TestOutcome::ERROR, + failure not expected. +*/ +#define OSIUNITTEST_CATCH_ERROR(trycode, catchcode, component, testname) \ + OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname, OsiUnitTest::TestOutcome::ERROR, false) + +/*! \brief Perform a try/catch test with severity OsiUnitTest::TestOutcome::WARNING, + failure not expected. +*/ +#define OSIUNITTEST_CATCH_WARNING(trycode, catchcode, component, testname) \ + OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname, OsiUnitTest::TestOutcome::WARNING, false) + +} // end namespace OsiUnitTest + +#endif /*OSISOLVERINTERFACETEST_HPP_*/ diff --git a/thirdparty/linux/include/coin/SymConfig.h b/thirdparty/linux/include/coin/SymConfig.h new file mode 100644 index 0000000..d3c548e --- /dev/null +++ b/thirdparty/linux/include/coin/SymConfig.h @@ -0,0 +1,19 @@ +/* include/config_sym.h. Generated by configure. */ +/* include/config_sym.h.in. */ + +#ifndef __CONFIG_SYM_H__ +#define __CONFIG_SYM_H__ + +/* Version number of project */ +#define SYMPHONY_VERSION "5.6.10" + +/* Major Version number of project */ +#define SYMPHONY_VERSION_MAJOR 5 + +/* Minor Version number of project */ +#define SYMPHONY_VERSION_MINOR 6 + +/* Release Version number of project */ +#define SYMPHONY_VERSION_RELEASE 10 + +#endif diff --git a/thirdparty/linux/include/coin/SymWarmStart.hpp b/thirdparty/linux/include/coin/SymWarmStart.hpp new file mode 100644 index 0000000..74089d1 --- /dev/null +++ b/thirdparty/linux/include/coin/SymWarmStart.hpp @@ -0,0 +1,72 @@ +/*===========================================================================*/ +/* */ +/* This file is part of the SYMPHONY Branch, Cut, and Price Callable */ +/* Library. */ +/* */ +/* SYMPHONY was jointly developed by Ted Ralphs (tkralphs@lehigh.edu) and */ +/* Laci Ladanyi (ladanyi@us.ibm.com). */ +/* */ +/* (c) Copyright 2004-2006 Ted Ralphs and Lehigh University. */ +/* All Rights Reserved. */ +/* */ +/* The authors of this file are Menal Guzelsoy and Ted Ralphs */ +/* */ +/* This software is licensed under the Eclipse Public License. Please see */ +/* accompanying file for terms. */ +/* */ +/*===========================================================================*/ + +#ifndef SymWarmStart_H +#define SymWarmStart_H + +#include "CoinWarmStart.hpp" + +typedef struct WARM_START_DESC warm_start_desc; + +//############################################################################# + +class SymWarmStart : public CoinWarmStart +{ + +public: + + /* Default constructor. Will do nothing! */ + SymWarmStart(){} + + /* Initialize the warmStart_ using the given warm start. If dominate + WarmStart is set, then, SymWarmStart will take the control of the + given description, otherwise, will copy everything. + */ + SymWarmStart(warm_start_desc * ws); + + /*Get the warmStart info from a file*/ + SymWarmStart(char *f); + + /* Copy constructor */ + SymWarmStart(const SymWarmStart & symWS); + + /* Destructor */ + virtual ~SymWarmStart(); + + /* Clone the warmstart */ + virtual CoinWarmStart * clone() const; + + /* Get the pointer to the loaded warmStart_ */ + virtual warm_start_desc * getCopyOfWarmStartDesc(); + + /* Move the pointer to the rootnode of the warmStart to another + node which will change the underlying tree + */ + // virtual void setRoot(bc_node *root) {} //FIX_ME! Ask Prof. Ralphs. + + /* Write the current warm start info to a file */ + virtual int writeToFile(char * f); + +private: + + /* Private warm start desc. to keep everything */ + warm_start_desc *warmStart_; + +}; + +#endif diff --git a/thirdparty/linux/include/coin/symphony.h b/thirdparty/linux/include/coin/symphony.h new file mode 100644 index 0000000..d9ddace --- /dev/null +++ b/thirdparty/linux/include/coin/symphony.h @@ -0,0 +1,327 @@ +/*===========================================================================*/ +/* */ +/* This file is part of the SYMPHONY MILP Solver Framework. */ +/* */ +/* SYMPHONY was jointly developed by Ted Ralphs (ted@lehigh.edu) and */ +/* Laci Ladanyi (ladanyi@us.ibm.com). */ +/* */ +/* (c) Copyright 2005-2015 Ted Ralphs. All Rights Reserved. */ +/* */ +/* This software is licensed under the Eclipse Public License. Please see */ +/* accompanying file for terms. */ +/* */ +/*===========================================================================*/ + +#ifndef _SYM_API_H +#define _SYM_API_H + +#define COMPILING_FOR_MASTER + +#ifdef PROTO +#undef PROTO +#endif +#define PROTO(x) x + +/***************************************************************************** + ***************************************************************************** + ************* ********** + ************* Return Values ********** + ************* ********** + ***************************************************************************** + *****************************************************************************/ + +/*----------------------- Global return codes -------------------------------*/ +#define FUNCTION_TERMINATED_NORMALLY 0 +#define FUNCTION_TERMINATED_ABNORMALLY -1 +#define ERROR__USER -100 + +/*-------------- Return codes for sym_parse_comand_line() -------------------*/ +#define ERROR__OPENING_PARAM_FILE -110 +#define ERROR__PARSING_PARAM_FILE -111 + +/*----------------- Return codes for sym_load_problem() ---------------------*/ +#define ERROR__READING_GMPL_FILE -120 +#define ERROR__READING_WARM_START_FILE -121 +#define ERROR__READING_MPS_FILE -122 +#define ERROR__READING_LP_FILE -123 + +/*-------------------- Return codes for sym_solve() -------------------------*/ +#define TM_NO_PROBLEM 225 +#define TM_NO_SOLUTION 226 +#define TM_OPTIMAL_SOLUTION_FOUND 227 +#define TM_TIME_LIMIT_EXCEEDED 228 +#define TM_NODE_LIMIT_EXCEEDED 229 +#define TM_ITERATION_LIMIT_EXCEEDED 230 +#define TM_TARGET_GAP_ACHIEVED 231 +#define TM_FOUND_FIRST_FEASIBLE 232 +#define TM_FINISHED 233 +#define TM_UNFINISHED 234 +#define TM_FEASIBLE_SOLUTION_FOUND 235 +#define TM_SIGNAL_CAUGHT 236 +#define TM_UNBOUNDED 237 +#define PREP_OPTIMAL_SOLUTION_FOUND 238 +#define PREP_NO_SOLUTION 239 +#define TM_ERROR__NO_BRANCHING_CANDIDATE -250 +#define TM_ERROR__ILLEGAL_RETURN_CODE -251 +#define TM_ERROR__NUMERICAL_INSTABILITY -252 +#define TM_ERROR__COMM_ERROR -253 +#define TM_ERROR__USER -275 +#define PREP_ERROR -276 + +/***************************************************************************** + ***************************************************************************** + ************* ********** + ************* General Constants ********** + ************* ********** + ***************************************************************************** + *****************************************************************************/ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef ANYONE +#define ANYONE -1 +#endif +#ifndef ANYTHING +#define ANYTHING -1 +#endif + +#define DSIZE sizeof(double) +#define ISIZE sizeof(int) +#define CSIZE sizeof(char) + +#ifndef BITSPERBYTE +#define BITSPERBYTE 8 +#endif +#ifndef BITS +#define BITS(type) (BITSPERBYTE * (int)sizeof (type)) +#endif + +#ifdef HIBITI +#undef HIBITI +#endif +#define HIBITI (1U << (BITS(int) - 1)) +#ifdef MAXINT +#undef MAXINT +#endif +#define MAXINT ((int)(~(HIBITI))) +#ifdef MAXDOUBLE +#undef MAXDOUBLE +#endif +#define MAXDOUBLE 1.79769313486231570e+308 + +#define SYM_INFINITY 1e20 + +#define BIG_DBL 1e40 + +#define SYM_MINIMIZE 0 +#define SYM_MAXIMIZE 1 + +#define MAX_NAME_SIZE 255 + +/*--------------------- return values for user-written functions ------------*/ +#define USER_ERROR -5 +#define USER_SUCCESS -4 +#define USER_NO_PP -3 +#define USER_AND_PP -2 +#define USER_DEFAULT -1 + +/*------------ search order options for multi-criteria problems -------------*/ +#define MC_FIFO 0 +#define MC_LIFO 1 + +/*------------ warm_starting options for multi-criteria problems -------------*/ +#define MC_WS_UTOPIA_FIRST 0 +#define MC_WS_UTOPIA_BOTH_FIXED 1 +#define MC_WS_UTOPIA_BOTH 2 +#define MC_WS_BEST_CLOSE 3 + +/*------------------------ compare_candidates -------------------------------*/ +#define BIGGEST_DIFFERENCE_OBJ 0 +#define LOWEST_LOW_OBJ 1 +#define HIGHEST_LOW_OBJ 2 +#define LOWEST_HIGH_OBJ 3 +#define HIGHEST_HIGH_OBJ 4 +#define HIGH_LOW_COMBINATION 9 + +/*--------------------------- select_child ----------------------------------*/ +#define PREFER_LOWER_OBJ_VALUE 0 +#define PREFER_HIGHER_OBJ_VALUE 1 + +/*-------------------- generate_cuts_in_lp defaults -------------------------*/ +#define GENERATE_CGL_CUTS 20 +#define DO_NOT_GENERATE_CGL_CUTS 21 + +/*-------------------- xxx_cuts_generation_levels ---------------------------*/ +#define DO_NOT_GENERATE -1 +#define GENERATE_DEFAULT 0 +#define GENERATE_IF_IN_ROOT 1 +#define GENERATE_ONLY_IN_ROOT 2 +#define GENERATE_ALWAYS 3 +#define GENERATE_PERIODICALLY 4 + +/*------------------------- node selection rules ----------------------------*/ +#define LOWEST_LP_FIRST 0 +#define HIGHEST_LP_FIRST 1 +#define BREADTH_FIRST_SEARCH 2 +#define DEPTH_FIRST_SEARCH 3 +#define BEST_FIRST_SEARCH 4 +#define DEPTH_FIRST_THEN_BEST_FIRST 5 + +/*-------------------------- diving_strategy --------------------------------*/ +#define BEST_ESTIMATE 0 +#define COMP_BEST_K 1 +#define COMP_BEST_K_GAP 2 + +/*--------------- parameter values for feasibility pump heuristic -----------*/ +#define SYM_FEAS_PUMP_DEFAULT 1 /* use fp using the default rules */ +#define SYM_FEAS_PUMP_REPEATED 2 /* use fp till the end of solve */ +#define SYM_FEAS_PUMP_TILL_SOL 3 /* use fp till a solution is found */ +#define SYM_FEAS_PUMP_DISABLE -1 /* dont use fp */ + +typedef struct MIPDESC MIPdesc; +typedef struct WARM_START_DESC warm_start_desc; +typedef struct SYM_ENVIRONMENT sym_environment; + +/*===========================================================================*/ +/*===================== Interface functions (master.c) ======================*/ +/*===========================================================================*/ + +void sym_version PROTO((void)); +sym_environment *sym_open_environment PROTO((void)); +int sym_set_defaults PROTO((sym_environment *env)); +int sym_parse_command_line PROTO((sym_environment *env, int argc, + char **argv)); +int sym_set_user_data PROTO((sym_environment *env, void *user)); +int sym_get_user_data PROTO((sym_environment *env, void **user)); +int sym_read_mps PROTO((sym_environment *env, char *infile)); +int sym_read_lp PROTO((sym_environment *env, char *infile)); +int sym_read_gmpl PROTO((sym_environment *env, char *modelfile, + char *datafile)); +int sym_write_mps PROTO((sym_environment *env, char *infile)); +int sym_write_lp PROTO((sym_environment *env, char *infile)); + +int sym_load_problem PROTO((sym_environment *env)); +int sym_find_initial_bounds PROTO((sym_environment *env)); + +int sym_solve PROTO((sym_environment *env)); +int sym_warm_solve PROTO((sym_environment *env)); +int sym_mc_solve PROTO((sym_environment *env)); + +int sym_create_permanent_cut_pools PROTO((sym_environment *env, int *cp_num)); +int sym_close_environment PROTO((sym_environment *env)); +int sym_explicit_load_problem PROTO((sym_environment *env, int numcols, + int numrows, int *start, int *index, + double *value, double *collb, + double *colub, char *is_int, double *obj, + double *obj2, char *rowsen, + double *rowrhs, double *rowrng, + char make_copy)); + +int sym_is_abandoned PROTO((sym_environment *env)); +int sym_is_proven_optimal PROTO((sym_environment *env)); +int sym_is_proven_primal_infeasible PROTO((sym_environment *env)); +int sym_is_iteration_limit_reached PROTO((sym_environment *env)); +int sym_is_time_limit_reached PROTO((sym_environment *env)); +int sym_is_target_gap_achieved PROTO((sym_environment *env)); + +int sym_get_status PROTO((sym_environment *env)); +int sym_get_num_cols PROTO((sym_environment *env, int *numcols)); +int sym_get_num_rows PROTO((sym_environment *env, int *numrows)); +int sym_get_num_elements PROTO((sym_environment *env, int *numelems)); +int sym_get_col_lower PROTO((sym_environment *env, double *collb)); +int sym_get_col_upper PROTO((sym_environment *env, double *colub)); +int sym_get_row_sense PROTO((sym_environment *env, char *rowsen)); +int sym_get_rhs PROTO((sym_environment *env, double *rowrhs)); +int sym_get_matrix PROTO((sym_environment *env, int *nz, int *matbeg, + int *matind, double *matval)); +int sym_get_row_range PROTO((sym_environment *env, double *rowrng)); +int sym_get_row_lower PROTO((sym_environment *env, double *rowlb)); +int sym_get_row_upper PROTO((sym_environment *env, double *rowub)); +int sym_get_obj_coeff PROTO((sym_environment *env, double *obj)); +int sym_get_obj2_coeff PROTO((sym_environment *env, double *obj2)); +int sym_get_obj_sense PROTO((sym_environment *env, int *sense)); + +int sym_is_continuous PROTO((sym_environment *env, int index, int *value)); +int sym_is_binary PROTO((sym_environment *env, int index, int *value)); +int sym_is_integer PROTO((sym_environment *env, int index, char *value)); + +double sym_get_infinity PROTO(()); + +int sym_get_col_solution PROTO((sym_environment *env, double *colsol)); +int sym_get_sp_size PROTO((sym_environment *env, int *size)); +int sym_get_sp_solution PROTO((sym_environment *env, int index, + double *colsol, double *objval)); +int sym_get_row_activity PROTO((sym_environment *env, double *rowact)); +int sym_get_obj_val PROTO((sym_environment *env, double *objval)); +int sym_get_primal_bound PROTO((sym_environment *env, double *ub)); +int sym_get_iteration_count PROTO((sym_environment *env, int *numnodes)); + +int sym_set_obj_coeff PROTO((sym_environment *env, int index, double value)); +int sym_set_obj2_coeff PROTO((sym_environment *env, int index, double value)); +int sym_set_col_lower PROTO((sym_environment *env, int index, double value)); +int sym_set_col_upper PROTO((sym_environment *env, int index, double value)); +int sym_set_row_lower PROTO((sym_environment *env, int index, double value)); +int sym_set_row_upper PROTO((sym_environment *env, int index, double value)); +int sym_set_row_type PROTO((sym_environment *env, int index, char rowsense, + double rowrhs, double rowrng)); +int sym_set_obj_sense PROTO((sym_environment *env, int sense)); +int sym_set_col_solution PROTO((sym_environment *env, double * colsol)); +int sym_set_primal_bound PROTO((sym_environment *env, double bound)); +int sym_set_continuous PROTO((sym_environment *env, int index)); +int sym_set_integer PROTO((sym_environment *env, int index)); +int sym_set_col_names PROTO((sym_environment *env, char **colname)); +int sym_add_col PROTO((sym_environment *env, int numelems, int *indices, + double *elements, double collb, double colub, + double obj, char is_int, char *name)); +int sym_add_row PROTO((sym_environment *env, int numelems, int *indices, + double *elements, char rowsen, double rowrhs, + double rowrng)); +int sym_delete_cols PROTO((sym_environment *env, int num, int * indices)); +int sym_delete_rows PROTO((sym_environment *env, int num, int * indices)); + +int sym_write_warm_start_desc PROTO((warm_start_desc *ws, char *file)); +warm_start_desc *sym_read_warm_start PROTO((char *file)); + +void sym_delete_warm_start PROTO((warm_start_desc *ws)); +warm_start_desc *sym_get_warm_start PROTO((sym_environment *env, + int copy_warm_start)); + +int sym_set_warm_start PROTO((sym_environment *env, warm_start_desc *ws)); + +int sym_set_int_param PROTO((sym_environment *env, const char *key, int value)); +int sym_set_dbl_param PROTO((sym_environment *env, const char *key, double value)); +int sym_set_str_param PROTO((sym_environment *env, const char *key, const char *value)); + +int sym_get_int_param PROTO((sym_environment *env, const char *key, int *value)); +int sym_get_dbl_param PROTO((sym_environment *env, const char *key, double *value)); +int sym_get_str_param PROTO((sym_environment *env, const char *key, char **value)); + +int sym_get_lb_for_new_rhs PROTO((sym_environment *env, int cnt, + int *new_rhs_ind, double *new_rhs_val, + double *lb_for_new_rhs)); +int sym_get_ub_for_new_rhs PROTO((sym_environment *env, int cnt, + int *new_rhs_ind, double *new_rhs_val, + double *ub_for_new_rhs)); +#if 0 +int sym_get_lb_for_new_obj PROTO((sym_environment *env, int cnt, + int *new_obj_ind, double *new_obj_val, + double *lb_for_new_obj)); +#endif +int sym_get_ub_for_new_obj PROTO((sym_environment *env, int cnt, + int *new_obj_ind, double *new_obj_val, + double *ub_for_new_obj)); + +warm_start_desc *sym_create_copy_warm_start PROTO((warm_start_desc * ws)); +MIPdesc *sym_create_copy_mip_desc PROTO((sym_environment *env)); +MIPdesc *sym_get_presolved_mip_desc PROTO((sym_environment *env)); +sym_environment * sym_create_copy_environment PROTO((sym_environment *env)); + +int sym_test PROTO((sym_environment *env, int argc, char **argv, + int *test_status)); + +#endif |