线性或二次优化经常会碰到无解情况。一个典型的线性或二次优化问题如下:
除了数据精度等问题外, MOSEK 优化器会提示下面几种无解情况:
- PRIME INFEASIBLE
- DUAL INFEASIBLE
当然有时候两个都 INFEASIBLE。其中 PRIME INFEASIBULE 主要是指限制条件互相冲突了,没有可行解。DUAL INFEASIBLE 是指对偶形式的限制条件。
DUAL INFEASIBLE 通常表明在给定限制条件下,目标函数的方向反了,最优值可能是无穷大。这种情况在日常中不太容易出现(一般是max
和min
写反了)。我们最常见需要解决的是 PRIME INFEASIBLE ,也就是找出那些冲突的限制条件。以 C++为例:
第一步:在 C++代码里导出问题到文件
model->writeTask("./dump.task");
如果是在 Python 中:
with Model("your problem") as model:
# your problem, variables and conditions
model.writeTask("./dump.ptf")
mosek 在导出时有三种格式: odf, ptf, task。其中 odf 是早期版本, ptf 支持更复杂的模型且可读, task 是二进制文件。所以优先选用 ptf 文件格式。
对于不支持的模型,
.odf
会提示以下错误:mosek.Error: rescode.err_invalid_file_format_for_affine_conic_constraints(4012):
The file format does not support a problem with affine conic constraints. Use the PTF format instead.
注意都升级 mosek 以及 Python 包到最新版本。如果 mosek 版本和 mosek 的 Python 包版本不兼容,如果是 ptf ,在 mosek 进行处理时会提示无法识别格式的错误:
Reading started.
MOSEK error 1090: The specified format cannot be read. The format code is 6
如果 mosek 版本和 mosek 的 Python 包版本不兼容,在读取 task 导出文件时可能会提示:
Reading started.
MOSEK error 2561: The Task file is invalid.
第二步:在命令行运行诊断命令
mosek dump.opf --infrepo -d MSK_IPAR_INFEAS_REPORT_AUTO 1 -q mose.log
如果提示找不到 mosek 或无输出,将mosek
的路径写全,
/opt/3rd/mosek/10.1/tools/platform/linux64x86/bin/mosek dump.opf --infrepo -d MSK_IPAR_INFEAS_REPORT_AUTO 1 -q mosek.log
然后在mosek.log
里可以看哪些条件不满足,类似于下面这个:
MOSEK PRIMAL INFEASIBILITY REPORT.
Problem status: The problem is primal infeasible
The following constraints are involved in the primal infeasibility.
Index Name Lower bound Upper bound Dual lower Dual upper
5229 condition[2] unimportant 1.000000e-02 -0.000000e+00 -1.000000e+00
The following bound constraints are involved in the infeasibility.
Index Name Lower bound Upper bound Dual lower Dual upper Dual cone
4 weights[3] -1.728642e-03 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
8 weights[7] -1.561579e-03 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
22 weights[21] -1.350838e-03 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
24 weights[23] -1.430027e-03 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
31 weights[30] -4.973163e-03 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
65 weights[64] 9.658339e-06 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
66 weights[65] 1.240400e-06 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
68 weights[67] 6.213882e-03 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
69 weights[68] -1.487085e-03 unimportant -1.000000e+00 -0.000000e+00 -0.000000e+00
比如上面提到是condition
的第二行无法满足,对应的冲突限制条件也列出来了。dump.opf
里可以查到condition[2]
的表达式,它是那些weights
之和。这里的冲突很简单,就是weights
都给了下界,加起来也会有一个下界,而这个下界超出了condition[2]
约定的的上界,从而引发一个冲突。
另注: mosek 的 fusion 是需要单独编译安装的,参考下面步骤即可:https://docs.mosek.com/latest/cxxfusion/install-interface.html#testing-the-installation-and-compiling-examples。
Q. E. D.