我正试图在不同的市场上寻找购买和销售能源电池的最佳调度方式。我遇到了一个问题,就是电池在同一个市场上同时充放电。我的约束是如何避免同时充放电的?
这里是我的例子:
def battery_optimisation(data: pd.DataFrame, technical_parameters=None, include_revenue=True, solver: str='glpk'):
# Battery's technical specification
MIN_BATTERY_CAPACITY = 0
MAX_BATTERY_CAPACITY = 100
MAX_RAW_POWER = 40
INITIAL_CAPACITY = 0
EFFICIENCY = 1
battery = ConcreteModel()
solvername='glpk'
solverpath_folder='C:\\glpk-4.65\\w64'
solverpath_exe='C:\\glpk-4.65\\w64\\glpsol'
opt = SolverFactory(solver,executable=solverpath_exe)
battery.Period = Set(initialize=list(data.period), ordered=True)
battery.Price = Param(initialize=list(data.spot_hourly), within=Any)
battery.intraday = Param(initialize=list(data.id_hourly), within=Any)
battery.fcr_hourly = Param(initialize=list(data.fcr_hourly), within=Any)
battery.afrr_up = Param(initialize=list(data.afrr_up_energy_hourly), within=Any)
battery.afrr_down = Param(initialize=list(data.afrr_down_energy_hourly), within=Any)
# battery variables
battery.Capacity = Var(battery.Period, bounds=(MIN_BATTERY_CAPACITY, MAX_BATTERY_CAPACITY))
battery.Charge_power = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.Discharge_power = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_dah = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_dah = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_intra = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_intra = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_fcr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_fcr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_afrr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_afrr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.power_balance =Var(battery.Period, doc='binary variable', within=Binary, initialize=0)
battery.power_p = Var(battery.Period, doc='energy derivative with respect to time', initialize=0)
# Set constraints for the battery
# Defining the battery objective (function to be maximise)
def maximise_profit(battery):
rev = sum(data.id_hourly[i] * (battery.discharge_power_intra[i] / 2 * EFFICIENCY) for i in battery.Period) + \
sum(data.fcr_hourly[i] * (battery.discharge_power_fcr[i] / 2 * EFFICIENCY) for i in battery.Period) + \
sum(data.afrr_up_energy_hourly[i] * (battery.discharge_power_afrr[i] / 2 * EFFICIENCY) for i in battery.Period) + \
sum(data.spot_hourly[i] * (battery.discharge_power_dah[i] / 2 * EFFICIENCY) for i in battery.Period)
cost = sum(data.id_hourly[i] * (battery.charge_power_intra[i] / 2) for i in battery.Period) + \
sum(data.fcr_hourly[i] * (battery.charge_power_fcr[i] / 2) for i in battery.Period) + \
sum(data.afrr_down_energy_hourly[i] * (battery.charge_power_afrr[i] / 2) for i in battery.Period) + \
sum(data.spot_hourly[i] * (battery.charge_power_dah[i] / 2) for i in battery.Period)
return rev - cost
# CONSTRAINT - BATTERY CAN'T CHARGE OVER CAPACITY
def over_charge(battery, i):
battery_charge = battery.charge_power_intra[i] + \
battery.charge_power_fcr[i] + \
battery.charge_power_afrr[i] + \
battery.charge_power_dah[i]
return battery_charge <= (MAX_BATTERY_CAPACITY - battery.Capacity[i]) * 2 / EFFICIENCY
# CONSTRAINT - CAN DISCHARGE MORE THAN CAPITY
def over_discharge(battery, i):
battery_charge = battery.discharge_power_intra[i] + \
battery.discharge_power_fcr[i] + \
battery.discharge_power_afrr[i] + \
battery.discharge_power_dah[i]
return battery_charge <= battery.Capacity[i] * 2
# CONSTRAINT - BATTERY CAN'T DISCHARGE IF PRICES ARE NEGATIVE
def negative_discharge_spot(battery, i):
# if the spot price is not positive, suppress discharge
if battery.Price.extract_values_sparse()[None][i] <= 0:
return battery.Discharge_power[i] == 0
# otherwise skip the current constraint
return Constraint.Skip
# CONSTRAINT - CAPACITY RULE
def capacity_constraint(battery, i):
# Assigning battery's starting capacity at the beginning
if i == battery.Period.first():
return battery.Capacity[i] == INITIAL_CAPACITY
# if not update the capacity normally
battery_capacity = (battery.Capacity[i-1] \
+ ((battery.charge_power_intra[i-1] / 2 * EFFICIENCY) \
+ (battery.charge_power_fcr[i-1] / 2 * EFFICIENCY) \
+ (battery.charge_power_afrr[i-1] / 2 * EFFICIENCY) \
+ (battery.charge_power_dah[i-1] / 2 * EFFICIENCY)) \
- ((battery.discharge_power_intra[i-1] / 2) \
+ (battery.discharge_power_fcr[i-1] / 2) \
+ (battery.discharge_power_afrr[i-1] / 2) \
+ (battery.discharge_power_dah[i-1] / 2)))
return battery.Capacity[i] == battery_capacity
# def _p_balance(battery, i):
# return battery.discharge_power_fcr[i] <= 0 | battery.charge_power_fcr[i] <= 0
# Set constraint and objective for the battery
battery.capacity_constraint = Constraint(battery.Period, rule=capacity_constraint)
battery.over_charge = Constraint(battery.Period, rule=over_charge)
battery.over_discharge = Constraint(battery.Period, rule=over_discharge)
battery.negative_discharge = Constraint(battery.Period, rule=negative_discharge_spot)
battery.objective = Objective(rule=maximise_profit, sense=maximize)
# battery._p_balance = Constraint(battery.Period, rule=_p_balance)
# Maximise the objective
opt.solve(battery, tee=False)如果你看看结果,你可以看到,在'FCR‘市场,它是同时充放电。

我试过了:
天真的方法。提供一个OR-条件: def _p_balance(电池,i):返回battery.discharge_power_fcri == 0\ battery.charge_power_fcri == 0
乘数: def _p_balance(电池,i):返回battery.discharge_power_fcri * battery.charge_power_fcri == 0
->这使得这个问题非线性化,而GLPK不支持这个问题.
发布于 2022-10-04 17:33:48
这不是一个完整的答案,但太长,不能发表评论。
你这里没有“电池”的模型。我认为,你有一个4个能源市场的市场模型。
您的代码中没有多少解释性注释,但我认为您有4个市场: IntraDay、Day、FCR、AFRR,每个市场都有相应的价格和成本。因此,你实际上是在建立一个分销系统的模型,如果有一些价格差异来生产你所展示的产品,这将是完全合法的。如果FCR成本低,价格高(在FCR市场和其他市场),您可以大量购买,并在相同的市场或其他市场出售,这似乎正在发生。
所以,如果我们看看你的目标函数,尤指。FCR部分是孤立的,它显示您使用相同的成本值作为两个成本的乘数& rev.。唯一的区别是效率。...And您的效率被设置为1,所以成本是中立的,无论你做什么在FCR市场,所以解决方案提供可能有充放电.OBJ值将与此无关。所以,试着把你的效率稍微改变为<1,我想你会看到(部分)改进。
还有一个nits:您将Capacity[i]作为变量。通常,“容量”是一个固定值,类似于10 is。我会把它重新命名为“控告”或“国家”
当价格是负的时候你不应该限制排放..。OBJ应该为您处理这一问题,我认为效率的变化将消除这一限制。
https://stackoverflow.com/questions/73950740
复制相似问题