问题描述
我正在尝试在 Pyomo 中模拟一个简单的线性问题。我在 AMPL 中完成了建模并得到了正确的答案,但出于某种奇怪的原因,Pyomo 说它没有界限。
如果有人能够善意地观察我所做的事情,看看为什么它在 pyomo 中不起作用。所有数据和代码如下。
这是最初的问题: BCoE 已确定在接下来的 12 个月中的每一个月内,它将需要下表中给出的笔记本电脑数量。为满足这些要求,BCoE 将笔记本电脑租用一、二或三个月的时间。租用笔记本电脑一个月的费用为 100 美元,两个月为 180 美元,三个月为 250 美元。第 1 月初,BCOE 拥有 70 台笔记本电脑。确定以最低成本满足未来 12 个月要求的租赁计划。为这个问题编写一个数学程序,并使用您选择的求解器来求解。
月 | 笔记本电脑要求 |
---|---|
1 | 700 |
2 | 1100 |
3 | 500 |
4 | 600 |
5 | 1100 |
6 | 500 |
7 | 700 |
8 | 700 |
9 | 300 |
10 | 600 |
11 | 700 |
12 | 700 |
这是我在 PYOMO 中编写的代码:
# IMPORT THE NECESSARY CLASSES
from pyomo.environ import *
infinity = float('inf')
# CREATE THE MODEL
model=ConcreteModel()
# GENERAL VARIABLES:
borrowPeriod = [1,2,3] # Number of Months you can Borrow The laptops
Months = [1,3,4,5,6,7,8,9,10,11,12] # Ind
demandPerMonth = [700,1100,500,600,700,300,700]
# Variables Month1 - Month12 are meant to just kNow which Indices to use for each Month when I code the constraints
Month1 = []
for i in range(1,2):
for j in borrowPeriod:
tmp = i,j
Month1.append(tmp)
Month2 = []
for i in range(1,3):
for j in borrowPeriod:
tmp = i,j
Month2.append(tmp)
Month2 = Month2[-5:]
Month3 = []
for i in range(1,4):
for j in borrowPeriod:
tmp = i,j
Month3.append(tmp)
Month3 = Month3[-5:]
Month3.append(Month1[-1])
Month4 = []
for i in range(1,5):
for j in borrowPeriod:
tmp = i,j
Month4.append(tmp)
Month4 = Month4[-5:]
Month4.append(Month2[-1])
Month5 = []
for i in range(1,6):
for j in borrowPeriod:
tmp = i,j
Month5.append(tmp)
Month5 = Month5[-5:]
Month5.append(Month3[-2])
Month6 = []
for i in range(1,7):
for j in borrowPeriod:
tmp = i,j
Month6.append(tmp)
Month6 = Month6[-5:]
Month6.append(Month4[-2])
Month7 = []
for i in range(1,8):
for j in borrowPeriod:
tmp = i,j
Month7.append(tmp)
Month7 = Month7[-5:]
Month7.append(Month5[-2])
Month8 = []
for i in range(1,9):
for j in borrowPeriod:
tmp = i,j
Month8.append(tmp)
Month8 = Month8[-5:]
Month8.append(Month6[-2])
Month9 = []
for i in range(1,10):
for j in borrowPeriod:
tmp = i,j
Month9.append(tmp)
Month9 = Month9[-5:]
Month9.append(Month7[-2])
Month10 = []
for i in range(1,11):
for j in borrowPeriod:
tmp = i,j
Month10.append(tmp)
Month10 = Month10[-5:]
Month10.append(Month8[-2])
Month11 = []
for i in range(1,12):
for j in borrowPeriod:
tmp = i,j
Month11.append(tmp)
Month11 = Month11[-5:]
Month11.append(Month9[-2])
Month12 = []
for i in range(1,13):
for j in borrowPeriod:
tmp = i,j
Month12.append(tmp)
Month12 = Month12[-5:]
Month12.append(Month10[-2])
# FULLDATA is meant to hold all actual variables I would be manipulating in the constraints and Objective Function.
fullData = []
for i in Months:
for j in borrowPeriod:
tmp = i,j
fullData.append(tmp)
fullData
model.full = Var(fullData,initialize=0)
# THE OBJECTIVE FUNCTION:
model.value = Objective(expr = 100*sum(model.full[x] for _,x in enumerate(fullData) if x[1] == 1) + 180*sum(model.full[x] for _,x in enumerate(fullData) if x[1] == 2) + 250*sum(model.full[x] for _,x in enumerate(fullData) if x[1] == 3),sense=minimize)
# THE CONSTRAINTS - These Contraints are as per the question
model.month1 = Constraint(expr = 70 + sum(model.full[x] for _,x in enumerate(Month1)) >= 700)
model.month2 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month2)) >= 1100)
model.month3 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month3)) >= 500)
model.month4 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month4)) >= 600)
model.month5 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month5)) >= 1100)
model.month6 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month6)) >= 500)
model.month7 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month7)) >= 700)
model.month8 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month8)) >= 700)
model.month9 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month9)) >= 300)
model.month10 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month10)) >= 600)
model.month11 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month11)) >= 700)
model.month12 = Constraint(expr = sum(model.full[x] for _,x in enumerate(Month12)) >= 700)
这是我得到的结果
[ 0.00] Setting up Pyomo environment
[ 0.00] Applying Pyomo preprocessing actions
[ 0.01] Creating model
[ 0.01] Applying solver
[ 0.05] Processing results
Number of solutions: 0
Solver results file: results.json
[ 0.05] Applying Pyomo postprocessing actions
[ 0.05] Pyomo Finished
errorcode: 0
retval: instance: <pyomo.core.base.PyomoModel.ConcreteModel object at 0x0000020CD402C9F8>
local:
time_initial_import: 0.0059854984283447266
usermodel: <module 'HW5' from 'C:\\Users\\aizuw\\Documents\\Schools\\UTK -\\Classes\\Second Semester\\IE 522\\Assignments\\HW 5\\HW5.py'>
options: <pyomo.common.config.ConfigDict object at 0x0000020CD3F59688>
results: {'Problem': [{'Name': 'unkNown','Lower bound': -inf,'Upper bound': inf,'Number of objectives': 1,'Number of constraints': 13,'Number of variables': 37,'Number of nonzeros': 69,'Sense': 'minimize'}],'Solver': [{'Status': 'ok','Termination condition': 'unbounded','Statistics': {'Branch and bound': {'Number of bounded subproblems': 0,'Number of created subproblems': 0}},'Error rc': 0,'Time': 0.021906614303588867}]}
{
"Problem": [
{
"Lower bound": -Infinity,"Name": "unkNown","Number of constraints": 13,"Number of nonzeros": 69,"Number of objectives": 1,"Number of variables": 37,"Sense": "minimize","Upper bound": Infinity
}
],"Solver": [
{
"Error rc": 0,"Statistics": {
"Branch and bound": {
"Number of bounded subproblems": 0,"Number of created subproblems": 0
}
},"Status": "ok","Termination condition": "unbounded","Time": 0.021906614303588867
}
]
}
解决方法
该问题在构造时是无界的,因为您没有约束变量的域,因此允许它变为负值,并且求解器正在发疯,因为它也试图对“负购买”进行建模。这解决了问题。 (注意:您也不必初始化变量):
model.full = Var(fullData,domain=NonNegativeReals)
此外,如果您对此有所研究,则可以稍微加强模型构建。您应该能够处理约束的 RHS 值列表,并使用循环将它们全部生成,而不是单独写出它们。与您创建月度指数相同。你能想出一个数学表达式来表示第 n 个月手头上的计算机数量吗?如果是这样,您可以使用一些列表推导式和简单条件即时制作索引。 :)