基于CVXPY的无功功率凸优化问题SOCP约束改写求助
针对你提出的两个非DCP约束,以下是基于CVXPY cp.SOC 函数的改写方案,完全符合DCP规则:
约束1:凸锥约束改写
原约束形式
V_n[idx_from_combined[l]] * V_n[idx_to_combined[l]] * (np.sin(theta_max))**2 >= theta_l[l]**2
其中 V_n(电压幅值)、theta_l(相角差)为优化变量,theta_max 是常数相角差上限。
改写逻辑
原约束等价于:
$$\theta_l^2 \leq (\sin\theta_{\text{max}})^2 \cdot V_f \cdot V_t$$
($V_f = V_n[\text{idx_from_combined}[l]]$,$V_t = V_n[\text{idx_to_combined}[l]]$)
这是旋转二阶锥的标准形式 $a^2 \leq b \cdot c$($b,c \geq 0$),可转换为CVXPY支持的标准二阶锥(SOC):
$$\left| \begin{bmatrix} 2a \ b - c \end{bmatrix} \right|2 \leq b + c$$
这里令 $a = \theta_l$,$b = V_f \cdot \sin\theta{\text{max}}$,$c = V_t \cdot \sin\theta_{\text{max}}$(因电压幅值非负、$\sin\theta_{\text{max}} > 0$,满足$b,c \geq 0$)。
CVXPY代码实现
import cvxpy as cp import numpy as np sin_theta_max = np.sin(theta_max) Vf = V_n[idx_from_combined[l]] Vt = V_n[idx_to_combined[l]] theta_l_var = theta_l[l] # DCP兼容的SOC约束 constraint1 = cp.SOC(Vf * sin_theta_max + Vt * sin_theta_max, cp.hstack([2 * theta_l_var, Vf * sin_theta_max - Vt * sin_theta_max]))
约束2:旋转SOCP约束改写
原约束形式
Q_ol[l] * V_n[idx_from_combined[l]] >= (cp.sum(cp.square(P_sl[l]) + cp.square(Q_sl[l])))*X_l[l]
其中 Q_ol(支路无功功率)、V_n(电压幅值)、P_sl/Q_sl(节点注入功率)为优化变量,X_l[l] 是支路电抗常数($X_l[l] > 0$)。
改写逻辑
两边除以正的电抗常数 $X_l[l]$,约束等价于:
$$\sum(P_{sl}^2 + Q_{sl}^2) \leq \frac{Q_{ol} \cdot V_f}{X_l[l]}$$
令 $a = \sqrt{\sum(P_{sl}^2 + Q_{sl}^2)}$(注入功率的L2范数),则约束变为旋转二阶锥形式 $a^2 \leq b \cdot c$,其中 $b = Q_{ol}$,$c = \frac{V_f}{X_l[l]}$(需保证 $b \geq 0$、$c \geq 0$,因电压幅值非负、电抗为正,只需额外约束 $Q_{ol} \geq 0$,具体根据问题场景调整)。
转换为标准SOC形式:
$$\left| \begin{bmatrix} 2a \ b - c \end{bmatrix} \right|_2 \leq b + c$$
CVXPY代码实现
X = X_l[l] Vf = V_n[idx_from_combined[l]] Q_ol_var = Q_ol[l] P_sl_var = P_sl[l] Q_sl_var = Q_sl[l] # 计算注入功率的L2范数 S_norm = cp.norm(cp.hstack([P_sl_var, Q_sl_var]), 2) # DCP兼容的SOC约束 constraint2 = cp.SOC(Q_ol_var + (Vf / X), cp.hstack([2 * S_norm, Q_ol_var - (Vf / X)])) # 若问题中Q_ol允许为负,需添加约束确保左边非负:Q_ol_var * Vf >= 0
关键说明
- 所有改写后的约束均符合CVXPY的DCP规则,可直接用于凸优化模型编译。
- 需确保电压幅值等非负变量在模型中添加对应约束(如
V_n >= 0)。 - 若
theta_max对应的正弦值为0(极端情况),需单独处理为theta_l_var == 0。
内容的提问来源于stack exchange,提问作者bens44

