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