Python数学建模PuLP库线性规划进阶基于字典详解
作者:youcans 发布时间:2022-03-11 18:04:04
1、基于字典的创建规划问题
上篇中介绍了使用 LpVariable 对逐一定义每个决策变量,设定名称、类型和上下界,类似地对约束条件也需要逐一设置模型参数。在大规模的规划问题中,这样逐个定义变量和设置模型参数非常繁琐,效率很低。Pulp 库提供了一种快捷方式,可以结合 Python语言的循环和容器,使用字典来创建问题。
-(1)使用快捷方法建立一个规划问题,可以用字典类型(dict) 建立多个变量,例如:
name = [‘废料1', ‘废料2', ‘废料3', ‘废料4', ‘镍', ‘铬', ‘钼']
# A dictionary of the costs of each of the Ingredients is created
mass = pulp.LpVariable.dicts(“原料”, material, lowBound=0, cat=‘Continuous')
-(2)使用字典类型(dict) 设置目标函数和约束条件的参数,例如:
cost = {
‘废料1': 16,
‘废料2': 10,
‘废料3': 8,
‘废料4': 9,
‘镍': 48,
‘铬': 60,
‘钼': 53}
-(3)使用 遍历循环结构 设置目标函数和约束条件,例如:
AlloyModel += pulp.lpSum([cost[item] * mass[item] for item in material]), “总生产成本”
AlloyModel += pulp.lpSum([mass[item] for item in material]) == 1000, “质量约束”
2、线性规划问题案例
本篇以合金钢材生产投料问题为例,分析基于列表和字典创建问题的快捷方法。
问题描述:
某钢铁厂通过熔炼回收的金属废料并添加一定新料的方法生产满足化学成分要求的合金,计划生产1000千克的合金。
所有金属废料的主要成分是铁,不同金属废料还含有各种微量元素。
金属废料、新料的各组分含量占比、可用数量和单位成本如下表所示。生成合金中各组分的含量要求,也如表中所示。
问如何安排投料比例,在满足合金组分含量要求的条件下的材料成本最小?
材料 | 碳 | 镍 | 铬 | 钼 | 可用量 | 成本 |
---|---|---|---|---|---|---|
废料1 | 0.80 | 18.0 | 12.0 | 0.0 | 75 | 16 |
废料2 | 0.70 | 3.2 | 1.1 | 0.1 | 250 | 10 |
废料3 | 0.85 | 0 | 0 | 0 | 不限 | 8 |
废料4 | 0.40 | 0 | 0 | 0 | 不限 | 9 |
镍 | 0 | 100 | 0 | 0 | 不限 | 48 |
铬 | 0 | 0 | 100 | 0 | 不限 | 60 |
钼 | 0 | 0 | 0 | 100 | 不限 | 53 |
合金下限 | 0.65 | 3.0 | 1.0 | 1.1 | / | / |
合金上限 | 0.75 | 3.5 | 1.2 | 1.3 | / | / |
3、建立模型
(1)决策变量
x1:废料 1 用量(千克)
x2:废料 2 用量(千克)
x3:废料 3 用量(千克)
x4:废料 4 用量(千克)
x5:原料镍 用量(千克)
x6:原料铬 用量(千克)
x7:原料钼 用量(千克)
(2)目标函数
min cost = 16*x1 + 10*x2 + 8*x3 + 9*x4 + 48*x5 + 60*x6 + 53*x7
(3)约束条件
0.8*x1 + 0.7*x2 + 0.85*x3 + 0.40*x4 >= 0.65*1000
0.8*x1 + 0.7*x2 + 0.85*x3 + 0.40*x4 <= 0.75*1000
18.0*x1 + 3.2*x2 + 100.0*x5 >= 3.0*1000
18.0*x1 + 3.2*x2 + 100.0*x5 <= 3.5*1000
12.0*x1 + 1.1*x2 + 100.0*x6 >= 1.0*1000
12.0*x1 + 1.1*x2 + 100.0*x6 >= 1.2*1000
0.1*x2 + 100.0*x7 >= 1.1*1000
0.1*x2 + 100.0*x7 >= 1.3*1000
(4)变量取值范围
xi >= 0, i=1,2,…7
x1 <= 75, x2 <= 250
4、PuLP 程序1:使用 LpVariable 逐一定义变量
本程序与上篇的方法相同,使用 LpVariable 逐一定义变量。完整的程序代码如下:
import pulp # 导入 pulp库
# 1.建立优化问题 AlloyLP: 求最小值(LpMinimize)
AlloyLP = pulp.LpProblem("合金生产材料优化", sense=pulp.LpMinimize) # 定义问题,求最小值
# 2.定义决策变量 x1~x7
x1 = pulp.LpVariable('废料1#', lowBound=0, upBound=75.0, cat='Continuous') # 定义 x1
x2 = pulp.LpVariable('废料2#', lowBound=0, upBound=250., cat='Continuous') # 定义 x2
x3 = pulp.LpVariable('废料3#', lowBound=0, cat='Continuous') # 定义 x3
x4 = pulp.LpVariable('废料4#', lowBound=0, cat='Continuous') # 定义 x4
x5 = pulp.LpVariable('原料镍', lowBound=0, cat='Continuous') # 定义 x5
x6 = pulp.LpVariable('原料铬', lowBound=0, cat='Continuous') # 定义 x6
x7 = pulp.LpVariable('原料钼', lowBound=0, cat='Continuous') # 定义 x7
# 3.定义目标函数 cost
AlloyLP += (16*x1 + 10*x2 + 8*x3 + 9*x4 + 48*x5 + 60*x6 + 53*x7) # 投料成本
# 4.设置约束条件
AlloyLP += (x1 + x2 + x3 + x4 + x5 + x6 + x7 == 1000) # 等式约束
AlloyLP += (0.8*x1 + 0.7*x2 + 0.85*x3 + 0.4*x4 >= 0.65*1000) # 不等式约束
AlloyLP += (0.8*x1 + 0.7*x2 + 0.85*x3 + 0.4*x4 <= 0.75*1000) # 不等式约束
AlloyLP += (18.0*x1 + 3.2*x2 + 100.0*x5 >= 3.0*1000) # 不等式约束
AlloyLP += (18.0*x1 + 3.2*x2 + 100.0*x5 <= 3.5*1000) # 不等式约束
AlloyLP += (12.0*x1 + 1.1*x2 + 100.0*x6 >= 1.0*1000) # 不等式约束
AlloyLP += (12.0*x1 + 1.1*x2 + 100.0*x6 <= 1.2*1000) # 不等式约束
AlloyLP += (0.1*x2 + 100.0*x7 >= 1.1*1000) # 不等式约束
AlloyLP += (0.1*x2 + 100.0*x7 <= 1.3*1000) # 不等式约束
AlloyLP += (x1 + x2 + x3 + x4 + x5 + x6 + x7 == 1000) # 等式约束
# 5.求解线性规划问题
AlloyLP.solve()
# 6.输出优化结果
print(AlloyLP) # 输出问题设定参数和条件
# print("求解状态:", pulp.LpStatus[AlloyLP.status]) # 输出求解状态
for v in AlloyLP.variables():
print(v.name, " = ", v.varValue) # 输出每个变量的最优值
print("最小材料成本 = ", pulp.value(AlloyLP.objective)) # 输出最优解的目标函数值
# = 关注 Youcans,分享原创系列 https://blog.csdn.net/youcans =
5、PuLP 程序2:使用 dict 定义决策变量和约束条件
本程序使用 dict 定义变量、目标函数和约束条件参数,便于复杂问题的参数设定。
import pulp # 导入 pulp库
# 1.建立优化问题 AlloyLP: 求最小值(LpMinimize)
AlloyLP = pulp.LpProblem("合金生产材料优化", sense=pulp.LpMinimize) # 定义问题,求最小值
# 2.定义决策变量 x1~x7
x1 = pulp.LpVariable('废料1#', lowBound=0, upBound=75.0, cat='Continuous') # 定义 x1
x2 = pulp.LpVariable('废料2#', lowBound=0, upBound=250., cat='Continuous') # 定义 x2
x3 = pulp.LpVariable('废料3#', lowBound=0, cat='Continuous') # 定义 x3
x4 = pulp.LpVariable('废料4#', lowBound=0, cat='Continuous') # 定义 x4
x5 = pulp.LpVariable('原料镍', lowBound=0, cat='Continuous') # 定义 x5
x6 = pulp.LpVariable('原料铬', lowBound=0, cat='Continuous') # 定义 x6
x7 = pulp.LpVariable('原料钼', lowBound=0, cat='Continuous') # 定义 x7
# 3.定义目标函数 cost
AlloyLP += (16*x1 + 10*x2 + 8*x3 + 9*x4 + 48*x5 + 60*x6 + 53*x7) # 投料成本
# 4.设置约束条件
AlloyLP += (x1 + x2 + x3 + x4 + x5 + x6 + x7 == 1000) # 等式约束
AlloyLP += (0.8*x1 + 0.7*x2 + 0.85*x3 + 0.4*x4 >= 0.65*1000) # 不等式约束
AlloyLP += (0.8*x1 + 0.7*x2 + 0.85*x3 + 0.4*x4 <= 0.75*1000) # 不等式约束
AlloyLP += (18.0*x1 + 3.2*x2 + 100.0*x5 >= 3.0*1000) # 不等式约束
AlloyLP += (18.0*x1 + 3.2*x2 + 100.0*x5 <= 3.5*1000) # 不等式约束
AlloyLP += (12.0*x1 + 1.1*x2 + 100.0*x6 >= 1.0*1000) # 不等式约束
AlloyLP += (12.0*x1 + 1.1*x2 + 100.0*x6 <= 1.2*1000) # 不等式约束
AlloyLP += (0.1*x2 + 100.0*x7 >= 1.1*1000) # 不等式约束
AlloyLP += (0.1*x2 + 100.0*x7 <= 1.3*1000) # 不等式约束
AlloyLP += (x1 + x2 + x3 + x4 + x5 + x6 + x7 == 1000) # 等式约束
# 5.求解线性规划问题
AlloyLP.solve()
# 6.输出优化结果
print(AlloyLP) # 输出问题设定参数和条件
# print("求解状态:", pulp.LpStatus[AlloyLP.status]) # 输出求解状态
for v in AlloyLP.variables():
print(v.name, " = ", v.varValue) # 输出每个变量的最优值
print("最小材料成本 = ", pulp.value(AlloyLP.objective)) # 输出最优解的目标函数值
# = 关注 Youcans,分享原创系列 https://blog.csdn.net/youcans =
6、Python程序和运行结果
程序 1 和程序 2 的运行结果完全相同,结果如下:
Welcome to the CBC MILP Solver
Version: 2.9.0
Build Date: Feb 12 2015
钢材生产问题:
MINIMIZE
16*原料_废料1 + 10*原料_废料2 + 8*原料_废料3 + 9*原料_废料4 + 53*原料_钼 + 60*原料_铬 + 48*原料_镍 + 0
SUBJECT TO
质量约束: 原料_废料1 + 原料_废料2 + 原料_废料3 + 原料_废料4 + 原料_钼 + 原料_铬 + 原料_镍 = 1000
碳最小占比: 0.8 原料_废料1 + 0.7 原料_废料2 + 0.85 原料_废料3 + 0.4 原料_废料4 >= 650
碳最大占比: 0.8 原料_废料1 + 0.7 原料_废料2 + 0.85 原料_废料3 + 0.4 原料_废料4 <= 750
镍最小占比: 18 原料_废料1 + 3.2 原料_废料2 + 100 原料_镍 >= 3000
镍最大占比: 18 原料_废料1 + 3.2 原料_废料2 + 100 原料_镍 <= 3500
铬最小占比: 12 原料_废料1 + 1.1 原料_废料2 + 100 原料_铬 >= 1000
铬最大占比: 12 原料_废料1 + 1.1 原料_废料2 + 100 原料_铬 <= 1200
钼最小占比: 0.1 原料_废料2 + 100 原料_钼 >= 1100
钼最大占比: 0.1 原料_废料2 + 100 原料_钼 <= 1300
废料1可用量: 原料_废料1 <= 75
废料2可用量: 原料_废料2 <= 250
VARIABLES
原料_废料1 Continuous
原料_废料2 Continuous
原料_废料3 Continuous
原料_废料4 Continuous
原料_钼 Continuous
原料_铬 Continuous
原料_镍 Continuous
优化状态: Optimal
原料_废料1 = 75.0
原料_废料2 = 90.909091
原料_废料3 = 672.28283
原料_废料4 = 137.30808
原料_钼 = 10.909091
原料_铬 = 0.0
原料_镍 = 13.590909
最优总成本 = 9953.671725000002
来源:https://blog.csdn.net/youcans/article/details/116370914
猜你喜欢
- 可控制的滚动新闻不同于自动的滚动条,它是通过按钮控制移动的,当你把鼠标放在按钮上时,新闻内容就会向上或
- 我们的每期话题,团队在内部都会通过邮件进行一番讨论,随着讨论的激烈,往往能碰撞出很多有意义的观点,因此,将讨论内容分享出来,有兴趣的朋友可以
- 如果你是一名Web Developer,而且还知道CSS Sprite这个词,请先去搜索一下,也许你正在使用这个技术,但只是不知道它的名字罢
- 关于mysql数据库在Linux下的应用一直以来都是我认为比较棘手的,这次通过搭建Linux学习环境顺便研究和学习Mysql数据库在Linu
- 当我们想复制两个一模一样的列表时,我们可能使用到list.copy()这个方法,这个方法可以让我们复制一个相同的数组,当遇到下面这种情况时,
- 由于特定需求,最近实验室需要远程连接外地的sql server 2000服务器,最开始怎么连也连不上,出现了很多问题,但是在今天上午,借用实
- JSP 获取spring容器中bean的方法总结方案1(Web中使用):ApplicationContext ct = WebApplica
- 注意:安装时要保证Oracle安装目录不能带有中文字符(如果第一次安装出现“加载数据库错误areasQueries”的错误,一般是因为Ora
- asp之日期和时间函数示例可以使用日期和时间函数来得到各种格式的日期和时间函数语法说明示例NowNow()取得系统当前的日期和
- 如下所示:function makeAcquire($nUsers,$nAwards) { &
- 如下所示:var myarr=new Array(); //先声明一维 for(var i=0;i<2;i++){ //一
- 1、使用mysqli扩展库 预处理技术 mysqli stmt 向数据库添加3个用户<?php /
- 本文实例讲述了python使用socket向客户端发送数据的方法。分享给大家供大家参考。具体如下:import socket, syspor
- 大家知道,在js里encodeURIComponent 方法是一个比较常用的编码方法,但因工作需要,在asp里需用到此方法,查了好多资料,没
- 学习目的 掌握如何用ADO.NET插入新的记录 我们学得好快,今天做一个简易的新闻发布网页,可以说是个演示型的,只是让大家能理插入数据的最主
- 如何做一个分页程序? 这在ASP中确实容易实现,但需要技巧,看看下面的分页代码和说明: <angu
- 实际参数在函数中我们可以使用 arguments 对象获得 (注:形参可通过 arguments.callee 获得),虽然 argumen
- 1.首先主题选择不要落俗!现在许多的个人主页就象“大锅饭”。题材包罗万象,内容雷同无味。人人都是“软件速递”“音乐宝库”“主页教程”等等。让
- 我需要查询从现在算起五天前的日期。按照商业习惯,这五天应该不包含星期六和星期天。专家回答:对于许多跟商业日期有关的情况,最好的解决方案是使用
- 字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,