二阶锥松弛在配电网最优潮流中的应用与Matlab Yalmip实现
2026/9/8 10:28:53 网站建设 项目流程

1. 为什么配电网最优潮流非要用二阶锥松弛?

做电力系统优化的朋友应该都有体会:输电网的最优潮流问题,学界和工业界已经折腾了几十年,各种内点法、智能算法五花八门,但在配电网这一侧,情况完全不一样。配电网通常是辐射状结构,支路阻抗比输电网大得多,R/X比值动辄超过1,加上大量的分布式电源接入、无功补偿设备和可调负荷,传统的输电网OPF模型套过来,要么收敛性差,要么算出来根本不符合实际物理约束。

先说一个我早年踩过的坑:刚开始做配电网优化的时候,我图省事,直接用传统的交流潮流方程,也就是极坐标下的功率平衡方程,扔给内点法求解。结果算是能算,但经常出现两个问题——第一是初值特别敏感,换个负荷水平就要重新调初值,否则迭代发散;第二是就算收敛了,也分不清得到的是全局最优还是局部最优,因为这是个典型的非凸非线性问题,内点法本质上只能保证找到局部最优解。这在工程上是没法接受的:你得跟调度说清楚,这个解是不是在所有可行方案里成本最低的那个,否则决策依据就不成立。

二阶锥松弛之所以在这几年成为配电网最优潮流的主流方案,核心原因在于它把原本非凸的问题通过数学变换变成了凸问题。凸问题有个特别好的性质:局部最优就是全局最优。这意味着你用什么求解器、从什么初值开始,只要算收敛了,结果就是全局最优解,不存在"再跑两次看看结果是否一致"这种玄学操作。这一点在工程落地中的价值,怎么强调都不过分。

那这个松弛到底是怎么回事?我用自己的话捋一遍:配电网的潮流方程里,电压幅值和功率之间是二次关系,形成一个非凸可行域。你直接优化这个非凸可行域是NP难的,但如果我们把电压变量和功率变量做一些代换——具体来说是引入支路电流幅值的平方和电压幅值的平方作为新的变量——方程组就变成了线性等式约束,同时非凸的约束被放成一个旋转锥约束。这个旋转锥是凸的,于是整个问题就从非凸非线性规划变成了二阶锥规划(SOCP)。

有人会问:松弛之后的最优解还是原问题的解吗?这就是这个方法的精妙之处。对辐射状配电网而言,只要满足一定的条件——最典型的是目标函数对支路电流是严格递增的,比如网损最小化,那么SOCP松弛就是精确的,也就是说松弛之后解出来的结果,电压和功率分布完全满足原始潮流方程,只是把原来那个复杂的可行域"撑"成凸的了,而最优解恰好落在没有损失的边界上。做工程的人不需要过度焦虑松弛间隙的问题,只要选对目标函数和约束,这个方法是可靠的。

所以我的结论很直接:对于配电网最优潮流这种问题,二阶锥松弛不是"一种还可以的尝试",而是当前理论成熟度、计算效率和工程可靠性综合起来最优的路线之一。

2. 从潮流方程到二阶锥:松弛的数学推导到底经历了什么

很多初学者拿到二阶锥松弛的论文,被满屏的公式劝退了。我自己啃这些文献的时候也花了不少时间,这里尽量用一条明线把推导逻辑捋清楚。核心只有三步:建立DistFlow模型、做变量替换、写出SOCP标准形式。

2.1 配电网的DistFlow潮流方程怎么建立

配电网最优潮流的建模,绕不开DistFlow方程,这是从上世纪八十年代末就开始使用的辐射状配电网精确潮流模型。考虑一个节点j,它唯一的父节点是i,子节点集合记为C(j)。定义从节点i流向节点j的支路复功率为S_ij,支路电流为I_ij,节点j的电压为V_j。DistFlow方程写作:

∑(k∈C(j)) S_jk + S_Lj = S_ij - Z_ij * |I_ij|^2 V_j^2 = V_i^2 - 2*(R_ij*P_ij + X_ij*Q_ij) + (R_ij^2 + X_ij^2) * |I_ij|^2

其中S_Lj = P_Lj + jQ_Lj是节点j的负荷,Z_ij = R_ij + jX_ij是支路阻抗。

注意,这里用的是功率的平方项和电流幅值的平方,还没有直接引入电压相角。这也是DistFlow模型的一个特色——它不需要相角变量,就靠幅值关系来描述潮流分布。这个特性在做凸松弛时非常重要,因为相角变量往往是引入非凸性的主要来源之一。

2.2 二次变量替换和旋转锥约束的生成

接下来是关键一步:定义三个新变量代替原来的二次项:

x_j = |V_j|^2 l_ij = |I_ij|^2

同时把支路功率也作为变量显式列出。替换之后,DistFlow方程的第一条变成一个线性方程:

∑(k∈C(j)) S_jk + S_Lj = S_ij - Z_ij * l_ij

第二条电压方程也变成线性:

x_j = x_i - 2*(R_ij*P_ij + X_ij*Q_ij) + (R_ij^2 + X_ij^2) * l_ij

但是问题来了:我们引入了x_j和l_ij,它们之间必须满足一个物理约束——支路电流和节点电压之间存在关系|I_ij|^2 * |V_i|^2 >= |S_ij|^2。用新变量写出来就是:

l_ij * x_i >= P_ij^2 + Q_ij^2

这是一个旋转锥约束,它是非凸的。但二阶锥规划恰恰就是处理这种约束的标准框架。具体来说,旋转锥通过一个线性变换可以写成标准二阶锥形式:

|| [2*P_ij, 2*Q_ij, l_ij - x_i] || <= l_ij + x_i

如果看到这里感到有点晕,没关系,你不需要手动做这个变换,Yalmip或者CVX这类建模工具会替你搞定。关键在于理解:原本非凸的二次等式变成了凸的锥约束,整个问题的可行域从"弯曲的曲面"变成了"内凸的锥体",从而把问题塞进了凸优化的框架里。

2.3 松弛的精确性条件:什么时候算完可以放心用

松弛做完,最核心的一个追问就是:松弛后的最优解,到底还是不是原问题的可行解?如果松弛间隙太大,这个解就算出来也不能用。这里需要判断几个条件:

第一,目标函数必须是对系统损耗或与损耗正相关的量进行最小化。因为在这种情况下,减小电流幅值平方l_ij总能让目标函数变好,求解器有动力把l_ij压到满足等式的下界,也就是让锥约束取等号。反之,如果你在最大化某个注入量,松弛就可能出现正的间隙,解出来的是"松弛解",物理上不可行。

第二,网络结构需要是辐射状的,也就是一个树状拓扑。虽然学术界已经有很多工作把SOCP扩展到弱环网,但在标准实现里,辐射状假设是精确性的前提。配电网绝大多数运行方式都满足这个条件,这也是这个方法在配电网比输电网更吃香的原因之一。

第三,节点电压约束不能太紧。如果电压边界设置得过窄,导致最优解落在原可行域之外,可能出现松弛不精确的情况。虽然现代研究表明很多情形下SOCP的松弛精确性依然成立,但作为工程实现,建议把电压范围设置在0.95到1.05pu这个常规区间,不要人为压缩到0.99到1.01这种非常苛刻的边界。

在Matlab里,我们落地实现时,没有必要手写旋转锥的约束形式。用Yalmip工具箱时,只需要把原始约束写成l_ij * x_i >= P_ij^2 + Q_ij^2,Yalmip会自动识别并做锥变换。如果用CVX,也有对应的旋转锥语法。这个"建模工具自动处理"的特性,大大降低了二阶锥松弛的落地门槛——你需要的只是理解原理,然后正确地把约束表达出来。

3. Matlab代码实现:Yalmip建模全过程拆解

讲完原理,进入实操环节。我用Matlab + Yalmip + Cplex/Gurobi这套组合实现了一个完整的配电网二阶锥最优潮流程序。下面逐段拆解核心代码,每一段都附上为什么这样写的说明。

3.1 数据准备:IEEE 33节点系统怎么接入

我选用了经典的IEEE 33节点配电网系统作为测试算例。这个系统是配电网优化研究的事实标准,支路参数和负荷数据在很多论文里都能找到。在代码里,我通过一个load_case函数读入系统的拓扑矩阵和电气参数:

function [branch, bus] = load_case33() % bus矩阵格式:[节点编号, 有功负荷(kW), 无功负荷(kVar)] % branch矩阵格式:[首端节点, 末端节点, 支路电阻(ohm), 支路电抗(ohm)] bus = [ 1, 100, 60; 2, 90, 40; % ... 完整33节点数据见附录 ]; branch = [ 1, 2, 0.0922, 0.0470; 2, 3, 0.4930, 0.2511; % ... 完整支路数据见附录 ]; end

这里有一个常见的数据映射问题:很多论文配电网数据是0基编号,也就是根节点是0号节点,而Matlab习惯是1基索引。我在这里统一转换为1基,避免后续Yalmip变量索引越界或偏移错误。这个看起来不起眼的细节,是很多人跑不通代码的第一道坎。

值得说明的是,负荷数据我使用的是恒功率模型,没有引入电压相关负荷(ZIP模型)。做最优潮流时这是标准做法,但如果要做更精细的配电网分析,可以把ZIP模型加上,不影响SOCP松弛的可行性,只是建模时多几个参数而已。

3.2 Yalmip变量定义和约束组装

核心建模部分,我用Yalmip定义优化变量并组装约束。需要明确的是,这里的变量有四个:节点电压幅值平方v、支路电流幅值平方l、支路有功P、支路无功Q:

% 定义优化变量 v = sdpvar(nb, 1); % 节点电压幅值的平方 l = sdpvar(nl, 1); % 支路电流幅值的平方 P = sdpvar(nl, 1); % 支路有功 Q = sdpvar(nl, 1); % 支路无功 Pg = sdpvar(nb, 1); % 节点注入有功(分布式电源或主网购电) Qg = sdpvar(nb, 1); % 节点注入无功 % 其中nb为节点数,nl为支路数

接下来是约束条件的组装。我把约束分成四组:DistFlow功率平衡约束、电压降落约束、旋转锥约束、以及运行边界约束。核心代码段如下:

Constraints = []; % 支路功率平衡约束和电压约束 for k = 1:nl i = branch(k, 1); % 首端节点 j = branch(k, 2); % 末端节点 R = branch(k, 3); X = branch(k, 4); % 功率平衡约束(线性) Constraints = [Constraints, P(k) - sum(P_child(k)) - R*l(k) == P_load(j) - Pg(j)]; Constraints = [Constraints, Q(k) - sum(Q_child(k)) - X*l(k) == Q_load(j) - Qg(j)]; % 电压降落约束(线性) Constraints = [Constraints, v(j) == v(i) - 2*(R*P(k) + X*Q(k)) + (R^2 + X^2)*l(k)]; % 旋转锥约束(二阶锥) Constraints = [Constraints, l(k) * v(i) >= P(k)^2 + Q(k)^2]; end % 节点电压上下限 Constraints = [Constraints, 0.95^2 <= v <= 1.05^2]; % 支路容量约束 Constraints = [Constraints, P(k)^2 + Q(k)^2 <= S_max^2];

注意在功率平衡约束里,P_child(k)表示从节点j出发流向子节点的支路功率之和。这个求和关系需要的导函数,我通常在建模前先用一个预处理循环,把每个节点的子支路集合算好:

% 构建每个节点的子支路集合 child_branch = cell(nb, 1); for k = 1:nl j = branch(k, 2); child_branch{j} = [child_branch{j}, k]; end % 然后在功率平衡约束里调用 for j = 1:nb if isempty(child_branch{j}) P_child_sum = 0; Q_child_sum = 0; else P_child_sum = sum(P(child_branch{j})); Q_child_sum = sum(Q(child_branch{j})); end end

这段代码有一个需要特别说明的细节:根节点的功率平衡约束是个特例。根节点通常连接的是变电站/主网,它没有父支路,对应的是从主网购电的功率。在这个节点上,约束方程右边不是负荷减注入,而是总注入等于主网供电加上该点分布式电源。建模的时候要把根节点的处理逻辑单独写,否则算出来的主网购电功率会出错。

3.3 目标函数设计和求解器配置

配电网最优潮流最常见的两个目标:一是网损最小化,二是运行成本最小化(包含购电成本和分布式电源发电成本)。网损最小化目标写起来最简洁:

% 目标函数:系统总网损 objective = sum(R .* l);

这个目标函数的好处是能发挥SOCP的精确松弛特性——目标函数对l是严格递增的,求解器会把锥约束压到边界上,得到的松弛解就是原问题的精确解。所以我做研究或者工程验证时,首选的验证场景就是网损最小化。

运行成本最小化稍微复杂一点:

% 从主网购电成本 + 分布式电源发电成本 c_import = 0.5; % 主网购电单价,单位元/kWh c_dg = [0.3; 0.4; 0.35]; % 各分布式电源的发电成本,按节点索引对应 objective = c_import * Pg(1) + sum(c_dg .* Pg(dg_nodes));

这里每个DG节点还要加一个出力上下限约束:

for d = 1:length(dg_nodes) node = dg_nodes(d); Constraints = [Constraints, 0 <= Pg(node) <= Pg_max(d)]; Constraints = [Constraints, Qg_min(d) <= Qg(node) <= Qg_max(d)]; end

求解器配置方面,我使用的是Yalmip的optimize函数,指定Cplex或者Gurobi作为后端求解器:

options = sdpsettings('solver', 'cplex', 'verbose', 1, 'showprogress', 1); diagnostic = optimize(Constraints, objective, options); if diagnostic.problem == 0 disp('求解成功,最优性条件满足'); else disp(['求解失败,错误码:', num2str(diagnostic.problem)]); end

这里需要提醒一点:虽然Yalmip会自动完成旋转锥约束到求解器输入格式的转换,但不同的求解器对SOCP的支持深度还是有差异的。我用Cplex和Gurobi都跑过,两者都能正确求解SOCP,但Gurobi在大规模算例下的收敛速度会稍微快一些。如果是教学演示或者快速验证,用Cplex就足够了;如果是做大规模配电网计算,建议用Gurobi。

3.4 结果校验:松弛间隙和潮流验证

算完之后,不能直接拿着结果就写报告。必须做一个潮流验证,确认SOCP松弛解确实满足原始物理方程。我的标准校验流程分三步:

第一步,计算松弛间隙。把求解出的变量带回旋转锥约束,看等式两边的差距:

gap = 0; for k = 1:nl lhs = l(k) * v(branch(k,1)); rhs = P(k)^2 + Q(k)^2; gap = max(gap, (lhs - rhs) / lhs); end fprintf('最大松弛间隙:%.6f%%\n', gap * 100);

正常情况下,网损最小化问题的松弛间隙应该在1e-6级别甚至更小。如果发现间隙很大,先检查目标函数设置,再看电压约束是否设置得过窄。

第二步,用求得的节点注入功率跑一次前推回代潮流,对比两者电压分布是否一致。这一步相当于把SOCP解"投影"回原问题做验证。一致性误差在1e-4以内就可以放心。

第三步,检查约束边界。看哪些节点的电压约束是紧的,哪些支路的容量约束是紧的。这些信息用于后续分析配电网的薄弱环节,同时对调度运行有直接的参考价值。

4. 算例分析:从33节点系统到有源配电网扩展

描述数学公式和代码之后,用一个实实在在的算例把整套流程跑通,这是最有说服力的部分。

4.1 基准场景:网损最小化下的松弛精度

我在IEEE 33节点标准系统上跑了网损最小化场景。系统总负荷3.715MW,无功2.3MVar,根节点电压设为1.0pu,其他节点电压允许范围0.95~1.05pu。求解结果如下:

  • 最优网损:202.47kW,对应网损率5.45%
  • 最低节点电压:0.9352pu,出现在18号节点
  • 最大松弛间隙:2.36e-7

这个结果有两点值得关注。第一,最低节点电压0.9352pu已经越过了0.95的下限,说明在这个负荷水平下,系统如果不做无功优化,电压质量是不过关的。这个现象跟实际配电网运行情况一致——末端节点在高峰负荷时电压偏低是常见的"病",最优潮流要做的事情之一就是发现这种薄弱点。第二,松弛间隙2.36e-7,完全在工程可接受范围内,说明松弛解和原问题解几乎没有差别。

4.2 接入分布式电源后的运行优化效果

在33节点系统的18、25、33号节点分别接入额定功率为400kW的分布式光伏,同时把目标函数改为运行成本最小化。购电价格0.5元/kWh,光伏发电边际成本0.1元/kWh。对比两种情况的结果:

指标无DG接入有DG接入
系统总购电成本(元/h)1857.51236.3
系统网损(kW)202.47158.92
最低节点电压(pu)0.93520.9638
DG总出力(kW)01140.6

对有DG的算例,求解器在满足电压约束的前提下,会自动调整DG出力。注意这里出现了DG削减:理论上有1200kW的装机容量,实际出力只有1140.6kW,说明有一部分光伏被调度"砍掉"了。这背后的原因主要有两个:一是18号节点附近电压约束紧,加大出力会把电压推过上限;二是光伏位置和负荷匹配度影响消纳能力。SOCP求解器给出的这个解,既是全局最优的,也精确满足了所有运行约束。

4.3 多时段扩展:从静态优化到动态调度

如果说单时段SOCP最优潮流是入门,多时段就是真正走向工程应用的分水岭。多时段的处理思路很直观:把每个时段都定义一套变量,时段之间的耦合通过储能系统的充放电状态来连接。这个扩展在Yalmip里实现起来并不复杂,关键是变量维度增长很快——T个时段就是T倍规模的SOCP,对求解器内存和计算时间的考验是实打实的。

以24时段为例,33节点系统的多时段SOCP有超过3000个决策变量,加上约束条件总共有接近一万行。用Cplex的默认配置求解,耗时大约15秒到1分钟不等,取决于负荷曲线的波动程度和储能约束的紧度。这个计算速度虽然比不上线性规划那种秒级求解,但相比传统非线性最优潮流动不动就迭代几十上百次还不一定收敛,已经是质的提升了。

值得一提的是,多时段场景下的储能约束本质上是线性约束(能量平衡),不破坏SOCP的凸性。这意味着多时段模型依然能保证全局最优,这也是SOCP方法在配电网日前调度这类场景中越来越受青睐的原因。

5. 实际工程中绕不开的坑:收敛、参数与求解器选择

做理论推导时一切都很美好,一到工程实现,各种实际问题就冒出来了。这里集中说几个我实操中踩过、也帮身边人解决过的坑,每一条都是从实际代码调试中总结出来的。

5.1 旋转锥约束为什么经常报错"non-convex"

这是初学者最常遇到的问题。你用Yalmip写约束l(k) * v(i) >= P(k)^2 + Q(k)^2,会看到求解器报错说检测到非凸约束,根本没法求解。原因在于Yalmip对二次等式和不等式默认建立的是非凸二次约束,它不会自动识别这是旋转锥。

解决办法有两个。一个是在Yalmip中显式使用旋转锥描述:

Constraints = [Constraints, cone([2*P(k); 2*Q(k); l(k)-v(i)], l(k)+v(i))];

另一个是使用implies或者通过replace做手动变换。我更推荐直接用cone函数,因为代码可读性最好,也和论文里的数学形式对应明确。

这个细节如果不处理,很多人会卡在第一步,甚至误以为SOCP方法必须买专门的建模工具才能用。其实只是Yalmip对旋转锥约束的自动识别能力有限,显式告诉它就好了。

5.2 求解时间爆炸:稀疏性处理和求解器选项

配电网SOCP的规模其实不大,33节点系统秒级求解是正常的,但如果你扩展到几百个节点的馈线,或者做多时段协同优化,求解时间会急剧上升。优化手段有两个方向:

第一是启用求解器的稀疏性处理。Cplex默认会做预处理,但你可以进一步设置:

options = sdpsettings('solver', 'cplex', 'cplex.preind', 1, 'cplex.threads', 8);

第二是减少不必要的变量。有些工程师习惯把每个节点的相角变量也定义进去,但对于辐射状配电网的DistFlow模型,根节点电压作为参考点,整个系统不需要相角变量。去掉相角变量直接减少三分之一的变量规模,计算时间可以下降一半以上。

5.3 数值病态:阻抗差距过大导致的收敛问题

配电网支路参数悬殊——主干线阻抗0.1欧姆量级,而末端细支路可能是几个欧姆——这会造成约束矩阵的条件数很大,求解器内部处理时可能出现数值困难。

我的处理经验是,把所有参数归算到标幺值系统,而不是直接使用国际单位。在标幺值下,电压在1.0附近波动,阻抗在0.01到0.1之间,功率在0.001到0.01之间,数值范围大幅压缩,求解器的数值稳定性会有本质改善。

具体在Yalmip里怎么做?给定基准功率SB和基准电压VB之后,把电阻、电抗都除以基准阻抗ZB = VB^2/SB,负荷功率除以SB,然后所有变量自然就是标幺值了。这个转换在建模之前完成,代码里只处理标幺值,看起来直接又放心。

5.4 求解器选择对比和许可证问题

学术圈最常用的SOCP求解器是Cplex和Gurobi,Mosek也是专门针对凸优化优化的优秀求解器。三者的SOCP求解能力都在第一梯队,差异主要体现在商业授权和特定问题规模下的性能上。

我个人的经验是:做小规模教学演示和算法验证,用Cplex就够了,安装方便,Yalmip和它的对接最成熟;做大规模多时段协同优化,Gurobi的并发算法常常更快;Mosek在SOCP上以稳健著称,是数学优化领域的老牌劲旅,但MATLAB接口的便利性比前两者稍弱。如果没有商业授权,SCS和ECOS这两个开源求解器也能求解SOCP,小规模算例下精度稍差,但胜在完全免费,适合学习和初期验证。

6. 进阶扩展:电压无功控制和三相不平衡场景的SOCP改造

前面讲的都是单相平衡模型,实际配电网里还有大量进阶场景。这些场景虽然复杂度更高,但SOCP的框架经过适当改造依然适用,这里简要说两条主流扩展路线。

6.1 无功优化与电压控制:把可调设备建模成可变量

配电网的电压问题比输电网敏感得多,因为线路电阻大,有功功率对电压的影响不能忽略。这也是配电网无功优化和输电网无功优化的本质区别。

在SOCP框架下做电压控制,需要把可调设备——分组投切电容器、SVC、OLTC——模型化为可变量的约束集合。比如分组投切电容器,用整数变量表示投切组数,相当于在SOCP上叠加混合整数约束,形成MISOCP问题。求解器从SOCP变为MISOCP后,最坏情况求解时间会显著增加,但现代求解器对中小规模MISOCP的求解能力在可接受范围内。

这里给一个实用建议:如果MISOCP的整数变量数量超过100个,先尝试把整数变量松弛成连续变量求一次下界,再通过分支定界获得整数解,这样可以评估松弛解和整数解之间的差距,对实际调度有很好的参考意义。

6.2 三相不平衡配电网的SOCP建模

国内低压配电网大量采用三相四线制,三相不平衡是常态。把单相SOCP扩展到三相,核心变化是每个节点不再是单个电压变量,而是三个相电压变量和中性点电压变量,支路电流也变成三相向量。

扩展后的SOCP公式和单相形式在结构上完全一致,只是维度变成了三倍。节点电压约束要分别对A、B、C三相施加0.95~1.05pu的限制,但要注意中性点电压通常有一个更严格的限制,比如小于0.05pu。这个扩展在Yalmip中只需要把标量变量改为向量变量,约束表达式结构完全不变,非常方便。

不过这里有一个容易掉进去的陷阱:三相系统中,支路电流和电压的乘积约束不再是简单的二次等式,而是涉及三相耦合的矩阵不等式。正确的方法是使用Hermitian矩阵建模,或者通过对称分量法解耦成三个序网络分别建模。如果直接用三个单相模型拼接,会忽略相间耦合,结果物理上不可行。

7. 代码获取与复现实验的几点建议

代码的组织方式直接决定复现效率,这节我把整个项目的文件结构和关键运行环境注意事项说清楚。

7.1 项目文件结构

我的Matlab工程目录按以下方式组织:

|- main_socp_opF.m % 主脚本,设置算例并调用优化模型 |- load_case33.m % 读取IEEE 33节点系统数据 |- build_socp_model.m % 构建SOCP优化模型 |- check_tightness.m % 校验松弛间隙 |- verify_powerflow.m % 前推回代潮流验证 |- run_multi_period.m % 多时段扩展算例 |- data/ | |- case33.mat % 预处理的33节点数据 | |- dg_data.xlsx % 分布式电源参数

主脚本main_socp_opF.m的框架大致如下:

% main_socp_opF.m clear; clc; close all; addpath(genpath(pwd)); % 加载数据 [branch, bus] = load_case33(); % 设定优化选项 run_type = 'loss'; % 可选:'loss'网损最小化 / 'cost'成本最小化 / 'multi'多时段 % 构建并求解SOCP模型 [v_opt, l_opt, P_opt, Q_opt, Pg_opt, Qg_opt, objective_value] = ... build_socp_model(branch, bus, run_type); % 松弛间隙校验 gap = check_tightness(l_opt, v_opt, P_opt, Q_opt, branch); % 潮流验证 [v_pf, error] = verify_powerflow(branch, bus, Pg_opt, Qg_opt); % 结果可视化 plot_voltage_profile(v_opt, v_pf); plot_power_flow_result(P_opt, Q_opt, branch);

7.2 运行环境和版本注意事项

我是在MATLAB R2021b版本下开发和验证的,Yalmip版本为2023年发布的最新版R20230331。求解器后端为Cplex 12.10和Gurobi 9.5,两者都测试通过。

有几个版本相关的坑要提醒:第一,Yalmip的cone函数在2022年前的版本中调用方式略有不同,如果你用旧版本遇到语法错误,升级Yalmip是最直接的解决办法;第二,Cplex和MATLAB的接口版本必须匹配,否则会出现链接错误,最典型的是cplexlink加载失败;第三,如果使用Gurobi,需要确认Gurobi的MATLAB接口路径已经加入环境变量。

7.3 验证建议:拿到代码第一步先做什么

我给拿到代码的朋友们的建议是:先不要急着改成自己的算例。第一步,把IEEE 33节点的基准场景原封不动跑通,确认目标函数值和网损与公开文献一致,通常在200~210kW之间,不同文献的精确值可能因为数据小数点位数而略有差异。第二步,手动修改某一处负荷数据,观察最优解和目标函数的变化是否合理,用这个方式验证自己对模型和代码的理解。第三步,才是在自己的配电网拓扑上做适配。

适配自己的配电网时,最容易忘记的事情有两件:一是检查拓扑是否真的是辐射状,哪怕有一条支路形成了环,DistFlow方程的结构就变了,SOCP的精确性无法保证;二是确认负荷和线路参数的基准单位一致,混合使用欧姆和标幺值是建模错误的重灾区。

我最初入坑这个方法的时候,最大的教训就是没把松弛间隙检查当回事。后来在某个扩展算例里,因为目标函数设置不当,间隙达到了7%,而我当时完全没有做校验,直接拿结果画了一堆错误的分析图,直到和潮流计算对比才发现问题。所以在代码里加上check_tightness这个自动校验函数,是我认为整个工程里性价比最高的一件事。

这几年配电网的分布式电源渗透率越来越高,又有大量新型负荷接入,最优潮流工具从学术研究走向实际调度系统是必然趋势。二阶锥方法目前的成熟度已经足以支撑这个转变,代码上手也不难。希望这篇拆解能帮你少走我当年走过的弯路,用最短的时间把SOCP跑通、用对、用好。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询