點(diǎn)邊際電價(jià)(LMP)怎么算?YALMIP+CPLEX安全約束經(jīng)濟(jì)調(diào)度實(shí)戰(zhàn)解析)
簡(jiǎn)介電力市場(chǎng)節(jié)點(diǎn)邊際電價(jià)出清優(yōu)化方案圍繞史新紅《機(jī)組運(yùn)行約束對(duì)機(jī)組節(jié)點(diǎn)邊際電價(jià)的影響分析》進(jìn)行復(fù)現(xiàn)以單時(shí)段出清模型為核心在忽略爬坡約束的前提下完整考慮機(jī)組運(yùn)行約束適合電力市場(chǎng)、電力經(jīng)濟(jì)相關(guān)專(zhuān)業(yè)學(xué)生及研究者用于學(xué)習(xí)節(jié)點(diǎn)邊際電價(jià)LMP與系統(tǒng)邊際電價(jià)的形成機(jī)理。采用KKT條件將對(duì)偶問(wèn)題轉(zhuǎn)化為矩陣形式求解拉格朗日乘子影子價(jià)格程序結(jié)構(gòu)清晰、注釋完整便于對(duì)照?qǐng)?bào)告理解影子價(jià)格在出清優(yōu)化中的經(jīng)濟(jì)含義。壓縮包共5個(gè)文件包含3個(gè)Matlab程序m、1篇參考文獻(xiàn)caj和1份完整報(bào)告doc總大小僅383KB輕量易下載。目前已有4668人學(xué)習(xí)資源內(nèi)附出清過(guò)程詳細(xì)報(bào)告并針對(duì)運(yùn)行問(wèn)題提供答疑支持可幫助讀者快速理解邊際電價(jià)出清的規(guī)范做法并復(fù)現(xiàn)算例。1. 打開(kāi)這個(gè)zip之前先弄懂節(jié)點(diǎn)邊際電價(jià)為什么是一堆影子價(jià)格我做電力市場(chǎng)出清仿真這幾年最常被問(wèn)的一句話是節(jié)點(diǎn)邊際電價(jià)LMP到底是怎么算出來(lái)的很多人第一反應(yīng)是“用報(bào)價(jià)加權(quán)平均”或者“按負(fù)荷比例分?jǐn)偝杀尽边@兩個(gè)直覺(jué)在單節(jié)點(diǎn)系統(tǒng)里能湊合一旦把電網(wǎng)拓?fù)浜途€路阻塞放進(jìn)來(lái)誤差能到幾十美元。真實(shí)情況是LMP不是市場(chǎng)規(guī)則里拍腦袋定的而是安全約束經(jīng)濟(jì)調(diào)度SCED這個(gè)線性規(guī)劃問(wèn)題里功率平衡約束和線路阻塞約束的拉格朗日乘子組合出來(lái)的結(jié)果。換句話說(shuō)價(jià)格不是算出來(lái)的是從優(yōu)化問(wèn)題的對(duì)偶問(wèn)題里“問(wèn)”出來(lái)的。這個(gè)名為“基于yalmipcplex的電力市場(chǎng)-節(jié)點(diǎn)邊際電價(jià)出清優(yōu)化”的zip本質(zhì)上是把這條鏈路完整打通用YALMIP在MATLAB里把出清模型寫(xiě)成約束和目標(biāo)交給CPLEX求解再?gòu)那蠼饨Y(jié)果里抽出每個(gè)節(jié)點(diǎn)的邊際電價(jià)。它適合三類(lèi)人正在做電力市場(chǎng)仿真的研究生、售電或發(fā)電側(cè)做策略的算法工程師、想從通用優(yōu)化轉(zhuǎn)行電力調(diào)度的開(kāi)發(fā)者。讀完你不僅能跑通一個(gè)三節(jié)點(diǎn)系統(tǒng)的出清還能自己拆LMP、判斷結(jié)果對(duì)不對(duì)、避開(kāi)一堆讓人撓頭的坑。2. SCED與LMP直流潮流下的安全約束經(jīng)濟(jì)調(diào)度怎么定價(jià)2.1 沒(méi)有線路阻塞時(shí)電網(wǎng)其實(shí)是一個(gè)“大池子”先看最簡(jiǎn)單的情況假設(shè)整個(gè)電網(wǎng)是一個(gè)點(diǎn)所有發(fā)電機(jī)和負(fù)荷接在同一個(gè)母線上不考慮線路容量。那么出清問(wèn)題就是在滿足總負(fù)荷的前提下讓發(fā)電總成本最小。這是一個(gè)再簡(jiǎn)單不過(guò)的線性規(guī)劃目標(biāo)是最小化所有機(jī)組的發(fā)電成本之和約束只有一個(gè)——總出力等于總負(fù)荷。這個(gè)問(wèn)題的對(duì)偶乘子拉格朗日乘子就是統(tǒng)一出清價(jià)所有節(jié)點(diǎn)完全一樣。為什么因?yàn)樵谶@個(gè)假設(shè)下不管電從哪個(gè)機(jī)組來(lái)、送到哪個(gè)節(jié)點(diǎn)去成本只跟機(jī)組自身的報(bào)價(jià)有關(guān)跟“位置”無(wú)關(guān)。這就是電力市場(chǎng)里常說(shuō)的“全網(wǎng)一口價(jià)”。但現(xiàn)實(shí)電網(wǎng)不是這樣。輸電線路有容量上限電能必須遵循基爾霍夫定律流動(dòng)。于是同樣1MW負(fù)荷加在送端節(jié)點(diǎn)和加在受端節(jié)點(diǎn)引起的發(fā)電成本增量完全不同。這個(gè)“不同”就是節(jié)點(diǎn)邊際電價(jià)存在的原因。我一般會(huì)給新人打一個(gè)比方LMP是什么是“在這個(gè)節(jié)點(diǎn)多接1MW負(fù)荷整個(gè)系統(tǒng)最優(yōu)發(fā)電成本會(huì)增加多少錢(qián)”。這個(gè)增量包含了機(jī)組邊際報(bào)價(jià)也包含了線路阻塞帶來(lái)的機(jī)會(huì)成本。2.2 線路越過(guò)容量?jī)r(jià)格就開(kāi)始“撕裂”用一個(gè)最小例子說(shuō)明。兩個(gè)節(jié)點(diǎn)一條線路連著。送端節(jié)點(diǎn)1有一臺(tái)便宜機(jī)組報(bào)價(jià)10美元/MWh受端節(jié)點(diǎn)2有一臺(tái)貴機(jī)組報(bào)價(jià)20美元/MWh負(fù)荷全在節(jié)點(diǎn)2。線路容量很大時(shí)便宜機(jī)組直接送電全網(wǎng)價(jià)格10美元?,F(xiàn)在把線路容量調(diào)小比如只能送60MW而負(fù)荷是100MW。便宜機(jī)組最多往節(jié)點(diǎn)2送60MW剩下的40MW必須讓節(jié)點(diǎn)2的貴機(jī)組發(fā)。這時(shí)候全網(wǎng)不再是統(tǒng)一價(jià)。節(jié)點(diǎn)1的LMP是10美元——因?yàn)樵诠?jié)點(diǎn)1多1MW負(fù)荷本地便宜機(jī)組直接多發(fā)1MW就行。節(jié)點(diǎn)2的LMP變成20美元——因?yàn)樵诠?jié)點(diǎn)2多1MW負(fù)荷線路已經(jīng)滿了只能讓貴機(jī)組加出力。兩個(gè)節(jié)點(diǎn)的價(jià)差正好等于阻塞線路的“稀缺租金”。這個(gè)租金不是任何人主觀定的是線路潮流約束的對(duì)偶乘子。安全約束經(jīng)濟(jì)調(diào)度SCED的核心就是把這些約束全部放進(jìn)優(yōu)化問(wèn)題里讓價(jià)格自己“長(zhǎng)出來(lái)”。2.3 為什么偏偏是YALMIP CPLEX理論上你自己用MATLAB寫(xiě)一個(gè)單純形法或者調(diào)linprog也能解這個(gè)LP。但出清模型有個(gè)特殊要求你得知道每個(gè)約束對(duì)應(yīng)的影子價(jià)格而且要把影子價(jià)格準(zhǔn)確地映射到“功率平衡乘子”“線路阻塞乘子”這些業(yè)務(wù)概念上。自己寫(xiě)求解器變量和約束多了以后對(duì)偶信息的跟蹤極其容易出錯(cuò)。YALMIP的價(jià)值在于建模層和求解層分離。你只需要聲明變量是sdpvar然后像寫(xiě)數(shù)學(xué)公式一樣寫(xiě)約束YALMIP負(fù)責(zé)把模型轉(zhuǎn)換成標(biāo)準(zhǔn)LP/QP形式傳給底層求解器。CPLEX則在求解層提供了成熟的單純形和對(duì)偶單純形算法數(shù)值穩(wěn)定大規(guī)模稀疏問(wèn)題也能扛。更關(guān)鍵的是YALMIP的dual函數(shù)能直接取回約束對(duì)應(yīng)的對(duì)偶乘子這比從CPLEX原生接口里翻對(duì)偶解要友好得多。我見(jiàn)過(guò)不少直接從CPLEX Java/C接口取乘子的工程代碼里全是矩陣索引和符號(hào)轉(zhuǎn)換維護(hù)成本極高。另外YALMIP的好處是求解器可替換。同一個(gè)人樣模型把sdpsettings里的solver改成其他商業(yè)求解器或開(kāi)源求解器也能跑只是性能和對(duì)偶信息獲取的方便程度不同。我一般在教學(xué)和驗(yàn)證階段固定用CPLEX因?yàn)樗腖P對(duì)偶解默認(rèn)返回完整且預(yù)求解不會(huì)輕易“吃掉”你關(guān)注的約束乘子。3. YALMIP寫(xiě)三節(jié)點(diǎn)出清建模、求解和第一個(gè)LMP3.1 直流潮流的近似邏輯與適用邊界市場(chǎng)出清仿真里最常用的潮流模型是直流潮流DCOPF不是交流潮流。交流潮流要同時(shí)算有功、無(wú)功、電壓幅值和相角問(wèn)題是非凸的求解慢、可能不收斂而且LMP的定義在交流模型下要復(fù)雜得多——無(wú)功價(jià)格、電壓約束的影子價(jià)格都會(huì)摻進(jìn)來(lái)。直流潮流做的事情很粗暴忽略無(wú)功、忽略網(wǎng)損、假設(shè)電壓幅值都是1只保留有功和相角的關(guān)系。這個(gè)關(guān)系寫(xiě)出來(lái)很簡(jiǎn)單線路有功潮流P_ij約等于兩端相角差除以電抗也就是P_ij(θ_i-θ_j)/x_ij。x是線路電抗單位用標(biāo)幺值。這個(gè)線性關(guān)系讓整個(gè)出清問(wèn)題變成一個(gè)純線性規(guī)劃凸、可收斂、對(duì)偶乘子有清晰的價(jià)格含義。代價(jià)是精度——直流潮流不適用于電壓?jiǎn)栴}、無(wú)功優(yōu)化場(chǎng)景但在節(jié)點(diǎn)邊際電價(jià)仿真、市場(chǎng)力分析、阻塞管理這些場(chǎng)景里它是絕對(duì)的主流選擇。你去看各地的現(xiàn)貨市場(chǎng)出清系統(tǒng)核心引擎基本都是某種形式的DCOPF或加入了網(wǎng)損近似的擴(kuò)展版。需要注意一個(gè)邊界x_ij不能為0。電抗為零意味線路導(dǎo)納無(wú)窮大B矩陣奇異潮流方程無(wú)解。我見(jiàn)過(guò)有人在測(cè)試數(shù)據(jù)里為了省事把所有線路電抗寫(xiě)成0結(jié)果YALMIP一跑就報(bào)“NaN”或者不可行最后查了半天發(fā)現(xiàn)是電抗單位寫(xiě)錯(cuò)了。3.2 三節(jié)點(diǎn)系統(tǒng)的參數(shù)與完整求解代碼為了把原理落到代碼上我構(gòu)造一個(gè)最簡(jiǎn)單但能體現(xiàn)阻塞定價(jià)的三節(jié)點(diǎn)鏈?zhǔn)较到y(tǒng)。節(jié)點(diǎn)1是送端節(jié)點(diǎn)2是中轉(zhuǎn)節(jié)點(diǎn)3是負(fù)荷中心。節(jié)點(diǎn)1有一臺(tái)便宜機(jī)組節(jié)點(diǎn)2有一臺(tái)貴機(jī)組負(fù)荷100MW全部在節(jié)點(diǎn)3。線路1-2容量設(shè)為60MW線路2-3容量設(shè)為150MW。這樣一定會(huì)出現(xiàn)阻塞——便宜機(jī)組的電最多送60MW到節(jié)點(diǎn)2節(jié)點(diǎn)3的缺口只能讓節(jié)點(diǎn)2的貴機(jī)組頂上。系統(tǒng)參數(shù)如下對(duì)象參數(shù)數(shù)值線路1-2電抗(p.u.) / 容量(MW)0.1 / 60線路2-3電抗(p.u.) / 容量(MW)0.1 / 150機(jī)組G1所在節(jié)點(diǎn) / 報(bào)價(jià)($/MWh) / 出力上下限(MW)1 / 10 / 0~100機(jī)組G2所在節(jié)點(diǎn) / 報(bào)價(jià)($/MWh) / 出力上下限(MW)2 / 20 / 0~100負(fù)荷D3所在節(jié)點(diǎn) / 大小(MW)3 / 100下面是完整的YALMIP CPLEX求解代碼。這段代碼我建議你原樣跑通一次再逐步改參數(shù)觀察價(jià)格變化。%% 三節(jié)點(diǎn)直流潮流出清YALMIP CPLEX % 節(jié)點(diǎn)1送端2中轉(zhuǎn)3受端(負(fù)荷) % 線路L12連接1-2L23連接2-3 clear; clc; %% 系統(tǒng)數(shù)據(jù) mpc.nb 3; % 節(jié)點(diǎn)數(shù) mpc.nl 2; % 線路數(shù) % 線路: [起點(diǎn), 終點(diǎn), 電抗(p.u.), 容量(MW)] mpc.line [1 2 0.1 60; 2 3 0.1 150]; % 機(jī)組: [節(jié)點(diǎn), 報(bào)價(jià)($/MWh), 出力下限(MW), 出力上限(MW)] mpc.gen [1 10 0 100; 2 20 0 100]; mpc.load [0 0 100]; % 節(jié)點(diǎn)3負(fù)荷100MW %% 構(gòu)建直流潮流B矩陣和線路-節(jié)點(diǎn)關(guān)聯(lián)矩陣Bf B zeros(mpc.nb, mpc.nb); for k 1:mpc.nl f mpc.line(k,1); t mpc.line(k,2); x mpc.line(k,3); B(f,f) B(f,f) 1/x; B(f,t) B(f,t) - 1/x; B(t,f) B(t,f) - 1/x; B(t,t) B(t,t) 1/x; end Bf zeros(mpc.nl, mpc.nb); for k 1:mpc.nl f mpc.line(k,1); t mpc.line(k,2); x mpc.line(k,3); Bf(k,f) 1/x; Bf(k,t) -1/x; end ref 3; % 參考節(jié)點(diǎn)選3相角置0 %% 定義優(yōu)化變量 P sdpvar(2, 1); % 兩臺(tái)機(jī)組出力 theta sdpvar(3, 1); % 節(jié)點(diǎn)相角 %% 約束 cons_plim (mpc.gen(:,3) P mpc.gen(:,4)); % 機(jī)組出力上下限 cons_ref (theta(ref) 0); % 參考節(jié)點(diǎn)相角為0 F Bf * theta; % 線路有功潮流表達(dá)式 cons_fline (F mpc.line(:,4)); % 線路潮流上限 cons_fdown (-mpc.line(:,4) F); % 線路潮流下限 cons_balance (sum(P) sum(mpc.load)); % 功率平衡 % 合并所有約束傳給求解器 all_cons [cons_plim, cons_ref, cons_fline, cons_fdown, cons_balance]; %% 目標(biāo)函數(shù)與求解 obj mpc.gen(:,2) * P; % 總發(fā)電成本線性成本 options sdpsettings(solver, cplex, verbose, 1); sol optimize(all_cons, obj, options); %% 讀取結(jié)果 P_opt value(P); F_opt value(F); theta_opt value(theta); fprintf(G1出力: %.2f MW, G2出力: %.2f MW\n, P_opt(1), P_opt(2)); fprintf(線路L12潮流: %.2f MW, 線路L23潮流: %.2f MW\n, F_opt(1), F_opt(2)); fprintf(總發(fā)電成本: %.2f 美元\n, value(obj));邏輯上說(shuō)得很直白先構(gòu)建B矩陣和Bf矩陣B矩陣用來(lái)算節(jié)點(diǎn)相角和功率注入的關(guān)系Bf矩陣用來(lái)從相角直接得到每條線路的潮流。然后聲明兩臺(tái)機(jī)組的出力P和三個(gè)節(jié)點(diǎn)的相角theta為優(yōu)化變量。約束分四組機(jī)組出力上下限、參考節(jié)點(diǎn)相角、線路潮流上下限、功率平衡。目標(biāo)函數(shù)是線性成本之和。參數(shù)說(shuō)明要強(qiáng)調(diào)幾個(gè)地方。第一參考節(jié)點(diǎn)必須固定否則所有相角同時(shí)加一個(gè)常數(shù)潮流不變但矩陣求解不唯一YALMIP不會(huì)報(bào)錯(cuò)但結(jié)果看著像隨機(jī)數(shù)。第二F Bf * theta不是約束是表達(dá)式它把相角和潮流聯(lián)系起來(lái)后續(xù)的線路容量約束都作用在這個(gè)表達(dá)式的值上。第三sdpsettings里solver指定用cplexverbose1讓求解器打印迭代日志如果CPLEX沒(méi)有正確安裝或授權(quán)YALMIP會(huì)報(bào)錯(cuò)這時(shí)可以把solver改成其他支持的求解器先驗(yàn)證模型邏輯。跑完這段代碼你會(huì)得到G1出力60MW、G2出力40MW、總成本1400美元。這個(gè)結(jié)果本身就是阻塞定價(jià)的起點(diǎn)——便宜機(jī)組只發(fā)到線路容量允許的上限剩下的全靠貴機(jī)組。3.3 第一次看結(jié)果哪些約束在“卡脖子”求解完成后不要只看出力數(shù)字要看哪條約束是積極約束active constraint也就是dual值不等于0的約束。積極約束就是“卡脖子”的位置線路L12的潮流上限約束和功率平衡約束都會(huì)有非零對(duì)偶乘子。機(jī)組G1的出力上限60MW不會(huì)觸發(fā)它的上限是100MW觸發(fā)的是線路容量60MW。我習(xí)慣把結(jié)果分成兩種場(chǎng)景做對(duì)比。場(chǎng)景A線路L12容量60MW價(jià)格分層場(chǎng)景B把線路L12容量改成150MW也就是不阻塞。兩張場(chǎng)景的LMP對(duì)比如下節(jié)點(diǎn)場(chǎng)景AL12容量60MW場(chǎng)景BL12容量150MW節(jié)點(diǎn)110 美元/MWh10 美元/MWh節(jié)點(diǎn)220 美元/MWh10 美元/MWh節(jié)點(diǎn)320 美元/MWh10 美元/MWh機(jī)組出力G160, G240G1100, G20場(chǎng)景B里全網(wǎng)一口價(jià)10美元跟2.1節(jié)的理論預(yù)測(cè)完全一致。場(chǎng)景A里節(jié)點(diǎn)1和節(jié)點(diǎn)2/3差了10美元差的這10美元就是線路L12阻塞的影子價(jià)格。這個(gè)“一堵就分層”的現(xiàn)象是所有節(jié)點(diǎn)邊際電價(jià)仿真的核心。后面第四章我要講的LMP分解就是把這10美元從數(shù)學(xué)上拆出來(lái)。4. LMP的提取與分解從對(duì)偶乘子到節(jié)點(diǎn)電價(jià)4.1 取對(duì)偶乘子YALMIP的dual()與符號(hào)約定YALMIP里取對(duì)偶乘子非常簡(jiǎn)單直接調(diào)用dual(約束句柄)。但要命的是符號(hào)約定對(duì)于形如“表達(dá)式 0”的約束YALMIP返回的乘子是非負(fù)的對(duì)于等式約束乘子可以是任意實(shí)數(shù)符號(hào)由等式方向決定。我初學(xué)時(shí)在這里栽過(guò)跟頭——把功率平衡約束的dual取出來(lái)直接當(dāng)成LMP結(jié)果算出來(lái)的價(jià)格全反了。標(biāo)準(zhǔn)做法是把功率平衡等式約束寫(xiě)成sum(P) sum(mpc.load)然后dual(cons_balance)就是能量?jī)r(jià)格基礎(chǔ)分量λ。線路潮流約束F Fmax返回的是非負(fù)乘子μ_up-Fmax F返回的也是非負(fù)乘子μ_dn。不需要手動(dòng)取負(fù)號(hào)只需要在匯總公式里按KKT條件的方向組合。4.2 拆LMP能量分量、阻塞分量與參考節(jié)點(diǎn)有了對(duì)偶乘子還需要一個(gè)矩陣節(jié)點(diǎn)轉(zhuǎn)移因子PTDF。PTDF的含義是某個(gè)節(jié)點(diǎn)注入1MW功率參考節(jié)點(diǎn)吸收每條線路上會(huì)增加多少潮流。直流潮流下PTDF矩陣可以由Bf和B矩陣直接算出來(lái)。下面這段代碼接著上一節(jié)的系統(tǒng)數(shù)據(jù)計(jì)算PTDF并把三個(gè)節(jié)點(diǎn)的LMP拆成能量分量和阻塞分量。%% 計(jì)算PTDF矩陣 nonref [1 2]; % 非參考節(jié)點(diǎn)參考節(jié)點(diǎn)3的列保持0 Bred B(nonref, nonref); % 去掉參考節(jié)點(diǎn)行列的B矩陣 PTDF zeros(mpc.nl, mpc.nb); PTDF(:, nonref) Bf(:, nonref) / Bred; % 線路注入靈敏度參考節(jié)點(diǎn)列為0 %% 取對(duì)偶乘子 lambda dual(cons_balance); % 功率平衡乘子能量?jī)r(jià)格基礎(chǔ) mu_up dual(cons_fline); % 線路FFmax的乘子非負(fù) mu_dn dual(cons_fdown); % 線路-FmaxF的乘子非負(fù) %% 組合LMP LMP zeros(mpc.nb, 1); for i 1:mpc.nb LMP(i) lambda - sum((mu_up - mu_dn) .* PTDF(:, i)); end %% 打印結(jié)果 fprintf(能量分量(全網(wǎng)統(tǒng)一): %.2f $/MWh\n, lambda); for i 1:mpc.nb blocking lambda - LMP(i); % 阻塞分量含符號(hào) fprintf(節(jié)點(diǎn)%d LMP%.2f $/MWh, 阻塞分量%.2f $/MWh\n, ... i, LMP(i), blocking); end這里PTDF(:,i)是一個(gè)列向量表示節(jié)點(diǎn)i的注入對(duì)各條線路潮流的靈敏度。用mu_up減去mu_dn再和PTDF逐元素相乘后求和得到該節(jié)點(diǎn)阻塞分量的修正值。公式為什么是“減去”而不是“加上”回到第二章的雙節(jié)點(diǎn)例子送端節(jié)點(diǎn)1的LMP10全網(wǎng)能量分量為20阻塞修正值是-10方向必須能讓送端更便宜、受端更貴。如果你拿到的數(shù)據(jù)算出來(lái)方向相反優(yōu)先檢查PTDF的參考節(jié)點(diǎn)是否選對(duì)了以及線路約束寫(xiě)成“F Fmax”時(shí)YALMIP返回的dual是否真的非負(fù)。在三節(jié)點(diǎn)例子里這個(gè)代碼會(huì)輸出lambda20美元節(jié)點(diǎn)1的LMP10美元阻塞分量-10節(jié)點(diǎn)2和節(jié)點(diǎn)3的LMP20美元阻塞分量0。這跟3.3節(jié)表格完全一致。阻塞分量只作用于阻塞線路的“送端”這是直流潮流的典型特征。注意阻塞盈余的概念也由此而來(lái)節(jié)點(diǎn)3的用戶按20美元買(mǎi)電節(jié)點(diǎn)1的機(jī)組按10美元賣(mài)電中間每度電的10美元差額就是阻塞盈余在真實(shí)市場(chǎng)里會(huì)通過(guò)阻塞費(fèi)用結(jié)算機(jī)制分配。關(guān)于參考節(jié)點(diǎn)再補(bǔ)充一句LMP的數(shù)值總量不依賴(lài)參考節(jié)點(diǎn)的選擇三個(gè)節(jié)點(diǎn)算出來(lái)都一致。但分解出來(lái)的能量分量和阻塞分量會(huì)隨參考節(jié)點(diǎn)變化——參考節(jié)點(diǎn)的阻塞分量恒為0能量分量會(huì)被“吸收”一部分。所以做分解時(shí)不要在報(bào)告里只說(shuō)“能量?jī)r(jià)是多少”一定要注明參考節(jié)點(diǎn)是哪個(gè)。4.3 擾動(dòng)校核用電價(jià)的定義反推你的結(jié)果這是我最推薦的驗(yàn)證習(xí)慣。LMP的嚴(yán)格定義是“某節(jié)點(diǎn)增加單位負(fù)荷引起的最優(yōu)成本增量”。與其信公式不如直接讓計(jì)算機(jī)“擾動(dòng)”一下。做法是把求解過(guò)程封裝成一個(gè)函數(shù)然后對(duì)每個(gè)節(jié)點(diǎn)做一次1MW負(fù)荷擾動(dòng)重新求解比較成本差。function [P, F, obj_val] solve_sced(mpc) % 把第三章的建模和求解包成函數(shù)返回出力、潮流和目標(biāo)值 % mpc結(jié)構(gòu)里有l(wèi)ine/gen/load/nb/nl等字段 % 具體建模代碼同第三章略 end %% 擾動(dòng)校核對(duì)每個(gè)節(jié)點(diǎn)加1MW負(fù)荷求成本增量 c0 0; % 先求基礎(chǔ)場(chǎng)景的總成本 [~, ~, c0] solve_sced(mpc); for i 1:mpc.nb mpc2 mpc; mpc2.load(i) mpc2.load(i) 1; % 只在節(jié)點(diǎn)i加1MW [~, ~, c1] solve_sced(mpc2); fprintf(節(jié)點(diǎn)%d擾動(dòng)法LMP%.2f $/MWh\n, i, c1 - c0); end在三節(jié)點(diǎn)例子里這個(gè)擾動(dòng)校核的結(jié)果會(huì)和4.2節(jié)的LMP完全吻合節(jié)點(diǎn)1加1MW負(fù)荷成本增加10美元節(jié)點(diǎn)2和節(jié)點(diǎn)3加1MW負(fù)荷成本增加20美元。邏輯也很好驗(yàn)證——節(jié)點(diǎn)1的負(fù)荷增加不會(huì)加重線路L12的負(fù)擔(dān)本地負(fù)荷吸收本地出力便宜機(jī)組直接加發(fā)節(jié)點(diǎn)2和節(jié)點(diǎn)3的負(fù)荷增加則必須靠貴機(jī)組。擾動(dòng)法看著笨但它是唯一不考慮對(duì)偶理論也能解釋得通的價(jià)格驗(yàn)證手段。我每次寫(xiě)新模型都會(huì)保留這個(gè)校核腳本作為L(zhǎng)MP結(jié)果的“金標(biāo)準(zhǔn)”。5. 出清仿真的五類(lèi)翻車(chē)現(xiàn)場(chǎng)與排查路徑5.1 INFEASIBLE電抗為零、參考缺失與負(fù)荷不平衡現(xiàn)象optimize返回求解狀態(tài)為不可行或者YALMIP直接報(bào)NaN。原因有三大類(lèi)按我實(shí)際遇到頻次排序第一線路電抗x寫(xiě)成0B矩陣奇異第二參考節(jié)點(diǎn)相角約束沒(méi)有加模型自由度過(guò)大導(dǎo)致數(shù)值病態(tài)第三總發(fā)電出力上限小于總負(fù)荷數(shù)學(xué)上無(wú)解。還有一類(lèi)隱蔽的負(fù)荷數(shù)據(jù)寫(xiě)在某個(gè)節(jié)點(diǎn)但該節(jié)點(diǎn)沒(méi)有發(fā)電機(jī)也沒(méi)有外來(lái)線路形成孤島。解決先查B矩陣的行列式行列式接近0立刻定位電抗異常檢查所有節(jié)點(diǎn)是否至少有發(fā)電機(jī)或線路連通到參考節(jié)點(diǎn)??焖俣ㄎ徊豢尚屑s束的辦法是給功率平衡加一個(gè)人工松弛變量比如把平衡約束改成sum(P)slacksum(load)讓slack無(wú)界求解后看slack落在哪個(gè)節(jié)點(diǎn)就知道哪里功率缺了。5.2 dual()全為零對(duì)偶信息被預(yù)求解消掉了現(xiàn)象模型求解成功出力、潮流都對(duì)但dual(cons_balance)返回0。LMP算出來(lái)全是0怎么看都不對(duì)。原因CPLEX預(yù)求解階段可能判定某條約束冗余并直接刪掉對(duì)偶乘子隨之丟失。尤其當(dāng)功率平衡約束的表達(dá)式寫(xiě)法不夠“標(biāo)準(zhǔn)”時(shí)容易觸發(fā)。另外YALMIP里多個(gè)約束合并成復(fù)合約束后dual返回的向量順序和約束順序如果不匹配也容易讓人誤讀成零。解決把需要取乘子的約束單獨(dú)定義成獨(dú)立的句柄不要和其他約束揉在一起。求解前在sdpsettings里關(guān)閉部分預(yù)求解options.cplex.preprocessing.reduce 0。如果還是取不到用擾動(dòng)法4.3節(jié)交叉驗(yàn)證——不需要信dual也能得到價(jià)格。這是最保險(xiǎn)的兜底手段。5.3 全網(wǎng)一口價(jià)是不是哪里沒(méi)設(shè)容量現(xiàn)象明明加了線路容量約束三節(jié)點(diǎn)系統(tǒng)還是全網(wǎng)統(tǒng)一價(jià)跟第二章“大池子”一樣。原因線路容量設(shè)得太大了。容量上限在200MW線路實(shí)際潮流才100MW約束雖然存在但從未被激活乘子當(dāng)然為0價(jià)格不會(huì)分層。很多人第一次跑通代碼后發(fā)現(xiàn)價(jià)格都一樣以為自己優(yōu)化錯(cuò)了其實(shí)是數(shù)據(jù)沒(méi)卡到阻塞點(diǎn)。解決逐步縮小關(guān)鍵線路容量觀察LMP分叉的臨界點(diǎn)。這個(gè)臨界值其實(shí)有物理含義線路容量緊到一定程度市場(chǎng)上的便宜機(jī)組送不過(guò)去受端價(jià)格開(kāi)始爬升。我在3.3節(jié)里把L12容量從150降到60就是故意制造這個(gè)分叉。調(diào)參時(shí)每次都對(duì)比“潮流值vs容量上限”兩個(gè)數(shù)字相等的那條線就是當(dāng)前最擁堵的線。5.4 LMP是負(fù)的或高于機(jī)組報(bào)價(jià)稀缺定價(jià)不是bug現(xiàn)象某節(jié)點(diǎn)LMP出現(xiàn)負(fù)值或者高于全網(wǎng)最高機(jī)組報(bào)價(jià)20美元達(dá)到35美元。原因這是線性規(guī)劃里約束影子價(jià)格的正常表現(xiàn)不是求解器抽風(fēng)。負(fù)價(jià)格通常出現(xiàn)在機(jī)組有最小技術(shù)出力比如最小出力50MW但負(fù)荷只有30MW或者必須開(kāi)機(jī)維持電壓支撐的場(chǎng)景價(jià)格高于最高報(bào)價(jià)則說(shuō)明某條受約束的線路把稀缺性放大受端愿意付出的邊際代價(jià)遠(yuǎn)超本地最貴機(jī)組的報(bào)價(jià)。解決不要“修”結(jié)果先理解是哪條約束在定價(jià)。把該節(jié)點(diǎn)的擾動(dòng)法LMP手動(dòng)算一遍你會(huì)發(fā)現(xiàn)它和影子價(jià)格完全一致。如果業(yè)務(wù)上不能接受負(fù)價(jià)格那是市場(chǎng)規(guī)則需要加價(jià)格下限不是優(yōu)化模型的問(wèn)題。仿真時(shí)保留這個(gè)現(xiàn)象即可。5.5 多解與退化同一份數(shù)據(jù)不同的價(jià)格現(xiàn)象代碼沒(méi)變、數(shù)據(jù)沒(méi)變不同機(jī)器上跑出來(lái)G1/G2出力的分配有差異甚至LMP在某些節(jié)點(diǎn)上有微小波動(dòng)。原因LP存在多個(gè)最優(yōu)解尤其是機(jī)組報(bào)價(jià)都是線性沒(méi)有二次項(xiàng)時(shí)成本曲線是一條直線多個(gè)出力組合可以達(dá)到相同的總成本。單純形法會(huì)沿著頂點(diǎn)走起點(diǎn)和預(yù)求解差異會(huì)讓它落在不同的最優(yōu)頂點(diǎn)上。價(jià)格本身不一定變但個(gè)別節(jié)點(diǎn)的阻塞分量可能因?yàn)閰⒖技s束的取舍而不同。解決給目標(biāo)函數(shù)加一個(gè)極小的二次項(xiàng)比如0.0001×P^2讓問(wèn)題變成凸二次規(guī)劃最優(yōu)解唯一。這在實(shí)際現(xiàn)貨市場(chǎng)出清里也是常用手段——報(bào)價(jià)段內(nèi)部按線性處理但出清程序里會(huì)加微小的平滑項(xiàng)避免解漂移。代價(jià)是價(jià)格含義從純線性變成帶微弱二次修正但量級(jí)完全可以忽略。6. 從單時(shí)段到多時(shí)段SCED擴(kuò)展成時(shí)序價(jià)格的進(jìn)階技巧6.1 給模型加時(shí)間軸爬坡約束與24小時(shí)價(jià)格單時(shí)段模型解決好“某一時(shí)刻的電價(jià)”但現(xiàn)貨市場(chǎng)價(jià)格是時(shí)序的調(diào)度員關(guān)心的是機(jī)組能不能在15分鐘或1小時(shí)內(nèi)從50MW爬升到80MW。給模型加時(shí)間軸的套路是固定的所有變量加一個(gè)時(shí)間維度P變成2×T的矩陣theta變成3×T的矩陣功率平衡、線路容量約束對(duì)每個(gè)時(shí)段單獨(dú)寫(xiě)目標(biāo)函數(shù)變成所有時(shí)段的成本之和。額外要加的約束是爬坡約束T 24; % 24個(gè)時(shí)段 P sdpvar(2, T); % 每臺(tái)機(jī)組每個(gè)時(shí)段的出力 R_up 30; % 每時(shí)段最大爬坡上限MW R_dn 30; % 每時(shí)段最大爬坡下限MW cons_ramp []; for t 2:T cons_ramp [cons_ramp, P(:,t) - P(:,t-1) R_up]; cons_ramp [cons_ramp, P(:,t-1) - P(:,t) R_dn]; end這里P(:,t)-P(:,t-1)用矩陣形式一次性約束兩臺(tái)機(jī)組比寫(xiě)兩個(gè)標(biāo)量約束干凈。爬坡約束會(huì)對(duì)價(jià)格產(chǎn)生實(shí)質(zhì)影響低谷時(shí)段便宜機(jī)組被強(qiáng)制壓低出力高峰時(shí)段又爬不上去受端節(jié)點(diǎn)在爬坡受限的時(shí)段會(huì)看到價(jià)格尖峰。每個(gè)時(shí)段的功率平衡約束dual取出來(lái)就是該時(shí)段的能量?jī)r(jià)格序列把它們連成曲線就是典型的24小時(shí)出清價(jià)。注意多時(shí)段模型里L(fēng)MP的取值要區(qū)分“該時(shí)段的lambda”和“跨時(shí)段爬坡約束的影子價(jià)格”后者會(huì)影響多個(gè)時(shí)段的價(jià)格形成分析時(shí)不要混在一起。6.2 MIP與LP的兩階段出清機(jī)組啟停后怎么取LMP這是最容易被忽視的進(jìn)階問(wèn)題。一旦引入機(jī)組啟停變量變成0/1整數(shù)模型從LP變成MIP。從數(shù)學(xué)上嚴(yán)格說(shuō)MIP的對(duì)偶乘子不再有經(jīng)典LP影子價(jià)格的解釋直接從混合整數(shù)解里取dual得到的“價(jià)格”是失真且沒(méi)有經(jīng)濟(jì)含義的。行業(yè)里標(biāo)準(zhǔn)的做法是兩階段出清第一階段用MIP求解機(jī)組啟停和出力計(jì)劃目標(biāo)函數(shù)包含啟停成本第二階段把第一步解出來(lái)的0/1狀態(tài)變量固定成常數(shù)重新求解一次純LP從第二次LP里取對(duì)偶乘子作為L(zhǎng)MP。YALMIP里做這個(gè)操作也很方便——binvar聲明啟停變量第一階段optimize之后把啟停變量的值用value提取出來(lái)替換成約束值再二次optimize。第二階段模型不包含整數(shù)變量CPLEX自動(dòng)走LP路徑dual()就能正常取回乘子。我去年在某模擬項(xiàng)目X里第一次做帶啟停的出清時(shí)直接對(duì)MIP結(jié)果取dual算出來(lái)的價(jià)格低得離譜后來(lái)查文獻(xiàn)才發(fā)現(xiàn)這個(gè)坑。從此固定了“先MIP定狀態(tài)、再LP定價(jià)”的習(xí)慣。6.3 校驗(yàn)?zāi)_本與工程習(xí)慣最后說(shuō)一個(gè)長(zhǎng)期受益的習(xí)慣每次建新模型第一件事不是跑結(jié)果而是寫(xiě)一個(gè)自動(dòng)校核腳本包含三類(lèi)檢查。一是潮流檢查把解出來(lái)的P和theta代回Bf*theta確認(rèn)潮流方程成立。二是平衡檢查每時(shí)段的發(fā)電機(jī)總出力減去負(fù)荷誤差不超過(guò)1e-6。三是價(jià)格檢查用4.3節(jié)的擾動(dòng)法隨機(jī)抽三個(gè)節(jié)點(diǎn)驗(yàn)證LMP。這三關(guān)過(guò)了再談報(bào)告和曲線。這套習(xí)慣幫我擋掉了無(wú)數(shù)個(gè)“看起來(lái)很美但實(shí)際算錯(cuò)”的版本。說(shuō)到底出清優(yōu)化最玄學(xué)的地方不在YALMIP語(yǔ)法也不在CPLEX配置而在“你有沒(méi)有真正理解什么是影子價(jià)格”。我踩過(guò)的坑從符號(hào)搞反到預(yù)求解吞乘子沒(méi)有一個(gè)能靠調(diào)參解決全是回到定義本身才找到答案。希望這篇筆記能幫你少走這些彎路把時(shí)間花在分析和業(yè)務(wù)上。本文還有配套的精品資源點(diǎn)擊獲取