Pyomo:如何更新现有模型实例的约束定义?

时间:2018-03-22 18:36:40

标签: parameters model mutable pyomo

我遇到了问题,我确信有一个答案(可能是一行代码)。

我有以下最小模型(在数学上是荒谬的,但它描述了我的问题):

from pyomo.environ import *

model=AbstractModel()
m=model
m.name="Example model"

#Sets
m.mySet=Set(doc="my set")

m.myVar = Var(m.mySet, name="my variable", initialize=0, within=NonNegativeReals)
m.mutableParameter = Param(m.mySet, name="some mutable parameter", default=0, mutable=True)

m.someDefaultValue = 10
m.someOtherValue = 20
def changingConstraint_rule(m, n):
    if m.mutableParameter[n] == 0:
        return m.myVar[n] == m.someDefaultValue
    else:
        return m.myVar[n] == m.someOtherValue/m.mutableParameter[n]
m.changingConstraint = Constraint(m.mySet, rule=changingConstraint_rule)

#Objective function
def myObj(m):
    return sum([m.myVar[n] for n in m.mySet])
m.myObjective = Objective(rule=myObj, sense=minimize)

如您所见,changingConstraint的行为取决于mutableParameter所具有的值。

现在,当我使用m.create_instance('mydata.dat')创建此模型的实例时,Pyomo会根据实例所在的mutableParameter的值自动决定if子句的哪个部分使用创建

但是当我现在更新我的mutableParameter(到一个非零值)并再次运行模型时,Pyomo不会更新它在约束中使用if子句的情况,并且仍然采用原始解释:

from pyomo import *
from pyomo.environ import *

from minimalModel import m

instance = m.create_instance('datafile.dat')

# Run model once with standard values
solver = 'ipopt'
opt = SolverFactory(solver)
results = opt.solve(instance)

# Change the mutableParameter and run the model again
for t in instance.mySet:
    instance.mutableParameter[t] = 99

# --> This is where I seem to be missing some call to update the instance. I've tried instance.preprocess(), that didn't work <--
results = opt.solve(instance)

告诉Pyomo“重新读取模型文件并根据mutableParameters的新值重新评估所有if子句”,我该怎么做?

我有一种虚拟的方法:使用新参数编写新的.dat-File,并通过另一个create_instance()调用创建一个全新的实例。但这需要我为任何可变参数的每个更改编写一个新的.dat文件。我确信有更聪明的方法可以做到这一点。

我会感激任何提示。谢谢!

1 个答案:

答案 0 :(得分:1)

我已经弄明白了,恭请陈琦指出我正确的方法。

需要做的是在重新评估模型之前重建约束,而不是整个模型。

事先,我正在尝试

instance.reconstruct()

再次调用opt.solve()之前。那没用。实际需要做的是通过

重建约束本身
instance.changingConstraint.reconstruct()

然后根据可变参数的新值重新计算约束中的if子句。