IPOPT是一种常用的非线性优化求解器,使用内点法进行求解。对于复杂问题,需要借助自动微分工具,帮助求解梯度、雅各比矩阵、Hessian矩阵,如ADOL-C,CppAD
安装
参考非线性优化求解器IPOPT 和 ubuntu 环境下 IPOPT 安装与使用
我安装完后,部分文件和官方说明的不同,目录coin
在我的电脑上是coin-or
,sudo vim /usr/include/cppad/ipopt/solve_callback.hpp
,修改如下
1 2
| # include <coin-or/IpIpoptApplication.hpp> # include <coin-or/IpTNLP.hpp>
|
配置
CMake配置
1 2 3 4 5 6 7 8 9
| message(status "IPOPT_CFLAGS: " ${IPOPT_CFLAGS}) message(status "IPOPT_CFLAGS_OTHER: " ${IPOPT_CFLAGS_OTHER}) set(CMAKE_CXX_FLAGS "-DHAVE_CSTDDEF -DHAVE_MPI_INITIALIZED")
include_directories(/usr/local/include) link_directories(/usr/local/lib)
add_executable(solver example.cpp) target_link_libraries(solver ipopt)
|
举例
状态变量 $ x = [x_1,x_2,x_3,x_4]^\mathrm{T}$
目标函数
约束条件:
起始点
优化结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| #include <cppad/ipopt/solve.hpp> #include <iostream>
namespace { using CppAD::AD; class FG_eval { public: typedef CPPAD_TESTVECTOR( AD<double> ) ADvector; void operator()(ADvector& fg, const ADvector& x) { assert( fg.size() == 3 ); assert( x.size() == 4 );
AD<double> x1 = x[0]; AD<double> x2 = x[1]; AD<double> x3 = x[2]; AD<double> x4 = x[3]; fg[0] = x1 * x4 * (x1 + x2 + x3) + x3; fg[1] = x1 * x2 * x3 * x4; fg[2] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4; return; } }; }
bool get_started(void) { bool ok = true; size_t i; typedef CPPAD_TESTVECTOR( double ) Dvector; size_t nx = 4; size_t ng = 2; Dvector xi(nx); xi[0] = 1.0; xi[1] = 1.0; xi[2] = 1.0; xi[3] = 1.0;
Dvector xl(nx), xu(nx); for(i = 0; i < nx; i++) { xl[i] = 1.0; xu[i] = 5.0; } Dvector gl(ng), gu(ng); gl[0] = 25.0; gu[0] = 1.0e19; gl[1] = 40.0; gu[1] = 40.0;
FG_eval fg_eval;
std::string options; options += "Integer print_level 0\n"; options += "String sb yes\n"; options += "Integer max_iter 100\n"; options += "Numeric tol 1e-6\n"; options += "String derivative_test second-order\n"; options += "Numeric point_perturbation_radius 0.\n";
CppAD::ipopt::solve_result<Dvector> solution;
CppAD::ipopt::solve<Dvector, FG_eval>( options, xi, xl, xu, gl, gu, fg_eval, solution );
ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success; double rel_tol = 1e-6; double abs_tol = 1e-6; std::cout << "solution x: "<< std::endl; for(i = 0; i < nx; i++) { std::cout << solution.x[i] << std::endl; } return ok; }
int main(int argc, const char** argv) { get_started(); return 0; }
|