使用Python画作业调度甘特图

一、背景

之前研究过遗传算法解决经典作业调度问题柔性作业调度问题,并将调度结果使用matlab画甘特图(用任意多颜色表示任意多工件),还是挺有成就感的。但是使用Matlab画出甘特图后没法很好地整合到如网站等类似生产环境。最近恰好被一个爱好者咨询到了,且自己最近因为工作原因也在学习Python,也就想是否可以通过Python画出优雅的甘特图。还真有类似的解决方案:Matplotlib方案实用代码Python(七)甘特图画法 和 Plotly方案
Gantt Charts in Python

二、方案比较

Matplotlib方案

  • Matplotlib相对比较成熟,文案显示比较优雅,但缺点是没法很好地以时间为单位显示作业调度过程,没法很好地整合到生产环境。

Plotly方案

  • Plotly是也是Python的一个开源库,有单独的甘特图API支持,比较方便。另外,其作业调度的时间显示比较灵活,可以很好整合到生产环境。该类库也有个缺点:原生API没法在作业调度信息上很好地显示作业调度信息,如工件A的第三道工序的耗费时间。幸好,可以通过layout.annotations配置来解决这个问题。

三、实现方案

以柔性作业调度问题用例MK01的最佳调度图

在这里插入图片描述

未使用annotations进行配置修改画图效果

在这里插入图片描述

Matlab方案甘特图

在这里插入图片描述

三、代码清单

import time
import plotly as py
import plotly.figure_factory as ff

# x轴, 对应于画图位置的起始坐标x
# start, time, of, every, task, , //每个工序的开始时间
n_start_time = [0, 0, 2, 6, 0, 0, 3, 4, 10, 13, 4, 3, 10, 6, 12, 4, 5, 6, 14, 7, 9, 9, 16, 7, 11, 14, 15, 12, 16, 17,
                16, 15, 18, 19, 19, 20, 21, 20, 22, 21, 24, 24, 25, 27, 30, 30, 27, 25, 28, 33, 36, 33, 30, 37, 37]
# length, 对应于每个图形在x轴方向的长度
# duration, time, of, every, task, , //每个工序的持续时间
n_duration_time = [6, 2, 1, 6, 4, 3, 1, 6, 3, 3, 2, 1, 2, 1, 2, 1, 1, 3, 2, 2, 6, 2, 1, 4, 4, 2, 6, 6, 1, 2, 1, 4, 6, 1,
                   6, 1, 1, 1, 5, 6, 1, 6, 4, 3, 6, 1, 6, 3, 2, 6, 1, 4, 6, 1, 3]

# y轴, 对应于画图位置的起始坐标y
# bay, id, of, every, task, , ==工序数目,即在哪一行画线
n_bay_start = [1, 5, 5, 1, 2, 4, 5, 5, 4, 4, 3, 0, 5, 2, 5, 0, 0, 3, 5, 0, 3, 0, 5, 2, 2, 0, 3, 1, 0, 5, 4, 2, 1, 0, 5,
               0, 0, 2, 0, 3, 2, 1, 2, 0, 1, 0, 3, 4, 5, 3, 0, 2, 5, 2, 0]

# 工序号,可以根据工序号选择使用哪一种颜色
# n_job_id = [1, 9, 8, 2, 0, 4, 6, 9, 9, 0, 6, 4, 7, 1, 5, 8, 3, 8, 2, 1, 1, 8, 9, 6, 8, 5, 8, 4, 2, 0, 6, 7, 3, 0, 2, 1, 7, 0, 4, 9, 3, 7, 5, 9, 5, 2, 4, 3, 3, 7, 5, 4, 0, 6, 5]
n_job_id = ['B', 'J', 'I', 'C', 'A', 'E', 'G', 'J', 'J', 'A', 'G', 'E', 'H', 'B', 'F', 'I', 'D', 'I', 'C', 'B', 'B',
            'I', 'J', 'G', 'I', 'F', 'I', 'E', 'C', 'A', 'G', 'H', 'D', 'A', 'C', 'B', 'H', 'A', 'E', 'J', 'D', 'H',
            'F', 'J', 'F', 'C', 'E', 'D', 'D', 'H', 'F', 'E', 'A', 'G', 'F']

op = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']

colors = ('rgb(46, 137, 205)',
          'rgb(114, 44, 121)',
          'rgb(198, 47, 105)',
          'rgb(58, 149, 136)',
          'rgb(107, 127, 135)',
          'rgb(46, 180, 50)',
          'rgb(150, 44, 50)',
          'rgb(100, 47, 150)',
          'rgb(58, 100, 180)',
          'rgb(150, 127, 50)')

millis_seconds_per_minutes = 1000 * 60
start_time = time.time() * 1000

job_sumary = {}


# 获取工件对应的第几道工序
def get_op_num(job_num):
    index = job_sumary.get(str(job_num))
    new_index = 1
    if index:
        new_index = index + 1
    job_sumary[str(job_num)] = new_index
    return new_index


def create_draw_defination():
    df = []
    for index in range(len(n_job_id)):
        operation = {}
        # 机器,纵坐标
        operation['Task'] = 'M' + str(n_bay_start.__getitem__(index) + 1)
        operation['Start'] = start_time.__add__(n_start_time.__getitem__(index) * millis_seconds_per_minutes)
        operation['Finish'] = start_time.__add__(
            (n_start_time.__getitem__(index) + n_duration_time.__getitem__(index)) * millis_seconds_per_minutes)
        # 工件,
        job_num = op.index(n_job_id.__getitem__(index)) + 1
        operation['Resource'] = 'J' + str(job_num)
        df.append(operation)
    df.sort(key=lambda x: x["Task"], reverse=True)
    return df


def draw_prepare():
    df = create_draw_defination()
    return ff.create_gantt(df, colors=colors, index_col='Resource',
                           title='mk01的一个最佳调度', show_colorbar=True,
                           group_tasks=True, data=n_duration_time,
                           showgrid_x=True, showgrid_y=True)


def add_annotations(fig):
    y_pos = 0
    for index in range(len(n_job_id)):
        # 机器,纵坐标
        y_pos = n_bay_start.__getitem__(index)

        x_start = start_time.__add__(n_start_time.__getitem__(index) * millis_seconds_per_minutes)
        x_end = start_time.__add__(
            (n_start_time.__getitem__(index) + n_duration_time.__getitem__(index)) * millis_seconds_per_minutes)
        x_pos = (x_end - x_start) / 2 + x_start

        # 工件,
        job_num = op.index(n_job_id.__getitem__(index)) + 1
        text = 'J(' + str(job_num) + "," + str(get_op_num(job_num)) + ")=" + str(n_duration_time.__getitem__(index))
        # text = 'T' + str(job_num) + str(get_op_num(job_num))
        text_font = dict(size=14, color='black')
        fig['layout']['annotations'] += tuple(
            [dict(x=x_pos, y=y_pos, text=text, textangle=-30, showarrow=False, font=text_font)])


def draw_fjssp_gantt():
    fig = draw_prepare()
    add_annotations(fig)
    py.offline.plot(fig, filename='fjssp-gantt-picture')


if __name__ == '__main__':
    draw_fjssp_gantt()

四、相关文档

  • 10
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Python可以使用Matplotlib和Plotly两种库来车间调度甘特图。其中,Matplotlib相对比较成熟,文案显示比较优雅,但无法很好地以时间为单位显示作业调度过程,也不易整合到生产环境。而PlotlyPython的一个开源库,有单独的甘特图API支持,可以很方便地甘特图,并且时间显示比较灵活,可以较好地整合到生产环境。 以下是使用Plotly库实现车间调度甘特图的方案: 1. 准备工作:安装Plotly库和相关依赖,导入所需模块。 2. 提供作业调度信息:准备好作业调度信息,包括工件、工序、开始时间和结束时间等。 3. 创建甘特图使用Plotly的Gantt Charts API创建甘特图对象。 4. 配置甘特图:设置甘特图的样式,如纵轴和横轴的标签、大小、颜色等。 5. 添加作业调度信息:使用Plotly的add_trace方法,根据作业调度信息添加相应的条形图。 6. 显示甘特图使用Plotly的show方法显示甘特图。 以下是代码示例: ```python import plotly.express as px # 准备作业调度信息,具体格式根据实际数据结构进行调整 job_scheduling_info = [ {'工件': 'A', '工序': '1', '开始时间': '2022-01-01 08:00:00', '结束时间': '2022-01-01 10:00:00'}, {'工件': 'A', '工序': '2', '开始时间': '2022-01-01 10:30:00', '结束时间': '2022-01-01 12:00:00'}, {'工件': 'B', '工序': '1', '开始时间': '2022-01-01 09:00:00', '结束时间': '2022-01-01 11:00:00'}, {'工件': 'B', '工序': '2', '开始时间': '2022-01-01 11:30:00', '结束时间': '2022-01-01 14:00:00'}, # 其他作业调度信息... ] # 创建甘特图对象 fig = px.timeline(job_scheduling_info, x_start="开始时间", x_end="结束时间", y="工件", color="工序") # 配置甘特图样式 fig.update_layout( title="车间调度甘特图", xaxis_title="时间", yaxis_title="工件", height=600, # 图片高度 width=800, # 图片宽度 ) # 显示甘特图 fig.show() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值