欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

用Python的SimPy庫簡化復(fù)雜的編程模型的介紹

 更新時間:2015年04月13日 15:26:50   投稿:goldensun  
這篇文章主要介紹了用Python的SimPy庫簡化復(fù)雜的編程模型的介紹,本文來自于官方的開發(fā)者技術(shù)文檔,需要的朋友可以參考下

在我遇到 SimPy 包的其中一位創(chuàng)始人 Klaus Miller 時,從他那里知道了這個包。Miller 博士閱讀過幾篇提出使用 Python 2.2+ 生成器實(shí)現(xiàn)半?yún)f(xié)同例程和“輕便”線程的技術(shù)的 可愛的 Python專欄文章。特別是(使我很高興的是),他發(fā)現(xiàn)在用 Python 實(shí)現(xiàn) Simula-67 樣式模擬時,這些技術(shù)很有用。

結(jié)果表明 Tony Vignaux 和 Chang Chui 以前曾創(chuàng)建了另一個 Python 庫,它在概念上更接近于 Simscript,而且該庫使用了標(biāo)準(zhǔn)線程技術(shù),而不是我的半?yún)f(xié)同例程技術(shù)。該小組在一起研究時,認(rèn)為基于生成器的樣式更有效得多,并且最近在 SourceForge 上發(fā)起了使用 GPL 的項目,稱為 SimPy(請參閱 參考資料,獲得 SimPy 主頁的鏈接),目前處于 beta 測試版狀態(tài)。Vignaux 教授希望他在惠靈頓維多利亞大學(xué)(University of Victoria)的將來大學(xué)教學(xué)中使用統(tǒng)一的 SimPy 包;我相信該庫也非常適合應(yīng)用到各類實(shí)用問題中。

我承認(rèn)在近期的通信交流和調(diào)查研究之前,我對編程領(lǐng)域的模擬方面沒有任何基礎(chǔ)知識。我猜想本專欄文章的大部分讀者也和我一樣,對這方面的知識知之甚少。盡管有人會認(rèn)為這種樣式編程的方式有些新奇,但在理解資源有限的實(shí)際系統(tǒng)的行為時,模擬是很有用的。不管您感興趣的是有限帶寬網(wǎng)絡(luò)、汽車交通行為、市場和商業(yè)性優(yōu)化、生物/進(jìn)化的交互作用還是其它“隨機(jī)”系統(tǒng),SimPy 對這樣的建模都提供了簡單的 Python 工具。
隨機(jī)的定義

與“連接”相類似,它是那些 最適合形容其作業(yè)的詞匯之一 - 再也找不到更適合的了:

隨機(jī)(stochastic),源自希臘語 stokhastikos(形容詞)
1)推測的、與推測相關(guān)的或者具有推測特點(diǎn)的;好推測的。
2)在統(tǒng)計學(xué)上:涉及或包含一個隨機(jī)變量或多個隨機(jī)變量,或涉及偶然性或概率。

來源:Dictionary.com

在本專欄文章中,我將一直使用食品雜貨店內(nèi)具有多條通道的付款區(qū)域這個相當(dāng)簡單的示例。通過使用所演示的模擬,我們可以根據(jù)對掃描器技術(shù)、購物者習(xí)慣、人員配備需求等進(jìn)行的各種更改所產(chǎn)生的經(jīng)濟(jì)上和等待時間上的含義提出問題。這個建模的優(yōu)點(diǎn)是在您對所做的更改產(chǎn)生的含義有清晰的想法時,它讓您能提前制定策略。很明顯,大多數(shù)讀者不會專門經(jīng)營一家食品雜貨店,但這些技術(shù)可以廣泛地應(yīng)用于各類系統(tǒng)中。
模擬的概念

SimPy 庫只提供了三個抽象/父類,并且它們對應(yīng)于模擬的三個基本概念。有許多其它常規(guī)函數(shù)和常量用于控制模擬的運(yùn)行,但重要的概念都與這些類結(jié)合在一起。

模擬中的核心概念是 進(jìn)程。一個進(jìn)程只是一個對象,它完成某些任務(wù),隨后在它準(zhǔn)備完成下一個任務(wù)之前有時會等待一會兒。在 SimPy 中,您還可以“鈍化”進(jìn)程,這意味著在一個進(jìn)程完成一個任務(wù)后,只有當(dāng)其它進(jìn)程要求該進(jìn)程完成其它任務(wù)時,它才會去做。把進(jìn)程當(dāng)作嘗試完成一個目標(biāo),常常是很有用的。在編寫進(jìn)程時,通常把它編寫成可以在其中執(zhí)行多個操作的循環(huán)。在每個操作之間,可以插入 Python“yield”語句,它讓模擬調(diào)度程序在返回控制之前執(zhí)行每個等待進(jìn)程的操作。

進(jìn)程執(zhí)行的許多操作取決于 資源的使用。資源只是在可用性方面受到限制。在生物學(xué)模型中,資源可能是食物供應(yīng);在網(wǎng)絡(luò)模型中,資源可以是路由器或有限帶寬通道;在我們的市場模擬中,資源是付款通道。資源執(zhí)行的唯一任務(wù)是在任何給定的時間內(nèi)將它的使用限于一個特定的進(jìn)程上。在 SimPy 編程模型下,進(jìn)程單獨(dú)決定它要保留資源的時間有多長,資源本身是被動的。在實(shí)際系統(tǒng)中,SimPy 模型可能適合概念性方案,也可能不適合;很容易想象到資源在本質(zhì)上會限制其利用率(例如,如果服務(wù)器計算機(jī)在必需的時間幀內(nèi)沒有獲得滿意的響應(yīng),則它會中斷連接)。但作為編程問題,進(jìn)程或資源是否是“主動”方就不是特別重要(只要確保您理解了您的意圖)。

最后一個 SimPy 類是 監(jiān)控程序。實(shí)際上監(jiān)控程序不是很重要,只不過它很方便。監(jiān)控程序所做的全部任務(wù)就是記錄向它報告的事件,并保存有關(guān)這些事件的統(tǒng)計信息(平均值、計數(shù)、方差等)。該庫提供的 Monitor 類對記錄模擬措施是個有用的工具,但您也可以通過您想使用的其它任何技術(shù)來記錄事件。事實(shí)上,我的示例使 Monitor 子類化,以提供某些(稍微)增強(qiáng)的能力。


設(shè)置商店:對模擬編程

在我所撰寫的大部分文章中,我都會馬上給出樣本應(yīng)用程序,但在本例中,我認(rèn)為帶您經(jīng)歷食品雜貨店應(yīng)用程序的每個步驟會更有用。如果您愿意的話,可以把每個部分剪貼在一起;SimPy 創(chuàng)造者們將在將來的發(fā)行版中包含我的示例。

SimPy 模擬中的第一步是幾個常規(guī)的導(dǎo)入(import)語句:
清單 1. 導(dǎo)入 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 所需的最低版本),將需要如指出的那樣,導(dǎo)入生成器特性。對于 Python 2.3 以后的版本,不需要這樣做。

對于我的應(yīng)用程序,我定義了幾個運(yùn)行時常量,它們描述了在特定的模擬運(yùn)行期間我感興趣的幾個方案。在我更改方案時,我必須在主腳本內(nèi)編輯這些常量。要是這個應(yīng)用程序的內(nèi)容更充實(shí),那么我就可能用命令行選項、環(huán)境變量或配置文件來配置這些參數(shù)。但就目前而言,這個樣式已經(jīng)足夠了:
清單 2. 配置模擬參數(shù)

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

我們的模擬需要完成的主要任務(wù)是定義一個或多個進(jìn)程。對于模擬食品雜貨店,我們感興趣的進(jìn)程是在通道處付款的顧客。
清單 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

每位顧客已經(jīng)決定采購一定數(shù)量的商品。(我們的模擬不涉及從食品雜貨店通道上選擇商品;顧客只是推著他們的手推車到達(dá)付款處。)我不能確定這里的指數(shù)變量分布確實(shí)是一個精確的模型。在其低端處我感覺是對的,但我感到對實(shí)際購物者究竟采購了多少商品的最高極限有點(diǎn)失實(shí)。在任何情況下,您可以看到如果可以使用更好的模型信息,則調(diào)整我們的模擬是多么簡單。

顧客采取的操作是我們所關(guān)注的。顧客的“執(zhí)行方法”就是 .checkout() 。這個進(jìn)程方法通常被命名為 .run() 或 .execute() ,但在我的示例中, .checkout() 似乎是最可描述的。您可以對它起任何您希望的名稱。 Customer 對象所采取的實(shí)際 操作僅僅是檢查幾個點(diǎn)上的模擬時間,并將持續(xù)時間記錄到 waittime 和 checkouttime 監(jiān)控程序中。但在這些操作之間是至關(guān)重要的 yield 語句。在第一種情況中,顧客請求資源(付款通道)。只有當(dāng)顧客獲得了所需的資源之后,他們才能做其它操作。一旦來到付款通道,顧客實(shí)際上就在付款了 — 所花時間與所購商品的數(shù)量成比例。最后,經(jīng)過付款處之后,顧客就釋放資源,以便其他顧客可以使用它。

上述代碼定義了 Customer 類的操作,但我們需要在運(yùn)行模擬之前,創(chuàng)建一些實(shí)際的顧客對象。我們 可以為一天中將要購物的每位顧客生成顧客對象,并為每位顧客分配相應(yīng)的付款時間。但更簡潔的方法是“在每位顧客到商店時”,讓工廠對象生成所需的顧客對象。實(shí)際上模擬并不會同時對一天內(nèi)將要購物的所有顧客感興趣,而是只對那些要同時爭用付款通道的顧客感興趣。注意: Customer_Factory 類本身是模擬的一部分 — 它是一個進(jìn)程。盡管對于這個客戶工廠,您可能聯(lián)想到人造的機(jī)器工人(la Fritz Lang 的 Metropolis),但還是應(yīng)該只把它看作編程的便利工具;它并不直接對應(yīng)已建模域中的任何事物。
清單 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

正如我前面提到的,我想收集一些當(dāng)前 SimPy Monitor 類沒有解決的統(tǒng)計信息。也就是,我并不僅僅對平均付款時間感興趣,而且還對給定方案中最糟糕情況感興趣。所以我創(chuàng)建了一個增強(qiáng)的監(jiān)控程序,它收集最小和最大的計數(shù)值。
用監(jiān)控程序監(jiān)視模擬

class Monitor2(Monitor):
  def __init__(self):
    Monitor.__init__(self)
    self.min, self.max = (int(2**31-1),0)
  def tally(self, x):
    Monitor.tally(self, x)
    self.min = min(self.min, x)
    self.max = max(self.max, x)

我們模擬的最后一步當(dāng)然是 運(yùn)行它。在大多數(shù)標(biāo)準(zhǔn)示例中,只運(yùn)行一次模擬。但對于我的食品雜貨店,我決定通過幾次模擬進(jìn)行循環(huán),每次對應(yīng)于某一天的業(yè)務(wù)。這看來是個好主意,因?yàn)橛行┙y(tǒng)計信息會隨每天的情況而有相當(dāng)大的不同(因?yàn)榈竭_(dá)的顧客人次以及所購商品數(shù)采用隨機(jī)產(chǎn)生的不同值)。
清單 6. 每天運(yùn)行模擬

for run in range(RUNS):
  waittime = Monitor2()
  checkouttime = Monitor2()
  checkout_aisle = Simulation.Resource(AISLES)
  Simulation.initialize()
  cf = Customer_Factory()
  Simulation.activate(cf, cf.run(), 0.0)
  Simulation.simulate(until=CLOSING)
  #print "Customers:", checkouttime.count()
  print "Waiting time average: %.1f" % waittime.mean(), \
     "(std dev %.1f, maximum %.1f)" % (sqrt(waittime.var()),waittime.max)
  #print "Checkout time average: %1f" % checkouttime.mean(), \
  #   "(standard deviation %.1f)" % sqrt(checkouttime.var())
print 'AISLES:', AISLES, ' ITEM TIME:', ITEMTIME


三人不歡:一些結(jié)果(以及它們意味著什么)

當(dāng)我最初考慮食品雜貨店模型時,我認(rèn)為模擬可以解答幾個直接問題。例如,我想象店主可能會選擇購買改進(jìn)的掃描儀(減少 ITEMTIME ),或者選擇雇傭更多職員(增加 AISLES )。我想只要在每個方案下運(yùn)行這個模擬(假設(shè)雇員和技術(shù)成本給定的情況下),并確定上面兩種選擇哪種更能減少成本。

只有運(yùn)行了模擬后,我才意識到可能會出現(xiàn)比預(yù)料的更有趣的事情。查看收集的所有數(shù)據(jù),我意識到我不知道要嘗試優(yōu)化的是什么。 什么。例如,減少 平均付款時間和減少 最差情況的時間,哪個更重要?哪些方面會提高總體顧客滿意度?另外,如何比較顧客在付款之前所用的等待時間以及掃描所購商品所花的時間?以我個人的經(jīng)驗(yàn),我會在等待的隊列中感到不耐煩,但在掃描我的商品時,我不會感到很麻煩(即使這會花一些時間)。

當(dāng)然,我沒有經(jīng)營食品雜貨店,所以我不知道所有這些問題的答案。但這個模擬確實(shí)讓我準(zhǔn)確地決定什么是折衷方案;而且它很簡單,足以稍作調(diào)整就可適用于許多行為(包括那些還未顯式地參數(shù)化的行為 — 例如,“一整天中顧客 真的會一直不斷地來嗎?”)。

我只要演示最后一個示例,就可以說明該模型的價值。我在上面曾寫道復(fù)雜系統(tǒng)的行為難以概念化。我認(rèn)為這里的示例可以證明這一事實(shí)。在可用的通道從 6 條減少到 5 條(其它參數(shù)不變)時,您認(rèn)為會出現(xiàn)什么情況?最初我想會 稍微增加最糟糕情況下的付款時間。而事實(shí)并非如此:
清單 7. 通道數(shù)變化前后運(yùn)行的兩個樣本

% python Market.py
Waiting time average: 0.5 (std dev 0.9, maximum 4.5)
Waiting time average: 0.3 (std dev 0.6, maximum 3.7)
Waiting time average: 0.4 (std dev 0.8, maximum 5.6)
Waiting time average: 0.4 (std dev 0.8, maximum 5.2)
Waiting time average: 0.4 (std dev 0.8, maximum 5.8)
Waiting time average: 0.3 (std dev 0.6, maximum 5.2)
Waiting time average: 0.5 (std dev 1.1, maximum 5.2)
Waiting time average: 0.5 (std dev 1.0, maximum 5.4)
AISLES: 6  ITEM TIME: 0.1
% python Market.py
Waiting time average: 2.1 (std dev 2.3, maximum 9.5)
Waiting time average: 1.8 (std dev 2.3, maximum 10.9)
Waiting time average: 1.3 (std dev 1.7, maximum 7.3)
Waiting time average: 1.7 (std dev 2.1, maximum 9.5)
Waiting time average: 4.2 (std dev 5.6, maximum 21.3)
Waiting time average: 1.6 (std dev 2.6, maximum 12.0)
Waiting time average: 1.3 (std dev 1.6, maximum 7.5)
Waiting time average: 1.5 (std dev 2.1, maximum 11.2)
AISLES: 5  ITEM TIME: 0.1

減少一條付款通道不是使平均等待時間增加 1/5 或類似的情況,而是使它增加了大約 4 倍。而且,最不幸的顧客(在這些特定的運(yùn)行期間)的等待時間從 6 分鐘增加到了 21 分鐘。如果我是經(jīng)理,我認(rèn)為了解這個極限情況對顧客滿意度而言是極其重要的。誰會早已知道這一點(diǎn)呢?

相關(guān)文章

最新評論