化的微網(wǎng)多電源容量配置Matlab實(shí)現(xiàn))
做微網(wǎng)容量配置的同仁應(yīng)該都有體會(huì)風(fēng)光出力一波動(dòng)、負(fù)荷一變臉之前算好的配置可能立馬就不夠看了。我早先做這類項(xiàng)目時(shí)用的還是確定性優(yōu)化加多個(gè)典型日?qǐng)鼍敖Y(jié)果每次評(píng)審都被追問一句“極端場(chǎng)景你考慮了沒有”。后來轉(zhuǎn)用兩階段魯棒優(yōu)化來做微網(wǎng)多電源容量配置把不確定性問題從“事后補(bǔ)丁”變成了“事前兜底”整個(gè)項(xiàng)目的說服力提升了一個(gè)檔次。這篇博客就把我在Matlab里的完整實(shí)現(xiàn)思路、建模細(xì)節(jié)、求解流程和踩過的坑一次性說清楚想直接復(fù)現(xiàn)的按章節(jié)走就行。1. 核心思路為什么容量配置要用兩階段魯棒優(yōu)化1.1 容量配置問題到底在解決什么微網(wǎng)里的“多電源”一般不是指發(fā)電機(jī)品類多而是指可控與不可控電源的組合。常見配置包括光伏、風(fēng)電這類不可控可再生電源柴油機(jī)或微型燃?xì)廨啓C(jī)這類可控發(fā)電單元再加上儲(chǔ)能系統(tǒng)常規(guī)負(fù)荷里還往往帶一定比例的可中斷負(fù)荷。容量配置要做的事就是在這些候選電源類型和數(shù)量都給定的前提下把每種電源的安裝容量選出來使得整體方案在全壽命周期內(nèi)既滿足供電可靠性又讓綜合費(fèi)用盡量低。這個(gè)決策里有個(gè)天然的層次矛盾——容量投資是一次性的大額支出而系統(tǒng)運(yùn)行成本是日積月累的支出。如果只考慮投資成本配得越少越省錢但運(yùn)行階段可能天天買高價(jià)電如果只考慮運(yùn)行成本配得越足越穩(wěn)但投資回收期會(huì)拉得很難看。容量配置問題本質(zhì)上就是要把這兩個(gè)階段的目標(biāo)捏在一起做聯(lián)合優(yōu)化。傳統(tǒng)做法是把典型日?qǐng)鼍肮潭ㄏ聛肀热绱杭?、夏季、大?fù)荷日、小負(fù)荷日各挑幾天讓優(yōu)化模型在這幾個(gè)場(chǎng)景下做運(yùn)行模擬再把運(yùn)行費(fèi)用折算進(jìn)目標(biāo)函數(shù)。這種方法的弱點(diǎn)很明顯所選的典型日終究只是歷史數(shù)據(jù)的抽樣萬一未來出現(xiàn)比歷史更惡劣的連續(xù)陰雨天、風(fēng)速長時(shí)間偏小、或者負(fù)荷尖峰疊加新能源低谷的情況按這套容量配置出來的微網(wǎng)可能直接撐不住。兩階段魯棒優(yōu)化把不確定性直接納入到了模型結(jié)構(gòu)里。它不再問“這些給定場(chǎng)景下能不能跑通”而是問“在允許的不確定性范圍內(nèi)最惡劣的場(chǎng)景下系統(tǒng)能不能扛得住、運(yùn)行費(fèi)用最多是多少”。這個(gè)視角的轉(zhuǎn)變讓結(jié)果對(duì)邊界條件天然保守恰好適合容量配置這種要管五年十年的大決策。1.2 為什么用“兩階段”結(jié)構(gòu)表達(dá)這個(gè)問題把數(shù)學(xué)模型攤開看容量配置有兩個(gè)層次的動(dòng)作需要優(yōu)化第一階段這里在知道不確定參數(shù)可能的取值范圍、但不知道具體出力的前提下決定各電源的裝機(jī)容量。第二階段運(yùn)行層在容量給定、不確定參數(shù)的具體取值被揭示后做實(shí)時(shí)經(jīng)濟(jì)調(diào)度也就是在各機(jī)組出力、儲(chǔ)能充放電之間找到成本最低的運(yùn)行方案。這兩個(gè)階段時(shí)間尺度不同信息結(jié)構(gòu)也不同。第一階段是“看分布做決策”第二階段是“看實(shí)現(xiàn)做響應(yīng)”。兩階段魯棒優(yōu)化的目標(biāo)函數(shù)就是先求第一階段的投資成本再加上第二階段在最壞不確定場(chǎng)景下的最小運(yùn)行成本。寫成數(shù)學(xué)語言就是典型的“min-max-min”結(jié)構(gòu)外層min對(duì)應(yīng)容量決策中間max對(duì)應(yīng)不確定性集合里挑最壞場(chǎng)景內(nèi)層min對(duì)應(yīng)運(yùn)行調(diào)度優(yōu)化。這里的核心難點(diǎn)在于中間層的max不是隨便挑一個(gè)場(chǎng)景而是要對(duì)整個(gè)不確定性集合求最大。如果直接把三種不確定變量風(fēng)電、光伏、負(fù)荷的所有組合都枚舉一遍計(jì)算量是指數(shù)級(jí)的在容量配置這種中等規(guī)模問題上根本跑不動(dòng)。后面要講的列與約束生成算法CCG就是專門用來對(duì)付這個(gè)難題的它不枚舉所有場(chǎng)景而是讓“壞場(chǎng)景”在迭代中自己浮出水面。1.3 與隨機(jī)規(guī)劃、信息間隙決策理論的對(duì)比取舍做微網(wǎng)規(guī)劃的同行還會(huì)遇到隨機(jī)規(guī)劃和信息間隙決策理論IGDT等備選方案。簡單說下我的取舍理由隨機(jī)規(guī)劃需要預(yù)設(shè)不確定參數(shù)的概率分布且理論上要有足夠多的場(chǎng)景保證收斂。工程里風(fēng)光出力的精確分布往往很難拿到即便拿歷史數(shù)據(jù)擬合尾部風(fēng)險(xiǎn)也常被低估。計(jì)算量同樣不小。信息間隙決策理論它在給定“偏差幅度”下最大化系統(tǒng)對(duì)偏差的承受能力不需要分布思路很簡潔但對(duì)非線性約束的處理比較麻煩而且它的魯棒性度量方式偏向“最大可承受偏差”和工程上關(guān)心“最壞情況下的費(fèi)用”表述不太一致。兩階段魯棒優(yōu)化只需要不確定量落在某個(gè)有界集合內(nèi)即可不要求精確概率求解結(jié)果直接給出最壞情況下的運(yùn)行成本上界。這種“以集合代替分布”的做法在數(shù)據(jù)有限場(chǎng)景下非常實(shí)用。所以最終選兩階段魯棒優(yōu)化不是因?yàn)樗呒?jí)而是因?yàn)樗汀叭萘颗渲眯枰5?、?shù)據(jù)又不夠精細(xì)”這一工程需求最匹配。2. 建模細(xì)節(jié)目標(biāo)函數(shù)、約束與不確定性集合的構(gòu)建2.1 目標(biāo)函數(shù)的分層設(shè)計(jì)模型的目標(biāo)函數(shù)分兩層寫第一層是投資成本其中p代表電源類型索引涵蓋光伏pv、風(fēng)電wt、柴油機(jī)de、儲(chǔ)能es等c_p是單位容量投資成本N_p是安裝容量r是折現(xiàn)率L是規(guī)劃年限。這樣可以把一次性投資折算成等年值和年運(yùn)行成本放在同一個(gè)時(shí)間尺度上比較。第二層是在所有可能的風(fēng)光出力和負(fù)荷波動(dòng)下取運(yùn)行成本最大的那個(gè)場(chǎng)景然后對(duì)應(yīng)該最惡劣場(chǎng)景求經(jīng)濟(jì)調(diào)度的最小運(yùn)行成本是燃料成本由柴油機(jī)出力和燃油單價(jià)決定是向上級(jí)電網(wǎng)購電時(shí)支付的購電成本有時(shí)還要把切負(fù)荷懲罰加進(jìn)去表示在極端場(chǎng)景下不得已切除一部分負(fù)荷的代價(jià)如果配置了儲(chǔ)能還可以考慮儲(chǔ)能循環(huán)老化折算成的運(yùn)行維護(hù)成本。兩者合起來就是整個(gè)兩階段魯棒優(yōu)化模型的函數(shù)主體這里要注意一個(gè)容易被忽略的點(diǎn)運(yùn)行成本內(nèi)部求的是min但它的外層又被max包住。也就是說調(diào)度員在給定容量下總會(huì)盡力把運(yùn)行成本壓到最低但大自然不確定性會(huì)挑一個(gè)讓這個(gè)最低成本最高的場(chǎng)景來“為難”你。這種對(duì)抗式邏輯正是魯棒優(yōu)化的靈魂。2.2 約束條件的幾大核心族建模時(shí)約束數(shù)量看著多核心其實(shí)就幾個(gè)族規(guī)劃階段和運(yùn)行階段分開列。規(guī)劃階段的核心約束是容量上界與安裝數(shù)量約束。每種電源的總安裝容量不能超過該場(chǎng)地或預(yù)算對(duì)應(yīng)的上限比如屋頂光伏受可用面積限制風(fēng)機(jī)受占地面積和噪聲限制。這條約束在Math中表達(dá)為運(yùn)行階段的約束是最多的主要包括功率平衡約束任意時(shí)刻所有電源出力、儲(chǔ)能放電、購電功率的總和等于負(fù)荷加儲(chǔ)能充電功率。求解中這個(gè)約束要帶平衡變量處理否則在極端場(chǎng)景下可能因?yàn)楣β薀o法平衡而彈出“infeasible”。儲(chǔ)能動(dòng)態(tài)約束包括充電功率上限、放電功率上限、荷電狀態(tài)SOC上下限、以及SOC的時(shí)間遞推關(guān)系這里充放電效率、分別參與兩個(gè)方向的能量轉(zhuǎn)換同時(shí)還要避免同一個(gè)時(shí)刻既充電又放電的邏輯錯(cuò)誤。實(shí)踐中最常見的做法是引入充電狀態(tài)和放電狀態(tài)的0-1變量來互斥否則連續(xù)變量求解器很容易給出“邊充邊放”這種物理上無意義但數(shù)學(xué)上似乎可行的解??煽仉娫闯隽团榔录s束柴油機(jī)的出力有上下限單位時(shí)間內(nèi)增減出力還受爬坡率限制。容量配置階段如果不加爬坡約束運(yùn)行成本會(huì)被樂觀估計(jì)配置結(jié)果會(huì)偏向多裝柴油機(jī)、少裝儲(chǔ)能。我在實(shí)際項(xiàng)目里吃過這個(gè)虧建議大家從建模第一天就把爬坡約束放進(jìn)去。棄風(fēng)棄光約束為了給魯棒優(yōu)化留出可行性余地可再生能源出力可以適度削減但削減量要控制在某個(gè)比例以內(nèi)比如不得高于預(yù)測(cè)出力的5%。這條約束也叫“可再生能源利用率下限”它的存在避免了魯棒解為了“抗最壞場(chǎng)景”而過度配置儲(chǔ)能、同時(shí)又在正常場(chǎng)景拼命棄風(fēng)棄光這種自相矛盾的結(jié)果。2.3 不確定性集合的取舍與數(shù)學(xué)表達(dá)兩階段魯棒優(yōu)化里不確定性集合的選擇直接決定求解難度和結(jié)果保守度。常用的有盒式不確定集每個(gè)不確定參數(shù)獨(dú)立地在區(qū)間內(nèi)波動(dòng)數(shù)學(xué)上最簡單但所有參數(shù)同時(shí)取極端值的概率極低做出來會(huì)過于保守。多面體不確定集在盒式基礎(chǔ)上加一個(gè)“總偏差預(yù)算”要求所有不確定參數(shù)偏離預(yù)測(cè)值的總量不能超過某個(gè)閾值。它把獨(dú)立極端情況限制住了保守度低不少數(shù)學(xué)上依然保持線性結(jié)構(gòu)。橢球不確定集用橢球描述相關(guān)性數(shù)學(xué)上更精細(xì)但會(huì)把模型變成二階錐規(guī)劃求解器要求和計(jì)算時(shí)間都上一個(gè)臺(tái)階。工程上最常用的還是多面體不確定集。以光伏為例可以寫成負(fù)荷的寫法類似只是把、換成和。這里的一組0-1變量和一組連續(xù)變量會(huì)并存0-1變量決定波動(dòng)方向連續(xù)變量決定波動(dòng)幅度。預(yù)算參數(shù)直接控制保守程度——設(shè)得越大允許同時(shí)波動(dòng)的變量越多結(jié)果越保守設(shè)得越小解的魯棒性越弱。從實(shí)操來看我通常建議先把設(shè)為0跑一版確定性模型作為費(fèi)用下限再把設(shè)為極端值跑一版最保守模型作為費(fèi)用上限。中間取若干檔位做靈敏度分析能畫出“保守度-成本”曲線這個(gè)曲線在項(xiàng)目評(píng)審時(shí)非常有用比單給一個(gè)“最優(yōu)解”有說服力得多。3. 兩階段魯棒求解CCG算法的原理與實(shí)現(xiàn)路徑3.1 “min-max-min”三層結(jié)構(gòu)到底在算什么剛才提到模型整體是“min-max-min”結(jié)構(gòu)很多人第一次看到會(huì)覺得有點(diǎn)繞。我用一個(gè)通俗的類比拆開講第一層min容量決策你作為微網(wǎng)規(guī)劃師現(xiàn)在要拍板裝多少光伏、多少風(fēng)機(jī)、多少儲(chǔ)能。決策完設(shè)備錢就花出去了。中間層max自然選擇你不知道未來光照、風(fēng)速、負(fù)荷到底會(huì)怎樣但你清楚它們會(huì)落在某個(gè)波動(dòng)范圍內(nèi)。大自然這時(shí)候“站了出來”替你挑了一個(gè)讓你運(yùn)行成本最高的組合。內(nèi)層min調(diào)度響應(yīng)面對(duì)這個(gè)已經(jīng)發(fā)生的“壞場(chǎng)景”微網(wǎng)的運(yùn)行調(diào)度系統(tǒng)會(huì)立刻做出最優(yōu)響應(yīng)——柴油機(jī)多出力、儲(chǔ)能放電、或者切掉一部分負(fù)荷盡量把這一天的運(yùn)行費(fèi)壓到最低。如果把這個(gè)邏輯寫成一句話就是在你最擔(dān)心的世界里做最經(jīng)濟(jì)的應(yīng)對(duì)。容量配置決策能不能扛住這個(gè)“最擔(dān)心的世界”就是魯棒優(yōu)化給出的答案。3.2 CCG算法主流程詳解CCGColumn and Constraint Generation列與約束生成是目前求解兩階段魯棒優(yōu)化最主流的精確算法之一它的核心思路不是枚舉所有場(chǎng)景而是“讓極端場(chǎng)景在迭代中自己長出來”每一輪只往主問題里加一個(gè)最惡劣場(chǎng)景對(duì)應(yīng)的約束。算法寫成偽碼很清晰初始化設(shè)置下界為負(fù)無窮上界為正無窮設(shè)定一個(gè)初始的“壞場(chǎng)景”通常取不確定參數(shù)的名義值即預(yù)測(cè)值設(shè)定收斂閾值比如0.01。求解主問題MP主問題里包含第一階段容量決策變量、第二階段運(yùn)行變量以及所有已經(jīng)識(shí)別出來的惡劣場(chǎng)景約束。解出來得到容量配置和當(dāng)前下界。固定容量配置求解子問題SP子問題是一個(gè)“給定容量、找最壞場(chǎng)景、算最小運(yùn)行成本”的優(yōu)化問題解出來得到當(dāng)前最壞場(chǎng)景和對(duì)應(yīng)的運(yùn)行成本再疊加投資成本得到當(dāng)前上界。收斂判斷如果上界和下界的相對(duì)誤差小于閾值停止迭代把當(dāng)前容量配置作為最終結(jié)果輸出。如果沒收斂把子問題解出來的這個(gè)最壞場(chǎng)景對(duì)應(yīng)的運(yùn)行變量和約束以新列的形式加入到主問題中返回步驟2繼續(xù)迭代。這個(gè)流程里最微妙的點(diǎn)在第5步——每輪迭代不是簡單改個(gè)參數(shù)而是往主問題里新增一組完整約束包含該場(chǎng)景下的功率平衡、儲(chǔ)能動(dòng)態(tài)、機(jī)組出力等讓主問題規(guī)模逐輪增大但每一輪都會(huì)更接近“所有極端場(chǎng)景都被考慮”的收斂狀態(tài)。3.3 子問題的對(duì)偶轉(zhuǎn)化與KKT條件處理子問題本身是一個(gè)內(nèi)嵌max的min問題不能直接用現(xiàn)成的商業(yè)求解器求解。解決這個(gè)問題的兩種主流途徑是強(qiáng)對(duì)偶轉(zhuǎn)化利用線性規(guī)劃的對(duì)偶理論把內(nèi)層的min問題替換為它的對(duì)偶max問題這樣整個(gè)子問題就變成一個(gè)單層的max問題外層找壞場(chǎng)景、內(nèi)層變成了對(duì)偶max合起來是max-max直接合并成一個(gè)max問題。這個(gè)方法的前提是內(nèi)層模型是線性且可行的強(qiáng)對(duì)偶定理保證二者最優(yōu)值相等。KKT條件轉(zhuǎn)化把內(nèi)層min問題的最優(yōu)性條件KKT條件作為約束加入外層問題中這樣也把雙層問題壓成了單層。但KKT條件里的互補(bǔ)松弛條件會(huì)引入非線性項(xiàng)需要借助大M法線性化。從我的使用經(jīng)驗(yàn)看只要模型保持線性優(yōu)先用強(qiáng)對(duì)偶轉(zhuǎn)化它實(shí)現(xiàn)簡單、對(duì)求解器友好。只有在模型里不得不加入非線性因素、強(qiáng)對(duì)偶無法直接套用的場(chǎng)景下才考慮KKT路線。這里有一個(gè)工程細(xì)節(jié)提醒做對(duì)偶轉(zhuǎn)化時(shí)內(nèi)層min問題里的“運(yùn)行成本”目標(biāo)函數(shù)寫多了哪個(gè)二次項(xiàng)或絕對(duì)值項(xiàng)對(duì)偶形式就會(huì)變得很難處理。比如儲(chǔ)能充放電損耗如果是按“功率平方”建模那內(nèi)層就不是LP強(qiáng)對(duì)偶就不能直接用了。前期的模型線性化工作直接影響后面能不能順利套用CCG。3.4 外逼近與CCG的差異性對(duì)比做魯棒優(yōu)化的文獻(xiàn)里還有一類叫“外逼近”outer approximation的算法容易和CCG混淆。我的理解是外逼近法在迭代中用一階近似約束逼近子問題的最優(yōu)值函數(shù)它對(duì)凸問題的效果很好但對(duì)離散變量的處理比較弱CCG則通過直接添加第二階段的變量和約束來逼近它不需要最優(yōu)值函數(shù)的光滑性假設(shè)對(duì)混合整數(shù)問題更友好。容量配置問題里儲(chǔ)能充放電狀態(tài)是0-1變量柴油機(jī)啟停也可能引入整數(shù)變量這些離散量的存在會(huì)讓外逼近的處理變得很啰嗦而CCG天然不怕。所以我最終在Matlab里落地的是CCG下面所有代碼也都圍繞這個(gè)算法展開。4. Matlab實(shí)操代碼框架、求解器配置與關(guān)鍵實(shí)現(xiàn)4.1 求解環(huán)境與依賴說明我在Windows環(huán)境下的Matlab R2022b上完成實(shí)現(xiàn)調(diào)用的是YALMIP工具箱加CPLEX求解器。如果你們手頭沒有CPLEX用Gurobi也可以代碼的頂層結(jié)構(gòu)完全不用動(dòng)只需要把YALMIP的solver設(shè)置那一行改掉。有一點(diǎn)務(wù)必確認(rèn)CCG里的主問題和子問題都涉及混合整數(shù)規(guī)劃不要用Matlab自帶的linprog或intlinprog去硬扛那個(gè)規(guī)模和速度在迭代求解下會(huì)很痛苦。工程上至少要用CPLEX、Gurobi或MOSEK這類商業(yè)求解器。4.2 模型參數(shù)與典型場(chǎng)景準(zhǔn)備實(shí)現(xiàn)的第一步是把以下參數(shù)準(zhǔn)備好電源候選集合每種電源的單位投資成本、壽命、最大允許安裝容量單位運(yùn)行成本柴油燃料單價(jià)、單位購電電價(jià)、切負(fù)荷懲罰單價(jià)不確定量預(yù)測(cè)值典型日24小時(shí)的光伏出力標(biāo)幺值、風(fēng)電出力標(biāo)幺值、負(fù)荷標(biāo)幺值序列不確定性集合參數(shù)波動(dòng)幅度的上下界、預(yù)算參數(shù)、以及可切負(fù)荷比例儲(chǔ)能參數(shù)容量單價(jià)、功率上限、SOC上下限、充放電效率、初始SOC調(diào)度約束參數(shù)柴油機(jī)出力上下限、爬坡率、最小運(yùn)行時(shí)間。所有時(shí)序數(shù)據(jù)都按小時(shí)分辨率建模典型日的數(shù)量可以取3到4個(gè)。如果只做示例可以先用一個(gè)典型日跑通代碼再擴(kuò)展到多典型日。4.3 主問題的YALMIP建??蚣苓@里給出一個(gè)精簡但完整的主問題建模框架關(guān)鍵模塊分了四塊決策變量聲明、投資成本目標(biāo)、運(yùn)行約束塊、以及CCG迭代用的場(chǎng)景約束塊。% 決策變量第一階段 N_pv sdpvar(1,1); % 光伏安裝容量 N_wt sdpvar(1,1); % 風(fēng)電安裝容量 N_de sdpvar(1,1); % 柴油機(jī)安裝容量 N_es sdpvar(1,1); % 儲(chǔ)能安裝容量 % 決策變量第二階段在當(dāng)前場(chǎng)景集合下 P_pv sdpvar(T,1); % 光伏實(shí)際出力 P_wt sdpvar(T,1); % 風(fēng)電實(shí)際出力 P_de sdpvar(T,1); % 柴油機(jī)出力 P_ch sdpvar(T,1); % 儲(chǔ)能充電功率 P_dis sdpvar(T,1); % 儲(chǔ)能放電功率 SOC sdpvar(T1,1); % 儲(chǔ)能荷電狀態(tài) P_buy sdpvar(T,1); % 購電功率 P_cut sdpvar(T,1); % 切負(fù)荷功率 u_ch binvar(T,1); % 充電狀態(tài)標(biāo)記 u_dis binvar(T,1); % 放電狀態(tài)標(biāo)記 % 目標(biāo)函數(shù)投資等年值 運(yùn)行成本運(yùn)行成本是從屬部分 inv_cost (c_pv*N_pv c_wt*N_wt c_de*N_de c_es*N_es) * crf; obj inv_cost (1/sce_num) * sum(oper_cost); % 多場(chǎng)景取平均CCG里場(chǎng)景逐輪新增這段代碼里crf是把一次性投資折算成年值的等額分付資本回收系數(shù)。它的計(jì)算是也就是通過折現(xiàn)率r和壽命年限L把全部投資折算成每年等額支付。這是個(gè)非常常用的財(cái)務(wù)轉(zhuǎn)換系數(shù)不要漏掉它否則投資成本和年運(yùn)行成本不在同一時(shí)間軸上模型結(jié)果會(huì)系統(tǒng)性偏向多裝儲(chǔ)能。另外主問題里的場(chǎng)景塊不是一次性寫全的而是在CCG迭代過程中不斷追加。因此我在建模時(shí)采用了一個(gè)場(chǎng)景計(jì)數(shù)的循環(huán)每輪迭代把新場(chǎng)景的約束用“追加約束”的方式加進(jìn)YALMIP的約束列表中。4.4 子問題的強(qiáng)對(duì)偶轉(zhuǎn)化與YALMIP實(shí)現(xiàn)子問題的數(shù)學(xué)形式是“給定N先max挑場(chǎng)景再min算調(diào)度成本”。對(duì)內(nèi)層min做對(duì)偶轉(zhuǎn)化后整個(gè)子問題變成一個(gè)max問題可以直接用YALMIP建模求解。核心實(shí)現(xiàn)思路是先把內(nèi)層min問題寫成標(biāo)準(zhǔn)LP形式提取出其對(duì)偶變量把內(nèi)層min的約束轉(zhuǎn)成對(duì)偶可行域約束目標(biāo)函數(shù)改為外層不確定變量驅(qū)動(dòng)的目標(biāo)部分加對(duì)偶目標(biāo)部分注意最后要加上對(duì)偶問題中的常數(shù)項(xiàng)也就是固定容量參數(shù)對(duì)應(yīng)的那一塊。在我的代碼里子問題被封裝成一個(gè)獨(dú)立的函數(shù)輸入是當(dāng)前容量配置輸出是最壞場(chǎng)景下的運(yùn)行成本、對(duì)應(yīng)的最壞場(chǎng)景參數(shù)以及當(dāng)前上界。這里有個(gè)很關(guān)鍵的對(duì)偶實(shí)現(xiàn)細(xì)節(jié)% 內(nèi)層min問題示意 % min c*x d*u % s.t. A*x B*u b % x 0, u是有界不確定變量 % 對(duì)偶后目標(biāo)為 max b*lambda - (B*u)*lambda % 對(duì)偶可行域 A*lambda c % lambda 0 % 原運(yùn)行變量x被消去只剩對(duì)偶變量lambda和外層不確定變量u用YALMIP寫子問題時(shí)不需要手工推導(dǎo)出所有的對(duì)偶表達(dá)式可以借助YALMIP的dualize命令來自動(dòng)處理線性規(guī)劃的對(duì)偶。這一點(diǎn)對(duì)新手尤其友好能大幅減少手工推導(dǎo)出錯(cuò)的可能。但要注意dualize只適用于連續(xù)線性規(guī)劃如果內(nèi)層有0-1變量就得先把整數(shù)變量作為“給定參數(shù)”剝離出去或者改用KKT路線。4.5 CCG迭代主循環(huán)的代碼骨架主循環(huán)邏輯寫出來非常短但就是這段短代碼扛起了整個(gè)迭代UB inf; LB -inf; tol 1e-3; nominal_u get_nominal_scenario(); % 名義場(chǎng)景作為初始?jí)膱?chǎng)景 while abs(UB - LB) / abs(LB) tol % 1. 把當(dāng)前最壞場(chǎng)景加入主問題的場(chǎng)景列表 mp build_mp(k, nominal_u, worst_u_set); optimize(mp, obj_mp, sdpsettings(solver,cplex,verbose,0)); LB value(obj_mp); N_now get_capacity(value([N_pv,N_wt,N_de,N_es])); % 2. 固定容量解子問題找新的最壞場(chǎng)景 [sp_obj, worst_u_new] solve_sp(N_now); UB value(inv_cost) sp_obj; % 3. 收斂判斷 if abs(UB - LB)/abs(LB) tol break; end worst_u_set [worst_u_set; worst_u_new]; % 新場(chǎng)景入列 end初次接觸這段流程的讀者會(huì)發(fā)現(xiàn)主問題每輪都要重新求解一次而新增的約束越來越多求解時(shí)間會(huì)隨迭代輪數(shù)增長。這是正?,F(xiàn)象不代表程序?qū)憠牧恕奈业膶?shí)踐看一般迭代十輪以內(nèi)就能收斂到相對(duì)誤差1%以內(nèi)總耗時(shí)在幾分鐘量級(jí)工程上完全能接受。4.6 結(jié)果可視化的常見處理算法跑完后建議把以下幾張圖和表整理出來各類電源的容量配置柱狀圖直觀對(duì)比投資占比最壞場(chǎng)景下的24小時(shí)功率平衡曲線包括光伏、風(fēng)電、柴油機(jī)、儲(chǔ)能、購電和負(fù)荷曲線確認(rèn)功率平衡約束確實(shí)被滿足“保守度-成本”曲線橫軸是某個(gè)不確定參數(shù)的預(yù)算值縱軸是最優(yōu)年化總成本這是評(píng)審時(shí)最有說服力的單張圖儲(chǔ)能SOC曲線檢查是否在允許范圍內(nèi)波動(dòng)并確認(rèn)沒有出現(xiàn)無意義的邊充邊放行為。計(jì)算完成后還可以順手算一個(gè)關(guān)鍵指標(biāo)——最壞場(chǎng)景下的運(yùn)行成本相對(duì)確定性模型運(yùn)行成本的增量。這個(gè)增量就是“魯棒溢價(jià)”它告訴決策者為了對(duì)抗不確定性系統(tǒng)每年要多付出多少運(yùn)行成本。有時(shí)候這個(gè)溢價(jià)算出來并不高但能讓方案在極端天氣里不趴窩這筆賬就非常劃算。5. 常見問題與排查技巧實(shí)錄5.1 CCG迭代不收斂或收斂速度極慢現(xiàn)象迭代了二三十輪UB和LB之差始終降不下來。排查思路先懷疑不確定性集合的預(yù)算參數(shù)是否設(shè)置得過大導(dǎo)致最壞場(chǎng)景過于極端每次新場(chǎng)景都讓主問題的容量決策大幅跳變?cè)贆z查子問題的壞場(chǎng)景搜索是否正確可以打印每輪找到的最壞場(chǎng)景看是否在幾個(gè)極端點(diǎn)之間反復(fù)橫跳。最有效的加速手段就是“多場(chǎng)景并行初始化”。我一般會(huì)先把每個(gè)不確定參數(shù)單獨(dú)取極端值比如光伏全低、風(fēng)電全高、負(fù)荷全高的排列組合作為初始場(chǎng)景一次性塞進(jìn)主問題的場(chǎng)景集里。這樣前兩輪迭代就能把保守度拉到位后面幾輪只是微調(diào)收斂速度能提升一倍以上。另一個(gè)加速技巧是給主問題加“正則化”約束比如限制相鄰兩輪容量配置的總變動(dòng)幅度不超過某個(gè)閾值。這本質(zhì)上改變了問題的收斂路徑但不會(huì)影響最終收斂點(diǎn)。對(duì)大型實(shí)例這種技巧幾乎必用。5.2 子問題出現(xiàn)infeasible提示這個(gè)是我調(diào)試早期代碼時(shí)遇到最多的問題。原因通常是給定某組容量N后最壞場(chǎng)景下的功率平衡約束根本無法滿足比如切負(fù)荷上限設(shè)置太小或者儲(chǔ)能容量設(shè)得太低導(dǎo)致備用完全不足。處理方式有三種調(diào)整可切負(fù)荷比例上限比如從5%放寬到10%增大儲(chǔ)能的功率上限或容量上下限把外購電力的購電上限從固定值改成可變上限并接入本地配電網(wǎng)的容量約束。還有一個(gè)更穩(wěn)妥的做法是在子問題里加入“松弛變量”目標(biāo)函數(shù)對(duì)松弛變量給予極高懲罰系數(shù)。這樣即使某個(gè)極端場(chǎng)景下不平衡量不為零子問題也能給出一個(gè)帶懲罰費(fèi)用的解CCG主流程不會(huì)中斷。最后再檢查最優(yōu)解中松弛變量的值如果很大說明該容量配置確實(shí)不可行需要在主問題中強(qiáng)制增加容量。5.3 對(duì)偶轉(zhuǎn)化結(jié)果與原始問題不一致這種情況最隱蔽排查難度也最大我遇到過兩次最后發(fā)現(xiàn)都是建模里的符號(hào)問題。例如原問題中的不等式方向?qū)懛崔D(zhuǎn)對(duì)偶時(shí)對(duì)偶變量非負(fù)條件就反了。另一個(gè)高頻錯(cuò)誤是把等式約束誤寫成了不等式約束對(duì)偶后出現(xiàn)自由度丟失解出來的“最壞場(chǎng)景”根本不在原問題允許范圍內(nèi)。我的排查方法是不要只相信對(duì)偶推導(dǎo)結(jié)果先用一個(gè)小規(guī)模實(shí)例固定一組容量值直接枚舉所有可能的不確定場(chǎng)景組合把真實(shí)的最壞運(yùn)行成本算出來同時(shí)用對(duì)偶轉(zhuǎn)化的子問題求一遍二者比對(duì)。數(shù)值一致說明對(duì)偶過程沒問題如果不一致縮小模型規(guī)模逐步二分定位出錯(cuò)約束直到找出符號(hào)或系數(shù)寫錯(cuò)的位置。5.4 求解器頻繁報(bào)數(shù)值問題YALMIP里經(jīng)常遇到的警告是“big-M too large”或“numerical issues”。這類問題的根源往往是儲(chǔ)能SOC約束或充放電互斥約束里用了過大或過小的大M參數(shù)。我的經(jīng)驗(yàn)法則是大M取該約束涉及變量取值范圍的10倍即可。比如SOC范圍是0到1大M取10就足夠不用為了“保險(xiǎn)”取到10000。另外模型里不同約束之間存在數(shù)量級(jí)差異時(shí)比如投資成本是百萬級(jí)SOC是0到1最好對(duì)參數(shù)和變量做歸一化處理比如把所有功率和容量都用標(biāo)幺值表示。歸一化后數(shù)值穩(wěn)定性明顯改善CPLEX的迭代步長也正常很多。5.5 常見問題速查表問題現(xiàn)象主要原因建議處理迭代多輪不收斂預(yù)算參數(shù)過大或場(chǎng)景初始集合太弱減小預(yù)算值用極端組合做初始場(chǎng)景UB低于LB對(duì)偶推導(dǎo)錯(cuò)誤或子問題遺漏約束用小規(guī)模暴力枚舉驗(yàn)證對(duì)偶正確性子問題infeasible容量不足導(dǎo)致最壞場(chǎng)景無法平衡引入松弛變量設(shè)置切負(fù)荷上限主問題規(guī)模過大求解緩慢場(chǎng)景數(shù)量累積過多定期清理冗余場(chǎng)景重新構(gòu)造子集儲(chǔ)能出現(xiàn)邊充邊放缺0-1互斥約束或M參數(shù)不當(dāng)加入互斥二進(jìn)制變量規(guī)范化大M結(jié)果為全裝儲(chǔ)能或全裝柴油機(jī)目標(biāo)函數(shù)量綱不一致或缺少約束檢查等年值轉(zhuǎn)換確認(rèn)運(yùn)行約束完整6. 實(shí)操體會(huì)與補(bǔ)充建議寫到這分享幾個(gè)我從多個(gè)項(xiàng)目里沉淀下來的體會(huì)希望能幫大家少走彎路。第一點(diǎn)不要一上來就追求最嚴(yán)苛的保守度。容量配置的最終目的是讓微網(wǎng)在真實(shí)場(chǎng)景下運(yùn)行經(jīng)濟(jì)、可靠而不是在數(shù)學(xué)意義上“永遠(yuǎn)不敗”。把預(yù)算參數(shù)從松到緊多調(diào)幾檔畫一張成本和魯棒性的權(quán)衡曲線再定方案這是我做項(xiàng)目時(shí)最常用也讓各方都認(rèn)可的操作。評(píng)審專家喜歡這張曲線比冗長的公式推導(dǎo)更有說服力。第二點(diǎn)兩階段魯棒優(yōu)化的計(jì)算結(jié)果最好再配一輪蒙特卡洛仿真來校核。具體做法是把優(yōu)化得到的容量配置固定住隨機(jī)生成幾千組可能的風(fēng)光負(fù)荷序列模擬運(yùn)行并統(tǒng)計(jì)切負(fù)荷率和平均運(yùn)行成本。如果蒙特卡洛測(cè)試中極少出現(xiàn)切負(fù)荷說明預(yù)算參數(shù)設(shè)保守了可以適當(dāng)放松如果切負(fù)荷頻繁說明魯棒程度不夠需要調(diào)大預(yù)算參數(shù)。這種“優(yōu)化仿真”雙驗(yàn)證模式是我目前最推薦的做法能有效防止魯棒模型在“工程直覺”和“數(shù)學(xué)最優(yōu)”之間跑偏。第三點(diǎn)代碼一定要模塊化。主問題構(gòu)建、子問題求解、參數(shù)定義、結(jié)果后處理分開寫成多個(gè)函數(shù)。原因不只是維護(hù)方便更重要是CCG迭代時(shí)要反復(fù)調(diào)用子問題求解函數(shù)如果每個(gè)子問題都是單獨(dú)一個(gè)腳本文件調(diào)試時(shí)改一處變量名整個(gè)項(xiàng)目就全亂了。模塊化之后換一組新參數(shù)測(cè)新案例只需要改參數(shù)腳本求解核心根本不動(dòng)。第四點(diǎn)規(guī)模放大時(shí)優(yōu)先考慮場(chǎng)景削減和約束篩選。如果微網(wǎng)節(jié)點(diǎn)多、電源類型多、時(shí)間分辨率細(xì)CCG的主問題規(guī)模會(huì)膨脹得很快。此時(shí)可以先按典型日聚類初步壓縮數(shù)據(jù)從根源減少場(chǎng)景數(shù)量還能在迭代過程中定期檢查已有場(chǎng)景約束中有沒有冗余約束——如果連續(xù)多輪迭代某個(gè)約束的松弛變量始終為零就可以把它從主問題中臨時(shí)移除以節(jié)省內(nèi)存和求解時(shí)間。最后想說的是兩階段魯棒優(yōu)化在微網(wǎng)容量配置里的價(jià)值不是它比傳統(tǒng)方法算得快、算得準(zhǔn)而是它逼著你把“最壞情況”拿出來擺在桌面上公開討論。做電力系統(tǒng)規(guī)劃最怕的就是方案只在正常工況下漂亮一到特殊天氣就捉襟見肘。魯棒優(yōu)化至少讓所有參與決策的人都知道這個(gè)方案最差會(huì)差到什么程度。如果你的微網(wǎng)項(xiàng)目將來可能面對(duì)比較嚴(yán)苛的并網(wǎng)考核或者極端天氣考驗(yàn)花點(diǎn)時(shí)間把兩階段魯棒這套工具用起來大概率不會(huì)讓你后悔。