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

Pyomo报错:无法对非集合ConcreteModel组件应用集合运算符

Pyomo优化模型TypeError问题解决

问题重现

以下是报错的Pyomo模型代码:

# model definition
model = ConcreteModel()

# Sets and indices
model.O = RangeSet(len(data))  # Set of representative operating conditions
model.D = RangeSet(len(data)) # Demand profile for the operating conditions
model.G = RangeSet(1)   # set of existing generators
model.C = RangeSet(1)   # set of candidate generators

# Parameters
model.Cg= Param(initialize=35, within=NonNegativeReals, mutable=True) # Opex of existing generators
model.Cc= Param(initialize=25, within=NonNegativeReals, mutable=True) # Opex of candidate generators
model.Ic= Param(initialize=70000, within=NonNegativeReals, mutable=True) # Annualized investment cost

# Decision Variables
model.pg = Var(model.O, model.G, bounds=(0, 400), initialize=0, within=NonNegativeReals)
model.pc = Var(model.O, model.C, bounds=(0, 500), initialize=0, within=NonNegativeReals)
model.pc_max = Var(model.C, bounds=(0, 500), initialize=0, within=NonNegativeIntegers)

# Objective function
def objective_rule(model, O):
    return sum(data.loc[O-1, 'w']*(sum(model.Cg*model.pg[O,G] for G in model.G))+\
               data.loc[O-1, 'w']*(sum(model.Cc*model.pc[O,C] for C in model.C)) for O in model.O)+\
                sum(model.Ic*model.pc_max[C] for C in model.C)

model.objective = Objective(model, rule=objective_rule, sense=minimize)

# Constraints
# 1. sign restrictions already provided for in the definition of decision variables
def con1_limit_candidate_units(model, O, C):
    return model.pc[O,C] <= model.pc_max[C]

model.con1 = Constraint(model.O, model.C, rule=con1_limit_candidate_units)

def con2_power_balance(model, O, G):
    return sum(model.pg[O, G] for G in model.G) + sum(model.pc[O, C] for C in model.C) == data.loc[O-1, 'd']

model.con2 = Constraint(model.O, model.G, rule = con2_power_balance)

opt = SolverFactory('cplex')
instance = model.create_instance()
results = opt.solve(instance) # solves and updates instance
print('Objective value=',value(instance.objective))

运行后抛出错误:

TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_5960/507444092.py in <module>
     36                 sum(model.Ic*model.pc_max[C] for C in model.C)
     37 
---> 38 model.objective = Objective(model, rule=objective_rule, sense=minimize)
     39 #Constraints
     40 #1. sign restrictions already provided for in the definition of decision variables

~\anaconda3\lib\site-packages\pyomo\core\base\objective.py in __init__(self, *args, **kwargs)
    279 
    280         kwargs.setdefault('ctype', Objective)
---> 281         ActiveIndexedComponent.__init__(self, *args, **kwargs)
    282 
    283         self.rule = Initializer(_init)

~\anaconda3\lib\site-packages\pyomo\core\base\indexed_component.py in __init__(self, *args, **kwds)
   1046 
   1047     def __init__(self, *args, **kwds):
-> 1048         IndexedComponent.__init__(self, *args, **kwds)
   1049         # Replicate the ActiveComponent.__init__() here.  We don't want
   1050         # to use super, because that will run afoul of certain

~\anaconda3\lib\site-packages\pyomo\core\base\indexed_component.py in __init__(self, *args, **kwds)
    289             #
    290             self._implicit_subsets = None
-> 291             self._index = process_setarg(args[0])
    292         else:
    293             #

~\anaconda3\lib\site-packages\pyomo\core\base\set.py in process_setarg(arg)
    118                             % (arg.ctype.__name__, arg.name,))
    119         if isinstance(arg, Component):
-> 120             raise TypeError("Cannot apply a Set operator to a non-Set "
    121                             "%s component (%s)"
    122                             % (arg.__class__.__name__, arg.name,))

TypeError: Cannot apply a Set operator to a non-Set ConcreteModel component (unknown)

报错原因

  1. Objective构造参数错误:原代码中Objective(model, rule=...)把model作为第一个参数传递,Pyomo会将这个参数解析为索引集合,而model是ConcreteModel对象,不是集合,因此触发类型错误。
  2. 目标函数Rule定义错误:objective_rule(model, O)额外声明了O参数,Pyomo会认为这个目标函数是按O索引的多目标函数,但实际我们需要的是全局单目标函数,多余的参数导致Pyomo错误地尝试将目标函数索引化。

解决方法

步骤1:修正目标函数Rule

移除Rule中多余的O参数,因为目标函数是对所有操作条件求和的全局表达式:

def objective_rule(model):
    return sum(data.loc[O-1, 'w']*(sum(model.Cg*model.pg[O,G] for G in model.G))+\
               data.loc[O-1, 'w']*(sum(model.Cc*model.pc[O,C] for C in model.C)) for O in model.O)+\
                sum(model.Ic*model.pc_max[C] for C in model.C)

步骤2:修正Objective创建方式

不需要将model作为第一个参数传递,正确写法如下:

model.objective = Objective(rule=objective_rule, sense=minimize)

步骤3:(可选)约束优化

原约束con2_power_balance的索引包含G,但约束逻辑是对每个O的功率平衡,不需要按G索引,修正约束定义:

def con2_power_balance(model, O):
    return sum(model.pg[O, G] for G in model.G) + sum(model.pc[O, C] for C in model.C) == data.loc[O-1, 'd']

model.con2 = Constraint(model.O, rule = con2_power_balance)

修正后完整代码

# model definition
model = ConcreteModel()

# Sets and indices
model.O = RangeSet(len(data))  # Set of representative operating conditions
model.D = RangeSet(len(data)) # Demand profile for the operating conditions
model.G = RangeSet(1)   # set of existing generators
model.C = RangeSet(1)   # set of candidate generators

# Parameters
model.Cg= Param(initialize=35, within=NonNegativeReals, mutable=True) # Opex of existing generators
model.Cc= Param(initialize=25, within=NonNegativeReals, mutable=True) # Opex of candidate generators
model.Ic= Param(initialize=70000, within=NonNegativeReals, mutable=True) # Annualized investment cost

# Decision Variables
model.pg = Var(model.O, model.G, bounds=(0, 400), initialize=0, within=NonNegativeReals)
model.pc = Var(model.O, model.C, bounds=(0, 500), initialize=0, within=NonNegativeReals)
model.pc_max = Var(model.C, bounds=(0, 500), initialize=0, within=NonNegativeIntegers)

# Objective function
def objective_rule(model):
    return sum(data.loc[O-1, 'w']*(sum(model.Cg*model.pg[O,G] for G in model.G))+\
               data.loc[O-1, 'w']*(sum(model.Cc*model.pc[O,C] for C in model.C)) for O in model.O)+\
                sum(model.Ic*model.pc_max[C] for C in model.C)

model.objective = Objective(rule=objective_rule, sense=minimize)

# Constraints
# 1. sign restrictions already provided for in the definition of decision variables
def con1_limit_candidate_units(model, O, C):
    return model.pc[O,C] <= model.pc_max[C]

model.con1 = Constraint(model.O, model.C, rule=con1_limit_candidate_units)

def con2_power_balance(model, O):
    return sum(model.pg[O, G] for G in model.G) + sum(model.pc[O, C] for C in model.C) == data.loc[O-1, 'd']

model.con2 = Constraint(model.O, rule = con2_power_balance)

opt = SolverFactory('cplex')
instance = model.create_instance()
results = opt.solve(instance) # solves and updates instance
print('Objective value=',value(instance.objective))

内容的提问来源于stack exchange,提问作者Mr. EAo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:35:04