|
|
import random
|
|
|
from turtledemo.paint import switchupdown
|
|
|
|
|
|
from pfsp_simulated_annealing.machine import Machine
|
|
|
from pfsp_simulated_annealing.workpiece import Workpiece
|
|
|
|
|
|
|
|
|
class Simulate:
|
|
|
def __init__(self, n, m, p):
|
|
|
self.Wnum = n #声明一个整数变量Wnum,表示工件的数量。
|
|
|
self.Mnum = m #声明一个整数变量Mnum,表示机器的数量。
|
|
|
self.cost = [[0] * m for _ in range(n)] #声明一个二维整数数组cost,用于存储每个工件在每台机器上的加工时间。
|
|
|
for i in range(n):
|
|
|
for j in range(m):
|
|
|
self.cost[i][j] = p[i * m + j]
|
|
|
|
|
|
self.management = [[j for j in range(n)] for _ in range(m)] #声明一个二维整数数组management,用于存储工件的调度顺序。
|
|
|
self.Time = [[0] * n for _ in range(m)] #声明一个二维整数数组Time,用于存储每台机器上每个工件的开始加工时间,也就是调度顺序。
|
|
|
self.switchx = 0 #声明两个整数变量switchx和switchy,用于存储交换操作中的两个工件的索引。
|
|
|
self.switchy = 0
|
|
|
self.switchrow = 0
|
|
|
self.M = [Machine() for _ in range(m)] #声明一个Machine对象数组M,用于存储每台机器的信息。
|
|
|
self.W = [Workpiece() for _ in range(n)] #声明一个Workpiece对象数组W,用于存储每个工件的信息。
|
|
|
print(f"Simulate初始化")
|
|
|
self.print_data() #打印出来看看有没有错误
|
|
|
|
|
|
def random_reset(self): #其实就是初始化工件在每个机器上的调度顺序
|
|
|
"随机重置工件在每个机器上的调度顺序"
|
|
|
for i in range(self.Mnum): # 遍历每台机器
|
|
|
for j in range(self.Wnum): # 遍历工件
|
|
|
# 生成随机索引
|
|
|
x = random.randint(j, self.Wnum - 1)
|
|
|
# 交换
|
|
|
self.management[i][j], self.management[i][x] = self.management[i][x], self.management[i][j]
|
|
|
print("工件初始调度顺序 (management):")
|
|
|
for man in self.management:
|
|
|
print(man)
|
|
|
|
|
|
def roll_back(self):
|
|
|
"""交换管理矩阵中指定行的两个元素""" #根据保存的row,x,y,,把交换过的位置给交换回去
|
|
|
# 保存当前行、列的值
|
|
|
temp = self.management[self.switchrow][self.switchx]
|
|
|
# 交换元素
|
|
|
self.management[self.switchrow][self.switchx] = self.management[self.switchrow][self.switchy]
|
|
|
self.management[self.switchrow][self.switchy] = temp
|
|
|
|
|
|
def random_exchange(self): #找到下一个调度方案,并且每次只改变一台机器上的两个工件之间的调度顺序
|
|
|
"""随机交换两个工件在同一台机器的调度位置""" #同时还得记录是哪俩个交换了位置
|
|
|
random.seed() # 用于初始化随机数生成器
|
|
|
self.switchrow = random.randint(0, self.Mnum - 1)
|
|
|
self.switchx = random.randint(0, self.Wnum - 1)
|
|
|
self.switchy = random.randint(0, self.Wnum - 1)
|
|
|
#print(f"随机改变了第{self.switchrow}台机器,第{self.switchx}和{self.switchy}个工件之间的调度顺序")
|
|
|
# 交换工件位置
|
|
|
self.management[self.switchrow][self.switchx], self.management[self.switchrow][self.switchy] = \
|
|
|
self.management[self.switchrow][self.switchy], self.management[self.switchrow][self.switchx]
|
|
|
#print("随机交换后的管理信息:")
|
|
|
#for row in self.management:
|
|
|
# print(row)
|
|
|
|
|
|
|
|
|
def f(self):
|
|
|
#print("模拟一个车间调度系统中的调度过程,直到所有工件完成在所有机器上的处理")
|
|
|
rtime = 0 #记录总花费时间
|
|
|
while True:
|
|
|
#判断是否有工件加工完毕并且可以转移到下一台机器上
|
|
|
for i in range(self.Mnum):
|
|
|
current_piece = self.M[i].process() #获得当前这个机器正在处理的工件索引
|
|
|
if current_piece != self.Wnum - 1: #如果当前工件的索引不等于最后一个也就是这次测试的工件的数量
|
|
|
x = self.management[i][current_piece + 1] #得到这台机器下一个要处理的工件的号码
|
|
|
if self.M[i].left_time == 0 and self.W[x].left_time == 0 and self.W[x].being_processed == i - 1:
|
|
|
#当前这台机器的剩余加工时间为0 并且 这台机器的下一个要加工的工件的剩余加工时间为0
|
|
|
# 并且这台机器的下一个要加工的工件的现在停留在前一台机器上
|
|
|
#也就是说,当前机器空闲了,当前机器的下一个要加工的工件它刚好在前一台机器,并且在前一台工具那也已经加工完了,那这台机器就可以开始加工这个工件了
|
|
|
self.M[i].next_wp(self.cost[x][i]) #当前机器开始加工下一个工件,设置时间为下一个工件在那台机器上要耗费的时间
|
|
|
self.W[x].next_machine(self.cost[x][i]) #这个工件转移到下一台机器加工 因为加工顺序必须是从0 1 2 3 4 这样一台台排下去的
|
|
|
self.Time[i][current_piece + 1] = rtime #记录这台机器第几个工件的开始加工时间,因为current_price
|
|
|
|
|
|
|
|
|
#同时减少机器和工件的加工时间,每次都减1
|
|
|
for i in range(self.Mnum):
|
|
|
self.M[i].next_time()
|
|
|
|
|
|
for i in range(self.Wnum):
|
|
|
self.W[i].next_time()
|
|
|
|
|
|
flag = False #判断是否全部加工完毕
|
|
|
for i in range(self.Wnum):
|
|
|
if self.W[i].left_time != 0 or self.W[i].being_processed != self.Mnum - 1:
|
|
|
flag = True
|
|
|
break
|
|
|
|
|
|
if not flag:
|
|
|
#print(f"此次调度方案耗时:{rtime}")
|
|
|
return rtime + 1
|
|
|
rtime += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def output_data(self):
|
|
|
# 构建 management_str 字符串
|
|
|
management_str = []
|
|
|
for i in range(self.Mnum):
|
|
|
row = []
|
|
|
for j in range(self.Wnum):
|
|
|
row.append(str(self.management[i][j]))
|
|
|
management_str.append('\t'.join(row))
|
|
|
management_str = '\n'.join(management_str)
|
|
|
|
|
|
# 写入 management.txt 文件
|
|
|
file_name = "output/management.txt"
|
|
|
try:
|
|
|
with open(file_name, 'w', encoding='utf-8') as fw:
|
|
|
fw.write(management_str)
|
|
|
fw.flush()
|
|
|
print(f"写入文件 {file_name} 成功")
|
|
|
except IOError as e:
|
|
|
print(f"写入文件 {file_name} 时出错: {e}")
|
|
|
|
|
|
# 构建 time_str 字符串
|
|
|
time_str = []
|
|
|
for i in range(self.Mnum):
|
|
|
row = []
|
|
|
for j in range(self.Wnum):
|
|
|
row.append(f"{self.Time[i][j]}\t{self.Time[i][j] + self.cost[self.management[i][j]][i]}")
|
|
|
time_str.append('\t'.join(row))
|
|
|
time_str = '\n'.join(time_str)
|
|
|
|
|
|
# 写入 time.txt 文件
|
|
|
file_name = "output/time.txt"
|
|
|
try:
|
|
|
with open(file_name, 'w', encoding='utf-8') as fw:
|
|
|
fw.write(time_str)
|
|
|
fw.flush()
|
|
|
print(f"写入文件 {file_name} 成功")
|
|
|
except IOError as e:
|
|
|
print(f"写入文件 {file_name} 时出错: {e}")
|
|
|
|
|
|
def reset_for_new_round(self): #重置所有的参数
|
|
|
for i in range(self.Wnum):
|
|
|
self.W[i].reset()
|
|
|
for i in range(self.Mnum):
|
|
|
self.M[i].reset()
|
|
|
|
|
|
def print_data(self):
|
|
|
print(f"工件数量: {self.Wnum}")
|
|
|
print(f"机器数量: {self.Mnum}")
|
|
|
print("加工时间 (cost):")
|
|
|
for row in self.cost:
|
|
|
print(row)
|
|
|
print("工件调度顺序 (management):")
|
|
|
for man in self.management:
|
|
|
print(man)
|
|
|
print("开始加工时间 (Time):")
|
|
|
for row in self.Time:
|
|
|
print(row)
|
|
|
print("机器状态 (M):")
|
|
|
for machine in self.M:
|
|
|
print(machine)
|
|
|
print("工件状态 (W):")
|
|
|
for workpiece in self.W:
|
|
|
print(workpiece) |