风电、光伏与抽水蓄能电站互补调度运行研究:一份可复现的Matlab实现笔记
搞新能源调度的人应该都有同感:风电和光伏的出力曲线,全是“看天吃饭”的锯齿状波动。白天光照强光伏功率一路飙升,傍晚又断崖式下跌;风场更是毫无规律,半夜可能满发,白天反而趴窝。这种波动性扔进电网里,如果不加调节,弃风弃光率和系统调峰压力都会非常难看。把抽水蓄能电站加进来做多能源互补调度,是目前工程上最成熟的调节手段之一。这篇博文我就把风-光-蓄互补调度运行研究这个课题的建模思路、Matlab实现细节和踩坑记录完整地梳理一遍,适合刚入门电力系统优化调度的研究生,也适合想做新能源消纳方案的技术人员参考。
课题本身不算特别复杂,核心就三件事:把风电、光伏、抽水蓄能的出力特性用数学模型描述清楚,把调度目标和约束条件写成可求解的优化问题,然后选一个合适的算法用Matlab把整个流程跑通。难的地方也在这三件事里——模型简化到什么程度、约束怎么处理、算法参数怎么调,每一步都直接影响结果的可靠性。下面我把完整思路拆开来讲。
1. 为什么非要做风-光-蓄互补调度
1.1 风、光出力“看天吃饭”,三个绕不开的痛点
先说风电。风速的随机性和间歇性不用多解释,更麻烦的是风电往往有反调峰特性——夜间负荷低谷时段风速反而偏高,风电出力大,结果就是谷底被进一步下压,火电机组被迫深度调峰甚至停机。到了白天负荷高峰,风速又可能降下来,风电帮不上忙,系统只能靠其他电源硬扛。
光伏的特性大家更熟悉,出力曲线基本跟着太阳走,午间形成“鸭子曲线”的肚子,傍晚快速跌落形成陡峭的爬坡需求。这种短时大幅波动对系统的爬坡速率要求极高,常规火电机组根本跟不上,需要更灵活的资源去填补。
第三个痛点是预测误差。风电功率预测误差在10%-20%很正常,光伏受云层影响更是经常“说翻脸就翻脸”。预测偏差意味着调度计划不能完全执行,需要留有足够的调节裕度来消化实际出力和计划出力的差值。这三个痛点叠加起来,单靠火电调峰不仅成本高,响应速度也跟不上,必须引入储能性质的调节资源。
1.2 抽水蓄能凭什么当“调节器”
抽水蓄能是目前最成熟的大规模储能方式,核心原理就是能量时移——负荷低谷时把水从下水库抽到上水库储存势能,负荷高峰时放水发电。它最大的优势在于响应速度快,工况转换灵活,机组从静止到满发一般只需要几分钟,调节速率可以达到每分钟几十兆瓦,这是火电机组完全比不上的。
从调度角度看,抽蓄相当于给系统提供了一个“缓冲池”。光伏大发时把多余的电能通过抽水方式存起来,避免弃光;光伏出力骤降或晚高峰时再放水发电顶上。风-光-蓄联合起来,就可以把原来“不可控的波动出力”改造成“可控程度更高的组合出力”,这正是当前能源基地建设中多能互补模式的工程基础。
需要说明的是,抽蓄本身也有约束,不是想怎么调就怎么调。抽水工况和发电工况不能同时进行,水库库容有上下限,机组启停有最小间隔时间,一天内抽水量和发电量还要满足水量平衡。这些约束正是调度模型里最需要细致处理的部分。
1.3 这个调度模型到底在优化什么
把风、光、蓄放在一起做互补调度,本质上是在解一个带约束的优化问题。目标函数按照研究侧重点不同,可以是最小化系统运行成本、最大化新能源消纳量,也可以是最小化等效负荷波动或碳排放量。实际课题中最多的是以系统运行成本最小为目标,同时兼顾弃风弃光率。
决策变量包括各时段抽蓄机组的发电功率和抽水功率、火电机组的出力分配,以及需要时还可以把联络线交换功率纳入进来。约束条件包括电力平衡约束、机组出力上下限、爬坡约束、水库水量与库容约束、系统备用约束等。
听起来和普通的经济调度没有本质区别,但加入抽蓄之后就多了一个“时间耦合”的特性:决定当前时段抽多少水,会影响未来时段的发电能力,所以不能逐时段独立求解,必须把整个调度周期内各时段的决策统筹起来一起优化。这个特性也决定了求解算法的选择——需要能够处理非线性、高维度、含约束的优化问题,粒子群算法这类智能算法在这种场景下是常用的选择,后面细讲。
2. 从物理特性到数学模型
2.1 风电出力特性建模
风电出力建模在调度研究中一般不做微观空气动力学计算,工程上最常用的思路是先给定预测功率曲线,再叠加不确定性场景。基础模型是风功率转换关系式:
[ P_w = \begin{cases} 0, & v < v_{ci} \text{ 或 } v \geq v_{co} \ \frac{v^3 - v_{ci}^3}{v_r^3 - v_{ci}^3} P_r, & v_{ci} \leq v < v_r \ P_r, & v_r \leq v < v_{co} \end{cases} ]
其中(v_{ci})、(v_r)、(v_{co})分别是切入风速、额定风速和切出风速,(P_r)是额定功率。实际写代码时,直接把预测出力序列读入就行,风电的时序功率数据可以从项目资料或公开数据集里获取。
2.2 光伏出力特性建模
光伏出力同样建议直接用预测曲线,如果要从光照强度推算,标准公式是:
[ P_{pv} = \eta_{pv} \cdot A \cdot G \cdot [1 - \beta(T_c - T_{ref})] ]
其中(G)是太阳辐照度(W/m²),(A)是光伏板总面积,(\eta_{pv})是光电转换效率,(\beta)是温度系数,(T_c)是电池板温度。这个公式的价值在于可以做场景敏感性分析,比如你想要考察温度升高时光伏出力怎么变化,改参数重新跑一遍就行。
在Matlab里,我习惯把风、光数据统一组织成矩阵:行是时段(比如一天24个时段),列是不同场景。这样后续写约束条件时,向量化操作会非常方便,不需要写一堆for循环。
2.3 抽水蓄能机组运行模型
抽蓄的建模是整套模型的核心。单台机组的运行工况可以简化成水泵工况、发电工况和停机工况三种状态。数学描述上,发电功率和抽水功率各有上下限,并且同一时刻只能处于一种工况。抽发之间的能量转换关系是:
发电时:[ E_{gen} = \eta_g \cdot V_{dis} \cdot \rho \cdot g \cdot H ]
抽水时:[ E_{pump} = \frac{V_{pump} \cdot \rho \cdot g \cdot H}{\eta_p} ]
其中(\eta_g)、(\eta_p)分别是发电效率和抽水效率(一般取0.85-0.9),(H)是水头差,(V)是水量。调度研究中更常用的是能量层面的简化:抽水1度电,发电时大约只能收回0.75度电左右。这个能量损耗是抽蓄调度的关键因素,模型必须体现出来,否则优化结果会倾向于频繁抽发而失去经济性。
水量平衡约束要写清楚上下水库的联动关系。以上水库为例:
[ V_{t+1} = V_t + \eta_p \cdot P_{pump,t} \cdot \Delta t \cdot k_1 - P_{gen,t} \cdot \Delta t / k_2 ]
这里的(k_1)、(k_2)是功率-水量换算系数,具体数值根据水头和库容曲线确定。简化处理时,也可以直接用能量作为状态变量建模,即上水库的“储能电量”等于之前累计的抽水电量乘以效率再减去累计发电量。两种方式效果等价,但能量建模写代码更直观,推荐初学者使用:
% 上水库储能量动态方程(24时段) E_store(1) = E_store_0; for t = 1:24 E_store(t+1) = E_store(t) + pump_power(t) * eta_p * dt - gen_power(t) * dt / eta_g; end这个方程是整个调度模型里最核心的约束之一。它把“当前时段的决策”和“未来时段的可用能量”联系了起来,实现了时间维度上的解耦——每时刻的决策不再独立,而是受制于此前积累的储能状态。
3. 互补调度优化模型与约束体系
3.1 目标函数:经济性与环保性怎么权衡
我做的这个模型目标函数选的是系统综合运行成本最小,包含三部分:火电煤耗成本、抽蓄运行维护费用、弃风弃光惩罚成本。写出来就是:
[ \min ; C = \sum_{t=1}^{T} \left( \sum_{i=1}^{N} (a_i P_{i,t}^2 + b_i P_{i,t} + c_i) + c_{om} (P_{pump,t} + P_{gen,t}) + c_{curt} (P_{wind,t}^{pred} - P_{wind,t}^{sch} + P_{pv,t}^{pred} - P_{pv,t}^{sch}) \right) ]
(a_i)、(b_i)、(c_i)是火电机组的煤耗系数,(c_{om})是抽蓄单位电量运维成本,(c_{curt})是弃风弃光惩罚系数。惩罚项的存在非常关键,它把“多消纳新能源”转化成了目标函数内的经济信号。只要惩罚系数设置合理,优化结果就会自动倾向于优先利用风电和光伏出力,而不是一味压低成本而牺牲清洁能源消纳。
实际调试时你会发现,惩罚系数的大小直接影响结果走向。设得太大,优化算法会为了消纳最后1%的新能源而不计成本地调用抽蓄,导致抽蓄频繁启停;设得太小,又会出现明显的弃风弃光现象。我一般先设一个基准值,然后通过敏感性分析调整,观察弃风弃光率和总成本之间的平衡点。
3.2 约束条件:电力平衡、机组出力、库容水位
约束条件分四类,全部要转换成一堆矩阵或者函数句柄才能在优化算法里处理:
第一是功率平衡约束。任一时刻所有电源出力之和要等于负荷加上抽蓄的抽水功率:
[ \sum_{i=1}^{N} P_{i,t} + P_{w,t} + P_{s,t} + P_{gen,t} = P_{load,t} + P_{pump,t} ]
注意抽水功率在这里是“负荷”,放水发电是“电源”,符号方向不要搞错。
第二是机组出力上下限约束。火电有最小技术出力和最大出力限制,抽蓄在发电工况和抽水工况下也各有功率范围。爬坡约束也要加:火电机组相邻时段出力变化不能超过爬坡速率。
第三是上水库库容约束。储能量不能超过水库最大容量,也不能低于死水位对应的最小储能量。同时调度周期结束时,上水库的储能量要恢复到初始值,这样才能保证调度方案可以循环执行。
第四是逻辑约束。同一时段不能同时抽水和发电。建模时通常引入二进制变量(\delta)来处理:
[ \delta_t \cdot P_{gen}^{min} \leq P_{gen,t} \leq \delta_t \cdot P_{gen}^{max} ] [ (1-\delta_t) \cdot P_{pump}^{min} \leq P_{pump,t} \leq (1-\delta_t) \cdot P_{pump}^{max} ]
这个约束处理起来比较麻烦,涉及混合整数问题,后面讲算法时会讨论怎么处理。
3.3 为什么选粒子群算法而不是线性规划
看到这里你可能会问,目标函数里有二次项,约束里有混合整数,直接用商业求解器或者Matlab自带的优化工具箱不香吗?确实,如果问题规模不大,可以直接用intlinprog(处理混合整数线性规划)或者fmincon(处理非线性规划)来求解。我自己的实践体会是:
问题规模小、约束条件线性化程度高的时候,求解器效率远高于智能算法,结果也更稳定。但当约束条件复杂、目标函数非线性强、变量维度升到几十上百时,传统求解器容易陷入局部最优或者干脆不收敛,这时候粒子群算法这类启发式算法反而更灵活——它不要求目标函数和约束有特定的数学形式,改模型时不需要把约束重新线性化。
粒子群算法的思路很直观:一群粒子在可行解空间里飞行,每个粒子记住自己找到的最好位置(个体最优),同时知道整个群体目前找到的最好位置(全局最优),然后根据这两个信息更新速度和位置。迭代若干代之后,粒子群收敛到最优解附近。代码量小,易于实现,做课题研究时快速改模型、跑对比方案很合适。
对于抽蓄的“不能同时抽发”逻辑约束,粒子群的一个取巧处理是:把发电功率和抽水功率都作为决策变量,但施加一个惩罚项,当二者同时大于0时,给目标函数加一个很大的惩罚值。这样粒子在搜索过程中会自然避开“既抽又发”的不可行区域,避免引入整数变量,大大简化了编程难度。
4. 粒子群算法Matlab实现,附可跑通的代码框架
4.1 调度周期与数据准备
我以一天24个时段为例,每个时段1小时。输入数据包括:24时段的负荷预测值、风电预测出力、光伏预测出力、火电机组参数、抽蓄参数。数据从CSV读入是我测试下来最稳定的方式,用readmatrix或readtable都可以。这里提一个热知识:readmatrix在读取带有时间列的CSV时会自动处理格式,但如果你只需要数值部分,直接用readmatrix(file, 'Range', 'B2:Y25')指定范围更省心。
% 读取数据示例 data = readmatrix('schedule_input.csv', 'Range', 'B2:Y25'); load_profile = data(1, :)'; % 负荷 wind_forecast = data(2, :)'; % 风电预测 pv_forecast = data(3, :)'; % 光伏预测数据准备好后,把决策变量定义成向量形式。假设火电有2台机组,加上抽蓄发电功率和抽水功率,每个粒子的决策变量维度就是 (24 \times 4),拉平成一维向量就是96维。粒子群处理高维问题时,维度越高收敛越慢,这个维度规模还在可接受范围内。
4.2 粒子群主程序
写粒子群主程序时,我习惯把“算法主循环”和“适应度函数”分开,这样调试时只改一个文件就行。主循环代码如下:
% 粒子群主程序 nVar = 96; % 决策变量数量:2台火电*24 + 抽发*24 + 抽水*24 nPop = 80; % 种群数量 maxIter = 300; % 最大迭代次数 % 初始化粒子位置和速度(在边界内随机) X = repmat(xmin, nPop, 1) + rand(nPop, nVar) .* repmat((xmax - xmin), nPop, 1); V = zeros(nPop, nVar); % 计算初始适应度 fitness = zeros(nPop, 1); for i = 1:nPop fitness(i) = myCostFunction(X(i, :)); end % 初始化个体最优和全局最优 pbestX = X; pbestF = fitness; [gbestF, gbestIdx] = min(fitness); gbestX = X(gbestIdx, :); % 迭代 w = 0.9; c1 = 2.0; c2 = 2.0; % 惯性权重和学习因子 for iter = 1:maxIter w = 0.9 - 0.5 * iter / maxIter; % 惯性权重线性递减 for i = 1:nPop % 更新速度(速度边界裁剪) V(i, :) = w * V(i, :) + c1 * rand(1, nVar) .* (pbestX(i, :) - X(i, :)) ... + c2 * rand(1, nVar) .* (gbestX - X(i, :)); V(i, :) = max(min(V(i, :), vmax), -vmax); % 更新位置 X(i, :) = X(i, :) + V(i, :); % 边界处理:越界粒子拉回边界 + 随机扰动 outLow = X(i, :) < xmin; outHigh = X(i, :) > xmax; X(i, outLow) = xmin(outLow) + 0.1 * rand(size(xmin(outLow))) .* (xmax(outLow) - xmin(outLow)); X(i, outHigh) = xmax(outHigh) - 0.1 * rand(size(xmax(outHigh))) .* (xmax(outHigh) - xmin(outHigh)); % 重新计算适应度 fitness(i) = myCostFunction(X(i, :)); % 更新个体最优 if fitness(i) < pbestF(i) pbestF(i) = fitness(i); pbestX(i, :) = X(i, :); end end % 更新全局最优 [bestF, bestIdx] = min(pbestF); if bestF < gbestF gbestF = bestF; gbestX = pbestX(bestIdx, :); end fprintf('迭代%d: 最优成本=%.4f\n', iter, gbestF); end代码里的速度边界vmax我通常设成变量范围的10%-20%,太小容易收敛慢,太大会导致粒子在可行域边缘反复振荡。
4.3 适应度函数怎么写
适应度函数是整个模型的核心,它把决策变量翻译成目标函数值和约束违反量。我的写法是:先计算目标函数值,再计算各约束的违反程度,最后把违反程度乘以一个大惩罚系数加进适应度里。
function f = myCostFunction(x) % 解码决策变量 P1 = x(1:24); % 火电1出力 P2 = x(25:48); % 火电2出力 Pgen = x(49:72); % 抽蓄发电功率 Ppump = x(73:96); % 抽蓄抽水功率 % 基础成本计算 fuelCost1 = sum(a1 * P1.^2 + b1 * P1 + c1); fuelCost2 = sum(a2 * P2.^2 + b2 * P2 + c2); omCost = c_om * sum(Pgen + Ppump); % 弃风弃光量计算 curt = sum(max(0, wind_forecast - wind_schedule) + max(0, pv_forecast - pv_schedule)); curtCost = c_curt * curt; % 功率平衡约束检查 balanceViolation = sum(abs(P1 + P2 + Pgen + wind_schedule + pv_schedule - load_profile - Ppump)); % 水库库容约束 E_store = zeros(25, 1); E_store(1) = E_init; for t = 1:24 E_store(t+1) = E_store(t) + Ppump(t) * eta_p - Pgen(t) / eta_g; end storeViolation = sum(max(0, E_store - E_max)) + sum(max(0, E_min - E_store)); % 最终适应度 = 目标函数 + 约束惩罚 penalty = 1e5; % 惩罚系数 f = fuelCost1 + fuelCost2 + omCost + curtCost + penalty * (balanceViolation + storeViolation); end注意max(0, ...)这种写法能自动把约束违反量线性化处理,配合惩罚系数让粒子快速逃离不可行区域。实际调参时,如果发现粒子经常越界,就把惩罚系数调大;如果结果精度不够稳定,就减小惩罚系数并增大种群规模。
4.4 算法参数调试心得
粒子群参数说多不多,但每个都影响结果。惯性权重(w)我采用线性递减策略,从0.9降到0.4。初始(w)大,粒子全局搜索能力强,不容易漏掉好的区域;迭代后期(w)小,局部搜索能力强,结果更精细。学习因子(c_1)、(c_2)通常都取2.0,但如果你发现结果振荡厉害,可以把(c_1)调小一些(比如1.5),减少粒子“过度自信”导致的速度振荡。
种群规模和迭代次数的选择,我建议宁多勿少。96维问题,种群80-100、迭代300-500次是一个相对稳妥的配置。如果跑了500次迭代成本还在明显下降,那就继续加大迭代次数,直到连续50代成本变化小于0.1%再停止。调试时可以先跑一个较小的种群快速验证模型逻辑,Model调通后再加大规模进行正式实验。
5. 常见问题与排查技巧实录
5.1 运行Matlab时的典型问题速查表
这个项目在Matlab环境下跑的过程中,我自己遇到过的和帮别人排查过的问题不少,整理成表格方便查阅。
| 问题现象 | 根本原因 | 解决办法 |
|---|---|---|
intlinprog或优化工具箱函数未定义 | 缺少Optimization Toolbox工具箱 | 在Matlab的“附加功能”里安装Optimization Toolbox;也可以用粒子群等自编算法绕过 |
| 粒子群迭代发散,适应度出现NaN | 决策变量超出物理允许范围,比如功率为负值或过大 | 检查边界设置,检查代码中sqrt或log函数是否对负数求值导致NaN,在适应度函数开头加数值有效性判断 |
| 结果中抽蓄同时抽水和发电 | 逻辑约束未处理或惩罚系数太小 | 在适应度函数中增加同时抽发的惩罚项,系数设为无法接受的量级 |
| 水库储能量不守恒,末时刻偏离初始值 | 水量平衡方程写错,或效率系数应用位置反了 | 单独写一段代码验证储能量动态方程,输入一个固定抽发序列人工核算一遍 |
| 收敛速度极慢,1000代还在波动 | 决策变量范围和速度范围设置不合理 | 检查变量初始化和vmax设置,尝试归一化决策变量到[0,1]区间 |
| 结果随机性大,每次运行不一致 | 粒子群算法本质是随机优化算法,未设置随机种子 | 统一用rng(固定值)设置随机种子,便于对比实验复现 |
5.2 数据处理与导入的常见坑
Matlab做课题时数据处理往往是隐藏的时间杀手。CSV导入这块,readmatrix是实测最稳的函数,但有两个注意点:文件路径不能有中文或特殊符号,否则部分老版本Matlab会报错;如果CSV第一行是表头,readmatrix默认会跳过表头,但如果你手动指定了Range,表头跳过的行为会变化,最好用readtable先看一眼数据长什么样再决定怎么读。
还有一个小坑是时间列的处理。很多新能源数据文件第一列是时间戳(比如2025-01-01 00:00),如果你只需要数值列,直接readmatrix会自动把时间列忽略,但有时候数据文件里的时间是日期序列值(Excel导出的常见坑),就会把时间列当成普通数值读进来,导致你的数据矩阵整体错位。我的习惯是每次读入后先size()检查矩阵维度,再plot()一眼扫一遍曲线,确认数据没串位再往下走。
单列数据转置、多列提取这些基础操作就不展开了。有一点值得提:Matlab R2016b之后推荐用datetime类型处理时间索引,做预测数据对齐时非常方便。如果你需要把datetime转成字符串用于文件名,直接用char(datetime)或datestr都能实现,但需要注意datetime在R2022a之后显示格式有调整,建议显式指定Format属性。
5.3 结果不收敛、振荡怎么排查
粒子群的结果如果呈现明显的振荡,优先检查三件事:
第一,目标函数的量级是否合理。如果你的成本值是百万级别的,而约束惩罚只有十万级别,粒子就会宁愿违反约束也要降低成本,结果里会出现功率平衡明显被破坏的情况。解决方法是把惩罚系数抬高到目标函数正常量级的10-100倍。
第二,速度更新是否越界。没有速度裁剪的粒子群会越飞越远,位置越来越离谱。务必加上V = max(min(V, vmax), -vmax)这行代。实际测试中,加了速度裁剪后同样的模型迭代300次的效果,比不裁剪迭代1000次还稳定。
第三,初始化是否覆盖了整个可行域。如果repmat(xmin)和repmat(xmax)写反了,或者初始位置全部集中在一个角落,粒子群前几百代都在赶路,收敛自然慢。建议初始化后做个直方图确认粒子分布均匀。
6. 结果分析、扩展方向与我的几点体会
6.1 调度结果怎么分析
算完出结果之后,除了看最终成本值,我建议至少画三张图:第一张是各电源出力时序堆叠图,可以直接看出抽蓄在负荷低谷时抽水、高峰时发电的“削峰填谷”行为是否符合预期;第二张是上水库储能量变化曲线,正常情况应该是一个先下降后回升或者先上升后下降的平滑曲线,如果储能量曲线剧烈震荡,说明约束或惩罚项的位置有问题;第三张是弃风弃光功率曲线,用来验证多能互补的消纳效果。
很多同学喜欢只看一个总成本和收敛曲线就收工,这远远不够。抽蓄调度方案的合理性必须通过时序图来检验——比如夜间抽水功率恰好等于风电富余功率,说明消纳逻辑是对的;如果抽蓄在白天光伏大发时反而发电,那模型大概率出错了。
6.2 从简化算例到实际工程的升级路线
课题做完了如果想往工程应用方向延伸,这个模型有不少升级空间。一是把新能源出力的不确定性显式建模,比如用场景法或者机会约束规划来处理风电光伏预测误差,让调度方案具备鲁棒性。二是加入多时间尺度协调,日前计划、日内滚动修正、实时调整三层架构是实际调度系统的标准配置。三是把火电的启停费用和最小启停时间加进去,模型复杂度提高一个档次,但更贴近真实电网运行需求。
如果性能吃紧,可以试试把粒子群和局部搜索算法结合,做混合算法——用粒子群做全局搜索,再用fmincon做局部精修。这两个方法在Matlab里都有现成接口,组合使用效果往往比单一算法更好。
6.3 个人体会:先跑通后优化,再回归物理
这个课题做了三轮之后,我最深的体会是:调度优化项目的核心难点不在算法,而在模型物理含义的准确性。粒子群、差分进化、遗传算法,这些算法代码在网上都能找到成熟版本,真正决定结果可信度的是你对抽蓄运行规律、电力平衡约束、弃能惩罚机制的理解深度。很多同学找到一个标准的Particle Swarm代码就拿自己数据开跑,结果曲线很漂亮,成本也降了,但仔细一看抽蓄在白天高峰时段还在抽水,这明显不符合物理逻辑,整个结论就站不住脚了。
所以我强烈建议:在写完模型代码之后,先构造一个简单的两时段算例(比如低谷时段和高峰时段各1小时),手工计算一遍最优分配,再用完整模型去复现。这一步能帮你验证所有约束方程都写对了,再上大算例就会少走很多弯路。这种“先跑通、再优化、最后回归物理意义检验”的习惯,是我做这个课题积累的最重要的经验。
最后分享一个小技巧:调度模型代码版本管理一定要做好。从最简单的模型开始,每加一个约束就保存一个版本,加完跑一次测试。这样出现问题时可以快速知道是哪个改动引入了错误,不用对着几百行代码从头揪到尾。Matlab对文件夹路径要求严格,建议每个课题建立一个独立项目目录,把数据、主程序、适应度函数、结果图分开存放,运行环境保持一致,避免不同版本Matlab或工具箱差异带来的麻烦。