// Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CoinHelperFunctions.hpp" #include "OsiWarmStart.hpp" #include "OsiSolverInterface.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #include "OsiRowCutDebugger.hpp" //############################################################################# // Hotstart related methods (primarily used in strong branching) // It is assumed that only bounds (on vars/constraints) can change between // markHotStart() and unmarkHotStart() //############################################################################# void OsiSolverInterface::markHotStart() { delete ws_; ws_ = getWarmStart(); } void OsiSolverInterface::solveFromHotStart() { setWarmStart(ws_); resolve(); } void OsiSolverInterface::unmarkHotStart() { delete ws_; ws_ = NULL; } //############################################################################# // Get indices of solution vector which are integer variables presently at // fractional values //############################################################################# OsiVectorInt OsiSolverInterface::getFractionalIndices(const double etol) const { const int colnum = getNumCols(); OsiVectorInt frac; OsiAbsFltEq eq(etol); for (int i = 0; i < colnum; ++i) { if (isInteger(i)) { const double ci = getColSolution()[i]; const double distanceFromInteger = ci - floor(ci + 0.5); if (! eq(distanceFromInteger, 0.0)) frac.push_back(i); } } return frac; } //############################################################################# // Methods for determining the type of column variable. // The method isContinuous() is presently implemented in the derived classes. // The methods below depend on isContinuous and the values // stored in the column bounds. //############################################################################# bool OsiSolverInterface::isBinary(int colIndex) const { if ( isContinuous(colIndex) ) return false; const double * cu = getColUpper(); const double * cl = getColLower(); if ( (cu[colIndex]== 1 || cu[colIndex]== 0) && (cl[colIndex]== 0 || cl[colIndex]==1) ) return true; else return false; } //----------------------------------------------------------------------------- bool OsiSolverInterface::isInteger(int colIndex) const { return !isContinuous(colIndex); } //----------------------------------------------------------------------------- bool OsiSolverInterface::isIntegerNonBinary(int colIndex) const { if ( isInteger(colIndex) && !isBinary(colIndex) ) return true; else return false; } //----------------------------------------------------------------------------- bool OsiSolverInterface::isFreeBinary(int colIndex) const { if ( isContinuous(colIndex) ) return false; const double * cu = getColUpper(); const double * cl = getColLower(); if ( (cu[colIndex]== 1) && (cl[colIndex]== 0) ) return true; else return false; } //############################################################################# // Built-in (i.e., slow) methods for problem modification //############################################################################# void OsiSolverInterface::setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { while (indexFirst != indexLast) { setColBounds(*indexFirst, boundList[0], boundList[1]); ++indexFirst; boundList += 2; } } //----------------------------------------------------------------------------- void OsiSolverInterface::setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { while (indexFirst != indexLast) { setRowBounds(*indexFirst, boundList[0], boundList[1]); ++indexFirst; boundList += 2; } } //----------------------------------------------------------------------------- void OsiSolverInterface::setRowSetTypes(const int* indexFirst, const int* indexLast, const char* senseList, const double* rhsList, const double* rangeList) { while (indexFirst != indexLast) { setRowType(*indexFirst++, *senseList++, *rhsList++, *rangeList++); } } //----------------------------------------------------------------------------- void OsiSolverInterface::setContinuous(const int* indices, int len) { for (int i = 0; i < len; ++i) { setContinuous(indices[i]); } } //----------------------------------------------------------------------------- void OsiSolverInterface::setInteger(const int* indices, int len) { for (int i = 0; i < len; ++i) { setInteger(indices[i]); } } //----------------------------------------------------------------------------- void OsiSolverInterface::addCols(const int numcols, const OsiPackedVectorBase * const * cols, const double* collb, const double* colub, const double* obj) { for (int i = 0; i < numcols; ++i) { addCol(*cols[i], collb[i], colub[i], obj[i]); } } //----------------------------------------------------------------------------- void OsiSolverInterface::addRows(const int numrows, const OsiPackedVectorBase * const * rows, const double* rowlb, const double* rowub) { for (int i = 0; i < numrows; ++i) { addRow(*rows[i], rowlb[i], rowub[i]); } } //----------------------------------------------------------------------------- void OsiSolverInterface::addRows(const int numrows, const OsiPackedVectorBase * const * rows, const char* rowsen, const double* rowrhs, const double* rowrng) { for (int i = 0; i < numrows; ++i) { addRow(*rows[i], rowsen[i], rowrhs[i], rowrng[i]); } } //############################################################################# // Apply Cuts //############################################################################# OsiSolverInterface::ApplyCutsReturnCode OsiSolverInterface::applyCuts( const OsiCuts & cs, double effectivenessLb ) { OsiSolverInterface::ApplyCutsReturnCode retVal; int i; // Loop once for each column cut for ( i=0; i // If the model name passed is on list of known models // then all cuts are checked to see that they do NOT cut // off the known optimal solution. void OsiSolverInterface::activateRowCutDebugger (const char * modelName) { delete rowCutDebugger_; rowCutDebugger_ = new OsiRowCutDebugger(*this,modelName); } //------------------------------------------------------------------- // Get Row Cut Debugger
// If there is a row cut debugger object associated with // model AND if the known optimal solution is within the // current feasible region then a pointer to the object is // returned which may be used to test validity of cuts. // Otherwise NULL is returned const OsiRowCutDebugger * OsiSolverInterface::getRowCutDebugger() const { if (rowCutDebugger_&&rowCutDebugger_->onOptimalPath(*this)) { return rowCutDebugger_; } else { return NULL; } } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiSolverInterface::OsiSolverInterface () : appData_(NULL), rowCutDebugger_(NULL), ws_(NULL) { intParam_[OsiMaxNumIteration] = 9999999; intParam_[OsiMaxNumIterationHotStart] = 9999999; dblParam_[OsiDualObjectiveLimit] = DBL_MAX; dblParam_[OsiPrimalObjectiveLimit] = DBL_MAX; dblParam_[OsiDualTolerance] = 1e-6; dblParam_[OsiPrimalTolerance] = 1e-6; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiSolverInterface::OsiSolverInterface (const OsiSolverInterface & source) : appData_(source.appData_), rowCutDebugger_(NULL), ws_(NULL) { if ( source.rowCutDebugger_!=NULL ) rowCutDebugger_ = new OsiRowCutDebugger(*source.rowCutDebugger_); CoinDisjointCopyN(source.intParam_, OsiLastIntParam, intParam_); CoinDisjointCopyN(source.dblParam_, OsiLastDblParam, dblParam_); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiSolverInterface::~OsiSolverInterface () { // delete debugger - should be safe as only ever returned const delete rowCutDebugger_; rowCutDebugger_ = NULL; delete ws_; ws_ = NULL; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiSolverInterface & OsiSolverInterface::operator=(const OsiSolverInterface& rhs) { if (this != &rhs) { appData_ = rhs.appData_; delete rowCutDebugger_; if ( rhs.rowCutDebugger_!=NULL ) rowCutDebugger_ = new OsiRowCutDebugger(*rhs.rowCutDebugger_); else rowCutDebugger_ = NULL; CoinDisjointCopyN(rhs.intParam_, OsiLastIntParam, intParam_); CoinDisjointCopyN(rhs.dblParam_, OsiLastDblParam, dblParam_); delete ws_; ws_ = NULL; } return *this; }