【问题标题】:pyomo: how to index Variable in only part of a Set?pyomo:如何仅在 Set 的一部分中索引变量?
【发布时间】:2021-11-16 15:17:42
【问题描述】:

我正在尝试在 pyomo 优化模型中跟踪 SOC。我有许多 BEV,我想跟踪每个 SOC。我传递给pe.Objective 的表达式如下所示:

sum(sum(model.SOC[t+1, b] - model.SOC[t, b] for b in model.buses) for t in model.times)

model.busesmodel.times 是我声明为pe.Set 的两个集合。时间从 (0, ...., 95) 开始。因此,在model.times 的最后一次迭代中,它会尝试访问model.SOC[96, b],这会导致KeyError

有没有办法告诉 pyomo 找出集合的最后一个元素来防止这个错误?

有点像:

sum(sum(model.SOC[t+1, b] - model.SOC[t, b] for b in model.buses) for t in model.times[0:-2])

不幸的是,这也引发了一个错误:

IndexError: times indices must be integers, not slice

这是一个应该重现错误的最小示例:

import pyomo.environ as pe

solver = pe.SolverFactory('glpk')
model = pe.ConcreteModel('Test')
model.times = pe.Set(initialize=list(range(96)))
model.buses = pe.Set(initialize=list(range(5)))
model.SOC = pe.Var(model.times*model.buses, domain=pe.PositiveReals)

def example_rule(model):
    return sum(sum(model.SOC[t+1, b] - model.SOC[t, b] for b in model.buses) for t in model.times)

model.obj = pe.Objective(rule=example_rule, sense=pe.maximize)

model.pprint()

非常感谢!

【问题讨论】:

    标签: python optimization pyomo


    【解决方案1】:

    是的,有几种方法可以做到这一点。首先,如果要索引的集合是有序的(这是默认设置),您可以通过各种方式对集合使用firstlastprev 方法。 (请参阅下面我对您的代码所做的修改)

    其次,您始终可以构建自己的子集并将其放入模型中或不放入。下面的第二个模型显示了任意复杂子集的构造并将其放入模型中。该集合可以用作目标或约束的基础。

    这个解决方案类似于这个answer

    import pyomo.environ as pe
    
    solver = pe.SolverFactory('glpk')
    model = pe.ConcreteModel('Test')
    model.times = pe.Set(initialize=list(range(5)), ordered=True)  # ordered is default, this is for clarity...
    model.buses = pe.Set(initialize=list(range(2)))
    model.SOC = pe.Var(model.times*model.buses, domain=pe.PositiveReals)
    
    def example_rule(model):
        return sum(sum(model.SOC[t+1, b] - model.SOC[t, b] for b in model.buses) for t in model.times if t != model.times.last())
    
    model.obj = pe.Objective(rule=example_rule, sense=pe.maximize)
    
    model.pprint()
    
    
    # making your own subset...
    times = 10
    model2 = pe.ConcreteModel("other")
    model2.times = pe.Set(initialize=range(times))
    # make a subset of the even values that are no more than 4 values close to the end....
    model2.times_subset = pe.Set(initialize=[t for t in model2.times if t%2==0 and t <= times-4])
    
    model2.pprint()
    

    产量:

    3 Set Declarations
        SOC_index : Size=1, Index=None, Ordered=True
            Key  : Dimen : Domain      : Size : Members
            None :     2 : times*buses :   10 : {(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1), (4, 0), (4, 1)}
        buses : Size=1, Index=None, Ordered=Insertion
            Key  : Dimen : Domain : Size : Members
            None :     1 :    Any :    2 : {0, 1}
        times : Size=1, Index=None, Ordered=Insertion
            Key  : Dimen : Domain : Size : Members
            None :     1 :    Any :    5 : {0, 1, 2, 3, 4}
    
    1 Var Declarations
        SOC : Size=10, Index=SOC_index
            Key    : Lower : Value : Upper : Fixed : Stale : Domain
            (0, 0) :     0 :  None :  None : False :  True : PositiveReals
            (0, 1) :     0 :  None :  None : False :  True : PositiveReals
            (1, 0) :     0 :  None :  None : False :  True : PositiveReals
            (1, 1) :     0 :  None :  None : False :  True : PositiveReals
            (2, 0) :     0 :  None :  None : False :  True : PositiveReals
            (2, 1) :     0 :  None :  None : False :  True : PositiveReals
            (3, 0) :     0 :  None :  None : False :  True : PositiveReals
            (3, 1) :     0 :  None :  None : False :  True : PositiveReals
            (4, 0) :     0 :  None :  None : False :  True : PositiveReals
            (4, 1) :     0 :  None :  None : False :  True : PositiveReals
    
    1 Objective Declarations
        obj : Size=1, Index=None, Active=True
            Key  : Active : Sense    : Expression
            None :   True : maximize : SOC[1,0] - SOC[0,0] + SOC[1,1] - SOC[0,1] + SOC[2,0] - SOC[1,0] + SOC[2,1] - SOC[1,1] + SOC[3,0] - SOC[2,0] + SOC[3,1] - SOC[2,1] + SOC[4,0] - SOC[3,0] + SOC[4,1] - SOC[3,1]
    
    5 Declarations: times buses SOC_index SOC obj
    2 Set Declarations
        times : Size=1, Index=None, Ordered=Insertion
            Key  : Dimen : Domain : Size : Members
            None :     1 :    Any :   10 : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        times_subset : Size=1, Index=None, Ordered=Insertion
            Key  : Dimen : Domain : Size : Members
            None :     1 :    Any :    4 : {0, 2, 4, 6}
    
    2 Declarations: times times_subset
    [Finished in 553ms]
    

    【讨论】:

    • 完美,谢谢! :) 这个prevw 解决了我的问题。互联网上有没有可以学习这个的地方?在 pyomo 文档中甚至没有提到 prevw(或者至少我没有看到它)
    • 是的,恕我直言,Pyomo 文档涵盖了基础知识,但缺乏好的模块文档。这是“好的”,但不是很好......如果没有其他帖子,我不会知道prevw。有时我会修改ipython,它显示完成和文档存根。 pyomo.readthedocs.io/en/expr_dev/_modules/index.html
    猜你喜欢
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 1970-01-01
    相关资源
    最近更新 更多