You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyomo约束定义中按索引访问参数触发TypeError报错

问题

在练习Pyomo时,按照文档定义了带索引的Param对象,但在约束中按索引访问参数时触发错误。根据文档说明,Param对象的行为与Var对象类似,预期可以像访问Var值一样在约束中访问Param值,但实际出现问题。尝试了用ConstraintList和规则两种方式定义约束,均未解决问题。

原代码:

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

#Model
model = pyo.ConcreteModel()

#Set
model.index_1 = pyo.RangeSet(1,2)
model.index_2 = pyo.RangeSet(0,2)

#Variables
model.pg = pyo.Var(model.index_1)
model.pg[1].setlb(0)
model.pg[2].setlb(0)
model.pg[1].setub(20)
model.pg[2].setub(30)
model.c = pyo.Var(model.index_1, bounds=(0, None))
model.m = pyo.Var(model.index_2, bounds=(-15, 15))
model.b = pyo.Var(model.index_2, bounds=(None, None))

#Parameters
model.Cg = model.Param(model.index_1, initialize={1: 0.2, 2: 0.5})
model.Pl = model.Param(model.index_2, initialize={0: 15, 1: 15, 2: 15})
model.Pd = model.Param(initialize=25)

#Objective
model.obj = pyo.Objective(expr = pyo.summation(model.c), sense=pyo.minimize)

#Constraints
model.C1 = pyo.ConstraintList()
for i in model.index_1:
    model.C1.add(expr = model.pg[i] * model.Cg[i] == model.c[i])
model.C2 = pyo.ConstraintList()
model.C2.add(expr = model.b[0] == model.m[0]*model.Pl[0] + model.m[1]*model.Pl[1])
model.C2.add(expr = model.b[1] == model.m[0]*model.Pl[0] + model.m[2]*model.Pl[2])
model.C2.add(expr = model.b[2] == model.m[1]*model.Pl[1] + model.m[2]*model.Pl[2])
model.C3 = pyo.Constraint(expr = model.b[2] == model.Pd)
model.C4 = pyo.ConstraintList()
model.C4.add(expr = model.b[0] >= -model.Pg[1])
model.C4.add(expr = model.b[1] >= -model.Pg[2])

opt = SolverFactory('glpk')
opt.solve(model)

print('--------------------------------------------------------------------')
for i in model.index_1:
    print(f"pg[{i}]: {pyo.value(model.pg[i])}")
for i in model.index_1:
    print(f"c[{i}]: {pyo.value(model.c[i])}")
for j in model.index_2:
    print(f"m[{j}]: {pyo.value(model.m[j])}")
for j in model.index_2:
    print(f"b[{j}]: {pyo.value(model.b[j])}")

print("Total cost: ", pyo.summation(model.c))

报错信息:

Traceback (most recent call last):
  File "exercice9.py", line 26, in <module>
    model.C1.add(expr = model.pg[i] * model.Cg[i] == model.c[i])
                                      ~~~~~~~~^^^
TypeError: '_generic_component_decorator' object is not subscriptable

尝试用规则定义约束,问题依旧:

def rule_1(model, i):
    return model.pg[i] * model.Cg[i] == model.c[i]
model.C1 = pyo.Constraint(model.index_1, rule=rule_1)

错误原因与解决方法

核心错误:Param对象创建方式错误

创建Param组件时,误用了model.Param,正确的方式应该是使用pyo.Param。model.Param是Pyomo中的组件装饰器,用于标记方法来动态生成参数,并非直接创建Param实例的构造函数。用它创建的model.Cg、model.Pl、model.Pd都是装饰器对象,不支持下标访问,因此触发TypeError。

次要错误:变量名大小写错误

约束C4中引用了model.Pg,但实际定义的变量是小写的model.pg,Pyomo对变量名大小写敏感,这会导致后续运行时出现变量未定义的错误。

修正后的完整代码

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

# Model
model = pyo.ConcreteModel()

# Set
model.index_1 = pyo.RangeSet(1,2)
model.index_2 = pyo.RangeSet(0,2)

# Variables
model.pg = pyo.Var(model.index_1)
model.pg[1].setlb(0)
model.pg[2].setlb(0)
model.pg[1].setub(20)
model.pg[2].setub(30)
model.c = pyo.Var(model.index_1, bounds=(0, None))
model.m = pyo.Var(model.index_2, bounds=(-15, 15))
model.b = pyo.Var(model.index_2, bounds=(None, None))

# Parameters - 修正:使用pyo.Param而非model.Param
model.Cg = pyo.Param(model.index_1, initialize={1: 0.2, 2: 0.5})
model.Pl = pyo.Param(model.index_2, initialize={0: 15, 1: 15, 2: 15})
model.Pd = pyo.Param(initialize=25)

# Objective
model.obj = pyo.Objective(expr = pyo.summation(model.c), sense=pyo.minimize)

# Constraints
model.C1 = pyo.ConstraintList()
for i in model.index_1:
    model.C1.add(expr = model.pg[i] * model.Cg[i] == model.c[i])
model.C2 = pyo.ConstraintList()
model.C2.add(expr = model.b[0] == model.m[0]*model.Pl[0] + model.m[1]*model.Pl[1])
model.C2.add(expr = model.b[1] == model.m[0]*model.Pl[0] + model.m[2]*model.Pl[2])
model.C2.add(expr = model.b[2] == model.m[1]*model.Pl[1] + model.m[2]*model.Pl[2])
model.C3 = pyo.Constraint(expr = model.b[2] == model.Pd)
model.C4 = pyo.ConstraintList()
# 修正:将model.Pg改为model.pg
model.C4.add(expr = model.b[0] >= -model.pg[1])
model.C4.add(expr = model.b[1] >= -model.pg[2])

opt = SolverFactory('glpk')
opt.solve(model)

print('--------------------------------------------------------------------')
for i in model.index_1:
    print(f"pg[{i}]: {pyo.value(model.pg[i])}")
for i in model.index_1:
    print(f"c[{i}]: {pyo.value(model.c[i])}")
for j in model.index_2:
    print(f"m[{j}]: {pyo.value(model.m[j])}")
for j in model.index_2:
    print(f"b[{j}]: {pyo.value(model.b[j])}")

print("Total cost: ", pyo.value(pyo.summation(model.c)))

补充说明

  • 修正Param的创建方式后,model.Cg[i]即可正常访问参数值,无论使用ConstraintList还是规则方式定义约束都能正常工作。
  • 最后输出总成本时,建议用pyo.value(pyo.summation(model.c))来获取具体数值,否则会输出表达式对象而非计算结果。

内容的提问来源于stack exchange,提问作者Korpi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:54:58