CVX是一个用于构建和求解凸优化问题的MATLAB工具箱。它允许您以自然、直观的方式在MATLAB中表述和解决凸优化问题,而无需手动将问题转换为标准形式。本文将通过几个典型示例带您快速入门CVX。
1. 什么是CVX?
CVX是一个用于构建和求解纪律性凸规划(Disciplined Convex Programming, DCP)的建模系统。它支持多种标准问题类型,包括:
线性规划(LP)
二次规划(QP)
二阶锥规划(SOCP)
半定规划(SDP)
混合整数凸规划(MIDCP)
CVX最大的优势是让您能够以接近数学表达式的自然方式描述优化问题,而无需手动转换为标准形式。
2. 基础安装
在使用CVX前,需要先安装:
下载CVX工具箱并解压到MATLAB路径中
在MATLAB中运行cvx_setup命令完成安装
% 解压CVX到MATLAB路径后
cd path/to/cvx
cvx_setup
3. 典型案例
3.1 最小二乘问题
最小二乘是最基本的优化问题,目标是找到使残差平方和最小的x。
% 生成随机数据
m = 20; n = 10;
A = randn(m, n);
b = randn(m, 1);
% 使用CVX求解最小二乘问题
cvx_begin
variable x(n)
minimize( norm(A*x - b) )
cvx_end
% 比较CVX解与MATLAB内置解
x_ls = A\b;
fprintf('CVX解与标准最小二乘解的差异: %f\n', norm(x - x_ls));
说明:
cvx_begin和cvx_end定义了CVX问题的边界
variable x(n)声明了一个n维优化变量
minimize(norm(A*x - b))定义了目标函数
3.2 带边界约束的最小二乘
在实际问题中,变量通常有物理限制,如非负性约束。
% 在最小二乘基础上添加非负约束
cvx_begin
variable x(n)
minimize( norm(A*x - b) )
subject to
x >= 0
cvx_end
% 比较有约束和无约束的解
fprintf('有约束解的范数: %f\n', norm(A*x - b));
fprintf('无约束解的范数: %f\n', norm(A*x_ls - b));
说明:
subject to关键字引入约束条件
x >= 0表示所有变量必须非负
3.3 L1范数最小化(稀疏解)
L1范数最小化常用于寻找稀疏解,例如压缩感知。
% 求解L1范数最小化问题
cvx_begin
variable x(n)
minimize( norm(A*x - b, 1) )
cvx_end
% 比较L1和L2最小化的解
fprintf('L1解的非零元素数量: %d\n', nnz(x));
fprintf('L2解的非零元素数量: %d\n', nnz(x_ls));
说明:
norm(..., 1)指定使用L1范数
L1最小化倾向于产生稀疏解(更多零元素)
3.4 二次约束优化问题
% 生成随机数据
P = randn(n, n);
P = P'*P; % 确保P是半正定的
q = randn(n, 1);
r = rand;
% 求解二次约束问题
cvx_begin
variable x(n)
minimize( 0.5*quad_form(x, P) + q'*x + r )
subject to
norm(x) <= 1
sum(x) == 0
cvx_end
说明:
quad_form(x, P)计算x'Px,其中P必须是半正定的
添加了两个约束:欧几里得范数约束和和为零约束
3.5 半定规划(SDP)
半定规划涉及矩阵变量和半正定约束。
n = 5;
C = randn(n); C = (C + C')/2; % 对称矩阵
A = randn(3, n, n); % 3个对称约束矩阵
b = rand(3, 1);
cvx_begin
variable X(n, n) symmetric
minimize( trace(C*X) )
subject to
for k = 1:3
trace(A(k,:)*X) == b(k);
end
X == semidefinite(n);
cvx_end
说明:
variable X(n, n) symmetric声明对称矩阵变量
X == semidefinite(n)表示X必须是半正定的
trace(C*X)是线性目标函数
3.6 最优权衡曲线
通过改变约束参数,可以生成最优权衡曲线,展示不同目标间的权衡关系。
n = 100;
m = 50;
A = randn(m, n);
b = randn(m, 1);
gamma = logspace(-1, 2, 50);
l2norm = zeros(size(gamma));
l1norm = zeros(size(gamma));
for i = 1:length(gamma)
cvx_begin
variable x(n)
minimize( norm(A*x - b) + gamma(i)*norm(x, 1) )
cvx_end
l2norm(i) = norm(A*x - b);
l1norm(i) = norm(x, 1);
end
% 绘制权衡曲线
loglog(l1norm, l2norm);
xlabel('||x||_1');
ylabel('||Ax-b||_2');
title('最优权衡曲线');
说明:
通过改变gamma参数,平衡拟合误差和解的稀疏性
权衡曲线展示了两个目标间的权衡关系
4. 常见错误与注意事项
DCP规则:CVX强制执行纪律性凸规划规则,如果违反规则会报错
例如:maximize(convex_function)会报错,因为最大化凸函数不是凸问题
变量声明:必须先用variable或variables声明变量
求解器选择:可以使用cvx_solver命令选择不同的求解器
cvx_solver sedumi % 使用SeDuMi求解器
精度设置:可以调整求解精度
cvx_precision high % 高精度模式
5. 进阶技巧
5.1 表达式持有器
cvx_begin
variable x(n)
expression y
y = A*x - b;
minimize( norm(y) + gamma*norm(x,1) )
cvx_end
5.2 对偶变量获取
cvx_begin
variable x(n)
dual variable lambda
minimize( norm(A*x - b) )
subject to
lambda: C*x == d
cvx_end
结语
CVX极大地简化了凸优化问题的建模过程,使您能够专注于问题本身而非技术细节。通过以上案例,您应该已经掌握了CVX的基本用法。随着经验的积累,您可以尝试更复杂的优化问题,包括几何规划、指数锥规划等。
记住,要有效使用CVX,需要对凸优化有一定的了解。推荐参考《Convex Optimization》(Boyd and Vandenberghe)一书获取理论基础。
祝您在凸优化的世界里探索愉快!