Python实现拣货员拣货的时间长短分析

Posted hhh_Moon_hhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python实现拣货员拣货的时间长短分析相关的知识,希望对你有一定的参考价值。

Python实现拣货员拣货的时间长短分析

一、需求的描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
另外,这里还有一个堵塞的情况;

在这里插入图片描述
最后,一些参数如下所示:
在这里插入图片描述

二、我们对于需求的分析

对于一个问题,首先应该分析清楚他是要我们做什么的!!

首先,我们应该定义一个类(员工类),然后,每一个员工就是对应于一个类的实例对象了啦。也就是说,我们这里需要定义30个实例对象的。

接着,我们在员工类里面给对象设置一些属性,比如说:1、开始工作的时间;2、需要到达的位置,还有需要拣出来多少货物;3、等待(堵塞)了多长的时间。 等等

然后,在类里面实现一些函数,比如:1、计算行走的时间;2、计算拣货的时间;3、计算堵塞的时间;4、打印员工的相关拣货信息;5、计算一个员工总共的耗时时间。 等等

最后,在 main 函数中执行代码计算最终的结果。

在这里需要强调一下:1、每一个员工的信息(拣货的信息)需要用户进行输入进去的;2、注意每个员工都有可能会遇到堵塞的情况;3、一个员工工作的总时间为 行走时间 + 拣货时间 + 堵塞时间。

然后呢,我们写一个文件来定义员工类,

接着写一个文件来实现时间的计算,

然后,在主函数之中调用实现时间的计算的文件来进行实现功能。

三、员工类的实现

直接上代码,因为,我在代码里面写了十分详细地注释,相信大家是可以看懂得啦。(看代码里面的注释一定是可以理解的)
员工类的实现的源代码:


# 自定义一个模块,这个文件中定义一个员工类,每一个员工都是该类的一个实例对象


class Employee(object):

    """
    员工类
    """

    def __init__(self, start_time, goods_message, taboo_table, speed=0.9, choose=1, wait_time=0):
        """
        初始化一个实例对象
        :param start_time: 员工开始出发的时间
        :param goods_message: 员工需要达到的货架以及所需要取多少货品
        :param taboo_table: 禁忌表,记录每个员工何时在哪一个通道内部,何时进入、出去,
        刚开始,禁忌表为空,后面利用函数进行添加
        :param speed: 恒定的行走速度,0.9
        :param choose: 恒定值,挑选商品,1
        :param wait_time: 等待的时间,即就是堵塞的时间,先赋值为 0 ,后续再更改
        """
        self.start_time = start_time  # 开始出发的时间
        self.goods_message = goods_message  # 需要达到的货架以及所需要取多少货品
        """
        一个商品信息应该如下:[(x, r, y), goods_number]
        然后多个类似的列表会组成一个总的商品列表
        """
        self.taboo_table = taboo_table  # 禁忌表,记录何时在哪一个通道内部,何时进入、出去
        self.speed = speed
        self.choose = choose
        self.time_of_walk_and_choose = 0  # 先赋值为 0 ,后续再更改
        self.wait_time = wait_time  # 堵塞的时间,先赋值为 0 ,后续再更改
        self.the_total_of_the_time = 0  # 总的时间(包含了行走、等待或者说堵塞、拣货这三个时间),先赋值为 0 ,后续再更改
        self.time_of_walk = 0  # 走的总时间,先赋值为 0 ,后续再更改
        self.time_of_choose = 0  # 拣货的总时间,先赋值为 0 ,后续再更改


    def compute_walk_and_choose_time(self):
        """
        计算行走以及取货物的时间,此时尚未考虑堵塞的问题,将在后续的函数考虑
        :return: 空
        """
        x_list = []
        y_list = []
        for i in self.goods_message:
            x_list.append(i[0][0])
            # 获取到所有的要去的通道的编号
        for j in self.goods_message:
            if j[0][0] == max(x_list):  # 如果是在最后一个通道内的货架
                y_list.append(j[0][2])
                # 获取到最后一个通道内部的 y 坐标
        y = max(y_list)
        # 求出最后一个通道所需要达到的最远的 y 坐标
        if len(self.goods_message) % 2 == 0:
            # 如果商品信息的列表的长度是偶数,即就是说去偶数个货架
            distance = (max(x_list) - 1) * 3.2 + 1 + 20 * len(x_list)
            # d = (max(x) - 1) * 3.2 + 1 + 20 * n, n 为偶数
        else:
            distance = (max(x_list) - 1) * 3.2 + 1 + 20 * (len(x_list) - 1) + 1.2 * y
            # d = (max(x) - 1) * 3.2 + 1 + 20 * (n - 1) + 1.2 * y, n 为奇数
        time1 = distance / self.speed  # 计算行走的时间
        sum_goods_number = 0
        for k in self.goods_message:
            sum_goods_number += k[1]
        time2 = sum_goods_number * self.choose  # 挑拣商品的时间
        time_of_walk_and_choose = time1 + time2
        self.time_of_walk_and_choose = time_of_walk_and_choose
        # 将这个时间赋值给对象的属性记录下来
        self.time_of_walk = time1
        self.time_of_choose = time2
        # 分别记录下行走的时间以及拣货的时间


    def make_the_taboo_table(self):
        """
        生成禁忌表,
        记录每个员工何时在哪一个通道内部,何时进入、出去
        :return: 空
        """
        x_list = []
        for i in self.goods_message:
            x_list.append(i[0][0])
            # 获取到所有的要去的通道的编号
        x_list.sort()  # 从小到大排序
        if len(x_list) % 2 == 0:
            # 偶数个通道
            record_number = 0
            t1 = self.start_time  # 最开始初始化为开始的时间
            for n in range(len(x_list)):
                # 循环所有的通道
                if n == 0:
                    # 员工第一个进入的通道
                    dt1 = (1 + (x_list[n] - 1) * 3.2) / self.speed
                    # 走到通道的入口需要的时间
                else:
                    # 不是员工第一个进入的通道
                    dt1 = ((x_list[n] - x_list[n - 1]) * 3.2) / self.speed
                    # 走到通道的入口需要的时间
                sum_of_goods = 0
                for m in self.goods_message:
                    # 循环所有的货架
                    if m[0][0] == x_list[record_number]:
                        sum_of_goods += m[1]
                dt2 = (sum_of_goods * self.choose) + (20 / self.speed)  # 变化了的时间
                # 包含了 拣货 + 行走
                self.taboo_table[f'{x_list[record_number]}'] = [t1 + dt1, t1 + dt1 + dt2]
                # 进入时间为:初始时间 + 走到入口
                # 出去时间为:初始时间 + 走到入口 + 在通道内部的时间
                t1 = t1 + dt1 + dt2  # 重新对 t1 进行赋值
                record_number += 1  # 记录数字自加一
        else:
            # 通道个数为奇数
            record_number = 0
            t1 = self.start_time  # 最开始初始化为开始的时间
            # 这里初始化为最开始的时间
            for n in range(len(x_list) - 1):  # 最后一个需要单独处理啦
                # 循环所有的通道
                if n == 0:
                    # 员工第一个进入的通道
                    dt1 = (1 + (x_list[n] - 1) * 3.2) / self.speed
                    # 走到通道的入口需要的时间
                else:
                    # 不是员工第一个进入的通道
                    dt1 = ((x_list[n] - x_list[n - 1]) * 3.2) / self.speed
                    # 走到通道的入口需要的时间
                sum_of_goods = 0
                for m in self.goods_message:
                    # 循环所有的货架
                    if m[0][0] == x_list[record_number]:
                        sum_of_goods += m[1]
                dt2 = (sum_of_goods * self.choose) + (20 / self.speed)  # 变化了的时间
                # 包含了 拣货 + 行走
                self.taboo_table[f'{x_list[record_number]}'] = [t1 + dt1, t1 + dt1 + dt2]
                # 进入时间为:初始时间 + 走到入口
                # 出去时间为:初始时间 + 走到入口 + 在通道内部的时间
                t1 = t1 + dt1 + dt2  # 重新对 t1 进行赋值
                record_number += 1
                # 记录数字自加一
                continue
            y_list = []
            for j in self.goods_message:
                if j[0][0] == max(x_list):  # 如果是在最后一个通道内的货架
                    y_list.append(j[0][2])
                    # 获取到最后一个通道内部的 y 坐标
            y = max(y_list)
            # 求出最后一个通道所需要达到的最远的 y 坐标
            last_sum_of_goods1 = 0
            for m in self.goods_message:
                # 循环所有的货架
                if m[0][0] == x_list[record_number]:
                    last_sum_of_goods1 += m[1]
            self.taboo_table[f'{x_list[len(x_list) - 1]}'] = [t1 + ((x_list[len(x_list) - 1] - x_list[len(x_list) - 1 - 1]) * 3.2) / self.speed, t1 + ((x_list[len(x_list) - 1] - x_list[len(x_list) - 1 - 1]) * 3.2) / self.speed + last_sum_of_goods1 * self.choose + (1.2 * y) / self.speed]


    def compute_the_total_of_the_time(self):
        """
        计算一个员工所需要的总的时间
        :return: 空
        """
        self.the_total_of_the_time = self.time_of_walk_and_choose + self.wait_time
        # 总时间 = 行走以及拣货的时间 + 等待(堵塞)的时间


    def __str__(self):

        """
        定义一个函数来打印相关对象的信息
        :return: 空
        """

        print("该员工处理的订单信息为:", end='\\n')
        j = 1
        for message in self.goods_message:
            print(f'第 {j} 个货物,坐标位置: {message[0]},取货数目: {message[1]}')
            j += 1
            # j 自加一
        print()

        str0 = f"该员工的工作总时间为:{self.the_total_of_the_time}," \\
               f"行走的时间为:{self.time_of_walk}," \\
               f"拣货的时间为:{self.time_of_choose}," \\
               f"堵塞的时间为:{self.wait_time}."
        return str0


四、计算时间的源代码

这里还是一样的啊,我们直接给出来源代码,因为里面也是有很多的详细地注释来进行解释代码的啦
源代码:

# 导入模块

from employee_package.employee import Employee


def execute_the_code():

    """
    运行程序,进行员工拣货的模拟实现,
    首先实现每一个员工的初始化操作,
    然后,实现每一个员工的工作时间的计算
    :return: 空
    """

    # 员工的人数
    q = 3

    # 生成员工列表并进行初始化
    employ_list = []

    # 初始化员工的信息
    for i in range(q):
        """
        初始化
        """
        input_goods_message = []
        # 请用户输入商品的货架信息
        while True:
            print(f"请输入第 {i + 1} 个员工的初始化信息,即就是第 {i + 1} 个员工对应的订单信息")
            x = int(input('输入 x 坐标 :'))
            # 转换为 int
            y = int(input('输入 y 坐标 :'))  # 转换为 int
            r = int(input('输入 r 坐标 :'))  # 转换为 int
            number = int(input('输入该货架中要取出来多少货物 :'))  # 转换为 int
            input_goods_message.append([(x, r, y), number])
            # [(x, r, y), goods_number]
            break_or_not = input('如果输入完毕了,请输入 1 来结束操作 !\\n 如果要继续输入请直接回车!')
            if break_or_not == '1':
                break
            else:
                continue
        # 定义一个中间变量作为新的员工
        new_employee = Employee(start_time=20 * i,
                                goods_message=input_goods_message,
                                taboo_table={})
        # 加入新的员工到列表之中去
        employ_list.append(new_employee)

    # 计算每一个员工除了堵塞意外所用的时间
    for i in range(q):
        """
        除了堵塞以外的时间
        """
        employ_list[i].compute_walk_and_choose_time()
        # 计算除了堵塞意外所用的时间

    # 生成每一个员工的禁忌表
    for i in range(q):
        """
        生成禁忌表
        """
        employ_list[i].make_the_taboo_table()
        # 生成每一个员工的禁忌表

    # # 打印每一个员工的禁忌表
    # for i in range(q):
    #     """
    #     打印禁忌表
    #     """
    #     print(employ_list[i].taboo_table)
    #     # 打印每一个员工的禁忌表

    # 计算每一个员工的等待(堵塞)的时间
    for i in range(q):
        """
        计算堵塞的时间
        """
        # 对任意一个员工都是要进行计算出来延迟的时间的
        new_dict = {}
        for j in range(q):
            # 将每一个非该对象的字典都加入到新的空字典中去
            if j != i:  # 只要不是当前的对象
                for data in employ_list[j].taboo_table.keys():
                    # 这里的 data 是一个键
                    if data in new_dict.keys():
                        # 如果已经有了这个键 key
                        new_dict[data].append(employ_list[j].taboo_table[data])
                        # 加入的是一个列表
                    else:
                        # 如果还没有这个键 key
                        new_dict[data] = [employ_list[j].taboo_table[data]]
        # 添加除了当前员工以外的所有的员工的禁忌表到一个字典中方便计算当前员工的堵塞时间
        # 这一步相当于是将其他人的禁忌表整合在了一起
        for a_key in employ_list[i].taboo_table.keys():
            # 遍历当前员工的所有的键,employ_list[i].taboo_table.keys()
            if a_key in new_dict.keys():
                # 如果当前员工的键在刚刚生成的字典的键中,那么就需要判断是否会发生堵塞
                for time in new_dict[a_key]:  # 这里读取到的是一个列表,因此需要遍历列表中的每一个元素
                    if (employ_list[i].taboo_table[a_key][0] >= time[0]) and (employ_list[i].taboo_table[a_key][0] < time[1]):
                        # 如果当前对象进入该通道的时间与其他的对象发生了冲突,那么,我们就需要记录此时的等待时间,也就是说记录堵塞的时间
                        # 这里的情况如果满足,那就是发生了冲突的
                        employ_list[i].wait_time += time[1] - employ_list[i].taboo_table[a_key][0]
                        # 将等待的时间加入到每一个员工的等待时间中去,
                        # 加上一个时间差
                    else:
                        # 如果没有冲突
                        employ_list[i].wait_time += 0
            else:
                # 如果当前员工的键不在刚刚生成的字典的键中,那么无论如何都是可以直接前去拣货的啦
                employ_list[i].wait_time += 0  # 加 0
        # 这一步是进行计算 i 这个员工的堵塞时间

    # 计算每一个员工所需要的总时间
    for i in range(q):
        """
        计算总时间
        """
        employ_list[i].compute_the_total_of_the_time()
        # 计算每一个员工所需要的总时间

    # 打印每一个员工的信息
    for i in range(q):
        """
        输出信息
        """
        print(f"第 {i + 1} 个员工的工作信息如下 : ")
        print()
        # 打印拣货信息
        str00 = employ_list[i].__str__()
        # 打印时间信息
        print(str00)  # 打印每一个员工的信息
        print()

五、main函数的源代码

main函数的源代码:

# 导入模块

from execute_the_code import execute


if __name__ == '__main__':

    """
    main 函数
    """

    # 执行代码, run the code
    execute.execute_the_code()

六、整个程序的源代码:

员工类文件:

# 自定义一个模块,这个文件中定义一个员工类,每一个员工都是该类的一个实例对象


class Employee(object):

    """
    员工类
    """

    def __init__(self, start_time, goods_message, taboo_table, speed=0.9, choose=1, wait_time=0):
        """
        初始化一个实例对象
        :param start_time: 员工开始出发的时间
        :param goods_message: 员工需要达到的货架以及所需要取多少货品
        :param taboo_table: 禁忌表,记录每个员工何时在哪一个通道内部,何时进入、出去,
        刚开始,禁忌表为空,后面利用函数进行添加
        :param speed: 恒定的行走速度,0.9
        :param choose: 恒定值,挑选商品,1
        :param wait_time: 等待的时间,即就是堵塞的时间,先赋值为 0 ,后续再更改
        """
        self.start_time = start_time  # 开始出发的时间
        self.goods_message = goods_message  # 需要达到的货架以及所需要取多少货品
        """
        一个商品信息应该如下:[(x, r, y), goods_number]
        然后多个类似的列表会组成一个总的商品列表
        """
        self.taboo_table = taboo_table  # 禁忌表,记录何时在哪一个通道内部,何时进入、出去
        self.speed = speed
        self.choose = choose
        self.time_of_walk_and_choose = 0  # 先赋值为 0 ,后续再更改
        self.wait_time = wait_time  # 堵塞的时间,先赋值为 0 ,后续再更改
        self.the_total_of_the_time = 0  # 总的时间(包含了行走、等待或者说堵塞、拣货这三个时间),先赋值为 0 ,后续再更改
        self.time_of_walk = 0  # 走的总时间,先赋值为 0 ,后续再更改
        self.time_of_choose = 0  # 拣货的总时间,先赋值为 0 ,后续再更改


    def compute_walk_and_choose_time(self):
        """
        计算行走以及取货物的时间,此时尚未考虑堵塞的问题,将在后续的函数考虑
        :return: 空
        """
        x_list = []
        y_list = []
        for i in self.goods_message:
            x_list.append(i[0][0])
            # 获取到所有的要去的通道的编号
        for j in self.goods_message:
            if j[0][0] == max(x_list):  # 如果是在最后一个通道内的货架
                y_list.append(j[0][2])
                # 

以上是关于Python实现拣货员拣货的时间长短分析的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Anylogic 在仓库操作中为拣货流程创建订单

拣货问题(自定义 unProject() 函数)

设计模式-策略模式JAVA实现

如何在货架拣货块中指定拣货策略? - 任何逻辑

拣货电话的计数方法是啥

Laravel 用于拣货清单的简单电子商务逻辑