
前阵子帮几个做配电网规划的朋友审程序发现一个很有意思的现象很多人一提到分布式电源优化配置第一反应就是上智能算法——粒子群、遗传算法轮番上把网损、电压、成本全塞进适应度函数里跑个几千代碰运气。倒不是说启发式算法没用而是这个问题的数学结构明明可以写得非常干净潮流约束经过二阶锥松弛之后配上 MATLABYALMIP 建模用 CPLEX 或 Gurobi 这种商业求解器几十秒内就能拿到带最优性证明的解。分布式电源优化配置 二阶锥 编程方法这套组合正是目前配电网规划论文和工程可研里最主流、也最值得掌握的技术路线。这篇文章就从一个实际可跑的算例出发把完整链路走一遍为什么要用二阶锥、DistFlow 潮流方程怎么一步步松弛成锥约束、MATLABYALMIP 里怎么写、CPLEX/Gurobi 怎么调以及我在这条路上踩过的坑。无论你是刚接触配电网优化的研究生还是被智能算法坑过、想换个严谨求解方案的工程师这篇文章应该都能让你少走不少弯路。1. 为什么分布式电源优化配置会写成二阶锥1.1 分布式电源配置到底在优化什么分布式电源优化配置通俗说就是回答两个问题分布式电源装在哪里装多大。这里面既可能包含光伏、风电这类间歇性电源也可能包含燃气轮机、储能等可调度资源。配好了可以降低网损、改善电压分布、延缓配电网扩容配得不好轻则网损不变甚至上升重则引起节点电压越限、线路过载、逆潮流倒送等一堆麻烦。一个完整的优化配置模型目标函数常见的做法是这几种年综合费用最小包含 DG 投资成本、运行维护成本、网损费用有时还加上购电费用系统有功网损最小节点电压偏差最小或以上多个目标的加权组合。约束条件则至少包含潮流约束、节点电压上下限约束、支路电流上限约束、DG 安装容量上限约束。如果还考虑了 DG 的选址问题那就会引入 0-1 整数变量——某个节点建不建 DG——模型就会从纯连续优化升级为混合整数优化。我在这篇文章里主线采用网损最小作为目标同时把DG 是否安装这个 0-1 决策放进去。这样既能让读者理解 SOCP 松弛的核心又能完整演示混合整数二阶锥规划MISOCP在 YALMIP 里的写法。等你掌握了这个框架想换成年综合费用目标或者加时序场景都是改目标函数和约束集的问题不用推翻重来。1.2 潮流约束的非凸性让求解变得尴尬很多人一开始会想既然要做规划那我直接用牛顿-拉夫逊法求解交流潮流再套一层粒子群、遗传算法去搜 DG 位置和容量不就行了这个思路没有错但问题在于非线性的交流潮流方程是非凸的。非凸意味着什么意味着整个可行域可能有大量局部极值点启发式算法只能保证找到一个可行解无法证明这个解离全局最优有多远。运气好的时候找到的解挺漂亮运气不好就只能在论文里画一张收敛曲线自我安慰。更麻烦的是外层智能算法每评估一个粒子都要跑一次完整潮流算 33 节点可能还行一旦扩展到 100 节点、多场景、多时段计算量会迅速爆炸。而二阶锥规划SOCP不一样。SOCP 是一种特殊的凸优化问题可行域是凸的局部最优就是全局最优。再加上 CPLEX、Gurobi 这类商业求解器采用分支定界法处理整数变量配合线性松弛可以在有限时间内给出全局最优解并附带最优性间隙MIP Gap。在工程可研里你能给业主一个这个解离最优解偏差不超过 0.1%的量化保证这比启发式算法的一句算法收敛到最优要硬气得多。1.3 为什么偏偏是二阶锥而不是线性规划既然凸优化这么好那直接用线性规划LP简化潮流不更省事这就要看你要什么精度的潮流模型了。线性化的潮流模型比如忽略网损的 DistFlow 线性形式处理规划问题非常快但它把网损项直接丢掉了——而你优化目标恰恰就是网损这会陷入一个逻辑矛盾你想降低的东西在你的模型里根本不存在。此外线性潮流在电压偏差较大、DG 渗透率较高时误差会明显变大。二阶锥的好处在于它保留了潮流方程里最关键的非线性项 ——有功无功的平方项 —— 但不让这个非线性项破坏凸性。它是精确性和可解性之间一个非常合适的平衡点。对于辐射状配电网DistFlow 潮流方程经过变量替换和凸松弛后可以严格转换成二阶锥形式。在绝大部分实际场景下这个松弛是精确的也就是解出来的结果和原交流潮流模型几乎等价。这一点在后面的推导里你会看得很清楚。这里顺手整理了一个求解器的对比方便大家做技术选型求解器支持 SOCP支持整数变量MATLAB 接口备注Gurobi支持支持MISOCP自带gurobi_setup.m一步配置求解速度快学术界/工业界都很流行CPLEX支持支持MISOCP需安装配套接口老牌稳健文档多节点和割平面参数细MOSEK支持支持自带SOCP 内点法很强整数能力一般ECOS支持不支持YALMIP 内置免费连续 SOCP 完全够用SCS支持不支持YALMIP 内置免费大规模问题表现好Sedumi / SDPT3支持不支持YALMIP 内置传统半定/SOC 求解器速度一般如果模型里没有 0-1 整数变量那么免费的 ECOS、SCS 完全可以跑完连续 SOCP一旦加入节点装不装 DG这种选址变量就变成 MISOCP还是老老实实上 Gurobi 或 CPLEX 吧。2. DistFlow 潮流方程的凸松弛推导2.1 先认识 DistFlow辐射网的潮流专用方程要做配电网优化一般不用交流潮流的一般形式节点导纳矩阵那个而是用DistFlow 支路潮流方程。它的核心假设很贴合配电网辐射状结构根节点是变电站潮流逐级向外流动忽略支路对地电容并把电压相角的影响用较小的误差换掉。对每条支路i - jDistFlow 用四个变量描述潮流P_ij从节点 i 流向节点 j 的有功功率支路首端功率Q_ij从节点 i 流向节点 j 的无功功率U_i节点 i 的电压幅值平方即U_i V_i^2L_ij支路 ij 的电流幅值平方即L_ij I_ij^2标准 DistFlow 方程组如下P_ij - r_ij * L_ij sum(P_jk) P_load_j - P_DG_j Q_ij - x_ij * L_ij sum(Q_jk) Q_load_j - Q_DG_j U_j U_i - 2 * ( r_ij * P_ij x_ij * Q_ij ) ( r_ij^2 x_ij^2 ) * L_ij其中r_ij、x_ij是支路电阻和电抗sum(P_jk)表示从节点 j 流向它所有子节点的有功之和。第一个方程是节点有功平衡第二个是节点无功平衡第三个是电压降落方程。这三条都是线性的所以 DistFlow 的非线性只来自最后一个变量关系。2.2 DistFlow 唯一的非线性项来自电流的定义交流电路里电流、功率和电压还有一层天然约束I_ij^2 ( P_ij^2 Q_ij^2 ) / V_i^2用我们定义的变量替换就是L_ij ( P_ij^2 Q_ij^2 ) / U_i这是一个等式约束而且P^2 Q^2除U的形式是一个非凸约束。问题就出在这里。如果直接把这个约束丢给求解器整个模型就回到非凸非线性规划的老路上无法保证全局最优。二阶锥松弛的做法就是把这个等式约束放宽成不等式L_ij ( P_ij^2 Q_ij^2 ) / U_i注意这个放宽的方向是精心选择的原本等于现在允许大于等于。也就是说模型允许电流幅值平方比实际需要的功率/电压比值更大。听起来像是放水但关键在于目标函数是网损最小网损和 L 直接成正比所以优化器会本能地把 L 压到最小。只要没有其他约束拦着最优解里的 L 就会贴在不等式边界上也就是取等号。于是松弛问题和原问题在最优解处等价。2.3 把不等式写成一目了然的二阶锥标准式L (P^2 Q^2) / U虽然直观但要直接进入求解器最好写成一阶形式的标准二阶锥约束。整理一下L * U P^2 Q^2这个式子两边一乘看起来仍然不是锥。标准二阶锥的形式是|| [x; y] ||_2 z。对上面的约束做一个恒等变形4 * ( P^2 Q^2 ) (U - L)^2 (U L)^2展开化简就能得到|| [ 2P ; 2Q ; U - L ] ||_2 U L这才是 YALMIP 里可以直接用的标准形式。如果你用cone()函数写出来就是cone([2*P; 2*Q; U_fb - L], U_fb L)cone()在 YALMIP 里定义的是norm(x, 2) y其中第一个参数是列向量第二个参数是标量。这一句就完整表达了两条支路潮流约束的组合关系非常干净。到这里DistFlow 的四条方程里三条是线性的最后一条被松弛成了二阶锥约束。整个配电网潮流模型就变成了一个凸的 SOCP 模型。如果再加上 DG 选址的 0-1 变量就是 MISOCP。2.4 完整数学模型长什么样把上面推导的方程拼起来得到一个可用于编程的完整模型。我用最常用的网损最小目标来展示目标函数min J sum( r_ij * L_ij )考虑投资成本时可以直接在后面加一项alpha * sum(C_dg_i * S_dg_i)其中 alpha 是网损费用和投资费用的权重系数。约束条件约束类别数学形式说明节点有功平衡P_ij - r_ij * L_ij sum(P_jk) P_load_j - P_DG_j流入功率减去支路损耗等于负荷加流出功率节点无功平衡Q_ij - x_ij * L_ij sum(Q_jk) Q_load_j - Q_DG_j无功同理电压降落U_j U_i - 2*(r_ij*P_ij x_ij*Q_ij) (r_ij^2 x_ij^2)*L_ij线性方程电流定义松弛根节点电压U_1 1变电站母线电压设为 1 pu 标幺值电压上下限U_min U_i U_max一般取 0.95^2 ~ 1.05^2DG 出力上限0 P_DG_i S_DG_i有功不能超过配置容量DG 无功上限Q_DG_i P_DG_i * tan(acos(pf))按功率因数约 0.9 折算DG 安装决策0 S_DG_i S_max * x_ix_i ∈ {0,1}只有 x_i1 的节点允许装 DGDG 总容量上限sum(S_DG_i) S_total_max按并网批复或消纳能力约束给变量符号做个统一约定编程时就不会乱符号含义单位标幺P_ij/Q_ij支路首端有功/无功puU_i节点电压幅值平方pu^2L_ij支路电流幅值平方pu^2S_DG_i节点 i 的 DG 配置容量pux_i节点 i 是否安装 DG0/1P_load_i/Q_load_i节点负荷pu3. MATLAB YALMIP CPLEX/Gurobi 的工程落地3.1 环境版本和安装避坑先说版本。理论上 MATLAB R2019b 及以上都可以YALMIP 目前仍在活跃更新直接在yalmip.github.io下载最新压缩包解压后addpath(genpath(yalmip文件夹))再savepath保存路径即可。这种直接从官网拉源码的方式比很多来路不明的网盘资源靠谱得多。求解器的安装是大多数人卡壳的地方。Gurobi 相对省心安装 Gurobi 后在 MATLAB 里运行 Gurobi 安装目录下自带的gurobi_setup.m把接口加到 MATLAB 路径然后yalmiptest就能检测到。CPLEX 则需要 IBM 的安装包并配好对应 MATLAB 版本的接口。很多老版本 CPLEX 的 mex 文件会因为 MATLAB 版本升级而失效这时要么换新版 CPLEX要么在 MATLAB 当前版本的支持矩阵里找对应接口。我个人的建议是如果新项目没有历史包袱优先选 Gurobi如果是和已有 CPLEX 论文代码对比才用 CPLEX。两者的 MISOCP 求解能力都在第一梯队但 Gurobi 的授权和安装流程对 MATLAB 用户更友好。有个容易被忽略的点如果没有商业求解器授权可以在 YALMIP 里先用sdpsettings(solver,ecos)或solver,scs跑连续 SOCP 问题练手。ECOS/SCS 都是免费开源求解器而且 YALMIP 内置了接口配置文件路径都不需要自己配。但一旦模型带整数变量免费求解器能处理的规模和数据稳定性都很有限还是要回到商业求解器上来。3.2 算例数据准备IEEE 33 节点系统和标幺化我用的是电力系统优化里最常见、也最轻量的IEEE 33 节点辐射状配电网。如果你电脑里有 MATPOWER可以直接加载它自带的case33bw数据mpc loadcase(case33bw); baseMVA mpc.baseMVA; % 基准功率一般 10 MVA bus mpc.bus; branch mpc.branch;这里有一个非常重要的细节MATPOWER 的 branch 数据里电阻电抗单位是欧姆不是标幺值。节点电压倒是已经给了标幺值形式所以潮流计算里电压直接可以用但阻抗必须做标幺化换算% 基准阻抗 V_base_kV bus(1, 11); % 基准电压case33bw 里是 12.66 kV Z_base V_base_kV^2 / baseMVA; % Z_base 12.66^2 / 10 ≈ 16.03 欧姆 r_pu branch(:, 3) / Z_base; % 支路电阻标幺值 x_pu branch(:, 4) / Z_base; % 支路电抗标幺值 P_load bus(:, 3) / baseMVA; % 有功负荷标幺值 Q_load bus(:, 4) / baseMVA; % 无功负荷标幺值很多新手把欧姆值直接当期pu用算出来的电压曲线平得诡异网损也小得离谱基本就是这个原因。之前我帮人排查一个模型解出来网损只有 0.0002 pu明显量级不对一查就是阻抗没除基准值。在写模型之前统计一下基本数据n size(bus, 1); % 33 个节点 nbr size(branch, 1); % 32 条支路 S_max 0.2; % 单节点 DG 最大容量2 MW / 10MVA 0.2 pu pf 0.9; % DG 功率因数另外对于 33 节点系统case33bw的支路顺序基本上就是按父节点 - 子节点排列的大部分支路满足branch(k,1) branch(k,2)可以直接用。如果不放心可以用 BFS 从根节点 1 出发理顺拓扑。这里为了代码简洁我直接按 MATPOWER 数据方向的常规假设来用。3.3 YALMIP 核心建模代码逐段拆解下面这段就是整个 MISOCP 模型的核心。我把每个 block 拆开讲。第一步定义决策变量。U sdpvar(n, 1); % 节点电压幅值平方 L sdpvar(nbr, 1); % 支路电流幅值平方 P sdpvar(nbr, 1); % 支路有功潮流 Q sdpvar(nbr, 1); % 支路无功潮流 P_DG sdpvar(n, 1); % DG 有功注入 Q_DG sdpvar(n, 1); % DG 无功注入 S_DG sdpvar(n, 1); % DG 配置容量 X binvar(n, 1); % 选址变量1 表示该节点安装 DG如果只做定容不做选址就把X删掉S_DG的上限直接用常数S_max卡住。完整版里加上X展示的是更通用的选址定容模型。第二步写约束集合。C []; % 电压上下限根节点电压固定为 1 pu C [C, 0.95^2 U 1.05^2]; C [C, U(1) 1]; % DG 出力约束 for i 1:n C [C, 0 P_DG(i) S_DG(i)]; % 有功不超过容量 C [C, Q_DG(i) P_DG(i) * tan(acos(pf))]; % 功率因数约束 C [C, Q_DG(i) - P_DG(i) * tan(acos(pf))]; % 考虑容性/感性调节 C [C, 0 S_DG(i) S_max * X(i)]; % 容量与选址变量的耦合 end % 可选DG 总容量约束 % C [C, sum(S_DG) S_total_max];这里S_DG(i) S_max * X(i)是选址和定容的关键耦合约束。如果X(i)0容量只能为 0如果X(i)1容量放宽到上限。这种写法在 MISOCP 里非常常见本质是一个大 M 约束只不过把S_max当成了 M。第三步写支路潮流约束。for k 1:nbr fb branch(k, 1); % 父节点 tb branch(k, 2); % 子节点 rk r_pu(k); xk x_pu(k); % 二阶锥约束对应 L (P^2 Q^2) / U C [C, cone([2*P(k); 2*Q(k); U(fb) - L(k)], U(fb) L(k))]; % 电压降落方程 C [C, U(tb) U(fb) - 2*(rk*P(k) xk*Q(k)) (rk^2 xk^2)*L(k)]; end这一段是整个模型的精髓。cone()的第一参数是[2P; 2Q; U_fb - L]第二参数是U_fb L。YALMIP 看到这种结构会自动识别为二阶锥约束传给 Gurobi/CPLEX 时也走对应的圆锥接口速度会快很多。第四步节点功率平衡约束。对于辐射网每个非根节点只有一个父支路。我用一个parentbr数组记录每个节点的父支路编号children存每个节点的子支路编号然后逐节点写功率平衡% 计算父子关系 parentbr zeros(n, 1); children cell(n, 1); for k 1:nbr fb branch(k, 1); tb branch(k, 2); parentbr(tb) k; children{fb}(end1) k; end % 节点功率平衡 for j 2:n % 根节点 1 是松弛节点跳过 kp parentbr(j); % 父支路编号 rk r_pu(kp); xk x_pu(kp); % 流出有功 该节点所有子支路首端功率之和 outP 0; outQ 0; for kc children{j} outP outP P(kc); outQ outQ Q(kc); end % 有功平衡上游注入减去损耗 DG - 负荷 下游流出 C [C, P(kp) - rk*L(kp) P_DG(j) - P_load(j) outP]; % 无功平衡 C [C, Q(kp) - xk*L(kp) Q_DG(j) - Q_load(j) outQ]; end这里P(kp) - rk*L(kp)是父支路送达到节点 j 的功率这个写法扣除了支路损耗是精确版 DistFlow。很多文献里为了简化会省掉损耗项对于辐射网 33 节点这种阻抗不大、网损小的问题影响不大但既然模型里已经引入了 L顺手把损耗扣掉并不增加复杂度反而让结果更严谨。第五步目标函数和求解设置。% 目标函数网络有功损耗最小 J sum(r_pu .* L); % 求解设置 ops sdpsettings(solver, gurobi, verbose, 1, gurobi.MIPGap, 1e-3); % 如果用 CPLEX则 % ops sdpsettings(solver, cplex, verbose, 1, cplex.mip.tolerances.mipgap, 1e-3); % 求解 result optimize(C, J, ops);optimize返回后result.problem等于 0 表示成功求解非 0 需要查yalmiperror(result.problem)看具体错误。这是 YALMIP 里最基本也最常被忽略的检查步骤。3.4 求解器的参数设置细节在 YALMIP 里设置求解器参数格式是求解器名.参数名。Gurobi 的 MIPGap 在 YALMIP 里的字段名是gurobi.MIPGap而 CPLEX 是cplex.mip.tolerances.mipgap两家命名风格差异很大切换求解器时特别容易搞混。几个我常用的参数组合ops sdpsettings(... solver, gurobi, ... verbose, 1, ... gurobi.MIPGap, 1e-3, ... gurobi.TimeLimit, 300, ... gurobi.NumericFocus, 1); % 数值稳定性优先MIPGap1e-3 表示当整数解的gap小于 0.1% 时停止足够工程使用。想要更精确可以设 1e-4代价是求解时间变长。TimeLimit超过 300 秒强制返回当前最优整数解。规划问题不需要像运行调度那样抢时间但卡住不动时有一个兜底总比干等强。NumericFocusGurobi 的数值病态开关模型里面如果存在数量级相差很大的系数建议打开。如果你用的是连续 SOCP没有X变量Gurobi 会直接走连续二阶锥算法不需要设 MIPGap求解速度通常在几秒以内。加了 0-1 分支之后求解时间取决于候选节点数量。33 节点如果允许全节点安装33 个 0-1 变量分支起来也不会太慢但到 100 节点时就要往下文说的提速技巧上靠了。4. 结果校验与几个真正有用的工程技巧4.1 松弛间隙检查验证松弛是紧的二阶锥松弛的数学优雅是一回事工程上能不能信是另一回事。跑完模型第一件事不是画图而是检查每条支路的松弛间隙。你要确认松弛不等式在最优解处基本都是取等号的否则模型和原问题就不等价了。计算方法很简单。对每条支路gap L_opt - (P_opt.^2 Q_opt.^2) ./ U_parent_opt;其中U_parent_opt U_opt(branch(:,1))。如果这个 gap 相对L_opt的比例在 1e-3 量级甚至更小松弛就是紧的结果可信。如果某个支路 gap 很大说明该支路电流被约束拉离了物理下限可能出现电压越限约束卡得太紧、或者网损目标被其他权重项干扰的情况。我在实际跑 33 节点案例时通常所有支路的相对间隙都能低于 1e-8这已经很接近数值精度极限了。如果你的模型出现较大间隙先别急着信结果回头检查一下是不是电压上限约束设得过窄或者目标函数里额外加的投资项权重过大。4.2 电压分布模型结果到底改变了什么求解完成后把电压结果取出来开方就得到每个节点的电压幅值标幺值U_opt value(U); V_opt sqrt(U_opt);对比一下两种场景一是电网不装 DG 的基准潮流电压二是优化配置 DG 后的电压。你会看到 DG 接入点附近电压有明显抬升。如果某些节点电压抬到了 1.05 附近说明 DG 容量已经接近该节点的承载上限。这个信息比网损数字更有工程意义因为配电网规划中电压越限往往是比网损更硬的约束——你不可能为了省电费让用户电压超标。顺手提一句如果模型里设置了Q_DG的无功调节能力电压改善效果会比纯有功注入更明显。逆变器型的 DG 完全可以利用无功调节来抑制过电压这也是分布式电源优化配置里值得深入研究的方向。4.3 算得快和算得准的几个思路求解速度问题在 MISOCP 里非常现实。我自己的经验是以下几招最有效限制候选节点。工程上不是每个节点都适合装 DG比如只有末端负荷重、电压偏低的节点才真正需要 DG 支撑。把候选节点从 33 个缩到 5~10 个整数变量数量直接降一个量级求解时间可以缩短 10 倍以上。先跑连续松弛再分支定界。把X变量的整数约束释放成0 X 1先解一个连续 SOCP然后把结果作为整数搜索的热启动值。YALMIP 里可以用assign()和initialized参数把初始解喂给求解器能显著减少分支数。放宽 MIPGap。工程方案对比阶段MIPGap 设 1e-2 完全够用只有最终方案才需要收紧到 1e-3 或 1e-4。统一数量级。这个问题我在项目里反复遇到。如果你把基准功率设为 10 MVA负荷和 DG 都在 0.01~0.2 pu 之间电压约束在 1 附近支路阻抗在 1e-3 量级这种数量级对求解器非常友好。反过来如果谁用了瓦特、欧姆、伏特做单位数值差几十万倍求解器的线性松弛和数值分解都会出奇奇怪怪的问题。删除冗余变量。不要在模型里定义永远用不到的P_DG、Q_DG的全节点变量。虽然稀疏技术能处理但约束数量多了会让预求解阶段变慢也容易埋数值隐患。这里要给一个小提示连续 SOCP 和 MISOCP 的求解时间差异是天壤之别。如果模型里不需要干选址就不要轻易引入 0-1 变量但如果你要说服业主/导师这个节点该不该投资那 0-1 变量又是不可或缺的。所以建模之前先想清楚你要的是容量优化还是选址定容这会直接决定模型复杂度和求解策略。5. 我踩过的坑和这套模型的扩展方向5.1 三个能让你少加班的坑第一个坑把欧姆当标幺用。这个前面已经提过但我还是想再敲一遍黑板。配电网优化里所有参数必须统一成 pu 值才能进求解器。电压幅值平方 U 默认基准是 1 pu带进去的电压约束是 0.9025~1.10250.95^2 和 1.05^2如果忘了平方电压就会约束错位。见到电压曲线全部顶在上限附近的先查电压约束写的到底是不是平方值。第二个坑YALMIP 版本太老导致 cone() 识别异常。老版本 YALMIP 对锥约束的预处理能力有限某些情况下会直接把锥约束展开成大量线性约束白白牺牲性能。做事之前先跑一次yalmiptest确认 YALMIP 能正确识别你写的cone()再去开 boss 求解器。第三个坑松弛不紧时强制用结果做决策。虽然辐射网、网损最小目标下松弛几乎总是紧的但当你加了小时级时序、储能充放电、响应型负荷之类的新约束后二阶锥松弛可能在某些时段出现明显间隙。这时候结果会偏乐观不适合直接出方案。我的习惯是求解完用 MATPOWER 或牛顿法做一次精确潮流校核看看锥间隙是否造成实际误差。如果误差超过 1%我会考虑加入割平面或者改用更严格的多边形近似。5.2 从静态规划走向更真实的场景这篇文章里跑的是单时段静态优化。实际工程里DG 出力是随时间变化的负荷也有日曲线、季节差异所以往多时段扩展几乎是必然的。扩展方法很直接把每时刻的负荷作为一组场景模型里给每条支路、每个节点增加时间维度变量目标函数改成全时段网损之和。代价是变量数和约束数随周期数量线性增长。这时候前面的限制候选节点和MIPGap 放宽这两个技巧就变得非常重要。更进一步还可以用 K-means 或场景削减方法把 8760 小时的曲线压缩成十几个典型日解算速度和精度的平衡会好很多。从模型能力上说还可以把储能、无功补偿装置、联络开关配网重构一并纳入形成一个包含连续和整数变量的混合整数规划大模型。只要核心的 DistFlow 锥松弛不变描述储能 SOC 递推的线性约束描述开关状态的 0-1 变量都是往现有框架里加菜的事。这也是我推荐大家把二阶锥这套方法学扎实的原因——它是配电网优化里的底层基础设施学会一次后面几乎所有规划问题都能套同一个 YALMIP 框架。最后分享一个我自己坚持了很久的习惯任何优化程序跑完都必须做一次基准模型复算。就是先把 DG 全部设成 0用同一个 YALMIP 框架解一个没有 DG 的纯网络模型和 MATPOWER 的精确潮流对比对不上就说明建模环节有问题而不是求解器有问题。这是个笨方法但真的能帮你避开 90% 的模型错误。配电网优化程序写得再快再好前提都是模型本身站得住脚。