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