庫實戰(zhàn)指南:從入門到避坑的系統(tǒng)動力學建模要點)
簡介面向系統(tǒng)動力學建模者與 Vensim 軟件初學者這份 PDF 是一份關(guān)于 Vensim 內(nèi)置函數(shù)庫的說明文檔。內(nèi)容聚焦 Vensim_PLE 版本中全部 25 個函數(shù)按數(shù)學函數(shù)、邏輯函數(shù)、隨機函數(shù)、測試函數(shù)和延遲函數(shù)進行分類系統(tǒng)梳理了每個函數(shù)的基本形式、功能含義及在方程編輯器中的調(diào)用方式。其中涵蓋 SIN、EXP、LN、SQRT、ABS、INTEGER、MODULO 等基礎(chǔ)數(shù)學函數(shù)MAX、MIN、IF THEN ELSE 等邏輯判斷函數(shù)RANDOM UNIFORM、RANDOM NORMAL 等隨機函數(shù)以及 STEP、RAMP、PULSE、PULSE TRAIN 等測試函數(shù)每種函數(shù)都配有使用步驟部分還給出典型應用示例可幫助讀者快速理解變量關(guān)系并完成模型構(gòu)建。資源為單文件 PDF大小僅 123KB內(nèi)容精煉適合隨用隨查。目前已有 414 人瀏覽學習可作為系統(tǒng)動力學課程學習、Vensim 入門練習及模型調(diào)試時的函數(shù)速查手冊。 接手過不少系統(tǒng)動力學模型也幫人調(diào)過無數(shù)報錯我發(fā)現(xiàn)一個規(guī)律模型跑出離譜結(jié)果的案例里至少一半問題出在函數(shù)上而不是結(jié)構(gòu)上。同樣的存量流量圖換一個函數(shù)寫法仿真曲線可能完全是兩回事。今天就把我這些年用Vensim函數(shù)庫的經(jīng)驗一次性梳理清楚——Vensim函數(shù)庫是系統(tǒng)動力學建模中最基礎(chǔ)也最容易被低估的一環(huán)它直接決定了你的模型能把現(xiàn)實世界模擬到什么程度。這篇文章適合三類人剛接觸Vensim、對著函數(shù)列表一臉茫然的初學者已經(jīng)能搭出模型結(jié)構(gòu)、但總覺得仿真結(jié)果差點意思的進階用戶以及被困在某個報錯或離譜曲線里、想找排查思路的實戰(zhàn)派。1. 函數(shù)庫是什么建模時它卡在你流程的哪一環(huán)1.1 從一次模型崩了的經(jīng)歷說起早幾年我?guī)腿藢徱粋€庫存模型存量、流量、輔助變量畫得清清楚楚方程也寫得規(guī)規(guī)矩矩。但一跑仿真庫存直接變成負數(shù)整個系統(tǒng)像瘋了一樣震蕩。排查了半天最后問題出在一行不起眼的IF THEN ELSE上——條件分支里的某個中間變量在特殊條件下算出除零把整個鏈條帶崩了。這件事給我的教訓很深系統(tǒng)動力學的模型骨架很重要但函數(shù)就是骨架關(guān)節(jié)里的軟骨軟骨壞了模型一步都走不動。Vensim函數(shù)庫里幾十個函數(shù)每一個都對應一類常見數(shù)學邏輯或時間行為的封裝。你用不用得對直接決定模型的穩(wěn)定性與可信度。1.2 函數(shù)庫的分類全景圖Vensim自帶的幫助文檔會把函數(shù)分成十幾類但按照我實際建模的習慣真正常用的是這五個大類類別代表函數(shù)核心用途數(shù)學與邏輯ABS、SQRT、LN、EXP、INTEGER、MODULO、IF THEN ELSE、MAX、MIN基礎(chǔ)運算與條件判斷時間控制TIME、STEP、PULSE、RAMP描述某時刻發(fā)生的輸入變化平滑與延遲SMOOTH、SMOOTH3、DELAY1、DELAY3刻畫感知滯后與物理輸送滯后隨機函數(shù)RANDOM UNIFORM、RANDOM NORMAL引入環(huán)境不確定性與擾動表函數(shù)WITH LOOKUP描述非線性關(guān)系對接實測數(shù)據(jù)我見過不少建模者只靠前兩類函數(shù)打天下線段性關(guān)系全用常量結(jié)果模型跑出來像玩具。實際情況是平滑、延遲和表函數(shù)才是系統(tǒng)動力學區(qū)別于普通Excel模型的靈魂。后面我會逐個講清楚這些函數(shù)怎么用、什么時候用。2. 核心函數(shù)實操我把最常用的這批函數(shù)逐個捋了一遍2.1 數(shù)學與邏輯類先解決算得對不對數(shù)學函數(shù)沒什么玄機用法和常見編程語言幾乎一樣。重點說說IF THEN ELSE它可能是整個函數(shù)庫里使用頻率最高、也最容易寫錯的函數(shù)。實際庫存調(diào)整量 IF THEN ELSE(庫存 安全庫存, 緊急補貨量, 正常補貨量)基本邏輯不復雜但有一個隱藏特性很多人不知道Vensim的IF THEN ELSE會對兩個分支都進行求值。這在絕大多數(shù)情況下沒有影響但如果那個沒被走到的分支里有除零、開根號為負數(shù)這類非法運算模型直接給你報錯或者算出NAN。另一個高頻函數(shù)是MODULO它不只是一個數(shù)學玩具。我在做周期性生產(chǎn)計劃模型時經(jīng)常用MODULO(時間, 周期)來判斷當前時刻是否處于某個周期階段比一個個寫STEP要省事得多。2.2 時間控制類模型里什么時候發(fā)生什么STEP、PULSE和RAMP是我說的時間控制三兄弟。它們都是以時間為自變量的特殊輸入函數(shù)專門用來描述外部沖擊。廣告投入 基準投入 STEP(50, 第12周) PULSE(20, 第30周, 8)STEP(高度, 起始時間)表示從某時刻開始值永久增加一個固定量PULSE(起始時間, 持續(xù)時間)表示從某時刻開始持續(xù)多個時間步長的脈沖RAMP(斜率, 起始時間)表示從某時刻開始線性增長。這三個函數(shù)放在一起非常靈活能把現(xiàn)實中突然的政策變化一次性的促銷活動漸進的產(chǎn)能擴張等沖擊都描述出來。關(guān)鍵是時間參數(shù)要和模型的時間單位保持一致——模型時間單位是月就別寫第12周這種不匹配后期查起來非常痛苦。2.3 平滑與延遲類系統(tǒng)動力學的靈魂函數(shù)如果說只能選一類函數(shù)深入掌握我會毫不猶豫選平滑和延遲。這類函數(shù)的建模思想非常樸素現(xiàn)實世界中的感知和信息傳遞永遠存在滯后不會瞬間完成。SMOOTH(input, 延遲時長)描述的是感知平滑的滯后。舉個例子實際需求每小時都在變但銷售團隊感知到的近期需求水平并不會立刻跳變而是逐漸趨近——這就是一階指數(shù)平滑。Vensim里還有SMOOTH3對應三階平滑響應更慢、過渡更平滑。DELAY1和DELAY3描述的是實物延遲。進入一個管道的東西不是立刻全部從另一端出來而是經(jīng)過一段時間陸續(xù)出來。DELAY1相當于一個混合良好的緩沖池DELAY3相當于三個串聯(lián)的緩沖池出流更接近真實的先入先出形態(tài)。我在供應鏈模型里最常用的搭配是用SMOOTH3構(gòu)造預期需求用DELAY3構(gòu)造在途庫存。這樣跑出來的庫存波動曲線和現(xiàn)實企業(yè)里看到的形狀幾乎一模一樣。2.4 表函數(shù)和隨機函數(shù)給模型接入現(xiàn)實數(shù)據(jù)WITH LOOKUP是整個函數(shù)庫里最有建模感的函數(shù)。它允許你直接把兩個變量之間的非線性關(guān)系定義成一張折線表Vensim在仿真時自動做線性插值。需求量 WITH LOOKUP(價格, ([(0,0)-(100,1000)],(0,800),(20,600),(50,350),(100,100)))這就是給模型喂現(xiàn)實數(shù)據(jù)的最直接方式。價格和需求之間的關(guān)系很少是線性的實測數(shù)據(jù)顯示什么形狀就把折線打成什么樣。注意方括號里是插值范圍后面才是真正的數(shù)據(jù)點——很多人第一次寫這里會漏掉范圍定義直接報語法錯誤。隨機函數(shù)用來給模型注入不確定性。RANDOM UNIFORM(下限, 上限, 種子)生成區(qū)間內(nèi)均勻分布隨機數(shù)RANDOM NORMAL(均值, 標準差, 種子)生成正態(tài)分布隨機數(shù)。做蒙特卡洛模擬或者敏感性分析時這些函數(shù)是標配。種子參數(shù)有個小竅門同一組參數(shù)下種子固定則每次仿真結(jié)果一致種子設(shè)為0則每次運行結(jié)果不同。想復現(xiàn)實驗結(jié)果就固定種子想模擬真實世界的不可預測性就設(shè)0。3. 實戰(zhàn)選函數(shù)同一個場景我為什么這么選3.1 庫存補貨模型SMOOTH與DELAY怎么搭配假設(shè)要建一個零售商的庫存模型。很多新手會直接把顧客需求當作補貨依據(jù)——這在實際業(yè)務(wù)中是不可能的因為從需求發(fā)生到數(shù)據(jù)匯總再到?jīng)Q策中間存在感知延遲從下單到貨物上架又存在物流延遲。我當時的處理方式是顧客需求經(jīng)過SMOOTH3形成感知需求感知需求驅(qū)動補貨決策補貨量進入DELAY3形成在途庫存最后抵達可用庫存。這個模型跑出來后你能清楚看到需求突變時庫存的過度反應和回調(diào)——這就是供應鏈里著名的牛鞭效應的內(nèi)生來源。這里的選型邏輯是感知類滯后用SMOOTH系列物質(zhì)類滯后用DELAY系列。兩者不能互換混用了整個系統(tǒng)的時間特性就亂了。3.2 人口增長模型隨機擾動與一次性沖擊的表達在一個區(qū)域人口模型中出生率會受到經(jīng)濟環(huán)境、偶發(fā)事件的影響而波動。給出生率加一個RANDOM NORMAL擾動能比固定常量更真實地反映這種環(huán)境不確定性。年出生人口 育齡人口 * 基準出生率 * RANDOM NORMAL(0.8, 1.2, 0.05, 42)如果想進一步模擬某一年發(fā)生了一次外部沖擊導致出生率短期下降就再疊加一個負的PULSE。這種寫法把一個靜態(tài)模型變成了能夠回答如果發(fā)生X結(jié)果會怎樣的動態(tài)決策工具——這正是系統(tǒng)動力學建模的核心價值。3.3 市場擴散模型非線性的表函數(shù)怎么打點Bass擴散模型里有一個關(guān)鍵輔助變量潛在采納者接觸到已采納者的概率。這個概率通常用常數(shù)表示但真實市場中社交強度會隨著傳播階段變化。這時候我會用WITH LOOKUP定義一張基于時間的折線前期平穩(wěn)、中期上升、后期回落。表函數(shù)打點有個實操技巧先用5到7個關(guān)鍵點把大體形狀勾出來跑一次模型看曲線再根據(jù)結(jié)果在拐點附近加密數(shù)據(jù)點。別一上來就猛打二十個點調(diào)起來會非常費勁。數(shù)據(jù)點的疏密度本質(zhì)上是你在用多少信息量描述這段非線性關(guān)系之間做權(quán)衡。4. 實測排坑記錄函數(shù)用得越多這些坑越要避開4.1 IF THEN ELSE的分支陷阱兩個分支都會執(zhí)行前面提到了Vensim的IF THEN ELSE會對兩個分支都做求值。這個坑我踩得非常慘模型跑出來的曲線在某段時間突然跳成NAN找了兩天最后發(fā)現(xiàn)問題出在一個輔助變量在條件為假的分支里做了除零運算。排查建議如果在仿真中途某一步突然出現(xiàn)NAN或者無窮值優(yōu)先檢查所有IF THEN ELSE的分支把可能產(chǎn)生非法運算的詞句單獨抽出來測試。另一種更穩(wěn)妥的寫法是把有風險的計算拆成一個單獨變量再用ZIDZ零除保護函數(shù)包裝——ZIDZ(a, b)在b為0時返回0能直接從根上斷掉除零問題。4.2 SMOOTH系列的秘密初值行為不是你想的那樣SMOOTH函數(shù)的第三個初值參數(shù)是可選參數(shù)。如果省略Vensim會用仿真開始時刻的輸入值作為平滑初值。這意味著如果你的輸入在第0天就是一個異常值模型前期的平滑曲線會被這個異常值污染可能要到幾個延遲時長之后才恢復正常。我在處理真實數(shù)據(jù)時遇到過一次某個月的實際需求因為統(tǒng)計口徑調(diào)整突然翻了三倍結(jié)果用SMOOTH做預期需求時前幾個月模型都在跟這個異常值做斗爭。解決方法是顯式傳入初值參數(shù)預期需求 SMOOTH(實際需求, 8, 歷史平均需求)經(jīng)驗是任何含延遲或平滑的函數(shù)只要數(shù)據(jù)起點有異常務(wù)必顯式指定初值。這個初值最好用歷史數(shù)據(jù)的均值或中位數(shù)而不是默認值。4.3 DELAY3的內(nèi)部串聯(lián)結(jié)構(gòu)與穩(wěn)態(tài)收斂DELAY3本質(zhì)上是在內(nèi)部串聯(lián)了三個一階延遲。它比DELAY1的沖擊響應更平滑但也帶來了一個坑它的內(nèi)部狀態(tài)需要一定時間才能達到穩(wěn)態(tài)。如果從非穩(wěn)態(tài)開始仿真DELAY3輸出的初始段會出現(xiàn)明顯波動。尤其在把模型從舊參數(shù)切換到新參數(shù)時延遲鏈里遺留下來的舊庫存會讓新曲線的初期失真。做法是在模型里給所有DELAY3和SMOOTH3接上合適的初值或者在切換參數(shù)的場景下先讓模型跑到穩(wěn)態(tài)再開始記錄結(jié)果。4.4 表函數(shù)超出定義域默認外推可能帶歪整個模型WITH LOOKUP默認對定義域外的輸入做線性外推。這聽起來合理但在實際場景里非常危險。價格降到定義域下限之下時外推出來的需求可能是一個荒謬的巨量當輸入落在定義域之外時模型會順著最后兩個點的斜率無限延伸。我見過一個廣告預算模型因為預算輸入跑出了表函數(shù)定義域模擬出的市場反應直接變成了天文數(shù)字。對策有兩個一是把定義域范圍設(shè)得足夠?qū)捔糇阌嗔慷窃诒砗瘮?shù)外面套一層IF THEN ELSE或MAX/MIN限幅強行把輸入拉回定義域內(nèi)。我更推薦后者——模型里的不可能輸入值本身就說明前面的邏輯可能存在邊界問題及早暴露是好事。4.5 隨機種子與可復現(xiàn)性仿真結(jié)果能不能穩(wěn)定重現(xiàn)隨機函數(shù)的種子參數(shù)是我在高強度使用后發(fā)現(xiàn)的重要問題。做實驗要對比不同方案時如果每次仿真隨機數(shù)都重新生成那么結(jié)果差異可能來自隨機擾動而不是方案本身的差異。建議做法跑基準實驗時固定種子確保結(jié)果可復現(xiàn)做敏感性分析或蒙特卡洛模擬時再放開種子通過大批次運行來統(tǒng)計結(jié)果分布。這兩種模式下模型本身一個字都不用改只需要換掉種子的寫法。另外一個容易忽視的點時間步長TIME STEP也會影響隨機函數(shù)和延遲函數(shù)的數(shù)值表現(xiàn)。時間步長取0.5和0.25同一個延遲參數(shù)在新結(jié)果上可能差出好幾個百分點。正式實驗前先做一次時間步長收斂性測試能避免很多爭論。5. 從會用到用好函數(shù)庫背后的建模思維5.1 怎么讀Vensim自帶的函數(shù)手冊Vensim的Help菜單里有完整的函數(shù)手冊但很多人沒看進去因為它是按照字母順序排的。我的建議是反過來看先打開任意一個自帶的示例模型看里面用了哪些函數(shù)然后逐個跳轉(zhuǎn)到手冊里查意思。示例模型里每個函數(shù)都有上下文比干看定義好理解十倍。另一個技巧是用模型中的Take a look at this function按鈕——Vensim編輯器里函數(shù)輸入框旁邊有個小圖標點一下直接跳到對應手冊條目邊寫邊查最有效率。5.2 一個模型從初稿到定稿函數(shù)選型復盤我做一個產(chǎn)能規(guī)劃模型時初稿只用了STEP和IF THEN ELSE結(jié)果仿真曲線非常生硬產(chǎn)能擴建像開關(guān)一樣瞬間完成庫存變化全是直角彎。審模型的老前輩看完只說了一句你這生產(chǎn)線是瞬間轉(zhuǎn)移的傳送門啊。改版時把所有STEP換成了RAMP產(chǎn)能爬坡變成漸進式增長把瞬時到貨的庫存流入改成DELAY3對應真實的設(shè)備調(diào)試和產(chǎn)能爬坡周期預期需求從直接取實際需求改成SMOOTH3體現(xiàn)出市場感知的滯后。整個模型的曲線形狀發(fā)生了質(zhì)變從機械感變成了真實感決策參考價值也完全不同。這次復盤讓我認識到選擇哪個函數(shù)本質(zhì)上是你在對現(xiàn)實世界的哪種行為機理做假設(shè)。RAMP表示漸進過程STEP表示突變DELAY表示存在實物滯后SMOOTH表示存在感知滯后——這些選擇背后都是對真實系統(tǒng)的判斷。根據(jù)我個人經(jīng)驗真正高效的做法是先搭一個能跑通的粗模型只求結(jié)構(gòu)完整然后逐段審視每個輔助變量問自己這個變量和它的輸入之間是瞬時關(guān)系、平滑關(guān)系還是延遲關(guān)系答案直接決定你該用哪個函數(shù)。Vensim的函數(shù)庫看起來只是幾十個命令背后卻是一整套關(guān)于時間、滯后、非線性和不確定性的建模哲學。最后再分享一個小技巧寫完整個模型后把每個方程點開檢查一遍凡是看到只有常量和加減乘除的輔助變量就多問一句——這個變量真的瞬時就能算出來嗎如果在現(xiàn)實里它有滯后、有波動、有非線性函數(shù)庫里多半已經(jīng)有對應的工具等著你了。本文還有配套的精品資源點擊獲取