Pyomo:最小化向量中的最大值
Pyomo: Minimize for Max Value in Vector
我正在优化电池存储与太阳能光伏相结合的行为,以产生尽可能高的收入流。
我现在想增加一个收入来源:调峰(或减少需求费用)
我的做法如下:
- 在每千瓦时的价格旁边,工业客户支付他在一个时期内(i=1:end)从电网获取的最大电量 (kW),即所谓的需求电费
- 这个最大量是在向量中找到的 P_Grid = P_GridLoad(电网自消耗的能量)+ P_GridBatt(用于给电池充电的能量)
- 存在一个价格向量,它告诉所有时间点每千瓦的价格
- 我现在想生成一个向量 P_GridMax,它在所有时间点都为零,但是 P_Grid 的最大值出现的那一刻(然后它等于 max(P_Grid).
- 因此,向量 P_GridMax 由零和一个非零元素组成(不多!)
- 在这样做时,我现在可以将此向量与价格向量相乘,对所有时间点求和并收到计费的需求费用
- 通过将此向量包含到我的模型的 objective 中,我可以最大限度地减少这些费用
现在,是否有人看到了如何制定此类约束 (P_GridMax) 的解决方案?我已经更新了 objective 函数并定义了 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 编码的经验很少,非常感谢您提供详尽的解释:)
最好的,
马蒂亚斯
这是一种方法:
引入二进制辅助变量ismax[i] for i in i_TIME
。如果在 i
期间获得最大值,则此变量为 1,否则为 0。那么显然你有一个约束sum(ismax[i] for i in i_TIME) == 1
:最大值必须恰好在一个周期内达到。
现在您需要两个附加约束:
- 如果
ismax[i] == 0
那么P_GridMax[i] == 0
。
- if
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
那么这个约束的left-hand边至少是M
,所以根据M
的定义不管值是多少都会满足P_GridMax[i]
的是(在这种情况下第一个约束力 P_Grid[i] == 0
)。对于 ismax[i] == 1
,约束的 left-hand 侧变为 P_GridMax[i]
,正是我们想要的。
另一个想法是你实际上不需要用时间索引你的 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)
如果您真的打算按元素乘以向量,您也可以只创建一个新变量来表示该索引产品,并应用相同的原理来提取最大值。
我正在优化电池存储与太阳能光伏相结合的行为,以产生尽可能高的收入流。 我现在想增加一个收入来源:调峰(或减少需求费用)
我的做法如下:
- 在每千瓦时的价格旁边,工业客户支付他在一个时期内(i=1:end)从电网获取的最大电量 (kW),即所谓的需求电费
- 这个最大量是在向量中找到的 P_Grid = P_GridLoad(电网自消耗的能量)+ P_GridBatt(用于给电池充电的能量)
- 存在一个价格向量,它告诉所有时间点每千瓦的价格
- 我现在想生成一个向量 P_GridMax,它在所有时间点都为零,但是 P_Grid 的最大值出现的那一刻(然后它等于 max(P_Grid).
- 因此,向量 P_GridMax 由零和一个非零元素组成(不多!)
- 在这样做时,我现在可以将此向量与价格向量相乘,对所有时间点求和并收到计费的需求费用
- 通过将此向量包含到我的模型的 objective 中,我可以最大限度地减少这些费用
现在,是否有人看到了如何制定此类约束 (P_GridMax) 的解决方案?我已经更新了 objective 函数并定义了 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 编码的经验很少,非常感谢您提供详尽的解释:)
最好的, 马蒂亚斯
这是一种方法:
引入二进制辅助变量ismax[i] for i in i_TIME
。如果在 i
期间获得最大值,则此变量为 1,否则为 0。那么显然你有一个约束sum(ismax[i] for i in i_TIME) == 1
:最大值必须恰好在一个周期内达到。
现在您需要两个附加约束:
- 如果
ismax[i] == 0
那么P_GridMax[i] == 0
。 - if
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
那么这个约束的left-hand边至少是M
,所以根据M
的定义不管值是多少都会满足P_GridMax[i]
的是(在这种情况下第一个约束力 P_Grid[i] == 0
)。对于 ismax[i] == 1
,约束的 left-hand 侧变为 P_GridMax[i]
,正是我们想要的。
另一个想法是你实际上不需要用时间索引你的 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)
如果您真的打算按元素乘以向量,您也可以只创建一个新变量来表示该索引产品,并应用相同的原理来提取最大值。