""" Machine shop example Covers: - Interrupts - Resources: PreemptiveResource Scenario: A workshop has *n* identical machines. A stream of jobs (enough to keep the machines busy) arrives. Each machine breaks down periodically. Repairs are carried out by one repairman. The repairman has other, less important tasks to perform, too. Broken machines preempt theses tasks. The repairman continues them when he is done with the machine repair. The workshop works continuously. A machine has two processes: working implements the actual behaviour of the machine (producing parts). break_machine periodically interrupts the working process to simulate the machine failure. The repairman’s other job is also a process (implemented by other_job). The repairman itself is a PreemptiveResource with a capacity of 1. The machine repairing has a priority of 1, while the other job has a priority of 2 (the smaller the number, the higher the priority). В мастерской есть *n* идентичных станков. Поступает поток заданий (достаточных для того, чтобы машины были заняты). Каждая машина периодически выходит из строя. Ремонт выполняется одним ремонтником. У ремонтника есть и другие, менее важные задачи, которые он должен выполнять. Сломанные машины прерывают такие задания. Мастер по ремонту продолжает их, когда заканчивает ремонт машины. Мастерская работает непрерывно. Машина состоит из двух процессов: рабочий реализует фактическое поведение машины (изготовление деталей). Поломаный станок периодически прерывает рабочий процесс, чтобы имитировать сбой машины break_machine. Другая работа ремонтника - это тоже процесс (реализованный other_job). Ремонтник сам по себе является прерываемым ресурсом с пропускной способностью 1. Ремонт машины имеет приоритет 1, в то время как другая работа имеет приоритет 2 (здесь чем меньше число, тем выше приоритет). """ import random import simpy RANDOM_SEED = 4217 PT_MEAN = 10.0 # Avg. processing time in minutes PT_SIGMA = 2.0 # Sigma of processing time MTTF = 300.0 # Mean time to failure in minutes BREAK_MEAN = 1 / MTTF # Param. for expovariate distribution REPAIR_TIME = 30.0 # Time it takes to repair a machine in minutes JOB_DURATION = 30.0 # Duration of other jobs in minutes NUM_MACHINES = 10 # Number of machines in the machine shop WEEKS = 4 # Simulation time in weeks SIM_TIME = WEEKS * 7 * 24 * 60 # Simulation time in minutes def time_per_part(): # Return actual processing time for a concrete part. return random.normalvariate(PT_MEAN, PT_SIGMA) def time_to_failure(): # Return time until next failure for a machine. return random.expovariate(BREAK_MEAN) num_repair = 0 class Machine(object): """ A machine produces parts and my get broken every now and then. If it breaks, it requests a *repairman* and continues the production after the it is repaired. A machine has a *name* and a number of *parts_made* thus far. """ def __init__(self, env, name, repairman): self.env = env self.name = name self.parts_made = 0 self.broken = False # Start "working" and "break_machine" processes for this machine. self.process = env.process(self.working(repairman)) env.process(self.break_machine()) def working(self, repairman): """ Produce parts as long as the simulation runs. While making a part, the machine may break multiple times. Request a repairman when this happens. """ global num_repair while True: # Start making a new part done_in = time_per_part() while done_in: try: # Working on the part start = self.env.now yield self.env.timeout(done_in) done_in = 0 # Set to 0 to exit while loop. except simpy.Interrupt: self.broken = True done_in -= self.env.now - start # How much time left? # Request a repairman. This will preempt its "other_job". with repairman.request(priority=1) as req: yield req num_repair +=1 yield self.env.timeout(REPAIR_TIME) self.broken = False # Part is done. self.parts_made += 1 def break_machine(self): # Break the machine every now and then. while True: yield self.env.timeout(time_to_failure()) if not self.broken: # Only break the machine if it is currently working!! self.process.interrupt() def other_jobs(env, repairman): # The repairman's other (unimportant) job. while True: # Start a new job done_in = JOB_DURATION while done_in: # Retry the job until it is done. # It's priority is lower than that of machine repairs. with repairman.request(priority=2) as req: yield req try: start = env.now yield env.timeout(done_in) done_in = 0 except simpy.Interrupt: done_in -= env.now - start # Setup and start the simulation print('Manufacturing model') random.seed(RANDOM_SEED) # This helps reproducing the results # Create an environment and start the setup process env = simpy.Environment() repairman = simpy.PreemptiveResource(env, capacity=1) machines = [Machine(env, 'Machine_%d' % i, repairman) for i in range(NUM_MACHINES)] env.process(other_jobs(env, repairman)) # Execute! env.run(until=SIM_TIME) # Analyis/results print('Machine shop results after %s weeks' % WEEKS) for machine in machines: print('%s made %d parts.' % (machine.name, machine.parts_made)) print('Number of repairs',num_repair)