本文分享了由Vitor Lemos編寫的關于AnyLogic的使用實踐技巧,希望能為正在學習或使用AnyLogic的用戶提供幫助。post/the-simulation-model-life-cycle-part-5-experimentation
作者:Jaco-Ben Vosloo
更新:Apr 6, 2022
閱讀時間:12 min
本系列文旨在對仿真項目的生命周期進行說明,并給出一些最佳實踐和實用建議。
這篇文章是關于仿真模型生命周期的 7 部分系列文章的第 5 部分。
注意:在后面的步驟中可能會“返回”前面的步驟中執行一些活動,但并不需要重做整個步驟。 上面列出的步驟是典型項目遵循的一般步驟。在所有步驟中,您都可以后退并重新訪問之前的步驟,但在完成至少 80%-90% 的步驟之前,您不太可能跳過一個步驟或向前移動。
實驗可以說是仿真模型生命周期中比較有難度的一個步驟。我有時覺得這更像是一門藝術,而不是一門科學。想要從一開始就只考慮正確實驗是非常難的,更不用說以正確的方式執行它們。本文并不是一篇創建良好實驗的全面指南,更像是正確掌握基本知識的快速入門指南。
我們都知道,我們不能為了給出想要或期望的答案而設計實驗,讓我們看一些實踐來幫助我們創建有意義的實驗。 下面,我們將深入研究之前的示例,其中包含一些在 AnyLogic 中設置實驗的最佳實踐。
在仿真階段,您需要將重點放在模型的原始目標上,如仿真模型生命周期的part 1(定義問題)中所定義的。否則,你可能會因為一些有趣的想法和假設轉移重心,雖然這些想法和假設具有增值作用,但不是模型或項目的主要目標。
因此,需要創建不同的場景來測試目標的不同部分,以及一次性測試整個目標的組合場景。聽起來比實際場景要容易得多!慢慢來,把你的場景組織好。如果您遵循了part 2和part 3中的最佳實踐,那么您的場景應該只是一個簡單的Excel或其他一些基本數據文件,您可以導入并在模型中運行,而無需任何麻煩。
根據我們的零售商示例,我們的場景非常簡單:
在我們的兩個場景文件中,唯一的區別是隊列的數量這一個參數。
或許難以置信,但現實生活中的例子通常也是這樣的,場景之間的唯一區別通常就是單個參數的變化。
壓力測試所花費的時間在很大程度上取決于可用時間、模型輸出的置信度以及決策的重要性。
基本上,你可以這么問自己:“出錯的代價是什么,而要保證自己是正確的代價是什么?”
在這個階段中,你會創建一些場景,有時是離譜的,但這些場景是為了推進模型的極限,以確定解決方案空間。當然,也要小心不要測試一些離譜的輸入,例如模型中沒有隊列。這種類型的測試是為了查看模型是否中斷,最好在執行單元測試的part 3中完成。這里的重點應該是測試在什么條件下第 1 點的假設和發現是有效的。
例如:
這里的目的是測試您得出的結論是否仍然有效,以及在哪些條件下它們無效或只是有所不同。這也可以幫助您識別邏輯中可能存在的錯誤。如果結果無法解釋,則可能是存在錯誤,或者您只需要添加更好的輸出數據,以便提供足夠的上下文和洞察力來解釋結果。
這是從實驗中獲得有效仿真結果的絕對必要條件。您必須使用不同的隨機流運行多個復制實驗,以獲得輸出的分布。通常通過創建蒙特卡洛實驗來實現,在該實驗中,您只需收集特定的模型輸出,同時在多個運行中改變種子。
如果您只對每個場景運行一次迭代,即使兩個場景都具有相同的隨機種子,您也不知道這些結果在可能性的宇宙中位于何處。
注:向您推薦一篇文章“在AnyLogic 中如何設置隨機性?”幫助您理解和使用AnyLogic的隨機功能。
示例:假設您創建了一個仿真模型,可以模擬紐約市一年中任何一天的平均溫度,并要求您給出冬季和夏季溫度之間的預期差值。如果你只仿真夏季的某一天,并將其與冬季的某一天進行比較,由于純粹的隨機性,你可能最終模擬出最冷的夏季和最溫暖的冬季,這將給你一個小于10。F的增量。
那我們可以假設冬季和夏季溫度之間的差異幾乎可以忽略不計嗎?
請注意,如果沒有數千天數據,你至少需要模擬100天才能得到一個具有代表性的平均值。。。。然后您會得到夏季和冬季的平均溫差約為40。F。
這就引出了我們的第二點:平均值。你可能聽說過一句格言,如果你的頭在冰箱里,腳在烤箱里,平均來說,你處于一個非常舒適的溫度。
你們不僅需要多次運行才能得到一個有代表性的平均值,而且還需要以此來獲得可能結果的分布。你需要知道最小值、最大值、標準差以及任何其他適用于特定項目的值。通常,在直方圖中顯示測量結果可以很好地直觀地表示各種運行中的輸出。
在我們的零售商示例中:如果客戶的平均等待時間為10分鐘,最長為2小時,我們還需要問問自己,模型或輸入數據中是否存在缺陷,或者這只是過程的本質嗎?
注意:由于我們之前是以客戶的歷史服務時間進行仿真,因此在實驗階段進行多次復制運行是沒有意義的,因為我們將一遍又一遍地模擬相同的服務時間......因此,每次運行都會得到相同的結果。我們需要向場景文件中添加新參數,并在模型中使用它們來模擬服務時間的分布。
在前一點的基礎上,你的實驗輸出結果需要包含足夠的信息,以便你不僅可以給出結果,而且能夠證明和解釋結果。為此,您需要以下幾點:
詳細結果將與單次運行實驗中輸出的結果相同,并且摘要將只是每個場景的多次運行的摘要。通常,只有當您在模型中看到較大的標準差或顯著的最小值或最大值,并且懷疑其中一個復制可能遇到錯誤時,您才會查看詳細數據。由于輸出文件中提供了每個復制的單獨結果,因此我們可以在一些外部工具(例如Excel)中輕松計算匯總統計數據。但是,當我們可以讓模型為我們做這件事時,為什么還要為每個場景比較計算這個呢。
現在,我們已經了解了良好實驗的基礎,讓我們繼續執行part 4中的示例,并將這些操作實現到模型中。
注意:在本例中,我們將繼續使用在part 3中設置的自定義實驗對象。AnyLogic確實提供了一些用于靈敏度、蒙特卡洛、參數變化和其他實驗的預定義實驗選項,但對于一些更為復雜和長期的仿真模型,我并不喜歡使用它們,具體有以下幾個原因:
該示例分為三個部分,第一部分側重于我們需要對模型和場景文件進行的一些升級,以便我們可以為每個場景設置和保存一些細節。 第二部分是關于保存輸出并一個接一個地運行多個場景。 最后一部分的重點是我們現在如何使用第 1 部分和第 2 部分中的更新來一個接一個地運行多個場景,保存輸出并從模型中下載它。
這些新列將定義一些之前未通過場景對象設置的模型行為。
我發現最好在場景文件中添加一個命名為“ModelSetup”的新表,在這里我有一個包含多個列的單行,用于存儲模型運行的設置。同時,我還添加了一列場景名稱,然后在運行多個場景時可以將其輸出到結果文件。
下面是對每個新字段的快速解釋:
在 Excel 文件內的新工作表中創建這些字段后。 您可以將新工作表作為新數據庫表導入模型。 現在,此數據可在場景創建中使用。
現在,我們需要將場景文件中的相同字段添加到場景對象中,以便模型可以使用它們。
我們還需要在我們創建的“getScenarioFromDB”場景加載器函數中填充這些字段`
請注意以下事項:
注:Project Lombok 是一個 java 庫,可自動插入您的編輯器和構建工具。
既然參數在場景對象中可用,我們可以在模型邏輯中使用它們來設置模型。
第一步(也就是a)在場景文件中添加新列)是使用場景對象內的設置,該設置定義是否使用歷史數據或三角形分布。
下一步是使用場景變量來定義我們是使用單個隊列還是多個隊列。
現在模型正在使用新的設置變量,我們可以將更多仿真結果保存到輸出文件中。
a) 詳細結果
在part 4中,我們只將單個仿真輸出保存到文本文件中。文本文件是main中的一個對象,因此如果我們有多個仿真運行,每個復制場景都將覆蓋前一復制的數據。
在part 4中將客戶等待時間保存到文本文件
為了讓所有模型的顧客等待時間寫入一個文本文件,我們需要將文本文件對象存儲在仿真對象上,并使用參數傳遞給模型。現在,所有迭代都將寫入同一個文本文件,所有結果都將在同一個文件中。幸運的是,文本文件也是線程安全的,所以如果我們為實驗進行多線程處理,結果仍然會正確保存。 (更多關于多線程的信息將在以后的文章中介紹;-))
但是,我們如何區分某次迭代和下一次迭代呢?或者某個場景和下一個場景?
在文本文件中,我們添加了兩個新列,場景名稱和種子,并使用制表符分隔所有列(因此代碼中有“/t”)。僅供參考:選項卡可以在Excel中輕松打開單獨的文本文件,每個選項卡表示一個新列。
在part 5中,使用參數將模型輸出保存到文本文件
但是種子參數從哪里來?
在仿真中識別種子通常是一個大問題,不時會在Stack Overflow上發布。。。
舉個例子:
如何輸出由 AnyLogics 隨機種子(獨特的仿真運行)RNG 生成的種子?
在這個例子中,我將我們的自定義實驗對象從part 4升級到現在,還包括種子和文本文件作為“startRound”函數的輸入;
種子現在可以提供給定制實驗,也就是說我們在創建定制實驗時可以完全控制它。
您還將注意到另一個名為Results的參數,該參數在代碼中進一步使用。
b) 總結結果
通常我們對每次復制實驗的單個結果關注不多,而是對多次運行的匯總統計信息更加關注。為了實現這一點,我們創建了一個名為Results的新Java類。每次復制都會將結果保存在此對象中,并在其中存儲統計信息,我們可以將摘要統計信息寫入下一個文本文件。
下面的結果文件幾乎概括了所有模型中我會使用的最基本的形式。
使用這種方法,會將所有統計信息都存儲在這一個對象中,所以您無需將數百個對象從面板拖放到main或仿真頁面。
現在,我們已經對模型和結果類進行了更新,我們可以在仿真首頁上設置一個新功能,讓我們可以選擇多個Excel文件,將它們一次導入到DB中,并讓它們所代表的場景在設置完成后執行并保存所有結果。
1.我們創建了一個按鈕,允許用戶使用以下代碼選擇多個excel文件:
FileDialog fileDialog = new FileDialog(new Frame(), "Select all input files", FileDialog.LOAD );
fileDialog.setMultipleMode(true);
fileDialog.setFile( "*.xlsx" );
fileDialog.setVisible( true );
File[] files = fileDialog.getFiles();
for (File file:files) {
filesToLoad.add(file.getAbsolutePath());
}
2.然后,我們允許用戶設置復制的數量
3.然后創建按順序運行所有場景的按鈕,為不同場景運行之間的每個對應迭代設置相同的種子。此函數還將傳遞txt文件以獲取每個模型運行的詳細結果。它還為每個場景傳遞一個新的結果對象,并將其保存到具有相應場景名稱的映射中。
一旦執行了所有場景,它將從結果映射中獲取結果,并將摘要統計信息寫入一個名為“summaryResults”的新txt文件
下面是場景比較功能的簡短視頻
如果我們在Excel中打開摘要文件,我們會得到一個摘要表,如下所示。
在本文中,我們研究了仿真模型生命周期的實驗階段,以及如何在模型內正確設置實驗。我們研究了一些利用自定義實驗的高級方法,允許我們完全控制場景比較和敏感性分析實驗。與前一篇文章相比,這無疑增加了復雜性,但是這是值得的,尤其是當您在構建復雜模型時,需要完全控制實驗執行。
在下一篇文章中,我們將稍作休息,看看一些分析結果的最佳實踐。