前言
之前两篇推文分别介绍了遗传算法和蚁群优化算法求解作业车间调度问题,本篇推文将介绍柔性作业车间问题的一种变体:考虑AGV转运的柔性作业车间调度问题。
感兴趣的可以先去阅读之前的推文,了解作业车间调度问题以及求解思路:
优化算法|蚁群优化算法求解作业车间调度问题(Python代码实现)
问题描述
考虑AGV转运的柔性作业车间调度问题可描述如下:有若干工件需要经过多道工序加工,每道工序可选择的加工机器不一致,所有工件的工序均需要通过AGV进行转运,故决策变量为每个工件的每道工序分配加工机床和AGV,实现总完工时间最小的目标。
问题的假设条件为:
1)不存在机器设备故障问题,整个加工装配过程所有机器正常运行;
2)在初始时刻所有机器和AGV处于待工作状态,初始工序的准备时间为0;
3)AGV电量充足,不考虑亏电等异常情况;
4)所有AGV 性能一样,在所有加工机器之间搬运零件的速度相同;
5)同一时刻,每台机器只能同时加工一个工件;
6)同一时刻,任一工序只能由一台机床加工。
部分代码展示
读取数据
def preprocess(time_path, distance_path):
initial_sequence = []
time_matrix = []
with open(time_path, "r") as data:
# 第一行读取3个参数:工件数job_num,机器数machine_num,AGV数量 agv_num
total_jobs, total_machines, total_agv = re.findall('\S+', data.readline())
job_num, machine_num, agv_num = int(total_jobs), int(total_machines), int(total_agv)
job_id = 1
for key, line in enumerate(data):
if key >= job_num:
break
# 按空格分隔字符串
parsed_line = re.findall('\S+', line)
for j in range(int(parsed_line[0])):
initial_sequence.append(job_id)
i = 1
while i < len(parsed_line):
temp_list = []
number_operations = int(parsed_line[i])
for id_operation in range(1, number_operations+1):
machine_id_for_current_operation = int(parsed_line[i + 2 * id_operation - 1])
process_time = int(parsed_line[i + 2 * id_operation])
temp_list.append(machine_id_for_current_operation)
temp_list.append(process_time)
i += 1 + 2 * number_operations
time_matrix.append(temp_list)
job_id += 1
编码与解码
编码分为两部分:工序编码以及机器编码。
工序编码:编码方式采用基于工序编码全排列的编码方式进行编码,编码的长度等于所有工件的工序之和。编码顺序代表工序被加工的优先级。
初始种群中,对初始工序随机排序,对每个工序随机选取可选用的机器进行加工。
def initial_solution(self):
operation_sequence = np.copy(self.initial_sequence)
np.random.shuffle(operation_sequence) # 初始工序随机排序
operation_sequence = operation_sequence.tolist()
machine_select = []
machine_time = []
for i in range(len(operation_sequence)):
P = self.machine_time_matrix[i] # 一行对应一个工序的加工信息
n_machine = [P[j] for j in range(0, len(P), 2)]
n_time= [P[j] for j in range(1, len(P), 2)]
index=np.random.randint(0,len(n_time),1) # 随机选择加工时间
machine_select.append(n_machine[index[0]]) # 提取对应时间的机床
machine_time.append(n_time[index[0]]) # 提取加工时间
return operation_sequence, machine_select, machine_time
绘制甘特图
def Gantt(self, job, operation_machine_processed, operation_start_time, operation_work_time, road, road_machine, road_job):
plt.rcParams['font.sans-serif'] = ['Times New Roman'] # 如果要显示中文字体,则在此处设为:SimHei
plt.rcParams['axes.unicode_minus'] = False # 显示负号
M = ['red', 'blue', 'yellow', 'orange', 'green', 'palegoldenrod', 'purple', 'pink', 'Thistle', 'Magenta',
'SlateBlue', 'RoyalBlue', 'Cyan', 'Aqua', 'floralwhite', 'ghostwhite', 'goldenrod', 'mediumslateblue',
'navajowhite', 'navy', 'sandybrown', 'moccasin']
Job_text = ['J' + str(i + 1) for i in range(100)]
Machine_text = ['M' + str(i + 1) for i in range(50)]
t = 0
k = 0
for k in range(self.vehicle_num):
for m in range(1, len(road[k]), 2):
plt.barh(k, width=road[k][m + 1] - road[k][m],
height=0.6,
left=road[k][m],
color=M[road_job[k][m // 2]-1],
edgecolor='black')
plt.text(x=road[k][m] + (road[k][m + 1] - road[k][m]) / 2 - 2,
y=k - 0.05,
s=Machine_text[road_machine[k][m]] + '-' + Machine_text[road_machine[k][m + 1]],
fontsize=5)
for inx in job:
plate_id = inx - 1
for operation_id in range(self.operation_num):
plt.barh(operation_machine_processed[plate_id][operation_id] + k + 1,
width=operation_work_time[plate_id][operation_id],
height=0.8, left=operation_start_time[plate_id][operation_id],
color=M[plate_id],
edgecolor='black')
plt.text(x=operation_start_time[plate_id][operation_id] + operation_work_time[plate_id][
operation_id] / 2 - 0.1,
y=operation_machine_processed[plate_id][operation_id] + k + 1,
s=Job_text[plate_id],
fontsize=12)
if operation_work_time[plate_id][operation_id] + operation_start_time[plate_id][operation_id] > t:
t = operation_work_time[plate_id][operation_id] + operation_start_time[plate_id][operation_id]
list = ['AGV' + str(i + 1) for i in range(self.vehicle_num)]
list1 = ['M' + str(_ + 1) for _ in range(self.machine_num)]
list.extend(list1)
plt.xlim(0, t)
plt.hlines(k + 0.4, xmin=0, xmax=t, color="black") # 横线
plt.title('Scheduling Gantt chart')
plt.ylabel('Machines')
plt.xlabel('Time(s)')
plt.show()
算法结果
若有运筹优化建模及算法定制需求,欢迎联系我们私聊沟通