面试问题:2018年全国大学生数学建模竞赛项目(RGV动态调度模型、贪婪算法)

1、 赛题背景

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

2、 RGV流程图

在这里插入图片描述

3、 面试问题

3.1 RGV和CNC是什么?

RGV是轨道式自动引导车(Rail Guide Vehicle)。
CNC是计算机数控机床(Computer Number Controller)

3.2 这个系统是怎么运行的?

首先对RGV的结构进行说明:RGV包含一个清洗槽和一个机械臂,机械臂上有两个手爪。
这个系统通电后,RGV首先位于CNC1和CNC2的初始位置,所有CNC都是空闲状态。若某台CNC处于空闲状态,则向RGV发出上料信号,否则,CNC处于加工状态,待加工完成后立即向RGV发出上料信号。若RGV未选择这台CNC,则该CNC会持续发出上料信号。
RGV根据我设计的预测工位函数,直接确定为哪一台CNC进行上下料作业,上料是上的未加工生料,下料是取下已加工熟料。然后RGV会运行至预测工位函数返回的CNC处,当这台CNC发出上料信号后,就会为这台CNC进行上下料作业。
若这台CNC上有熟料,当RGV完成上下料作业后,将手中的熟料放入清洗槽中,清洗后将成料放到下料传送带上送出系统。至此RGV完成一整项包括移动、上下料以及清洗的作业任务。
若这台CNC上无熟料,则RGV完成的任务中只包含移动以及上下料的时间。
RGV完成一项作业任务后,立即利用预测工位函数判别并执行下一个作业指令。
并且,RGV每对一个熟料进行清洗作业后,系统的成品数量就加一。

3.3 预测工位函数是怎么设计的?

利用Python语言,定义一个返回值有两个元素的函数,就是我所提到的预测工位函数。在函数中创建一个有八个元素的列表T,这八个元素代表八台CNC,然后T[i]就是将第i台CNC的剩余工作时间,RGV移动到第i台CNC所需的时间,第i台CNC的清洗时间相加。然后求出T[i]中,i从0到7,中的最小值,然后就将得到的能够达到最短时间的CNC所处的工位数以及CNC的编码数作为函数返回值。这其中用到的算法就是贪婪算法。

3.4 简要介绍一下贪婪算法

贪婪算法简单来说就是:“今朝有酒今朝醉”,即一定要做当前情况下的最佳选择。也就是说,不从整体最优上加以考虑,贪婪算法做出的是局部最优解。

3.5 整个比赛的流程是怎么样的?

竞赛总共为期三天,首先确定本次竞赛要做的题目,然后将赛题抽象化为数学语言,即得到限定条件以及目标函数。然后查阅资料,参考各类文献,最后整合文献,确定求解数学模型所使用的的算法。然后根据算法去编写相应的求解程序。论文的撰写则贯穿建模竞赛的全程。

3.6 参与比赛过程中你遇到了什么困难?怎么解决的?

在这次比赛中,我遇到的困难主要是在选择求解算法方面的问题。对于RGV的调度问题来说,网上有多种算法可以解决,例如遗传算法、模拟退火算法等,由于我本身不是科班出身,因此对这些算法的了解程度并不高,所以当时为了寻找一个合适的算法消耗了很多时间。最后,我回归问题本身,不再在网络上寻找算法,而是自己来寻找解决方法。最终,我发现解决调度问题的关键点在于效率问题,只要让RGV每次的移动都最有效,就能实现一个最优的动态调度模型。因此我采用贪婪算法作为编写RGV的预测工位函数的核心算法。

3.7 你在队伍中担当的是什么角色?

我们队伍一共三个人,我和组长负责数学模型的建立,建立起模型后,我负责求解算法的确定以及求解程序的编写工作。在写论文时,我负责有关算法部分的论文的编写。

3.8 你从数学建模竞赛中学到什么?

这个比赛需要三个参赛队员在三天的时间内,完成选题、资料收集、建模、模型求解以及论文撰写工作,这锻炼了我的团队协作能力。
并且比赛的题目一般是社会热点题目,需要参赛队员在三天内搜集并学习大量的相关资料,这提高了我的学习能力。

4 代码部分

# -*- coding: utf-8 -*-
"""
Created on Sat Sep 15 09:14:04 2018

@author: Administrator
"""

from pandas.core.frame import DataFrame

#设定各个参数的数值
#智能加工系统开始作业到停止作业的累计时间
t = 0    
#t时刻加工系统已加工的成品总数
n = 0
#RGV移动j个单位所需时间
M_0 = 0
M_1 = 18
M_2 = 32
M_3 = 46
#CNC加工完成一个一道工序的物料所需时间
TC_TIME = 545
#RGV为CNC1#,3#,5#,7#一次上下料所需时间
P1_TIME = 27
#RGV为CNC2#,4#,6#,8#一次上下料所需时间
P2_TIME = 32
#RGV完成一个物料的清洗作业所需时间
W_TIME = 25
#设定物料二维列表用于存储上下料开始结束时间
subject = [[0]*3 for i in range(1000)]
#RGV未开始上料时,b为0,RGV开始上料时,b为1
b = 0
#定义变量k,用作存储上料时间的循环
k = 0


#创建CNC类
#c_id:CNC的代号, 
#t_time:系统的总时间,即t
#tc_time:CNC从当前状态到空闲状态的时间
#number:此CNC加工的成料总数
#x:x为零表示CNC上无熟料,为一时表示CNC上有熟料
#y:y为零表示CNC正常工作,为一时表示CNC发生故障
class CNC():
    def __init__(self, c_id, t_time, tc_time, e_time, number, x, y):
        self.c_id = c_id
        self.t_time = t_time
        self.tc_time = tc_time
        self.number = number
        self.x = x
        self.y = y

#创建RGV类
#t_time:系统的总时间,即t
#m_time:RGV移动j个单位所需时间
#p_time:RGV一次上下料的时间
#w_time:RGV完成一次物料清洗作业所需时间
#k:RGV当前工位
#l:RGV下次工位
#a:为零表示RGV不在清洗状态,为一表示RGV完成清洗作业
#s:为零表示RGV处于等待状态,为一表示RGV处于运行状态
class RGV():
    def __init__(self, t_time, m_time, p_time, w_time, k, l, a, s):
        self.t_time = t_time
        self.m_time = m_time
        self.p_time = p_time
        self.w_time = w_time
        self.k = k
        self.l = l
        self.a = a
        self.s = s

#定义RGV下一工位以及CNC编号的预测函数,函数返回值为RGV下次作业的工位位置以及时间最短的CNC的编号
def locate():
    #RGV完成一次作业任务所需花费时间(RGV从当前等待状态直至进入下一次等待状态)
    T = [C[i].tc_time + V.m_time + V.p_time + V.w_time*C[i].x for i in range(0, 8)]
    #取上述八台CNC中的RGV一次作业任务时间的最小值
    Tmin = min(T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7])
    #将RGV的下一次工位l以及取得时间的最小值的CNC的编号即h返回给函数值
    for i in range(0, 8):
        if Tmin == T[i]:
            h = i + 1
            break
    if (h == 1 or h == 2):
        l = 1
    elif (h == 3 or h == 4):
        l = 2
    elif (h == 5 or h == 6):
        l = 3
    else:
        l = 4        
    return l, h


#创建八台CNC对象
C1 = CNC(1, t, 0, 0, 0, 0, 0)
C2 = CNC(2, t, 0, 0, 0, 0, 0)
C3 = CNC(3, t, 0, 0, 0, 0, 0)
C4 = CNC(4, t, 0, 0, 0, 0, 0)
C5 = CNC(5, t, 0, 0, 0, 0, 0)
C6 = CNC(6, t, 0, 0, 0, 0, 0)
C7 = CNC(7, t, 0, 0, 0, 0, 0)
C8 = CNC(8, t, 0, 0, 0, 0, 0)

#创建八台CNC的工作剩余时间的列表
C = (C1, C2, C3, C4, C5, C6, C7, C8)


#创建RGV对象
V = RGV(t, 0, 0, 0, 1, 1, 0, 0)

#系统连续作业八小时
while t < 28800:
    #当RGV处于等待状态时
    if V.s == 0:
        #调用预测函数,将RGV下一工位赋值给对象V,l_h[0]为RGV下一工位
        l_h = locate()
        V.l = l_h[0]
        #根据预测的下移工位的结果,将移动不同单位所需的时间赋值给m_time
        V.m_time = M_0*(abs(V.l - V.k) == 0) + M_1*(abs(V.l - V.k) == 1) + \
        M_2*(abs(V.l - V.k) == 2) + M_3*(abs(V.l - V.k) == 3)
    #由于RGV已经开始运动,因此s置为一
    V.s = 1 

   
    
    #总时间加一秒
    t = t + 1
    #由于总时间加一秒,因此所有作业时间都需减一秒,若不足一秒,则依旧置零
    #对于每台CNC有
    #每台CNC的tc_time减一秒
    #并且当tc_time由一减到零秒时,说明此时CNC加工出一个熟料,因此置x为1
    for i in range(0, 8):
        if C[i].tc_time == 0:
             C[i].tc_time = 0
        else:
            C[i].tc_time = C[i].tc_time - 1
        if C[i].tc_time == 1:
            C[i].x = 1
   
    #对于RGV来说
    #RGV移动的时间m_time减一
    if V.m_time == 0:
        V.m_time = 0
    else:
        V.m_time = V.m_time - 1 
    #RGV一次上下料的时间p_time减一
    if V.p_time == 0:
        V.p_time = 0
    else:
        V.p_time = V.p_time - 1 
    #RGV完成一次物料清洗的时间w_time减一
    if V.w_time == 0:
        V.w_time = 0
    else:
        V.w_time = V.w_time - 1 
    #RGV的清洗时间当从一减少到零时,将RGV状态置为等待状态,并将成料个数增加一个
    #RGV的清洗时间当从一减少到零时,将RGV状态置为等待状态,并将成料个数增加一个
    if V.w_time == 1:
        #成料个数增加一个
        n = n + 1
        #当成料个数增加一个时,将此时CNC编号与加工成料对应起来
        subject[n][0] = C[l_h[1]-1].c_id
        #将此时的时刻定义为下料时间
        subject[n][2] = t
        V.s = 0
        
      
        
    #当RGV移动到相应工位后,判断当前CNC剩余工作时间是否为零,l_h[1]为当前CNC的编号
    if V.m_time == 0:
        #首先将l位置设定为当前RGV的位置
        V.k = V.l
        #如果此台CNC到达了空闲状态,并且RGV不处于上下料过程中,则RGV开始进行上下料作业,反之RGV保持当前等待状态
        if (C[l_h[1]-1].tc_time == 0 and b == 0):
            #将机械手抓起生料时定义为上料时间
            k = k + 1 
            subject[k][1] = t
            #如果空闲CNC的id为奇数,赋奇数上下料时间给RGV,反之则赋偶数上下料时间给RGV
            if l_h[1]%2 == 1:
                V.p_time = P1_TIME
            else:
                V.p_time = P2_TIME
            b = 1
        #当RGV上下料结束,将b重新置为零,意为RGV此时又处在未上下料的状态下
        if V.p_time == 0:
            b = 0
            #上下料结束后,若此机床未在加工零件,则将CNC加工完成一个一道工序的物料所需时间赋给当前CNC
            if C[l_h[1]-1].tc_time == 0:
                C[l_h[1]-1].tc_time = TC_TIME
                #如果CNC上有熟料,并且RGV未处于清洗状态,则机床进行清洗
                #清洗结束后将s置为零;反之RGV直接进入等待状态,重新判断下次工位
                if (C[l_h[1]-1].x == 1 and V.w_time == 0):
                    V.w_time = W_TIME
                else:
                    V.s = 0

#将列表转换为dataframe格式并输出excel
Subject = DataFrame(subject)
Subject.to_excel('1_yidao.xls')
   
原创文章 29 获赞 62 访问量 10万+

猜你喜欢

转载自blog.csdn.net/mahoon411/article/details/106109671