采用Python+Gurobi实现运输问题建模求解【基础语法】
目录
1. Gurobi介绍
Gurobi是由美国 Gurobi Optimization 公司开发新一代大规模优化器。无论在生产制造领域,还是在金融、保险、交通、服务等其他各种领域,当实际问题越来越复杂,问题规模越来越庞大的时候,我们需要一个经过证明可以信赖的大规模优化工具,为我们的决策提供质量保证,为我们增强信心。在理论和实践中,Gurobi 优化工具都被证明是全球性能领先的大规模优化器,具有突出的性价比,可以为客户在开发和实施中极大降低成本。
Gurobi 是全局优化器,支持的模型类型包括:
- 连续和混合整数线性问题
- 凸目标或约束连续和混合整数二次问题
- 非凸目标或约束连续和混合整数二次问题
- 含有对数、指数、三角函数、高阶多项式目标或约束,以及任何形式的分段约束的非线性问题
- 含有绝对值、最大值、最小值、逻辑与或非目标或约束的非线性问题
以上介绍来源于:来源:gurobi中国官网
Gurobi提供多种API接口,其中就包括Python语言,而且其语法和python非常接近,对python的语言要求并不高。擅长python的小伙伴也可以在运筹优化领域寻求一席之地,重要的是:可以免费申请学术版!
2. 安装
可以登录官网注册账号(建议使用学校邮箱),按照官网引导安装即可,在申请学术版时如遇到在线校园网认证失败请采用线下认证方式。
这里采用的编程环境为:anaconda(3.6 python)+ Gurobi+pycharm
3.基础语法
这里对Gurobi的数据结构做简要介绍,详细内容可以查阅官方文档。
3.1 语法对比
list、tuple、dict是python中常用的数据结构,在 Gurobi中同样支持,而且 Gurobi还对其进行了扩展优化,以便提高效率,具体如下:
数据结构 | gurobi语法扩展 | gurobi建模用途 |
---|---|---|
list | tuplelist | 下标、索引、变量、约束等各种对象的集合 |
tuple | - | 适合多维下标 |
dict | tupledict | 表示带下标的数值,如变量 |
- | multidict | 快速创建tuplelist和tupledict |
sum | quicksum | 求和 |
在使用gurobi之前需要将其导入:
from gurobi import *
3.2 基本用法:list和tuplelist
"创建list和tuplelist"
cities_py=[('A','B'),('A','D'),('B','D'),('D','E')]
cities_gurobi=tuplelist(cities_py)
'tuplelist除了具备list增、删、改、查等方法外,还增加了快速筛选select方法'
"筛选符合条件的元素"
for i,j in cities_py:
if i=='A':
print((i,j))
print(cities_gurobi.select('A','*'))
3.3 基本用法:dict和tupledict
"创建dict和tupledict"
link_cost_py={('1','2'):10,('1','3'):12,('2','3'):4,('3','4'):10}
link_cost_gurobi=tupledict(link_cost_py)
'tupledict也增加了select、sum、prod等方法,提高建模效率(后续建模时介绍)'
3.4 基本语法:创建tuplelist和tupledict
'multidict提供了同时创建tuplelist和tupledict的方法,可减少参数输入工作量,提高了建模速度,'
link_list,cost=multidict(
{('1','2'):10,('1','3'):12,('2','3'):4,('3','4'):10}
)
print('link list :%s'%link_list)
print('link cost :%s'%cost)
link_list,cost,time=multidict(
{('1', '2'): [10,4], ('1', '3'): [12,2], ('2', '3'): [4,8], ('3', '4'): [10,8]}
)
print('link list :%s'%link_list)
print('link cost :%s'%cost)
print('link time :%s'%time)
3.5 基本用法:sum和quicksum
sum_py=sum(v for v in link_cost_py.values())
sum_gurobi=quicksum(link_cost_gurobi[i] for i in link_list)
sum_gurobi_=quicksum( cost[i]*time[i] for i in link_list)
sum_gurobi__=cost.prod(time)
3.6 实际问题建模过程
- problem instance(待优化问题)
- model generator(将数据组成成模型,产生模型对象)
- model instance(存在于内存的一个完整数学模型)
- gurobi optimizer(优化求解)
- solution retrieval(读取求解结果)
- analysis(结果分析)
3.7 Gurobi模型构建过程
- 实例化模型 :m=Model( )
- 添加变量 : m.addVar( ),m.addVars( )
- 设定目标函数 :m.setObjective( ) ,m.setObjectiveN()
- 添加约束 :m.addConstr(),m.addConstrs( )
- 求解 :m.optimizer( )
- 结果分析 :m.getvars( )
3.8 建模举例
(1)待优化问题
m
a
x
x
+
y
+
2
z
max \space x+y+2z
max x+y+2z
s.t.
x
+
2
y
+
3
z
<
=
4
x+2y+3z<= 4
x+2y+3z<=4
x
+
y
>
=
1
x+y>=1
x+y>=1
x
,
y
,
z
∈
0
,
1
x,y,z \in {0,1}
x,y,z∈0,1
(2)Gurobi建模
'创建模型'
m=Model()
'添加变量'
x=m.addVar(vtype=GRB.BINARY,name='X')
y=m.addVar(vtype=GRB.BINARY,name='Y')
z=m.addVar(vtype=GRB.BINARY,name='Z')
'设置目标函数'
m.setObjective(x+y+2*z,GRB.MAXIMIZE)
'添加约束'
m.addConstr(x+2*y+3*z<=4)
m.addConstr(x+y>=1)
'优化求解'
m.optimize()
'读取结果'
for v in m.getVars():
print(v.varName,v.x)
参数解释
- addVar( ):
*添加单个变量
*vtype:变量类型(连续、整数、0-1等)
*name:变量名称(可选) - setObjective( ):
*设置单一目标函数
* x + y + 2 z x+y+2z x+y+2z为目标函数
*GRB.MAXIMIZE指定优化方向为最大化 - addConstr( )
*添加单个约束条件(这里采用简单、直观的书写方式) - optimize()
*优化求解 - getVars()
*获取模型所有变量
*varName:获取变量名
*v.x:获取变量的值
参考
- http://www.gurobi.cn/picexhview.asp?id=100
- https://blog.csdn.net/qq_45832050/article/details/109920683