1.求解器的选择
OR-Tools提供了用于求解 线性规划和 混合整数规划问题的 MPSolver 接口容器,易于调用各种不同求解器。gurobi 当然无论在各个问题上性能都要优胜许多,考虑到毕竟是商用求解器,这里主要枚举开源免费的求解器。
问题类型 | 求解器 |
---|---|
纯整数规划(IP) | CP-SAT |
线性规划(LP) | Glop |
混合整数规划(MIP) | SCIP, CP-SAT |
由于MIP问题是最为麻烦难解的,建模时候尽量考虑建成LP或IP,求解速度会快很多。尤其google ortools 整合了SAT/CP solver,CP_SAT 对于一部分MIP问题也可以求解,部分问题效果比SCIP好很多。
2.求解器的收敛
做一个简单的数值实验对比不同求解器的求解速度。构建一个小规模整数规划问题,算例都一样,模型也一样,唯一的区别即求解器不同,这里测试GUROBI,CP_SAT,SCIP三个比较常用的求解器。
ortools调用solver.
solver = pywraplp.Solver.CreateSolver('SCIP') # GUROBI SCIP CP_SAT
2.1 相同时间下求解结果
先用gurobi求解算例,14s后得到最优解,设定求解时间为14s,再依次求解CP_SAT,SCIP,结果如下表所示。
求解器 | 求解时间(s) | 是否最优解 | obj |
---|---|---|---|
gurobi | 14 | 是 | 9190.0 |
CP_SAT | 14 | 是 | 9190.0 |
SCIP | 14 | 否 | 9305.49 |
(CP_SAT 在规定时间内同样求得最优解,但如果不加限制求解依然不会停止,这里可能是求解器数值问题)
2.2 不同时间段求解结果
我们设定不同的停止时间,观察求解器的求解情况,可以看到gurobi无论是在初始解以及最后的收敛上都要技高一筹,其实在第7s时就已经找到了最优解,但程序最终停止时间是14s,剩余的这段时间大概就是验优的过程。我设置的算例为IP,CP_SAT表现略逊gurobi但也不错,但SCIP在短时间内陷入了局部最优,跳出局部最优需要更多的时间,显然这就是不同求解器内部性能的一个差异了。
limit Time(s) | gurobi | CP_SAT | SCIP |
---|---|---|---|
1 | 9215.0 | 9241.0 | 9305.49 |
2 | 9215.0 | 9215.5 | 9305.49 |
3 | 9215.0 | 9215.0 | 9305.49 |
5 | 9209.5 | 9211.5 | 9305.49 |
7 | 9190.0 | 9199.5 | 9305.49 |
10 | opt | 9196.0 | 9305.49 |
12 | opt | 9205.5 | 9305.49 |
14 | opt | 9190.0 | 9305.49 |
2.3 目标函数变化曲线
上面用一个小规模算例简单比较了一下三个求解器的求解性能,为了更好的看到求解器gap变化情况,这里将算例规模适当扩大(算例太大了过于费时),给予不同的停止时间,绘制目标函数随时间变化曲线。结果很显著,对于整数规划问题CP_SAT效果明显优于SCIP。
求解器内部搜索、剪枝算法有差异,尤其到接近最优解时,容易围绕最优解震荡,耗费大量的时间,在调用时需要注意,最好限制GAP或时间。这里参考知乎回答:
3.结论
- gurobi的收敛性能很好,但商业求解器价格昂贵,在一些小规模case上尤其IP使用google的CP_SAT是个不错的替代选项;
- 在使用时有必要限定求解时间和gap,尤其在不要求最优解的情况下;