首页 > 解决方案 > 如何从 pyomo 模型中删除 Set 元素(和相关组件)?

问题描述

我试图在创建模型后从 pyomo Set 中删除元素,以探索较小的优化问题实例。简而言之,我的问题是:删除 Set 元素后如何确保模型的完整性?

我的方法是循环遍历可能被更改的 Set 索引的 Param、Var、Constraint 和 Expression 组件。(对于大型模型来说非常麻烦,但不知道该怎么做!)

删除 set 元素后调用solve() 时会引发错误,并且在我尝试纠正这种情况时,我一直在尝试使用已删除 Set 元素的索引值删除 Param 组件。

随着每个组件的循环,索引键等于该 Set 元素值的组件将被删除。但它似乎不适用于 pyo.Param 组件,因为当您尝试索引它们时,返回的是实际值而不是组件。所以'del'不起作用....并且传递一个全新的字典(这需要在pyomo之外进行重组)将不起作用,除非它是可变的。也许它需要是可变的?

这是一个最小的例子......(有两个集合,两个参数和一个变量)

# --- Build a model ---
my_model = pyo.ConcreteModel()
my_model.A = pyo.Set(initialize=['a1', 'a2'])
my_model.B = pyo.Set(initialize=['b1', 'b2'])
my_model.C = pyo.Set(initialize=[('a1', 'b1'), ('a2', 'b1'), ('a2', 'b2')], within=my_model.A*my_model.B)
my_model.param1 = pyo.Param(my_model.A, initialize={'a1': 5, 'a2': 9})
my_model.param2 = pyo.Param(my_model.B, initialize={'b1': 1, 'b2': 2})
my_model.x = pyo.Var(my_model.A, my_model.B, domain=pyo.NonNegativeReals)
def constraint_rule(m, a):
    temp = sum([(m.param1[a] * m.x[a, b]) 
                for b in m.B])
    return 5, temp, None
my_model.constraint = pyo.Constraint(my_model.A, rule=constraint_rule)
def objective_rule(m):
    return sum([(m.param1[a] * m.param2[b] * m.x[a, b]) 
                for a in m.A 
                for b in m.B])
my_model.objective_expr = pyo.Expression(rule=objective_rule)
my_model.objective = pyo.Objective(rule=lambda m: m.component('objective_expr'), sense=pyo.minimize)

# --- Now let's remove an element ('a2') from set1 ---

# --- First, hold on to data, so that we're not later attempting to change components while iterating over them inside loops ---
temp_A = my_model.A.data().copy()
temp_B = my_model.B.data().copy()
temp_param1_dict = {k: v for k, v in my_model.param1.items()}
temp_x_list = [k for k in my_model.x.items()].copy()

# --- Do the removals ---
element_to_remove = 'a2'
for k in temp_A:
    if k == element_to_remove:
        my_model.A.remove(k)
for k in list(temp_param1_dict):
    if k == element_to_remove:
        del my_model.param1[k] 
for k, v in temp_x_list:
    if k[0] == element_to_remove:
        del my_model.x[k]

# --- Reconstruct the associated expressions ---
my_model.objective_expr.reconstruct()
my_model.constraint.reconstruct()

# --- Solve ---
results = pyo.SolverFactory('ipopt').solve(my_model, tee=True)

在我的设置(pyomo=5.6.2)上,上面的代码抛出异常:

AttributeError: 'int' object has no attribute '_component'

...对于“del my_model.param1[k]”这一行

但是,如果我只是注释掉删除参数的部分,那么我会得到另外两个错误(我认为是在预处理过程中):

KeyError: 90706423712
AttributeError: 'NoneType' object has no attribute 'getname'

(注意:这基本上是上一个问题的后续:https ://groups.google.com/d/msg/pyomo-forum/WEySR4eJ4-A/Fyas8sGcAQAJ )

感谢您提供的任何见解!

标签: pythonoptimizationpyomo

解决方案


推荐阅读