【问题标题】:The parameter values are not updating in the Pyomo model with PySP callback使用 PySP 回调的 Pyomo 模型中的参数值未更新
【发布时间】:2021-07-15 00:02:44
【问题描述】:

我正在使用 PySP (Pyomo) 解决一个随机优化问题。我为我的问题创建了一个具体的模型,并根据

中给出的农民示例定义了场景

https://github.com/Pyomo/pysp/blob/main/examples/farmer/concrete/ReferenceModel.py

在上面的示例中,每个场景都调用了一个pysp_instance_creation_callback() 函数。在该函数中,为每个场景克隆了一个模型实例,以便使用 instance.Yield.store_values(Yield[scenario_name]) 为每个场景更新场景变量(在本例中为 Yield)。

我对我的问题采用了类似的方法。然而,在我的例子中,对于每个场景,未知数的大小都不同,不像农民的例子,场景只适用于三种作物(小麦、糖、玉米)。例如,我的场景应该是这样的,

Scenario1 = {123, 124, 118}
Scenario2 = {117, 10}
Scenario3 = {118, 120, 125, 126}
Scenario4 = {0, 125}
...

我的代码 sn-p 类似于下面的代码(为简单起见,我只提到了有用的约束和变量)

# Variable:
model.nEdges = 129
model.x_ij = range(0, model.nEdges)  # line switching variable range
model.xij = Var(model.x_ij, bounds=(0, 1), within=Binary)

# Scenario parameter:
model.Fault = Param(mutable=True, initialize={123,124,118}, within=Any)

# Constraint:
for key, ite in model.Fault.items():
    for faulty in ite.value:
        model.c.add(model.xij[faulty] == 0)

# Scenarios:
Fault = {}
Fault['Scenario1'] = {123, 124, 118}
Fault['Scenario2'] = {120, 124, 118}
Fault['Scenario3'] = {1, 125}

# callback function to update the model parameter
def pysp_instance_creation_callback(scenario_name, node_names):
    instance = model.clone()
    instance.Fault.store_values(Fault[scenario_name])
    return instance

但是,这种方法对我不起作用。对于每个场景,model.Fault 的值在初始化时保持不变,即 {123,124,118}。虽然如果我检查每个场景的实例值,即instance.Fault.value,那么看起来这些值正在更新(instance.Fault.value 给出与不同场景一致的不同值)但是在检查实际模型的输出 lp 文件时,约束不会按需要更新,并且最终解决方案对于前面提到的每个场景都是相同的。我不知道如何解决这个问题,而且我已经陷入这个问题好几天了。有人可以帮我吗?

【问题讨论】:

    标签: python optimization pyomo


    【解决方案1】:

    简短的回答是您没有正确使用 Param。可变参数用于保存 标量 值,这些值出现在 表达式树中(用于目标或约束)。您将一个复杂的数据结构放入 Param 中,然后在创建原始模型时对其进行迭代,使用间接数据(作为另一个变量的 index )。这不起作用的原因是model.clone() 复制了模型当前存在的,它复制了原始约束。您添加到model.c 的约束实际上独立于可变参数Fault,因此当您更改其中的值时,Pyomo 无法知道什么/如何更新约束。

    针对这种特定情况的更好方法是修复变量,而不是创建额外的约束:

    model.xij = Var(model.x_ij, bounds=(0, 1), within=Binary)
    
    # Scenarios:
    Fault = {}
    Fault['Scenario1'] = {123, 124, 118}
    Fault['Scenario2'] = {120, 124, 118}
    Fault['Scenario3'] = {1, 125}
    
    # callback function to update the model parameter
    def pysp_instance_creation_callback(scenario_name, node_names):
        instance = model.clone()
        for faulty in Fault[scenario_name]:
            instance.xij[faulty].fix(0)
        return instance
    

    【讨论】:

    • 这完全解决了我的问题。我不能对你的帮助表示足够的感谢。谢谢你:)
    • 是否可以在 pysp_instance_creation_callback 中添加约束?假设如果 xij 依赖于其他变量 yij,使得 xij >= yij,那么当 yij = 1 时,我无法将 xij[faulty] 修复为 0。有什么方法可以解决这个问题吗?
    【解决方案2】:

    在开始之前,我应该指出 PySP 不再处于积极开发中。 mpi-sppy https://github.com/Pyomo/mpi-sppy

    正在进行新的开发

    回到您的问题:PySP 假设模型的“形状”对于每个场景都是相同的,因此您必须进行更多编码才能使该假设有效。 mpi-sppy 或多或少也是如此,尽管它具有允许根据场景具有零概率的 Var 的机制。 mpi-sspy 比 PySP 的麻烦要少一些,参数可以在不同场景之间改变大小,但它确实有一些组件假设模型的形状可以由任意场景确定(PySP 使用 ReferenceModel 所以它强烈假设形状没有改变)。

    【讨论】:

      猜你喜欢
      • 2021-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2022-11-28
      • 1970-01-01
      • 2017-11-19
      相关资源
      最近更新 更多