首页 / 资讯中心 / 文章详情

基于NSGA-Ⅲ的梯级水火电联合多目标调度:原理与Matlab实现

基于NSGA-Ⅲ的梯级水火电联合多目标调度:原理与Matlab实现 ★ FEATURED ARTICLE
1. 水火互补问题为什么必须跳出单目标优化的思维定式1.1 水电和火电的性格差异三年前我第一次接触基于NSGA-Ⅲ优化算法的梯级水电和火电机组的联合多目标调度研究这个方向时心里其实是有疑问的水电本来就是清洁能源把火电跟它放在同一个模型里优化除了增加复杂度还能带来什么直到自己动手搭起模型、跑出第一张帕累托前沿图才意识到我最初的认知是片面的。水电虽然有近乎零燃料成本的优势但它出力受来水、库容和水位约束不能像火电那样保证长时间持续可控火电虽然运行成本高、排放也高却能为电网提供稳定的基荷和可靠的深度调峰能力。真正的问题从来不是谁替代谁而是两者怎样协同才能让整个系统在成本、排放、稳定、水量利用等多个维度上达到整体最优。先给不熟悉电力调度背景的朋友补一个基础概念电网侧负荷是动态波动的发电侧每时每刻都要与负荷保持平衡。火电机组启动慢、爬坡速率有限但燃料供应稳定适合承担基荷和缓变负荷水电机组本质上是一个可以快速响应的高机动电源几十秒内就能大幅调整出力非常适合跟踪负荷的快速爬坡段。但水电站的出力上限是由当前水库水位、发电流量和机组特性共同决定的日常调度的安全性约束又多不可能无限制地发电。这两个电源的性格差异决定了它们适合放在一个模型里做互补调度而不是各算各的。1.2 梯级流域的耦合约束单座水电站的调度其实不算复杂真正让调度决策变得困难的是梯级二字。上游水电站的下泄流量会在几个小时甚至几十个小时之后到达下游库区这个水流传播时间造成了上下游电站之间的时间错位如果有一条支流汇入或者区间来水叠加下游水库的入库条件会变得更加复杂。各个水库的库容限制、水位变幅限制、发电流量上限都不同任何一个水库的调度决策都会影响下游全部电站的运行状态和电量出力。我最初在建模时吃过亏。当时为了追求单站发电量最优让上游某个电站满负荷运行了一段时间结果下游水库来水量激增库水位迅速逼近上限只能被迫大量弃水。单看上游电站出力漂亮单看下游电站也没有违规但整个梯级的综合水量利用率反而下降了。顺着这个教训我在模型里明确加入了水量平衡方程和上下游库容关系把每一座水库的时段初始库容、末库容、入库流量、发电流量、弃水流量都纳入决策约束体系。只有把整个梯级当作一个相互耦合的系统来处理后续的优化结果才有工程指导意义否则算出来的最优方案很可能只是局部最优或者根本不可执行。1.3 经济与环境目标的冲突本质水火联合调度在传统框架里常常被简化成单目标的经济调度也就是找一个总运行成本最小的方案。但现实中的电力调度决策还要面对碳排放和污染物排放约束这从本质上改变了问题的性质。火电机组的煤耗特性和污染物排放特性虽然都用二次曲线拟合但两条曲线的形状并不完全平行最低煤耗对应的出力点与最低排放对应的出力点往往落在不同的区间。一个严格按最低成本设计的调度计划排放量大概率不是最低反过来追求最低排放往往要增加水电机组的利用或者把高排放火电机组的出力压低综合运行成本迅速上升。这种省钱与减排不可兼得的矛盾是无法靠单目标加权法完整体现的因为加权需要事先确定成本目标与排放目标之间的换算关系而这个权重本身夹杂着政策和决策偏好属于主观选择。我坚持用多目标优化来做这个研究目的是把一整套互相不支配的折中方案同时呈现出来左端是成本最低、排放较高的方案右端是排放最低、成本攀高的方案中间稀稀拉拉分布着各种均衡点。决策者拿到这套帕累托前沿之后再根据当天电网的实际需求、新能源出力情况和政策考核要求去挑选这才是多目标调度在研究层面应该有的解题路径。2. 调度模型的数学骨架目标函数与关键约束的逐条拆解2.1 目标函数的选择与表达我最终搭建的模型采用双目标框架第一目标为系统总运行成本最小第二目标为火电机组总污染物排放最小。调度时间尺度选取24个时段每个时段1小时这也是目前日调度研究中最常见的粒度。火电机组i在时段t的出力记作 P_{i,t}煤耗成本采用稳态运行下常用的二次函数拟合表达式为成本目标 f1 Σ_t Σ_i ( a_i * P_{i,t}^2 b_i * P_{i,t} c_i ) Σ_t Σ_j m_j * Q_{j,t} 弃水惩罚项其中 a_i、b_i、c_i 是机组煤耗特性系数m_j 是水电机组的单位发电流量维护成本Q_{j,t} 是水电机组j的时段发电流量。弃水惩罚项不是必需的但加上之后算法会主动避免那些为了安全而过度弃水的方案。排放目标同样用二次多项式描述排放目标 f2 Σ_t Σ_i ( α_i * P_{i,t}^2 β_i * P_{i,t} γ_i )需要注意α、β、γ 的数值与煤质、机组容量和燃烧效率有关不同文献差异很大这不是模型错误只是参数标定口径不同。我一开始直接套用了某开源案例的典型参数来做算法验证后期接入实际机组数据后又重新做了参数拟合两个阶段的目标值形态差别不小但算法框架完全不用改动这也说明把目标函数和求解算法解耦是很有价值的设计习惯。2.2 约束条件的完备性缺少约束的优化模型算出来的结果是空中楼阁约束过紧又会让可行域非常狭窄。我在模型里使用的关键约束如下表所示约束类型表达式说明系统功率平衡Σ_i P_{i,t} Σ_j P_{h,j,t} P_load(t)每个时段的发电出力必须等于负荷火电出力上下限P_min_i ≤ P_{i,t} ≤ P_max_i机组技术出力范围火电爬坡速率-ΔP_down_i ≤ P_{i,t} - P_{i,t-1} ≤ ΔP_up_i防止机组出力跳变水电发电流量Q_min_j ≤ Q_{j,t} ≤ Q_max_j发电流量运行范围水库库容V_min_j ≤ V_{j,t} ≤ V_max_j水位安全限制水量平衡V_{j,t} V_{j,t-1} ( I_{j,t} - Q_{j,t} - S_{j,t} ) * Δt考虑上游来水和失水水电出力特性P_{h,j,t} k_j * Q_{j,t} * H_{j,t}出力与流量、水头的乘积关系生态流量下限Q_{j,t} S_{j,t} ≥ Q_eco_j保障下游生态需水我在建模时额外加入了生态流量下限这一条模型复杂度和求解难度都会上升但这个约束让结果在实际工程中更有说服力。没加这个约束的方案在枯水期往往意味着河道干涸风险几乎不可能被调度部门采纳加进去之后虽然帕累托前沿整体略微右移但所有推荐方案都具备可执行性。2.3 约束处理方案从罚函数到松弛节点NSGA-III本质上是一个无约束的元启发式算法它不会自己去处理等式和不等式限制所以在评价适应度阶段必须设计好约束处理机制。我最早采用的是传统罚函数法把每个约束的违规量乘上一个惩罚系数后加到目标函数上但效果很不理想。原因是两个目标取值范围差异太大成本可能是几十万量级排放可能是几万量级一个统一的罚函数权重很难同时适配两个目标调参过程让人非常头疼而且种群在迭代早期容易陷入一堆不可行解中难以恢复。后来我换了两阶段处理方案效果稳定很多。第一阶段是消去等式约束系统功率平衡约束不参与罚函数计算而是把某台火电机组作为松弛节点在评价过程中用负荷减去其它所有机组出力来反算该机组出力。如果反算结果落在该机组上下限之内等式约束自动满足如果越界再对该机组单独施加一个较小的违规惩罚。第二阶段是对剩余不等式约束统一计算违规度把违规度作为所有个体比较的第一优先级违规度相同才比较目标值。这个做法在多数NSGA-III的Matlab实现框架里都能直接嵌入比在目标函数里手动加罚项干净得多也更容易复现代码结果。3. NSGA-Ⅲ为什么适合这类问题参考点机制与算法流程3.1 NSGA-Ⅱ在高维目标下的失效原因很多学习多目标优化的人最早接触的是NSGA-II我也一样。NSGA-II通过非支配排序和拥挤距离两个机制来推动进化拥挤距离的计算思路是某个个体与相邻个体在目标空间中的距离越大越应该被保留这样可以防止种群堆成一团。但问题在于拥挤距离在二阶目标问题下效果很好一旦目标维度上升到3维、4维距离排序的区分度就急剧下降。不同个体在各个两两目标平面上的距离差异变得不明显很多个体计算出来几乎一样的拥挤距离值排序也接近于随机选择最终结果就是帕累托前沿上某些区域个体扎堆另一些区域稀疏甚至空白。我在三目标扩展实验里第一次体会到这个差距。当时我在双目标基础上加入了生态流量满足度作为第三个目标用NSGA-II跑完后三维帕累托前沿明显有一条稀疏的倾斜带种群在迭代后期被压在一个狭窄的曲面区域里多样性几乎停滞。换用NSGA-III之后同样的初始种群和同样迭代代数前沿覆盖范围明显完整很多。3.2 参考点生成与自适应归一化NSGA-III的核心改进是用分布在单位超平面上的参考点集合替代拥挤距离作为维持种群多样性的工具。参考点的生成方式是Das-Dennis方法在目标维度为M、剖分系数为p的条件下参考点数量等于组合数 C(Mp-1, p)。几个典型配置是三目标p6时为28个参考点四目标p5时为56个参考点目标数或剖分系数增加参考点数会涨得非常快实际使用时要根据计算资源权衡。生成参考点只是第一步更重要的是如何利用它们筛选个体。每代种群计算完目标值后先做自适应归一化第一步求理想点也就是当前种群各目标的最小值向量第二步计算每个目标轴上的极值点通过这些极值点确定一个超平面第三步用超平面在坐标轴上的截距把所有目标值缩放到[0,1]区间附近。归一化这一步在整个算法里非常关键我一开始图省事直接跳过了它结果目标量级更大的成本目标在归一化前的距离计算里占了绝对主导整个种群沿排放轴的方向几乎没有多样性地发展前沿严重偏斜提醒了我不能省略预处理环节。3.3 环境选择基于小生境的精英保留策略NSGA-III的环境选择流程表达如下将所有个体做非支配分层后逐层保留当某一层的个体被加入会导致种群超出容量限制时我需要在这个临界层里筛选出剩余名额。筛选不再依赖拥挤距离而是借助参考点关联每个个体经过归一化后计算其到所有参考点方向线的垂直距离关联到距离最近的参考点然后统计每个参考点当前已经被保留的个体数也就是小生境计数。选择优先级是优先保留关联到小生境计数较少参考点的个体这样可以确保种群均匀覆盖整个目标空间。我在实现时发现一个容易被忽略的细节参考点是预设的、固定不变的而每代极值点和截距是动态变化的归一化之后参考点对目标空间的分割才真正生效。如果种群前期分布极不均匀个别参考点的小生境计数长期为0算法会自动把这些空参考点附近的个体拉高优先级从而在进化过程中逐渐填补缺口。这种机制对电力调度这类前沿形状未知的问题特别有利不需要事先假设前沿是凸的还是凹的。3.4 为什么电力调度场景可以发挥NSGA-Ⅲ的优势联合调度问题具有三个明显特点决策变量维度高、连续变量主导、目标函数光滑但前沿形状复杂。NSGA-III使用的模拟二进制交叉和多项式变异算子对连续实数编码的决策变量适配度很高参考点机制保证了高维目标下的种群多样性自适应归一化可以自动匹配量级差异巨大的目标函数。此外它不像加权法那样需要用户预先给出各目标的权重也就避免了由主观权重导致的帕累托前沿截断问题。一次运行直接返回一整条均匀分布的折中解集合这样的输出形态非常契合调度决策场景。4. Matlab代码实现要点框架、核心函数与调参经验4.1 程序整体架构与数据流整个程序的模块划分我总结为六个部分数据准备模块、参数设置模块、种群初始化模块、目标函数与约束评价模块、NSGA-III主循环模块、结果输出与绘图模块。数据准备阶段读入负荷曲线、火电机组参数、各水库参数和来水数据参数设置阶段确定种群规模、最大迭代次数、参考点剖分系数、交叉概率和变异概率种群初始化阶段生成初始决策变量矩阵。决策变量编码用的是实数编码按顺序排列火电机组各时段出力和水电机组各时段发电流量。以24时段、5台火电加4座水电站为例决策变量维数是 24 * (5 4) 216算上水库库容变量后达到240维左右。这个维度直接用随机初始化也可以跑但效果很一般。我在迭代几十次后发现初始种群可行解占比实在太低于是改用拉丁超立方抽样生成初始样本确保决策空间各维度均匀覆盖虽然构造时间多了几毫秒但前50代的收敛速度明显提升。4.2 三个最关键的代码片段第一个关键片段是生成参考点。使用Das-Dennis方法的Matlab简化实现逻辑如下% 生成M维目标空间、剖分系数为p的参考点集合 function refPoints generateRefPoints(M, p) if M 2 refPoints [ (0:p)/p, (p:-1:0)/p ]; return; end refPoints []; for i 0:p subPoints generateRefPoints(M-1, p-i); % 递归生成子参考点 refPoints [ refPoints; ... i/p * ones(size(subPoints,1),1), (1 - i/p) * subPoints ]; end end这段代码虽然简洁但能正确生成单纯形上的均匀参考点。三目标、p6时会得到28个点四目标、p5时得到56个点。如果剖分系数设定得过大参考点数会指数级膨胀迭代每代的计算成本不可忽略我建议从三目标p6、四目标p4起步试算再根据需求调整。第二个关键片段是关联操作。每个个体归一化后需要计算它到每条参考线的垂直距离这是环境选择的计算热点写成批处理可以大幅加速% 归一化目标值: objNorm (个体数 x M) % 参考方向向量: refDir refPoints ./ vecnorm(refPoints, 2, 2) % 计算每个个体到所有参考方向的垂直距离 proj objNorm * refDir; % 投影长度 dist sqrt(max(0, sum(objNorm.^2, 2) - proj.^2)); % 垂直距离 [~, nearestRef] min(dist, [], 2);这段向量化代码把两层循环压成矩阵乘法在我的实测场景下比逐个体遍历快一个数量级。当种群规模从100增加到300时这部分的耗时并没有线性爆炸整体迭代速度能接受。第三个关键片段是环境选择里的小生境计数更新。关联之后统计每个参考点当前保留的个体数处理临界层时优先保留小生境数少的参考点附近的个体。这段逻辑用Matlab写起来不复杂但却是决定算法最终前沿质量的核心值得单独调试验证。4.3 参数配置与收敛性判断参数设置直接影响NSGA-III的收敛速度和解分布质量以下是我多次实验后的经验范围参数建议值说明种群规模模型维度的1.52倍240维问题建议300左右最大迭代次数300500太少前沿空隙大参考点剖分系数 p三目标6四目标4参考点数由C(Mp-1,p)决定SBX交叉概率0.80.9保持较强的探索能力多项式变异概率0.10.2过小易收敛于局部交叉分布指数20常规默认值即可变异分布指数2050值越小扰动越强收敛性不能只看迭代代数的硬设定。我习惯在每次迭代结束后计算当前种群的前沿超体积指标记录成一个一维序列如果连续20代的超体积变化幅度小于设定阈值就提前终止循环。这样既避免了浪费算力也保证运行前只需要粗略设一个上限代数不用反复试错调整。如果你手头没有现成的超体积计算函数也可以用简单的方法统计连续多代不动的前沿个体占比作为收敛的粗略信号。5. 实际算例的结果分析与我踩过的坑5.1 帕累托前沿的读取与折中解选取算例跑完之后第一步就是画目标空间散点图横轴是总运行成本纵轴是总排放量。两个目标都是越小越好所以帕累托前沿位于左下角包络线上。理想情况下这条包络线应该是连续的、从左下方向右上方倾斜的曲线左端代表最低成本方案右端代表最低排放方案。如果点与点之间断断续续、有明显缺口通常说明参考点数量太少或者迭代代数不足。如果线型过于弯曲甚至凹进凸出也不必惊讶这正是问题的真实形状。实际需要提交给决策者的时候我们很少直接把整条前沿丢过去而会从中挑出一个或几个推荐方案。我常用模糊隶属度法做平衡解选取对每个目标按前沿中的最大最小值做归一化计算每个解的隶属度然后综合两个目标的隶属度取最大值对应方案。这个方法不需要额外参数而且选出来的折中解一般落在前沿的中间位置客观性比较好。在风格偏保守的电网调度场景决策者往往更看重成本侧的稳定可以适当调高成本目标的权重重新选择多目标结果的灵活性就在这里体现。5.2 我调试过程中踩过的三个坑第一个坑是等式约束占比太高导致初始种群全是不可行解。我在初始版本里直接随机生成所有机组出力和发电流量尝试用罚函数处理功率平衡约束结果前几十代大批量个体都是不可行解非支配排序几乎失去区分能力超体积指标长期趴在地上不动。后来启用松弛节点方案后可行解比例从不到5%提升到60%以上迭代过程立刻恢复健康。第二个坑是忽略了水头-出力关系的非线性。一开始为了追求代码简洁我把水电站出力简化成 P K * Q完全不考虑水头变化的影响。算出来的调度计划很好看但工程人员一眼就看出问题在水位偏低时段发电流量再大出力也达不到设定值方案不可执行。后来我加了一层拟合关系先根据库容曲线查水位再根据水位差估算水头最后用 P K * Q * H 计算出力精度提高后结果的工程可信度才真正立起来。第三个坑是参考点剖分系数没有随着目标数增加及时调整。四目标实验时我还用三目标习惯的p6参考点数量达到上百个种群规模却还是400每个参考点平均不到4个个体环境选择时小生境数几乎全是1和0多样性维护机制完全失效。调小p、同时把种群规模提升到500之后前沿分布重新变得均匀这类问题只靠理论推演很难预料实际跑几组参数对比最直观。5.3 模型扩展方向这套NSGA-III 水火联合调度的框架可以往三个方向继续延伸。其一是加入新能源出力不确定性把风电或光伏的随机波动用多场景法建模目标函数再增加一个系统风险指标变成三目标问题这个扩展在代码层面主要改动是出清功率平衡约束形式。其二是把水电站长期蓄能值纳入目标替代只关注日发电量的经济性这样可以让调度结果对未来的来水变化更稳健。其三是引入区间多目标表达把目标和约束都写成区间数NSGA-III配合区间排序策略就能处理但计算量会明显加大。我在完成基础版本后又尝试了前两个方向实验时间和Debug成本不低但整体框架复用程度很高换参数、换目标函数都可以快速验证新想法。最后再说一句实际体会这类研究最难的部分往往不是算法本身而是模型细节的工程合理性。面对一个结果很漂亮但现场完全不敢用的调度方案优先回头检查约束是否完整、参数是否可信远比换一个更高级的优化算法更有效。把NSGA-III跑通只是第一步让算出来的每个解都能被工程师点头认可才是这个课题真正值得投入的地方。
阅读完成 · 觉得有帮助?
咨询建站