00001
00022 #include "CoinSolver.h"
00023 #include "OSiLReader.h"
00024 #include "OSInstance.h"
00025 #include "FileUtil.h"
00026
00027 #include <iostream>
00028 #ifdef HAVE_CTIME
00029 # include <ctime>
00030 #else
00031 # ifdef HAVE_TIME_H
00032 # include <time.h>
00033 # else
00034 # error "don't have header file for time"
00035 # endif
00036 #endif
00037 using std::cout;
00038 using std::endl;
00039 using std::ostringstream;
00040
00041
00042 CoinSolver::CoinSolver() :
00043 m_OsiSolver(NULL),
00044 m_CoinPackedMatrix(NULL)
00045 {
00046 osrlwriter = new OSrLWriter();
00047 }
00048
00049 CoinSolver::~CoinSolver() {
00050 #ifdef DEBUG
00051 cout << "inside CoinSolver destructor" << endl;
00052 #endif
00053 cout << "inside CoinSolver destructor" << endl;
00054 delete m_CoinPackedMatrix;
00055 m_CoinPackedMatrix = NULL;
00056 delete m_OsiSolver;
00057 m_OsiSolver = NULL;
00058 delete osrlwriter;
00059 osrlwriter = NULL;
00060 cout << "leaving CoinSolver destructor" << endl;
00061 }
00062
00063
00064 void CoinSolver::solve() throw (ErrorClass) {
00065 try{
00066 OSiLReader *osilreader = NULL;
00067 osresult = new OSResult();
00068 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00069 clock_t start, finish;
00070 double duration;
00071 start = clock();
00072 if(osinstance == NULL){
00073 osilreader = new OSiLReader();
00074 osinstance = osilreader->readOSiL( &osil);
00075 }
00076 finish = clock();
00077 duration = (double) (finish - start) / CLOCKS_PER_SEC;
00078 cout << "Parsing took (seconds): "<< duration << endl;
00079 cout << "Start Solve with a Coin Solver" << endl;
00080
00081 bool solverIsDefined = false;
00082 std::cout << "SOLVER NAME = " << sSolverName << std::endl;
00083 if( sSolverName.find("clp") != std::string::npos){
00084 if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00085 || (osinstance->getNumberOfQuadraticTerms() > 0)
00086 || (osinstance->getNumberOfIntegerVariables() > 0)
00087 || (osinstance->getNumberOfBinaryVariables() > 0) ) throw ErrorClass( "Clp cannot do nonlinear or quadratic or integer");
00088 solverIsDefined = true;
00089
00090 m_OsiSolver = new OsiClpSolverInterface();
00091 }
00092 else{
00093 if( sSolverName.find("vol") != std::string::npos){
00094 if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00095 || (osinstance->getNumberOfQuadraticTerms() > 0) ) throw ErrorClass( "Vol cannot do nonlinear or quadratic");
00096 solverIsDefined = true;
00097 m_OsiSolver = new OsiVolSolverInterface();
00098 }
00099 else{
00100 if( sSolverName.find( "cplex") != std::string::npos){
00101 #ifdef COIN_HAS_CPX
00102 if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00103 || (osinstance->getNumberOfQuadraticTerms() > 0) ) throw ErrorClass( "Cplex cannot do nonlinear or quadratic");
00104 solverIsDefined = true;
00105 m_OsiSolver = new OsiCpxSolverInterface();
00106 #endif
00107 }
00108 else{
00109 if(sSolverName.find( "glpk") != std::string::npos){
00110 #ifdef COIN_HAS_GLPK
00111 if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00112 || (osinstance->getNumberOfQuadraticTerms() > 0) ) throw ErrorClass( "Glpk cannot do nonlinear or quadratic");
00113 solverIsDefined = true;
00114 m_OsiSolver = new OsiGlpkSolverInterface();
00115 #endif
00116 }
00117 else{
00118 if(sSolverName.find( "dylp") != std::string::npos){
00119
00120 #ifdef COIN_HAS_DYLP
00121 if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00122 || (osinstance->getNumberOfQuadraticTerms() > 0) ) {
00123
00124 throw ErrorClass( "DyLP cannot do nonlinear or quadratic");
00125 }
00126 if( (osinstance->getNumberOfIntegerVariables() > 0)
00127 || (osinstance->getNumberOfBinaryVariables() > 0) ) throw ErrorClass( "DyLP cannot do integer programming");
00128 solverIsDefined = true;
00129
00130 m_OsiSolver = new OsiDylpSolverInterface();
00131
00132 #endif
00133 }
00134 else{
00135 if( sSolverName.find( "symphony") != std::string::npos) {
00136 #ifdef COIN_HAS_SYMPHONY
00137 if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00138 || (osinstance->getNumberOfQuadraticTerms() > 0) ) throw ErrorClass( "SYMPHONY cannot do nonlinear or quadratic");
00139 solverIsDefined = true;
00140 m_OsiSolver = new OsiSymSolverInterface();
00141 #endif
00142 }
00143 else{
00144
00145 if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00146 || (osinstance->getNumberOfQuadraticTerms() > 0) ) throw ErrorClass( "Cbc cannot do nonlinear or quadratic");
00147 solverIsDefined = true;
00148 m_OsiSolver = new OsiCbcSolverInterface();
00149 }
00150 }
00151 }
00152 }
00153 }
00154 }
00155
00156
00157 if(solverIsDefined == false) throw ErrorClass("a supported solver was not defined");
00158 if(osinstance->getConstraintNumber() <= 0)throw ErrorClass("Coin solver Needs Constraints");
00159 if(osinstance->getVariableNumber() <= 0)throw ErrorClass("Coin solver requires decision variables");
00160 if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Coin solver needs an objective function");
00161 if(osinstance->getLinearConstraintCoefficientNumber() <= 0) throw ErrorClass("Coin solver needs linear constraints");
00162 if(!setCoinPackedMatrix() ) throw ErrorClass("Problem generating coin packed matrix");
00163
00164 if(optimize() != true) throw ErrorClass("there was an error trying to optimize the problem");
00165 delete osilreader;
00166 osilreader = NULL;
00167 }
00168 catch(const ErrorClass& eclass){
00169 std::cout << "THERE IS AN ERROR" << std::endl;
00170 osresult->setGeneralMessage( eclass.errormsg);
00171 osresult->setGeneralStatusType( "error");
00172 osrl = osrlwriter->writeOSrL( osresult);
00173 throw ErrorClass( osrl) ;
00174 }
00175 }
00176
00177
00178
00179 bool CoinSolver::setCoinPackedMatrix(){
00180 bool columnMajor = osinstance->getLinearConstraintCoefficientMajor();
00181 try{
00182 int maxGap = 0;
00183 m_CoinPackedMatrix = new CoinPackedMatrix(
00184 columnMajor,
00185 columnMajor? osinstance->getConstraintNumber() : osinstance->getVariableNumber(),
00186 columnMajor? osinstance->getVariableNumber() : osinstance->getConstraintNumber(),
00187 osinstance->getLinearConstraintCoefficientNumber(),
00188 columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->values : osinstance->getLinearConstraintCoefficientsInRowMajor()->values,
00189 columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes : osinstance->getLinearConstraintCoefficientsInRowMajor()->indexes,
00190 columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts : osinstance->getLinearConstraintCoefficientsInRowMajor()->starts,
00191 0, 0, maxGap );
00192
00193 return true;
00194 }
00195 catch(const ErrorClass& eclass){
00196 osresult->setGeneralMessage( eclass.errormsg);
00197 osresult->setGeneralStatusType( "error");
00198 osrl = osrlwriter->writeOSrL( osresult);
00199 throw ;
00200 }
00201 }
00202
00203 bool CoinSolver::optimize()
00204 {
00205 double *x = NULL;
00206 double *y = NULL;
00207 double *z = NULL;
00208 std::string *rcost = NULL;
00209
00210 if(osresult->setServiceName("Solved with Coin Solver: " + sSolverName) != true)
00211 throw ErrorClass("OSResult error: setServiceName");
00212 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00213 throw ErrorClass("OSResult error: setInstanceName");
00214
00215
00216
00217
00218
00219 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00220 throw ErrorClass("OSResult error: setVariableNumer");
00221 if(osresult->setObjectiveNumber( 1) != true)
00222 throw ErrorClass("OSResult error: setObjectiveNumber");
00223 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00224 throw ErrorClass("OSResult error: setConstraintNumber");
00225 if(osresult->setSolutionNumber( 1) != true)
00226 throw ErrorClass("OSResult error: setSolutionNumer");
00227
00228 int i = 0;
00229 try{
00230 m_OsiSolver->loadProblem(*m_CoinPackedMatrix, osinstance->getVariableLowerBounds(),
00231 osinstance->getVariableUpperBounds(),
00232 osinstance->getDenseObjectiveCoefficients()[0],
00233 osinstance->getConstraintLowerBounds(), osinstance->getConstraintUpperBounds());
00234
00235
00236
00237
00238
00239
00240 if(osinstance->getObjectiveNumber() == 0) throw ErrorClass("there is no objective function");
00241
00242
00243 if( osinstance->getObjectiveMaxOrMins()[0] == "min") m_OsiSolver->setObjSense(1.0);
00244 else m_OsiSolver->setObjSense(-1.0);
00245 m_OsiSolver->setDblParam(OsiObjOffset, osinstance->getObjectiveConstants()[0]);
00246
00247
00248 int *intIndex;
00249 int k = 0;
00250 char *varType;
00251 int numOfIntVars = osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables();
00252 intIndex = new int[ numOfIntVars];
00253 varType = osinstance->getVariableTypes();
00254 for(i = 0; i < osinstance->getVariableNumber(); i++){
00255 if( (varType[i] == 'B') || (varType[i]) == 'I' ) {
00256 intIndex[k++] = i;
00257 }
00258 }
00259 m_OsiSolver->setInteger( intIndex, numOfIntVars);
00260
00261 try{
00262 if(numOfIntVars > 0){
00263 m_OsiSolver->branchAndBound();
00264 }
00265 else{
00266 m_OsiSolver->initialSolve();
00267 cout << "DONE WITH INITIAL SOLVE" << endl;
00268 }
00269 }
00270 catch(CoinError e){
00271 std::string errmsg;
00272 errmsg = "Coin Solver Error: " + e.message() + "\n" + " see method "
00273 + e.methodName() + " in class " + e.className();
00274 throw ErrorClass( errmsg );
00275 }
00276 int solIdx = 0;
00277 std::string description = "";
00278 osresult->setGeneralStatusType("success");
00279 if (m_OsiSolver->isProvenOptimal() == true){
00280 osresult->setSolutionStatus(solIdx, "optimal", description);
00281
00282 x = new double[osinstance->getVariableNumber() ];
00283 y = new double[osinstance->getConstraintNumber() ];
00284 z = new double[1];
00285 rcost = new std::string[ osinstance->getVariableNumber()];
00286
00287 *(z + 0) = m_OsiSolver->getObjValue();
00288 osresult->setObjectiveValues(solIdx, z);
00289 for(i=0; i < osinstance->getVariableNumber(); i++){
00290 *(x + i) = m_OsiSolver->getColSolution()[i];
00291 }
00292 osresult->setPrimalVariableValues(solIdx, x);
00293
00294 if( sSolverName.find( "symphony") == std::string::npos){
00295 for(i=0; i < osinstance->getConstraintNumber(); i++){\
00296 *(y + i) = m_OsiSolver->getRowPrice()[ i];
00297 }
00298 osresult->setDualVariableValues(solIdx, y);
00299 }
00300
00301
00302
00303
00304 if( sSolverName.find( "symphony") == std::string::npos){
00305 int numberOfOtherVariableResult = 1;
00306 int otherIdx = 0;
00307
00308 osresult->setNumberOfOtherVariableResult(solIdx, numberOfOtherVariableResult);
00309 ostringstream outStr;
00310 int numberOfVar = osinstance->getVariableNumber();
00311 for(i=0; i < numberOfVar; i++){
00312 outStr << m_OsiSolver->getReducedCost()[ i];
00313 rcost[ i] = outStr.str();
00314 outStr.str("");
00315 }
00316 osresult->setAnOtherVariableResult(solIdx, otherIdx, "reduced costs", "the variable reduced costs", rcost);
00317
00318 }
00319 }
00320 else{
00321 if(m_OsiSolver->isProvenPrimalInfeasible() == true)
00322 osresult->setSolutionStatus(solIdx, "infeasible", description);
00323 else
00324 if(m_OsiSolver->isProvenDualInfeasible() == true)
00325 osresult->setSolutionStatus(solIdx, "dualinfeasible", description);
00326 else
00327 osresult->setSolutionStatus(solIdx, "other", description);
00328 }
00329 osrl = osrlwriter->writeOSrL( osresult);
00330 if(osinstance->getVariableNumber() > 0) delete[] x;
00331 x = NULL;
00332 if(osinstance->getConstraintNumber()) delete[] y;
00333 y = NULL;
00334 delete[] z;
00335 z = NULL;
00336 if(osinstance->getVariableNumber() > 0) delete[] rcost;
00337 return true;
00338 }
00339 catch(const ErrorClass& eclass){
00340 osresult->setGeneralMessage( eclass.errormsg);
00341 osresult->setGeneralStatusType( "error");
00342 osrl = osrlwriter->writeOSrL( osresult);
00343 throw ;
00344 }
00345 }
00346
00347 std::string CoinSolver::getCoinSolverType(std::string lcl_osol){
00348
00349 try{
00350 if( lcl_osol.find( "clp") != std::string::npos){
00351 return "coin_solver_glpk";
00352 }
00353 else{
00354 if( lcl_osol.find( "cbc") != std::string::npos){
00355 return "coin_solver_cpx";
00356 }
00357 else{
00358 if( lcl_osol.find( "cpx") != std::string::npos){
00359 return "coin_solver_clp";
00360 }
00361 else{
00362 if(lcl_osol.find( "glpk") != std::string::npos){
00363 return "";
00364 }
00365 else throw ErrorClass("a supported solver was not defined");
00366 }
00367 }
00368 }
00369 }
00370 catch(const ErrorClass& eclass){
00371 osresult->setGeneralMessage( eclass.errormsg);
00372 osresult->setGeneralStatusType( "error");
00373 osrl = osrlwriter->writeOSrL( osresult);
00374 throw ;
00375 }
00376 }
00377
00378 void CoinSolver::dataEchoCheck(){
00379 int i;
00380
00381 cout << "This is problem: " << osinstance->getInstanceName() << endl;
00382 cout << "The problem source is: " << osinstance->getInstanceSource() << endl;
00383 cout << "The problem description is: " << osinstance->getInstanceDescription() << endl;
00384 cout << "number of variables = " << osinstance->getVariableNumber() << endl;
00385 cout << "number of Rows = " << osinstance->getConstraintNumber() << endl;
00386
00387
00388 if(osinstance->getVariableNumber() > 0){
00389 for(i = 0; i < osinstance->getVariableNumber(); i++){
00390 if(osinstance->getVariableNames() != NULL) cout << "variable Names " << osinstance->getVariableNames()[ i] << endl;
00391 if(osinstance->getVariableTypes() != NULL) cout << "variable Types " << osinstance->getVariableTypes()[ i] << endl;
00392 if(osinstance->getVariableLowerBounds() != NULL) cout << "variable Lower Bounds " << osinstance->getVariableLowerBounds()[ i] << endl;
00393 if(osinstance->getVariableUpperBounds() != NULL) cout << "variable Upper Bounds " << osinstance->getVariableUpperBounds()[i] << endl;
00394 }
00395 }
00396
00397
00398 if(osinstance->getVariableNumber() > 0 || osinstance->instanceData->objectives->obj != NULL || osinstance->instanceData->objectives->numberOfObjectives > 0){
00399 if( osinstance->getObjectiveMaxOrMins()[0] == "min") cout << "problem is a minimization" << endl;
00400 else cout << "problem is a maximization" << endl;
00401 for(i = 0; i < osinstance->getVariableNumber(); i++){
00402 cout << "OBJ COEFFICIENT = " << osinstance->getDenseObjectiveCoefficients()[0][i] << endl;
00403 }
00404 }
00405
00406 if(osinstance->getConstraintNumber() > 0){
00407 for(i = 0; i < osinstance->getConstraintNumber(); i++){
00408 if(osinstance->getConstraintNames() != NULL) cout << "row name = " << osinstance->getConstraintNames()[i] << endl;
00409 if(osinstance->getConstraintLowerBounds() != NULL) cout << "row lower bound = " << osinstance->getConstraintLowerBounds()[i] << endl;
00410 if(osinstance->getConstraintUpperBounds() != NULL) cout << "row upper bound = " << osinstance->getConstraintUpperBounds()[i] << endl;
00411 }
00412 }
00413
00414
00415 if(m_CoinPackedMatrix != NULL) m_CoinPackedMatrix->dumpMatrix();
00416 }
00417
00418
00419
00420
00421