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