lanmaoooo 3 months ago
parent 804faaa8f0
commit 3eb52f35e0

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MavenRunner">
<option name="jreName" value="11" />
</component>
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/pfsp_simulated_annealing.iml" filepath="$PROJECT_DIR$/.idea/pfsp_simulated_annealing.iml" />
</modules>
</component>
</project>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,21 @@
20 10
0 96 1 80 2 56 3 48 4 14 5 88 6 50 7 15 8 67 9 65
0 25 1 44 2 10 3 41 4 64 5 52 6 19 7 28 8 72 9 27
0 76 1 62 2 48 3 54 4 47 5 35 6 72 7 54 8 27 9 56
0 41 1 6 2 3 3 33 4 77 5 44 6 43 7 50 8 19 9 43
0 65 1 91 2 75 3 30 4 47 5 55 6 51 7 1 8 36 9 73
0 81 1 69 2 65 3 93 4 61 5 3 6 44 7 17 8 6 9 14
0 49 1 9 2 12 3 54 4 75 5 66 6 34 7 12 8 32 9 6
0 93 1 89 2 31 3 14 4 37 5 57 6 33 7 96 8 32 9 45
0 39 1 83 2 55 3 32 4 18 5 9 6 93 7 65 8 75 9 73
0 52 1 46 2 64 3 13 4 54 5 62 6 45 7 80 8 19 9 65
0 72 1 4 2 29 3 94 4 85 5 51 6 29 7 65 8 50 9 16
0 55 1 43 2 47 3 32 4 87 5 97 6 41 7 86 8 17 9 30
0 8 1 91 2 81 3 93 4 14 5 86 6 64 7 42 8 70 9 3
0 27 1 11 2 94 3 38 4 33 5 67 6 8 7 55 8 99 9 18
0 34 1 86 2 87 3 10 4 64 5 30 6 47 7 51 8 69 9 26
0 15 1 5 2 39 3 23 4 16 5 1 6 57 7 55 8 62 9 35
0 59 1 55 2 43 3 49 4 23 5 25 6 51 7 72 8 9 9 1
0 93 1 4 2 43 3 5 4 84 5 55 6 22 7 78 8 31 9 11
0 20 1 91 2 73 3 41 4 100 5 38 6 75 7 9 8 76 9 71
0 59 1 13 2 93 3 26 4 11 5 7 6 66 7 42 8 54 9 99

File diff suppressed because one or more lines are too long

@ -0,0 +1,92 @@
import numpy as np
import matplotlib.pyplot as plt
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
mylist = [] # 记录时间安排,两个一组表示开头结尾
labels = [] # 记录调度方案,用于产生不同的颜色
# 改进颜色生成函数
def get_color(m_str):
"对于不同的工件产生不同的RGB颜色"
num = int(m_str)
# 使用 matplotlib 的 colormap 生成更均匀的颜色
from matplotlib.cm import get_cmap
cmap = get_cmap('tab20') # 选择一个 colormap例如 'tab20'
return cmap(num % 20) # 确保 num 在 colormap 的范围内
try:
inputfile = open("output/time.txt", 'r', encoding='utf-8')
while True:
templine = inputfile.readline()
if templine == '':
break
templine = templine.strip('\t\n')
templist = templine.split('\t')
templist1 = []
for item in templist:
templist1.append(int(item))
mylist.append(templist1)
inputfile.close()
except FileNotFoundError:
print("Error: 文件 time.txt 不存在")
exit()
try:
inputfile = open("output/management.txt", 'r', encoding='utf-8')
while True:
templine = inputfile.readline()
if templine == '':
break
templine = templine.strip('\t\n')
templist = templine.split('\t')
labels.append(templist)
inputfile.close()
except FileNotFoundError:
print("Error: 文件 management.txt 不存在")
exit()
y = np.array(mylist)
for i in range(len(mylist)):
for j in range(int(len(mylist[i])/2)):
left = y[i][2 * j]
width = y[i][2 * j + 1] - left
if width > 0: # 确保宽度为正值
plt.barh(i + 1, width, left=left, color=get_color(labels[i][j]))
plt.xlabel("time")
plt.ylabel("machine")
plt.title("甘特图") # 设置甘特图的标题
# 添加图例
unique_labels = list(set([item for sublist in labels for item in sublist]))
colors = [get_color(label) for label in unique_labels]
plt.legend(handles=[plt.Rectangle((0, 0), 1, 1, color=get_color(label)) for label in unique_labels], labels=unique_labels)
plt.show()
mylist = []
try:
inputfile = open("data/trace.txt", 'r', encoding='utf-8')
while True:
templine = inputfile.readline()
if templine == '':
break
templine = templine.strip('\t\n')
templist = templine.split('\t')
for item in templist:
mylist.append(int(item))
inputfile.close()
except FileNotFoundError:
print("Error: 文件 trace.txt 不存在")
exit()
plt.plot(mylist, linewidth=1)
plt.title("目标函数变化图", fontsize=20)
plt.xlabel("x", fontsize=10)
plt.ylabel("f", fontsize=14)
plt.tick_params(axis='both', labelsize=10)
plt.show()

@ -0,0 +1,27 @@
class Machine:
def __init__(self):
self.processing = -1 # 当前正在处理的工件索引 -1代表空闲 比如索引是12调度顺序中12位置上的值比如是7那就意味着第13个加工的工件是7号工件
self.left_time = 0 # 剩余加工时间 0时表示该工件在该机器上的处理已完成。
def left_time(self):
"""获取当前剩余处理时间"""
return self.left_time
def process(self):
"""获取当前正在处理的工件索引"""
return self.processing
def next_time(self):
"""减少剩余处理时间(模拟时间流逝)"""
if self.left_time > 0:
self.left_time -= 1
def next_wp(self, time):
"""切换到下一个工件并设置处理时间"""
self.processing += 1
self.left_time = time
def reset(self):
"""重置机器状态"""
self.processing = -1
self.left_time = 0

@ -0,0 +1,10 @@
13 16 9 11 14 19 1 15 8 6 3 12 18 2 4 5 10 17 0 7
13 9 16 14 11 8 15 12 1 3 2 4 18 19 10 6 17 5 0 7
9 16 14 11 8 13 3 15 1 2 12 4 6 10 17 0 5 7 19 18
13 8 3 11 9 14 2 1 15 4 10 17 16 0 12 18 6 7 19 5
3 8 9 15 11 2 10 0 13 17 16 4 14 18 6 19 12 7 1 5
3 2 0 10 17 15 9 8 16 4 14 13 19 6 18 11 7 5 12 1
0 2 17 15 16 9 10 19 6 14 13 4 3 11 8 5 18 12 1 7
17 0 16 9 19 15 10 4 14 6 11 8 5 18 13 7 2 1 3 12
17 9 0 15 4 10 19 14 8 5 6 18 11 7 13 2 16 3 1 12
9 4 0 15 14 19 8 5 18 17 7 11 10 13 6 3 16 2 1 12

@ -0,0 +1,10 @@
0 27 27 86 86 138 138 193 193 227 227 286 286 311 311 326 326 365 365 414 414 455 455 463 463 483 483 559 559 624 624 705 705 777 777 870 870 966 966 1059
27 38 138 184 184 239 239 325 325 368 368 451 451 456 463 554 554 598 598 604 604 666 666 757 757 848 848 861 861 865 865 874 874 878 878 947 966 1046 1059 1148
184 248 248 291 325 412 412 459 459 514 514 608 608 611 611 650 650 660 666 714 714 795 795 870 874 886 886 915 915 958 1046 1102 1102 1167 1167 1198 1198 1291 1291 1364
608 646 646 678 678 711 711 743 743 756 756 766 766 820 820 861 861 884 884 914 915 1009 1009 1014 1014 1063 1102 1150 1150 1243 1364 1405 1405 1459 1459 1473 1473 1499 1499 1592
711 788 788 806 806 860 884 900 900 987 987 1034 1034 1119 1150 1164 1164 1197 1197 1281 1281 1304 1304 1351 1351 1415 1415 1515 1515 1590 1590 1601 1601 1615 1615 1652 1652 1716 1716 1777
788 832 1034 1069 1164 1252 1252 1303 1303 1358 1358 1359 1359 1421 1421 1430 1430 1455 1455 1510 1510 1540 1540 1607 1607 1614 1614 1680 1680 1718 1718 1815 1815 1872 1872 1875 1875 1961 1961 2013
1252 1302 1302 1374 1374 1396 1396 1453 1455 1506 1506 1551 1551 1580 1614 1680 1680 1714 1714 1761 1761 1769 1769 1820 1820 1863 1863 1904 1904 1997 1997 2041 2041 2116 2116 2180 2180 2199 2199 2232
1396 1474 1474 1489 1506 1578 1578 1658 1680 1722 1722 1777 1777 1842 1842 1843 1843 1894 1894 1906 1906 1992 1997 2062 2062 2079 2116 2125 2125 2180 2232 2328 2328 2382 2382 2410 2410 2460 2460 2502
1474 1505 1658 1677 1677 1744 1777 1839 1843 1879 1879 1929 1929 1983 1983 2052 2062 2137 2137 2143 2502 2534 2572 2648 2648 2665 2665 2697 2697 2796 2796 2823 2823 2832 2832 2851 2851 2923 2923 2993
1677 1742 1879 1952 1952 2017 2017 2052 2052 2078 2078 2177 2177 2250 2250 2264 2648 2719 2719 2730 2730 2775 2775 2805 2805 2821 2821 2839 2955 2961 2961 3004 3004 3005 3005 3061 3061 3088 3088 3091

@ -0,0 +1,163 @@
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):
"""交换管理矩阵中指定行的两个元素""" #根据保存的rowxy把交换过的位置给交换回去
# 保存当前行、列的值
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)

@ -0,0 +1,74 @@
import math
import random
from pfsp_simulated_annealing.simulate import Simulate
import os
def main():
print(os.getcwd())
# 读取输入文件
try:
with open('data/input.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
# 提取 n 和 m
n, m = map(int, lines[0].split())
# 提取 p
p = []
for line in lines[1:]:
data = list(map(int, line.split()))
# 跳过机器序号从索引1开始每隔两个元素提取一个元素加工时间
for j in range(1, m + 1):
p.append(data[2 * j - 1]) # 提取加工时间
print(f"工件数n: {n}, 机器数m: {m}") # 打印 n 和 m
print(f"p: {p}") # 打印 p
except FileNotFoundError:
print("文件未找到!")
return
# 初始化模拟退火
sim = Simulate(n, m, p)
sim.random_reset()
current_t = 1061109567
count, count1 = 0, 0
trace = []
T = 10000.0
i = 0
while True:
print(f"当前第{i}次计算, 当前耗时{current_t}")
T *= 0.999
sim.random_exchange()
sim.reset_for_new_round()
new_t = sim.f()
if new_t < current_t: #如果耗时更少,那就接收
current_t = new_t
count = 0
count1 = 0
else:
# 使用math.exp计算接受概率
if random.random() < math.exp((current_t - new_t) / T):
if current_t == new_t:
count1 += 1
else:
count1 = 0
current_t = new_t
count = 0
else:
sim.roll_back()
count += 1
if current_t == new_t:
count1 += 1
if count > 100 or count1 > 100: #count > 100 || count1 > 100作为终止条件。
print("总完成时间为:", current_t)
sim.output_data()
with open('data/trace.txt', 'w') as f:
f.write('\t'.join(map(str, trace)))
return
trace.append(current_t)
i += 1
if __name__ == "__main__":
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

@ -0,0 +1,27 @@
class Workpiece:
def __init__(self):
self.being_processed = -1 # 当前正在处理的机器索引(-1表示尚未开始处理被哪台机器加工
self.left_time = 0 # 剩余处理时间 初始为0 为0时表示该工件在当前机器上的处理已完成。
def being_pro(self):
"""获取当前正在处理的机器索引"""
return self.being_processed
def left_time(self):
"""获取剩余处理时间"""
return self.left_time
def next_time(self):
"""减少剩余处理时间"""
if self.left_time > 0:
self.left_time -= 1
def next_machine(self, time):
"""转移到下一台机器并设置处理时间因为加工顺序必须是从0 1 2 3 4 这样一台台排下去的"""
self.being_processed += 1
self.left_time = time
def reset(self):
"""重置工件状态"""
self.being_processed = -1
self.left_time = 0
Loading…
Cancel
Save