00001
00018
00019
00020 #include <iostream>
00021
00022
00023 #include "OSBonminSolver.h"
00024 #include "OSGeneral.h"
00025 #include "OSParameters.h"
00026 #include "OSMathUtil.h"
00027 #include "CoinFinite.hpp"
00028 #include "CoinTime.hpp"
00029 #include "BonOsiTMINLPInterface.hpp"
00030 #include "BonTMINLP.hpp"
00031
00032 using namespace Bonmin;
00033 using namespace Ipopt;
00034
00035 using std::cout;
00036 using std::endl;
00037 using std::ostringstream;
00038
00039 BonminSolver::BonminSolver()
00040 {
00041 osrlwriter = new OSrLWriter();
00042 osresult = new OSResult();
00043 m_osilreader = NULL;
00044 m_osolreader = NULL;
00045 bonminErrorMsg = "";
00046 }
00047
00048 BonminSolver::~BonminSolver()
00049 {
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 {
00062 delete osresult;
00063 osresult = NULL;
00064
00065 }
00066 #ifdef DEBUG
00067 cout << "leaving BonminSolver destructor" << endl;
00068 #endif
00069 }
00070
00071
00072
00073 bool BonminProblem::get_variables_types(Index n, VariableType* var_types)
00074 {
00075 int i = 0;
00076 char *varType;
00077 varType = osinstance->getVariableTypes();
00078 n = osinstance->getVariableNumber();
00079 for(i = 0; i < n; i++)
00080 {
00081 if( varType[i] == 'B')
00082 {
00083 var_types[i] = BINARY;
00084 }
00085 else
00086 {
00087 if( varType[i] == 'I')
00088 {
00089 var_types[i] = INTEGER;
00090 }
00091 else
00092 {
00093 if( varType[i] == 'C')
00094 {
00095 var_types[i] = CONTINUOUS;
00096 }
00097 else
00098 {
00099 throw ErrorClass("variable type not yet implemented");
00100 }
00101 }
00102 }
00103 }
00104 return true;
00105 }
00106
00107
00108 bool BonminProblem::get_variables_linearity(Index n, Ipopt::TNLP::LinearityType* var_types)
00109 {
00110 std::cout << "Initialize Nonlinear Structures" << std::endl;
00111 try
00112 {
00113 osinstance->initForAlgDiff( );
00114 }
00115 catch(const ErrorClass& eclass)
00116 {
00117 bonminErrorMsg = eclass.errormsg;
00118 throw;
00119 }
00125 std::map<int, int> varIndexMap;
00126 std::map<int, int>::iterator posVarIndexMap;
00127 varIndexMap = osinstance->getAllNonlinearVariablesIndexMap( );
00128
00129
00130 int i;
00131
00132 for(i = 0; i < n; i++)
00133 {
00134 var_types[ i] = Ipopt::TNLP::LINEAR;
00135 }
00140 for(posVarIndexMap = varIndexMap.begin(); posVarIndexMap != varIndexMap.end(); ++posVarIndexMap)
00141 {
00142 std::cout << "Variable Index = " << posVarIndexMap->first << std::endl ;
00143 var_types[ posVarIndexMap->first] = Ipopt::TNLP::NON_LINEAR;
00144 }
00145 std::cout << "Number of nonlinear variables = " << varIndexMap.size() << std::endl;
00146
00147 return true;
00148 }
00149
00150 bool BonminProblem::get_constraints_linearity(Index m, Ipopt::TNLP::LinearityType* const_types)
00151 {
00152
00153 int i;
00154
00155 for(i = 0; i < m; i++)
00156 {
00157 const_types[ i] = Ipopt::TNLP::LINEAR;
00158 }
00159
00160
00161 int mm = osinstance->getNumberOfNonlinearExpressionTreeModIndexes();
00162
00163
00164
00165 for(i = 0; i < mm; i++)
00166 {
00167 if(osinstance->getNonlinearExpressionTreeModIndexes()[ i] >= 0)
00168 {
00169 std::cout << osinstance->getNonlinearExpressionTreeModIndexes()[ i] << std::endl;
00170 const_types[ osinstance->getNonlinearExpressionTreeModIndexes()[ i] ] = Ipopt::TNLP::NON_LINEAR;
00171
00172 }
00173
00174 }
00175
00176 return true;
00177 }
00178
00179
00180 bool BonminProblem::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
00181 Index& nnz_h_lag, TNLP::IndexStyleEnum& index_style)
00182 {
00183
00184
00185 n = osinstance->getVariableNumber();
00186
00187 m = osinstance->getConstraintNumber();
00188 #ifdef DEBUG
00189 cout << "Bonmin number variables !!!!!!!!!!!!!!!!!!!!!!!!!!!" << n << endl;
00190 cout << "Bonmin number constraints !!!!!!!!!!!!!!!!!!!!!!!!!!!" << m << endl;
00191 #endif
00192 try
00193 {
00194 osinstance->initForAlgDiff( );
00195 }
00196 catch(const ErrorClass& eclass)
00197 {
00198 bonminErrorMsg = eclass.errormsg;
00199 throw;
00200 }
00201
00202 osinstance->bUseExpTreeForFunEval = true;
00203
00204 SparseJacobianMatrix *sparseJacobian = NULL;
00205 try
00206 {
00207 sparseJacobian = osinstance->getJacobianSparsityPattern();
00208
00209 }
00210 catch(const ErrorClass& eclass)
00211 {
00212 bonminErrorMsg = eclass.errormsg;
00213 throw;
00214 }
00215
00216 nnz_jac_g = sparseJacobian->valueSize;
00217 #ifdef DEBUG
00218 cout << "nnz_jac_g !!!!!!!!!!!!!!!!!!!!!!!!!!!" << nnz_jac_g << endl;
00219 #endif
00220
00221
00222 if( (osinstance->getNumberOfNonlinearExpressions() == 0) && (osinstance->getNumberOfQuadraticTerms() == 0) )
00223 {
00224 cout << "This is a linear program" << endl;
00225 nnz_h_lag = 0;
00226 }
00227 else
00228 {
00229
00230 SparseHessianMatrix *sparseHessian = osinstance->getLagrangianHessianSparsityPattern();
00231
00232 nnz_h_lag = sparseHessian->hessDimension;
00233 }
00234 #ifdef DEBUG
00235 cout << "nnz_h_lag !!!!!!!!!!!!!!!!!!!!!!!!!!!" << nnz_h_lag << endl;
00236 #endif
00237
00238 index_style = TNLP::C_STYLE;
00239
00240 return true;
00241 }
00242
00243
00244 bool BonminProblem::get_bounds_info(Index n, Number* x_l, Number* x_u,
00245 Index m, Number* g_l, Number* g_u)
00246 {
00247 int i;
00248
00249 double * mdVarLB = osinstance->getVariableLowerBounds();
00250
00251
00252 double * mdVarUB = osinstance->getVariableUpperBounds();
00253
00254 for(i = 0; i < n; i++)
00255 {
00256 x_l[ i] = mdVarLB[ i];
00257 x_u[ i] = mdVarUB[ i];
00258 #ifdef DEBUG
00259 cout << "x_l !!!!!!!!!!!!!!!!!!!!!!!!!!!" << x_l[i] << endl;
00260 cout << "x_u !!!!!!!!!!!!!!!!!!!!!!!!!!!" << x_u[i] << endl;
00261 #endif
00262 }
00263
00264
00265
00266
00267
00268
00269 double * mdConLB = osinstance->getConstraintLowerBounds();
00270
00271 double * mdConUB = osinstance->getConstraintUpperBounds();
00272
00273 for(int i = 0; i < m; i++)
00274 {
00275 g_l[ i] = mdConLB[ i];
00276 g_u[ i] = mdConUB[ i];
00277 #ifdef DEBUG
00278 cout << "lower !!!!!!!!!!!!!!!!!!!!!!!!!!!" << g_l[i] << endl;
00279 cout << "upper !!!!!!!!!!!!!!!!!!!!!!!!!!!" << g_u[i] << endl;
00280 #endif
00281 }
00282 return true;
00283 }
00284
00285
00286
00287 bool BonminProblem::get_starting_point(Index n, bool init_x, Number* x,
00288 bool init_z, Number* z_L, Number* z_U, Index m, bool init_lambda,
00289 Number* lambda)
00290 {
00291
00292
00293
00294 assert(init_x == true);
00295 assert(init_z == false);
00296 assert(init_lambda == false);
00297 int i, m1, n1;
00298
00299
00300 #ifdef DEBUG
00301 cout << "get initial values !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
00302 #endif
00303
00304
00305 #ifdef DEBUG
00306 cout << "get number of initial values !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
00307 #endif
00308 int k;
00309 if (osoption != NULL)
00310 m1 = osoption->getNumberOfInitVarValues();
00311 else
00312 m1 = 0;
00313 #ifdef DEBUG
00314 cout << "number of variables initialed: " << m1 << endl;
00315 #endif
00316
00317 n1 = osinstance->getVariableNumber();
00318 bool* initialed;
00319 initialed = new bool[n1];
00320 #ifdef DEBUG
00321 cout << "number of variables in total: " << n1 << endl;
00322 #endif
00323
00324
00325 for(k = 0; k < n1; k++)
00326 initialed[k] = false;
00327
00328 if (m1 > 0)
00329 {
00330 #ifdef DEBUG
00331 cout << "get initial values " << endl;
00332 #endif
00333
00334 InitVarValue** initVarVector = osoption->getInitVarValuesSparse();
00335 #ifdef DEBUG
00336 cout << "done " << endl;
00337 #endif
00338
00339 double initval;
00340 try
00341 {
00342 for(k = 0; k < m1; k++)
00343 {
00344 i = initVarVector[k]->idx;
00345 if (initVarVector[k]->idx > n1)
00346 throw ErrorClass ("Illegal index value in variable initialization");
00347
00348 initval = initVarVector[k]->value;
00349 if (osinstance->instanceData->variables->var[i]->ub == OSDBL_MAX)
00350 {
00351 if (osinstance->instanceData->variables->var[i]->lb > initval)
00352 throw ErrorClass ("Initial value outside of bounds");
00353 }
00354 else if (osinstance->instanceData->variables->var[i]->lb == -OSDBL_MAX)
00355 {
00356 if (osinstance->instanceData->variables->var[i]->ub < initval)
00357 throw ErrorClass ("Initial value outside of bounds");
00358 }
00359 else
00360 {
00361 if ((osinstance->instanceData->variables->var[i]->lb > initval) ||
00362 (osinstance->instanceData->variables->var[i]->ub < initval))
00363 throw ErrorClass ("Initial value outside of bounds");
00364 }
00365
00366 x[initVarVector[k]->idx] = initval;
00367 initialed[initVarVector[k]->idx] = true;
00368 }
00369 }
00370 catch(const ErrorClass& eclass)
00371 {
00372 cout << "Error in BonminProblem::get_starting_point (OSBonminSolver.cpp)";
00373 cout << endl << endl << endl;
00374 }
00375 }
00376
00377 double default_initval;
00378 default_initval = 1.7171;
00379
00380
00381 for(k = 0; k < n1; k++)
00382 {
00383 if (!initialed[k])
00384 if (osinstance->instanceData->variables->var[k]->ub == OSDBL_MAX)
00385 if (osinstance->instanceData->variables->var[k]->lb <= default_initval)
00386 x[k] = default_initval;
00387 else
00388 x[k] = osinstance->instanceData->variables->var[k]->lb;
00389 else if (osinstance->instanceData->variables->var[k]->lb == -OSDBL_MAX)
00390 if (osinstance->instanceData->variables->var[k]->ub >= default_initval)
00391 x[k] = default_initval;
00392 else
00393 x[k] = osinstance->instanceData->variables->var[k]->ub;
00394 else if ((osinstance->instanceData->variables->var[k]->lb <= default_initval) &&
00395 (osinstance->instanceData->variables->var[k]->ub >= default_initval))
00396 x[k] = default_initval;
00397 else if (osinstance->instanceData->variables->var[k]->lb > default_initval)
00398 x[k] = osinstance->instanceData->variables->var[k]->lb;
00399 else
00400 x[k] = osinstance->instanceData->variables->var[k]->ub;
00401 }
00402 for(i = 0; i < n1; i++)
00403 {
00404 #ifdef DEBUG
00405 std::cout << "INITIAL VALUE !!!!!!!!!!!!!!!!!!!! " << x[ i] << std::endl;
00406 #endif
00407 }
00408
00409 osinstance->calculateAllObjectiveFunctionValues( x, true);
00410 delete[] initialed;
00411 return true;
00412 }
00413
00414
00415
00416 bool BonminProblem::eval_f(Index n, const Number* x, bool new_x, Number& obj_value)
00417 {
00418
00419 try
00420 {
00421 if(osinstance->getObjectiveNumber() > 0)
00422 {
00423 if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") == 0)
00424 {
00425 obj_value = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 )[ 0];
00426 }
00427 else
00428 {
00429 obj_value = -osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 )[ 0];
00430 }
00431 }
00432 }
00433 catch(const ErrorClass& eclass)
00434 {
00435 bonminErrorMsg = eclass.errormsg;
00436 throw;
00437 }
00438 if( CoinIsnan( (double)obj_value) ) return false;
00439 return true;
00440 }
00441
00442 bool BonminProblem::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
00443 {
00444 int i;
00445 double *objGrad = NULL;
00446 if(osinstance->getObjectiveNumber() > 0)
00447 {
00448 try
00449 {
00450
00451
00452
00453 objGrad = osinstance->calculateObjectiveFunctionGradient( const_cast<double*>(x), NULL, NULL, -1, new_x, 1);
00454 }
00455 catch(const ErrorClass& eclass)
00456 {
00457 bonminErrorMsg = eclass.errormsg;
00458 throw;
00459 }
00460
00461 for(i = 0; i < n; i++)
00462 {
00463 if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") == 0)
00464 {
00465 grad_f[ i] = objGrad[ i];
00466 }
00467 else
00468 {
00469 grad_f[ i] = -objGrad[ i];
00470 }
00471
00472 }
00473 }
00474
00475 return true;
00476 }
00477
00478
00479 bool BonminProblem::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
00480 {
00481 try
00482 {
00483 double *conVals = osinstance->calculateAllConstraintFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 );
00484 int i;
00485 for(i = 0; i < m; i++)
00486 {
00487 if( CoinIsnan( (double)conVals[ i] ) ) return false;
00488 g[i] = conVals[ i] ;
00489 }
00490 return true;
00491 }
00492 catch(const ErrorClass& eclass)
00493 {
00494 bonminErrorMsg = eclass.errormsg;
00495 throw;
00496 }
00497 }
00498
00499
00500
00501 bool BonminProblem::eval_jac_g(Index n, const Number* x, bool new_x,
00502 Index m, Index nele_jac, Index* iRow, Index *jCol,
00503 Number* values)
00504 {
00505 SparseJacobianMatrix *sparseJacobian;
00506 if (values == NULL)
00507 {
00508
00509
00510
00511
00512
00513 try
00514 {
00515 sparseJacobian = osinstance->getJacobianSparsityPattern();
00516 }
00517 catch(const ErrorClass& eclass)
00518 {
00519 bonminErrorMsg = eclass.errormsg;
00520 throw;
00521 }
00522 int i = 0;
00523 int k, idx;
00524 for(idx = 0; idx < m; idx++)
00525 {
00526 for(k = *(sparseJacobian->starts + idx); k < *(sparseJacobian->starts + idx + 1); k++)
00527 {
00528 iRow[i] = idx;
00529 jCol[i] = *(sparseJacobian->indexes + k);
00530
00531
00532 i++;
00533 }
00534 }
00535 }
00536 else
00537 {
00538
00539 try
00540 {
00541 sparseJacobian = osinstance->calculateAllConstraintFunctionGradients( const_cast<double*>(x), NULL, NULL, new_x, 1);
00542 }
00543 catch(const ErrorClass& eclass)
00544 {
00545 bonminErrorMsg = eclass.errormsg;
00546 throw;
00547 }
00548
00549 for(int i = 0; i < nele_jac; i++)
00550 {
00551 values[ i] = sparseJacobian->values[i];
00552
00553
00554
00555 }
00556 }
00557 return true;
00558 }
00559
00560
00561 bool BonminProblem::eval_h(Index n, const Number* x, bool new_x,
00562 Number obj_factor, Index m, const Number* lambda,
00563 bool new_lambda, Index nele_hess, Index* iRow,
00564 Index* jCol, Number* values)
00565 {
00566
00568 SparseHessianMatrix *sparseHessian;
00569
00570 int i;
00571 if (values == NULL)
00572 {
00573
00574
00575 try
00576 {
00577 sparseHessian = osinstance->getLagrangianHessianSparsityPattern( );
00578 }
00579 catch(const ErrorClass& eclass)
00580 {
00581 bonminErrorMsg = eclass.errormsg;
00582 throw;
00583 }
00584
00585 for(i = 0; i < nele_hess; i++)
00586 {
00587 iRow[i] = *(sparseHessian->hessColIdx + i);
00588 jCol[i] = *(sparseHessian->hessRowIdx + i);
00589
00590
00591 }
00592 }
00593 else
00594 {
00595
00596
00597 double* objMultipliers = new double[1];
00598 objMultipliers[0] = obj_factor;
00599 try
00600 {
00601 sparseHessian = osinstance->calculateLagrangianHessian( const_cast<double*>(x), objMultipliers, const_cast<double*>(lambda) , new_x, 2);
00602 delete[] objMultipliers;
00603 }
00604 catch(const ErrorClass& eclass)
00605 {
00606 bonminErrorMsg = eclass.errormsg;
00607 delete[] objMultipliers;
00608 throw;
00609 }
00610 for(i = 0; i < nele_hess; i++)
00611 {
00612 values[ i] = *(sparseHessian->hessValues + i);
00613 }
00614 }
00616 return true;
00617 }
00618
00619 bool BonminProblem::get_scaling_parameters(Number& obj_scaling,
00620 bool& use_x_scaling, Index n,
00621 Number* x_scaling,
00622 bool& use_g_scaling, Index m,
00623 Number* g_scaling)
00624 {
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 return true;
00635 }
00636
00637
00638
00639
00640 void BonminProblem::finalize_solution(TMINLP::SolverReturn status_,
00641 Index n, const Number* x, Number obj_value)
00642 {
00643
00644 status = status_;
00645 #ifdef DEBUG
00646 std::cout << "FINALIZE OBJ SOLUTION VALUE = " << obj_value << std::endl;
00647 #endif
00648
00649 }
00650
00651
00652
00653
00654 void BonminSolver::buildSolverInstance() throw (ErrorClass)
00655 {
00656 try
00657 {
00658
00659 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00660 if(osinstance == NULL)
00661 {
00662 m_osilreader = new OSiLReader();
00663 osinstance = m_osilreader->readOSiL( osil);
00664 }
00665
00666
00667 if (osinstance->getObjectiveNumber() > 1)
00668 throw ErrorClass("Solver cannot handle multiple objectives --- please delete all but one");
00669
00670
00671 tminlp = new BonminProblem( osinstance, osoption);
00672 this->bCallbuildSolverInstance = true;
00673
00674
00675 }
00676 catch(const ErrorClass& eclass)
00677 {
00678 std::cout << "THERE IS AN ERROR" << std::endl;
00679 osresult->setGeneralMessage( eclass.errormsg);
00680 osresult->setGeneralStatusType( "error");
00681 osrl = osrlwriter->writeOSrL( osresult);
00682 throw ErrorClass( osrl) ;
00683 }
00684 }
00685
00686
00687
00688 void BonminSolver::setSolverOptions() throw (ErrorClass)
00689 {
00690 try
00691 {
00692 this->bSetSolverOptions = true;
00693 bonminSetup.initializeOptionsAndJournalist();
00694
00695 bonminSetup.roptions()->AddStringOption2("print_solution","Do we print the solution or not?",
00696 "yes",
00697 "no", "No, we don't.",
00698 "yes", "Yes, we do.",
00699 "A longer comment can be put here");
00700
00701
00702 bonminSetup.options()->SetNumericValue("bonmin.time_limit", 5000);
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 bonminSetup.readOptionsString("bonmin.algorithm B-BB\n");
00721
00722
00723 bonminSetup.options()->SetIntegerValue("bonmin.bb_log_level", 0 );
00724 bonminSetup.options()->SetIntegerValue("bonmin.nlp_log_level", 0 );
00725
00726
00727 int printSolution;
00728 bonminSetup.options()->GetEnumValue("print_solution", printSolution,"");
00729 if(printSolution == 1)
00730 {
00731 tminlp->printSolutionAtEndOfAlgorithm();
00732 }
00733
00734 if(osoption == NULL && osol.length() > 0)
00735 {
00736 m_osolreader = new OSoLReader();
00737 osoption = m_osolreader->readOSoL( osol);
00738 }
00739
00740 if(osoption != NULL && osoption->getNumberOfSolverOptions() > 0 )
00741 {
00742 char *pEnd;
00743 int i;
00744 std::vector<SolverOption*> optionsVector;
00745 optionsVector = osoption->getSolverOptions( "bonmin",true);
00746 int num_bonmin_options = optionsVector.size();
00747 for(i = 0; i < num_bonmin_options; i++)
00748 {
00749 if(optionsVector[ i]->type == "numeric" )
00750 {
00751 std::cout << "FOUND A NUMERIC OPTION " << os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) << std::endl;
00752 if(optionsVector[ i]->category == "ipopt")
00753 {
00754 bonminSetup.options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00755 }
00756 else
00757 {
00758 if(optionsVector[ i]->category == "cbc" )
00759 {
00760 bonminSetup.options()->SetNumericValue("milp_solver."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00761 }
00762 else
00763 {
00764 bonminSetup.options()->SetNumericValue("bonmin."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00765 }
00766 }
00767 }
00768 else if(optionsVector[ i]->type == "integer" )
00769 {
00770 std::cout << "FOUND AN INTEGER OPTION " <<optionsVector[ i]->name << std::endl;
00771 if(optionsVector[ i]->category == "ipopt")
00772 {
00773 bonminSetup.options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00774 }
00775 else
00776 {
00777 if(optionsVector[ i]->category == "cbc" )
00778 {
00779 std::cout << "SETTING INTEGER CBC OPTION" << std::endl;
00780 bonminSetup.options()->SetIntegerValue("milp_solver."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ));
00781 }
00782 else
00783 {
00784 bonminSetup.options()->SetIntegerValue("bonmin."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00785 }
00786 }
00787 }
00788 else if(optionsVector[ i]->type == "string" )
00789 {
00790 std::cout << "FOUND A STRING OPTION " <<optionsVector[ i]->name << std::endl;
00791 if(optionsVector[ i]->category == "ipopt")
00792 {
00793 bonminSetup.options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value );
00794 }
00795 else
00796 {
00797 if(optionsVector[ i]->category == "cbc" )
00798 {
00799 bonminSetup.options()->SetStringValue("milp_solver."+optionsVector[ i]->name, optionsVector[ i]->value);
00800 }
00801 else
00802 {
00803 bonminSetup.options()->SetStringValue("bonmin."+optionsVector[ i]->name, optionsVector[ i]->value);
00804 }
00805 }
00806
00807 }
00808 }
00809 }
00810
00811 }
00812
00813 catch(const ErrorClass& eclass)
00814 {
00815 std::cout << "THERE IS AN ERROR" << std::endl;
00816 osresult->setGeneralMessage( eclass.errormsg);
00817 osresult->setGeneralStatusType( "error");
00818 osrl = osrlwriter->writeOSrL( osresult);
00819 throw ErrorClass( osrl) ;
00820 }
00821 }
00822
00823
00824
00825 void BonminSolver::solve() throw (ErrorClass)
00826 {
00827 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00828 if( this->bSetSolverOptions == false) setSolverOptions();
00829 try
00830 {
00831
00832
00833
00834
00835
00836
00837
00838
00839 try
00840 {
00841 bonminSetup.initialize( GetRawPtr(tminlp) );
00842
00843 bb( bonminSetup);
00844
00845 }
00846 catch(TNLPSolver::UnsolvedError *E)
00847 {
00848
00849 std::cerr<<"Ipopt has failed to solve a problem"<<std::endl;
00850 }
00851 catch(OsiTMINLPInterface::SimpleError &E)
00852 {
00853 std::cerr<<E.className()<<"::"<<E.methodName()
00854 <<std::endl
00855 <<E.message()<<std::endl;
00856 }
00857 catch(CoinError &E)
00858 {
00859 std::cerr<<E.className()<<"::"<<E.methodName()
00860 <<std::endl
00861 <<E.message()<<std::endl;
00862 }
00863
00864 if(( bb.model().isContinuousUnbounded() == true) && (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() <= 0) )
00865 {
00866 std::string solutionDescription = "";
00867 std::string message = "Success";
00868 int solIdx = 0;
00869
00870 if(osresult->setServiceName( "Bonin solver service") != true)
00871 throw ErrorClass("OSResult error: setServiceName");
00872 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00873 throw ErrorClass("OSResult error: setInstanceName");
00874 if(osresult->setVariableNumber( osinstance->getVariableNumber() ) != true)
00875 throw ErrorClass("OSResult error: setVariableNumber");
00876 if(osresult->setObjectiveNumber( 1) != true)
00877 throw ErrorClass("OSResult error: setObjectiveNumber");
00878 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00879 throw ErrorClass("OSResult error: setConstraintNumber");
00880 if(osresult->setSolutionNumber( 1) != true)
00881 throw ErrorClass("OSResult error: setSolutionNumer");
00882 if(osresult->setGeneralMessage( message) != true)
00883 throw ErrorClass("OSResult error: setGeneralMessage");
00884 solutionDescription = "The problem is unbounded";
00885 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00886 osresult->setGeneralStatusType("normal");
00887 if( osinstance->getVariableNumber() == 0) osresult->setSolutionMessage(solIdx, "Warning: this problem has zero decision variables!");
00888 osrl = osrlwriter->writeOSrL( osresult);
00889 return;
00890 }
00891
00892
00893 if(( bb.model().isProvenInfeasible() == true) )
00894 {
00895 std::string solutionDescription = "";
00896 std::string message = "Success";
00897 int solIdx = 0;
00898
00899
00900 if(osresult->setServiceName( "Bonin solver service") != true)
00901 throw ErrorClass("OSResult error: setServiceName");
00902 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00903 throw ErrorClass("OSResult error: setInstanceName");
00904 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00905 throw ErrorClass("OSResult error: setVariableNumer");
00906 if(osresult->setObjectiveNumber( 1) != true)
00907 throw ErrorClass("OSResult error: setObjectiveNumber");
00908 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00909 throw ErrorClass("OSResult error: setConstraintNumber");
00910 if(osresult->setSolutionNumber( 1) != true)
00911 throw ErrorClass("OSResult error: setSolutionNumber");
00912 if(osresult->setGeneralMessage( message) != true)
00913 throw ErrorClass("OSResult error: setGeneralMessage");
00914 solutionDescription = "The problem is infeasible";
00915 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00916
00917 osresult->setGeneralStatusType("normal");
00918 if( osinstance->getVariableNumber() == 0) osresult->setSolutionMessage(solIdx, "Warning: this problem has zero decision variables!");
00919 osrl = osrlwriter->writeOSrL( osresult);
00920 return;
00921 }
00922 status = tminlp->status;
00923 writeResult();
00924
00925 }
00926 catch(const ErrorClass& eclass)
00927 {
00928 osresult->setGeneralMessage( eclass.errormsg);
00929 osresult->setGeneralStatusType( "error");
00930 osrl = osrlwriter->writeOSrL( osresult);
00931 throw ErrorClass( osrl) ;
00932 }
00933 }
00934
00935
00936
00937
00938 void BonminSolver::writeResult()
00939 {
00940 double *x = NULL;
00941 double *z = NULL;
00942 int i = 0;
00943 int solIdx = 0;
00944 std::string solutionDescription = "";
00945 std::string message = "Bonmin solver finishes to the end.";
00946 if( osinstance->getVariableNumber() == 0) osresult->setSolutionMessage(0, "Warning: this problem has zero decision variables!");
00947
00948
00949 try
00950 {
00951 if(osinstance->getVariableNumber() > 0) x = new double[osinstance->getVariableNumber() ];
00952 z = new double[1];
00953
00954 if(osresult->setServiceName( OSgetVersionInfo()) != true)
00955 throw ErrorClass("OSResult error: setServiceName");
00956 if(osresult->setSolverInvoked( "COIN-OR Bonmin") != true)
00957 throw ErrorClass("OSResult error: setSolverInvoked");
00958 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00959 throw ErrorClass("OSResult error: setInstanceName");
00960
00961
00962
00963
00964 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00965 throw ErrorClass("OSResult error: setVariableNumer");
00966 if(osresult->setObjectiveNumber( 1) != true)
00967 throw ErrorClass("OSResult error: setObjectiveNumber");
00968 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00969 throw ErrorClass("OSResult error: setConstraintNumber");
00970 if(osresult->setSolutionNumber( 1) != true)
00971 throw ErrorClass("OSResult error: setSolutionNumer");
00972 if(osresult->setGeneralMessage( message) != true)
00973 throw ErrorClass("OSResult error: setGeneralMessage");
00974
00975 switch( status)
00976 {
00977 case TMINLP::SUCCESS:
00978 solutionDescription = "SUCCESS[BONMIN]: Algorithm terminated normally at a locally optimal point, satisfying the convergence tolerances.";
00979
00980 osresult->setSolutionStatus(solIdx, "locallyOptimal", solutionDescription);
00981
00982 if(osinstance->getObjectiveNumber() > 0)
00983 {
00984 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
00985 osresult->setObjectiveValuesDense(solIdx, z);
00986 }
00987 if( osinstance->getVariableNumber() > 0)
00988 {
00989 for(i=0; i < osinstance->getVariableNumber(); i++)
00990 {
00991 *(x + i) = bb.bestSolution()[i];
00992
00993 }
00994 osresult->setPrimalVariableValuesDense(solIdx, x);
00995 }
00996 break;
00997
00998 case TMINLP::LIMIT_EXCEEDED:
00999 solutionDescription = "LIMIT_EXCEEDED[BONMIN]: A resource limit was exceeded, we provide the current solution.";
01000
01001 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
01002
01003
01004
01005 if(osinstance->getObjectiveNumber() > 0)
01006 {
01007 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
01008 osresult->setObjectiveValuesDense(solIdx, z);
01009 }
01010 if( osinstance->getVariableNumber() > 0)
01011 {
01012 for(i=0; i < osinstance->getVariableNumber(); i++)
01013 {
01014 *(x + i) = bb.bestSolution()[i];
01015
01016 }
01017 osresult->setPrimalVariableValuesDense(solIdx, x);
01018 }
01019 break;
01020
01021 case TMINLP::MINLP_ERROR:
01022 solutionDescription = "MINLP_ERROR [BONMIN]: Algorithm stopped with unspecified error.";
01023
01024 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
01025
01026 break;
01027
01028 case TMINLP::CONTINUOUS_UNBOUNDED:
01029 solutionDescription = "CONTINUOUS_UNBOUNDED [BONMIN]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
01030
01031 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
01032
01033 break;
01034
01035
01036 case TMINLP::INFEASIBLE:
01037 solutionDescription = "INFEASIBLE [BONMIN]: Problem may be infeasible.";
01038
01039 osresult->setSolutionStatus(solIdx, "infeasible", solutionDescription);
01040 break;
01041
01042
01043 default:
01044 solutionDescription = "OTHER[BONMIN]: other unknown solution status from Bonmin solver";
01045
01046 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
01047 }
01048 osresult->setGeneralStatusType("normal");
01049 osrl = osrlwriter->writeOSrL( osresult);
01050 if(osinstance->getVariableNumber() > 0 ) delete[] x;
01051 x = NULL;
01052 delete[] z;
01053 z = NULL;
01054 }
01055
01056
01057 catch(const ErrorClass& eclass)
01058 {
01059 if(osinstance->getVariableNumber() > 0) delete[] x;
01060 x = NULL;
01061 delete[] z;
01062 z = NULL;
01063 osresult->setGeneralMessage( eclass.errormsg);
01064 osresult->setGeneralStatusType( "error");
01065 osrl = osrlwriter->writeOSrL( osresult);
01066 throw ErrorClass( osrl) ;
01067 }
01068
01069
01070 }
01071
01072
01073 void BonminSolver::dataEchoCheck()
01074 {
01075
01076 int i;
01077
01078
01079 cout << "This is problem: " << osinstance->getInstanceName() << endl;
01080 cout << "The problem source is: " << osinstance->getInstanceSource() << endl;
01081 cout << "The problem description is: " << osinstance->getInstanceDescription() << endl;
01082 cout << "number of variables = " << osinstance->getVariableNumber() << endl;
01083 cout << "number of Rows = " << osinstance->getConstraintNumber() << endl;
01084
01085
01086 if(osinstance->getVariableNumber() > 0)
01087 {
01088 for(i = 0; i < osinstance->getVariableNumber(); i++)
01089 {
01090 if(osinstance->getVariableNames() != NULL) cout << "variable Names " << osinstance->getVariableNames()[ i] << endl;
01091 if(osinstance->getVariableTypes() != NULL) cout << "variable Types " << osinstance->getVariableTypes()[ i] << endl;
01092 if(osinstance->getVariableLowerBounds() != NULL) cout << "variable Lower Bounds " << osinstance->getVariableLowerBounds()[ i] << endl;
01093 if(osinstance->getVariableUpperBounds() != NULL) cout << "variable Upper Bounds " << osinstance->getVariableUpperBounds()[i] << endl;
01094 }
01095 }
01096
01097
01098 if(osinstance->getVariableNumber() > 0 || osinstance->instanceData->objectives->obj != NULL || osinstance->instanceData->objectives->numberOfObjectives > 0)
01099 {
01100 if( osinstance->getObjectiveMaxOrMins()[0] == "min") cout << "problem is a minimization" << endl;
01101 else cout << "problem is a maximization" << endl;
01102 for(i = 0; i < osinstance->getVariableNumber(); i++)
01103 {
01104 cout << "OBJ COEFFICIENT = " << osinstance->getDenseObjectiveCoefficients()[0][i] << endl;
01105 }
01106 }
01107
01108 if(osinstance->getConstraintNumber() > 0)
01109 {
01110 for(i = 0; i < osinstance->getConstraintNumber(); i++)
01111 {
01112 if(osinstance->getConstraintNames() != NULL) cout << "row name = " << osinstance->getConstraintNames()[i] << endl;
01113 if(osinstance->getConstraintLowerBounds() != NULL) cout << "row lower bound = " << osinstance->getConstraintLowerBounds()[i] << endl;
01114 if(osinstance->getConstraintUpperBounds() != NULL) cout << "row upper bound = " << osinstance->getConstraintUpperBounds()[i] << endl;
01115 }
01116 }
01117
01118
01119 cout << endl;
01120 cout << "number of nonzeros = " << osinstance->getLinearConstraintCoefficientNumber() << endl;
01121 for(i = 0; i <= osinstance->getVariableNumber(); i++)
01122 {
01123 cout << "Start Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts[ i] << endl;
01124 }
01125 cout << endl;
01126 for(i = 0; i < osinstance->getLinearConstraintCoefficientNumber(); i++)
01127 {
01128 cout << "Index Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes[i] << endl;
01129 cout << "Nonzero Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->values[i] << endl;
01130 }
01131
01132
01133 cout << "number of qterms = " << osinstance->getNumberOfQuadraticTerms() << endl;
01134 for(int i = 0; i < osinstance->getNumberOfQuadraticTerms(); i++)
01135 {
01136 cout << "Row Index = " << osinstance->getQuadraticTerms()->rowIndexes[i] << endl;
01137 cout << "Var Index 1 = " << osinstance->getQuadraticTerms()->varOneIndexes[ i] << endl;
01138 cout << "Var Index 2 = " << osinstance->getQuadraticTerms()->varTwoIndexes[ i] << endl;
01139 cout << "Coefficient = " << osinstance->getQuadraticTerms()->coefficients[ i] << endl;
01140 }
01141 }
01142
01143
01144 BonminProblem::BonminProblem(OSInstance *osinstance_, OSOption *osoption_)
01145 {
01146 osinstance = osinstance_;
01147 osoption = osoption_;
01148 printSol_ = false;
01149 }
01150
01151 BonminProblem::~BonminProblem()
01152 {
01153
01154 }
01155
01156
01157