如何在Matlab中通过CVX调用MOSEK求解QP时提升收敛精度
Matlab环境CVX调用MOSEK求解QP精度不足的调整方案
CVX端基础配置校准
- 第一步先改CVX全局精度阈值,CVX默认精度仅适配快速原型验证,收敛判定极松。求解前在脚本里执行
cvx_precision high,若需要更高精度直接自定义容差:cvx_precision('best', 1e-12),强制CVX以更严格的残差、对偶间隙标准判定求解收敛,禁止提前终止。 - 优先调用本地独立安装的正式版MOSEK,不要用CVX安装包内置的老旧版本MOSEK,旧版本求解器存在QP求解逻辑bug,接口传参也容易丢信息。指定求解器的代码为
cvx_solver mosek,执行后可以看CVX启动输出的MOSEK版本号,确认和你本地安装的版本一致。 - 关闭CVX的激进问题化简逻辑,若发现CVX解析出的问题维度(变量数、约束数)和你手动建模的理论值不一致,执行
cvx_expert true关闭CVX自动判定“冗余约束”“冗余变量”的裁剪逻辑,避免有效问题信息被错误丢弃。 - 建模时尽量用原生QP结构写表达式,不要把简单二次目标拆成多个范数、幂运算嵌套,避免CVX自动把QP转成二阶锥规划形式引入额外松弛变量,拉低求解精度。
MOSEK求解器参数调优(强制充分迭代)
在cvx_begin前通过cvx_solver_settings传入MOSEK内部参数,覆盖默认的宽松收敛配置:
cvx_solver_settings(... % 收紧内点法收敛容差到接近双精度浮点极限 'MSK_DPAR_INTPNT_TOL_REL_GAP', 1e-14, ... 'MSK_DPAR_INTPNT_TOL_PFEAS', 1e-14, ... 'MSK_DPAR_INTPNT_TOL_DFEAS', 1e-14, ... 'MSK_DPAR_INTPNT_TOL_INFEAS', 1e-14, ... % 提高迭代上限,避免大/病态QP没跑完就触发迭代终止 'MSK_IPAR_INTPNT_MAX_ITERATIONS', 2000, ... % 开启高阶内点校正,提升病态问题求解精度 'MSK_IPAR_INTPNT_ORDER_METHOD', 1 ... )
- 如果调整上述参数后结果还是异常,可以临时关闭MOSEK自带的预处理:追加参数
'MSK_IPAR_PRESOLVE_USE', 0,排除预处理阶段错误改写问题的情况,正常求解时建议保持预处理开启以提升速度。 - 半正定QP存在零空间时,不要硬跑原始问题,可以手动给二次项海森矩阵加一个极小的单位矩阵正则:
Q = Q + 1e-12*eye(n),保证问题严格凸,避免内点法迭代震荡不收敛。
问题本身的数值校验
- 求解时先关闭静默模式
cvx_quiet(false),核对CVX输出的问题规模、目标函数类型和你建模的预期一致,避免写错表达式(比如把常量写成优化变量、二次项正定性写错)导致CVX传了错误的问题给MOSEK。 - 计算海森矩阵、约束矩阵的条件数,如果条件数超过1e12,先手动做变量、约束的归一化缩放,让所有矩阵元素量级落在0.1~10区间内,不要完全依赖求解器的自动缩放,病态矩阵的浮点误差会直接锁死求解精度上限。
- 求解完成后不要只看
cvx_status返回Solved就判定结果可靠,手动代入原始QP计算原始残差、对偶残差、目标值误差,如果手动算的残差远大于你设置的容差,说明接口状态判定有bug,优先升级CVX和MOSEK到兼容版本。
内容的提问来源于stack exchange,提问作者kloop
相关产品推荐
相关产品推荐

