本文整理自官方教程,是对多份官方资料学习所得笔记。
目录
不可行诊断工具infeasibility detection tools
优化失败
常见原因
- 代码问题
- 无法捕获异常
- 无法测试解的状态
- 许可证
- 数据错误
- 内存满了、硬件故障
诊断步骤
- 什么错误?
- 你需要做什幺才能让它失败?什么操作导致的?
- 可复现性?你能可靠地复现它还是只能随机复现它?
- 代码中的哪个位置失败?
-
- 模型创建
- 求解
- 回调
- 检索解决方案值
原因排查
- 捕获异常Catch exceptions
- 使用系统分析工具:System Monitor, top, Activity Monitor, profiler in compiler
- 独立于代码测试模型
- 换用云端的不同硬件
独立于代码测试模型
- 将模型导出为MPS文件。
model.update();
model.write("test.mps”);
导出参数配置,可以导出以下几个配置文件:
- 非默认参数放在.prm后缀的文档
- MIP初值放在.mst后缀的文档
- 初始 LP线性规划基础放在.bas后缀的文档
model.update();
model.write("test.mps");
model.write("test.prm");
model.write("test.mst");
- 在命令行/gurobi自己的shell界面运行gurobi
#命令行
gurobi_cl test.mps
#或者gurobi自己的shell界面
model=read("test.mps") model.optimize()
使用文档写入和读取参数,热启动:
#命令行
gurobi_cl
inputfile=test.prm inputfile=test.mst test.mps
#或者gurobi自己的shell界面
model=read("test.mps")
model.read("test.prm")
model.read("test.mst") model.optimize()
优化异常
常见异常
- 模型不可行infeasible
- 已知的解决方案不可行not feasible
- 解决方案欠优suboptimal
- 解决方案违反已知约束violates some known constraints
- 数值稳定性问题
常见原因
- 模型错误
- 输入数据异常
- 其它数字问题
原因排查
- 检查log日志,和模型统计数据
- 检查LP文件
- 测试已知解
- 尝试不可行诊断infeasibility detection
log日志
模型文档中的问题仅在使用 MPS 或 LP 文档时显示
MPS 和 LP 格式未完全指定
模型统计数据
统计数据如下,比较模型规模是否符合预期。
检查LP文件
输出 LP 格式文件。 LP 格式文件是最接近数学模型表达式的格式,每写一步程序,就可以输出为 LP 文件。打开后和手写的模型做对比,来检查程序是否正确。
对于 C, C++, C#, Python, Java, R, Matlab 这些 Gurobi 直接支持的语言,输出LP 文件可以用 model.write 命令;
测试已知解
MIP 最优性
把前一步的解作为初值带入,再次优化。看有没有提升
m=read("test.mps")
m.read("test.mst")
m.optimize()
可行性
对优化变量增加约束。通过约束增减来判断。
对复杂问题的不可行进行溯源,是一项繁琐的工作,计算量不亚于求解一个优化模型。如果以上方式无法在短时间找到源头,用户也可以通过逐步增加约束,边增加边判断的方式发现问题的源头
m=read("test.mps")
x=m.getVarByName("x")
x.setAttr("LB", 1.0)
x.setAttr("UB", 1.0)
不可行诊断工具infeasibility detection tools
主要有不可约不一致子系统 Irreducible Inconsistent Subsystem (IIS),和约束放松feasRelax两个方法。
不可约不一致子系统(IIS)
功能:
- 查找相互冲突的约束的最小集合
- 指示无法满足的属性
- 适用于模型开发
Gurobi 9.5 版本允许用户为变量的上下界、线性约束、二次约束、 SOS 约束、非线性约束单独设置 IIS Force 属性,也就是 IISConstrForce, IISLBForce, IISUBForce, IISSOSForce, IISQConstrForce, and IISGenConstrForce 属性。
如果这些属性值设置为 1(默认值为-1),那么就要求 Gurobi 必须将这些变量上下界和约束包含到 IIS 计算当中。
这个属性的最大作用,就是当一个可行模型在添加新的约束和变量上下界之后,变得不可行, 需要溯源哪些新的变化造成了模型不可行。
这种情况下,用户可以将原模型中的变量边界和约束的 Force 属性设定为 1,然后运行 ComputeIIS(),那么 Gurobi 只会专注在新增加的约束和变量边界上,不但溯源的时间会更短,而且提供的信息可以更容易让用户发现问题。 但需要注意这种方式获得的 IIS 集合不一定是最小集合。
约束放松feasRelax
功能:
- 找到有最少的约束冲突的解
- 检索人工添加的松弛变量以查找违规行为
- 适用于已部署的应用
复杂问题 computeIIS() 时间长,或者输出的 ILP 冲突约束文件不容易看出来具体的错误源头。这时采用 Gurobi 的 feasRelaxS() 和feasRelax() 函数。其中, feasRelaxS() 是 feasRelax() 函数的简化,易用,我们以此为列来进行说明。
feasRelaxS() 和 feasRelax() 函数的功能,是在原有模型基础上,为变量和约束添加松弛变量,让松弛模型变得可行,然后通过最小化松弛量来获得一个最小违反变量和约束限制的模型。
用户可以观察优化后的松弛变量的数值是否为 0(全部松弛变量为 0 意味着模型有可行解),以及数值范围, 来初步了解哪些约束可能是问题的源头,以及冲突的程度。需要说明的是,任何模型不可能由单一约束或者单一变量边界造成不可行。不可行的模型往往存在若干个约束和变量边界一起发生冲突,导致最终不可行,因此导致冲突的原因可以有无穷多的解读和因果链条,并不存在唯一的化解方式,需要结合模型的应用场景来调整。
样例:feasopt.py
样例步骤:
- 用 m=read(“model.ilp”) 读入这个模型。 ILP 格式和 LP 格式一致。
- 用 m.feasRelaxS(0,False,False,True) 添加松弛变量。函数参数的具体含义请看参考手册。
- 用 m.optimize() 运行这个松弛模型。
- 用 m.write(“model.sol”) 将松弛模型的优化结果输出到 model.sol 文件。
- 用 m.write(“model.lp”) 将松弛模型输出到 model.lp 文件,这里面包含了松弛变量,以 Art 开头。 所有的松弛变量为非负。
- 打开 model.sol 文件, 我们可以忽略在 model.lp 中标记为 free 的那些变量,例如 C1126 等,这些变量无论取什么数值都和不可行无关。我们注意到松弛变量 ArtN_R10165 的数值不为 0,对应的 R10165 约束中另外一个松弛变量ArtP_R10165 为 0,就意味着约束 R10165 距离可行还相差 0.5605625。化解这个冲突可以有很多方法,要结合模型实际应用背景来处理,例如可以让 C8069的下界从原来的 0, 更改为-0.5605625;或者更改 C66 的边界值,等等。
我们以上的方法是将 feasRelaxS() 函数作用于 ILP 文件,也就是运行 ComputeIIS()之后的输出文件。用户也可以直接将 feasRelaxS()作用于原始 LP 文件,方法一致。作用于 ILP的好处就是排除不相关的约束,让分析更聚焦在冲突的约束上
优化缓慢
常见原因
- 数值问题
- 内存限制
- 不切实际的容差值
- 大型或困难的模型
原因排查
- 导致性能降低的情况
- 算法瓶颈
- 参数调优工具 Parameter tuning tool
- 性能指南
- 将测试模型发送给Gurobi
导致性能降低的情况
- 哪些数据导致缓慢
- 缓慢是随机产生,还是可预测稳定产生?
- 硬件原因
算法瓶颈
- 模型初始化和解决方案检索。用gurobi_cl命令行工具检测.mps文件,查看速度是否提升
- 求解过程。
- 预解析
- 求解(初始 LP)
- MIP的节点0
- MIP的其他节点
- log日志显示预求解、LP 松弛、MIP 根、节点所花费的时间
- 在log日志中查看各个部分的时间开销,查找代码瓶颈
性能调优
常用方法
- 一般方法
- 预计算
- 连续优化
- 整数优化
- 约束简化
一般方法
模型初始化
- 每个矩阵生成器都有自己的陷阱和最佳实践。有效地对 API 使用迭代器
- 通过代码分析器查找:瓶颈
- OO接口是C矩阵接口上的薄层
- 使用Gurobi OO接口,利用延迟更新。仅在必要时调用更新函数以引用新对象
语法
- c++循环的优化
- 优化器模型的引用传参
- 避免在一个语句中嵌入多个循环和条件定义,避免嵌套多个 sum (quicksum) 语句。对于新手而言,建议用多个独立循环,单独罗列条件来构造复杂的多个变量或者约束
内存
- 内存不足会破坏性能
- 通过磁盘的虚拟内存比 RAM 慢得多
- 并行优化需要更多内存
- 通过计算机上的系统监视器工具查找:内存使用情况。如:系统监视器、活动监视器
- 参数
- 减少线程数threads
- 设置NodefileStart使用磁盘存储 MIP 节点信息
- 内存可劲儿造
预计算
- 意义:预先花时间,以简化模型。
- 方法:预先查找有不同预计算参数的性能方案
- 控制参数:Presolve
希望降低预计算时间,降低该参数;希望简化模型,增加该参数;
- 附加参数:精细调节
参数名 | 功能 |
PrePasses | 有空再补上这一行。下同 |
Aggregate | |
AggFill | |
PreSparsify | |
PreDual | |
PreDepRow |
连续优化
等有空再补上这一段。
整数优化
等有空再补上这一段。