拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

微电网合作型Stackelberg博弈的Matlab+Cplex优化调度实现

微电网合作型Stackelberg博弈的Matlab+Cplex优化调度实现 做过一段时间微电网优化调度的人,应该都有这种体会:单层优化模型解起来顺手,但一到“你的决策会改变对方的决策,对方的响应又反过来影响你的收益”这种场景,传统方法就显得笨拙。这篇博文想分享的是我用MatlabCplex实现的一个思路:把微网运行问题建模为合作型Stackelberg博弈,也就是运营商先定价格策略,用户侧再基于价格调整用电行为,而双方通过合作协议共同保证整体效益。项目本身并不算宏大,但博弈建模、双层优化转单层求解、Cplex与Yalmip的搭配调试,前前后后踩了不少坑,把这些经验写出来,希望对正在做微网交易策略、需求响应或者刚接触博弈优化的朋友有些参考价值。这篇文章不打算堆公式大全,而是把一个能跑通、能出结果的项目从建模到代码到调参完整拆开讲。不管你是刚开始接触Stackelberg博弈,还是已经在用Cplex做混合整数规划,里面涉及的双层转单层逻辑、KKT条件处理、大M法线性化、Cplex求解报错排查,都可以直接借鉴。尤其如果你正卡在“模型明明写得对但求解器就是不收敛”“Yalmip调Cplex一直报错”这类问题上,建议重点看第3节和第6节。1. 项目定位与核心问题拆解1.1 微网运行策略为什么需要博弈论先说一个很现实的问题:传统微网优化调度的目标函数通常是“系统总运行成本最小”或者“某个运营商收益最大”,它背后的假设是整个微网只有单一决策者,所有分布式电源、储能、负荷都听调度中心的指挥。这在模型里当然可以成立,但放到实际运行场景里就有点理想化了。真实的微网中,分布式光伏/风电的业主、储能运营商、终端用户是不同利益主体。用户看到电价高会主动降低用电或者转移负荷,看到电价低会增加用电甚至给电动汽车充电。也就是说,用户的行为会跟随运营商的定价策略变化,而运营商的收益又受到用户负荷曲线的影响——这本质上就是一个“你先出牌、我再出牌”的递阶决策问题。这类问题用单层优化处理,要么忽略用户的响应特征,导致出清结果在实际执行时严重偏离;要么干脆假设用户完全被动,这在市场化环境下已经不适用了。Stackelberg博弈正好天然匹配这种主从递阶结构:上层是微网运营商(领导者),先制定分时电价、储能充放电计划、与配网的交互策略;下层是用户(跟随者),在给定的价格信号下选择最优用电量。求解的时候不需要人为规定谁服从谁,而是让双方各自最优化,最终达到一个双方都接受的均衡状态。1.2 “合作型”到底意味着什么很多人看到Stackelberg博弈第一反应是“这不就是主从博弈,双方对抗嘛”。基础版确实是这样,但在微网场景下,如果我们让各方完全非合作,容易得到一个低效率的均衡:运营商为了自身收益把电价抬得很高,用户削减负荷,双方收益都不好。实践中更常见的做法是引入合作机制——双方通过协议约定收益分配或成本分摊规则,形成联盟后总收益大于各干各的收益之和,然后再把增量收益按照一定规则分配。这就是“合作型Stackelberg博弈”的核心:博弈层级仍然是主从结构,但利益关系不再是零和对抗,而是“先做大蛋糕,再分蛋糕”。对应到模型里,上层目标可以是微网整体社会福利最大化或联盟总收益最大化,下层用户仍然最大化自身效用,最后通过Shapley值、核仁或者简单比例分配等方式把系统增量收益分给各参与方。这样做出来的策略,既保留了价格引导需求的市场机制,又在整体效率上比纯非合作博弈更优,这也是当前园区级微电网、虚拟电厂撮合交易中比较受关注的设计思路。1.3 项目整体技术路线整个项目的实现路线可以概括为四步:第一步是搭建上下层决策模型,明确双方目标函数、决策变量和约束;第二步是把下层用户的优化问题用KKT条件替换,将双层模型转化为单层数学规划;第三步是处理互补松弛约束中的非线性项,通过大M法引入0-1变量,转化成混合整数线性规划;第四步用MatlabYalmip建模、调用Cplex求解,并对结果做收益分配与灵敏度分析。这个路线本身具有很强的通用性,换一套目标函数、换一批约束条件,比如把用户侧换成电动汽车聚合商、把上层换成配电网运营商,整体求解框架依然适用。这也是我比较推荐花时间把博弈模型和求解流程吃透的原因——不是只为了跑通一个项目,而是后续可以复用到很多类似的能源交易场景中。2. 数学建模:合作型Stackelberg博弈的完整框架2.1 上层运营商模型上层决策者一般设为微网运营商,它负责制定微网内部的购售电价、向配网购电/售电的计划,以及储能系统的充放电策略。目标函数我采用的是联盟总收益最大化,而不是运营商单方面利润最大化——这是“合作型”的一个关键落点。上层目标函数包含以下几块:向用户售电的收入、从配网购电的成本、分布式电源出力的运行维护成本、储能充放电的损耗成本。如果考虑更细一点,还可以加入向配网售电的收益、碳交易成本、需求响应补贴等。以调度时段t为单位,典型形式是:[ \max \sum_{t} \left( C_{sell,t} P_{load,t} - C_{grid,t} P_{buy,t} - C_{DG} P_{DG,t} - C_{ess} |P_{ess,t}| \right) ]其中 (C_{sell,t}) 是运营商向用户售电的分时电价,(P_{load,t}) 是用户总用电负荷,(C_{grid,t}) 是配网购电电价,(P_{buy,t}) 是向配网购电功率,(P_{DG,t}) 和 (P_{ess,t}) 分别是DG出力和储能充放电功率。上层约束包括微网功率平衡约束、储能SOC递推方程、储能充放电功率限值、与配网交互功率限值。功率平衡是所有微网模型的核心约束,表达式就是DG出力加储能放电加购电功率,等于用户负荷加储能充电,简单但必须严格满足。这里有个经验教训:储能SOC的递推约束,也就是 (SOC(t1) SOC(t) \eta_c P_{ch}(t) - P_{dis}(t)/\eta_d),建议把充放电拆成两个非负变量分别建模,而不是用一个带正负号的 (P_{ess})。否则目标函数里的绝对值项、约束里的充放电效率都很难线性化处理,后面转MILP时会非常痛苦。2.2 下层用户响应模型下层是用户侧,用户收到运营商给定的电价后,根据自己的用电偏好决定用电量。经济学里描述这种偏好最常用的是二次效用函数:[ U(P_{load}) \alpha P_{load} - \frac{1}{2}\beta P_{load}^2 ]这个函数的一阶导数是边际效用,(\alpha) 代表基础用电偏好,(\beta) 代表边际效用递减速度。用户的目标是最大化“用电效用减去电费支出”:[ \max_{P_{load}} \left[ U(P_{load}) - C_{sell} P_{load} \right] ]对 (P_{load}) 求导并令导数等于零,可以直接得到用户的最优响应函数:[ P_{load} \frac{\alpha - C_{sell}}{\beta} ]这个式子非常漂亮,它把所有交互逻辑都压缩到了一行公式里:电价 (C_{sell}) 越高,用户用电量越低;用户偏好 (\alpha) 越大,用电量越大。这个响应函数就是下层的“理性反应”,也是Stackelberg博弈中“跟随者”策略的核心。实际项目中用户侧不会这么单薄,还可以加上可转移负荷、可中断负荷、电动汽车充放电约束、用户用电量上下限等。下限保证用户的基础用电需求,上限限制功率容量。如果是电动汽车聚合商作为下层,还需要SOC约束和充放电时间窗约束。但不管下层怎么换主体,核心结构都是“给定价格→优化用电→得到响应函数/KKT系统”,这个套路是通用的。2.3 合作收益分配机制前面说合作型博弈要“做大蛋糕”,那蛋糕做大了怎么分?这一步在模型里体现为两层含义:一层是在目标函数层面,上层不再纯粹追求自身利润,而是追求联盟总收益最大化;另一层是在结果后处理阶段,把联盟总收益与各成员非合作均衡下的收益之差作为“增量收益”,通过分配规则分给各成员。分成比例可以是提前谈判好的固定Shapley值,也可以是按贡献度计算的边际收益分配。在Matlab实现里,分配逻辑并不参与优化求解,而是在博弈均衡解出来之后单独计算。比如计算各参与方单独运行时的收益、两两联盟时的收益、三方联盟时的收益,再用Shapley值公式计算分配系数。算例规模不大时直接穷举联盟组合就行,不需要额外调求解器。强调一点:合作分配机制虽然不直接影响Cplex求解过程,但它决定了联盟成员是否愿意执行博弈结果。很多论文只做了上层收益最大化,算完发现用户侧收益反而下降了,这种方案实际根本推不下去。我建议在模型目标函数里至少包含一个“用户侧总效用项”,或者在后处理环节明确展示用户收益变化。3. MatlabCplex环境搭建与踩坑记录3.1 版本搭配与Cplex Community这个项目我用的是Matlab和IBM ILOG CPLEX。先聊安装和版本匹配问题,这里坑比较多。Cplex分商业版和Community Edition社区免费版。社区版可以在IBM官网直接申请下载,功能上是完整的,但模型规模有硬限制:变量数不超过1000个、约束数不超过1000个。很多同学不知道这个限制,模型稍微复杂一点就报“out of memory”或者“model too large to load”,其实是社区版的限制,不是电脑内存不够。版本搭配方面,Cplex从12.9开始支持到Matlab R2021a,12.10支持到R2021b,Cplex 22.1支持的Matlab版本范围更宽一些,基本覆盖了R2023a到R2024系列。这里强烈建议先用ver命令确认Matlab版本,再去IBM官网查对应Cplex版本支持列表。我自己遇到过明明是正确安装流程,但yalmsetup检测不到Cplex的问题,后来发现是Cplex版本太老,和Matlab新版本不兼容。另外一个入口是用Yalmip作为建模层。Yalmip相当于一个翻译层,它把MATLAB里写的优化模型自动翻译成Cplex能识别的格式。强烈推荐:不要直接用Cplex的MATLAB原生API写约束,那玩意儿调试起来非常折磨人。Yalmip语法简洁,写约束、改目标、换求解器都方便,而且可以随时切到Gurobi、Mosek做结果对比验证。安装完成后,验证是否配置成功:yalmsetup % 如果Yalmip版本正常会列出已检测到的求解器 cplex_getVersion % 或直接调用 cplex.getVersion3.2 Yalmip建模的工程习惯用Yalmip建模微网调度问题,我有几个长期沉淀下来的习惯,适合从第一天就照着做。第一,所有变量先统一声明,用sdpvar声明连续变量,binvar声明0-1变量。决策变量多的时候建议用结构体封装:比如x.Pgrid sdpvar(1,24); x.Pess sdpvar(1,24);,这样后面写约束和目标函数时结构非常清晰,而且不容易出现变量名称混淆的问题。第二,所有约束收集到一个变量里,不要散着写。常见的写法是:Constraints []; Constraints [Constraints, Pgrid 0]; Constraints [Constraints, SOC(2:25) SOC(1:24) eta_ch .* Pch - Pdis ./ eta_dis];第三,求解器设置用sdpsettings统一控制。最核心的两个参数是solver,cplex和verbose,2。前者指定求解器,后者控制求解过程的输出信息。还建议设置cplex.mip.timelimit,600,防止复杂模型卡几个小时无返回值。我特别注意变量上下界约束一定要写完整,尤其是储能出力、购售电功率,不要以为Cplex会自动限制变量范围。没写界的变量一旦进入目标函数,求解器会因为目标无界而报错,而这种情况的报错信息又很难一眼看出来原因。3.3 Cplex求解器切换与结果验证模型建完之后,先用Cplex求解,如果结果奇怪或者求解时间异常,我建议立刻换个求解器交叉验证。比如把solver从cplex换成gurobi或者mosek,如果线性规划部分的解和Cplex一致,说明模型没问题,问题出在求解器参数或数值稳定性上。用Yalmip还有个特别方便的调试方法:求解完成后检查val value(Objective)是否合理,再逐个查看关键约束的dual值。对偶变量代表了约束的边际价值,在双层博弈中,上层问题的对偶变量往往有明确的经济学含义——某个约束的影子价格就是它对应的市场电价或者边际成本。我调试模型时经常通过观察对偶值判断约束是否激活,比单纯看目标函数值有效得多。4. 双层博弈转单层:核心求解逻辑与代码构造4.1 为什么要把双层转为单层Stackelberg博弈的直接求解思路是迭代:上层给一个价格,下层求最优响应,上层根据响应再调整价格,直到收敛。这个思路实现简单,但它有两个致命问题。一是没法保证收敛到全局均衡,迭代过程可能振荡;二是每次迭代都要调用一次Cplex,调度周期24小时、变量上百个,迭代几十次求解时间非常感人。所以我采用更主流的数学转换方法:把下层用户的优化问题用KKT条件替换,并入上层模型的约束中。这样原本的“上层-下层”结构就变成了“上层-下层KKT条件”的单层数学规划。虽然复杂度提升了,但Cplex可以直接对单层做全局求解,不再依赖迭代收敛。当然,转换后得到的单层模型不是标准线性规划,而是带互补约束的数学规划,还需要进一步线性化。线性化方法见4.3。4.2 KKT条件推导与代码实现用户侧优化问题如下:[ \max_{P_{load}} \left( \alpha P_{load} - \frac{1}{2}\beta P_{load}^2 - C_{sell} P_{load} \right) ] [ s.t. \quad P_{load}^{min} \leq P_{load} \leq P_{load}^{max} ]对应的KKT条件包含三部分:拉格朗日函数对 (P_{load}) 的偏导为零、原始约束的可行性、互补松弛条件。用Yalmip写这个系统其实可以直接通过kkt命令生成,但工程上我建议手动写出KKT系统再线性化,原因后面说。Yalmip实现的一个便捷写法:Pload sdpvar(1,24); Csell sdpvar(1,24); % 上层变量作为参数出现 % 下层目标函数(用户效用-电费) Obj_user sum(alpha .* Pload - 0.5 .* beta .* Pload.^2 - Csell .* Pload); % 下层约束定义 Constraints_user [Pload_min Pload Pload_max]; % 用Yalmip的kkt命令生成KKT系统 [KKT_system, details] kkt(Constraints_user, Obj_user, Pload);kkt的好处是自动处理拉格朗日乘子、梯度条件、互补松弛约束,省去手动推导的繁琐。但它有个问题:生成的KKT系统里带有乘积项(决策变量互为函数),这会导致最终模型变成非线性。想直接丢给Cplex,就必须再做线性化。4.3 互补松弛条件的大M法线性化KKT条件中最麻烦的是互补松弛项,形式是 (0 \leq \lambda \perp g(x) \geq 0),意思是拉格朗日乘子 (\lambda) 和约束间隙 (g(x)) 至少有一个为零。这个条件本身是一个逻辑关系,不是线性等式或不等式,没法直接交给Cplex的单纯形法MIP求解器处理。标准做法是引入0-1变量和大M常数。以不等式约束 (g(x) \geq 0),乘子 (\lambda \geq 0) 为例,等价地引入 (z \in {0,1}),写为:[ g(x) \geq -M(1-z), \quad \lambda \leq M z ]如果 (z1),则 (g(x) \geq 0) 正常生效,(\lambda \leq M) 被放松;如果 (z0),则 (\lambda0),约束可以被放松。这一线性化技巧能将KKT系统转成混合整数线性约束。这里我特别提醒:M常数不能取得太随意。M太小会切断可行域,导致原本可行的解被排除;M太大会引起数值稳定性问题,Cplex常用的对偶单纯形法对这类大M惩罚系数很敏感。经验做法是取相关变量理论上界的10到20倍。比如电价上限是1.2元/kWh,电价变量的M取20到50就能兼顾。实际调试时,如果发现Cplex报“numerical difficulties”,优先检查M的取值。4.4 完整模型框架代码示例这里给出一个简化但结构完整的主干代码,覆盖双层转单层的全过程。完整项目还有大量业务约束,不宜全部贴出,但核心求解框架是这样的:%% 定义上层变量 Csell sdpvar(1,24, full); % 售电价 Pgrid sdpvar(1,24, full); % 与配网交换功率 Pess sdpvar(1,24, full); % 储能出力 SOC sdpvar(1,25, full); % 储能SOC %% 定义下层变量及KKT系统 Pload sdpvar(1,24, full); % 用户负荷 lambda_lb sdpvar(1,24, full); % 变量下限乘子 lambda_ub sdpvar(1,24, full); % 变量上限乘子 % 下层最优性条件(用户效用最大化一阶条件) % d(alpha*P - 0.5*beta*P^2 - Csell*P)/dP alpha - beta*P - Csell 0 Stationarity [alpha - beta .* Pload - Csell lambda_ub - lambda_lb 0]; % 互补松弛 z_lb binvar(1,24); z_ub binvar(1,24); M 100; Comp_1 [Pload - Pload_min -M .* (1 - z_lb)]; Comp_2 [lambda_lb M .* z_lb]; Comp_3 [Pload_max - Pload -M .* (1 - z_ub)]; Comp_4 [lambda_ub M .* z_ub]; %% 上层约束 Constraints [Stationarity, Comp_1, Comp_2, Comp_3, Comp_4]; Constraints [Constraints, SOC(2:25) SOC(1:24) eta_ch .* max(Pess,0) - min(Pess,0)./eta_dis]; Constraints [Constraints, SOC_min SOC SOC_max, SOC(1) SOC(25)]; Constraints [Constraints, Pgrid_min Pgrid Pgrid_max]; Constraints [Constraints, Pload_min Pload Pload_max]; %% 上层目标函数(联盟总收益最大化) Revenue sum(Csell .* Pload); Cost_grid sum(Cgrid .* Pgrid); Cost_dg sum(Cdg .* Pdg_fixed); Objective Revenue - Cost_grid - Cost_dg; %% 求解 ops sdpsettings(solver, cplex, verbose, 2, cplex.mip.timelimit, 300); optimize(Constraints, -Objective, ops); % Yalmip默认最小化 %% 结果还原 Csell_opt value(Csell); Pload_opt value(Pload); Pgrid_opt value(Pgrid);有一个细节:Yalmip默认最小化目标函数,所以这里传-Objective。储能充放电我为了代码简洁用了max(Pess,0)的形式,但如果你执意要严格线性化,记得把储能拆成充电和放电两个非负变量,然后分别加效率和容量约束。4.5 求解成功后的结果检查求解结束不等于结果就能用,我通常做三组检查。第一是检查求解状态和信息.optimize返回的sol结构体里有sol.problem字段,0代表求解成功,非零对应各类异常。建议加一段:if sol.problem ~ 0 warning(求解失败: %s, yalmiperror(sol.problem)); else disp(求解成功); end第二是检查对偶变量经济含义。比如功率平衡约束的对偶乘子就应该等于该时段的边际电价。如果对偶值出现明显异常,比如电价在白天光伏大发时段反而暴涨,说明模型的约束逻辑有问题,优先去查功率平衡约束和购售电方向约束。第三是画曲线图。把分时电价、用户负荷、储能SOC、与配网交换功率放在同一张图里,检查时序是否合理:电价低谷段负荷上升、储能充电;电价高峰段负荷回落、储能放电。我用这个办法抓到过好几次符号写反的bug。5. 仿真算例与结果分析5.1 算例场景与参数设置参考算例设计如下:一个典型园区微网,含光伏100kW、储能200kWh/100kW、固定负荷和弹性负荷各一块,以24小时为调度周期,时间间隔1小时。配网购电采用分时电价,峰谷价差明显:高峰时段10点到14点电价0.95元/kWh,平段0.6元/kWh,低谷时段23点到次日7点0.35元/kWh。用户侧参数设置:(\alpha0.12),(\beta0.0004),负荷下限取该时段基础负荷的60%,上限取150%。这样用户的响应范围足够,能明显看到价格对用电的引导效果。合作与非合作的区分,主要通过上层目标函数是否包含用户效用来实现。这类算例不需要追求大而全,重点是能说明博弈机制:价格指挥用户,用户反过来影响成本和收益,最终结果和单层优化有显著差异。5.2 非合作与合作均衡对比以典型参数迭代求解后,结果呈现以下规律:非合作模式下,运营商会把电价定得偏高,倒逼用户削减负荷,进而降低购电成本和系统峰值压力。用户侧收益受损,运营商收益有所改善,但整体社会福利不是最大的。原因在于双方都在追求个体最优,电价中隐含着盈利加成,用户用电量被压到接近下限,效用损失明显。合作模式下,上层目标改为联盟总收益最大化,电价曲线整体更平滑,高峰电价降低,低谷电价微涨,削峰填谷的效果依然存在,但用户因电价下降而增加用电量,用户总效用上升。联盟总收益比非合作高,增量部分再按Shapley值在运营商和用户之间分配。这就是合作型博弈的核心价值:帕累托改进让双方都愿意留在联盟中。实际项目中,如果用户侧是电动汽车聚合商或者工业产线,价格弹性参数差异很大,结果会有区别,但上述机制定性不变。这也提示我们:做仿真时不必纠结于一个具体数字,关键是验证合作机制带来的收益改善方向和幅度。5.3 参数灵敏度:价格弹性对策略的影响我建议做一档参数灵敏度分析,专门改变用户效用函数的(\beta)值,观察均衡结果如何变化。(\beta)大时,边际效用下降快,用户对价格非常敏感,电价小幅上调就会显著抑制用电。这时运营商的定价策略必须收敛一些,不能太激进,否则负荷跌得太多,运营商的售电收入反而下降。(\beta)小时,用户价格弹性低,电价上调对负荷影响不大,运营商拥有更强的市场力,非合作模式下可以把电价定得更高,合作机制带来的改进也更明显。这个分析的意义在于提醒:项目方案不应该是固定一组参数跑出一个结果就完事,而是要通过灵敏度分析展示模型在不同市场环境下的适应能力。写论文也好,做工程方案也好,这部分说服力很强。6. Cplex求解报错与工程化避坑速查表6.1 常见报错与解决方案我把这个项目里碰到的Cplex和Yalmip相关报错整理成一张速查表,基本覆盖了微网博弈模型调试中的高频问题。报错现象可能原因处理建议Model is infeasible约束之间存在矛盾,常见是功率平衡约束与购售电上下限冲突先注释掉部分约束做隔离测试,找到冲突约束Out of memory或model too large使用Cplex Community版,规模超1000变量/约束缩减调度时段(24→12)或升级商业版Numerical difficulties大M取值过大、变量量纲差异大缩小M,检查电量单位统一为kWh或MWSolver not foundYalmip检测不到Cplex运行yalmsetup确认路径,检查Cplex版本与Matlab兼容性状态Infeasible or unbounded变量未设置上下界导致目标无界为所有决策变量显式补充上下界约束求解时间过长MIP整数变量过多,或大M过大设置cplex.mip.timelimit,尝试收紧M取值,减少对称约束一定要在项目初期就把检查清单跑一遍,不然进入模型细节调试时,常常分不清是业务约束的问题还是Cplex配置的问题。6.2 关于Matlab与Cplex版本兼容的一个忠告这个项目里我遇到过一个特别典型的问题:Matlab是R2023b,Cplex是12.10版本编译的,yalmsetup能识别到Cplex,但一调用就报“undefined function”错误。这种问题大多数情况下是Cplex的mex文件没有正确匹配Matlab版本,而不是授权问题。解决办法是到IBM官网下载对应Matlab版本的Cplex版本,并确认cplex目录结构正确。一个有效的验证方法是直接在Matlab里运行cplex Cplex(test);如果没有报错,说明接口正常,后续问题多半在模型本身。另外一个经验是:Matlab的savepath有时候会因为权限问题没有把Cplex路径写进启动配置,导致每次重启Matlab都要重新addpath。建议在startup.m里加上Cplex的路径设置,省去反复手动配置的麻烦。6.3 编程习惯层面的避坑建议代码量上来后,调试效率取决于工程习惯。我建议把模型拆成函数模块:主脚本负责数据加载和结果处理,模型搭建函数负责生成变量和约束,求解函数负责调动Cplex,结果分析函数负责画图与指标计算。这样改一处逻辑不会牵一发而动全身。另一个建议是中间结果随时保存。用save保存工作区变量,尤其是求解成本较高的MIP模型,避免每次改后处理代码都要重新跑一遍求解器。时长30分钟的MIP模型,如果每次调图都要重新求解,效率极低。加上求完立即把结果数值抽出来存成.mat,后续分析和论文画图非常方便。写在最后的几点体会算这个项目的时候,有一段时间我被Cplex的integer infeasible问题卡了很久,后来发现居然是一个很蠢的原因:储能SOC的初值写错了。这里也提醒所有做微网优化的朋友,凡是涉及SOC递推的模型,初值设置至关重要,一个单位不一致就可能导致全部约束冲突。从技术框架上讲,MatlabYalmipCplex这套组合,做微电网运行策略、电力市场博弈、虚拟电厂调度这类问题,依然是非常可靠的选择。Cplex的MIP求解能力和Yalmip的建模灵活性,搭配起来可以应对多数中规模双层优化问题。如果你后续想把模型扩展到多微网协同、包含更多随机因素,可以进一步引入分布式求解框架或者鲁棒优化技巧,博弈模型本身仍然是上层框架的最好底座之一。最后分享一个个人习惯:项目初期我会故意把模型复杂度控制在一个手算能验证的小规模上,比如2个时段、1个用户、不接储能。在这个级别把博弈机制和收益分配算清楚,证明逻辑没问题,再逐步扩展规模。这样做看似绕路,实际是排查模型逻辑错误最快的方式。很多时候算法调不动不是Cplex不行,而是模型本身就存在问题,小规模手算能让问题更早暴露。如果你正在做类似项目,不妨也试试这个思路。
返回列表