simpy 仿真 模拟
一个车间内有100台相同的机器,每台机器正常运行时每小时能固定创造3元的净利润,但平均每小时损坏一次。而一个熟练修理工修复一台机器平均需0.5小时,一个不熟练修理工修复一台机器平均需3小时。以上时间均服从指数分布。设一名熟练修理工一小时工资为6元,一名不熟练修理工一小时工资为2元。车间每天工作8小时。试求该车间应设多少名熟练修理工和不熟练修理工,使每周(6天)的总净利润最大?
import numpy as np
from sko.GA import GA
import pandas as pd
import matplotlib.pyplot as plt
import random
import simpy
Days= 10 # Simulation time in weeks
RANDOM_SEED = 42
PT_MEAN = 10.0 # Avg. processing time in minutes
PT_SIGMA = 2.0 # Sigma of processing time
MTTF = 60 # Mean time to failure in minutes
BREAK_MEAN = 0.017 # Param. for expovariate distribution
REPAIR_WAGE1 = 0*6 * 8 * Days # 第一种修理工的小时工资
REPAIR_WAGE2 = 0 *2 * 8 * Days # 第二种修理工的小时工资
REPAIR_TIME1 = 30.0 # 第一种修理工修理一台机器所需时间(分钟)
REPAIR_TIME2 = 180.0 # 第二种修理工修理一台机器所需时间(分钟)
JOB_DURATION = 10 # Duration of other jobs in minutes
NUM_MACHINES = 10 # Number of machines in the machine shop
SIM_TIME =8*60*Days # Simulation time in minutes
def time_per_part():
"""Return actual processing time for a concrete part."""
return 60
def time_to_failure():
"""Return time until next failure for a machine."""
return random.expovariate(BREAK_MEAN)
def time_per_part():
"""Return actual processing time for a concrete part."""
return 60
def time_to_failure():
"""Return time until next failure for a machine."""
return random.expovariate(BREAK_MEAN)
class Machine(object):
def __init__(self, env, name, repairman1,repairman2):
self.env = env
self.name = name
self.parts_made = 0
self.broken = False
self.process = env.process(self.working(repairman1,repairman2))
env.process(self.break_machine())
def working(self, repairman1, repairman2):
"""Produce parts as long as the simulation runs.
While making a part, the machine may break multiple times.
Request a repairman when this happens.
"""
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 as interrupt:
self.broken = True
done_in -= self.env.now - start # How much time left?
# Ignore the interrupt and continue with the next iteration
# Handle multiple interrupts
while isinstance(interrupt.cause, simpy.Interrupt):
interrupt = interrupt.cause
if self.broken: # Add this condition to skip repair process
continue
# Request a repairman. This will preempt its "other_job".
if not repairman1.count - repairman1.capacity == 0:
with repairman1.request(priority=1) as req:
yield req
yield self.env.timeout(REPAIR_TIME1)
self.broken = False
else:
with repairman2.request(priority=1) as req:
yield req
yield self.env.timeout(REPAIR_TIME2)
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, repairman1,repairman2):
while True:
done_in = JOB_DURATION
while done_in:
with repairman1.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
with repairman2.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
def problem(parameter):
random.seed(RANDOM_SEED) # This helps reproducing the result
x1,x2= parameter # 将参数赋值给 x1 和 x2
env = simpy.Environment() # 创建环境对象
repairman1 = simpy.PreemptiveResource(env, capacity=x1)
repairman2 = simpy.PreemptiveResource(env, capacity=x2)
machines = [Machine(env, 'Machine %d' % i, repairman1,repairman2) for i in range(NUM_MACHINES)]
env.process(other_jobs(env, repairman1,repairman2))
env.run(until=SIM_TIME)
for machine in machines:
print('%s made %d parts.' % (machine.name, machine.parts_made))
money = 0
for machine in machines:
money += machine.parts_made * 3
money -= (x1 *REPAIR_WAGE1) # 第一种修理工的工资
money -= (x2 *REPAIR_WAGE2) # 第二种修理工
return money
print(problem([100,100]))
# problem_dimension = 2 # 两种修理工 # 每种修理工的数量范围
# # 使用遗传算法求解问题
# ga = GA(func=problem, n_dim=problem_dimension, size_pop=50, max_iter=100, lb=[1,1], ub=[10,10],precision=1)
# best_solution, best_fitness = ga.run()
# print("Best solution:", best_solution)
# print("Best fitness:", best_fitness)
# Y_history = pd.DataFrame(ga.all_history_Y)
# fig, ax = plt.subplots(2, 1)
# ax[0].plot(Y_history.index, Y_history.values, '.', color='red')
# Y_history.min(axis=1).cummin().plot(kind='line')
# plt.show()
不知道你这个问题是否已经解决, 如果还没有解决的话:首先,我们需要确定应该雇佣多少名熟练修理工和不熟练修理工来实现最优解。
假设我们雇佣a名熟练修理工和b名不熟练修理工。
根据题目中的条件,我们可以计算出每天机器的平均损坏次数,即100台机器每天平均损坏100次。 修理一台机器平均需要0.5小时的时间,其中熟练修理工和不熟练修理工的修理时间分别为0.5小时和3小时。修理时间服从指数分布。
我们需要计算出不同修理工的修理效率和工资开支,以及每周的总净利润。
首先计算不同修理工的修理效率: - 熟练修理工的修理效率 = 修理工每小时的工作时间 / 修理时间 - 不熟练修理工的修理效率 = 修理工每小时的工作时间 / 修理时间
然后计算不同修理工的工资开支: - 熟练修理工的工资开支 = 熟练修理工的小时工资 * 熟练修理工的工作时间 - 不熟练修理工的工资开支 = 不熟练修理工的小时工资 * 不熟练修理工的工作时间
工作时间 = 每天的工作小时数 * 每周的工作天数 = 8 * 6 = 48小时
工作效率和工资开支计算完毕后,我们可以计算每周的总净利润: 总净利润 = 每天机器的净利润 * 每台机器的正常运行小时数 - 工资开支
每天机器的净利润 = 每台机器正常运行小时数 * 每小时的净利润 = 3元 每台机器正常运行小时数 = 每天的工作小时数 - 平均每台机器的损坏次数 * 平均修理时间 平均每台机器的损坏次数 = 每台机器的正常运行小时数 / 平均修理时间
将上述公式代入,可以得到总净利润的表达式。 用a和b来表示雇佣的熟练修理工和不熟练修理工的数量,我们的目标是使总净利润最大化。
提出问题时并没有给出任何限制条件,因此我们需要进行进一步的假设和限制条件,以便能够得出具体的解决方案。
由于题目没有给出修理时间服从指数分布的具体参数,我们可以假设修理时间服从指数分布的参数为1,这样方便我们进行计算和模拟。
在这个假设下,我们可以编写代码来模拟雇佣不同数量的熟练修理工和不熟练修理工的情况,计算总净利润,并找到最优解。
以下是具体的解决方案的伪代码:
```python
best_profit = 0 # 最大的总净利润 best_a = 0 # 最优解对应的熟练修理工数量 best_b = 0 # 最优解对应的不熟练修理工数量
for a in range(1, 100): # 遍历熟练修理工数量 for b in range(1, 100): # 遍历不熟练修理工数量 # 计算熟练修理工和不熟练修理工的工作效率 proficient_efficiency = 0.5 / 0.5 # 熟练修理工的工作效率 unskilled_efficiency = 0.5 / 3 # 不熟练修理工的工作效率
# 计算熟练修理工和不熟练修理工的工资开支
proficient_salary = 6 * 48 * a # 熟练修理工的工资开支
unskilled_salary = 2 * 48 * b # 不熟练修理工的工资开支
# 计算每周的总净利润
daily_profit = 3
normal_hours = 8 - 1 # 每台机器正常运行的小时数,减去平均每台机器的损坏次数
average_repair_time = 0.5 # 平均修理时间,假设为0.5小时
average_damage_times = normal_hours / average_repair_time # 平均每台机器的损坏次数
normal_hours = normal_hours * 100 # 将小时转换为分钟,为了模拟修理时间服从指数分布
total_profit = 0 # 每周的总净利润
# 模拟每天的损坏和修理过程
for day in range(6): # 模拟6天
for machine in range(100): # 100台机器
for repair_time in range(int(average_damage_times * 60) + 1): # 每台机器需要的修理时间
# 使用指数分布模拟修理时间
repair_time = -math.log(random.random()) * repair_time
if repair_time <= normal_hours:
# 机器正常运行时的净利润
total_profit += daily_profit
else:
# 使用熟练修理工还是不熟练修理工修理机