i want to model the maintenace process on a piece of production equipment. this machine may be down for maintenace due to one of three reasons, namely (i) it may breakdown according to an exponentially distributed probability described by expovariate of 1/MTBF, where MTBF is the mean time between failures, (ii) or it may eventually become due for a time based service as per defined schedule, say after 4, 13, 26 or 52 weeks since the previous service, the servicing of which re-sets the breakdown probability to start all over again (iii) or it may be taken down for routine inspections and any arising repair or restoration works following the findings of the inspections, which again resets the breakdowns expovariate function. is it possible to set up three while True loops that will run their respective timeout functions concurrently but all stop as soon as any one of the three processes actually times out? preferably within the simpy environment? something like...
import simpy
import random
mtbf = 150 #hours
service_interval = 600 #hours
inspect_repair_interval = 300 #hours
def run_to_failure():
while True:
failed = random.expovariate(1/mtbf)
yield env.timeout(failed)
def run_to_service():
while True:
stopped = service_interval
yield env.timeout(stopped)
def run_to_repair():
while True:
paused = inspect_repair_interval
yield env.timeout(paused)
now, how do i run all 3 functions concurrently but be able to stop and reset all once any one of them yields? the yielded value will serve as an input to subsequent processes, and which of those subsequent processes run also depends on which function yielded the value
Here is a example of a machine with three process running at the same time: the main machine task, a loop of regular maintenance, and breakdown events
"""
quick sim of a machine with breakdowns
programmer: Michael R. Gibbs
"""
import simpy
import random
class Machine():
"""
A machine with a main processing loop that can be
interupted with breakdowns
"""
def __init__(self, env):
"""
Initializes the machine and starts
processing and breadowns
"""
self.env = env
# start main task
self.startup()
# start schedule for service
self.service = self.env.process(self.wait_for_service())
def startup(self):
"""
Starts up the machine
Also starts up the breakdown schedule
"""
self.task = self.env.process(self.main_task())
self.breakdown = self.env.process(self.wait_for_breakdown())
def shut_down(self):
"""
Shuts down the machine
Also kills the pending breakdown
"""
if self.task is not None:
# only shutdown if not running
self.task.interrupt()
self.task = None
if self.breakdown is not None:
# only cancel pending breakdown if it is still pending
self.breakdown.interrupt()
def main_task(self):
"""
The main processing loop of the machine
"""
print(f'{self.env.now} - starting up machine')
try:
while True:
yield self.env.timeout(3)
print(f'{self.env.now} - did some work')
except simpy.Interrupt as i:
print(f'{self.env.now} - processing has been interupted')
print(f'{self.env.now} - shutting down machine')
def wait_for_service(self):
"""
Schedules and executes maintaince
runs on a loop
breakdowns do not delay maintenance schedule
"""
while True:
yield self.env.timeout(21)
# time for maintenance
print(f'{self.env.now} - time for service')
if self.task is None:
# already processing a breakdown
print( "-------already shutdown ")
else:
self.shut_down()
# do maintenance
yield self.env.timeout(2)
print(f'{self.env.now} - finished service')
# restart machaine
self.startup()
def wait_for_breakdown(self):
"""
Creates a one time breakdown
"""
print(f'{self.env.now} - breakdow clock started')
try:
yield self.env.timeout(random.randint(4,10))
# time for a breakdown
self.breakdown = None
print(f'{self.env.now} - breakdown')
# shutdown and fix machine
self.shut_down()
yield self.env.timeout(7)
# machine fixed, start it back up
print(f'{self.env.now} - breakdow fixed')
self.startup()
except simpy.Interrupt as i:
print(f'{self.env.now} - breakdow clock stopped')
env = simpy.Environment()
machine = Machine(env)
env.run(100)