/Users/kmartin/Documents/files/code/cpp/OScpp/COIN-OS/OS/src/OSSolverInterfaces/OSCoinSolver.cpp

Go to the documentation of this file.
00001 
00020 #define DEBUG
00021 
00022 #include "OSCoinSolver.h"
00023 #include "OSInstance.h"
00024 #include "OSFileUtil.h"
00025 #include "CglPreProcess.hpp"
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 osiSolver(NULL),
00044 m_osilreader(NULL),
00045 m_CoinPackedMatrix(NULL)
00046 {
00047 osrlwriter = new OSrLWriter();
00048 }
00049 
00050 CoinSolver::~CoinSolver() {
00051         #ifdef DEBUG
00052         cout << "inside CoinSolver destructor" << endl;
00053         #endif
00054         cout << "inside CoinSolver destructor" << endl;
00055         if(m_osilreader != NULL) delete m_osilreader;
00056         m_osilreader = NULL;
00057         delete m_CoinPackedMatrix;
00058         m_CoinPackedMatrix = NULL;
00059         delete osiSolver;
00060         if(osiSolver != NULL) osiSolver = NULL;
00061         delete osrlwriter;
00062         osrlwriter = NULL;
00063         delete osresult;
00064         osresult = NULL;
00065         cout << "leaving CoinSolver destructor" << endl;
00066 }
00067 
00068 
00069 void CoinSolver::buildSolverInstance() throw (ErrorClass) {
00070         try{
00071                 osresult = new OSResult();
00072                         if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00073                         clock_t start, finish;
00074                         double duration;
00075                         start = clock();
00076                         if(osinstance == NULL){
00077                                 m_osilreader = new OSiLReader();
00078                                 osinstance = m_osilreader->readOSiL( osil);
00079                         }
00080                                         finish = clock();
00081                         duration = (double) (finish - start) / CLOCKS_PER_SEC;
00082                         cout << "Parsing took (seconds): "<< duration << endl;
00083                                 cout << "Start Solve with a Coin Solver" << endl;
00084                         // get the type of solver requested from OSoL string
00085                         bool solverIsDefined = false;
00086                         std::cout << "SOLVER NAME =  " << sSolverName << std::endl;
00087                         if( sSolverName.find("clp") != std::string::npos){
00088                                 solverIsDefined = true;
00089                                 osiSolver = new OsiClpSolverInterface();
00090                         }
00091                         else{
00092                                 if( sSolverName.find("vol") != std::string::npos){
00093                      #ifdef COIN_HAS_VOL
00094                                         solverIsDefined = true;
00095                                         osiSolver = new OsiVolSolverInterface();
00096                      #endif
00097                                 }
00098                                 else{
00099                                         if( sSolverName.find( "cplex") != std::string::npos){
00100                                                 #ifdef COIN_HAS_CPX
00101                                                 solverIsDefined = true;
00102                                                 osiSolver = new OsiCpxSolverInterface();
00103                                                 #endif
00104                                         }
00105                                         else{
00106                                                 if(sSolverName.find( "glpk") != std::string::npos){
00107                                                         #ifdef COIN_HAS_GLPK
00108                                                         solverIsDefined = true;
00109                                                         osiSolver = new OsiGlpkSolverInterface();
00110                                                         #endif
00111                                                 }
00112                                                 else{
00113                                                         if(sSolverName.find( "dylp") != std::string::npos){
00114                                                                 #ifdef COIN_HAS_DYLP
00115                                                                 solverIsDefined = true;
00116                                                                 osiSolver = new OsiDylpSolverInterface();
00117                                                                 #endif
00118                                                         }
00119                                                         else{
00120                                                                 if( sSolverName.find( "symphony") != std::string::npos) {
00121                                                                         #ifdef COIN_HAS_SYMPHONY
00122                                                                         solverIsDefined = true;
00123                                                                         osiSolver = new OsiSymSolverInterface();
00124                                                                         #endif
00125                                                                 }
00126                                                                 else{
00127                                                                         // default solver is CBC
00128                                                                         solverIsDefined = true;
00129                                                                         osiSolver = new OsiCbcSolverInterface();
00130                                                                 }
00131                                                         }
00132                                                 }
00133                                         }
00134                                 }
00135                         }
00136                         //
00137                         //
00138                         if(solverIsDefined == false) throw ErrorClass("a supported solver was not defined");
00139                         if(osinstance->getConstraintNumber() <= 0)throw ErrorClass("Coin solver Needs Constraints");
00140                         if(osinstance->getVariableNumber() <= 0)throw ErrorClass("Coin solver requires decision variables");
00141                         if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Coin solver needs an objective function");
00142                         if(osinstance->getLinearConstraintCoefficientNumber() <= 0) throw ErrorClass("Coin solver needs linear constraints");
00143                         if(!setCoinPackedMatrix() ) throw ErrorClass("Problem generating coin packed matrix");
00144                         osiSolver->loadProblem(*m_CoinPackedMatrix, osinstance->getVariableLowerBounds(), 
00145                                 osinstance->getVariableUpperBounds(),  
00146                                 osinstance->getDenseObjectiveCoefficients()[0], 
00147                                 osinstance->getConstraintLowerBounds(), osinstance->getConstraintUpperBounds()
00148                         );
00149                         //dataEchoCheck();      
00150                         if(osinstance->getObjectiveNumber() == 0) throw ErrorClass("there is no objective function");
00151                         if( osinstance->getObjectiveMaxOrMins()[0] == "min") osiSolver->setObjSense(1.0);
00152                         else osiSolver->setObjSense(-1.0);
00153                         // set the integer variables
00154                         int *intIndex = NULL;
00155                         int i = 0;
00156                         int k = 0;
00157                         char *varType;
00158                         int numOfIntVars = osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables();
00159                         if(numOfIntVars > 0) {
00160                                 intIndex = new int[ numOfIntVars];
00161                                 varType = osinstance->getVariableTypes();
00162                                 for(i = 0; i < osinstance->getVariableNumber(); i++){
00163                                         if( (varType[i] == 'B') || (varType[i]) == 'I' ) {
00164                                                 intIndex[k++] = i;
00165                                         }
00166                                 }
00167                                 osiSolver->setInteger( intIndex,  numOfIntVars);
00168                         }
00169                         if(numOfIntVars > 0){ 
00170                                 delete[] intIndex;
00171                                 intIndex = NULL;
00172                         }
00173                         bCallbuildSolverInstance = true;
00174         }
00175         catch(const ErrorClass& eclass){
00176                 std::cout << "THERE IS AN ERROR" << std::endl;
00177                 osresult->setGeneralMessage( eclass.errormsg);
00178                 osresult->setGeneralStatusType( "error");
00179                 osrl = osrlwriter->writeOSrL( osresult);
00180                 throw ErrorClass( osrl) ;
00181         }                               
00182 }//end buildSolverInstance()
00183 
00184 
00185 bool CoinSolver::setCoinPackedMatrix(){
00186         bool columnMajor = osinstance->getLinearConstraintCoefficientMajor();
00187         try{
00188                 int maxGap = 0;
00189                 m_CoinPackedMatrix = new CoinPackedMatrix(
00190                         columnMajor, //Column or Row Major
00191                         columnMajor? osinstance->getConstraintNumber() : osinstance->getVariableNumber(), //Minor Dimension
00192                         columnMajor? osinstance->getVariableNumber() : osinstance->getConstraintNumber(), //Major Dimension
00193                         osinstance->getLinearConstraintCoefficientNumber(), //Number of nonzeroes
00194                         columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->values : osinstance->getLinearConstraintCoefficientsInRowMajor()->values, //Pointer to matrix nonzeroes
00195                         columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes : osinstance->getLinearConstraintCoefficientsInRowMajor()->indexes, //Pointer to start of minor dimension indexes -- change to allow for row storage
00196                         columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts : osinstance->getLinearConstraintCoefficientsInRowMajor()->starts, //Pointers to start of columns.
00197                         0,   0, maxGap ); 
00198 
00199                 return true;
00200         }
00201         catch(const ErrorClass& eclass){
00202                 osresult->setGeneralMessage( eclass.errormsg);
00203                 osresult->setGeneralStatusType( "error");
00204                 osrl = osrlwriter->writeOSrL( osresult);
00205                 throw ;
00206         }
00207 } // end setCoinPackedMatrix
00208 
00209 void CoinSolver::solve() throw (ErrorClass) {
00210         // make sure the solver instance exists
00211         if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00212         // first check the various solvers and see if they are of the proper problem type
00213         if( osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0){
00214                 // throw an exception if we have a solver that cannot do integer programming
00215                 if( sSolverName.find("clp") != std::string::npos) throw ErrorClass( "Clp cannot do integer programming");
00216                 if( sSolverName.find("vol") != std::string::npos) throw ErrorClass( "Vol cannot do integer programming");
00217                 if( sSolverName.find("dylp") != std::string::npos) throw ErrorClass( "DyLP cannot do integer programming");
00218                 if( sSolverName.find("ipopt") != std::string::npos) throw ErrorClass( "Ipopt cannot do integer programming");
00219         }
00220         if( (osinstance->getNumberOfNonlinearExpressions() > 0)
00221                 || (osinstance->getNumberOfQuadraticTerms() > 0) ){
00222                 throw ErrorClass( "This COIN-OR Solver is not configured for nonlinear programming");
00223         }
00224         // if we are throw an exception if the problem is nonlinear
00225         double *x = NULL;
00226         double *y = NULL;
00227         double *z = NULL;
00228         int i = 0;
00229         std::string *rcost = NULL;
00230         // resultHeader infomration
00231         if(osresult->setServiceName("Solved with Coin Solver: " + sSolverName) != true)
00232                 throw ErrorClass("OSResult error: setServiceName");
00233         if(osresult->setInstanceName(  osinstance->getInstanceName()) != true)
00234                 throw ErrorClass("OSResult error: setInstanceName");
00235         //if(osresult->setJobID( osresultdata->jobID) != true)
00236         //      throw ErrorClass("OSResult error: setJobID");
00237         //if(osresult->setGeneralMessage( osresultdata->message) != true)
00238         //      throw ErrorClass("OSResult error: setGeneralMessage");
00239         // set basic problem parameters
00240         if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00241                 throw ErrorClass("OSResult error: setVariableNumer");
00242         if(osresult->setObjectiveNumber( 1) != true)
00243                 throw ErrorClass("OSResult error: setObjectiveNumber");
00244         if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00245                 throw ErrorClass("OSResult error: setConstraintNumber");
00246         if(osresult->setSolutionNumber(  1) != true)
00247                 throw ErrorClass("OSResult error: setSolutionNumer");   
00248         //
00249         try{
00250                 osiSolver->setDblParam(OsiObjOffset, osinstance->getObjectiveConstants()[0]);
00251                 // set some OSI options
00252 #ifdef COIN_HAS_SYMPHONY
00253                 //first the number of processors -- applies only to SYMPHONY
00254                 if( sSolverName.find( "symphony") != std::string::npos) {
00255                         OsiSymSolverInterface * si =
00256                         dynamic_cast<OsiSymSolverInterface *>(osiSolver) ;
00257                         std::string num_proc = "";
00258                         string::size_type pos1 = this->osol.find("num_proc"); 
00259                         string::size_type pos2;
00260                         if(pos1 != std::string::npos){
00261                                 // get the end of the other start element
00262                                 pos1 = osol.find(">", pos1 + 1);
00263                                 if(pos1 != std::string::npos){
00264                                         // get the start of other end tag
00265                                         pos2 = osol.find( "</other", pos1 + 1);
00266                                         if( pos2 != std::string::npos){
00267                                                 // get the substring
00268                                                 num_proc = osol.substr( pos1 + 1, pos2 - pos1 - 1); 
00269                                         }
00270                                 }
00271                         }
00272                         //pass the option on
00273                         if(num_proc.size() > 0) si->setSymParam("max_active_nodes", num_proc);  
00274                 }
00275 #endif
00276                 //
00277                 //
00278                 //
00279                 // now some other Osi options
00280                 osiSolver->setHintParam(OsiDoScale, false, OsiHintTry);
00281                 osiSolver->setHintParam(OsiDoReducePrint, true, OsiHintTry);
00282                 OsiSolverInterface *m_OsiSolverPre = NULL;      
00283                 // try to catch Coin Solver errors
00284                 try{
00285                         if( osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0){
00286                                 //cout << "CALL BRANCH AND BOUND " << endl;
00287                                 // just use simple branch and bound for anything but cbc
00288                                 if( sSolverName.find( "cbc") == std::string::npos) {
00289                                         osiSolver->branchAndBound();    
00290                                 }
00291                                 else{
00292                                         // this is Solver Cbc
00293                                         // initial solve does not work on Jeff Camm problem without scaling
00294                                         //osiSolver->initialSolve();
00295                                         // copy from John Forrest examples in Cbc
00296                                         CglPreProcess process;
00297                         /* Do not try and produce equality cliques and
00298                            do up to 10 passes -- I use 10 because John does in Cbc and he is brilliant*/
00299                                         m_OsiSolverPre = process.preProcess(*osiSolver, false, 10);
00300                         if (!osiSolver) {
00301                           throw ErrorClass("Pre-processing says infeasible");
00302                         } else {
00303                                 printf("processed model has %d rows and %d columns\n",
00304                                         m_OsiSolverPre->getNumRows(), m_OsiSolverPre->getNumCols());
00305                         } 
00306                        osiSolver->setHintParam( OsiDoScale, true, OsiHintDo) ;
00307                        m_OsiSolverPre->branchAndBound( ); 
00308                        cout << "CALL POSTPROCESS " << endl;
00309                        process.postProcess( *m_OsiSolverPre);
00310                        cout << "DONE WITH CALL POSTROCESS " << endl;
00311                                 }
00312                         }
00313                         else{
00314                                 osiSolver->initialSolve();
00315                         }
00316                 }
00317                 catch(CoinError e){
00318                         std::string errmsg;
00319                         errmsg = "Coin Solver Error: " + e.message() + "\n" + " see method "  
00320                                 + e.methodName() + " in class " + e.className();
00321                         throw ErrorClass( errmsg );
00322                 }
00323                 int solIdx = 0;
00324                 std::string description = "";
00325                 osresult->setGeneralStatusType("success");
00326                 if (osiSolver->isProvenOptimal() == true){
00327                         osresult->setSolutionStatus(solIdx, "optimal", description);
00328                         /* Retrieve the solution */
00329                         x = new double[osinstance->getVariableNumber() ];
00330                         y = new double[osinstance->getConstraintNumber() ];
00331                         z = new double[1];
00332                         rcost = new std::string[ osinstance->getVariableNumber()];
00333                         //
00334                         *(z + 0)  =  osiSolver->getObjValue();
00335                         osresult->setObjectiveValues(solIdx, z);
00336                         for(i=0; i < osinstance->getVariableNumber(); i++){
00337                                 *(x + i) = osiSolver->getColSolution()[i];
00338                         }
00339                         osresult->setPrimalVariableValues(solIdx, x);
00340                         // Symphony does not get dual prices
00341                         if( sSolverName.find( "symphony") == std::string::npos){
00342                                 for(i=0; i <  osinstance->getConstraintNumber(); i++){
00343                                         *(y + i) = osiSolver->getRowPrice()[ i];
00344                                 }
00345                                 osresult->setDualVariableValues(solIdx, y);
00346                         }
00347                         //
00348                         //
00349                         // now put the reduced costs into the osrl
00350                         // Symphony does not get reduced costs
00351                         if( sSolverName.find( "symphony") == std::string::npos){
00352                                 int numberOfOtherVariableResult = 1;
00353                                 int otherIdx = 0;
00354                                 // first set the number of Other Variable Results
00355                                 osresult->setNumberOfOtherVariableResult(solIdx, numberOfOtherVariableResult);
00356                                 ostringstream outStr;
00357                                 int numberOfVar =  osinstance->getVariableNumber();
00358                                 for(i=0; i < numberOfVar; i++){
00359                                         outStr << osiSolver->getReducedCost()[ i]; 
00360                                         rcost[ i] = outStr.str();
00361                                         outStr.str("");
00362                                 }
00363                                 osresult->setAnOtherVariableResult(solIdx, otherIdx, "reduced costs", "the variable reduced costs", rcost);                     
00364                                 // end of settiing reduced costs
00365                         }                                       
00366                 }
00367                 else{ 
00368                         if(osiSolver->isProvenPrimalInfeasible() == true) 
00369                                 osresult->setSolutionStatus(solIdx, "infeasible", description);
00370                         else
00371                                 if(osiSolver->isProvenDualInfeasible() == true) 
00372                                         osresult->setSolutionStatus(solIdx, "dualinfeasible", description);
00373                                 else
00374                                         osresult->setSolutionStatus(solIdx, "other", description);
00375                 }
00376                 osrl = osrlwriter->writeOSrL( osresult);
00377                 if(osinstance->getVariableNumber() > 0) delete[] x;
00378                 x = NULL;
00379                 if(osinstance->getConstraintNumber()) delete[] y;
00380                 y = NULL;
00381                 delete[] z;     
00382                 z = NULL;
00383                 if(osinstance->getVariableNumber() > 0){
00384                         delete[] rcost;
00385                         rcost = NULL;
00386                 }
00387                 cout << "DONE WITH COIN SOLVER SOLVE" << endl;
00388         }
00389         catch(const ErrorClass& eclass){
00390                 osresult->setGeneralMessage( eclass.errormsg);
00391                 osresult->setGeneralStatusType( "error");
00392                 osrl = osrlwriter->writeOSrL( osresult);
00393                 throw ;
00394         }
00395 } // end solve
00396 
00397 std::string CoinSolver::getCoinSolverType(std::string lcl_osol){
00398 // this is deprecated, but keep it around
00399         try{
00400                 if( lcl_osol.find( "clp") != std::string::npos){
00401                         return "coin_solver_glpk";
00402                 }
00403                 else{
00404                         if( lcl_osol.find( "cbc") != std::string::npos){
00405                                 return "coin_solver_cpx";
00406                         }
00407                         else{
00408                                 if( lcl_osol.find( "cpx") != std::string::npos){
00409                                         return "coin_solver_clp";
00410                                 }
00411                                 else{
00412                                         if(lcl_osol.find( "glpk") != std::string::npos){
00413                                                 return "";
00414                                         }
00415                                         else throw ErrorClass("a supported solver was not defined");
00416                                 }
00417                         }
00418                 }
00419         }
00420         catch(const ErrorClass& eclass){
00421                 osresult->setGeneralMessage( eclass.errormsg);
00422                 osresult->setGeneralStatusType( "error");
00423                 osrl = osrlwriter->writeOSrL( osresult);
00424                 throw ;
00425         }
00426 } // end getCoinSolverType
00427 
00428 void CoinSolver::dataEchoCheck(){
00429         int i;
00430         // print out problem parameters
00431         cout << "This is problem:  " << osinstance->getInstanceName() << endl;
00432         cout << "The problem source is:  " << osinstance->getInstanceSource() << endl;
00433         cout << "The problem description is:  " << osinstance->getInstanceDescription() << endl;
00434         cout << "number of variables = " << osinstance->getVariableNumber() << endl;
00435         cout << "number of Rows = " << osinstance->getConstraintNumber() << endl;
00436 
00437         // print out the variable information
00438         if(osinstance->getVariableNumber() > 0){
00439                 for(i = 0; i < osinstance->getVariableNumber(); i++){
00440                         if(osinstance->getVariableNames() != NULL) cout << "variable Names  " << osinstance->getVariableNames()[ i]  << endl;
00441                         if(osinstance->getVariableTypes() != NULL) cout << "variable Types  " << osinstance->getVariableTypes()[ i]  << endl;
00442                         if(osinstance->getVariableLowerBounds() != NULL) cout << "variable Lower Bounds  " << osinstance->getVariableLowerBounds()[ i]  << endl;
00443                         if(osinstance->getVariableUpperBounds() != NULL) cout << "variable Upper Bounds  " <<  osinstance->getVariableUpperBounds()[i] << endl;
00444                 }
00445         }
00446         
00447         // print out objective function information
00448         if(osinstance->getVariableNumber() > 0 || osinstance->instanceData->objectives->obj != NULL || osinstance->instanceData->objectives->numberOfObjectives > 0){
00449                 if( osinstance->getObjectiveMaxOrMins()[0] == "min")  cout <<  "problem is a minimization" << endl;
00450                 else cout <<  "problem is a maximization" << endl;
00451                 for(i = 0; i < osinstance->getVariableNumber(); i++){
00452                         cout << "OBJ COEFFICIENT =  " <<  osinstance->getDenseObjectiveCoefficients()[0][i] << endl;
00453                 }
00454         }
00455         // print out constraint information
00456         if(osinstance->getConstraintNumber() > 0){
00457                 for(i = 0; i < osinstance->getConstraintNumber(); i++){
00458                         if(osinstance->getConstraintNames() != NULL) cout << "row name = " << osinstance->getConstraintNames()[i] <<  endl;
00459                         if(osinstance->getConstraintLowerBounds() != NULL) cout << "row lower bound = " << osinstance->getConstraintLowerBounds()[i] <<  endl;
00460                         if(osinstance->getConstraintUpperBounds() != NULL) cout << "row upper bound = " << osinstance->getConstraintUpperBounds()[i] <<  endl; 
00461                 }
00462         }
00463         
00464         // print out linear constraint data
00465         if(m_CoinPackedMatrix != NULL) m_CoinPackedMatrix->dumpMatrix();
00466 } // end dataEchoCheck
00467 
00468 
00469 
00470 
00471 

Generated on Sat Mar 29 22:38:02 2008 by  doxygen 1.5.3