1. 序列二次规划法SQP概述
序列二次规划法(Sequential Quadratic Programming, SQP)是解决非线性约束优化问题的有效数值方法。我第一次接触SQP是在研究生期间的一个机械臂轨迹优化项目中,当时需要最小化机械臂运动能耗同时满足关节角度限制和末端执行器的路径约束。传统优化方法要么收敛速度慢,要么难以处理非线性约束,而SQP完美解决了这些问题。
SQP的核心思想是将原始非线性优化问题转化为一系列二次规划(QP)子问题来迭代求解。每次迭代时,在当前点构造一个二次近似模型,通过求解这个局部QP问题得到搜索方向,再结合线搜索确定步长。这种方法结合了牛顿法的快速收敛特性和约束优化的可行性保持机制。
实际工程中约80%的约束优化问题都可以用SQP有效求解,特别是在机械设计、化工过程优化、金融投资组合等领域应用广泛。
2. 非线性优化问题建模
2.1 标准问题形式
考虑如下一般形式的非线性约束优化问题:
matlab复制min f(x)
s.t. h_i(x) = 0, i = 1,...,m
g_j(x) ≤ 0, j = 1,...,p
其中x∈R^n为决策变量,f(x)为目标函数,h_i(x)为等式约束,g_j(x)为不等式约束。所有函数至少二阶连续可微。
2.2 MATLAB建模示例
以化工反应器优化为例,我们需要最小化生产成本:
matlab复制function [f, h, g] = reactor_model(x)
% x = [温度; 压力; 催化剂浓度]
f = 2*x(1)^2 + 5*exp(x(2)) - 3*x(3); % 成本函数
h = x(1)*x(3) - 10; % 产物收率等式约束
g = [x(2) - 5; % 压力上限
-x(3) + 0.1]; % 催化剂下限
end
3. SQP算法实现细节
3.1 拉格朗日函数与KKT条件
构造拉格朗日函数:
code复制L(x,λ,μ) = f(x) + λ'h(x) + μ'g(x)
KKT最优性条件要求:
- ∇xL = 0
- h(x) = 0
- g(x) ≤ 0
- μ ≥ 0
- μ_j g_j(x) = 0 (互补松弛)
3.2 QP子问题构造
在第k次迭代时,在当前点x_k处构造QP子问题:
matlab复制min 0.5*d'B_k*d + ∇f(x_k)'d
s.t. h(x_k) + ∇h(x_k)'d = 0
g(x_k) + ∇g(x_k)'d ≤ 0
其中B_k是拉格朗日函数的Hessian矩阵或其近似。
3.3 算法流程
- 初始化:给定x0,B0(通常取单位矩阵)
- 循环直到收敛:
a. 求解当前QP子问题得搜索方向d_k
b. 线搜索确定步长α_k
c. 更新x_{k+1} = x_k + α_k d_k
d. 更新B_k+1 (BFGS等拟牛顿法) - 输出最优解x*
4. MATLAB实现详解
4.1 fmincon函数使用
MATLAB优化工具箱提供了内置的SQP实现:
matlab复制options = optimoptions('fmincon','Algorithm','sqp');
[x_opt, fval] = fmincon(@objfun, x0, [], [], [], [], lb, ub, @confun, options);
function f = objfun(x)
f = 2*x(1)^2 + 5*exp(x(2)) - 3*x(3);
end
function [c, ceq] = confun(x)
ceq = x(1)*x(3) - 10; % 等式约束
c = [x(2) - 5; % 不等式约束
-x(3) + 0.1];
end
4.2 自定义SQP实现
对于需要深度定制的情况,可以手动实现SQP:
matlab复制function [x_opt, hist] = mySQP(fun, x0, max_iter, tol)
n = length(x0);
x = x0;
B = eye(n); % 初始Hessian近似
hist = zeros(max_iter, n+1);
for k = 1:max_iter
[f, df, d2f] = fun(x);
% 构造并求解QP子问题
[d, lambda] = solveQP(B, df, x);
% 线搜索
alpha = 1;
while fun(x + alpha*d) > f + 0.1*alpha*df'*d
alpha = alpha/2;
end
% 更新迭代点
x_new = x + alpha*d;
% BFGS更新Hessian近似
s = x_new - x;
y = fun(x_new, 'gradient') - df;
B = B + (y*y')/(y'*s) - (B*s*s'*B)/(s'*B*s);
x = x_new;
hist(k,:) = [x', f];
if norm(d) < tol
break;
end
end
x_opt = x;
end
5. 工程应用案例分析
5.1 机械臂轨迹优化
考虑6自由度机械臂从A点到B点的最优轨迹规划:
matlab复制% 目标:最小化关节变化总和
% 约束:末端执行器路径约束、关节角度限制
function trajectory_optimization()
n = 100; % 时间步数
q0 = zeros(6,1); % 初始关节角度
qf = [pi/2; 0; 0; 0; 0; 0]; % 最终位置
% SQP求解
options = optimoptions('fmincon','Display','iter','Algorithm','sqp');
q_opt = fmincon(@(q)sum(diff(q).^2,'all'),...
linspace(q0,qf,n),...
[],[],[],[],...
repmat([-pi;-pi/2;-pi;-pi;-pi;-pi],1,n),...
repmat([pi;pi/2;pi;pi;pi;pi],1,n),...
@(q)path_constraints(q,q0,qf),...
options);
% 可视化结果
plot_trajectory(q_opt);
end
function [c, ceq] = path_constraints(q, q0, qf)
ceq = [q(:,1) - q0; q(:,end) - qf]; % 始终点约束
c = []; % 可添加避障约束等
end
5.2 投资组合优化
马科维茨均值-方差模型:
matlab复制function portfolio_optimization()
returns = randn(100,3); % 3种资产的收益率
mu = mean(returns)';
Sigma = cov(returns);
% 目标:最小化风险,预期收益≥r_min
r_min = 0.05;
x0 = ones(3,1)/3;
options = optimoptions('fmincon','Algorithm','sqp');
w_opt = fmincon(@(w)w'*Sigma*w,...
x0,...
[],[],...
[mu'; ones(1,3)],...
[r_min; 1],...
zeros(3,1),...
ones(3,1),...
[],...
options);
pie(w_opt);
end
6. 性能调优与问题排查
6.1 收敛性问题处理
-
振荡现象:减小初始步长或增加阻尼项
matlab复制options = optimoptions('fmincon','StepTolerance',1e-6,'ScaleProblem','obj-and-constr'); -
Hessian矩阵病态:使用正则化
matlab复制B_k = B_k + 1e-6*eye(n); -
约束冲突:检查约束可行性
matlab复制[c,ceq] = confun(x0); if any(imag(c)) || any(imag(ceq)) error('初始点不满足约束'); end
6.2 计算效率优化
-
解析梯度提供:
matlab复制options = optimoptions('fmincon','SpecifyObjectiveGradient',true); -
并行计算:
matlab复制options = optimoptions('fmincon','UseParallel',true); -
稀疏模式利用:
matlab复制options = optimoptions('fmincon','HessPattern',hesspattern);
7. 高级技巧与扩展应用
7.1 全局优化结合
当问题存在多个局部最优时:
matlab复制gs = GlobalSearch;
problem = createOptimProblem('fmincon','objective',@objfun,...);
x_opt = run(gs,problem);
7.2 实时优化应用
对于需要在线优化的控制系统:
matlab复制function realtime_optimization()
persistent opt_obj
if isempty(opt_obj)
opt_obj = optimset('Algorithm','sqp','Display','off');
end
while true
measurements = get_sensor_data();
x_opt = fmincon(@(x)cost_func(x,measurements),...
x0,...
[],[],[],[],...
lb,ub,...
@(x)constraints(x,measurements),...
opt_obj);
apply_controls(x_opt);
pause(0.1);
end
end
7.3 自动微分应用
对于复杂函数,使用自动微分提高精度:
matlab复制fun = ADfun(@myObjective,1); % 1表示求梯度
[x,grad] = feval(fun,x,ADoptions('gradient',1));
8. 实际项目经验分享
在最近的一个能源系统优化项目中,我们需要在30分钟内完成包含500多个变量的非线性优化。经过测试发现:
- 初始点选择至关重要:使用物理启发式方法生成初始点比随机初始化快3倍收敛
- 约束缩放很关键:将约束值归一化到[0,1]范围可提高数值稳定性
- 并行计算收益:在16核服务器上,计算时间从45分钟降至8分钟
一个特别有用的调试技巧是可视化优化路径:
matlab复制options = optimoptions('fmincon','OutputFcn',@outfun);
function stop = outfun(x,optimValues,state)
persistent h
if strcmp(state,'iter')
if isempty(h)
h = plot(x(1),x(2),'ro');
else
set(h,'XData',[get(h,'XData') x(1)],...
'YData',[get(h,'YData') x(2)]);
end
end
stop = false;
end
