优化|PyOptInterface:高效且灵活的Python优化建模语言

liftword2周前 (01-20)技术文章14

优化建模语言作为优化求解器与终端用户之间的桥梁,是构建、求解和分析优化模型的重要工具。建模语言的效率直接影响优化模型的构建和求解时间。PyOptInterface是一种基于Python编程语言的优化建模语言,相比现有建模语言兼具高效率和灵活性,在优化建模性能方面实现了10-20倍的显著提升。


一、PyOptInterface简介

PyOptInterface是一个基于Python 的开源通用优化建模语言,由合肥工业大学电气与自动化工程学院杨越副教授、清华大学电机系吴文传教授团队合作开发,代码目前已经在Github开源:https://github.com/metab0t/PyOptInterface,并附有详尽的在线文档网站:https://metab0t.github.io/PyOptInterface/,相关论文已经发布在arXiv预印本平台:https://arxiv.org/abs/2405.10130。

PyOptInterface目前支持求解以下八类优化问题:

  1. 线性规划 (LP)
  2. 混合整数线性规划(MILP)
  3. 二次规划 (QP)
  4. 混合整数二次规划 (MIQP)
  5. 二次约束二次规划 (QCQP)
  6. 混合整数二次约束二次规划 (MIQCQP)
  7. 二阶锥规划 (SOCP)
  8. 混合整数二阶锥规划 (MISOCP)

在优化求解器的支持方面,PyOptInterface目前支持调用以下四种性能领先的商业和开源优化求解器:

1. COPT

2. Gurobi

3. HiGHS

4. Mosek


二、实际优化建模中的痛点问题

在优化建模方面,已有AMPL、GAMS、Pyomo、JuMP.jl等兼容多个求解器的通用建模语言,也有COPT、Gurobi等求解器自带的Python编程接口,然而在实际使用中存在以下痛点:

  1. AMPL、GAMS等基于领域特定语言(Domain Specific Language,DSL)的优化建模语言学习门槛高,难以和Python等数据分析处理的工作流融合,难以实现高效的模型增量修改和求解。
  2. Pyomo等兼容多求解器的建模语言,对大规模优化模型的建模速度不尽如人意,与直接使用求解器的底层接口之间的性能差距显著。
  3. COPT、Gurobi等求解器自带的Python编程接口性能较好,然而不同求解器的接口存在差异,导致代码与求解器深度耦合,难以切换求解器。


三、PyOptInterface与其他优化建模语言相比的优势:

PyOptInterface使用了创新性的设计架构,通过建立变量、约束等对象与优化求解器底层接口间的高效映射,最大程度压缩了通用建模语言和使用优化求解器底层接口之间的性能差距,与现有的建模语言相比具有以下几大优势:

  1. 通过C++实现的内核直接调用优化求解器的底层C接口,构建优化模型的速度非常快,在性能测试中建模速度最接近求解器的C++接口,比Pyomo快10-20倍,比一些优化求解器的官方Python接口快2-5倍,并超越了目前速度最快的开源建模语言JuMP.jl。
  2. 支持多求解器的模型增量修改和重新求解(包括添加/删除/修改变量或者约束条件、更改目标函数等),无需重新构建模型,适合实现Benders分解、列生成、序列线性化等需要逐次求解模型的算法。
  3. 提供了涵盖常用功能的统一编程接口,只需编写一份代码即可适用于所有优化求解器。
  4. 在统一接口的基础上,仍然提供了设置优化求解器特定参数等底层接口和高级功能,比如支持混合整数规划(MIP)中的回调函数(callback function),提供与优化求解器官方Python接口相近的完备功能。



四、建模性能测试

我们选择了八个不同规模的优化模型作为测试案例,分别使用 Gurobi 和 COPT 作为优化器进行了两轮基准测试。针对每个模型,记录了不同建模语言生成模型并提交给优化求解器的总时间,并将优化求解的时间限制设为0.0秒,以避免求解过程的影响。从测试结果可以看出:PyOptInterface与现有的优化建模语言相比具有明显的性能优势。


表1 生成模型并将其提交给 Gurobi 优化求解器的时间(秒)

Model

Variables

C++

PyOptInterface

JuMP

gurobipy

Pyomo

fac-25

67651

0.2

0.2

0.2

1.2

4.1

fac-50

520301

0.8

1.2

1.8

9.7

32.7

fac-75

1732951

2.7

4.1

6.6

32.5

119.3

fac-100

4080601

6.3

10.0

17.8

79.1

286.3

lqcp-500

251501

0.9

1.5

1.3

6.3

23.8

lqcp-1000

1003001

3.7

6.0

6.1

26.7

106.6

lqcp-1500

2254501

8.3

14.0

17.7

61.8

234.0

lqcp-2000

4006001

14.5

24.9

38.3

106.9

444.1


表2 生成模型并将其提交给COPT 优化求解器的时间(秒)

Model

Variables

C++

PyOptInterface

JuMP

coptpy

Pyomo

fac-25

67651

0.3

0.2

0.3

0.6

4.1

fac-50

520301

2.2

1.5

2.7

5.4

32.8

fac-75

1732951

8.1

6.6

10.2

20.3

117.4

fac-100

4080601

22.4

23.4

30.3

58.0

284.0

lqcp-500

251501

3.8

3.1

3.0

6.6

26.4

lqcp-1000

1003001

16.0

15.5

13.9

28.1

112.1

lqcp-1500

2254501

37.6

32.4

33.7

64.6

249.3

lqcp-2000

4006001

68.2

60.3

66.2

118.4

502.4


五、安装使用

PyOptInterface 已经在PyPI上正式发布,支持Windows、Linux和MacOS平台,支持Python 3.8-3.12的各个版本,可以通过直接 pip 安装:

 pip install pyoptinterface
 

安装完成后,可以在 Python 代码中导入该软件包:

 import pyoptinterface as poi
 


PyOptInterface无任何第三方依赖,但是如果需要将它与特定的优化求解器配合使用,需要手动安装相应的优化求解器软件。详情请参考文档地址(https://metab0t.github.io/PyOptInterface/getting_started.html)中的安装配置教程。

PyOptInterface也提供开源求解器HiGHS的打包安装方法:

 pip install pyoptinterface[highs]


此命令将同时安装HiGHS优化器的二进制版本,可以与PyOptInterface配合使用。



六、结语

PyOptInterface目前已在电力能源优化等领域试用,欢迎读者在科研等领域积极试用PyOptInterface,并通过以下方式提出宝贵的意见和建议,并引用我们的预印本论文。本开源软件的使用、修改和传播需遵守Mozilla Public License Version 2.0。


Github Issue地址:

https://github.com/metab0t/PyOptInterface/issues


论文链接:https://arxiv.org/abs/2405.10130


联系邮箱:yue.yang@hfut.edu.cn ; linchenhui@tsinghua.edu.cn



附录、入门教程

以一个简单的线性规划问题为例:


首先声明模型,其次调用model.add_variable函数添加变量,可以设置变量的上下界和名称,随后调用model.add_linear_constraint添加线性约束条件,调用model.set_objective设置目标函数,由于使用了运算符重载,线性表达式可以由变量的四则运算直接构建,最后调用model.optimize求解优化模型,并调用model.get_value查询变量的最优解取值。

如果加入整数变量的约束,则问题转化为混合整数线性规划问题,需要在调用model.add_variable的时候声明x和y是整数变量:

如果将目标函数变为二次函数,则问题转化为混合整数二次规划问题,修改目标函数即可:


最后展示一个利用PyOptInterface求解8皇后问题的示例,构建8*8的0-1变量数组,建模为混合整数线性规划问题,利用HiGHS求解器找到一个可行解,并打印最终的棋盘布置。示例中我们用Numpy的多维数组储存PyOptInterface的变量对象,表明了PyOptInterface可以与其他Python生态系统中第三方包无缝配合。

import numpy as np
import pyoptinterface as poi
from pyoptinterface import highs

model = highs.Model()

N = 8

x = np.empty((N, N), dtype=object)
for i in range(N):
for j in range(N):
        x[i, j] = model.add_variable(domain=poi.VariableDomain.Binary)

for i in range(N):
# 行列约束
    model.add_linear_constraint(poi.quicksum(x[i, :]), poi.Eq, 1.0)
    model.add_linear_constraint(poi.quicksum(x[:, i]), poi.Eq, 1.0)
for i in range(-N+1, N):
# 对角线约束
    model.add_linear_constraint(poi.quicksum(x.diagonal(i)), poi.Leq, 1.0)
model.add_linear_constraint(poi.quicksum(np.fliplr(x).diagonal(i)), poi.Leq, 1.0)

model.optimize()

get_v = np.vectorize(lambda x: model.get_value(x))
x_value = get_v(x)

print(x_value.astype(int))

相关文章

"Python可视化神作:16大案例,国界大佬私藏,源码放送!"

数据可视化是数学建模比赛中关键的一步。同学们在以数据可视化表现某些数据时可以尝试使用 Python 的第三方库。不过有些同学可能会问也会遇到不少问题,比如选择何种图表,以及如何制作,代码如何编写,这些...

Python Numpy库详细教程

1 Numpy概述1.1 概念Python本身含有列表和数组,但对于大数据来说,这些结构是有很多不足的。由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。对于数值运算来说这种 结构比较浪费...

Python离散事件仿真教程「Simpy」

离散事件仿真 (DES) 往往是专门产品的领域,例如 SIMUL8 和 MatLab/Simulink 。然而,当我在 Python 中执行过去使用 MatLab 的分析时,我很想测试 Python...

运维工程师的未来——Python

[来自IT168]【IT168 评论】互联网的应用,极大地方便了我们的生活,通过PC端,手机端等进行购物、订餐等早已不是什么稀奇事,然而在我们享受着这一便利的同时有没有想过是什么换来了我们如此的便利?...

UG编程第23节:建模练习

本节开始ug建模的简单入门练习,共9个实例(附有详细尺寸),要点对应的是涉及到的功能块和辅助功能,希望对大家有所帮助。1. 传动轴要点:①旋转②拉伸③钻孔④倒角2. 炮架要点:①拉伸②建辅助面③钻孔④...

BIMBase之python建模宝典:弧线绘制

BIMBase自从2021年发布以来获得了众多关心国产BIM和业务数字化转型的圈内老法师的关注,除了是国内首款完全自主知识产权的的BIMBase系统,实现建筑信息模型(BIM)关键核心技术自主研发安全...