IpOpt 拒绝解决无约束问题
IpOpt refuses to solve unconstrained problem
我是 IpOpt 的新手,我正在尝试用它解决简单的无约束优化问题。我的问题只是二次函数 f(x) = (5x - 3)^2
.
我为这个问题创建了一个简单的class:
#include <cstdio>
#include "IpIpoptApplication.hpp"
#include "IpTNLP.hpp"
using namespace Ipopt;
class MyProblem : public Ipopt::TNLP
{
public:
const int nVars = 1;
virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
Index& nnz_h_lag, IndexStyleEnum& index_style)
{
n = nVars;
m = 0;
nnz_jac_g = 0;
nnz_h_lag = 1;
index_style = IndexStyleEnum::C_STYLE;
return true;
}
virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
Index m, Number* g_l, Number* g_u)
{
return true;
}
virtual bool get_starting_point(Index n, bool init_x, Number* x,
bool init_z, Number* z_L, Number* z_U,
Index m, bool init_lambda,
Number* lambda)
{
std::cout << "get_starting_point" << std::endl;
if(init_x){
x[0] = 0.0;
}
return true;
}
virtual bool eval_f(Index n, const Number* x, bool new_x,
Number& obj_value)
{
const Number residual = (5 * x[0] - 3);
obj_value = residual * residual;
std::cout << "obj_value " << obj_value << std::endl;
return true;
}
virtual bool eval_grad_f(Index n, const Number* x, bool new_x,
Number* grad_f)
{
const Number residual = (5 * x[0] - 3);
grad_f[0] = 2 * 10 * residual;
std::cout << "grad_f " << grad_f[0] << std::endl;
return true;
}
virtual bool eval_g(Index n, const Number* x, bool new_x,
Index m, Number* g)
{
std::cout << "eval_g was called m=" << m << " *g " << g << std::endl;
return true;
}
virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
Index m, Index nele_jac, Index* iRow,
Index *jCol, Number* values)
{
std::cout << "eval_jac_g was called" << std::endl;
return true;
}
virtual void finalize_solution(SolverReturn status,
Index n, const Number* x, const Number* z_L, const Number* z_U,
Index m, const Number* g, const Number* lambda,
Number obj_value,
const IpoptData* ip_data,
IpoptCalculatedQuantities* ip_cq)
{
std::cout << "X final " << x[0] << std::endl;
}
};
int main()
{
SmartPtr<TNLP> mynlp = new MyProblem();
SmartPtr<IpoptApplication> app = new IpoptApplication();
app->Initialize();
ApplicationReturnStatus status = app->OptimizeTNLP(mynlp);
if (status == Solve_Succeeded) {
printf("\n\n*** The problem solved!\n");
}
else {
printf("\n\n*** The problem FAILED!\n");
}
return 0;
}
我设置了m = 0;
和nnz_jac_g = 0;
来表明我没有约束
IpOpt 给我以下输出:
******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
Ipopt is released as open source code under the Eclipse Public License (EPL).
For more information visit http://projects.coin-or.org/Ipopt
******************************************************************************
This is Ipopt version 3.12.11, running with linear solver mumps.
NOTE: Other linear solvers might be more efficient (see Ipopt documentation).
eval_g was called m=0 *g 0x5559e0661fd0
obj_value 9
X final 0
All variables are fixed and constraint violation 0.000000e+00
is below tolerance 1.000000e-08. Declaring success.
EXIT: Optimal Solution Found.
*** The problem solved!
但显然问题的解决方案应该是 x = 3/5
.
我的问题有什么问题 class?
据我所知,IpOpt 没有调用 get_starting_point
方法,这看起来很奇怪。
我的 IpOpt 版本是 3.12.11
,gcc 是 7.2.0-8ubuntu3.2
。我可以提供更多信息,但我不知道我还能展示什么。源码应该够漂亮了
PS对不起我的英语不好
您应该定义变量范围。
virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
Index m, Number* g_l, Number* g_u)
{
*x_l = -1e19; //nlp_lower_bound_inf
*x_u = 1e19; //nlp_upper_bound_inf
return true;
}
你的变量是随机的(因为其他编译器可能为未定义的边界提供不同的值)被零边界冻结。
还有一个错误。您应该定义 eval_h 或指定 hessian 近似方案。
我是 IpOpt 的新手,我正在尝试用它解决简单的无约束优化问题。我的问题只是二次函数 f(x) = (5x - 3)^2
.
我为这个问题创建了一个简单的class:
#include <cstdio>
#include "IpIpoptApplication.hpp"
#include "IpTNLP.hpp"
using namespace Ipopt;
class MyProblem : public Ipopt::TNLP
{
public:
const int nVars = 1;
virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
Index& nnz_h_lag, IndexStyleEnum& index_style)
{
n = nVars;
m = 0;
nnz_jac_g = 0;
nnz_h_lag = 1;
index_style = IndexStyleEnum::C_STYLE;
return true;
}
virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
Index m, Number* g_l, Number* g_u)
{
return true;
}
virtual bool get_starting_point(Index n, bool init_x, Number* x,
bool init_z, Number* z_L, Number* z_U,
Index m, bool init_lambda,
Number* lambda)
{
std::cout << "get_starting_point" << std::endl;
if(init_x){
x[0] = 0.0;
}
return true;
}
virtual bool eval_f(Index n, const Number* x, bool new_x,
Number& obj_value)
{
const Number residual = (5 * x[0] - 3);
obj_value = residual * residual;
std::cout << "obj_value " << obj_value << std::endl;
return true;
}
virtual bool eval_grad_f(Index n, const Number* x, bool new_x,
Number* grad_f)
{
const Number residual = (5 * x[0] - 3);
grad_f[0] = 2 * 10 * residual;
std::cout << "grad_f " << grad_f[0] << std::endl;
return true;
}
virtual bool eval_g(Index n, const Number* x, bool new_x,
Index m, Number* g)
{
std::cout << "eval_g was called m=" << m << " *g " << g << std::endl;
return true;
}
virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
Index m, Index nele_jac, Index* iRow,
Index *jCol, Number* values)
{
std::cout << "eval_jac_g was called" << std::endl;
return true;
}
virtual void finalize_solution(SolverReturn status,
Index n, const Number* x, const Number* z_L, const Number* z_U,
Index m, const Number* g, const Number* lambda,
Number obj_value,
const IpoptData* ip_data,
IpoptCalculatedQuantities* ip_cq)
{
std::cout << "X final " << x[0] << std::endl;
}
};
int main()
{
SmartPtr<TNLP> mynlp = new MyProblem();
SmartPtr<IpoptApplication> app = new IpoptApplication();
app->Initialize();
ApplicationReturnStatus status = app->OptimizeTNLP(mynlp);
if (status == Solve_Succeeded) {
printf("\n\n*** The problem solved!\n");
}
else {
printf("\n\n*** The problem FAILED!\n");
}
return 0;
}
我设置了m = 0;
和nnz_jac_g = 0;
来表明我没有约束
IpOpt 给我以下输出:
******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
Ipopt is released as open source code under the Eclipse Public License (EPL).
For more information visit http://projects.coin-or.org/Ipopt
******************************************************************************
This is Ipopt version 3.12.11, running with linear solver mumps.
NOTE: Other linear solvers might be more efficient (see Ipopt documentation).
eval_g was called m=0 *g 0x5559e0661fd0
obj_value 9
X final 0
All variables are fixed and constraint violation 0.000000e+00
is below tolerance 1.000000e-08. Declaring success.
EXIT: Optimal Solution Found.
*** The problem solved!
但显然问题的解决方案应该是 x = 3/5
.
我的问题有什么问题 class?
据我所知,IpOpt 没有调用 get_starting_point
方法,这看起来很奇怪。
我的 IpOpt 版本是 3.12.11
,gcc 是 7.2.0-8ubuntu3.2
。我可以提供更多信息,但我不知道我还能展示什么。源码应该够漂亮了
PS对不起我的英语不好
您应该定义变量范围。
virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
Index m, Number* g_l, Number* g_u)
{
*x_l = -1e19; //nlp_lower_bound_inf
*x_u = 1e19; //nlp_upper_bound_inf
return true;
}
你的变量是随机的(因为其他编译器可能为未定义的边界提供不同的值)被零边界冻结。
还有一个错误。您应该定义 eval_h 或指定 hessian 近似方案。