// 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 #include #include #include #include #include #include #include "CoinHelperFunctions.hpp" #include "CoinPackedVector.hpp" #include "CoinPackedMatrix.hpp" #include "CoinWarmStartBasis.hpp" #include "OsiRowCutDebugger.hpp" /* If we are on the path to the optimal integer solution then check if any generated cuts cut off the optimal solution! If so then print offending cuts and return non-zero code */ int OsiRowCutDebugger::validateCuts(const OsiCuts & cs, int first, int last) const { int nbad=0; int i; const double epsilon=1.0e-8; const int nRowCuts = CoinMin(cs.sizeRowCuts(),last); for (i=first; iub + epsilon ||sum < lb - epsilon) { double violation=CoinMax(sum-ub,lb-sum); std::cout<<"Cut "<ub + epsilon ||sum < lb - epsilon) { double violation=CoinMax(sum-ub,lb-sum); std::cout<<"Cut with "<colupper[i]+1.0e-3 || valuegetMatrixByCol()->isEquivalent(*si.getMatrixByCol())); // Loop once for each column looking for integer variables for (i=0;iisInteger(i)) { // integer variable found integerVariable_[i]=true; // Determine optimal solution value for integer i // from values saved in intSoln and probType. double soln; if ( probType==continuousWith0_1 ) { // Since 0_1 problem, had better be binary assert( siCopy->isBinary(i) ); // intSoln only contains integers with optimal value of 1 if ( intSoln.isExistingIndex(i) ) { soln = 1.0; assert( intSoln[i]==1. ); } else { soln = 0.0; } } else { // intSoln only contains integers with nonzero optimal values if ( intSoln.isExistingIndex(i) ) { soln = intSoln[i]; assert( intSoln[i]>=1. ); } else { soln = 0.0; } } // Set bounds in copyied problem to fix variable to its solution siCopy->setColUpper(i,soln); siCopy->setColLower(i,soln); } else { // this is not an integer variable integerVariable_[i]=false; } } // All integers have been fixed at optimal value. // Now solve to get continuous values #if 0 assert( siCopy->getNumRows()==5); assert( siCopy->getNumCols()==8); int r,c; for ( r=0; rgetNumRows(); r++ ) { std::cerr <<"rhs[" <rhs())[r] <getNumCols(); c++ ) { std::cerr <<"collower[" <collower())[c] <colupper())[c] <setWarmStart(&allSlack); siCopy->setHintParam(OsiDoScale,false); siCopy->initialSolve(); #if 0 for ( c=0; cgetNumCols(); c++ ) { std::cerr <<"colsol[" <colsol())[c] <getObjValue(),3.2368421052632)); #endif assert (siCopy->isProvenOptimal()); // Save column solution CoinCopyN(siCopy->getColSolution(),numberColumns_,optimalSolution_); delete siCopy; } } //if (integerVariable_!=NULL) si.rowCutDebugger_=this; return (integerVariable_!=NULL); } /* Activate debugger using full solution array. Up to user to get it correct. Returns true if debugger activated (i.e. solution was valid). */ bool OsiRowCutDebugger::activate(const OsiSolverInterface & si, const double * solution) { int i; //get rid of any arrays delete [] integerVariable_; delete [] optimalSolution_; OsiSolverInterface * siCopy = si.clone(); numberColumns_ = siCopy->getNumCols();; integerVariable_= new bool[numberColumns_]; optimalSolution_=new double[numberColumns_]; // Loop once for each column looking for integer variables for (i=0;iisInteger(i)) { // integer variable found integerVariable_[i]=true; // Determine optimal solution value for integer i // from values saved in intSoln and probType. double soln=floor(solution[i]+0.5); // in case just from array // Set bounds in copyied problem to fix variable to its solution siCopy->setColUpper(i,soln); siCopy->setColLower(i,soln); } else { // this is not an integer variable integerVariable_[i]=false; } } // All integers have been fixed at optimal value. // Now solve to get continuous values // make sure all slack basis //CoinWarmStartBasis allSlack; //siCopy->setWarmStart(&allSlack); siCopy->setHintParam(OsiDoScale,false); //siCopy->writeMps("bad.mps"); siCopy->initialSolve(); if (siCopy->isProvenOptimal()) { // Save column solution CoinCopyN(siCopy->getColSolution(),numberColumns_,optimalSolution_); } else { // bad solution delete [] integerVariable_; delete [] optimalSolution_; integerVariable_=NULL; optimalSolution_=NULL; } delete siCopy; return (integerVariable_!=NULL); } //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiRowCutDebugger::OsiRowCutDebugger () : numberColumns_(0), integerVariable_(NULL), optimalSolution_(NULL) { // nothing to do here } //------------------------------------------------------------------- // Alternate Constructor with model name //------------------------------------------------------------------- // Constructor with name of model OsiRowCutDebugger::OsiRowCutDebugger ( const OsiSolverInterface & si, const char * model) : numberColumns_(0), integerVariable_(NULL), optimalSolution_(NULL) { activate(si,model); } // Constructor with full solution (only integers need be correct) OsiRowCutDebugger::OsiRowCutDebugger (const OsiSolverInterface & si, const double * solution) : numberColumns_(0), integerVariable_(NULL), optimalSolution_(NULL) { activate(si,solution); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiRowCutDebugger::OsiRowCutDebugger (const OsiRowCutDebugger & source) { // copy numberColumns_=source.numberColumns_; integerVariable_=new bool[numberColumns_]; optimalSolution_=new double[numberColumns_]; CoinCopyN(source.integerVariable_, numberColumns_, integerVariable_ ); CoinCopyN(source.optimalSolution_, numberColumns_, optimalSolution_); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiRowCutDebugger::~OsiRowCutDebugger () { // free memory delete [] integerVariable_; delete [] optimalSolution_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiRowCutDebugger & OsiRowCutDebugger::operator=(const OsiRowCutDebugger& rhs) { if (this != &rhs) { delete [] integerVariable_; delete [] optimalSolution_; // copy numberColumns_=rhs.numberColumns_; integerVariable_=new bool[numberColumns_]; optimalSolution_=new double[numberColumns_]; CoinCopyN(rhs.integerVariable_, numberColumns_, integerVariable_ ); CoinCopyN(rhs.optimalSolution_, numberColumns_, optimalSolution_); } return *this; } // Redo solution after preprocessing void OsiRowCutDebugger::redoSolution(int numberColumns,const int * originalColumns) { assert (numberColumns<=numberColumns_); if (numberColumns