問題

这是我画甘特路径图的函数: def draw(self, job, machine, machine_time): # 画图
C_finish, Lp, ro =self.caculate(job, machine, machine_time)
list_M, list_S, list_W = Lp[0], Lp[1], Lp[2]

figure,ax=plt.subplots()
road, road_m, road_j = ro[0], ro[1], ro[2]
for i in range(len(road)):
x = road[i]
y = road_m[i]
plt.scatter(x, y, c='black')
plt.plot(x, y, linestyle='--', label = f'agv{i+1}') # agv的路径

count = np.zeros((1,self.job_num),dtype=np.int64)
for i in range(len(job)): # 每一道工序画一个小框
count[0, job[i]-1] += 1
plt.bar(x=list_S[i], bottom=list_M[i], height=0.5, width=list_W[i], orientation="horizontal",color='white',edgecolor='black')
plt.text(list_S[i]+list_W[i]/32,list_M[i] + .05, f'{job[i]}.{count[0, job[i]-1]}', color='black',fontsize=10,weight='bold')#12是矩形框里字体的大小,可修改
plt.plot([C_finish,C_finish],[0,0],c='black',linestyle='-.',label='完工时间:%d'% (C_finish))#用虚线画出最晚完工时间

font1={'weight':'bold','size':22} # 汉字字体大小,可以修改
plt.xlabel("加工时间",font1)
plt.title("甘特路径图",font1,loc='right')
plt.ylabel("机床",font1)

font2 = {'weight':'bold','size':10} # 汉字字体大小,可以修改
char = ''
i = 0
for cha in road_j:
char += (f'agv{i+1}:' + cha + '\n') # 各个agv的运行文字叙述
i += 1
plt.title(char, font2, loc='left')


index_ls = [f'T{k}' for k in range(self.machine_num + 1)] # 纵坐标内容
scale_ls = [k for k in range(self.machine_num + 1)] # 纵坐标刻度
plt.yticks(scale_ls, index_ls)
plt.axis([0,C_finish*1.1,0,self.machine_num+1])
plt.tick_params(labelsize = 22) # 坐标轴刻度字体大小,可以修改
labels=ax.get_xticklabels()
[label.set_fontname('SimHei')for label in labels]
plt.legend(prop={'family' : ['SimHei'], 'size' : 10}) # 标签字体大小,可以修改
plt.xlabel("加工时间",font1)
plt.show()
这是主函数:import pandas as pd
import data
from fjsp import fj
from DLTS_GA import GA

# path = './data.xlsx'
# df = pd.read_excel(path, sheet_name = '加工情况')
# df1 = pd.read_excel(path, sheet_name = '物流情况')
path = 'Ex1.csv'
path2 = 'Ex2.csv'
df = pd.read_csv(path)
df1 = pd.read_csv(path2)
parm_data = data.deal(df,df1) # 调度数据

job_num = 4 # 工件数量
machine_num = 9 # 机器数量
agv_num = 3 # agv数量

generation = 10 # 迭代次数
popsize = 10 # 种群规模
Pcmax = .6 # 最大交叉概率
Pcmin = .3 # 最小交叉概率
Pmmax = .1 # 最大变异概率
Pmmin = .05 # 最小变异概率

# ... 现有参数代码 ...
small_tabu_iter = 20 # 小规模禁忌搜索迭代次数
large_tabu_iter = 50 # 大规模禁忌搜索迭代次数
tabu_length = 7 # 禁忌表长度

f = fj(job_num, machine_num, agv_num, parm_data)
# 柔性模块编码
parm_ga = [generation, popsize, Pcmax, Pcmin, Pmmax, Pmmin, small_tabu_iter, large_tabu_iter, tabu_length]
# 遗传算法参数
parm_fj = [f, parm_data] # 柔性模块和数据
ga = GA(parm_ga, parm_fj) # 遗传模块
job, machine, machinetime, result = ga.ga_total()
print('************\njob:', job)
print('************\nmachine:', machine)
print('************\nmachinetime:', machinetime)
# 遗传算法结果
C_finish, _, ro = f.caculate(job, machine, machinetime)
print('************\nresult:',result)

print('************\n验证:',C_finish)
f.draw_change(result) # 完工时间随迭代次数的变化
f.draw(job, machine, machinetime)
# 甘特路径图
然后我打印出来的结果分别是:************
job: [2, 4, 3, 4, 1, 3, 1, 4, 4, 1, 1, 2, 3, 4, 1, 3]
************
machine: [2, 4, 5, 4, 4, 1, 1, 2, 7, 6, 1, 9, 8, 3, 8, 8]
************
machinetime: [8, 4, 5, 5, 8, 15, 14, 4, 10, 5, 10, 5, 8, 11, 9, 6]
************
result: [[0, np.int64(71)], [1, np.int64(67)], [2, np.int64(64)], [3, np.int64(62)], [4, np.int64(61)], [5, np.int64(61)], [6, np.int64(61)], [7, np.int64(61)], [8, np.int64(61)], [9, np.int64(61)], [10 np.int64(61)]]
************
验证: 61
然后现在我想根据这些结果画一个资源联合调度方案,横坐标是时间/min,纵坐标是机床及AGV编号,从上之下是T1、T2....T9、AGV1、AGV2、AGV3这样。画资源联合调度方案的函数可以怎么写?

思考

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的开始时间、结束时间、调度顺序等)进行适当修改。


关键思路

  1. 时间轴(x 轴): 仍然是从 0 到最终完工时间(或略大于完工时间)。
  2. 资源轴(y 轴): 需要从上到下先标示机床 T1 ~ T9(共 9 个),然后再标示 AGV1、AGV2、AGV3(共 3 个)。
    • 如果总共有 9 台机床 + 3 个 AGV,那么 y 轴可以设置为 0 ~ 12(或 1 ~ 12)。
    • 例如,最上面一行 y=1 对应 T1,最下面 y=12 对应 AGV3。
  3. 绘制机床调度: 类似之前的做法,遍历每道工序 (job, machine) 时,在对应的机床行(y 值)画出横条(bar),横坐标从开工时间到完工时间。
  4. 绘制 AGV 调度: 需要从你的代码(或者 f.caculate() 的返回结果)中获取每个 AGV 在什么时间段为哪个工件服务,并将这些时间段绘制在对应的 AGV 那几行上(y 值)。
  5. 可视化细节:
    • 可以使用 plt.barh() (水平条形图) 或者和之前一样的 plt.bar(..., orientation='horizontal') 来画甘特条。
    • 在机床上方/条形中标注工件信息,在 AGV 上方/条形中标注所运输的工件信息。
    • 注意设置不同的颜色区分机床加工与 AGV 运输(比如机床条形可以用白色边框黑色字体,AGV 条形可以用浅灰色或其他颜色等)。

示例代码

下面的示例函数假设:

  • f.caculate(job, machine, machine_time) 或其他过程已经能够返回每道工序在对应机床的 (start_time, end_time),以及 AGV(start_time, end_time, job_id, agv_id) 等信息。
  • 示例中我用 machine_intervalsagv_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()

使用说明

  1. 获取 AGV 区间

    • 在你的代码中,一般会有一段计算 AGV 运输时间的逻辑。你需要像机床加工一样,拿到每一次运输的开始时间、结束时间、AGV 编号以及服务的工件或工序信息,然后放入 agv_intervals 列表。
    • 形如:agv_intervals.append((start_time, end_time, agv_id, job_id))
    • 注意 AGV 的 y 值要放在机床下面,例如机床编号 19 对应 y=19,AGV13 对应 y=1012 等。
  2. 坐标刻度与标签

    • 由于你想从上至下看到 T1..T9, AGV1..AGV3,实际在 Matplotlib 中,如果我们按照 y=1 对应 T1,那么越大的 y 值会显示在图的下方。
    • 如果想纯视觉上“上面是 T1,下面是 AGV3”,可以把 y 轴反转(plt.gca().invert_yaxis())或在设置 yticks 时做一个反转的操作。不过一般甘特图都是 0 在最下面,数字越大越往上,这一点可以按你自己的偏好来做。
  3. 其他细节

    • 可以根据需要在条形中或者条形上方写上更详细的信息,比如开始/结束时间、哪道工序等。
    • 如果想把机床的条形和 AGV 的条形显示成不同颜色,可以像示例里那样分别设置 color 参数。
    • 如果想更好区分不同工件,也可以为不同工件设置不同颜色(例如按 job_id 的奇偶来区分),或者加一个 color map。

小结

  • 核心思路是在一张图上,把机床调度AGV 调度分别画成甘特条,并把机床和 AGV 放到同一条 y 轴刻度上。
  • 以上示例主要给出了绘图框架,你需要根据自己在 caculate() 或者在遗传算法中拿到的 AGV 运输区间数据,来填充 agv_intervals 的部分。
  • 如果在调度模型里还涉及到等待区缓冲区等其他资源,你也可以类似地在下方再加几行对应的资源区间,从而得到更完整的「资源联合甘特图」。

問題

这是我的ro值:[[[0, 0, 4, np.int64(9), np.int64(13), np.int64(21), np.int64(25), np.int64(36), np.int64(40), np.int64(49), np.int64(49), np.int64(58), np.int64(61)], [0, 0, 3, np.int64(8), np.int64(12), np.int64(16), np.int64(20), np.int64(26), np.int64(30), np.int64(35), np.int64(35), np.int64(43), np.int64(49), np.int64(55), np.int64(61)], [0, 0, 3, 6, 11, 14, 20, 27, 30, 36, 36, np.int64(42), np.int64(48), np.int64(48), np.int64(51)]], [[0, 0, 9, 9, 8, 8, 3, 3, 8, 8, 8, 1, 0], [0, 0, 1, 1, 4, 4, 1, 1, 4, 4, 4, 4, 0, 8, 0], [0, 0, 1, 0, 2, 1, 7, 2, 1, 7, 7, 7, 1, 1, 0]], ['装载台运送4材料到T9,到T9运送o41到T8,到T8运送o42到T3,到T3运送o43到T8,到T8运送o44到T8,运送o34到卸载台', '装载台运送1材料到T1,到T1运送o11到T4,到T4运送o12到T1,到T1运送o13到T4,到T4运送o14到T4,运送o35到卸载台,到T8运送o35到卸载台', '装载台运送3材料到T1,回到装载台运送2材料到T2,到T1运送o31到T7,到T2运送o21到T1,到T7运送o32到T7,到T7运送o33到T1,运送o32到卸载台']]

思考

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」的联合甘特图。示例代码中会演示:

  1. 如何从现有的机床加工信息(即 job, machine, machine_time 等)中取得机床的甘特区间;
  2. 如何从 ro 中提取 AGV 的“使用区间”,在同一张图里用水平条把 AGV 的忙碌时间段也表示出来;
  3. 最终在一张图上看到所有机床 (T1 ~ T9) 和所有 AGV (AGV1 ~ AGV3) 的时间使用情况。

注意

  • 你的 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()

关键解释

  1. 提取机床加工区间

    • 调用 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, 第几道工序)
  2. 提取 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 等待”还是“空闲”,从而在甘特图上画不同的颜色或做更精细的区分。上面只是示例演示。
  3. 在同一张图上绘制

    • 机床 T1 ~ T9 放在 y=1..9
    • AGV 1 ~ 3 放在 y=10..12
    • plt.barh() 画出时间跨度(甘特条),再 text 标注一些信息;
    • 如果想让 “T1 在最上面,AGV3 在最下面”,就使用 plt.gca().invert_yaxis() 翻转 Y 轴。
  4. 如何区分更多细节

    • 如果你想在 AGV 条上标注“从哪里到哪里”或者“运输的是哪个工件”,可以结合 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 始终在忙碌中,那么就可以像示例那样一段一段地画。
  • 最后,如果想美化或者进一步区分“AGV 处于运输状态 / 等待状态 / 空闲状态”,都可以在这个基础上修改——例如用不同颜色、不同行高、或者增加更多条形。

分享這個問答