濟(jì)性的儲(chǔ)能運(yùn)行優(yōu)化:MATLAB線性規(guī)劃建模與求解)
簡介這是一份面向電力系統(tǒng)與儲(chǔ)能領(lǐng)域研究者的 MATLAB 開源代碼聚焦電價(jià)套利背景下儲(chǔ)能系統(tǒng)的最優(yōu)運(yùn)行優(yōu)化問題。通過建立以經(jīng)濟(jì)效益最大化為目標(biāo)函數(shù)的優(yōu)化框架并考慮充放電約束、電價(jià)波動(dòng)等關(guān)鍵條件幫助用戶在分時(shí)電價(jià)機(jī)制下制定合理的儲(chǔ)能調(diào)度策略。代碼基于兩篇國外相關(guān)文獻(xiàn)的方法提供了三種獨(dú)立可運(yùn)行的求解路線簡單直接的運(yùn)行策略搜索、能夠處理隨機(jī)性的蒙特卡洛模擬法以及基于 fmincon 函數(shù)的數(shù)學(xué)規(guī)劃優(yōu)化方法。三種方法相互對照便于理解不同思路在收斂性、求解速度與結(jié)果精度上的差異也方便使用者按需替換或擴(kuò)展。壓縮包僅約114KB共10個(gè)文件以 MATLAB 的 .m 腳本為主5個(gè)同時(shí)包含電價(jià)時(shí)間序列文本、spot_price_2013.mat 數(shù)據(jù)、README 說明文檔、許可證等目錄精簡、結(jié)構(gòu)清晰下載后即可按腳本逐步運(yùn)行。目前已有973人學(xué)習(xí)下載適合具有一定 MATLAB 基礎(chǔ)、關(guān)注儲(chǔ)能經(jīng)濟(jì)調(diào)度或電力市場套利的入門與進(jìn)階學(xué)習(xí)者用于算法復(fù)現(xiàn)、對比實(shí)驗(yàn)或課題參考。1. 考慮經(jīng)濟(jì)性的儲(chǔ)能運(yùn)行優(yōu)化這套開源 MATLAB 代碼解決什么問題把「考慮經(jīng)濟(jì)性的儲(chǔ)能運(yùn)行優(yōu)化」這套開源 MATLAB 代碼跑通你會(huì)得到一個(gè)可以直接復(fù)用的調(diào)度決策模板。它的典型場景是某園區(qū)裝了 200 kWh 儲(chǔ)能柜分時(shí)電價(jià)峰谷價(jià)差 0.9 元/kWh看著每天倒騰一次就能賺一百多但真跑起來就發(fā)現(xiàn)沒那么簡單——什么時(shí)候充、什么時(shí)候放、充放多快、要不要留容量給下一個(gè)峰段每個(gè)決定都直接影響最終收益而充放次數(shù)多了還會(huì)加速電池老化。這套代碼做的事就是把上述決策寫成一個(gè)線性規(guī)劃問題用 MATLAB 內(nèi)置的 linprog 求解。輸入只要三樣24 小時(shí)分時(shí)電價(jià)、儲(chǔ)能電氣參數(shù)容量、功率、效率、SOC 上下限輸出是一天逐小時(shí)的充放電功率和 SOC 曲線目標(biāo)是在全部運(yùn)行約束下讓凈收益最大。它不需要額外安裝求解器有 MATLAB 基礎(chǔ)就能改能跑。適合三類人做儲(chǔ)能調(diào)度研究的學(xué)生拿它當(dāng)基準(zhǔn)結(jié)果做對比評(píng)估儲(chǔ)能項(xiàng)目收益的工程師用它算不同價(jià)差下的理論收益上限以及想學(xué)優(yōu)化建模、需要一份干凈模板的開發(fā)者。下面從建模開始一步步把來龍去脈講清楚。2. 儲(chǔ)能運(yùn)行優(yōu)化建模目標(biāo)函數(shù)、約束條件與求解器選型先講透優(yōu)化模型動(dòng)手寫代碼之前先花十分鐘把數(shù)學(xué)形式寫清楚這比調(diào)試省時(shí)間得多。儲(chǔ)能運(yùn)行優(yōu)化的標(biāo)準(zhǔn)形式是給定一個(gè)調(diào)度周期通常 24 小時(shí)、步長 1 小時(shí)在滿足電池自身運(yùn)行約束的前提下最大化周期內(nèi)的凈收益。核心就三件事目標(biāo)函數(shù)里放什么、約束條件有哪些、用哪類求解器。2.1 目標(biāo)函數(shù)怎么定峰谷套利、老化成本與需量電費(fèi)的取舍最基礎(chǔ)的目標(biāo)函數(shù)是峰谷套利。每個(gè)時(shí)段的收益等于放電收入減去充電成本寫成max Σ ( p_t * q_dis,t - p_t * q_ch,t ) * dt其中 p_t 是該時(shí)段電價(jià)q_dis,t 是放電功率q_ch,t 是充電功率dt 是步長。這個(gè)形式只反映了電費(fèi)差忽略了一個(gè)關(guān)鍵問題電池每放一度電循環(huán)壽命都在縮短這部分損耗是真實(shí)成本。所以第二個(gè)層次是把老化成本折算進(jìn)目標(biāo)函數(shù)放電收益變成 (p_t - c_deg) * q_dis,t * dt其中 c_deg 是每放電 1 kWh 折算出的電池?fù)p耗費(fèi)用具體折算方法見第 4 章。第三個(gè)層次是需量電費(fèi)管理。國內(nèi)工商業(yè)電價(jià)常見兩部制除了電度電費(fèi)還有按最大需量計(jì)收的基本電費(fèi)。儲(chǔ)能削減峰值負(fù)荷能直接省下這部分錢目標(biāo)函數(shù)里就要加入「需量電費(fèi)單價(jià) × 削減的峰值功率」這一項(xiàng)。但注意這一項(xiàng)會(huì)讓模型從純線性變成帶 max 算子的分段線性問題通常需要用 epigraph 變換或引入輔助變量才能保持線性。對絕大多數(shù)入門場景來說先做前兩個(gè)層次就夠了套利加老化成本。第三個(gè)層次建議在基礎(chǔ)版本跑通后再擴(kuò)展否則一邊學(xué)模型一邊處理 max 算子的重構(gòu)很容易卡住。2.2 約束條件怎么寫SOC 遞推、功率邊界與充放電互斥約束條件里最重要的一條是 SOC 遞推方程它描述電池能量隨時(shí)間的變化SOC(t1) SOC(t) [ eta_ch * q_ch,t - q_dis,t / eta_dis ] * dt / E_ratedeta_ch 和 eta_dis 分別是充放電效率E_rated 是額定容量。這條約束把相鄰時(shí)段的 SOC 串起來是整個(gè)模型的骨架。除了遞推方程還有幾類邊界約束SOC 上下限比如 0.1 到 0.9防止過充過放、充放電功率上下限0 到 P_max、初始 SOC 固定、以及終端 SOC 約束——要求周期結(jié)束時(shí)回到初始值避免優(yōu)化器把初始存電當(dāng)免費(fèi)資源一次性放空。還有一個(gè)容易糾結(jié)的點(diǎn)充放電互斥約束 q_ch * q_dis 0。這是非線性約束但絕大多數(shù)情況下可以安全丟棄。原因是只要充電和放電發(fā)生在同一時(shí)段能量先充進(jìn)去再放出來要經(jīng)過一次充放效率損耗0.95 × 0.95 ≈ 0.9白白損失 10% 能量電價(jià)是正的這種自我抵消的行為永遠(yuǎn)不可能是最優(yōu)解。省掉這個(gè)約束問題就從非線性規(guī)劃退化成純線性規(guī)劃求解速度和穩(wěn)定性都大幅提升。只有當(dāng)模型里加了最小充放電功率、啟停成本這類條款時(shí)才需要引入 0-1 二進(jìn)制變量重新變成 MILP。2.3 為什么用線性規(guī)劃linprog 與 YALMIP/啟發(fā)式算法的邊界儲(chǔ)能價(jià)格套利問題本質(zhì)上是 LP目標(biāo)線性、約束線性、變量連續(xù)。線性規(guī)劃的優(yōu)點(diǎn)是能保證全局最優(yōu)、求解可復(fù)現(xiàn)、速度快不存在啟發(fā)式算法那種每次運(yùn)行結(jié)果不穩(wěn)定、需要反復(fù)調(diào)參數(shù)的玄學(xué)。常見做法是直接用 MATLAB 內(nèi)置 linprog或者用 YALMIP 搭模型再調(diào)用底層求解器。YALMIP 的好處是建模語法接近數(shù)學(xué)表達(dá)式后續(xù)要加二進(jìn)制變量、做 MILP 擴(kuò)展時(shí)不用重寫整套矩陣。三者的選擇邊界大致如下求解方案能處理的模型獲取難度適用場景MATLAB linprog連續(xù)變量 LP內(nèi)置 Optimization Toolbox純價(jià)格套利、無二進(jìn)制變量的場景YALMIP GLPK/SCSLP/MILP免費(fèi)求解器需下載并配置路徑學(xué)生做原型、驗(yàn)證算法YALMIP Gurobi/CPLEX大規(guī)模 LP/MILP商業(yè)授權(quán)或?qū)W術(shù)授權(quán)高維問題、強(qiáng)耦合約束經(jīng)驗(yàn)是先別急著上 YALMIP 和商業(yè)求解器。用 linprog 把純 LP 版本跑通確認(rèn)模型邏輯沒問題再按需升級(jí)。很多人一上來就用遺傳算法之類的啟發(fā)式方法反而把簡單問題復(fù)雜化——非線性效率曲線、滯回特性這類模型才值得動(dòng)用啟發(fā)式線性能解的問題用線性方法拿全局最優(yōu)解才是正路。3. 用 MATLAB 跑通儲(chǔ)能經(jīng)濟(jì)性優(yōu)化linprog 建模代碼逐段拆解模型立住之后代碼就是把數(shù)學(xué)翻譯成矩陣。下面用一組常見參數(shù)做演示200 kWh / 50 kW 儲(chǔ)能系統(tǒng)充放電效率 0.95SOC 范圍 0.10.9三段式分時(shí)電價(jià)。代碼按數(shù)據(jù)準(zhǔn)備、模型構(gòu)建、結(jié)果處理三塊走。3.1 參數(shù)與分時(shí)電價(jià)數(shù)據(jù)準(zhǔn)備一份可直接改的輸入模板%% 儲(chǔ)能參數(shù)與分時(shí)電價(jià)定義 clc; clear; close all; E_rated 200; % 額定容量/kWh P_max 50; % 最大充放電功率/kW SOC_init 0.5; % 初始荷電狀態(tài) SOC_min 0.1; % SOC 下限 SOC_max 0.9; % SOC 上限 eta_ch 0.95; % 充電效率 eta_dis 0.95; % 放電效率 dt 1; % 時(shí)間步長/h % 24小時(shí)分時(shí)電價(jià)單位元/kWh % 0-7點(diǎn)谷段0.38-17點(diǎn)平段0.818-21點(diǎn)峰段1.222-23點(diǎn)平段0.8 price [0.3*ones(1,8), 0.8*ones(1,10), 1.2*ones(1,4), 0.8*ones(1,2)]; N 24; % 優(yōu)化周期內(nèi)時(shí)段數(shù)這里幾個(gè)要點(diǎn)price 向量必須按時(shí)間順序排列且長度等于 N效率值用的是小數(shù)而不是百分?jǐn)?shù)dt 的單位要和電價(jià)單位匹配電價(jià)是元/kWh、功率是 kW乘上 dt 小時(shí)得到元。如果要做多日連續(xù)仿真把 price 向量按天拼接即可但要注意 SOC 會(huì)在日與日之間傳遞不在本章范圍第 6 章會(huì)講滾動(dòng)處理。3.2 核心建模與求解代碼決策變量、約束矩陣與 linprog 調(diào)用%% 決策變量布局 % x [q_ch(1..N), q_dis(1..N), SOC(1..N1)] % SOC(1)是第1時(shí)段開始時(shí)SOCSOC(N1)是周期結(jié)束時(shí)SOC n_var 3*N 1; % 目標(biāo)函數(shù)linprog 求最小值所以充電成本為正、放電收益取負(fù) f zeros(n_var, 1); f(1:N) price * dt; % 充電花費(fèi) f(N1:2*N) -price * dt; % 放電收入取負(fù)號(hào) %% 等式約束SOC 遞推 % SOC(t1) SOC(t) eta_ch*q_ch(t)*dt/E_rated - q_dis(t)*dt/(E_rated*eta_dis) Aeq zeros(N, n_var); beq zeros(N, 1); for t 1:N Aeq(t,t) eta_ch * dt / E_rated; % q_ch(t) 系數(shù) Aeq(t,Nt) -dt / (E_rated * eta_dis); % q_dis(t) 系數(shù) Aeq(t,2*Nt) -1; % -SOC(t) Aeq(t,2*Nt1) 1; % SOC(t1) end % 初始 SOC 固定為 SOC_init Aeq [Aeq; zeros(1, n_var)]; Aeq(end, 2*N1) 1; beq [beq; SOC_init]; % 終端 SOC 約束周期結(jié)束回到初始值 Aeq [Aeq; zeros(1, n_var)]; Aeq(end, 3*N1) 1; beq [beq; SOC_init]; %% 變量邊界 lb zeros(n_var, 1); ub inf(n_var, 1); lb(1:2*N) 0; ub(1:2*N) P_max; % 充放電功率邊界 lb(2*N1:end) SOC_min; ub(2*N1:end) SOC_max; % SOC 邊界 lb(2*N1) SOC_init; ub(2*N1) SOC_init; % 初始 SOC 雙邊界固定 %% 求解 options optimoptions(linprog,Algorithm,dual-simplex,Display,iter); [x_opt, fval, exitflag] linprog(f, [], [], Aeq, beq, lb, ub, options);逐段說明一下。決策變量把充電功率、放電功率、SOC 排成一個(gè)長向量長度是 3N1。SOC 多一個(gè)點(diǎn)是用來表示周期結(jié)束狀態(tài)的這個(gè)布局決定了后面所有矩陣的列索引改的時(shí)候要非常小心。目標(biāo)函數(shù)里充電對應(yīng)正系數(shù)因?yàn)?linprog 是最小化放電對應(yīng)負(fù)系數(shù)最小化負(fù)的收益等價(jià)于最大化收益。SOC 變量的系數(shù)是 0它本身沒有直接成本。SOC 遞推約束用循環(huán)逐時(shí)段生成每個(gè)時(shí)段一行等式系數(shù)來自遞推公式的移項(xiàng)。這里最容易犯的錯(cuò)是 eta_dis 寫錯(cuò)位置——它是放在放電功率的分母上不是乘在分子上寫反了結(jié)果會(huì)差一個(gè)效率的平方。最后兩個(gè)等式分別固定初始 SOC 和終端 SOC。終端 SOC 約束是防止優(yōu)化器把初始電量當(dāng)免費(fèi)午餐的后悔藥如果去掉典型結(jié)果會(huì)是最后一個(gè)峰段把電池放到 SOC 下限第二天無電可用。提示初次調(diào)試時(shí)把Display設(shè)為iter能看到單純形迭代過程確認(rèn)模型穩(wěn)定后再改回final減少刷屏。3.3 結(jié)果提取與繪圖充放電曲線、SOC 曲線與收益統(tǒng)計(jì)%% 結(jié)果提取 q_ch x_opt(1:N); % 各時(shí)段充電功率/kW q_dis x_opt(N1:2*N); % 各時(shí)段放電功率/kW SOC x_opt(2*N1:end); % SOC序列長度 N1 profit -fval; % 凈收益 -目標(biāo)函數(shù)值 E_ch sum(q_ch) * dt; % 總充電電量/kWh E_dis sum(q_dis) * dt; % 總放電電量/kWh fprintf(凈收益: %.2f 元\n, profit); fprintf(充電電量: %.2f kWh, 放電電量: %.2f kWh\n, E_ch, E_dis); %% 繪圖功率、SOC、電價(jià)三聯(lián)圖 t 1:N; figure(Color,w,Position,[100 100 900 650]); subplot(3,1,1); bar(t, q_ch, 0.6, FaceColor,[0.2 0.5 1]); hold on; bar(t, -q_dis, 0.6, FaceColor,[1 0.6 0.2]); legend(充電,放電,Location,best); ylabel(功率/kW); ylim([-1.2*P_max 1.2*P_max]); xlim([0.5 N0.5]); subplot(3,1,2); stairs([t, N1], SOC, LineWidth,1.5); ylabel(SOC); ylim([0 1]); xlim([0.5 N0.5]); grid on; subplot(3,1,3); stairs(t, price, k, LineWidth,1.5); ylabel(電價(jià)/(元/kWh)); xlabel(時(shí)間/h); xlim([0.5 N0.5]); grid on;結(jié)果提取的關(guān)鍵是理解變量索引x_opt 里前 N 個(gè)是充電功率接著 N 個(gè)是放電功率最后 N1 個(gè)是 SOC。profit 取 -fval因?yàn)?linprog 最小化的目標(biāo)函數(shù)值本身是負(fù)的凈收益。繪圖時(shí)把放電功率畫成負(fù)值這樣一眼能看出充放時(shí)段和電價(jià)的對應(yīng)關(guān)系。正常的優(yōu)化結(jié)果應(yīng)該是谷段充電功率為正、SOC 抬升峰段放電功率為負(fù)、SOC 回落平段基本不動(dòng)。如果看到谷段不充、峰段不放或者功率在某個(gè)平臺(tái)期反復(fù)跳動(dòng)就是第 5 章要講的典型問題。4. 參數(shù)敏感性分析容量配比、老化成本與電價(jià)結(jié)構(gòu)怎么影響收益代碼跑通只是第一步真正決定這套優(yōu)化有沒有價(jià)值的是參數(shù)。同一個(gè)模型換一組容量配比或電價(jià)數(shù)據(jù)結(jié)論可能完全相反。這一章把三個(gè)最影響結(jié)果的參數(shù)講透。4.1 容量與功率配比C-rate決定策略可行域P_max 與 E_rated 的比值就是 C-rate。C-rate 0.25 意味著滿功率充放電需要 4 小時(shí)0.5C 需要 2 小時(shí)。這個(gè)指標(biāo)直接決定電池能不能在谷段窗口內(nèi)充滿。以本文參數(shù)為例谷段持續(xù) 8 小時(shí)50 kW 對 200 kWh 是 0.25C理論上 4 小時(shí)就能從空充到滿谷段綽綽有余。但如果谷段只有 2 小時(shí)0.25C 系統(tǒng)只能充 100 kWh浪費(fèi)一半容量這時(shí)把 P_max 提到 100 kW0.5C才能吃滿谷段電量。反過來P_max 也不是越大越好——變流器成本隨功率上升而且功率過大時(shí)充放電過程更激進(jìn)對電池壽命的影響在老化成本模型里會(huì)進(jìn)一步放大。C-rate滿充時(shí)間對 2 小時(shí)谷段的適配0.25C4 小時(shí)只能充一半容量收益受限0.5C2 小時(shí)剛好充滿1C1 小時(shí)能充滿但變流器成本高、壽命壓力大調(diào)參時(shí)建議固定 E_rated掃描 P_max 看凈收益曲線。收益隨 P_max 上升會(huì)先快速增長、后趨于飽和飽和點(diǎn)就是經(jīng)濟(jì)上最優(yōu)的功率配比。曲線拐點(diǎn)附近再疊加變流器成本才是真正的工程最優(yōu)解。4.2 循環(huán)壽命與老化成本折算目標(biāo)函數(shù)里最容易被忽略的一項(xiàng)老化成本折算的常見做法是線性折舊把電池總購置成本平攤到全生命周期放電量上。c_deg 電池單位容量成本 / (循環(huán)壽命 * 放電深度)假設(shè)電池 500 元/kWh循環(huán)壽命 4000 次、按 80% 放電深度計(jì)則 c_deg 500 / (4000 × 0.8) ≈ 0.156 元/kWh也就是每放 1 kWh 電要計(jì)提約 0.16 元損耗。不同循環(huán)壽命下的折算值如下循環(huán)壽命80% DoDc_deg元/kWh 放電2000 次0.314000 次0.166000 次0.10加入 c_deg 之后目標(biāo)函數(shù)里放電收益從 p_t 變成 p_t - c_deg。這個(gè)改動(dòng)會(huì)真實(shí)改變優(yōu)化結(jié)果某些價(jià)差小、原本勉強(qiáng)可套利的時(shí)段扣掉老化成本后變成虧損優(yōu)化器會(huì)主動(dòng)放棄在那段時(shí)間放電。這是模型從「看起來賺錢」走向「真實(shí)賺錢」的關(guān)鍵一步。注意線性折舊是個(gè)簡化模型實(shí)際電池老化與放電深度、倍率、溫度呈非線性關(guān)系。做方案對比用線性折算足夠做精確壽命預(yù)測則需要換用雨流計(jì)數(shù)或電化學(xué)老化模型那個(gè)就要上 MILP 或啟發(fā)式算法了。4.3 電價(jià)結(jié)構(gòu)與盈虧平衡價(jià)差先算門檻再調(diào)參判斷一個(gè)場景值不值得做儲(chǔ)能套利先算盈虧平衡價(jià)差不用跑代碼p_peak_min p_valley / (eta_ch * eta_dis) c_deg以谷價(jià) 0.3 元/kWh、雙效率 0.95、c_deg 0.156 為例p_peak_min 0.3 / 0.9025 0.156 ≈ 0.49 元/kWh。也就是說峰段電價(jià)超過 0.49 元時(shí)才有正收益超過越多賺得越多。如果峰價(jià)只有 0.5 元每度電毛利不到一分錢扣掉運(yùn)維成本基本白干如果把效率換成 0.9門檻直接升到 0.53。電價(jià)結(jié)構(gòu)里還有一個(gè)常被忽略的因素是谷段時(shí)長。谷段只有 2 小時(shí)而 C-rate 是 0.25C 時(shí)電池充不滿實(shí)際套利電量只有理論的一半。所以評(píng)估一個(gè)項(xiàng)目時(shí)不能只看峰谷價(jià)差還要看「價(jià)差 × 可套利電量 × 年循環(huán)次數(shù)」三者乘積。這個(gè)視角能解釋為什么同一套代碼換到某些省份的電價(jià)數(shù)據(jù)后收益大幅縮水——不是代碼錯(cuò)了是電價(jià)結(jié)構(gòu)根本不匹配。5. 儲(chǔ)能運(yùn)行優(yōu)化避坑指南MATLAB 求解中的五個(gè)常見問題排查理論和代碼都講完了下面是實(shí)際調(diào)試中踩過的坑按「現(xiàn)象 → 原因 → 解決」寫每條都是血淚經(jīng)驗(yàn)照著排查能省好幾個(gè)晚上。5.1 linprog 報(bào)錯(cuò)與求解器路徑問題現(xiàn)象運(yùn)行到 linprog 那行報(bào)Undefined function or variable linprog或者optimoptions直接報(bào)錯(cuò)。原因MATLAB 沒裝 Optimization Toolbox。linprog 不是基礎(chǔ)函數(shù)它屬于工具箱optimoptions 是 R2013b 之后引入的寫法老版本也不認(rèn)。解決先在命令行執(zhí)行ver(optim)如果顯示未安裝需要安裝對應(yīng)工具箱。確認(rèn)裝了但還是報(bào)錯(cuò)檢查是不是用了老版本語法老版本用optimset而不是optimoptions。如果不想裝工具箱就改用 YALMIP 加免費(fèi)求解器 GLPK建模代碼要相應(yīng)改成 YALMIP 語法。5.2 充放電曲線震蕩退化最優(yōu)解的判定與處理現(xiàn)象結(jié)果里相鄰時(shí)段功率劇烈交替比如 19 點(diǎn)放 50 kW、20 點(diǎn)充 50 kW、21 點(diǎn)又放SOC 曲線像鋸齒。目標(biāo)函數(shù)值看著正常但曲線完全不像能實(shí)際執(zhí)行的策略。原因電價(jià)平臺(tái)期存在退化解。LP 保證目標(biāo)函數(shù)最優(yōu)但不保證解唯一當(dāng)多個(gè)方案取得相同收益時(shí)單純形法返回的頂點(diǎn)解可能毫無規(guī)律。常見于峰段與峰段之間、平段與谷段邊界處。解決最干凈的方案是在目標(biāo)函數(shù)里加切換懲罰項(xiàng)用輔助變量把相鄰時(shí)段功率差值的絕對值計(jì)入目標(biāo)懲罰系數(shù)取一個(gè)很小的值比如 1e-3 量級(jí)既不影響總收益又能壓住震蕩。工程上更快的做法是如果震蕩幅度不大直接對結(jié)果做后處理平滑再重新核算目標(biāo)函數(shù)值如果收益損失在 1% 以內(nèi)說明震蕩只是退化解平滑后的策略可以放心用。記住先算收益差再?zèng)Q定要不要平滑別憑感覺改。5.3 終端 SOC 失控優(yōu)化結(jié)果把電池放空的后悔藥現(xiàn)象結(jié)果里最后一個(gè)峰段電池被放到 SOC 下限曲線看起來很「完美」地把每一度電都賺干凈了但第二天這個(gè)策略根本沒法繼續(xù)執(zhí)行——電池沒電了。原因沒加終端 SOC 約束。初始 SOC 是給定的、免費(fèi)的優(yōu)化器會(huì)把它當(dāng)成可消耗資源在最后一個(gè)高價(jià)時(shí)段全部變現(xiàn)。解決在等式約束里加上 SOC(N1) SOC_init。如果做的是滾動(dòng)優(yōu)化每一步的初始 SOC 來自實(shí)測不需要強(qiáng)綁終端值但至少加一個(gè) SOC(N1) ≥ SOC_min 的下限約束兜底。這個(gè)坑極其隱蔽因?yàn)閱稳战Y(jié)果看起來完全正常要連續(xù)跑多日才會(huì)暴露。5.4 最優(yōu)收益為負(fù)先查數(shù)據(jù)再查模型現(xiàn)象linprog 正常返回exitflag 是 1但凈收益算出來是負(fù)的。原因要么電價(jià)數(shù)據(jù)有問題要么這個(gè)場景本身就不經(jīng)濟(jì)。常見數(shù)據(jù)錯(cuò)誤包括峰谷價(jià)差寫反、電價(jià)單位不一致比如誤用元/MWh、效率參數(shù)填成 0.95 但實(shí)際想表達(dá) 95% 卻寫成了 95。解決先用第 4.3 節(jié)的盈虧平衡公式手算一遍門檻價(jià)看峰段電價(jià)是否高于門檻。如果高于門檻但結(jié)果還是負(fù)逐個(gè)檢查效率、電價(jià)單位、老化成本取值。如果確實(shí)低于門檻那負(fù)收益就是正確結(jié)論——說明這個(gè)場景不該上儲(chǔ)能套利模型給你省了一筆投資這本身就是價(jià)值。5.5 單位不一致導(dǎo)致的數(shù)值翻車現(xiàn)象收益大得離譜比如 200 kWh 的電池一天賺了幾萬塊或者 SOC 曲線亂跳、約束怎么調(diào)都矛盾。原因單位混用了——容量用 MWh、功率用 kW、電價(jià)用元/MWh導(dǎo)致約束矩陣?yán)锔黜?xiàng)數(shù)量級(jí)差好幾個(gè)量級(jí)數(shù)值病態(tài)。解決統(tǒng)一到 kW / kWh / 元/kWh 三個(gè)基礎(chǔ)單位。改完數(shù)據(jù)后在模型構(gòu)建前加一句打印核對各數(shù)組的最大最小值尤其是 E_rated 和 P_max 的比例關(guān)系。單位錯(cuò)誤這種事排查半天往往最后發(fā)現(xiàn)就是一處分母寫錯(cuò)屬于最冤的翻車方式。6. 進(jìn)階從單日優(yōu)化到滾動(dòng)優(yōu)化與規(guī)則策略對比驗(yàn)證6.1 滾動(dòng)優(yōu)化只執(zhí)行第一步每小時(shí)重算單日優(yōu)化適合算理論收益上限但真拿去運(yùn)行會(huì)有兩個(gè)問題一是電價(jià)預(yù)測不可能完全準(zhǔn)二是實(shí)際執(zhí)行的充放電量和計(jì)劃總會(huì)有偏差SOC 越偏越遠(yuǎn)。常見做法是把單日求解封裝成函數(shù)然后用滾動(dòng)優(yōu)化的框架循環(huán)調(diào)用每個(gè)小時(shí)基于當(dāng)前實(shí)測 SOC 和未來一段時(shí)間的電價(jià)預(yù)測重新求解一次但只執(zhí)行第一步。%% 滾動(dòng)優(yōu)化主循環(huán) T_total 24 * 7; % 仿真一周 H 24; % 優(yōu)化窗口長度 soc_now SOC_init; result_q_ch zeros(T_total, 1); result_q_dis zeros(T_total, 1); for k 1:T_total % 取未來 H 小時(shí)電價(jià)此處用真實(shí)電價(jià)代替預(yù)測 idx mod((k-1:kH-2), 24) 1; price_fc price(idx); % 調(diào)用封裝好的單次優(yōu)化函數(shù) [q_ch, q_dis, ~] solve_storage_one_day(price_fc, E_rated, P_max, ... soc_now, SOC_min, SOC_max, eta_ch, eta_dis, dt); % 只執(zhí)行第一步 result_q_ch(k) q_ch(1); result_q_dis(k) q_dis(1); % 按實(shí)際充放電量更新 SOC soc_now soc_now (eta_ch * q_ch(1) - q_dis(1) / eta_dis) * dt / E_rated; end這一步的意義在于讓優(yōu)化永遠(yuǎn)從真實(shí)狀態(tài)出發(fā)。單日優(yōu)化里終端 SOC 約束導(dǎo)致的可調(diào)度容量損失在滾動(dòng)框架下自然消失——每天每步都在重新初始化。窗口長度 H 的選取有個(gè)折中太短看不到完整谷峰周期太長對預(yù)測精度要求高且求解規(guī)模變大我一般取 24 小時(shí)。6.2 與規(guī)則策略對比用基準(zhǔn)線驗(yàn)證優(yōu)化增益滾動(dòng)優(yōu)化跑出來的結(jié)果好不好看需要跟一個(gè)規(guī)則基準(zhǔn)對比。最簡單的規(guī)則策略是「谷段充滿、峰段放完」谷段按最大功率充電峰段按最大功率放電其他時(shí)段不動(dòng)。把同一組電價(jià)和參數(shù)喂給規(guī)則策略算出收益再和優(yōu)化結(jié)果對比。兩者的差值就是優(yōu)化帶來的增益。如果增益很小說明電價(jià)結(jié)構(gòu)太簡單、規(guī)則策略已經(jīng)接近最優(yōu)如果增益明顯說明復(fù)雜電價(jià)結(jié)構(gòu)下優(yōu)化確實(shí)值得。這個(gè)對比在項(xiàng)目匯報(bào)里特別有用——評(píng)審不會(huì)只看絕對收益更關(guān)心你比拍腦袋策略多賺了多少。我最早跑這個(gè)題目時(shí)沒加終端 SOC 約束結(jié)果每日收益虛高跟規(guī)則策略一對比才發(fā)現(xiàn)自己把初始存電免費(fèi)放掉了。后來把約束補(bǔ)齊、單位統(tǒng)一收益數(shù)字才真正經(jīng)得起復(fù)核。這類代碼模型寫簡單一點(diǎn)沒關(guān)系邊界條件和單位才是真正翻車的地方。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取