【CDN布局规划】背后的算法技术3—多求解器批量求解对比

导读:优化领域存在诸多开源或者商业的 MIP 求解器,作为解决优化问题的底层核心工具,各类求解器针对不同编程语言提供了对应的建模求解接口。然而,不同求解器的建模求解接口存在差异,如果要切换求解器,还需要从头学习另一套 API 设计和编写代码,本着 DRY(Don’t Repeat Yourself)原则,本文调研了各类求解器的命令行调用方式,并以CDN布局规划问题为例,实现了一键运行,完成多案例、多求解器的自动化求解



作者 1:向杜兵,算法专家,某制造业龙头
作者 2:张哲铭,算法专家,某互联网大厂


  • 明人不说暗话,【运筹匠心】想要大家的赞!赞!赞!。先赞后看,多多益善(* ̄︶ ̄)~~~
  • 本期推文代码获取方式,将推文转发朋友圈获20赞,添加管理员微信,管理员会定期回复数据代码链接哈~~~
  • 各个系列的开源资料会定期整理发放,大家可以加粉丝群领取哦~~~

请加管理员微信:IndustryOR


大家好!我们是IndustryOR 团队,致力于分享业界落地的算法技术。欢迎关注微信公众号/知乎【运筹匠心】 。本期我们来谈一谈《CDN布局规划的算法技术》。本期案例共分 3 篇文章依次讲解:(1)业务问题拆解;(2)模型算法实现;(3)多求解器批量求解对比。

本篇文章讲解(3)多求解器批量求解对比

目前,市面上有众多商业和开源的 MIP 求解器可供选择,大多都支持不同的编程语言,且提供了丰富的建模求解接口。然而,如果我们想要更换求解器,或者想对不同求解器进行对比验证,调用不同求解器的 API 从头编写代码的方式需要重新学习各类求解器的 API,时间成本相对较高。

值得庆幸的是,大多数求解器都支持通过读取模型文件的方式进行求解,这意味着我们可以将问题建模后的模型数据保存到文件中,然后通过求解器的命令行进行求解,无需从头开始学习每种求解器的诸多接口,大大减少重复工作。

然而,不同求解器的命令行调用命令也存在差异。因此,我们对各类求解器的命令行调用方式进行了调研,并以前几期的 CDN 布局规划问题为例,对目前常见的 4 个求解器(Gurobi、CPLEX、COPT、MindOpt)进行了对比测试。

本文主要结构如下:
1. 各求解器命令行调用模式
2. 批量求解 Python 代码设计
3. CDN 布局规划问题求解对比分析

1.各求解器命令行调用模式

Gurobi
方式1:单行命令执行

gurobi_cl model.mps

方式2:交互执行

m=read("model.mps")
m.optimize()

CPLEX
交互式执行

read model.mps
optimize

COPT
方式1:交互式执行

read model.mps
optimize

方式2:读取命令文件

copt_cmd -i config.in

MindOpt
单行命令执行

mindopt model.mps

最终,确定各个求解器的调用模式,如下表所示:

求解器调用模式
Gurobi‘gurobi_cl model.mps’
CPLEX‘read model.mps’, ‘optimize’
COPT‘copt_cmd -i config.in’
MindOpt‘mindopt model.mps’
注:在后文所述的利用Python脚本对这些求解器进行命令行调用的过程中,部分求解器的某些方式调用失败,暂时没有解决,如果有读者有相关经验,我们可以互相交流

那么,了解了怎么通过这些求解器的命令行求解模型文件,就足够了吗?

命令行调用的方式多数是交互模式,即需要在命令行窗口交互式地输入命令才能向下执行,如果我们想要批量自动化求解多个模型,则可以通过编写自动化脚本的方式实现。

接下来将介绍如何编写 Python 脚本,实现对不同求解器的命令行调用,并自动化求解多个模型数据文件。该脚本通过读取模型文件、设置参数和调用相应的求解器命令,实现了自动化求解的过程。使用时只需准备好模型文件,然后一键运行,即可求解多个模型数据文件。

2.批量求解 Python 代码设计

由于不同求解器的调用方式存在差异,而对于自动化批量求解来说,我们不关心采用哪种求解器完成求解这个操作,我们又不想把各个求解器的调用逻辑混在一块,然后通过丑陋的if else判断,同时还得考虑后续可能需要扩展其他的求解器。因此,本着开闭原则,我们决定采用继承的方式来实现这个功能。这样,每个求解器的调用实现完全独立,扩展其他求解器也无需修改已有代码。

基类:SolverCaller

子类:GurobiCaller、CplexCaller、CoptCaller、MindOptCaller

3.CDN布局规划问题求解分析

借助该脚本,对 4 个商业求解器(经小案例测试,开源求解器 SCIP、OR-Tools 等在该问题上求解速度与商业求解器差距较大,不再对比)进行了对比,求解了 3*10 共30个案例(数据来源:某公开比赛数据集),以下为求解结果:
求解时间对比图

横轴:案例编号
纵轴:各求解器的求解时长(秒)
注:除了求解时长限制为 3600s 外,所有求解器均采用默认参数。
结论:
30 个案例中,solver_1、solver_2、solver_3、solver_4 在 1 小时内达到时长限制的案例数量分别为:3、4、15、12。

另外,对于 solver_3 和 solver_4 均达到时长限制(1小时)的案例,统计各自最终的 Gap,如下图所示:
求解 Gap对比图

横轴:案例的编号
纵轴:Gap(%)

结语

本篇:介绍了使用命令行调用求解器进行自动化批量求解的方法,并通过对CDN布局规划问题的多个实例进行比较分析,提供了对不同求解器求解性能的初步了解。需要强调的是,本文的对比结果只是针对这一特定问题的特定数据集,在其他数据,其他不同问题上,各个求解器的表现可能与本文中的存在差异。

本系列文章:在该系列中,我们一起从问题拆解、模型刻画、批量求解等方面研究了CDN布局规划问题,并沉淀了一套多求解器、批量求解、可扩展的自动化方案。完结撒花~~~

值得一提的是,如果我们不追求最优解,而是想要在更短的时间内得到一个不错的规划方案,那么可以设计启发式算法来对该问题求解,这也是在本次案例对应比赛中的主流技术方案。得益于灵活、高效等特点,启发式算法在工业界的应用更加广泛,且在更前沿的应用中,会与机器学习、深度学习、强化学习等 AI 技术相结合。后续我们也将分享在业界落地的诸多技术方案,期待我们下一次的相遇。


请大家多多点赞、评论、转发、关注!大家的支持是我们持续创作的动力。我们是【运筹匠心】 ,咱们下期见~~~

参考文献:
[1]Gurobi Optimizer Reference Manual
[2]启动 CPLEX
[2]COPT交互式命令行工具
[3]命令行调用 MindOpt

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设我们要求v1到其他各个点的最短路径,图如下: ![Dijkstra算法示例图](https://cdn.luogu.com.cn/upload/image_hosting/e2u9r9hc.png) 我们按照Dijkstra算法的步骤来求解: 1. 初始化:将v1的最短路径长度dist[v1]设为0,其余顶点的最短路径长度dist[v]设为正无穷。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | ∞ | | v3 | ∞ | | v4 | ∞ | | v5 | ∞ | 2. 确定已知最短路径的顶点:从所有未确定最短路径的顶点中选取dist值最小的顶点v1,将其标记为已确定最短路径。 3. 更新邻接顶点的最短路径长度: - 对于v2,dist[v1]+w(v1,v2)=10<∞,更新dist[v2]=10; - 对于v3,dist[v1]+w(v1,v3)=3<∞,更新dist[v3]=3; - 对于v4,v1和v4之间没有边,不需要更新; - 对于v5,v1和v5之间没有边,不需要更新。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | 10 | | v3 | 3 | | v4 | ∞ | | v5 | ∞ | 4. 重复步骤2和3,选择dist值最小的未确定最短路径的顶点v3,将其标记为已确定最短路径。 5. 更新邻接顶点的最短路径长度: - 对于v2,v3和v2之间没有边,不需要更新; - 对于v4,v3和v4之间没有边,不需要更新; - 对于v5,v3和v5之间没有边,不需要更新。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | 10 | | v3 | 3 | | v4 | ∞ | | v5 | ∞ | 6. 重复步骤2和3,选择dist值最小的未确定最短路径的顶点v2,将其标记为已确定最短路径。 7. 更新邻接顶点的最短路径长度: - 对于v4,dist[v2]+w(v2,v4)=20<∞,更新dist[v4]=20; - 对于v5,v2和v5之间没有边,不需要更新。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | 10 | | v3 | 3 | | v4 | 20 | | v5 | ∞ | 8. 重复步骤2和3,选择dist值最小的未确定最短路径的顶点v5,将其标记为已确定最短路径。 9. 更新邻接顶点的最短路径长度: - 对于v4,v5和v4之间没有边,不需要更新。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | 10 | | v3 | 3 | | v4 | 20 | | v5 | ∞ | 10. 重复步骤2和3,选择dist值最小的未确定最短路径的顶点v4,将其标记为已确定最短路径。 11. 更新邻接顶点的最短路径长度: - 对于v5,v4和v5之间没有边,不需要更新。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | 10 | | v3 | 3 | | v4 | 20 | | v5 | ∞ | 12. 重复步骤2和3,选择dist值最小的未确定最短路径的顶点v5,将其标记为已确定最短路径。 13. 更新邻接顶点的最短路径长度: - 无法更新。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | 10 | | v3 | 3 | | v4 | 20 | | v5 | ∞ | 14. 最终得到v1到各顶点的最短路径长度dist。 | 顶点 | dist值 | | --- | --- | | v1 | 0 | | v2 | 10 | | v3 | 3 | | v4 | 20 | | v5 | ∞ |

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值