优化 Pyomo Python - 'SumExpression is not iterable'

Optimization Pyomo Python - 'SumExpression is not iterable'

我是 Python 的新手,我似乎无法解决我遇到的问题,即使在经历了论坛上发布的类似问题之后也是如此。

我的问题是我的 objective 函数出现 ''SumExpression' object is not iterable' 错误。

我的代码:

import pyomo.environ as pyo
from pyomo.opt import SolverFactory

model=pyo.ConcreteModel()

#C = contract capacity
D =  [5048,5144,4616,4296,3696,3392,5048,5144,4616,4296,3696,3392]
R = [166.9,166.9,166.9,166.9,166.9,166.9,166.9,166.9,223.6,223.6,223.6,223.6]
PF=[0.027 for i in range (12)]
E=[1319.25,1319.25,1319.25,1319.25,1319.25,1319.25,1319.25,1319.25,1759,1759,1759,1759]

model.M=pyo.RangeSet(0,11)

model.X = pyo.Var(model.M, domain=pyo.NonNegativeReals)
model.C = pyo.Var(model.M, domain=pyo.NonNegativeReals)
model.Y = pyo.Var(model.M, domain=pyo.NonNegativeReals)


def constraint_1(model,M):
    return model.X[M]+model.C[M] >= D[M]
model.constraint_1 = pyo.Constraint(model.M, rule=constraint_1)

def constraint_2(model,M):
    return model.Y[M]+1.1*model.C[M] >= D[M]
model.constraint_2 = pyo.Constraint(model.M, rule=constraint_2)

def constraint_3(model,M):
    if M == 11:
        return model.C[0] >= model.C[M]
    else:
        return model.C[M+1] >= model.C[M]
model.constraint_3 = pyo.Constraint(model.M, rule=constraint_3)

def mod_obj(model,M):
    if M==11:
        return sum((1-PF[M])*R[M]*model.C[M]+2*R[M]*model.X[M]+R[M]*model.Y[M]+E[M]*(model.C[0]-model.C[M]))
    else:
        return sum((1-PF[M])*R[M]*model.C[M]+2*R[M]*model.X[M]+R[M]*model.Y[M]+E[M]*(model.C[M+1]-model.C[M]))

model.mod_obj = pyo.Constraint(model.M, rule=mod_obj)
model.obj=pyo.Objective(rule=mod_obj, sense=pyo.minimize)
opt = SolverFactory('glpk')
opt.solve(model)

model.pprint()

我得到的错误来自 objective 函数的第二行:

return sum((1-PF[M])*R[M]*model.C[M]+2*R[M]*model.X[M]+R[M]*model.Y[M]+E[M]*(model.C[M+1]-model.C[M]))

我认为它必须与 M+1 做一些事情,因为第一行没有给出错误但我似乎无法解决这个错误并感谢您的 help/input.

提前致谢!

你有一些事情挂在这里...

首先,当你使用 sum() 表达式时,里面的东西需要是可迭代的。您只是为 M 传递了一个固定值。示例:

In [32]: A = [5,6,7]                                                            

In [33]: sum(A[0] + A[1])                                                       
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-33-143c09ad32d9> in <module>
----> 1 sum(A[0] + A[1])

TypeError: 'int' object is not iterable

In [34]: sum(A[idx] for idx in range(3))                                        
Out[34]: 18

因此您需要将 sum() 函数设置为具有该类型的结构,这导致第二件事挂起您,为 model.C 构建正确的索引,出现环绕。您可以使用模数以数学方式构建您正在寻找的“环绕”。考虑:

In [39]: import pyomo.environ as pyo                                            

In [40]: M = pyo.RangeSet(0,11) # 0->11 inclusive                               

In [41]: M_prime = [(t+1)%12 for t in M]                                        

In [42]: M_prime                                                                
Out[42]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0]

所以我们可以将它们拼接成一个表达式,而不是在您的模型中传入索引 M,这对于 objective 函数来说是不正确的结构,因为传入 M 会在你的模型中生成 M 个表达式,对吗?所以,我认为您正在寻找这样的东西:

def mod_obj(model):
    return sum((1-PF[m])*R[m]*model.C[m]+2*R[m]*model.X[m]+R[m]*model.Y[m]+E[m]*(model.C[(m+1)%12]-model.C[m]) for m in model.M)

#model.mod_obj = pyo.Constraint(model.M, rule=mod_obj)
model.obj=pyo.Objective(rule=mod_obj, sense=pyo.minimize)

另请注意:您正在通过使用大写 M 代表集合 model.M 的成员来为 confusion/disaster 做好准备。我觉得用小写字母来表示集合成员更清晰,读起来更清楚。