优化算法|遗传算法求解考虑AGV转运的柔性作业车间调度问题

前言

之前两篇推文分别介绍了遗传算法和蚁群优化算法求解作业车间调度问题,本篇推文将介绍柔性作业车间问题的一种变体:考虑AGV转运的柔性作业车间调度问题

感兴趣的可以先去阅读之前的推文,了解作业车间调度问题以及求解思路:

优化算法|遗传算法求解作业车间调度问题(Python代码)

优化算法|蚁群优化算法求解作业车间调度问题(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()		

算法结果

若有运筹优化建模及算法定制需求,欢迎联系我们私聊沟通

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eternal1995

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值