联合甘特图绘制
Creato il: 18 gennaio 2025
Creato il: 18 gennaio 2025
Understanding resource scheduling
The user wants a Gantt chart for machines T1..T9 and AGV1..AGV3, incorporating job, machine, and machinetime data. The focus is on verifying and illustrating completion times across various resources.
Mapping the schedule
The user's goal is to integrate AGV usage into a Gantt chart with a vertical layout: T1..T9 at the top and AGV1..AGV3 at the bottom, showing resource intervals.
Crafting the draw function
I'm thinking of a Python function to integrate AGV and machine schedules in a Gantt chart. The y-axis spans T1..T9 and AGV1..AGV3, with Gantt bars for each resource's usage.
Mapping the function
I’m organizing a function to draw a combined schedule for machines and AGVs, with the y-axis spanning 0..12, listing machines and AGVs. Adding Gantt bars for operations to visualize resource usage.
Drawing the schedule
I'm piecing together a plan to plot a unified resources schedule. The y-axis will list machines and AGVs, with Gantt bars showing operation and AGV usage times.
Labeling and plotting
I'm crafting a Gantt chart function to plot machine and AGV schedules, labeling job indices, and adjusting for Chinese output. This involves drawing Gantt bars and fine-tuning axis setups.
Mapping the function
I’m detailing a Python function to plot AGV and machine schedules using matplotlib, labeling job indices, and ensuring Chinese output. This involves drawing Gantt bars and adjusting axis setups.
Crafting the scheduling function
I’m thinking through a function to align with the user’s request, drawing T1..T9 and AGV1..AGV3, while addressing the y-axis labeling discrepancy in matplotlib. Progress is evident in the granularity.
Thought about resource scheduling visualization,持续 23 秒
下面给出一个示例函数思路,用于在同一幅图中画出「机床 + AGV」的联合甘特图。该示例思路参考了你已有的 draw
函数,但将“机床”和“AGV”的调度信息统一放在一张图上。请根据自己的实际数据结构(例如:AGV的开始时间、结束时间、调度顺序等)进行适当修改。
f.caculate()
的返回结果)中获取每个 AGV 在什么时间段为哪个工件服务,并将这些时间段绘制在对应的 AGV 那几行上(y 值)。plt.barh()
(水平条形图) 或者和之前一样的 plt.bar(..., orientation='horizontal')
来画甘特条。下面的示例函数假设:
f.caculate(job, machine, machine_time)
或其他过程已经能够返回每道工序在对应机床的 (start_time, end_time)
,以及 AGV 的 (start_time, end_time, job_id, agv_id)
等信息。machine_intervals
和 agv_intervals
两个列表来分别存储机床和 AGV 的调度区段,你需要根据自己的逻辑把这些区段提取出来(或在 caculate
函数内生成)。请根据自己的数据结构进行修改和对接。
import matplotlib.pyplot as plt import numpy as np def draw_joint_schedule(self, job, machine, machine_time): """ 绘制机床 + AGV 联合甘特图 job : 工序对应的工件编号列表,比如 [2, 4, 3, ...] machine : 工序对应的机床编号列表,比如 [2, 4, 5, ...] (这里编号从1开始) machine_time: 工序对应的加工时长列表,比如 [8, 4, 5, ...] 需要你根据自己的代码逻辑,补充/修改获取机床与 AGV 的时间区间,并进行可视化。 """ # ----------------------------------------------------------------------- # 1. 根据已有函数/调度结果计算各资源的开工时间、完工时间 # 这里假设你已有这样一个函数或返回结构: # C_finish, (list_M, list_S, list_W), (road, road_m, road_j) = self.caculate(job, machine, machine_time) # 其中: # list_M[i] 表示第 i 道工序在哪个机床 (或 y 值), # list_S[i] 表示第 i 道工序的开始时间, # list_W[i] 表示第 i 道工序的持续时间(加工时长), # 具体含义要跟你的代码对应。 # ----------------------------------------------------------------------- C_finish, Lp, ro = self.caculate(job, machine, machine_time) list_M, list_S, list_W = Lp[0], Lp[1], Lp[2] # 分别是机床编号、开工时间、持续时间 # ----------------------------------------------------------------------- # 2. 准备联合绘图所需要的数据 # (1)机床区间 machine_intervals: [(start, end, machine_id, job_id, operation_index), ...] # (2)AGV 区间 agv_intervals: [(start, end, agv_id, job_id, transport_index), ...] # # 这里的构造只是一个示例,需要你根据自己的实际数据来做。 # ----------------------------------------------------------------------- machine_intervals = [] count_job_op = np.zeros((1, self.job_num), dtype=np.int64) # 记录每个工件是第几道工序 for i in range(len(job)): m_id = list_M[i] # 机床编号(注意是否从0开始 or 从1开始) s_t = list_S[i] # 该工序开始时间 dura = list_W[i] # 该工序持续时间 e_t = s_t + dura # 该工序结束时间 j_id = job[i] count_job_op[0, j_id - 1] += 1 # 工序计数:工件 j_id 的第几道工序 # 将机床加工区间添加进 machine_intervals # machine_id 用于在甘特图 Y 轴绘制时区分是哪台机床 # operation_index 用于在可视化时标注“工件.第几道工序” machine_intervals.append( (s_t, e_t, m_id, j_id, count_job_op[0, j_id - 1]) ) # ----------------------------------------------------------------------- # AGV 调度信息通常包含: 哪个工件在什么时间段由哪台 AGV 运输 # 假设你已经在 ro 等结构中拿到了 AGV 的行驶时间段 start/end, # 这里我们做一个简化示例:假设 ro 中包含了每个 AGV 的路径及时间信息。 # 你需要自己从 ro 或者其他变量里把 AGV 的 (start, end, agv_id, job_id) 整理出来。 # ----------------------------------------------------------------------- agv_intervals = [] # 假设 ro[3] (或者其他位置) 里存储了 AGV 调度区间信息,格式自行定义 # 这里仅演示一个形式 # for record in ro_agv: # # record = (start_time, end_time, agv_id, job_id) # agv_intervals.append(record) # 如果你暂时没有 AGV 的详细区间,可直接从已有路径 road, road_m, road_j 等中分析时间段, # 也可以用随机或伪数据做测试。 # ----------------------------------------------------------------------- # ----------------------------------------------------------------------- # 3. 正式开始绘图 # ----------------------------------------------------------------------- fig, ax = plt.subplots(figsize=(12, 6)) # 画布大小可自行调整 # 绘制机床的甘特条 for interval in machine_intervals: s_t, e_t, m_id, j_id, op_i = interval # y轴:机床编号 m_id。假设 m_id=1 ~ 9 对应 y=1 ~ 9 # 可能你的 m_id 原本是从 0 开始,需要做 +1 处理 # 这里假设 machine_id 就是 1 ~ 9 y_val = m_id # 宽度 width = e_t - s_t # 在 y=y_val 处画一条 bar,跨度是 [s_t, e_t] plt.barh(y=y_val, width=width, left=s_t, height=0.5, align='center', color='white', edgecolor='black') # 在条形上标注文字 “工件ID.工序序号” plt.text(s_t + width/10, y_val, f'J{j_id}.{op_i}', va='center', ha='left', color='black', fontsize=9) # 绘制 AGV 的甘特条 # 假设 AGV 的编号是 1~3,则它们在 y 轴上可以放在 10, 11, 12 这三行 for interval in agv_intervals: s_t, e_t, agv_id, j_id = interval y_val = self.machine_num + agv_id # 例如 machine_num=9, agv_id=1 => y=10 width = e_t - s_t plt.barh(y=y_val, width=width, left=s_t, height=0.5, align='center', color='lightgray', edgecolor='black') # 标注 “AGV#: 工件ID” plt.text(s_t + width/10, y_val, f'AGV{agv_id}-J{j_id}', va='center', ha='left', color='black', fontsize=9) # ----------------------------------------------------------------------- # 4. 绘制完工时间的虚线 # ----------------------------------------------------------------------- plt.plot([C_finish, C_finish], [0, 0], c='black', linestyle='-.', label=f'完工时间: {C_finish}') # ----------------------------------------------------------------------- # 5. 设置坐标轴信息 # ----------------------------------------------------------------------- # Y 轴刻度:1~9 表示机床 T1~T9, 10~12 表示 AGV1~AGV3 y_ticks = list(range(1, self.machine_num+1)) + \ list(range(self.machine_num+1, self.machine_num + self.agv_num + 1)) y_labels = [f"T{i}" for i in range(1, self.machine_num+1)] + \ [f"AGV{i}" for i in range(1, self.agv_num+1)] plt.yticks(y_ticks, y_labels) # X 轴范围稍微放大一点 plt.xlim(0, C_finish * 1.1) # Y 轴范围 plt.ylim(0.5, self.machine_num + self.agv_num + 0.5) # 坐标轴字体、标签等 font_title = {'weight': 'bold', 'size': 16} font_label = {'weight': 'bold', 'size': 12} plt.xlabel("时间 (min)", font_label) plt.ylabel("资源编号", font_label) plt.title("机床 + AGV 联合调度甘特图", font_title) plt.legend(loc='upper right', prop={'family': 'SimHei', 'size': 10}) plt.grid(axis='x', linestyle=':', color='gray', alpha=0.5) # 仅在 x 轴上加网格线 plt.tight_layout() plt.show()
获取 AGV 区间
agv_intervals
列表。agv_intervals.append((start_time, end_time, agv_id, job_id))
坐标刻度与标签
y=1
对应 T1,那么越大的 y 值会显示在图的下方。plt.gca().invert_yaxis()
)或在设置 yticks 时做一个反转的操作。不过一般甘特图都是 0 在最下面,数字越大越往上,这一点可以按你自己的偏好来做。其他细节
color
参数。job_id
的奇偶来区分),或者加一个 color map。caculate()
或者在遗传算法中拿到的 AGV 运输区间数据,来填充 agv_intervals
的部分。Breaking down the dataset
I’m extracting the AGV intervals from the dataset, which includes time coordinates, machine IDs, and textual descriptions.
Pinpointing AGV routes
I'm thinking through how ro[0] and ro[1] represent AGV routes, with ro[0][0] showing x-coordinates and ro[1][0] detailing y-coordinates, suggesting movement patterns and destinations.
Assessing coordinates and routes
Mapping out how AGVs navigate a 2D plane with specific paths and coordinates, while also considering the enumeration of multiple AGV routes from the dataset.
Crafting AGV intervals
I'm identifying the times and machine IDs for each AGV from ro[0] and ro[1] to integrate into a Gantt chart. This involves extracting meaningful intervals for visualization.
Mapping sequential AGV movements
I'm piecing together AGV intervals by examining times and station sequences for each AGV, focusing on consecutive time-slot pairs to understand their station transitions.
Outlining visualization options
I'm considering different ways to represent AGV intervals in a Gantt chart: using bars for travel times, indicating station stays, or combining both to enrich the visualization's utility.
Crafting a function
I'm sketching a function to draw a joint schedule, parsing machine and AGV intervals from ro, and mapping these onto a Gantt chart with designated Y-axis labels for clarity.
Mapping AGV activity
I'm focusing on illustrating AGV busy times on a Gantt chart, using colored bars with specific labels for clarity, while mapping textual strings to identify jobs.
Thought about joint scheduling plot,持续 20 秒
下面给你一个示例思路,展示如何根据你给出的 ro
数据,提取并绘制「机床+AGV」的联合甘特图。示例代码中会演示:
job, machine, machine_time
等)中取得机床的甘特区间;ro
中提取 AGV 的“使用区间”,在同一张图里用水平条把 AGV 的忙碌时间段也表示出来;注意:
- 你的
ro
里,ro[0]
、ro[1]
、ro[2]
各自包含 3 个子列表(或字符串),看起来对应 3 台 AGV 的调度路线。- 通常,
ro[0][i]
表示第i
台 AGV 不同时刻的时间节点(如开始、到达、离开等),ro[1][i]
表示第i
台 AGV 在对应时刻所处的“地点”或“机床编号/装载台/卸载台”编号,ro[2][i]
则是文本描述。- 在甘特图的角度,我们更关心的是:在什么时间段内 AGV1 (或 AGV2、AGV3) 处于忙碌(运输)状态。
- 下述示例中,我将 AGV 的“占用”简单地视为“从某一时刻到下一时刻都在忙”,画一个水平条在
AGV1
那一行(或AGV2
,AGV3
)。- 具体你要如何区分“AGV 是在路上”还是“停在某台机床等待”等,需要你根据自己实际的调度逻辑去决定。这里给出的是最基础的做法。
import matplotlib.pyplot as plt import numpy as np def draw_joint_schedule(self, job, machine, machine_time, ro): """ 使用 机床调度数据 + ro(AGV路线数据),绘制联合甘特图: 横轴:时间/min 纵轴:上面是 T1, T2, ..., T9,下面是 AGV1, AGV2, AGV3. """ # ============================================================= # 1) 先从 (job, machine, machine_time) 中获取机床甘特区间 # —— 假设你已有 self.caculate(job, machine, machine_time) # 会返回 (C_finish, (list_M, list_S, list_W), ro),其中: # list_M[i]: 第 i 道工序使用的机床编号(1~machine_num) # list_S[i]: 该工序开始时间 # list_W[i]: 该工序持续时间 # ============================================================= C_finish, Lp, _ = self.caculate(job, machine, machine_time) list_M, list_S, list_W = Lp # 分别是 机床编号, 开始时间, 持续时间 # 记录机床的区间 (start, end, machine_id, job_id, operation_index) machine_intervals = [] count_job_op = np.zeros((1, self.job_num), dtype=np.int64) for i in range(len(job)): m_id = list_M[i] # 机床编号(注意是 1-based 还是 0-based) s_t = list_S[i] # 开始时间 dura = list_W[i] # 加工时长 e_t = s_t + dura j_id = job[i] count_job_op[0, j_id - 1] += 1 # 工序计数:工件 j_id 的第几道工序 machine_intervals.append( (s_t, e_t, m_id, j_id, count_job_op[0, j_id - 1]) ) # ============================================================= # 2) 再解析 ro, 得到每台 AGV 的(忙碌)区间 # ro 的结构: # ro[0] = [ [AGV1 的时间序列], [AGV2 的时间序列], [AGV3 的时间序列] ], # ro[1] = [ [AGV1 的地点序列], [AGV2 的地点序列], [AGV3 的地点序列] ], # ro[2] = [ AGV1的文字描述, AGV2的文字描述, AGV3的文字描述 ] # # 可能 ro[0][0] = [0, 0, 4, 9, 13, ... 61], # ro[1][0] = [0, 0, 9, 9, 8, ... 0] # 表示 AGV1 在这些时间点,地点发生了变化。 # # 简单做法:只要时间在 [t_k, t_{k+1}],我们就认为 AGV 忙碌(或在运输)。 # ============================================================= agv_intervals = [] # 这里假设你有 3 台 AGV for agv_id in range(self.agv_num): time_list = ro[0][agv_id] # 某台AGV的时间序列 # place_list = ro[1][agv_id] # 对应地点/机床编号,如果你需要可以用它 # 遍历 time_list,相邻两时间之间,AGV 都是“忙碌”的 for idx in range(len(time_list) - 1): start_t = time_list[idx] end_t = time_list[idx+1] # 如果两个时间相同,可能表示瞬时动作(如 0->0),可自行筛除 if end_t > start_t: agv_intervals.append((start_t, end_t, agv_id+1)) # agv_id+1 表示 AGV 编号(从 1 开始) # ============================================================= # 3) 开始在同一张图里绘制 # 纵坐标顺序希望是 T1..T9..AGV1..AGV3(上到下) # 在 matplotlib 默认坐标系中,y=1 会在下边,y=12 在上边。 # 如果想让 T1 在上,就得么“反转”y轴,或对 y 做个转换。 # 这里演示最简单的方法:让 T1=1, T2=2, ..., T9=9, AGV1=10,11,12 ... # 再通过 invert_yaxis() 让图上下颠倒。 # ============================================================= fig, ax = plt.subplots(figsize=(12, 6)) # (a) 绘制机床甘特 for interval in machine_intervals: s_t, e_t, m_id, j_id, op_i = interval y_val = m_id # 假设机床 m_id 就是 1~9 width = e_t - s_t # 在 y=y_val 画个 bar plt.barh( y=y_val, # 对应机床 y 值 width=width, # 条形宽度 = 加工时长 left=s_t, # 条形开始位置 = 开始时间 height=0.5, # 条形高度 color='white', edgecolor='black' ) # 在条形上写 工件.工序 plt.text( s_t + width/10, y_val, f'J{j_id}.{op_i}', va='center', ha='left', fontsize=8, color='black' ) # (b) 绘制 AGV 甘特 # 我们让 AGV1 在 y=10, AGV2=11, AGV3=12 # 所以 agv_id = 1 => y=10; agv_id = 2 => y=11; agv_id = 3 => y=12 for (start_t, end_t, agv_id) in agv_intervals: y_val = self.machine_num + agv_id # machine_num=9 => AGV1=10, AGV2=11, AGV3=12 width = end_t - start_t plt.barh( y=y_val, width=width, left=start_t, height=0.5, color='lightblue', # 和机床区分 edgecolor='black' ) # 标注 “AGV i” plt.text( start_t + width/10, y_val, f'AGV{agv_id}', va='center', ha='left', fontsize=8, color='black' ) # (c) 绘制完工时间的竖虚线 plt.axvline(x=C_finish, color='red', linestyle='--', label=f'C_finish={C_finish}') # ============================================================= # 4) 设置坐标轴和标题 # ============================================================= # Y 轴:1..9 => T1..T9, 10..12 => AGV1..AGV3 y_ticks = list(range(1, self.machine_num+1)) + \ list(range(self.machine_num+1, self.machine_num+self.agv_num+1)) y_labels = [f"T{i}" for i in range(1, self.machine_num+1)] + \ [f"AGV{i}" for i in range(1, self.agv_num+1)] plt.yticks(y_ticks, y_labels) # 如果想让 T1 在图的最上方,可以反转 y 轴 plt.gca().invert_yaxis() plt.xlim(0, C_finish*1.1) plt.ylim(self.machine_num+self.agv_num+0.5, 0.5) # 这里也可以自己微调 plt.xlabel("时间 (min)", fontweight='bold') plt.ylabel("机床 / AGV 资源", fontweight='bold') plt.title("机床+AGV 联合甘特图 (示例)", fontsize=14, fontweight='bold') plt.legend(loc='upper right', prop={'size': 10}) plt.grid(axis='x', linestyle=':', color='gray', alpha=0.5) plt.tight_layout() plt.show()
提取机床加工区间
self.caculate(job, machine, machine_time)
,得到 (C_finish, (list_M, list_S, list_W), ro)
;list_M[i]
是机床编号,list_S[i]
、list_W[i]
分别是工序的开始时间与持续时间;machine_intervals
,格式为 (start_time, end_time, machine_id, job_id, 第几道工序)
。提取 AGV 忙碌区间
ro
有 3 个子列表(分别对应 3 台 AGV);ro[0][0] = [0, 0, 4, 9, ...]
表示第 1 台 AGV 在若干个时间点上发生状态改变;time_list[idx]
和 time_list[idx+1]
,构造一个区间 (start_t, end_t, agv_id)
;表示这个 AGV 在 [start_t, end_t]
期间是忙碌的。ro[1][agv_id]
(地点信息) 来区分“AGV 处于运动”还是“AGV 等待”还是“空闲”,从而在甘特图上画不同的颜色或做更精细的区分。上面只是示例演示。在同一张图上绘制
T1 ~ T9
放在 y=1..9
;1 ~ 3
放在 y=10..12
;plt.barh()
画出时间跨度(甘特条),再 text
标注一些信息;plt.gca().invert_yaxis()
翻转 Y 轴。如何区分更多细节
ro[1][agv_id]
(地点序列)、ro[2][agv_id]
(文字描述)自行解析,把对应的文字标注到条形上。(start_t, end_t)
的这段标记为“AGV1: 从 T9 运送到 T8 (工件4)”。place_list[idx]
和 place_list[idx+1]
,结合 ro[2][agv_id]
的描述,拼出文本,然后在 plt.text()
里显示。job/machine/machine_time + ro
数据中分别提取机床调度和 AGV 使用区间,再在同一个甘特图里绘制出来。ro[0]
, ro[1]
的含义(时间节点、地点节点)来定义 AGV 在每段时间区间内的状态。如果相邻时间点确实表示 AGV 始终在忙碌中,那么就可以像示例那样一段一段地画。