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

时间:2019-05-08 14:35:26

标签: python cplex battery pyomo mixed-integer-programming

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

我的方法如下:

  • 在每千瓦时的价格旁边,工业客户支付了他在一个时期(i = 1:end)内从电网汲取的最大功率(kW),即所谓的需求费用
  • 可以在向量P_Grid = P_GridLoad(自消耗的能量)+ P_GridBatt(用于给电池充电的能量)中找到最大数量
  • 存在一个价格向量,可以告诉所有时间点每千瓦的价格
  • 我现在想生成一个矢量P_GridMax,该矢量对于所有时间点都是零,但在发生P_Grid最大值的那一刻(那时它等于max(P_Grid))。
  • 因此,向量P_GridMax由零和一个非零元素组成(不多!)
  • 这样做,我现在可以将此向量与价格向量相乘,对所有时间点求和,并接收计费的需求费用
  • 通过将此向量包含在模型的目标中,可以使这些费用最小化

现在,有没有人看到如何制定这样的约束的解决方案(P_GridMax)?我已经更新了目标函数并定义了P_Grid。 任何其他方法也将受到欢迎。

这是我模型的相关部分,其中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

2 个答案:

答案 0 :(得分:1)

这里是执行此操作的一种方法:

引入一个二进制帮助变量ismax[i] for i in i_TIME。如果在周期i中获得最大值,则此变量为1,否则为0。那么显然您有一个约束sum(ismax[i] for i in i_TIME) == 1:最大值必须在一个周期内达到。

现在您需要两个附加约束:

  1. 如果ismax[i] == 0,然后是P_GridMax[i] == 0
  2. 如果ismax[i] == 1,那么对于所有j in i_TIME,我们必须拥有P_GridMax[i] >= P_GridMax[j]

表达这一点的最好方法是使用指标约束,但是我不认识Pyomo,所以我不知道它是否支持(我想是的,但是我不知道如何编写)。因此,我将改为使用big-M公式。

对于此公式,您需要定义一个常量M,以使P_Grid[i]不能超过任何i的值。这样,第一个约束变为

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

该约束将P_GridMax[i]强制为0,除非ismax[i] == 1。对于ismax[i] == 1,这是多余的。 第二个约束是针对所有j in i_TIME

P_GridMax[i] + M * (1 - ismax[i]) >= P_Grid[j]

如果ismax[i] == 0,则此约束的左侧至少为M,因此,根据M的定义,无论{{1 }}是(在这种情况下,第一个约束力P_GridMax[i])。对于P_Grid[i] == 0,约束的左侧就变成了ismax[i] == 1,正是我们想要的。

答案 1 :(得分:0)

另一个想法是,您实际上不需要随时间索引P_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)

如果您真的想将向量乘以元素,还可以只创建一个代表该索引乘积的新变量,并应用相同的原理来提取最大值。