KKT 条件
一、直观理解:等式乘子 + 不等式「该不该出手」的规则
KKT 条件(Karush–Kuhn–Tucker conditions)是带等式与不等式约束的非线性规划在最优点必须满足的一阶条件(在约束规范下)。可以把它想成拉格朗日乘子法的完整版:
- 对等式约束:照旧有自由乘子 ;
- 对不等式约束:乘子 ,并且遵守互补松弛——约束没顶满(不活跃)时,乘子必须为 0;乘子为正时,约束必须顶满。
就像交通罚单:只有你真的压线(约束活跃),交警(乘子)才会出手;没压线就没有「价格」信号。
KKT 既是检验候选点是否可能最优的工具,也是内点法、SQP 等算法的设计靶心。凸问题中,KKT 往往成为充分必要条件。
二、适用场景与优缺点
| 类型 | 说明 |
|---|---|
| 适用场景 | 有不等式约束的 NLP;推导解析最优性条件;验证 fmincon 解是否满足一阶条件;理解活跃集与影子价格;凸优化理论证明。 |
| 核心优点 | 统一等式/不等式框架;互补松弛有清晰含义;凸时与全局最优紧密联系;乘子可解释。 |
| 局限与缺点 | 非凸时仅为必要(需规范)而非充分;约束规范失败时可能「无 KKT 乘子」;手算仅限低维;数值上互补松弛需容差判断。 |
使用前确认:
- 问题是否写成 s.t. 的标准形;
- 是否(近似)凸;
- 需要手推还是数值验证;
- 活跃约束集合是否可枚举(小问题)。
三、核心原理:平稳、原可行性、对偶可行、互补
1. 标准问题
2. 拉格朗日函数
3. KKT 条件()
- 平稳性:
- 原可行性:
- 对偶可行性:
- 互补松弛:
在 LICQ 等约束规范下,局部最优解处存在乘子满足 KKT。
4. 活跃集
互补松弛意味着 。不活跃约束仿佛不存在;活跃不等式在局部可当等式处理。
5. 凸问题中的充分性
若 凸, 仿射, 凸,则满足 KKT 的点就是全局最优。这是凸优化「好用」的根本原因之一。
6. 与线性规划对偶
LP 的互补松弛、影子价格是 KKT 的特例。读 linprog 的 lambda 与读 fmincon 的 lambda 结构体,思想一脉相承。
四、关键决策
1. 标准形方向
MATLAB 与许多教材对不等式默认 。若你的约束是 ,先变号,否则 符号解释全反。
2. 活跃集枚举(低维)
小问题可分类讨论哪些不等式取等,化为等式拉格朗日,再验证 与未取等约束可行。
3. 数值容差
可视为活跃; 视为互补近似成立。
4. 非凸多解
多个 KKT 点可能对应不同局部极小/鞍点,需比较 或用全局方法。
5. 与算法输出对照
fmincon 返回的 lambda.ineqnonlin、lambda.lower 等可用于验 KKT,是建模报告加分项。
五、MATLAB 示例
例 1:解析型小问题
无约束极小在 不可行;最优点应在边界 上靠近 。
fun = @(z) (z(1)-2)^2 + (z(2)-2)^2;
x0 = [0.5; 0.5];
A = [1, 1];
b = 2;
lb = [0; 0];
opts = optimoptions("fmincon", "Display", "final", ...
"ConstraintTolerance", 1e-10);
[x, fval, ef, out, lambda] = fmincon(fun, x0, A, b, [], [], lb, [], [], opts);
fprintf("x=(%.6f,%.6f), f=%.6f, exit=%d\n", x(1), x(2), fval, ef);
disp("线性不等式乘子 lambda.ineqlin:"); disp(lambda.ineqlin);
disp("下界乘子 lambda.lower:"); disp(lambda.lower);
% 数值检查平稳性:grad f + A' * mu_ineq - mu_lower ≈ 0
grad = 2*([x(1);x(2)] - [2;2]);
stationarity = grad + A' * lambda.ineqlin - lambda.lower;
fprintf("平稳性残差范数 = %.3e\n", norm(stationarity));
fprintf("互补: mu*(Ax-b) = %.3e\n", lambda.ineqlin'*(A*x-b));
例 2:非线性不等式
fun = @(x) x(1)^2 + x(2)^2;
nonlcon = @(x) deal( (x(1)-1)^2 + (x(2)-1)^2 - 1, [] ); % c<=0
x0 = [0.2; 0.2];
opts = optimoptions("fmincon", "Display", "iter");
[x, fval, ef, out, lambda] = fmincon(fun, x0, [], [], [], [], [], [], nonlcon, opts);
fprintf("解=(%.6f,%.6f), f=%.6f\n", x(1), x(2), fval);
disp(lambda.ineqnonlin); % 非线性不等式乘子
例 3:低维活跃集手检框架
% 对候选 x,检查 h<=0, mu>=0, mu.*h≈0, 平稳性
% 此处仅演示互补松弛判定
h = @(x) [x(1)+x(2)-2; -x(1); -x(2)]; % <=0 形式
x = [1; 1];
hv = h(x);
active = abs(hv) < 1e-7;
fprintf("h = "); disp(hv');
fprintf("活跃掩码 = "); disp(active');
六、如何解释结果
报告建议包含:
- 标准形下的 ;
- 最优点 与 ;
- 哪些不等式活跃、哪些松弛;
- 乘子数值及其非负性;
- 平稳性残差、互补残差、可行性残差;
- 若问题凸,明确「KKT ⇒ 全局最优」;否则称「满足一阶必要条件的局部候选」;
- 灵敏度:活跃约束乘子的业务含义。
七、常见误区
1. 认为任何局部最优都自动有 KKT 乘子
约束规范失败时可能例外(异常例子存在)。
2. 忽略
乘子符号错误常来自约束方向写反。
3. 把 KKT 点都当成全局最优
非凸时 KKT 点可能是局部极大(对 max 问题)或鞍点型驻点,需二阶或全局信息。
4. 互补松弛理解反了
「」与「」是同一件事的两面。
5. 数值上要求 机器零
应设合理容差,并同时看约束违反。
6. 只会背条件不会用求解器
建模竞赛中,KKT 更多用于解释与验证;求解仍靠 fmincon 等,二者结合最佳。
八、小结
KKT 条件的核心思想可以概括为:
在约束规范下,有约束局部最优必满足平稳性、可行性、乘子符号与互补松弛;在凸问题中这些条件往往也是充分的。
它是连接拉格朗日乘子法、对偶理论与现代约束优化算法的枢纽。使用时写清标准形、检查活跃集与乘子解释,并在非凸场合保持「局部/必要」的表述克制。数值上用 fmincon 的 lambda 做 KKT 残差检验,能显著提升结果可信度。