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
相关产品推荐
相关产品推荐

