IPOPT的使用

IPOPT是一种常用的非线性优化求解器,使用内点法进行求解。对于复杂问题,需要借助自动微分工具,帮助求解梯度、雅各比矩阵、Hessian矩阵,如ADOL-C,CppAD

安装

参考非线性优化求解器IPOPTubuntu 环境下 IPOPT 安装与使用

我安装完后,部分文件和官方说明的不同,目录coin在我的电脑上是coin-orsudo 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>
//#include <mpi.h>
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 );

// Fortran style indexing
AD<double> x1 = x[0];
AD<double> x2 = x[1];
AD<double> x3 = x[2];
AD<double> x4 = x[3];
// f(x)
fg[0] = x1 * x4 * (x1 + x2 + x3) + x3;
// g_1 (x)
fg[1] = x1 * x2 * x3 * x4;
// g_2 (x)
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;
// number of independent variables (domain dimension for f and g)
size_t nx = 4;
// number of constraints (range dimension for g)
size_t ng = 2;
// x[i] 设置第i个变量的初始迭代值
Dvector xi(nx);
xi[0] = 1.0;
xi[1] = 1.0;
xi[2] = 1.0;
xi[3] = 1.0;

// x_l[i]设置xi的下界值, x_u[i]设置xi的上界值
Dvector xl(nx), xu(nx);
for(i = 0; i < nx; i++)
{
xl[i] = 1.0;
xu[i] = 5.0;
}
// g_l[i]设置约束i的下界值, g_u[i]设置约束i的上界值
Dvector gl(ng), gu(ng);
gl[0] = 25.0; gu[0] = 1.0e19;
gl[1] = 40.0; gu[1] = 40.0;

// object that computes objective and constraints
FG_eval fg_eval;

// options
std::string options;
// turn off any printing
options += "Integer print_level 0\n";
options += "String sb yes\n";
// maximum number of iterations
options += "Integer max_iter 100\n";
// approximate accuracy in first order necessary conditions;
// see Mathematical Programming, Volume 106, Number 1,
// Pages 25-57, Equation (6)
options += "Numeric tol 1e-6\n";
// derivative testing
options += "String derivative_test second-order\n";
// maximum amount of random pertubation; e.g.,
// when evaluation finite diff
options += "Numeric point_perturbation_radius 0.\n";

// place to return solution
CppAD::ipopt::solve_result<Dvector> solution;

// solve the problem
CppAD::ipopt::solve<Dvector, FG_eval>(
options, xi, xl, xu, gl, gu, fg_eval, solution
);

// Check some of the solution values
ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;
double rel_tol = 1e-6; // relative tolerance
double abs_tol = 1e-6; // absolute tolerance
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) {
//MPI_Init();
get_started();
return 0;
}