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