【问题标题】:Error handling in pyomo - division by zeropyomo 中的错误处理 - 除以零
【发布时间】:2023-01-19 20:52:44
【问题描述】:

我正在研究一个线性优化问题,我有一组城市和一组发电厂。城市有需要满足的电力需求。但是,就我的问题而言,在某些时间段内,城市没有电力需求(来自发电厂,因为它们可以自己生产一些)。我认为具体细节不是很重要,所以下面是我对该问题的最佳描述。

目标函数包含以下项:

Term in objective function

我创建了适当的城市和月份集,并将我的目标函数设置为:

sum(sum(1/model.monthly_demand[c,t]*model.theta[c] for c in model.cities) for t in model.months)

monthly_demand[c,t] = 0 出现除以零错误时,问题显然出现了。而且我不确定如何处理这个问题。理想情况下,我希望 theta[c] 在这种情况下设置为零,但我不确定如何执行此操作。我尝试在 sum() 函数中添加一些 if/else 语句,但据我所知这是不可能的。

我想我也可以定义一个传递给 pyomo 目标的函数,所以我的想法是尝试类似 if 语句的东西,当每月需求为零时将 theta[c] 设置为零,但这并不成功。

另一个想法是将需求设置为 0.000001 之类的值,但我希望这是最后的解决方案,因为我认为这会导致问题。

【问题讨论】:

    标签: linear-programming pyomo divide-by-zero


    【解决方案1】:

    您应该在方便的非零需求元素的任何地方制作一个子集。我假设 demand 是一个参数这是有道理的,但你没有具体说明。然后使用该子集作为求和的基础。这将避免包含空/零元素。

    注意模型打印输出中的目标元素。

    代码:

    import pyomo.environ as pyo
    
    demand_data = { ('LA', 0) : 20,
                    ('LA', 1) : 0,
                    ('SF', 1) : 15,
                    ('NY', 0) : 20,
                    ('NY', 1) : 30}
    
    m = pyo.ConcreteModel('electricity')
    
    m.C = pyo.Set(initialize=['LA', 'SF', 'NY'])
    m.T = pyo.Set(initialize=list(range(2)))
    
    # VARS
    m.x = pyo.Var(m.C, m.T, domain=pyo.NonNegativeReals)
    
    # PARAMS
    m.demand = pyo.Param(m.C, m.T, initialize=demand_data, default=0)
    
    # CONSTRAINTS
    # ...
    
    # OBJ
    # make a subset of the non-zero demand periods
    nonzero_demand_domain = {(c,t) for c in m.C for t in m.T if m.demand[c, t] > 0}
    
    # use that in your objective...
    m.obj = pyo.Objective(expr=sum(m.x[c, t] for c, t in nonzero_demand_domain))
    
    m.pprint()
    

    输出:

    4 Set Declarations
        C : Size=1, Index=None, Ordered=Insertion
            Key  : Dimen : Domain : Size : Members
            None :     1 :    Any :    3 : {'LA', 'SF', 'NY'}
        T : Size=1, Index=None, Ordered=Insertion
            Key  : Dimen : Domain : Size : Members
            None :     1 :    Any :    2 : {0, 1}
        demand_index : Size=1, Index=None, Ordered=True
            Key  : Dimen : Domain : Size : Members
            None :     2 :    C*T :    6 : {('LA', 0), ('LA', 1), ('SF', 0), ('SF', 1), ('NY', 0), ('NY', 1)}
        x_index : Size=1, Index=None, Ordered=True
            Key  : Dimen : Domain : Size : Members
            None :     2 :    C*T :    6 : {('LA', 0), ('LA', 1), ('SF', 0), ('SF', 1), ('NY', 0), ('NY', 1)}
    
    1 Param Declarations
        demand : Size=6, Index=demand_index, Domain=Any, Default=0, Mutable=False
            Key       : Value
            ('LA', 0) :    20
            ('LA', 1) :     0
            ('NY', 0) :    20
            ('NY', 1) :    30
            ('SF', 1) :    15
    
    1 Var Declarations
        x : Size=6, Index=x_index
            Key       : Lower : Value : Upper : Fixed : Stale : Domain
            ('LA', 0) :     0 :  None :  None : False :  True : NonNegativeReals
            ('LA', 1) :     0 :  None :  None : False :  True : NonNegativeReals
            ('NY', 0) :     0 :  None :  None : False :  True : NonNegativeReals
            ('NY', 1) :     0 :  None :  None : False :  True : NonNegativeReals
            ('SF', 0) :     0 :  None :  None : False :  True : NonNegativeReals
            ('SF', 1) :     0 :  None :  None : False :  True : NonNegativeReals
    
    1 Objective Declarations
        obj : Size=1, Index=None, Active=True
            Key  : Active : Sense    : Expression
            None :   True : minimize : x[NY,0] + x[NY,1] + x[LA,0] + x[SF,1]
    
    7 Declarations: C T x_index x demand_index demand obj
    

    【讨论】:

    • 不幸的是,我不能赞成您的回答,因为我是该网站的新手,但我只想说非常感谢您的详尽回答!很容易理解并解决了我的问题:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多