如何用CVXPY实现二进制变量与条件约束,避免电池同时充放电
解决离网混合可再生能源系统中电池同时充放电的约束问题
我正在做离网混合可再生能源系统的容量优化配置,现有代码可正常运行并输出结果,但存在电池同时充放电的问题。需要添加约束实现:当充电功率p_c为正时,放电功率p_d必须为0;反之当p_d为正时,p_c必须为0。之前尝试在约束中使用if语句,出现语法错误。
参数定义
""" Parameters for optimization c_0: 弃电权重 c_wt: 风力发电机成本 c_pv: 光伏组件成本 p_N: 电池最大充/放电功率 C_B: 电池最大容量 C_B_low: 电池最低容量 C_0: 电池初始容量 n_d: 放电效率 n_c: 充电效率 """ params = {'c_0': 100, 'c_wt': 1000, 'c_pv': 500, 'p_N': 10000, 'C_B':45000, 'C_B_low':9000, 'C_0':25000, 'n_d':0.9, 'n_c':0.95}
原优化函数代码
### 变量长度、权重及成本为假设值 n = len(p_l) ### 优化变量 s_pvs = cp.Variable(1, integer=True,) s_pvsw = cp.Variable(1, integer=True) s_pvse = cp.Variable(1, integer=True) s_wt = cp.Variable(1, integer=True) # 充电功率 p_c = cp.Variable(n) # 放电功率 p_d = cp.Variable(n) # 电池荷电状态 SOC = cp.Variable(n) # 弃电功率 p_lcurt = cp.Variable(n) ### 目标函数 obj = cp.sum(params["c_0"]*p_lcurt + params["c_wt"]*s_wt + params["c_pv"]*(s_pvs + s_pvsw + s_pvse)) ### 约束条件 constraints = [params["p_N"] >= p_c, p_c >= 0, params["p_N"] >= p_d, p_d >= 0, s_pvs >= 0, s_pvsw >= 0, s_pvse >= 0, s_wt >= 0, p_lcurt >= 0, SOC >= params["C_B_low"], SOC <= params["C_B"], SOC[0] == params["C_0"] + p_c[0]*params["n_c"] - p_d[0]/params["n_d"], SOC[1:] == SOC[:-1] + p_c[1:]*params["n_c"] - p_d[1:]/params["n_d"], s_pvs*p_pvs + s_pvse*p_pvse + s_pvsw*p_pvsw + s_wt*p_wt - p_l + p_lcurt - p_c + p_d == 0] problem = cp.Problem(cp.Minimize(obj), constraints) problem.solve(solver = cp.GLPK_MI, verbose = True) print("s_pvsw:",s_pvsw.value,"s_pvse:",s_pvse.value,"s_pvs:", s_pvs.value,"s_wt:", s_wt.value,"问题解", problem.value) return s_pvsw.value, s_pvse.value, s_pvs.value, s_wt.value, SOC.value, p_lcurt.value, p_d.value, p_c.value
解决方案:添加互斥线性约束
CVXPY等凸优化框架不支持直接在约束中使用if语句(逻辑判断属于非凸操作,无法被线性规划求解器处理),需通过二进制辅助变量+大M法将互斥逻辑转化为线性约束。
修改步骤:
新增二进制辅助变量:定义长度为
n的二进制变量b,每个b[t]取0或1,代表t时刻的操作状态:b[t] = 0:允许充电(或无操作),禁止放电b[t] = 1:允许放电(或无操作),禁止充电
添加互斥约束:利用电池最大充放电功率
params["p_N"]作为大M值,构造约束确保同一时刻p_c和p_d不同时为正。
修改后的完整代码(关键部分标注)
### 变量长度、权重及成本为假设值 n = len(p_l) ### 优化变量 s_pvs = cp.Variable(1, integer=True,) s_pvsw = cp.Variable(1, integer=True) s_pvse = cp.Variable(1, integer=True) s_wt = cp.Variable(1, integer=True) # 充电功率 p_c = cp.Variable(n) # 放电功率 p_d = cp.Variable(n) # 电池荷电状态 SOC = cp.Variable(n) # 弃电功率 p_lcurt = cp.Variable(n) # -------------------------- 新增二进制辅助变量 -------------------------- # 二进制变量:0表示允许充电/无操作,1表示允许放电/无操作 b = cp.Variable(n, boolean=True) # ----------------------------------------------------------------------- ### 目标函数 obj = cp.sum(params["c_0"]*p_lcurt + params["c_wt"]*s_wt + params["c_pv"]*(s_pvs + s_pvsw + s_pvse)) ### 约束条件 constraints = [params["p_N"] >= p_c, p_c >= 0, params["p_N"] >= p_d, p_d >= 0, s_pvs >= 0, s_pvsw >= 0, s_pvse >= 0, s_wt >= 0, p_lcurt >= 0, SOC >= params["C_B_low"], SOC <= params["C_B"], SOC[0] == params["C_0"] + p_c[0]*params["n_c"] - p_d[0]/params["n_d"], SOC[1:] == SOC[:-1] + p_c[1:]*params["n_c"] - p_d[1:]/params["n_d"], s_pvs*p_pvs + s_pvse*p_pvse + s_pvsw*p_pvsw + s_wt*p_wt - p_l + p_lcurt - p_c + p_d == 0, # -------------------------- 新增互斥约束 -------------------------- p_c <= params["p_N"] * (1 - b), p_d <= params["p_N"] * b, # ----------------------------------------------------------------------- ] problem = cp.Problem(cp.Minimize(obj), constraints) problem.solve(solver = cp.GLPK_MI, verbose = True) print("s_pvsw:",s_pvsw.value,"s_pvse:",s_pvse.value,"s_pvs:", s_pvs.value,"s_wt:", s_wt.value,"问题解", problem.value) return s_pvsw.value, s_pvse.value, s_pvs.value, s_wt.value, SOC.value, p_lcurt.value, p_d.value, p_c.value
约束逻辑说明
- 当
b[t] = 1时,p_c[t] <= params["p_N"]*(1-1) = 0,结合p_c >=0的约束,强制p_c[t] = 0,此时p_d[t]可在0到params["p_N"]之间取值。 - 当
b[t] = 0时,p_d[t] <= params["p_N"]*0 =0,结合p_d >=0的约束,强制p_d[t] =0,此时p_c[t]可在0到params["p_N"]之间取值。 - 若
p_c[t]和p_d[t]都为0,b[t]可取0或1,不影响结果。
内容的提问来源于stack exchange,提问作者Frederik Springer
相关产品推荐
相关产品推荐

