/home/coin/SVN-release/OS-2.2.0/OS/src/OSSolverInterfaces/OSBonminSolver.cpp

Go to the documentation of this file.
00001 /* $Id: OSBonminSolver.cpp 3479 2010-04-26 07:14:52Z kmartin $ */
00020 //#define DEBUG
00021 
00022 #include <iostream>
00023 
00024 
00025 #include "OSBonminSolver.h"
00026 #include "OSDataStructures.h"
00027 #include "OSParameters.h" 
00028 #include "OSMathUtil.h"
00029 #include "CoinFinite.hpp"
00030 #include "BonOsiTMINLPInterface.hpp"
00031 #include "BonTMINLP.hpp"
00032 
00033 
00034 #include "CoinTime.hpp"
00035 
00036 using std::cout; 
00037 using std::endl; 
00038 using std::ostringstream;
00039 
00040 BonminSolver::BonminSolver() {
00041         osrlwriter = new OSrLWriter();
00042         osresult = new OSResult();      
00043         m_osilreader = NULL;
00044         m_osolreader = NULL;
00045         bonminErrorMsg = "";
00046 
00047 } 
00048 
00049 BonminSolver::~BonminSolver() {
00050         #ifdef DEBUG
00051         cout << "inside BonminSolver destructor" << endl;
00052         #endif
00053         if(m_osilreader != NULL) delete m_osilreader;
00054         m_osilreader = NULL;
00055         if(m_osolreader != NULL) delete m_osolreader;
00056         m_osolreader = NULL;
00057 
00058         if(osrlwriter != NULL )delete osrlwriter;
00059         osrlwriter = NULL;
00060                 if(osresult != NULL ){
00061                         delete osresult;
00062                         osresult = NULL;
00063                         //cout << "DELETING OS RESULT" << endl;
00064                 }
00065         #ifdef DEBUG
00066         cout << "leaving BonminSolver destructor" << endl;
00067         #endif
00068 }
00069 
00070 
00071 
00072 
00073 
00074 
00075 bool BonminProblem::get_variables_types(Index n, VariableType* var_types){
00076         int i = 0;
00077         char *varType;
00078         varType = osinstance->getVariableTypes();
00079         n = osinstance->getVariableNumber();
00080         for(i = 0; i < n;   i++){
00081                 if( varType[i] == 'B') {
00082                         var_types[i] = BINARY;
00083                 }
00084                 else{
00085                         if( varType[i] == 'I') {
00086                                 var_types[i] = INTEGER;
00087                         }
00088                         else{
00089                                 var_types[i] = CONTINUOUS;
00090                         }       
00091                 }
00092         }
00093         return true;
00094 }
00095 
00096 bool BonminProblem::get_variables_linearity(Index n, Ipopt::TNLP::LinearityType* var_types){
00097         
00098         
00099         
00100         std::cout << "Initialize Nonlinear Structures" << std::endl;
00101         try{
00102                 osinstance->initForAlgDiff( );
00103         }
00104         catch(const ErrorClass& eclass){
00105                 bonminErrorMsg = eclass.errormsg;
00106                 throw;  
00107         }       
00113         std::map<int, int> varIndexMap;
00114         std::map<int, int>::iterator posVarIndexMap;
00115         varIndexMap = osinstance->getAllNonlinearVariablesIndexMap( );
00116         /* first make all continuous */
00117         
00118         int i;
00119         
00120         for(i = 0; i < n; i++){
00121                 var_types[ i] = Ipopt::TNLP::LINEAR;    
00122         }
00127         for(posVarIndexMap = varIndexMap.begin(); posVarIndexMap != varIndexMap.end(); ++posVarIndexMap){
00128                         std::cout <<  "Variable Index = "   << posVarIndexMap->first  << std::endl ;
00129                         var_types[ posVarIndexMap->first] = Ipopt::TNLP::NON_LINEAR;
00130         }
00131         std::cout << "Number of nonlinear variables =  " << varIndexMap.size() << std::endl;    
00132 
00133         return true;
00134 }
00135 
00136 bool BonminProblem::get_constraints_linearity(Index m, Ipopt::TNLP::LinearityType* const_types){
00137         
00138         int i;
00139         
00140         for(i  = 0; i < m; i++){
00141                 const_types[ i] = Ipopt::TNLP::LINEAR;
00142         }
00143         
00144         
00145         int mm = osinstance->getNumberOfNonlinearExpressionTreeModIndexes();
00146         
00147 
00148         
00149         for(i = 0; i < mm; i++){
00150                 if(osinstance->getNonlinearExpressionTreeModIndexes()[ i] >= 0){
00151                         std::cout << osinstance->getNonlinearExpressionTreeModIndexes()[ i] << std::endl;
00152                         const_types[ osinstance->getNonlinearExpressionTreeModIndexes()[ i] ] = Ipopt::TNLP::NON_LINEAR;
00153                         
00154                 }
00155                 
00156         }
00157                 
00158         return true;
00159 }
00160 
00161 // returns the size of the problem
00162 bool BonminProblem::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
00163                              Index& nnz_h_lag, TNLP::IndexStyleEnum& index_style)
00164 {
00165         //if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Bonmin NEEDS AN OBJECTIVE FUNCTION");                     
00166         // number of variables
00167         n = osinstance->getVariableNumber();
00168         // number of constraints
00169         m = osinstance->getConstraintNumber();
00170         #ifdef DEBUG
00171         cout << "Bonmin number variables  !!!!!!!!!!!!!!!!!!!!!!!!!!!" << n << endl;
00172         cout << "Bonmin number constraints  !!!!!!!!!!!!!!!!!!!!!!!!!!!" << m << endl;
00173         #endif
00174         try{
00175                 osinstance->initForAlgDiff( ); 
00176         }
00177         catch(const ErrorClass& eclass){
00178                 bonminErrorMsg = eclass.errormsg;
00179                 throw;  
00180         }       
00181         // use the OS Expression tree for function evaluations instead of CppAD
00182         osinstance->bUseExpTreeForFunEval = true;
00183         //std::cout << "Call sparse jacobian" << std::endl;
00184         SparseJacobianMatrix *sparseJacobian = NULL;
00185         try{
00186                 sparseJacobian = osinstance->getJacobianSparsityPattern();
00187                 //cout << "Get sparse Jacobian pattern" << std::endl;
00188         }
00189         catch(const ErrorClass& eclass){
00190                 bonminErrorMsg = eclass.errormsg;
00191                 throw;  
00192         }
00193         //std::cout << "Done calling sparse jacobian" << std::endl;
00194         nnz_jac_g = sparseJacobian->valueSize;
00195         #ifdef DEBUG
00196         cout << "nnz_jac_g  !!!!!!!!!!!!!!!!!!!!!!!!!!!" << nnz_jac_g << endl;  
00197         #endif
00198         // nonzeros in upper hessian
00199         
00200         if( (osinstance->getNumberOfNonlinearExpressions() == 0) && (osinstance->getNumberOfQuadraticTerms() == 0) ) {
00201                 cout << "This is a linear program"  << endl;
00202                 nnz_h_lag = 0;
00203         }
00204         else{
00205                 //std::cout << "Get Lagrangain Hessian Sparsity Pattern " << std::endl;
00206                 SparseHessianMatrix *sparseHessian = osinstance->getLagrangianHessianSparsityPattern();
00207                 //std::cout << "Done Getting Lagrangain Hessian Sparsity Pattern " << std::endl;
00208                 nnz_h_lag = sparseHessian->hessDimension;
00209         }
00210         #ifdef DEBUG
00211         cout << "nnz_h_lag  !!!!!!!!!!!!!!!!!!!!!!!!!!!" << nnz_h_lag << endl;  
00212         #endif
00213         // use the C style indexing (0-based)
00214         index_style = TNLP::C_STYLE;
00215   
00216   return true;
00217 }//get_nlp_info
00218 
00219 
00220 bool  BonminProblem::get_bounds_info(Index n, Number* x_l, Number* x_u,
00221                                 Index m, Number* g_l, Number* g_u){
00222         int i; 
00223 
00224         double * mdVarLB = osinstance->getVariableLowerBounds();
00225         //std::cout << "GET BOUNDS INFORMATION FOR BONMIN !!!!!!!!!!!!!!!!!" << std::endl;
00226         // variables upper bounds
00227         double * mdVarUB = osinstance->getVariableUpperBounds();
00228 
00229         for(i = 0; i < n; i++){
00230                 x_l[ i] = mdVarLB[ i];
00231                 x_u[ i] = mdVarUB[ i];
00232                 #ifdef DEBUG
00233                 cout << "x_l !!!!!!!!!!!!!!!!!!!!!!!!!!!" << x_l[i] << endl;
00234                 cout << "x_u !!!!!!!!!!!!!!!!!!!!!!!!!!!" << x_u[i] << endl;
00235                 #endif
00236         }
00237         // Bonmin interprets any number greater than nlp_upper_bound_inf as
00238         // infinity. The default value of nlp_upper_bound_inf and nlp_lower_bound_inf
00239         // is 1e19 and can be changed through bonmin options.
00240         // e.g. g_u[0] = 2e19;
00241 
00242         //constraint lower bounds
00243         double * mdConLB = osinstance->getConstraintLowerBounds();
00244         //constraint upper bounds
00245         double * mdConUB = osinstance->getConstraintUpperBounds();
00246         
00247         for(int i = 0; i < m; i++){
00248                 g_l[ i] = mdConLB[ i];
00249                 g_u[ i] = mdConUB[ i];
00250                 #ifdef DEBUG
00251                 cout << "lower !!!!!!!!!!!!!!!!!!!!!!!!!!!" << g_l[i] << endl;
00252                 cout << "upper !!!!!!!!!!!!!!!!!!!!!!!!!!!" << g_u[i] << endl;
00253                 #endif
00254         }  
00255         return true;
00256 }//get_bounds_info
00257 
00258 
00259 // returns the initial point for the problem
00260 bool BonminProblem::get_starting_point(Index n, bool init_x, Number* x,
00261      bool init_z, Number* z_L, Number* z_U, Index m, bool init_lambda,
00262      Number* lambda) {
00263         // Here, we assume we only have starting values for x, if you code
00264         // your own NLP, you can provide starting values for the dual variables
00265         // if you wish
00266         assert(init_x == true);
00267         assert(init_z == false);
00268         assert(init_lambda == false);
00269         int i, m1, n1;
00270         
00271 
00272 #ifdef DEBUG
00273         cout << "get initial values !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
00274 #endif
00275         
00276         //now set initial values
00277 #ifdef DEBUG
00278         cout << "get number of initial values !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
00279 #endif
00280         int k;
00281         if (osoption != NULL)
00282                 m1 = osoption->getNumberOfInitVarValues();
00283         else
00284                 m1 = 0;
00285 #ifdef DEBUG
00286         cout << "number of variables initialed: " << m1 << endl;
00287 #endif
00288 
00289         n1 = osinstance->getVariableNumber();
00290         bool* initialed;
00291         initialed = new bool[n1];
00292 #ifdef DEBUG
00293         cout << "number of variables in total: " << n1 << endl;
00294 #endif
00295 
00296 
00297         for(k = 0; k < n1; k++)
00298                 initialed[k] = false;
00299 
00300         if (m1 > 0)
00301         {
00302 #ifdef DEBUG
00303                         cout << "get initial values " << endl;
00304 #endif
00305 
00306                 InitVarValue**  initVarVector = osoption->getInitVarValuesSparse();
00307 #ifdef DEBUG
00308                 cout << "done " << endl;
00309 #endif
00310 
00311                 double initval;
00312                 try 
00313                 {
00314                         for(k = 0; k < m1; k++)
00315                         {       
00316                                 i = initVarVector[k]->idx;
00317                                 if (initVarVector[k]->idx > n1)
00318                                         throw ErrorClass ("Illegal index value in variable initialization");
00319 
00320                                 initval = initVarVector[k]->value;
00321                                 if (osinstance->instanceData->variables->var[i]->ub == OSDBL_MAX)
00322                                 {       if (osinstance->instanceData->variables->var[i]->lb > initval)
00323                                                 throw ErrorClass ("Initial value outside of bounds");
00324                                 }
00325                                 else
00326                                         if (osinstance->instanceData->variables->var[i]->lb == -OSDBL_MAX)
00327                                         {       if (osinstance->instanceData->variables->var[i]->ub < initval)
00328                                                         throw ErrorClass ("Initial value outside of bounds");
00329                                         }
00330                                         else
00331                                         {       if ((osinstance->instanceData->variables->var[i]->lb > initval) ||
00332                                                         (osinstance->instanceData->variables->var[i]->ub < initval))
00333                                                         throw ErrorClass ("Initial value outside of bounds");
00334                                         }
00335 
00336                                 x[initVarVector[k]->idx] = initval;
00337                                 initialed[initVarVector[k]->idx] = true;
00338                         }
00339                 }
00340                 catch(const ErrorClass& eclass){
00341                         cout << "Error in BonminProblem::get_starting_point (OSBonminSolver.cpp)";
00342                         cout << endl << endl << endl;
00343                 }       
00344         }  //  end if (m1 > 0)          
00345 
00346         double default_initval;
00347         default_initval = 1.7171;
00348         
00349 
00350         for(k = 0; k < n1; k++)
00351         {
00352                 if (!initialed[k])
00353                         if (osinstance->instanceData->variables->var[k]->ub == OSDBL_MAX)
00354                                 if (osinstance->instanceData->variables->var[k]->lb <= default_initval)
00355                                         x[k] = default_initval;
00356                                 else
00357                                         x[k] = osinstance->instanceData->variables->var[k]->lb;
00358                         else
00359                                 if (osinstance->instanceData->variables->var[k]->lb == -OSDBL_MAX)
00360                                         if (osinstance->instanceData->variables->var[k]->ub >= default_initval)
00361                                                 x[k] = default_initval;
00362                                         else
00363                                                 x[k] = osinstance->instanceData->variables->var[k]->ub;
00364                                 else
00365                                         if ((osinstance->instanceData->variables->var[k]->lb <= default_initval) && 
00366                                                 (osinstance->instanceData->variables->var[k]->ub >= default_initval))
00367                                                 x[k] = default_initval;
00368                                         else
00369                                                 if (osinstance->instanceData->variables->var[k]->lb > default_initval)
00370                                                         x[k] = osinstance->instanceData->variables->var[k]->lb;
00371                                                 else
00372                                                         x[k] = osinstance->instanceData->variables->var[k]->ub;
00373         }
00374         for(i = 0; i < n1; i++){
00375                 #ifdef DEBUG
00376                 std::cout << "INITIAL VALUE !!!!!!!!!!!!!!!!!!!!  " << x[ i] << std::endl;
00377                 #endif
00378         }
00379  
00380         osinstance->calculateAllObjectiveFunctionValues( x, true);
00381         delete[] initialed;
00382         return true;
00383 }//get_starting_point
00384 
00385 
00386 // returns the value of the objective function
00387 bool BonminProblem::eval_f(Index n, const Number* x, bool new_x, Number& obj_value){
00388         
00389         try{
00390                 if(osinstance->getObjectiveNumber() > 0){
00391                         if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") == 0){
00392                                 obj_value  = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 )[ 0];       
00393                         }else{// we have a max
00394                                 obj_value  = -osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 )[ 0];
00395                         }
00396                 }
00397         }
00398         catch(const ErrorClass& eclass){
00399                 bonminErrorMsg = eclass.errormsg;
00400                 throw;  
00401         }
00402         if( CoinIsnan( (double)obj_value) ) return false;
00403         return true;
00404 }
00405 
00406 bool BonminProblem::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f){
00407         int i;
00408         double *objGrad = NULL;
00409         if(osinstance->getObjectiveNumber() > 0){
00410                 try{
00411                         //objGrad = osinstance->calculateAllObjectiveFunctionGradients( const_cast<double*>(x), NULL, NULL,  new_x, 1)[ 0];
00412                         //std::cout << "Calculate Objective function gradient " << std::endl;
00413                         // we assume we are doing the objective function indexed by -1
00414                         objGrad = osinstance->calculateObjectiveFunctionGradient( const_cast<double*>(x), NULL, NULL, -1,  new_x, 1);
00415                 }
00416         catch(const ErrorClass& eclass){
00417                         bonminErrorMsg = eclass.errormsg;
00418                         throw;  
00419                 }
00420 
00421                 for(i = 0; i < n; i++){
00422                         if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") == 0){
00423                                 grad_f[ i]  = objGrad[ i];
00424                         }else{
00425                                 grad_f[ i]  = -objGrad[ i];
00426                         }
00427                         //std::cout << grad_f[ i]  << std::endl;
00428                 }
00429         }
00430 //std::cout << "DONE WITH Calculate Objective function gradient " << std::endl;
00431         return true;
00432 }//eval_grad_f
00433 
00434 // return the value of the constraints: g(x)
00435 bool BonminProblem::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) {
00436         try{
00437                 double *conVals = osinstance->calculateAllConstraintFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 );
00438                 int i;
00439                 for(i = 0; i < m; i++){
00440                         if( CoinIsnan( (double)conVals[ i] ) ) return false;
00441                         g[i] = conVals[ i]  ;   
00442                 } 
00443                 return true;
00444         }
00445         catch(const ErrorClass& eclass){
00446                 bonminErrorMsg = eclass.errormsg;
00447                 throw;  
00448         }
00449 }//eval_g
00450 
00451 
00452 // return the structure or values of the jacobian
00453 bool BonminProblem::eval_jac_g(Index n, const Number* x, bool new_x,
00454                            Index m, Index nele_jac, Index* iRow, Index *jCol,
00455                            Number* values){
00456         SparseJacobianMatrix *sparseJacobian;
00457         if (values == NULL) {
00458                 // return the values of the jacobian of the constraints
00459                 //cout << "n: " << n << endl;
00460                 //cout << "m: " << m << endl;
00461                 //cout << "nele_jac: " <<  nele_jac << endl;
00462                 // return the structure of the jacobian
00463                 try{
00464                         sparseJacobian = osinstance->getJacobianSparsityPattern();
00465                 }
00466                 catch(const ErrorClass& eclass){
00467                         bonminErrorMsg =  eclass.errormsg; 
00468                         throw; 
00469                 }
00470                 int i = 0;
00471                 int k, idx;
00472                 for(idx = 0; idx < m; idx++){
00473                         for(k = *(sparseJacobian->starts + idx); k < *(sparseJacobian->starts + idx + 1); k++){
00474                                 iRow[i] = idx;
00475                                 jCol[i] = *(sparseJacobian->indexes + k);
00476                                 //cout << "ROW IDX  !!!!!!!!!!!!!!!!!!!!!!!!!!!"  << iRow[i] << endl;
00477                                 //cout << "COL IDX  !!!!!!!!!!!!!!!!!!!!!!!!!!!"  << jCol[i] << endl;
00478                                 i++;
00479                         }
00480                 }
00481         }
00482         else {
00483                 //std::cout << "EVALUATING JACOBIAN" << std::endl; 
00484                 try{
00485                         sparseJacobian = osinstance->calculateAllConstraintFunctionGradients( const_cast<double*>(x), NULL, NULL,  new_x, 1);
00486                 }
00487                 catch(const ErrorClass& eclass){
00488                         bonminErrorMsg = eclass.errormsg;
00489                         throw;  
00490                 }
00491                 //osinstance->getIterateResults( (double*)x, 0.0, NULL, -1, new_x,  1);
00492                 for(int i = 0; i < nele_jac; i++){
00493                         values[ i] = sparseJacobian->values[i];
00494                         //values[ i] = osinstance->m_mdJacValue[ i];
00495                         //cout << "values[i]:!!!!!!!!!!!!  " <<  values[ i] << endl;
00496                         //cout << "m_mdJacValue[ i]:!!!!!!!!!!!!  " <<  osinstance->m_mdJacValue[ i] << endl;
00497                 }
00498         }
00499   return true;
00500 }//eval_jac_g
00501 
00502 //return the structure or values of the hessian
00503 bool BonminProblem::eval_h(Index n, const Number* x, bool new_x,
00504                        Number obj_factor, Index m, const Number* lambda,
00505                        bool new_lambda, Index nele_hess, Index* iRow,
00506                        Index* jCol, Number* values){
00507 
00509         SparseHessianMatrix *sparseHessian;
00510         
00511         int i;
00512         if (values == NULL) {
00513                 // return the structure. This is a symmetric matrix, fill the lower left triangle only.
00514                 //cout << "get structure of HESSIAN !!!!!!!!!!!!!!!!!!!!!!!!!! "  << endl;
00515                 try{
00516                         sparseHessian = osinstance->getLagrangianHessianSparsityPattern( );
00517                 }
00518                 catch(const ErrorClass& eclass){
00519                         bonminErrorMsg = eclass.errormsg;
00520                         throw;  
00521                 }
00522                 //cout << "got structure of HESSIAN !!!!!!!!!!!!!!!!!!!!!!!!!! "  << endl;
00523                 for(i = 0; i < nele_hess; i++){
00524                         iRow[i] = *(sparseHessian->hessColIdx + i);
00525                         jCol[i] = *(sparseHessian->hessRowIdx + i);
00526                                 //cout << "ROW HESS IDX  !!!!!!!!!!!!!!!!!!!!!!!!!!!"  << iRow[i] << endl;
00527                                 //cout << "COL HESS IDX  !!!!!!!!!!!!!!!!!!!!!!!!!!!"  << jCol[i] << endl;
00528                 }
00529         }
00530         else {
00531                 //std::cout << "EVALUATING HESSIAN" << std::endl; 
00532                 // return the values. This is a symmetric matrix, fill the lower left triangle only
00533                 double* objMultipliers = new double[1];
00534                 objMultipliers[0] = obj_factor;
00535                 try{
00536                         sparseHessian = osinstance->calculateLagrangianHessian( const_cast<double*>(x), objMultipliers, const_cast<double*>(lambda) ,  new_x, 2);
00537                 delete[]  objMultipliers;
00538                 }
00539                 catch(const ErrorClass& eclass){
00540                         bonminErrorMsg = eclass.errormsg;
00541                         delete[]  objMultipliers;
00542                         throw;  
00543                 }
00544                 for(i = 0; i < nele_hess; i++){
00545                         values[ i]  = *(sparseHessian->hessValues + i);
00546                 }
00547         }
00549         return true;
00550 }//eval_h
00551 
00552 bool BonminProblem::get_scaling_parameters(Number& obj_scaling,
00553                         bool& use_x_scaling, Index n,
00554                         Number* x_scaling,
00555                     bool& use_g_scaling, Index m,
00556                     Number* g_scaling){
00557         /*
00558          * Bonmin assumes problems cast as a min
00559          * if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") != 0){
00560                 obj_scaling = -1;
00561         }
00562     else obj_scaling = 1;
00563     use_x_scaling = false;
00564     use_g_scaling = false;
00565     */
00566         return true;
00567 }//get_scaling_parameters
00568 
00569 
00570 
00571 
00572 void BonminProblem::finalize_solution(TMINLP::SolverReturn status_,
00573                             Index n, const Number* x, Number obj_value)
00574 {
00575         
00576         status = status_;
00577         #ifdef DEBUG
00578         std::cout << "FINALIZE OBJ SOLUTION VALUE = " << obj_value << std::endl;
00579         #endif
00580 
00581 }
00582 
00583 
00584    
00585 
00586 void BonminSolver::buildSolverInstance() throw (ErrorClass) {
00587         try{    
00588                 
00589                 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00590                 if(osinstance == NULL){
00591                         m_osilreader = new OSiLReader();
00592                         osinstance = m_osilreader->readOSiL( osil);
00593                 }
00594                 // Create a new instance of your nlp 
00595                 tminlp = new BonminProblem( osinstance, osoption);
00596                 this->bCallbuildSolverInstance = true;
00597                 //Now initialize from tminlp
00598                 //bonminSetup.initialize( GetRawPtr(tminlp) );
00599         }
00600         catch(const ErrorClass& eclass){
00601                 std::cout << "THERE IS AN ERROR" << std::endl;
00602                 osresult->setGeneralMessage( eclass.errormsg);
00603                 osresult->setGeneralStatusType( "error");
00604                 osrl = osrlwriter->writeOSrL( osresult);
00605                 throw ErrorClass( osrl) ;
00606         }                               
00607 }//end buildSolverInstance() 
00608 
00609 
00610 
00611 void BonminSolver::setSolverOptions() throw (ErrorClass) {
00612         try{
00613                 this->bSetSolverOptions = true;
00614                 bonminSetup.initializeOptionsAndJournalist();
00615                 //Register an additional option -- just an example
00616                 bonminSetup.roptions()->AddStringOption2("print_solution","Do we print the solution or not?",
00617                                                  "yes",
00618                                                  "no", "No, we don't.",
00619                                                  "yes", "Yes, we do.",
00620                                                  "A longer comment can be put here");
00621                   
00622                  // Here we can change the default value of some Bonmin or Ipopt option
00623                 bonminSetup.options()->SetNumericValue("bonmin.time_limit", 5000); //changes bonmin's time limit
00624                 //bonminSetup.options()->SetIntegerValue("bonmin.num_resolve_at_node", 3); 
00625                 //bonminSetup.options()->SetIntegerValue("bonmin.num_resolve_at_root", 3); 
00626                 //bonminSetup.options()->SetIntegerValue("bonmin.num_retry_unsolved_random_point", 30); 
00627                 //bonminSetup.options()->SetIntegerValue("print_level", 12); 
00628                 //bonminSetup.options()->SetIntegerValue("bonmin.bb_log_level", 4); 
00629                 //bonminSetup.options()->SetStringValue("bonmin.nlp_failure_behavior", "fathom");
00630                 //bonminSetup.options()->SetNumericValue("bonmin.allowable_gap", -1);
00631                 //bonminSetup.options()->SetNumericValue("bonmin.allowable_fraction_gap", -.1);
00632                 //bonminSetup.options()->SetNumericValue("bonmin.cutoff_decr", -1);
00633                 //bonminSetup.options()->SetStringValue("mu_oracle","loqo");
00634         
00635         
00636                 //Here we read several option files
00637                 //bonminSetup.readOptionsFile("Mybonmin.opt");
00638                 //bonminSetup.readOptionsFile();// This reads the default file "bonmin.opt"
00639                   
00640                 // Options can also be set by using a string with a format similar to the bonmin.opt file
00641                 bonminSetup.readOptionsString("bonmin.algorithm B-BB\n");
00642                 
00643                                 //turn off a lot of output -- this can be overridden by using OSOptions
00644                 bonminSetup.options()->SetIntegerValue("bonmin.bb_log_level", 0 );
00645                 bonminSetup.options()->SetIntegerValue("bonmin.nlp_log_level", 0 );
00646                   
00647                 // Now we can obtain the value of the new option
00648                 int printSolution;
00649                 bonminSetup.options()->GetEnumValue("print_solution", printSolution,"");
00650                 if(printSolution == 1){
00651                         tminlp->printSolutionAtEndOfAlgorithm();
00652                 }       
00653                 //
00654                 if(osoption == NULL && osol.length() > 0)
00655                 {
00656                         m_osolreader = new OSoLReader();
00657                         osoption = m_osolreader->readOSoL( osol);
00658                 }
00659 
00660                 if(osoption != NULL && osoption->getNumberOfSolverOptions() > 0 ){
00661                         char *pEnd;
00662                         int i;
00663                         std::vector<SolverOption*> optionsVector;
00664                         optionsVector = osoption->getSolverOptions( "bonmin");
00665                         int num_bonmin_options = optionsVector.size();
00666                         for(i = 0; i < num_bonmin_options; i++){
00667                                 if(optionsVector[ i]->type == "numeric" ){
00668                                         std::cout << "FOUND A  NUMERIC OPTION  "  <<  os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) << std::endl;
00669                                         if(optionsVector[ i]->category == "ipopt"){
00670                                                 bonminSetup.options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) ); 
00671                                         }else{
00672                                                 if(optionsVector[ i]->category == "cbc" ){
00673                                                         bonminSetup.options()->SetNumericValue("milp_solver."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00674                                                 }
00675                                                 else{
00676                                                         bonminSetup.options()->SetNumericValue("bonmin."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );       
00677                                                 }
00678                                         }
00679                                 }  
00680                                 else if(optionsVector[ i]->type == "integer" ){
00681                                         std::cout << "FOUND AN INTEGER OPTION  "  <<optionsVector[ i]->name << std::endl;
00682                                         if(optionsVector[ i]->category == "ipopt"){
00683                                                 bonminSetup.options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );     
00684                                         }else{
00685                                                 if(optionsVector[ i]->category == "cbc" ){
00686                                                         std::cout << "SETTING INTEGER CBC OPTION" << std::endl;
00687                                                         bonminSetup.options()->SetIntegerValue("milp_solver."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ));
00688                                                 }
00689                                                 else{
00690                                                         bonminSetup.options()->SetIntegerValue("bonmin."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() )  );  
00691                                                 }
00692                                         }                                       
00693                                 }
00694                                 else if(optionsVector[ i]->type == "string" ){
00695                                         std::cout << "FOUND A STRING OPTION  "  <<optionsVector[ i]->name << std::endl;
00696                                         if(optionsVector[ i]->category == "ipopt"){
00697                                                 bonminSetup.options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value );      
00698                                         }else{
00699                                                 if(optionsVector[ i]->category == "cbc" ){
00700                                                         bonminSetup.options()->SetStringValue("milp_solver."+optionsVector[ i]->name, optionsVector[ i]->value);
00701                                                 }
00702                                                 else{
00703                                                         bonminSetup.options()->SetStringValue("bonmin."+optionsVector[ i]->name, optionsVector[ i]->value);     
00704                                                 }
00705                                         }       
00706 
00707                                 }
00708                         }       
00709                 }
00710                 
00711         }
00712         
00713         catch(const ErrorClass& eclass){
00714                 std::cout << "THERE IS AN ERROR" << std::endl;
00715                 osresult->setGeneralMessage( eclass.errormsg);
00716                 osresult->setGeneralStatusType( "error");
00717                 osrl = osrlwriter->writeOSrL( osresult);
00718                 throw ErrorClass( osrl) ;
00719         }                               
00720 }//end setSolverOptions() 
00721 
00722 
00723 //void BonminSolver::solve() throw (ErrorClass) {
00724 void BonminSolver::solve() throw (ErrorClass) {
00725                 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00726                 if( this->bSetSolverOptions == false) setSolverOptions();
00727         try{
00728 
00729                 //if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Bonmin NEEDS AN OBJECTIVE FUNCTION");
00730                 //double start = CoinCpuTime();
00731                 //OSiLWriter osilwriter;
00732                 //cout << osilwriter.writeOSiL( osinstance) << endl;
00733                 //if(osinstance->getVariableNumber() <= 0)throw ErrorClass("Bonmin requires decision variables");
00734                 //double duration = CoinCpuTime() - start;
00735 
00736                   try {
00737                           bonminSetup.initialize( GetRawPtr(tminlp) );
00738                     // bb is a Bonmin BonCbc object;;
00739                     bb(  bonminSetup);  //process parameter file using Ipopt and do branch and bound using Cbc
00740 
00741                   }
00742                   catch(TNLPSolver::UnsolvedError *E) {
00743                     //There has been a failure to solve a problem with Ipopt.
00744                     std::cerr<<"Ipopt has failed to solve a problem"<<std::endl;
00745                   }
00746                   catch(OsiTMINLPInterface::SimpleError &E) {
00747                     std::cerr<<E.className()<<"::"<<E.methodName()
00748                              <<std::endl
00749                              <<E.message()<<std::endl;
00750                   }
00751                   catch(CoinError &E) {
00752                     std::cerr<<E.className()<<"::"<<E.methodName()
00753                              <<std::endl
00754                              <<E.message()<<std::endl;
00755                   }
00756                   
00757         if(( bb.model().isContinuousUnbounded() == true) && (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() <= 0) ){
00758                 std::string solutionDescription = "";
00759                 std::string message = "Success";
00760                 int solIdx = 0;
00761 
00762                 if(osresult->setServiceName( "Bonin solver service") != true)
00763                         throw ErrorClass("OSResult error: setServiceName");
00764                 if(osresult->setInstanceName(  osinstance->getInstanceName()) != true)
00765                         throw ErrorClass("OSResult error: setInstanceName");
00766                 if(osresult->setVariableNumber( osinstance->getVariableNumber()  ) != true)
00767                         throw ErrorClass("OSResult error: setVariableNumber");
00768                 if(osresult->setObjectiveNumber( 1) != true)
00769                         throw ErrorClass("OSResult error: setObjectiveNumber");
00770                 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00771                         throw ErrorClass("OSResult error: setConstraintNumber");
00772                 if(osresult->setSolutionNumber(  1) != true)
00773                         throw ErrorClass("OSResult error: setSolutionNumer");           
00774                 if(osresult->setGeneralMessage( message) != true)
00775                         throw ErrorClass("OSResult error: setGeneralMessage");
00776                 solutionDescription = "The problem is unbounded";
00777                         osresult->setSolutionStatus(solIdx,  "error", solutionDescription);     
00778                 osresult->setGeneralStatusType("normal");
00779                 if( osinstance->getVariableNumber() == 0) osresult->setSolutionMessage(solIdx, "Warning: this problem has zero decision variables!");
00780                 osrl = osrlwriter->writeOSrL( osresult);                
00781                 return;
00782         }
00783         
00784         
00785         if(( bb.model().isProvenInfeasible() == true)  ){
00786                 std::string solutionDescription = "";
00787                 std::string message = "Success";
00788                 int solIdx = 0;
00789                 
00790 
00791                 if(osresult->setServiceName( "Bonin solver service") != true)
00792                         throw ErrorClass("OSResult error: setServiceName");
00793                 if(osresult->setInstanceName(  osinstance->getInstanceName()) != true)
00794                         throw ErrorClass("OSResult error: setInstanceName");
00795                 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00796                         throw ErrorClass("OSResult error: setVariableNumer");
00797                 if(osresult->setObjectiveNumber( 1) != true)
00798                         throw ErrorClass("OSResult error: setObjectiveNumber");
00799                 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00800                         throw ErrorClass("OSResult error: setConstraintNumber");
00801                 if(osresult->setSolutionNumber(  1) != true)
00802                         throw ErrorClass("OSResult error: setSolutionNumber");          
00803                 if(osresult->setGeneralMessage( message) != true)
00804                         throw ErrorClass("OSResult error: setGeneralMessage");
00805                 solutionDescription = "The problem is infeasible";
00806                         osresult->setSolutionStatus(solIdx,  "error", solutionDescription);     
00807                 osresult->setGeneralStatusType("normal");
00808                 if( osinstance->getVariableNumber() == 0) osresult->setSolutionMessage(solIdx, "Warning: this problem has zero decision variables!");
00809                 osrl = osrlwriter->writeOSrL( osresult);                
00810                 return;
00811         }
00812             status = tminlp->status;
00813             writeResult();
00814 
00815         }
00816         catch(const ErrorClass& eclass){
00817                 osresult->setGeneralMessage( eclass.errormsg);
00818                 osresult->setGeneralStatusType( "error");
00819                 osrl = osrlwriter->writeOSrL( osresult);
00820                 throw ErrorClass( osrl) ;
00821         }
00822 }//solve
00823 
00824 
00825 
00826 
00827 void BonminSolver::writeResult(){
00828         double *x = NULL;
00829         double *z = NULL;
00830         int i = 0;
00831         int solIdx = 0;
00832         std::string solutionDescription = "";
00833         std::string message = "Bonmin solver finishes to the end.";
00834         if( osinstance->getVariableNumber() == 0) osresult->setSolutionMessage(0, "Warning: this problem has zero decision variables!");
00835         
00836         
00837         try{
00838                 if(osinstance->getVariableNumber()  > 0) x = new double[osinstance->getVariableNumber() ];
00839                 z = new double[1];              
00840                 // resultHeader information
00841                 if(osresult->setServiceName( getVersionInfo()) != true)
00842                         throw ErrorClass("OSResult error: setServiceName");
00843                 if(osresult->setSolverInvoked( "COIN-OR Bonmin") != true)
00844                         throw ErrorClass("OSResult error: setSolverInvoked");
00845                 if(osresult->setInstanceName(  osinstance->getInstanceName()) != true)
00846                         throw ErrorClass("OSResult error: setInstanceName");    
00847                 //if(osresult->setJobID( osoption->jobID) != true)
00848                 //      throw ErrorClass("OSResult error: setJobID");   
00849                 // set basic problem parameters
00850                 
00851                 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00852                         throw ErrorClass("OSResult error: setVariableNumer");
00853                 if(osresult->setObjectiveNumber( 1) != true)
00854                         throw ErrorClass("OSResult error: setObjectiveNumber");
00855                 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00856                         throw ErrorClass("OSResult error: setConstraintNumber");
00857                 if(osresult->setSolutionNumber(  1) != true)
00858                         throw ErrorClass("OSResult error: setSolutionNumer");           
00859                 if(osresult->setGeneralMessage( message) != true)
00860                         throw ErrorClass("OSResult error: setGeneralMessage");
00861         
00862                 switch( status){
00863                         case  TMINLP::SUCCESS:
00864                                 solutionDescription = "SUCCESS[BONMIN]: Algorithm terminated normally at a locally optimal point, satisfying the convergence tolerances.";
00865                                 //std::cout << solutionDescription << std::endl;
00866                                 osresult->setSolutionStatus(solIdx,  "locallyOptimal", solutionDescription);            
00867                                 /* Retrieve the solution */
00868                                 if(osinstance->getObjectiveNumber() > 0){
00869                                         *(z + 0)  =  osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
00870                                         osresult->setObjectiveValuesDense(solIdx, z); 
00871                                 }
00872                                 if( osinstance->getVariableNumber() > 0){
00873                                         for(i=0; i < osinstance->getVariableNumber(); i++){
00874                                                 *(x + i) = bb.bestSolution()[i];
00875                                                 //std::cout <<  *(x + i)  << std::endl;
00876                                         }
00877                                         osresult->setPrimalVariableValuesDense(solIdx, x);
00878                                 }
00879                         break;
00880                         
00881                         case TMINLP::LIMIT_EXCEEDED:
00882                                 solutionDescription = "LIMIT_EXCEEDED[BONMIN]: A resource limit was exceeded, we provide the current solution.";
00883                                 //std::cout << solutionDescription << std::endl;
00884                                 osresult->setSolutionStatus(solIdx,  "other", solutionDescription);
00885                                 //osresult->setPrimalVariableValuesDense(solIdx, const_cast<double*>(x));
00886                                 //osresult->setDualVariableValuesDense(solIdx, const_cast<double*>( lambda));   
00887                                 /* Retrieve the solution */
00888                                 if(osinstance->getObjectiveNumber() > 0){
00889                                         *(z + 0)  =  osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
00890                                         osresult->setObjectiveValuesDense(solIdx, z); 
00891                                 }
00892                                 if( osinstance->getVariableNumber() > 0){
00893                                         for(i=0; i < osinstance->getVariableNumber(); i++){
00894                                                 *(x + i) = bb.bestSolution()[i];
00895                                                 //std::cout <<  *(x + i)  << std::endl;
00896                                         }
00897                                         osresult->setPrimalVariableValuesDense(solIdx, x);
00898                                 }
00899                         break;
00900                         
00901                         case TMINLP::MINLP_ERROR:
00902                                 solutionDescription = "MINLP_ERROR [BONMIN]: Algorithm stopped with unspecified error.";
00903                                 //std::cout << solutionDescription << std::endl;
00904                                 osresult->setSolutionStatus(solIdx,  "error", solutionDescription);     
00905 
00906                         break;
00907                         
00908                         case TMINLP::CONTINUOUS_UNBOUNDED:
00909                                 solutionDescription = "CONTINUOUS_UNBOUNDED [BONMIN]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00910                                 //std::cout << solutionDescription << std::endl;
00911                                 osresult->setSolutionStatus(solIdx,  "error", solutionDescription);     
00912 
00913                         break;
00914                         
00915                 
00916                         case TMINLP::INFEASIBLE:
00917                                 solutionDescription = "INFEASIBLE [BONMIN]: Problem may be infeasible.";
00918                                 //std::cout << solutionDescription << std::endl;
00919                                 osresult->setSolutionStatus(solIdx,  "infeasible", solutionDescription);
00920                         break;
00921                         
00922                         
00923                         default:
00924                                 solutionDescription = "OTHER[BONMIN]: other unknown solution status from Bonmin solver";
00925                                 //std::cout << solutionDescription << std::endl;
00926                                 osresult->setSolutionStatus(solIdx,  "other", solutionDescription);
00927                 }//switch end   
00928                 osresult->setGeneralStatusType("normal");
00929                 osrl = osrlwriter->writeOSrL( osresult);
00930                 if(osinstance->getVariableNumber() > 0 ) delete[] x;
00931                 x = NULL;
00932                 delete[] z;     
00933                 z = NULL;
00934         }//end try
00935         
00936         
00937         catch(const ErrorClass& eclass){
00938                 if(osinstance->getVariableNumber()  > 0) delete[] x;
00939                 x = NULL;
00940                 delete[] z;     
00941                 z = NULL;
00942                 osresult->setGeneralMessage( eclass.errormsg);
00943                 osresult->setGeneralStatusType( "error");
00944                 osrl = osrlwriter->writeOSrL( osresult);
00945                 throw ErrorClass( osrl) ;
00946         }       
00947         
00948         
00949 }// end writeResult()
00950 
00951 
00952 void BonminSolver::dataEchoCheck(){
00953         
00954         int i;
00955         
00956         // print out problem parameters
00957         cout << "This is problem:  " << osinstance->getInstanceName() << endl;
00958         cout << "The problem source is:  " << osinstance->getInstanceSource() << endl;
00959         cout << "The problem description is:  " << osinstance->getInstanceDescription() << endl;
00960         cout << "number of variables = " << osinstance->getVariableNumber() << endl;
00961         cout << "number of Rows = " << osinstance->getConstraintNumber() << endl;
00962 
00963         // print out the variable information
00964         if(osinstance->getVariableNumber() > 0){
00965                 for(i = 0; i < osinstance->getVariableNumber(); i++){
00966                         if(osinstance->getVariableNames() != NULL) cout << "variable Names  " << osinstance->getVariableNames()[ i]  << endl;
00967                         if(osinstance->getVariableTypes() != NULL) cout << "variable Types  " << osinstance->getVariableTypes()[ i]  << endl;
00968                         if(osinstance->getVariableLowerBounds() != NULL) cout << "variable Lower Bounds  " << osinstance->getVariableLowerBounds()[ i]  << endl;
00969                         if(osinstance->getVariableUpperBounds() != NULL) cout << "variable Upper Bounds  " <<  osinstance->getVariableUpperBounds()[i] << endl;
00970                 }
00971         }
00972         
00973         // print out objective function information
00974         if(osinstance->getVariableNumber() > 0 || osinstance->instanceData->objectives->obj != NULL || osinstance->instanceData->objectives->numberOfObjectives > 0){
00975                 if( osinstance->getObjectiveMaxOrMins()[0] == "min")  cout <<  "problem is a minimization" << endl;
00976                 else cout <<  "problem is a maximization" << endl;
00977                 for(i = 0; i < osinstance->getVariableNumber(); i++){
00978                         cout << "OBJ COEFFICIENT =  " <<  osinstance->getDenseObjectiveCoefficients()[0][i] << endl;
00979                 }
00980         }
00981         // print out constraint information
00982         if(osinstance->getConstraintNumber() > 0){
00983                 for(i = 0; i < osinstance->getConstraintNumber(); i++){
00984                         if(osinstance->getConstraintNames() != NULL) cout << "row name = " << osinstance->getConstraintNames()[i] <<  endl;
00985                         if(osinstance->getConstraintLowerBounds() != NULL) cout << "row lower bound = " << osinstance->getConstraintLowerBounds()[i] <<  endl;
00986                         if(osinstance->getConstraintUpperBounds() != NULL) cout << "row upper bound = " << osinstance->getConstraintUpperBounds()[i] <<  endl; 
00987                 }
00988         }
00989         
00990         // print out linear constraint data
00991         cout << endl;
00992         cout << "number of nonzeros =  " << osinstance->getLinearConstraintCoefficientNumber() << endl;
00993         for(i = 0; i <= osinstance->getVariableNumber(); i++){
00994                 cout << "Start Value =  " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts[ i] << endl;
00995         }
00996         cout << endl;
00997         for(i = 0; i < osinstance->getLinearConstraintCoefficientNumber(); i++){
00998                 cout << "Index Value =  " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes[i] << endl;
00999                 cout << "Nonzero Value =  " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->values[i] << endl;
01000         }
01001 
01002         // print out quadratic data
01003         cout << "number of qterms =  " <<  osinstance->getNumberOfQuadraticTerms() << endl;
01004         for(int i = 0; i <  osinstance->getNumberOfQuadraticTerms(); i++){
01005                 cout << "Row Index = " <<  osinstance->getQuadraticTerms()->rowIndexes[i] << endl;
01006                 cout << "Var Index 1 = " << osinstance->getQuadraticTerms()->varOneIndexes[ i] << endl;
01007                 cout << "Var Index 2 = " << osinstance->getQuadraticTerms()->varTwoIndexes[ i] << endl;
01008                 cout << "Coefficient = " << osinstance->getQuadraticTerms()->coefficients[ i] << endl;
01009         }
01010 } // end dataEchoCheck
01011 
01012 
01013 BonminProblem::BonminProblem(OSInstance *osinstance_,  OSOption *osoption_) {
01014         osinstance = osinstance_;
01015         osoption = osoption_;
01016         printSol_ = false;
01017 }
01018 
01019 BonminProblem::~BonminProblem() {
01020 
01021 }
01022 
01023 
01024 

Generated on Thu Aug 5 03:03:01 2010 by  doxygen 1.4.7