计算机租赁问题 - Pyomo 中的线性优化我的解决方案在 AMPL 中运行,但 Pyomo 说它没有边界 - 可能有什么问题

问题描述

我正在尝试在 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}]}

results.json 文件输出

{
    "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 个月手头上的计算机数量吗?如果是这样,您可以使用一些列表推导式和简单条件即时制作索引。 :)