/home/coin/SVN-release/OS-1.0.0/OS/src/OSSolverInterfaces/CoinSolver.cpp

Go to the documentation of this file.
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                 // get the type of solver requested from OSoL string
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                                                                 // default solver is CBC
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                 //dataEchoCheck();
00164                 if(optimize() != true) throw ErrorClass("there was an error trying to optimize the problem");
00165                 delete osilreader;
00166                 osilreader = NULL;
00167         }// end solve
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 }//end solve()
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, //Column or Row Major
00185                         columnMajor? osinstance->getConstraintNumber() : osinstance->getVariableNumber(), //Minor Dimension
00186                         columnMajor? osinstance->getVariableNumber() : osinstance->getConstraintNumber(), //Major Dimension
00187                         osinstance->getLinearConstraintCoefficientNumber(), //Number of nonzeroes
00188                         columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->values : osinstance->getLinearConstraintCoefficientsInRowMajor()->values, //Pointer to matrix nonzeroes
00189                         columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes : osinstance->getLinearConstraintCoefficientsInRowMajor()->indexes, //Pointer to start of minor dimension indexes -- change to allow for row storage
00190                         columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts : osinstance->getLinearConstraintCoefficientsInRowMajor()->starts, //Pointers to start of columns.
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 } // end setCoinPackedMatrix
00202 
00203 bool CoinSolver::optimize()
00204 {
00205         double *x = NULL;
00206         double *y = NULL;
00207         double *z = NULL;
00208         std::string *rcost = NULL;
00209         // resultHeader infomration
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         //if(osresult->setJobID( osresultdata->jobID) != true)
00215         //      throw ErrorClass("OSResult error: setJobID");
00216         //if(osresult->setGeneralMessage( osresultdata->message) != true)
00217         //      throw ErrorClass("OSResult error: setGeneralMessage");
00218         // set basic problem parameters
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                 // the code below causes a memory problem because it does not create a new copy in memory
00236                 //m_OsiSolver->assignProblem(m_CoinPackedMatrix, osinstance->getVariableLowerBounds(), 
00237                 //                      osinstance->getVariableUpperBounds(),  
00238                 //                      osinstance->getDenseObjectiveCoefficients()[0], 
00239                 //                      osinstance->getConstraintLowerBounds(), osinstance->getConstraintUpperBounds());
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                 // set the integer variables
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                 // try to catch Coin Solver errors
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                         /* Retrieve the solution */
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                         // Symphony does not get dual prices
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                         // now put the reduced costs into the osrl
00303                         // Symphony does not get reduced costs
00304                         if( sSolverName.find( "symphony") == std::string::npos){
00305                                 int numberOfOtherVariableResult = 1;
00306                                 int otherIdx = 0;
00307                                 // first set the number of Other Variable Results
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                                 // end of settiing reduced costs
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 } // end optimize
00346 
00347 std::string CoinSolver::getCoinSolverType(std::string lcl_osol){
00348 // this is deprecated, but keep it around
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 } // end getCoinSolverType
00377 
00378 void CoinSolver::dataEchoCheck(){
00379         int i;
00380         // print out problem parameters
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         // print out the variable information
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         // print out objective function information
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         // print out constraint information
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         // print out linear constraint data
00415         if(m_CoinPackedMatrix != NULL) m_CoinPackedMatrix->dumpMatrix();
00416 } // end dataEchoCheck
00417 
00418 
00419 
00420 
00421 

Generated on Thu May 15 22:15:05 2008 by  doxygen 1.4.7