问题描述
我定义了一个生成器,该生成器生成系统的泊松到达率。我希望每个生成的到达(客户)都有一个随机数(x,y),该值显示到达客户到系统的位置。即我想生成系统的泊松到达率,其中每个到达都来自随机位置。假设x在50范围内,y在60范围内。
如何将其添加到以下代码中?
class Arrival(object):
def __init__(self,stream_defin,referrer):
self.service = stream_defin["service"]
self.arrival_rate = stream_defin["rate"]
self.referrer = referrer
def sim_init(self,env,sim_stats):
self.sim_stats = sim_stats
self.env = env
self.env.process(self.sim_arrival_generator())
def sim_arrival_generator(self):
i = 0
while True:
interarrival = spstats.expon(scale=1/self.arrival_rate).rvs()
yield self.env.timeout(interarrival)
i+=1
解决方法
您的代码引用了许多您未提供其定义的对象和方法。这使得很难确切知道您要查找的内容。另外,我不确定我是否从概念上理解您的需求。但是,如果我以最简单的方式解释您的要求,那么我会建议您:
我假设此行当前正在创建一个“到达”,它由interarrival
变量引用:
interarrival = spstats.expon(scale=1/self.arrival_rate).rvs()
该值当前似乎是一个延迟值,以使连续延迟的模式覆盖泊松分布模式。不仅仅是时间值,您还希望在代码中的这一点上创建一个延迟以及x
和y
坐标给定的随机位置,并使它们一起代表一个“到达”。
我建议创建一个Python字典对象来表示每次到达。这是您可以执行的操作:
interarrival = {
'delay': spstats.expon(scale=1 / self.arrival_rate).rvs(),'position': {
'x': random.randint(self.min_x,self.max_x),'y': random.randint(self.min_y,self.max_y)
}
}
在答案中进行大量编码工作不是S.O.是真的,但是您在无聊的时刻抓住了我,我讨厌提供我实际上没有运行过的代码,所以...
我采取了许多自由行动,并填写了您的代码,以便它可以实际运行并“执行某些操作”,尽管所做的只是延迟到达之间的时间,并在每次到达时打印出其值。我假设您想查看实际的延迟是因为您致电self.env.timeout
,并且您的生成器从未停止生成到达信息。没有延迟或一些费时的处理,此代码将迅速产生成千上万您无法读取的到达信息。
我将您的班级从Arrival
重命名为Arrivals
,因为其中的代码处理的是一系列到达事件,而不是单个到达事件,而且我想不出一种改变它的好方法还有更多变化。我主要尝试添加代码,并尽可能减少提供的代码。考虑到所有这些,这就是我想到的:
import scipy.stats as spstats
import random
import json
import time
class Arrivals(object):
def __init__(self,stream_defin,referrer):
self.service = stream_defin["service"]
self.arrival_rate = stream_defin["rate"]
self.min_x,self.max_x = stream_defin["min_x"],stream_defin["max_x"]
self.min_y,self.max_y = stream_defin["min_y"],stream_defin["max_y"]
self.referrer = referrer
def sim_init(self,env,sim_stats):
self.sim_stats = sim_stats
self.env = env
self.env.process(self.sim_arrival_generator())
return self
def sim_arrival_generator(self):
i = 0
while True:
interarrival = {
'index': i,'delay': spstats.expon(scale=1 / self.arrival_rate).rvs(),'position': {
'x': random.randint(self.min_x,self.max_y)
}
}
yield self.env.timeout(interarrival)
i += 1
class Env():
def process(self,arrivals):
for arrival in arrivals:
# Do whatever needs to be done with each arrival
print('Processing arrival: ')
print(json.dumps(arrival,indent=4))
def timeout(self,arrival):
# Delay the arrival by its delay time before delivering for processing
print("Delaying %2.2f seconds..." % (arrival['delay']))
time.sleep(arrival['delay'])
return arrival
def main():
stream_defin = {
'service': 'service','rate': 0.5,'min_x': 5,'max_x': 50,'min_y': 10,'max_y': 60
}
stats = [] # a place to collect results,I assume
Arrivals(stream_defin,'referrer').sim_init(Env(),stats)
main()
这个东西可以永远运行,所以当你想停止它的时候必须用CTRL-C退出它。添加一个iterations
配置值以限制迭代次数将很容易。您既可以将其添加到生成器本身,也可以在达到指定的迭代计数时退出process()
方法。
采样结果(输出有实际延迟,如下所示):
Delaying 5.39 seconds...
Processing arrival:
{
"index": 0,"delay": 5.394974068076859,"position": {
"x": 34,"y": 29
}
}
Delaying 1.51 seconds...
Processing arrival:
{
"index": 1,"delay": 1.5095025601339542,"position": {
"x": 24,"y": 24
}
}
Delaying 1.48 seconds...
Processing arrival:
{
"index": 2,"delay": 1.4840036046166114,"position": {
"x": 28,"y": 57
}
}
Delaying 4.09 seconds...
Processing arrival:
{
"index": 3,"delay": 4.08649062133332,"position": {
"x": 37,"y": 14
}
}
...