资讯动态

MATLAB+CPLEX微电网调度优化实战:MILP建模与代码全解析

发布时间:2026/9/30 4:12:14 来源:尧图企业网站定制
做微电网调度优化这几年MATLAB加CPLEX这套组合我用得最顺手也踩坑最多。微电网日前调度、日内滚动调度本质上都是带整数变量的优化问题MATLAB负责建模和数据处理CPLEX负责把混合整数线性规划MILP解出来这一对配合得好能极大缩短从数据到决策的链路。这篇文章把从模型搭建、环境配置、代码实现到常见报错排查的整套流程整理出来适合正在做毕业设计、科研课题或者工程项目但是被版本不兼容、接口报错、模型无解这些问题卡住的人。我最早接触这套方案是因为课题需要求解一个含储能和柴油发电机的微电网调度模型。当时试过MATLAB自带求解器、试过遗传算法也试过Python生态最后发现MATLAB建模 YALMIP封装 CPLEX求解是性价比最高、最不容易出错的路线。下面我会先把调度问题的本质讲清楚再解释为什么选这个组合然后给出完整的建模和代码实现最后分享几个真实项目里踩过的坑和排查经验。1. 微电网调度优化到底优化了什么1.1 调度需求背后的三个核心矛盾微电网调度优化听起来很专业其实落到实际就是一件事在满足用电需求的前提下怎么用最低的成本安排各类电源的出力。这里面存在三个核心矛盾。第一可再生能源出力不可控。光伏晚上不发电风电时大时小这些出力没法像火电那样按需调整所以必须靠柴油机、储能和电网交互来填补缺口。第二电价和负荷随时间波动峰谷价差让什么时候买电、什么时候自己发变得很关键。第三储能系统本身有容量、功率、充电放电效率等物理限制用多了会衰减不能只盯着眼前收益。调度优化就是把这几个矛盾统一成一个数学问题在满足功率平衡和设备约束的前提下求一组让总运行成本最小的机组出力计划、储能充放电计划和电网购售电计划。这个事情在实际工程里每天都要做光伏电站、风电场、园区微网、工厂能源管理都离不开。1.2 为什么这本质上是个混合整数线性规划问题刚才说的调度问题数学上是一个典型的混合整数线性规划MILP理解这个非常关键因为它决定了你后面选什么求解器、怎么写代码。MILP里有两类变量。连续变量用来表示功率大小比如柴油发电机出力、储能充电功率、从电网购电的功率这些可以在一个范围内取任意值。整数变量更常见的是0-1变量用来表示设备的启停状态比如柴油发电机开还是关、储能充还是放。为什么必须有0-1变量因为像柴油发电机这样的设备一旦开机就有最小技术出力不是任意功率都能维持运行。这时需要一个开关变量u把开和关两种状态隔离开来约束写成P_min * u ≤ P_g ≤ P_max * u当u0时出力只能为零当u1时出力必须在最小和最大出力之间。这个约束形式在调度问题里到处都是也是MILP区别于纯线性规划的核心原因。目标函数里各项成本通常也是线性的燃料成本近似线性、购电费用等于功率乘以分时电价、储能充放电寿命损耗也简化成线性形式。所以整个问题就是一个标准的MILP用通用求解器直接解不需要写启发式算法。1.3 调度问题的规模和求解要求这里聊聊调度问题的规模因为这直接关系到求解器的选型和优化效果。一个典型场景是日前调度时间尺度取1小时一天24个时段如果做日内滚动调度时间尺度可以细化到15分钟甚至5分钟一天就是96个或288个时段。每个时段都会有几个连续变量机组出力、储能充放电、购售电功率和几个0-1变量机组启停、储能状态。假设模型里有3台柴油机组、1台储能、1个电网关口按15分钟粒度一天96个时段变量数量大概在700到1000个约束数量会到1500到2000条。这个规模的MILP用MATLAB自带的线性规划求解器是搞不定的因为分支定界过程需要专用的整数求解器这就是CPLEX、Gurobi这类商用求解器的用武之地。2. 为什么偏偏是 MATLAB 和 CPLEX 这对组合2.1 MATLAB 在不务正业这件事上反而最好用很多做工程的人看不起MATLAB觉得它慢、贵、不工业级。但做调度建模MATLAB的矩阵思维和工具箱生态真是无可替代。调度模型里几乎所有约束都可以写成矩阵形式MATLAB天然就是按矩阵设计的语言写出来的代码可读性和维护性远好于Python里一大段numpy操作。举个例子SOC状态递推在MATLAB里可以很自然地用一个循环加上下标索引写出来在Python里很容易写出难以阅读的列表推导式或者花式切片。数据处理是另一个优势。调度模型需要大量输入包括历史负荷曲线、风电光伏出力预测、分时电价、设备参数。MATLAB的表格、时间序列工具箱、绘图能力让数据预览和结果验证非常方便。我习惯在求解前先画出负荷和光伏的曲线看一眼趋势再决定调度策略的侧重点这一点在纯求解器环境里很难高效做到。更重要的是MATLAB里有一个让所有建模人爱不释手的工具YALMIP。它相当于一个建模语言层你只需要声明sdpvar、binvar变量把约束和目标函数用最接近数学公式的方式写出来最后调用optimize命令YALMIP会自动把模型转换成求解器需要的格式再调用CPLEX求解。可以说YALMIP把写模型从翻译给机器变成直接写数学。2.2 CPLEX 到底强在哪里CPLEX是IBM的混合整数线性规划求解器在这个领域有几十年的积累。它最强的地方在于分支定界框架下的各种剪枝策略、割平面生成、启发式算法以及一套非常成熟的预处理机制。举个实际感受一个中等规模的微电网调度MILPCPLEX通常在几秒到几十秒内就能找到最优解。如果手写遗传算法可能跑几分钟甚至更久而且没有最优性证明。CPLEX还能输出MIP gap最优性间隙告诉你当前解距离理论最优还有多远这在论文和工程验收里是很重要的一项指标。另外CPLEX对LP和MILP内部的处理非常细腻比如它有专门的冲突检测功能模型无解的时候能帮你找出一组导致矛盾的约束定位问题效率很高。这种能力在调试大型模型的时候简直是救命稻草。2.3 与其他工具方案的对比我不止一次被问为什么不直接用PythonPython也有很成熟的优化生态Pyomo、PuLP、Gurobi的Python接口都很完善。但从我的实际体感来看两者各有取舍。方案建模便捷度求解能力数据处理/可视化适合人群MATLAB YALMIP CPLEX高接近数学语言强强科研、算法验证、教学演示Python Pyomo/OR-Tools CPLEX/Gurobi中需要学习类定义强中工程落地、上生产系统MATLAB 自带 solve intlinprog中整数规模受限中强小型问题、免安装第三方遗传算法等启发式算法低手动设计智能不保证最优中非线性复杂问题、演示算法原理选型的核心逻辑很直接如果模型是线性或混合整数线性的就应当用商用求解器走精确算法不要自己写启发式这不是说遗传算法没用而是杀鸡不用牛刀。如果你后续还要做非线性、多目标或者与控制策略联合仿真MATLAB路线明显更顺因为Simulink和MATLAB的工具箱可以直接衔接YALMIP算出来的结果。2.4 环境配置里最容易翻车的版本问题这里特别提醒一个几乎所有新手都会踩的坑MATLAB和CPLEX的版本要匹配CPLEX和YALMIP的接口也要匹配。CPLEX官方对每个版本会提供对应各MATLAB版本编译好的接口文件通常在安装目录下cplex/matlab里。你需要在MATLAB里运行addpath把这个目录加入路径。问题在于如果你的MATLAB版本太新而CPLEX版本太老接口编译就会出现兼容问题反过来老MATLAB加载新版CPLEX接口也可能报错。我目前最稳妥的配置习惯是MATLAB选近两三年的稳定版本CPLEX选12.9或更高版本YALMIP直接用GitHub上的最新开发版。另外CPLEX有免费的Community Edition限制了模型规模上限对教学演示和毕业论文这种规模基本够用但一定要去确认你的模型变量数没有超过限制。IBM官方注册下载后发现License文件配不好通常在启动求解器时直接报错后面第5章我会专门讲这一类问题的排查。3. 调度优化模型的完整拆解3.1 目标函数一天下来到底花了多少钱调度优化的目标通常是最小化总运行成本。最基础也最常用的形式包含四项第一项是柴油发电机燃料成本用机组出力乘以单位燃料成本系数为了区分启停通常还会加上一个与开关状态相关的启停成本。第二项是从电网购电的费用等于购电功率乘以分时购电价。第三项是向电网售电的收入因为这是收益在最小化问题里取负号。第四项是储能充放电带来的寿命损耗成本很多模型里会简化成充放电电量乘一个很小的损耗系数用来防止储能频繁无意义地动作。目标函数写成数学形式就是这样的形式每一项都是线性的min Σ_t [ c_fuel * P_g(t) c_start * max(0, u(t)-u(t-1)) price_buy(t) * P_import(t) - price_sell(t) * P_export(t) c_bat * (P_ch(t) P_dis(t)) ]这里启停成本那一项严格写是 max但在MILP里我们一般直接线性化把启停逻辑拆成两个约束后面代码部分会说。3.2 约束条件物理世界写进数学模型约束条件分成四大类。第一类是功率平衡约束这是必须守恒的。在任何时刻所有电源出力加上储能放电加上购电功率必须等于负荷加上储能充电功率加上售电功率。这个约束是等式约束它决定了整个调度方案的可行性。第二类是机组运行约束包括出力上下限、最小运行/停机时间、爬坡速率限制。我们上一节提到的P_min * u ≤ P_g ≤ P_max * u就是出力上下限和开关状态的耦合约束。爬坡约束限制机组相邻两个时段出力变化不能太大防止调度指令对机组运行造成冲击。第三类是储能约束。储能的荷电状态SOC按递推关系变化SOC(t1)等于SOC(t)加上充电量减去放电量并考虑充放电效率。SOC本身有上下限一般不让它低于20%或高于90%这样有利于延长电池寿命。充放电功率也各有上限而且理论上不应该同时充电和放电。我们通常会通过目标的成本设置让求解器自动避免同时充放因为充电和放电都有损耗成本同时进行只会增加损失。第四类是与电网交互的约束购电功率和售电功率分别有上限这个上限就是微电网与外部电网联络线的传输容量。多数情况下购电和售电不同时发生这一点可以由电价结构自动保证但严谨起见也可以加0-1变量强制互斥。3.3 数据准备你的模型效果取决于输入质量模型写得再漂亮输入数据质量差也白搭。做调度优化至少需要以下几类数据。负荷曲线是最基本的数据如果是园区微网就去读关口电表的负荷数据如果做研究可以选用公开的IEEE负荷模型或者澳大利亚、欧洲的微网数据集。光伏和风电的预测出力曲线工程上来自气象预报加功率预测系统研究时可以直接用历史数据或模拟数据。分时电价信号需要明确是工商业峰谷电价还是现货市场价格。设备参数包括机组功率上下限、爬坡率、储能容量与效率、联络线容量。我用一个实操习惯在正式建模前先把所有输入曲线画到一张图上肉眼检查有没有明显异常值同时算一下一天的总发电潜力是否覆盖总负荷否则模型几乎注定无解。这个预检查会为你省下大量调模型的精力。4. 核心代码实现从建模到算完结果4.1 用 YALMIP 声明变量和参数下面给出一段可以跑通的日前调度示例代码。为了让代码短一些示例里只包含一台柴油发电机、一台储能、一个电网关口光伏和风电作为预测值直接给定。先看变量声明部分% 微电网日前调度示例MATLAB YALMIP CPLEX clear; clc; % 基本信息 T 24; % 调度时段数小时 dt 1; % 步长小时 % ---------- 输入数据这里按实际场景替换 ---------- % 负荷曲线kW示例给个带早晚高峰的序列 P_load [80,75,70,68,70,90,120,150,165,170,160,145,... 140,150,155,160,150,165,180,190,185,170,140,100]; % 光伏出力kW夜间为零白天有峰 P_pv [0,0,0,0,0,5,20,45,70,85,90,88,82,75,65,50,30,12,0,0,0,0,0,0]; % 风电出力kW随意给的波动序列 P_wt [35,38,36,30,28,25,22,20,24,30,36,40,42,38,32,28,26,25,30,34,38,40,36,32]; % 分时购电电价元/kWh峰平谷三段电价 price_buy [0.40,0.40,0.40,0.40,0.40,0.55,0.85,0.85,0.85,0.85,0.85,0.65,... 0.65,0.85,0.85,1.10,1.10,1.10,1.10,0.65,0.65,0.55,0.40,0.40]; % 售电电价高于低谷购电价很多会制造套利空间这里设得低一些 price_sell 0.25 * ones(1,T);这里要解释一下为什么我把数据单独放前面。调度优化有一个很常见的问题就是算出来的方案在现实中没法执行一个主要原因是输入数据只在方案里真实、在控制器里过期。把数据集中放在代码最前面后续替换成实时预测数据非常方便这是工程落地的基本素养。4.2 设备参数设置与决策变量声明设备参数放在数据后面接着声明所有决策变量% ---------- 设备参数 ---------- % 柴油发电机 P_g_min 20; % 最小出力 kW P_g_max 100; % 最大出力 kW c_fuel 0.9; % 发电成本系数 元/kWh c_start 30; % 单次启动成本 元 Ramp_max 40; % 每小时爬坡上限 kW % 储能 E_bat 200; % 电池容量 kWh SOC_init 0.5; % 初始荷电状态 SOC_min 0.2; % 最低荷电状态 SOC_max 0.9; % 最高荷电状态 P_ch_max 60; % 最大充电功率 kW P_dis_max 60; % 最大放电功率 kW eta_ch 0.95; % 充电效率 eta_dis 0.92; % 放电效率 c_bat 0.05; % 储能损耗成本 元/kWh % 电网联络线 P_grid_max 100; % 关口交换功率上限 kW % ---------- 决策变量 ---------- P_g sdpvar(T,1); % 发电机出力 u_g binvar(T,1); % 发电机启停状态 P_ch sdpvar(T,1); % 储能充电功率 P_dis sdpvar(T,1); % 储能放电功率 P_import sdpvar(T,1); % 购电功率 P_export sdpvar(T,1); % 售电功率 SOC sdpvar(T1,1); % 荷电状态注意多了一个时刻点 % 启动指示变量用于线性化启停成本 v_start binvar(T,1);这里两个细节值得说明。SOC声明成T1个时间点是为了把初始时刻和最后时刻都包含进去递推关系从SOC(1)走到SOC(T1)这样末尾SOC的约束可以直接写。另一个是启停指示变量v_start它的作用是线性化机组从停机变为开机这个逻辑用两个约束来控制v_start(t) u_g(t) - u_g(t-1)且 v_start(t) 0这样只有当u_g从0变成1时v_start才必须为1启停成本才会被计入。4.3 约束建模的核心写法约束条件是整个模型的灵魂YALMIP里声明约束可以用中括号拼接起来C []; % 1) 功率平衡约束每个时段都要满足 C [C, P_g P_pv P_wt P_dis P_import ... P_load P_ch P_export]; % 2) 发电机出力上下限并与启停状态耦合 C [C, P_g_min * u_g P_g P_g_max * u_g]; % 3) 发电机爬坡约束t从2到T for t 2:T C [C, -Ramp_max P_g(t) - P_g(t-1) Ramp_max]; end % 4) 启停成本的线性化约束 C [C, v_start u_g - [0; u_g(1:end-1)]]; C [C, v_start 0]; % 5) 储能SOC递推关系 SOC_eff [SOC(1:T) (eta_ch * P_ch - P_dis / eta_dis) * dt / E_bat]; C [C, SOC(2:end) SOC_eff]; % 6) SOC与充放电功率上下限 C [C, SOC_min SOC SOC_max]; C [C, 0 P_ch P_ch_max]; C [C, 0 P_dis P_dis_max]; % 7) 电网交互功率上下限 C [C, 0 P_import P_grid_max]; C [C, 0 P_export P_grid_max];这段里最需要注意的是爬坡约束的写法。如果发电机组的第一个时段没有爬坡限制那么循环从2开始就可以但如果你模型里机组在t1之前本来就在运行那需要给SOC和爬坡都补上初始状态信息。很多模型无解就是这里初始状态没有定义清楚。另外关于储能SOC递推我把效率放在了充电项和放电项上充电时乘eta_ch打入电量打折扣放电时除以eta_dis放出所需电量需要多消耗。这个处理更接近实际能量转换过程。注意SOC表达式中P_ch和P_dis都是向量eta_ch * P_ch - P_dis / eta_dis是向量运算YALMIP对这种逐时段的向量操作支持得很好。那要不要加充放电互斥的0-1约束我见过很多代码强行加了这个约束但代价是增加一组0-1变量求解变慢。实际工程里因为充电和放电都有损耗成本电价结构正常时求解器自动就不会同时充放因为同时充放意味着白白消耗两次效率损失。只有在使用实时电价且出现极度异常的价格波动时才可能同时充放形成套利路径这种情况我在后面第5章会专门分析。4.4 目标函数、求解命令与结果提取目标函数和求解调用是这样写的% ---------- 目标函数 ---------- Objective sum(c_fuel * P_g c_start * v_start ... price_buy .* P_import - price_sell .* P_export ... c_bat * (P_ch P_dis)); % ---------- 求解 ---------- ops sdpsettings(solver,cplex,verbose,1,... solver.cplex.mip.tolerances.mipgap,0.001,... solver.cplex.mip.limits.timelimit,120); optimize(C, Objective, ops); % ---------- 结果提取与展示 ---------- P_g_opt value(P_g); P_ch_opt value(P_ch); P_dis_opt value(P_dis); P_imp_opt value(P_import); P_exp_opt value(P_export); SOC_opt value(SOC); u_g_opt value(u_g); fprintf(最优运行成本%.2f 元\n, value(Objective));我把mipgap设为0.001意思是允许最优解和理论最优值有0.1%的差距。为什么要放宽这一丁点因为对微电网调度来说0.1%的成本差距换算成钱可能只有几块钱但能显著减少分支定界的搜索时间。工程上不追求数学意义上的绝对最优而是可接受的最优这个理念一定要在论文写求解精度的时候讲清楚。结果提取后我用两条曲线最能说明问题一条是功率平衡总览把负荷、各电源出力、储能充放电堆叠在一张面积图里另一条是SOC曲线。堆叠面积图能直观看到有没有时段功率不平衡SOC曲线能看出储能有没有在谷时充电、峰时放电。5. 实战中踩过的坑常见问题与排查技巧5.1 版本兼容与License报错我遇到最多的报错就是MATLAB调用CPLEX时提示找不到求解器或者直接报License Error -8、license manager error -8这类信息。-8错误的原因绝大多数是IBM License Manager没有正确启动或者环境变量里的LM_LICENSE_FILE指向了错误的license文件路径。排查顺序我基本固定先确认CPLEX自带的示例能否在命令行跑通能跑通就说明License本身没问题再确认MATLAB里path是否已经包含\cplex\matlab目录最后确认环境变量是否在重启之后就失效了。另一个经常出现的问题是CPLEX的matlab目录下没有适配你当前MATLAB版本的文件夹。IBM发布CPLEX时会对应当时的主流MATLAB版本如果你用了太新的MATLAB你可能要往低版本找一个接近的目录手动addpath或者干脆用YALMIP的非官方接口方案绕过。我个人的建议是不要把系统MATLAB版本追新稳定版本配稳定求解器这个组合一旦跑通就别乱动。5.2 模型无可行解的排查方法论模型无解也就是infeasible是所有优化建模者最常遇到的噩梦。一个二十四小时模型加起来几百条约束其中某一条写错CPLEX直接告诉你找不到可行解而且默认输出里的报错信息对新手几乎不友好。我的排查思路大概是三步。第一步先用CPLEX的冲突检测功能。在sdpsettings里设置solver.cplex.emphasis.advance,0之类的参数不能直接定位更有效的是在CPLEX交互环境下用display conflict all或者用YALMIP的optimize(C,Objective,ops)返回的sol.problem配合sol.info来看内部诊断信息。YALMIP有些版本会直接输出Problem is infeasible并给出哪些约束组的维度有问题。第二步用变量收敛检查。把SOC的上下限暂时放开把功率平衡等式改为不等式逐步放宽约束来定位是哪一类约束导致无解。我把SOC_min改成0、SOC_max改成1同时把功率平衡改成的形式如果这时候模型有解基本可以断定是储能约束或者功率平衡写得太苛刻。第三步检查初始条件。这是最容易被忽视的。SOC(1)等于0.5但如果你设了SOC(1)固定为某个值的同时又要求SOC(2)和SOC(1)之间的递推关系严格守恒而初始时刻的充放电功率和光伏出力无法满足从0.5走到合理范围那也会无解。解决方法是把初始SOC从一个等式约束改成不等式约束比如SOC(1)不低于0.4即可给求解器更多灵活空间实际工程中这更合理。5.3 求解性能变差的常见根源与对策如果你的模型没报错算得慢通常出在三个地方。第一0-1变量太多。每加一个0-1变量分支定界树的分支数就翻一倍所以能用连续松弛就尽量别引入离散。我在实际中会把储能状态模型尽量简化不做充放互斥就能省掉24个0-1变量。对微电网这种规模这个简化非常值得。第二约束里出现了大数和小数混写。比如容量用kWh功率用kW时间步长1小时递推公式里SOC变化值可能只有0.1量级而电压或者别的参数动辄上万这种数量级差异会严重影响数值稳定性。这个时候建议把单位统一比如储能容量用kWh、功率用kW并且把SOC直接写成0-1的标幺值形式问题往往就消失了。第三时间步长太细导致时段数暴涨。把96时段改成288时段后CPLEX求解时间可能不是线性增长而是指数级增长。如果只是方案预研完全可以用粗时间尺度先把策略跑通再对关键时段细化。5.4 充放电同时发生的背后原因前面我提过理论上电价正常就不会同时充放但如果你实际算出来充电和放电功率在同一条曲线上都有正值而且相加抵消那就要检查三件事。先看你是不是没加储能损耗成本c_bat。如果没有这一项模型的解空间里会出现充电1度同时放电1度这个零成本但能量无意义的操作因为SOC充放抵消但电量不守恒反而能利用效率差产生收益这属于模型漏洞。另一个可能原因是电价出现了负值时段比如部分现货市场极端场景下电价为负此时从电网取电不仅不花钱还赚钱模型当然会大量充电放电做循环。这虽然看起来奇怪但在真实市场里存在而且提醒你模型是不是被人为创造出了套利机会。最后一个原因是储能效率的数值设置如果eta_ch和eta_dis都设成1效率损失为零模型对同时充放不敏感加一点微小的c_bat就可以抑制。6. 从基础模型到进阶方向6.1 不确定性的引入从确定性到随机优化与鲁棒优化基础版的日前调度把所有输入当成已知但实际中光伏出力预测和负荷预测总有误差。这块最常见的是两类进阶做法。随机优化假设光伏出力服从某个概率分布通过采样生成多个场景把目标函数写成期望成本模型变成一个大规模MILP。它的代价是变量和约束数量随场景数线性增长CPLEX求解时间会明显增加通常会把场景数控制在几十到上百个。鲁棒优化则完全换了思路不追求期望最优而是保证在预测误差落在某个不确定集合内时方案都可行。它把约束写成最坏情况下的形式模型规模可能更小但求解往往需要迭代算法这时MATLAB脚本里写循环调CPLEX就很常见。我个人经验是对微电网这种规模不大但对可靠性要求高的场景鲁棒优化配合YALMIPCPLEX的落地效果优于随机优化。6.2 从单目标到多目标成本、碳排放与新能源消纳纯粹最小化运行成本会带来一个副作用模型尽量多买电网电因为电网电价低的时候比自己发电便宜但这会让柴油机组闲置也不利于提升可再生能源消纳比例。多目标优化可以让模型在成本、碳排放、弃电率之间做权衡。常见的实现方式有加权求和法、epsilon约束法。加权求和最简单但权重选择主观epsilon约束法是先把最关心的目标比如碳排放作为约束限定上限再最小化成本得到一组帕累托前沿解。这种多目标弹性的模型在课题研究里很常见代码上只需要把目标函数改一改约束加一条YALMIP的框架完全不用动。6.3 与控制策略、强化学习的衔接很多人搜到微电网调度MATLAB时同时会看到DQN算法MATLAB实现、PPO算法MATLAB实现这些关键词。它们之间的关系其实很清晰优化调度提供的是理想的最优基准强化学习追求的是在线决策的近似最优。如果你的环境变化很快负荷和光伏预测频繁刷新CPLEX这种离线求解器没法实时响应这时候把离线优化算出的最优解当作专家策略用其生成训练数据再训练一个深度强化学习模型来做实时决策是一个非常流行的课题方向。YALMIPCPLEX算出的结果可以作为强化学习环境里的最优动作标签或者奖励函数设计依据两者不是替代关系而是配合关系。我见过不少论文就是先用CPLEX算一批离线轨迹然后拿这些轨迹去训练DQN或PPO最后对比两者在在线场景下的表现差距。7. 几个从我项目里沉淀下来的实操心得最后说几个我做了多年调度项目后沉淀下来的习惯不一定写进标准教程里但很实用。一是建模型一定要保持可读性。变量命名建议统一用P_g、P_ch、SOC这种不要用x1、x2。调度模型要反复调试和迭代代码本身就是你唯一完整的模型文档用数学符号当变量名检查约束公式时能直接对应起来省下来的时间远大于命名时多打几个字符。二是所有求解结果都要跟物理直觉对一遍。算完先看成本构成比例再看储能SOC曲线是否呈现谷充峰放再看柴油机是否在峰时启动。如果结果不符合直觉八成不是求解器错了而是模型约束或参数出了问题。我遇到过有人算了三天发现SOC曲线完全反着走最后发现效率公式里除号写错了这种低级错误跟直觉对一眼就能看出来。三是一定要保留求解日志。CPLEX的verbose参数开高一点日志里会有MIP gap变化和求解时间。我每次跑完都把日志保存下来一方面写报告时可以用另一方面对比参数调整前后性能差异这个习惯在调大型模型时特别有用。四是拘泥于绝对最优值没有意义。微电网调度里输入数据都是预测值预测精度本身有限你花很大力气把MIP gap从0.1%压到0.01%对真实运行成本的改善微乎其微。倒不如把时间省下来做敏感性分析看看哪些参数对结果影响最大这对实际决策的帮助反而更大。MATLAB加CPLEX这套方案本身不难难的是把模型、数据和业务理解串在一起。你要是从这篇能先把一个完整的日前调度模型跑通再往后无论是加不确定性、加多目标还是接强化学习都有了扎实的地基。遇到具体报错别慌按版本、无解、性能、结果合理性这个顺序排查多数问题都能定位到具体环节。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑