SimPy 中的接收器状态
Sink state in SimPy
我正在探索 SimPy
模拟患者在护理过程中的流动。在模拟模型中,患者要么接受治疗,要么死亡。显然,这些都是相互竞争的风险,患者死后不应该接受治疗。但是,我对 SimPy 还很陌生,我还没有发现如何为水槽建模,以便这些已故患者无法继续进行模拟。
我比较熟悉R
中的simmer
包,里面可以branch()
模型结构,指定模型结构的哪个分支是死胡同。 SimPy 中是否有类似的功能?或者还有其他优雅的选择吗?
为了说明我的意思,下面是模拟模型:
from random import seed, randint
seed(123)
MAX_CYCLES = 5
PROB_DEATH = 0.2
class Patient:
def __init__(self, env, treatment_cycles = 0):
self.env = env
self.treatment_cycles = treatment_cycles
self.treatment_proc = env.process(self.get_treatment(env))
def get_treatment(self, env):
while self.treatment_cycles < MAX_CYCLES:
self.treatment_cycles += 1
rand = random.uniform(0, 1)
if (rand < PROB_DEATH):
yield env.timeout(random.randint(20, 40))
print('I have died at {}'.format(env.now))
### Once this point has been reached, patients should not be able to continue ###
else:
yield env.timeout(randint(20, 80))
print("I have completed a full cycle of treatment after {} days.".format(int(env.now)))
env = simpy.Environment()
pat = Patient(env)
env.run(until=250)
这会导致明显不希望的输出:
I have died at 22
I have completed a full cycle of treatment after 59 days.
I have died at 80
I have completed a full cycle of treatment after 135 days.
I have completed a full cycle of treatment after 209 days.
模拟主要有两种类型
classic 实体流,其中站点拥有所有逻辑,而实体只有很少的逻辑,站点决定实体的命运。
entity/agent 拥有所有代码并决定自己命运的特工基地。
实体流的 classic 示例是制造生产线,其中 stations/machines 决定对实体做什么以及下一步将其发送(分支)到哪里。您的 R 代码听起来像是使用这种范式
你的例子更像是代理,比如 entity/patient 控制自己的行为。
要解决此问题,您只需向 class 添加一个“状态”属性即可跟踪患者是活是死。然后在你的 while 循环中检查病人的状态
见下文:
"""
Show how to use a state variable to change behavior
programmer: Michael R. Gibbs
"""
from random import seed, randint, uniform
import simpy
seed(123)
MAX_CYCLES = 5
PROB_DEATH = 0.2
class Patient:
"""
patient seeking treatment
"""
def __init__(self, env, treatment_cycles = 0):
self.state = 'Live' # starts out as a living patient
self.env = env
self.treatment_cycles = treatment_cycles
self.treatment_proc = env.process(self.get_treatment(env))
def get_treatment(self, env):
"""
gets a treatment that can change the patient's
state from live, to dead
"""
while self.treatment_cycles < MAX_CYCLES and self.state=='Live':
# treat untile done, or patient has died
self.treatment_cycles += 1
rand = uniform(0, 1)
if (rand < PROB_DEATH):
# patient has died
yield env.timeout(randint(20, 40))
print('I have died at {}'.format(env.now))
# update state to dead
self.state = 'Dead'
### Once this point has been reached, patients should not be able to continue ###
else:
yield env.timeout(randint(20, 80))
print("I have completed a full cycle of treatment after {} days.".format(int(env.now)))
env = simpy.Environment()
pat = Patient(env)
env.run(until=250)
这是一种更多过程和更少代理基础的编码方式
进程是站
"""
Show how to use a state variable to change behavior
less agent, more process
programmer: Michael R. Gibbs
"""
from random import seed, randint, uniform
import simpy
seed(123)
MAX_CYCLES = 5
PROB_DEATH = 0.2
def died(env, patient):
"""
patien dies, and no more processing
"""
yield env.timeout(randint(20, 80))
patient.sate = 'Dead'
print(f"Patient {patient.id} has died on day {env.now}")
def provide_treatment(env, patient):
"""
determine fate of patient
if lives provide treatment and send to next treatment
if dies, send to death process
"""
if patient.treatment_cycles < MAX_CYCLES:
patient.treatment_cycles += 1
rand = uniform(0, 1)
if (rand < PROB_DEATH):
# patient has died
env.process(died(env,patient))
else:
# patient lives
yield env.timeout(randint(20, 80))
print(f"Patient {patient.id} completed a full cycle of treatment after {env.now} days.")
# send to next treatment
env.process(provide_treatment(env,patient))
else:
# done with all treatments, do not send anywhere
print(f"Patient {patient.id} has completed all treatments after {env.now} days")
class Patient:
"""
patient seeking treatment
"""
next_id = 1
def __init__(self, env, treatment_cycles = 0):
self.state = 'Live' # starts out as a living patient
self.id = Patient.next_id
Patient.next_id += 1
self.env = env
self.treatment_cycles = treatment_cycles
env = simpy.Environment()
pat = Patient(env)
env.process(provide_treatment(env,pat))
pat = Patient(env)
env.process(provide_treatment(env,pat))
pat = Patient(env)
env.process(provide_treatment(env,pat))
pat = Patient(env)
env.process(provide_treatment(env,pat))
env.run(until=250)
我正在探索 SimPy
模拟患者在护理过程中的流动。在模拟模型中,患者要么接受治疗,要么死亡。显然,这些都是相互竞争的风险,患者死后不应该接受治疗。但是,我对 SimPy 还很陌生,我还没有发现如何为水槽建模,以便这些已故患者无法继续进行模拟。
我比较熟悉R
中的simmer
包,里面可以branch()
模型结构,指定模型结构的哪个分支是死胡同。 SimPy 中是否有类似的功能?或者还有其他优雅的选择吗?
为了说明我的意思,下面是模拟模型:
from random import seed, randint
seed(123)
MAX_CYCLES = 5
PROB_DEATH = 0.2
class Patient:
def __init__(self, env, treatment_cycles = 0):
self.env = env
self.treatment_cycles = treatment_cycles
self.treatment_proc = env.process(self.get_treatment(env))
def get_treatment(self, env):
while self.treatment_cycles < MAX_CYCLES:
self.treatment_cycles += 1
rand = random.uniform(0, 1)
if (rand < PROB_DEATH):
yield env.timeout(random.randint(20, 40))
print('I have died at {}'.format(env.now))
### Once this point has been reached, patients should not be able to continue ###
else:
yield env.timeout(randint(20, 80))
print("I have completed a full cycle of treatment after {} days.".format(int(env.now)))
env = simpy.Environment()
pat = Patient(env)
env.run(until=250)
这会导致明显不希望的输出:
I have died at 22
I have completed a full cycle of treatment after 59 days.
I have died at 80
I have completed a full cycle of treatment after 135 days.
I have completed a full cycle of treatment after 209 days.
模拟主要有两种类型 classic 实体流,其中站点拥有所有逻辑,而实体只有很少的逻辑,站点决定实体的命运。 entity/agent 拥有所有代码并决定自己命运的特工基地。
实体流的 classic 示例是制造生产线,其中 stations/machines 决定对实体做什么以及下一步将其发送(分支)到哪里。您的 R 代码听起来像是使用这种范式
你的例子更像是代理,比如 entity/patient 控制自己的行为。
要解决此问题,您只需向 class 添加一个“状态”属性即可跟踪患者是活是死。然后在你的 while 循环中检查病人的状态
见下文:
"""
Show how to use a state variable to change behavior
programmer: Michael R. Gibbs
"""
from random import seed, randint, uniform
import simpy
seed(123)
MAX_CYCLES = 5
PROB_DEATH = 0.2
class Patient:
"""
patient seeking treatment
"""
def __init__(self, env, treatment_cycles = 0):
self.state = 'Live' # starts out as a living patient
self.env = env
self.treatment_cycles = treatment_cycles
self.treatment_proc = env.process(self.get_treatment(env))
def get_treatment(self, env):
"""
gets a treatment that can change the patient's
state from live, to dead
"""
while self.treatment_cycles < MAX_CYCLES and self.state=='Live':
# treat untile done, or patient has died
self.treatment_cycles += 1
rand = uniform(0, 1)
if (rand < PROB_DEATH):
# patient has died
yield env.timeout(randint(20, 40))
print('I have died at {}'.format(env.now))
# update state to dead
self.state = 'Dead'
### Once this point has been reached, patients should not be able to continue ###
else:
yield env.timeout(randint(20, 80))
print("I have completed a full cycle of treatment after {} days.".format(int(env.now)))
env = simpy.Environment()
pat = Patient(env)
env.run(until=250)
这是一种更多过程和更少代理基础的编码方式 进程是站
"""
Show how to use a state variable to change behavior
less agent, more process
programmer: Michael R. Gibbs
"""
from random import seed, randint, uniform
import simpy
seed(123)
MAX_CYCLES = 5
PROB_DEATH = 0.2
def died(env, patient):
"""
patien dies, and no more processing
"""
yield env.timeout(randint(20, 80))
patient.sate = 'Dead'
print(f"Patient {patient.id} has died on day {env.now}")
def provide_treatment(env, patient):
"""
determine fate of patient
if lives provide treatment and send to next treatment
if dies, send to death process
"""
if patient.treatment_cycles < MAX_CYCLES:
patient.treatment_cycles += 1
rand = uniform(0, 1)
if (rand < PROB_DEATH):
# patient has died
env.process(died(env,patient))
else:
# patient lives
yield env.timeout(randint(20, 80))
print(f"Patient {patient.id} completed a full cycle of treatment after {env.now} days.")
# send to next treatment
env.process(provide_treatment(env,patient))
else:
# done with all treatments, do not send anywhere
print(f"Patient {patient.id} has completed all treatments after {env.now} days")
class Patient:
"""
patient seeking treatment
"""
next_id = 1
def __init__(self, env, treatment_cycles = 0):
self.state = 'Live' # starts out as a living patient
self.id = Patient.next_id
Patient.next_id += 1
self.env = env
self.treatment_cycles = treatment_cycles
env = simpy.Environment()
pat = Patient(env)
env.process(provide_treatment(env,pat))
pat = Patient(env)
env.process(provide_treatment(env,pat))
pat = Patient(env)
env.process(provide_treatment(env,pat))
pat = Patient(env)
env.process(provide_treatment(env,pat))
env.run(until=250)