Python Pyomo:向量中最大值的最小化

Python Pyomo:向量中最大值的最小化,python,cplex,battery,pyomo,mixed-integer-programming,Python,Cplex,Battery,Pyomo,Mixed Integer Programming,我正在优化电池存储与太阳能光伏相结合的行为,以产生尽可能高的收入流。 我现在想再增加一个收入来源:调峰(或减少需求费用) 我的做法如下: 除了每千瓦时的价格外,工业用户还需支付一段时间(i=1:end)内从电网获取的最大电量(kW),即所谓的需求费 该最大量可在向量P_Grid=P_GridLoad(电网自耗能量)+P_GridBatt(用于电池充电的能量)中找到 存在一个价格向量,它告诉所有时间点每千瓦的价格 现在我想生成一个向量P_GridMax,它在所有时间点上都为零,但P_Grid的最

我正在优化电池存储与太阳能光伏相结合的行为,以产生尽可能高的收入流。 我现在想再增加一个收入来源:调峰(或减少需求费用)

我的做法如下:

  • 除了每千瓦时的价格外,工业用户还需支付一段时间(i=1:end)内从电网获取的最大电量(kW),即所谓的需求费
  • 该最大量可在向量P_Grid=P_GridLoad(电网自耗能量)+P_GridBatt(用于电池充电的能量)中找到
  • 存在一个价格向量,它告诉所有时间点每千瓦的价格
  • 现在我想生成一个向量P_GridMax,它在所有时间点上都为零,但P_Grid的最大值出现的时刻(然后它等于max(P_Grid))
  • 因此,向量P_GridMax由零和一个非零元素组成(不是更多!)
  • 通过这样做,我现在可以将这个向量与价格向量相乘,在所有时间点上求和,并收到已计费的需求费用
  • 通过将这个向量包含到我的模型的目标中,我可以最小化这些费用
现在,有人看到了一个如何制定这样一个约束(p_GridMax)的解决方案吗?我已经更新了我的目标函数并定义了p_网格。 也欢迎采取任何其他办法

这是我模型的相关部分,p_xxx=潮流向量,C_xxx=价格向量

m.P_Grid = Var(m.i_TIME, within = NonNegativeReals)
m.P_GridMax = Var(m.i_TIME, within = NonNegativeReals)


# Minimize electricity bill
def Total_cost(m):
    return ... + sum(m.P_GridMax[i] * m.C_PowerCosts[i] for i in m.i_TIME) - ...
m.Cost = Objective(rule=Total_cost)


## Peak Shaving constraints
def Grid_Def(m,i):
    return m.P_Grid[i] = m.P_GridLoad[i] + m.P_GridBatt[i]
m.Bound_Grid = Constraint(m.i_TIME,rule=Grid_Def)

def Peak_Rule(m,i):
    ????
    ????
    ????
    ????
m.Bound_Peak = Constraint(m.i_TIME,rule=Peak_Rule)
非常感谢您!请注意,我对python/pyomo编码的经验很少,我非常感谢您的详细解释:)

最好的,
Mathias有一种方法可以做到这一点:

在i\u时间内为i引入一个二进制辅助变量ismax[i。如果在时段
i
中获得最大值,则该变量为1,否则为0。很明显,你有一个约束条件
sum(i_TIME中i的ismax[i])==1
:最大值必须在一个周期内达到

现在需要两个附加约束:

  • 如果
    ismax[i]==0
    ,则
    P_GridMax[i]==0
  • 如果
    ismax[i]==1
    那么对于i\u时间内的所有
    j
    我们必须有
    P\u GridMax[i]>=P\u GridMax[j]
  • 最好的方法是使用指标约束,但我不知道Pyomo,所以我不知道它是否支持(我想它支持,但我不知道如何编写它们)。所以我将给出一个大M公式

    对于此公式,您需要定义一个常数
    M
    ,以便
    p_网格[i]
    不能超过任何
    i
    的该值。这样,第一个约束就变为

    P_GridMax[i] <= M * ismax[i]
    

    如果
    ismax[i]==0
    ,则该约束的左侧至少是
    M
    ,因此根据
    M
    的定义,无论
    p_GridMax[i]
    的值是多少(在这种情况下,第一个约束力
    p_Grid[i]==0
    )。对于
    ismax[i]==1
    来说,约束的左侧变成了
    P\u GridMax[i]
    ,这正是我们想要的。

    另一个想法是,实际上不需要随时间索引

    P\u GridMax
    变量

    如果您处理的是需求成本,则它们往往在某个时期内固定不变,或者在您的情况下,它们似乎在整个问题范围内固定不变(因为您只寻找一个最大值)

    在这种情况下,您只需执行以下操作:

    m.P_GridMax = pyo.Var(domain=pyo.NonNegativeReals)
    
    def Peak_Rule(m, i):
        return m.P_GridMax >= m.P_Grid[i]
    
    m.Bound_Peak = pyo.Constraint(m.i_TIME,rule=Peak_Rule)
    
    如果你真的打算按元素乘以向量,你也可以创建一个新的变量来表示索引产品,并应用相同的原理来提取最大值

    m.P_GridMax = pyo.Var(domain=pyo.NonNegativeReals)
    
    def Peak_Rule(m, i):
        return m.P_GridMax >= m.P_Grid[i]
    
    m.Bound_Peak = pyo.Constraint(m.i_TIME,rule=Peak_Rule)