• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 可愛的 Python:SimPy 簡化了復雜模型

    發表于:2007-07-04來源:作者:點擊數: 標簽:
    人們常常難以理解或預知實際系統的隨機行為。有時可能精確論證系統的統計特性(諸如一般的、最差和最好的 性能 特性)。但在其它時候,只有實際運行(或模擬)系統時,具體設計的 缺陷 才會顯現出來。本文中,David 討論了 SimPy,它是一種 Python 包,允許
      人們常常難以理解或預知實際系統的隨機行為。有時可能精確論證系統的統計特性(諸如一般的、最差和最好的性能特性)。但在其它時候,只有實際運行(或模擬)系統時,具體設計的缺陷才會顯現出來。本文中,David 討論了 SimPy,它是一種 Python 包,允許您非常方便地創建離散事件系統的模型。
      
      在我遇到 SimPy 包的其中一位創始人 Klaus Miller 時,從他那里知道了這個包。Miller 博士閱讀過幾篇提出使用 Python 2.2+ 生成器實現半協同例程和“輕便”線程的技術的可愛的 Python 專欄文章。特別是(使我很高興的是),他發現在用 Python 實現 Simula-67 樣式模擬時,這些技術很有用。
      
      結果表明 Tony Vignaux 和 Chang Chui 以前曾創建了另一個 Python 庫,它在概念上更接近于 Simscript,而且該庫使用了標準線程技術,而不是我的半協同例程技術。該小組在一起研究時,認為基于生成器的樣式更有效得多,并且最近在 SourceForge 上發起了使用 GPL 的項目,稱為 SimPy(請參閱參考資料,獲得 SimPy 主頁的鏈接),目前處于 beta 測試版狀態。Vignaux 教授希望他在惠靈頓維多利亞大學(University of Victoria)的將來大學教學中使用統一的 SimPy 包;我相信該庫也非常適合應用到各類實用問題中。
      
      我承認在近期的通信交流和調查研究之前,我對編程領域的模擬方面沒有任何基礎知識。我猜想本專欄文章的大部分讀者也和我一樣,對這方面的知識知之甚少。盡管有人會認為這種樣式編程的方式有些新奇,但在理解資源有限的實際系統的行為時,模擬是很有用的。不管您感興趣的是有限帶寬網絡、汽車交通行為、市場和商業性優化、生物/進化的交互作用還是其它“隨機”系統,SimPy 對這樣的建模都提供了簡單的 Python 工具。
      
      隨機的定義
      與“連接”相類似,它是那些最適合形容其作業的詞匯之一 — 再也找不到更適合的了:
      隨機(stochastic),源自希臘語 stokhastikos(形容詞)
      1)推測的、與推測相關的或者具有推測特點的;好推測的。
      2)在統計學上:涉及或包含一個隨機變量或多個隨機變量,或涉及偶然性或概率。
      
      在本專欄文章中,我將一直使用食品雜貨店內具有多條通道的付款區域這個相當簡單的示例。通過使用所演示的模擬,我們可以根據對掃描器技術、購物者習慣、人員配備需求等進行的各種更改所產生的經濟上和等待時間上的含義提出問題。這個建模的優點是在您對所做的更改產生的含義有清晰的想法時,它讓您能提前制定策略。很明顯,大多數讀者不會專門經營一家食品雜貨店,但這些技術可以廣泛地應用于各類系統中。
      
      模擬的概念
      SimPy 庫只提供了三個抽象/父類,并且它們對應于模擬的三個基本概念。有許多其它常規函數和常量用于控制模擬的運行,但重要的概念都與這些類結合在一起。
      
      模擬中的核心概念是進程。一個進程只是一個對象,它完成某些任務,隨后在它準備完成下一個任務之前有時會等待一會兒。在 SimPy 中,您還可以“鈍化”進程,這意味著在一個進程完成一個任務后,只有當其它進程要求該進程完成其它任務時,它才會去做。把進程當作嘗試完成一個目標,常常是很有用的。在編寫進程時,通常把它編寫成可以在其中執行多個操作的循環。在每個操作之間,可以插入 Python“yield”語句,它讓模擬調度程序在返回控制之前執行每個等待進程的操作。
      
      進程執行的許多操作取決于資源的使用。資源只是在可用性方面受到限制。在生物學模型中,資源可能是食物供應;在網絡模型中,資源可以是路由器或有限帶寬通道;在我們的市場模擬中,資源是付款通道。資源執行的唯一任務是在任何給定的時間內將它的使用限于一個特定的進程上。在 SimPy 編程模型下,進程單獨決定它要保留資源的時間有多長,資源本身是被動的。在實際系統中,SimPy 模型可能適合概念性方案,也可能不適合;很容易想象到資源在本質上會限制其利用率(例如,如果服務器計算機在必需的時間幀內沒有獲得滿意的響應,則它會中斷連接)。但作為編程問題,進程或資源是否是“主動”方就不是特別重要(只要確保您理解了您的意圖)。
      
      最后一個 SimPy 類是監控程序。實際上監控程序不是很重要,只不過它很方便。監控程序所做的全部任務就是記錄向它報告的事件,并保存有關這些事件的統計信息(平均值、計數、方差等)。該庫提供的 Monitor 類對記錄模擬措施是個有用的工具,但您也可以通過您想使用的其它任何技術來記錄事件。事實上,我的示例使 Monitor 子類化,以提供某些(稍微)增強的能力。
      
      設置商店:對模擬編程
      在我所撰寫的大部分文章中,我都會馬上給出樣本應用程序,但在本例中,我認為帶您經歷食品雜貨店應用程序的每個步驟會更有用。如果您愿意的話,可以把每個部分剪貼在一起;SimPy 創造者們將在將來的發行版中包含我的示例。
      
      SimPy 模擬中的第一步是幾個常規的導入(import)語句:
      
      清單 1. 導入 SimPy 庫 #!/usr/bin/env python
      from __future__ import generators
      from SimPy import Simulation
      from SimPy.Simulation import hold, request, release, now
      from SimPy.Monitor import Monitor
      import random
      from math import sqrt
      
      有些 SimPy 附帶的示例使用 import * 樣式,但我更喜歡使我填充的名稱空間更清晰。對于 Python 2.2(SimPy 所需的最低版本),將需要如指出的那樣,導入生成器特性。對于 Python 2.3 以后的版本,不需要這樣做。
      
      對于我的應用程序,我定義了幾個運行時常量,它們描述了在特定的模擬運行期間我感興趣的幾個方案。在我更改方案時,我必須在主腳本內編輯這些常量。要是這個應用程序的內容更充實,那么我就可能用命令行選項、環境變量或配置文件來配置這些參數。但就目前而言,這個樣式已經足夠了:
      
      清單 2. 配置模擬參數 AISLES = 5     # Number of open aisles
      ITEMTIME = 0.1   # Time to ring up one item
      AVGITEMS = 20   # Average number of items purchased
      CLOSING = 60*12  # Minutes from store open to store close
      AVGCUST = 1500   # Average number of daily customers
      RUNS = 10     # Number of times to run the simulation
      
      我們的模擬需要完成的主要任務是定義一個或多個進程。對于模擬食品雜貨店,我們感興趣的進程是在通道處付款的顧客。
      
      清單 3. 定義顧客的操作 class Customer(Simulation.Process):
      def __init__(self):
      Simulation.Process.__init__(self)
      # Randomly pick how many items this customer is buying
      self.items = 1 + int(random.expovariate(1.0/AVGITEMS))
      def checkout(self):
      start = now()      # Customer decides to check out
      yield request, self, checkout_aisle
      at_checkout = now()   # Customer gets to front of line
      waittime.tally(at_checkout-start)
      yield hold, self, self.items*ITEMTIME
      leaving = now()     # Customer completes purchase
      checkouttime.tally(leaving-at_checkout)
      yield release, self, checkout_aisle
      
      每位顧客已經決定采購一定數量的商品。(我們的模擬不涉及從食品雜貨店通道上選擇商品;顧客只是推著他們的手推車到達付款處。)我不能確定這里的指數變量分布確實是一個精確的模型。在其低端處我感覺是對的,但我感到對實際購物者究竟采購了多少商品的最高極限有點失實。在任何情況下,您可以看到如果可以使用更好的模型信息,則調整我們的模擬是多么簡單。
      
      顧客采取的操作是我們所關注的。顧客的“執行方法”就是 .checkout()。這個進程方法通常被命名為 .run() 或 .execute(),但在我的示例中,.checkout() 似乎是最可描述的。您可以對它起任何您希望的名稱。Customer 對象所采取的實際操作僅僅是檢查幾個點上的模擬時間,并將持續時間記錄到 waittime 和 checkouttime 監控程序中。但在這些操作之間是至關重要的 yield 語句。在第一種情況中,顧客請求資源(付款通道)。只有當顧客獲得了所需的資源之后,他們才能做其它操作。一旦來到付款通道,顧客實際上就在付款了 — 所花時間與所購商品的數量成比例。最后,經過付款處之后,顧客就釋放資源,以便其他顧客可以使用它。
      
      上述代碼定義了 Customer 類的操作,但我們需要在運行模擬之前,創建一些實際的顧客對象。我們可以為一天中將要購物的每位顧客生成顧客對象,并為每位顧客分配相應的付款時間。但更簡潔的方法是“在每位顧客到商店時”,讓工廠對象生成所需的顧客對象。實際上模擬并不會同時對一天內將要購物的所有顧客感興趣,而是只對那些要同時爭用付款通道的顧客感興趣。注意:Customer_Factory 類本身是模擬的一部分 — 它是一個進程。盡管對于這個客戶工廠,您可能聯想到人造的機器工人(la Fritz Lang 的 Metropolis),但還是應該只把它看作編程的便利工具;它并不直接對應已建模域中的任何事物。
      
      清單 4. 生成顧客流 class Customer_Factory(Simulation.Process):
      def run(self):
      while 1:
      c = Customer()
      Simulation.activate(c, c.checkout())
      arrival = random.expovariate(float(AVGCUST)/CLOSING)
      yield hold, self, arrival
      
      正如我前面提到的,我想收集一些當前 SimPy Monitor 類沒有解決的統計信息。也就是,我并不僅僅對平均付款時間感興趣,而且還對給定方案中最

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>