2018CUMCM(数学建模国赛)_B——智能RGV的动态调度策略

 

图1是一个智能加工系统的示意图,由8台计算机数控机床(Computer Number Controller,CNC)、1辆轨道式自动引导车(Rail Guide Vehicle,RGV)、1条RGV直线轨道、1条上料传送带、1条下料传送带等附属设备组成。RGV是一种无人驾驶、能在固定轨道上自由运行的智能车。它根据指令能自动控制移动方向和距离,并自带一个机械手臂、两只机械手爪和物料清洗槽,能够完成上下料及清洗物料等作业任务(参见附件1)。

1:智能加工系统示意图

 

针对下面的三种具体情况:

(1)一道工序的物料加工作业情况,每台CNC安装同样的刀具,物料可以在任一台CNC上加工完成;

(2)两道工序的物料加工作业情况,每个物料的第一和第二道工序分别由两台不同的CNC依次加工完成;

(3)CNC在加工过程中可能发生故障(据统计:故障的发生概率约为1%)的情况,每次故障排除(人工处理,未完成的物料报废)时间介于10~20分钟之间,故障排除后即刻加入作业序列。要求分别考虑一道工序和两道工序的物料加工作业情况。

请你们团队完成下列两项任务:

任务1对一般问题进行研究,给出RGV动态调度模型和相应的求解算法;

任务2利用表1中系统作业参数的3组数据分别检验模型的实用性和算法的有效性,给出RGV的调度策略和系统的作业效率,并将具体的结果分别填入附件2的EXCEL表中。

表1:智能加工系统作业参数的3组数据表                                时间单位:秒

系统作业参数

第1组

第2组

第3组

RGV移动1个单位所需时间

20

23

18

RGV移动2个单位所需时间

33

41

32

RGV移动3个单位所需时间

46

59

46

CNC加工完成一个一道工序的物料所需时间

560

580

545

CNC加工完成一个两道工序物料的第一道工序所需时间

400

280

455

CNC加工完成一个两道工序物料的第二道工序所需时间

378

500

182

RGV为CNC1#,3#,5#,7#一次上下料所需时间

28

30

27

RGV为CNC2#,4#,6#,8#一次上下料所需时间

31

35

32

RGV完成一个物料的清洗作业所需时间

25

30

25

注:每班次连续作业8小时。

 

1.系统的场景及实物图说明

在附图1中,中间设备是自带清洗槽和机械手的轨道式自动引导车RGV,清洗槽每次只能清洗1个物料,机械手臂前端有2个手爪,通过旋转可以先后各抓取1个物料,完成上下料作业。两边排列的是CNC,每台CNC前方各安装有一段物料传送带。右侧为上料传送带,负责为CNC输送生料(未加工的物料);左边为下料传送带,负责将成料(加工并清洗完成的物料)送出系统。其他为保证系统正常运行的辅助设备。

 

 

附图1RGVCNC车间布局图

 

    2:带机械手臂和清洗槽的RGV实物图

 

附图2是RGV的实物图,包括车体、机械臂、机械手爪和物料清洗槽等。

 

 

附图3RGV机械手臂前端的2个手爪实物图

在附图3左图中,机械臂前端上方手爪抓有1个生料A,CNC加工台上有1个熟料B。RGV机械臂移动到CNC加工台上方,机械臂下方空置的手爪准备抓取熟料B,在抓取了熟料B后即完成下料作业。

在附图3右图中,RGV机械臂下方手爪已抓取了CNC加工台上的熟料B抬高手臂,并旋转手爪,将生料A对准加工位置,安放到CNC加工台上,即完成上料作业。

 

2.系统的构成及说明

智能加工系统由8台CNC、1台带机械手和清洗槽的RGV、1条RGV直线轨道、1条上料传送带和1条下料传送带等附属设备构成。

1CNC在上料传送带和下料传送带的两侧各安装4台CNC,等距排列,每台CNC同一时间只能安装1种刀具加工1个物料。

如果物料的加工过程需要两道工序,则需要有不同的CNC安装不同的刀具分别加工完成,在加工过程中不能更换刀具。第一和第二道工序需要在不同的CNC上依次加工完成,完成时间也不同,每台CNC只能完成其中的一道工序。

2RGVRGV带有智能控制功能,能够接收和发送指令信号。根据指令能在直线轨道上移动和停止等待,可连续移动1个单位(两台相邻CNC间的距离)、2个单位(三台相邻CNC间的距离)和3个单位(四台相邻CNC间的距离)。RGV同一时间只能执行移动、停止等待、上下料和清洗作业中的一项。

3)上料传送带:上料传送带由4段组成,在奇数编号CNC1#、3#、5#、7#前各有1段。由系统传感器控制,只能向一个方向传动,既能连动,也能独立运动。

4)下料传送带:下料传送带由4段组成,在偶数编号CNC2#、4#、6#、8#前各有1段。由传感器控制,只能向同一个方向传动,既能连动,也能独立运动。

3. 系统的作业流程

(1)智能加工系统通电启动后,RGV在CNC1#和CNC2#正中间的初始位置,所有CNC都处于空闲状态。

(2)在工作正常情况下,如果某CNC处于空闲状态,则向RGV发出上料需求信号;否则,CNC处于加工作业状态,在加工作业完成即刻向RGV发出需求信号。

(3)RGV在收到某CNC的需求信号后,它会自行确定该CNC的上下料作业次序,并依次按顺序为其上下料作业。根据需求指令,RGV运行至需要作业的某CNC处,同时上料传送带将生料送到该CNC正前方,供RGV上料作业。

RGV为偶数编号CNC一次上下料所需时间要大于为奇数编号CNC一次上下料所需时间。

(4)在RGV为某CNC完成一次上下料作业后,就会转动机械臂,将一只机械手上的熟料移动到清洗槽上方,进行清洗作业(只清洗加工完成的熟料)。

具体过程:首先用另一只机械手抓取出清洗槽中的成料、转动手爪、放入熟料到清洗槽中,然后转动机械臂,将成料放到下料传送带上送出系统。这个作业过程所需要的时间称为RGV清洗作业时间,并且在这个过程中RGV不能移动。

熟料在清洗槽中的实际清洗时间是很短的,远小于机械手将成料放到下料传送带上的时间。

(5)RGV在完成一项作业任务后,立即判别执行下一个作业指令。此时,如果没有接到其他的作业指令,则RGV就在原地等待直到下一个作业指令。

某CNC完成一个物料的加工作业任务后,即刻向RGV发出需求信号。如果RGV没能即刻到达为其上下料,该CNC就会出现等待。

(6)系统周而复始地重复(3)至(5),直到系统停止作业,RGV回到初始位置。


解题思路:采用A*算法,计算各个CNC完成工件的期望时间矩阵,进而进行实时最优决策。

Case_1_1

# -*- coding: utf-8 -*-
"""
Created on Fri Sep 14 21:57:21 2018

@author: LIUZhendong
"""
import csv
from itertools import chain    
'''按照A*算法进行RGV分配加工所需时间模拟(第一组)======================================'''
def find_martrix_min_value(data_matrix,State_CNC):
    '''''
    功能:找到矩阵State_CNC为0下的data_matrix最小值
    '''
    min_data = 1000000000
    add=(0,0)
    for i in range(len(data_matrix)):
        for j in range (len(data_matrix[i])):
            if data_matrix[i][j] < min_data and State_CNC[i][j] == 0:
                min_data = data_matrix[i][j]
                add = (i,j)
    return add
T_total = 8 * 60 * 60
T_CNC_matrix = []
State_CNC = []          # 0表示完成工作进入等待    1 表示正在工作
State_RGV = 0           # 表示RGV的位置 其中0,1,2,3分别代表位于1#、2#,3#、4#,5#、6#,7#、8#之间
T_RGV = 0
T_G = []
T_H = []
T_down = []
Answer_CSV = []
for i in range (2):
    State_CNC.append([])
    T_CNC_matrix.append([])
    T_G.append([])
    T_down.append([])
    for j in range(4):
        State_CNC[i].append(0)
        T_CNC_matrix[i].append(0)
        T_G[i].append(0)
        T_down[i].append(0)
for times in range (1000):
    T_CNC_odd = 0
    T_CNC_even = 0
    T_cost = 0
    T_change = [31,28]
    T_clean = 25
    T_move = [0,20,33,46]
    T_process = 560
    T_process_1 = 400
    T_process_2 = 378
    for j in range (2):
        for k in range (4):
            if j == 0:
                T_G[j][k] = T_change[0]
            elif j == 1:
                T_G[j][k] = T_change[1]
#    print(T_G)
    for i in range (2):
        if State_RGV == 0:
            T_G[i][1] = T_G[i][1] + T_move[1]
            T_G[i][2] = T_G[i][2] + T_move[2]
            T_G[i][3] = T_G[i][3] + T_move[3]
        elif State_RGV == 1:
            T_G[i][0] = T_G[i][0] + T_move[1]
            T_G[i][2] = T_G[i][2] + T_move[1]
            T_G[i][3] = T_G[i][3] + T_move[2]
        elif State_RGV == 2:
            T_G[i][0] = T_G[i][0] + T_move[2]
            T_G[i][1] = T_G[i][1] + T_move[1]
            T_G[i][3] = T_G[i][3] + T_move[1]
        elif State_RGV == 3:
            T_G[i][0] = T_G[i][0] + T_move[3]
            T_G[i][1] = T_G[i][1] + T_move[2]
            T_G[i][2] = T_G[i][2] + T_move[1]
#    print(T_G)
    for j in range (2):
        T_H.append([])
        for k in range (4):
            T_H[j].append(T_process)
#    print(T_H)
#    print(type(T_G))
#    print(type(T_H))
    for i in range (2):
        for j in range (4):
            T_CNC_matrix[i][j] = T_G[i][j] + T_H[i][j] + T_clean
    print(T_CNC_matrix)
    add = find_martrix_min_value(T_CNC_matrix,State_CNC)
    (a,b) = add
    T_RGV = T_RGV + T_move[abs(State_RGV-b)]
#    print('{}:{}'.format(times,T_RGV))
    if a == 0:
        Num = 2 * (b + 1)
    elif a == 1:
        Num = 2 * (b + 1) - 1
    if a == 0:
        T_RGV = T_RGV + T_change[0]
    elif a == 1:
        T_RGV = T_RGV + T_change[1]
    State_CNC[a][b] = 1
    T_down[a][b] = T_process + T_RGV
    if T_down[a][b] + T_change[a] + T_clean > T_total:
        break
    Answer_CSV.append([]) 
    Answer_CSV[times].append(times+1)
    Answer_CSV[times].append('CNC{}#'.format(Num))
    T_up = T_RGV
    Answer_CSV[times].append(T_up)
    Answer_CSV[times].append(T_down[a][b])
    
    if times > 7:
        T_RGV = T_RGV + T_clean
    State_RGV = b
    if len(set(list(chain.from_iterable(State_CNC)))) == 1:
        for i in range (2):
            for j in range (4):
                State_CNC[i][j] = 0
        (c,d)=find_martrix_min_value(T_down,State_CNC)
        T_RGV = T_RGV + T_move[abs(State_RGV-d)]
        State_RGV = d
        T_RGV = T_down[c][d]
    if T_down[a][b] + T_change[a] + T_clean > T_total:
        break
#    print(State_CNC)
#    print(T_RGV)
#    print(State_RGV)
#print(Answer_CSV)
#writer = csv.writer(open("Case_1_1.csv",'w',newline=''))
#for item in Answer_CSV:
#    writer.writerow(item)

Case_1_2

Case_1_3

同上,修改至不同组数据


Case_2

# -*- coding: utf-8 -*-
"""
Created on Sat Sep 15 14:25:40 2018

@author: LIU Zhendong
"""

import csv
from itertools import chain
import random
'''穷举法--两道工序======================================'''
'''
算法规则:
RGV总共有三种工作要做
1、给1类刀具CNC上原件
2、把1类刀具CNC上原件给二类刀具
3、将2类刀具CNC上熟件卸下清洗存放
假设从1类刀具CNC上卸下的原件无处存放,需要RGV停止等待2类刀具
CNC结束工作再给其装上,期间RGV不能做其他事情
如果RGV遇到1类刀具CNC和2类刀具CNC同时请求时,优先选择2类刀具
CNC装件
'''

Group = 1
Loop = 254
Times = 1024
def find_martrix_min_value(data_matrix,State_CNC,p,q):
    '''''
    功能:找到矩阵State_CNC[0]为0下的data_matrix最小值
    '''
    min_data = 1000000000
    add=(0,0)
    for i in range(len(data_matrix)):
        for j in range (len(data_matrix[i])):
            if data_matrix[i][j] < min_data and State_CNC[p][i][j] == q:
                min_data = data_matrix[i][j]
                add = (i,j)
    return add

def find_free_min_add(data_matrix,State_CNC,p,q,r,s):
    '''''
    功能:找到矩阵State_CNC一定条件下最小值
    '''
    min_data = 1000000000
    add=(2,2)
    for i in range(len(data_matrix)):
        for j in range (len(data_matrix[i])):
            if data_matrix[i][j] < min_data and State_CNC[p][i][j] == q and State_CNC[r][i][j] == s:
                min_data = data_matrix[i][j]
                add = (i,j)
    return add
def Breakdown_random():
    '''''
    功能:随机产生故障并返回故障机器编号和故障时间
    '''
    a = random.randint(1,800)
    b = random.randint(600,1200)
    if a > 8:
        return (2,0,0)
    elif a % 2 == 0:
        return (0 , int(a/2-1) , b)
    elif a % 2 == 1:
        return (1 , int((a-1)/2) , b)


'''初始化变量==============================================='''
T_total = 8 * 60 * 60
MAX_OUTPUT = 0
T_CNC_matrix = []
# 表示CNC剩余工作时间列表
State_CNC = [[],[]]          
'''
State_CNC[0]  为一张2 * 4 列表,表示CNC状态
    其中0表示完成工作进入等待    1 表示正在工作
State_CNC[1]  为一张2 * 4 列表, 表示CNC携带的刀具
    其中0表示携带第一类刀具      1 表示携带第二类刀具
'''
State_RGV = 0

'''
State_RGV表示RGV的位置
    其中State_RGV = 0,1,2,3分别代表位于1#、2#,3#、4#,5#、6#,7#、8#之间

'''
State_CNC_Break = []    # 存放故障结束时间  0 表示无故障
T_RGV = 0
T_G = []
T_H = []
counts_CSV = []
Count_break = 0
T_down = []
Answer_CSV = []
Answer_CSV_Break =[]
NUM_CNC = []            # 存放CNC上物品编号
counts_CNC = []          # 记录CNC处理产品数量
T_change = [[31,28],[35,30],[32,27]]
T_clean = [25,30,25]
T_move = [[0,20,33,46],[0,23,41,59],[0,18,32,46]]
T_process = [560,580,545]
T_process_1 = [400,280,455]
T_process_2 = [378,500,182]
for i in range (2):
    State_CNC[0].append([])
    State_CNC[1].append([])
    T_CNC_matrix.append([])
    T_G.append([])
    T_down.append([])
    State_CNC_Break.append([])
    NUM_CNC.append([])
    counts_CNC.append([])
    for j in range(4):
        State_CNC[0][i].append(0)
        State_CNC[1][i].append(0)
        T_CNC_matrix[i].append(0)
        T_G[i].append(0)
        T_down[i].append(0)
        State_CNC_Break[i].append(0)
        NUM_CNC[i].append(0)
        counts_CNC[i].append(0)
#print(State_CNC)
        
        

'''穷举刀具各种情况主循环'''

for loop in range (Loop):
    for i in range (2):
        for j in range (4):
            T_CNC_matrix[i][j] = 0
            NUM_CNC[i][j] = 0
            counts_CNC[i][j] = 0
            State_CNC[0][i][j] = 0
            State_CNC[1][i][j] = 0
            T_CNC_matrix[i][j] = 0
            counts_CNC[i][j] = 0
    NUM_1 = 0
    NUM_2 = 0
    NUM = '{:08b}'.format(loop + 1)
    list_NUM = list(str(NUM))
    State_CNC[1][1][0] = int(list_NUM[7])
    State_CNC[1][0][0] = int(list_NUM[6])
    State_CNC[1][1][1] = int(list_NUM[5])
    State_CNC[1][0][1] = int(list_NUM[4])
    State_CNC[1][1][2] = int(list_NUM[3])
    State_CNC[1][0][2] = int(list_NUM[2])
    State_CNC[1][1][3] = int(list_NUM[1])
    State_CNC[1][0][3] = int(list_NUM[0])
#    State_CNC[1][1][0] = 0
#    State_CNC[1][0][0] = 0
#    State_CNC[1][1][1] = 0
#    State_CNC[1][0][1] = 1
#    State_CNC[1][1][2] = 1
#    State_CNC[1][0][2] = 1
#    State_CNC[1][1][3] = 1
#    State_CNC[1][0][3] = 1
#    print(State_CNC[1])
    for i in range (2):
        for j in range (4):
            if State_CNC[1][i][j] == 0:
                NUM_1 = NUM_1 + 1       #1类刀具CNC数目
            elif State_CNC[1][i][j] == 1:
                NUM_2 = NUM_2 + 1       #2类刀具CNC数目
#    print(NUM_1)
            

    
    
    
#    定义时间矩阵表示从目前位置到完成整件预估时间  
#    T_move + T_change + T_process_1 + T_change + T_move + T_change + T_process_2 + T_clean
#    预估时间矩阵T_CNC_matrix求解===============================================
#    2类刀具CNC预估时间矩阵
    for i in range (2):
        for j in range (4):
            if State_CNC[1][i][j] == 1:               # 携带2类刀具CNC
#                T_change
                if i == 0:
                    T_CNC_matrix[i][j] = 2 * T_change[Group][0]
                elif i == 1:
                    T_CNC_matrix[i][j] = 2 * T_change[Group][1]

#                T_process_2
                T_CNC_matrix[i][j] = T_CNC_matrix[i][j] + T_process_2[Group]

#                T_clean
                T_CNC_matrix[i][j] = T_CNC_matrix[i][j] + T_clean[Group]
#    print(T_CNC_matrix)


    Answer_CSV.append([])
    T_RGV = 0
    counts = 0
    counts_1 = 0            # 计数:1类刀具CNC正在加工零件数目
    counts_2 = 0            # 计数:2类刀具CNC正在加工零件数目
    State_RGV = 0
#循环求解
    for times in range (Times):
#        print(counts+1,'===================================================')
#        for i in range (2):
#            for j in range (4):
#                State_CNC[0][i][j] = 0
#        1类刀具CNC预估时间矩阵
#        State_CNC[1][1][0] = 0
#        State_CNC[1][0][0] = 1
#        State_CNC[1][1][1] = 1
#        State_CNC[1][0][1] = 0
#        State_CNC[1][1][2] = 1
#        State_CNC[1][0][2] = 0
#        State_CNC[1][1][3] = 0
#        State_CNC[1][0][3] = 0
#        NUM_1 = 5
        
        for i in range (2):
            for j in range (4):
                if State_CNC[1][i][j] == 0:               # 携带1类刀具CNC
#                    T_change
                    if i == 0:
                        T_CNC_matrix[i][j] = T_change[Group][0]
                    elif i == 1:
                        T_CNC_matrix[i][j] = T_change[Group][1]
#                    T_process_1
                    T_CNC_matrix[i][j] = T_CNC_matrix[i][j] + T_process_1[Group]
#        print(T_CNC_matrix)
        for i in range (2):
            for j in range (4):
                if State_CNC[1][i][j]== 0:
                    for k in range (2):
                        for l in range (4):
                            if State_CNC[1][k][l] == 1:
                                T_G[k][l] = T_CNC_matrix[i][j] + T_move[Group][abs(l-j)] + T_CNC_matrix[k][l]
                    (a,b) = find_martrix_min_value(T_G,State_CNC,1,1)
                    T_CNC_matrix[i][j] = T_G[a][b] + T_move[Group][abs(State_RGV-j)]
        (c,d) = find_martrix_min_value(T_CNC_matrix,State_CNC,1,0)
        for i in range (2):
            for j in range(4):
                T_G[i][j] = 0
#        print(T_CNC_matrix)
#    预估时间矩阵T_CNC_matrix求解===============================================





# =============================================================================
# NUM_1 1CNC数
# counts 零件标号
# counts_1 正在加工
# counts_1_free 加工完成空闲数
# counts_2 正在加工
# counts_2_free 加工完成空闲数

# =============================================================================
#

        for i in range (2):
            for j in range (4):
                if T_RGV >= T_down[i][j]:
                    State_CNC[0][i][j] = 0
#        print(State_CNC[0])
        (c,d) = find_free_min_add(T_CNC_matrix,State_CNC,0,0,1,0)
#            移动至目标CNC
#        print(c,d)
        for i in range (2):
            for j in range (4):
                if T_RGV >= T_down[i][j]:
                    State_CNC[0][i][j] = 0
        if(c,d) == (2,2):
            (c,d) = find_martrix_min_value(T_down,State_CNC,1,0)
            T_RGV = max(T_RGV + T_move[Group][abs(State_RGV-d)],T_down[c][d])
        else:
            T_RGV = T_RGV + T_move[Group][abs(State_RGV-d)]
        
        State_RGV = d
#           上件
        if c == 0:
            T_RGV = T_RGV + T_change[Group][0]
        elif c == 1:
            T_RGV = T_RGV + T_change[Group][1]
        T_down[c][d] = T_RGV + T_process_1[Group]
        
#        print('T_down',T_down)
        if c == 0:
            Num = 2 * (d + 1)
        elif c == 1:
            Num = 2 * (d + 1) - 1
        State_CNC[0][c][d] = 1
        counts = counts + 1
#        print(NUM_CNC)
        Answer_CSV[loop].append([])
        if counts_CNC[c][d] != 0:
            if find_free_min_add(T_CNC_matrix,State_CNC,0,0,1,1) == (2,2):
                (m,n) = find_martrix_min_value(T_down,State_CNC,1,1)
                T_RGV = max(T_RGV + T_move[Group][abs(State_RGV-n)],T_down[m][n])
            else:
                (m,n) = find_free_min_add(T_CNC_matrix,State_CNC,0,0,1,1)
                T_RGV = T_RGV + T_move[Group][abs(State_RGV-n)]
#           上件
#                print(m,n)
            if m == 0:
                T_RGV = T_RGV + T_change[Group][0]
            elif m == 1:
                T_RGV = T_RGV + T_change[Group][1]
            State_CNC[0][m][n] = 1
            State_RGV = n
#            print(counts_CNC)
            if counts_CNC[m][n] != 0:
                T_RGV = T_RGV + T_clean[Group]
            counts_CNC[m][n] = counts_CNC[m][n] + 1
            T_down[m][n] = T_process_2[Group] + T_RGV
            
#            print(NUM_CNC)
            NUM_CNC[m][n] = NUM_CNC[c][d]
#            print(NUM_CNC[m][n])
            if m == 0:
                Num = 2 * (n + 1)
            elif m == 1:
                Num = 2 * (n + 1) - 1
#            print(Answer_CSV[loop])
#            print(NUM_CNC[m][n] - 1)
            Answer_CSV[loop][NUM_CNC[m][n] - 1].append('CNC{}#'.format(Num))
            T_up = T_RGV
            Answer_CSV[loop][NUM_CNC[m][n] - 1].append(T_up)
            Answer_CSV[loop][NUM_CNC[m][n] - 1].append(T_down[m][n])
        NUM_CNC[c][d] = counts
#        print(counts)
        counts_CNC[c][d] = counts_CNC[c][d] + 1
        T_down[c][d] = T_process_1[Group] + T_RGV
#            超过8小时即结束循环
        if T_down[c][d] + T_change[Group][c] + T_clean[Group] > T_total:
            break
#            将结果输出至CSV表格
        if c == 0:
            Num = 2 * (d + 1)
        elif c == 1:
            Num = 2 * (d + 1) - 1
#        print(NUM_CNC[c][d])
        Answer_CSV[loop][NUM_CNC[c][d] - 1].append(NUM_CNC[c][d])
        Answer_CSV[loop][NUM_CNC[c][d] - 1].append('CNC{}#'.format(Num))
        T_up = T_RGV
        Answer_CSV[loop][times].append(T_up)
        Answer_CSV[loop][times].append(T_down[c][d])
        for i in range (2):
            for j in range (4):
                if T_RGV >= T_down[i][j]:
                    State_CNC[0][i][j] = 0
    counts_CSV.append(counts)
#    print(Answer_CSV)
MAX_loop = 0
for loop in range (Loop):
    if MAX_OUTPUT < counts_CSV[loop]:
        MAX_OUTPUT = counts_CSV[loop]
        MAX_loop = loop
print(Answer_CSV[MAX_loop])
print(counts_CSV[MAX_loop])
writer = csv.writer(open("Case_2_2_2_2_test.csv",'w',newline=''))
for item in Answer_CSV[MAX_loop]:
    writer.writerow(item)
#        

Case_3_1

# -*- coding: utf-8 -*-
"""
Created on Sat Sep 15 14:00:24 2018

@author: LIU Zhendong
"""
import csv
from itertools import chain
import random
'''按照A*算法进行RGV分配加工所需时间模拟(模拟1%故障率)======================================'''


Group = 2

def find_martrix_min_value(data_matrix,State_CNC):
    '''''
    功能:找到矩阵State_CNC为0下的data_matrix最小值
    '''
    min_data = 1000000000
    add=(0,0)
    for i in range(len(data_matrix)):
        for j in range (len(data_matrix[i])):
            if data_matrix[i][j] < min_data and State_CNC[i][j] == 0:
                min_data = data_matrix[i][j]
                add = (i,j)
    return add

def Breakdown_random():
    '''''
    功能:随机产生故障并返回故障机器编号和故障时间
    '''
    a = random.randint(1,800)
    b = random.randint(600,1200)
    if a > 8:
        return (2,0,0)
    elif a % 2 == 0:
        return (0 , int(a/2-1) , b)
    elif a % 2 == 1:
        return (1 , int((a-1)/2) , b)


'''初始化变量==============================================='''
T_total = 8 * 60 * 60
T_CNC_matrix = []
State_CNC = []          # 0表示完成工作进入等待    1 表示正在工作   
State_RGV = 0           # 表示RGV的位置 其中0,1,2,3分别代表位于1#、2#,3#、4#,5#、6#,7#、8#之间
State_CNC_Break = []    # 存放故障结束时间  0 表示无故障
T_RGV = 0
Count_break = 0
T_G = []
T_H = []
T_down = []
Answer_CSV = []
Answer_CSV_Break =[]
NUM_CNC = []            # 存放CNC上物品编号
for i in range (2):
    State_CNC.append([])
    T_CNC_matrix.append([])
    T_G.append([])
    T_down.append([])
    State_CNC_Break.append([])
    NUM_CNC.append([])
    for j in range(4):
        State_CNC[i].append(0)
        T_CNC_matrix[i].append(0)
        T_G[i].append(0)
        T_down[i].append(0)
        State_CNC_Break[i].append(0)
        NUM_CNC[i].append(0)
        
        
        


'''模拟主循环====================================================='''
for times in range (1000):
#    初始化
    T_change = [[31,28],[35,30],[32,27]]
    T_clean = [25,30,25]
    T_move = [[0,20,33,46],[0,23,41,59],[0,18,32,46]]
    T_process = [560,580,545]
    T_process_1 = [400,280,455]
    T_process_2 = [378,500,182]
    for j in range (2):
        for k in range (4):
            if j == 0:
                T_G[j][k] = T_change[Group][0]
            elif j == 1:
                T_G[j][k] = T_change[Group][1]
#    print(T_G)
    for i in range (2):
        if State_RGV == 0:
            T_G[i][1] = T_G[i][1] + T_move[Group][1]
            T_G[i][2] = T_G[i][2] + T_move[Group][2]
            T_G[i][3] = T_G[i][3] + T_move[Group][3]
        elif State_RGV == 1:
            T_G[i][0] = T_G[i][0] + T_move[Group][1]
            T_G[i][2] = T_G[i][2] + T_move[Group][1]
            T_G[i][3] = T_G[i][3] + T_move[Group][2]
        elif State_RGV == 2:
            T_G[i][0] = T_G[i][0] + T_move[Group][2]
            T_G[i][1] = T_G[i][1] + T_move[Group][1]
            T_G[i][3] = T_G[i][3] + T_move[Group][1]
        elif State_RGV == 3:
            T_G[i][0] = T_G[i][0] + T_move[Group][3]
            T_G[i][1] = T_G[i][1] + T_move[Group][2]
            T_G[i][2] = T_G[i][2] + T_move[Group][1]
#    print(T_G)
    for j in range (2):
        T_H.append([])
        for k in range (4):
            T_H[j].append(T_process[Group])

    for i in range (2):
        for j in range (4):
            T_CNC_matrix[i][j] = T_G[i][j] + T_H[i][j] + T_clean[Group]
#    print(T_CNC_matrix)
    add = find_martrix_min_value(T_CNC_matrix,State_CNC)
    (a,b) = add
#    print(add)
    T_RGV = T_RGV + T_move[Group][abs(State_RGV-b)]

    if a == 0:
        Num = 2 * (b + 1)
    elif a == 1:
        Num = 2 * (b + 1) - 1
    if a == 0:
        T_RGV = T_RGV + T_change[Group][0]
    elif a == 1:
        T_RGV = T_RGV + T_change[Group][1]
    State_CNC[a][b] = 1
    NUM_CNC[a][b] = times + 1
    T_down[a][b] = T_process[Group] + T_RGV
    
#    超过8小时即结束循环
    if T_down[a][b] + T_change[Group][a] + T_clean[Group] > T_total:
        break
#    将结果输出至CSV表格
    Answer_CSV.append([]) 
    Answer_CSV[times].append(times+1)
    Answer_CSV[times].append('CNC{}#'.format(Num))
    T_up = T_RGV
    Answer_CSV[times].append(T_up)
    Answer_CSV[times].append(T_down[a][b])
#    print(T_RGV)
    '''随机产生故障'''
    (e,f,g)= Breakdown_random()
    if times > 7 and e != 2:
#        存在故障
        State_CNC[e][f] = 1
        T_down[e][f] = g + T_RGV
        State_CNC_Break[e][f] = T_down[e][f]
        Answer_CSV_Break.append([])
        Answer_CSV_Break[Count_break].append(NUM_CNC[e][f])
        if e == 0:
            Num_Break = 2 * (f + 1)
        elif e == 1:
            Num_Break = 2 * (f + 1) - 1
        Answer_CSV_Break[Count_break].append('CNC{}#'.format(Num_Break))
        T_up = T_RGV
        Answer_CSV_Break[Count_break].append(T_up)
        Answer_CSV_Break[Count_break].append(T_down[e][f])
        Count_break = Count_break + 1
    for i in range (2):
        for j in range (4):
            if T_RGV > State_CNC_Break[i][j] and State_CNC_Break[i][j] != 0:
                State_CNC_Break[i][j] = 0
                State_CNC[i][j] = 0
                
        
#    清洗
    if times > 7:
        T_RGV = T_RGV + T_clean[Group]
    State_RGV = b
    
#    全部CNC在工作或故障,没有CNC等待,RGV自动跳转至下一个最快结束的机器位
    if len(set(list(chain.from_iterable(State_CNC)))) == 1:
        for i in range (2):
            for j in range (4):
                if State_CNC_Break[i][j] == 0:
                    State_CNC[i][j] = 0
        (c,d)=find_martrix_min_value(T_down,State_CNC)
        T_RGV = T_RGV + T_move[Group][abs(State_RGV-d)]
        State_RGV = d
        T_RGV = T_down[c][d]
    if T_down[a][b] + T_change[Group][a] + T_clean[Group] > T_total:
        break
#    print(State_CNC)
#    print(T_RGV)
#    print(State_RGV)
print(Answer_CSV)
print(Answer_CSV_Break)
print(Count_break)
writer = csv.writer(open("Case_3_1_3.csv",'w',newline=''))
for item in Answer_CSV:
    writer.writerow(item)

writer_1 = csv.writer(open("Case_3_1_Break_3.csv",'w',newline=''))
for item_1 in Answer_CSV_Break:
    writer_1.writerow(item_1)

Case_3_2

# -*- coding: utf-8 -*-
"""
Created on Sun Sep 16 17:06:37 2018

@author: LIU Zhendong
"""
'''两道工序按照A*算法进行RGV分配加工所需时间模拟(模拟1%故障率)======================================'''
import csv
from itertools import chain
import random
'''穷举法--两道工序======================================'''
'''
算法规则:
RGV总共有三种工作要做
1、给1类刀具CNC上原件
2、把1类刀具CNC上原件给二类刀具
3、将2类刀具CNC上熟件卸下清洗存放
假设从1类刀具CNC上卸下的原件无处存放,需要RGV停止等待2类刀具
CNC结束工作再给其装上,期间RGV不能做其他事情
如果RGV遇到1类刀具CNC和2类刀具CNC同时请求时,优先选择2类刀具
CNC装件
'''

Group = 2
Loop = 254
Times = 1024
def find_martrix_min_value(data_matrix,State_CNC,State_CNC_Break,p,q):
    '''''
    功能:找到矩阵State_CNC[0]为0下的data_matrix最小值
    '''
    min_data = 1000000000
    add=(2,2)
    for i in range(len(data_matrix)):
        for j in range (len(data_matrix[i])):
            if data_matrix[i][j] < min_data and State_CNC[p][i][j] == q and State_CNC_Break[i][j] == 0:
                min_data = data_matrix[i][j]
                add = (i,j)
    return add

def find_free_min_add(data_matrix,State_CNC,State_CNC_Break,p,q,r,s):
    '''''
    功能:找到矩阵State_CNC一定条件下最小值
    '''
    min_data = 1000000000
    add=(2,2)
    for i in range(len(data_matrix)):
        for j in range (len(data_matrix[i])):
            if data_matrix[i][j] < min_data and State_CNC[p][i][j] == q and State_CNC[r][i][j] == s and State_CNC_Break[i][j] == 0:
                min_data = data_matrix[i][j]
                add = (i,j)
    return add
def Breakdown_random():
    '''''
    功能:随机产生故障并返回故障机器编号和故障时间
    '''
    a = random.randint(1,800)
    b = random.randint(600,1200)
    if a > 8:
        return (2,0,0)
    elif a % 2 == 0:
        return (0 , int(a/2-1) , b)
    elif a % 2 == 1:
        return (1 , int((a-1)/2) , b)


'''初始化变量==============================================='''
T_total = 8 * 60 * 60
MAX_OUTPUT = 0
T_CNC_matrix = []
# 表示CNC剩余工作时间列表
State_CNC = [[],[]]          
'''
State_CNC[0]  为一张2 * 4 列表,表示CNC状态
    其中0表示完成工作进入等待    1 表示正在工作
State_CNC[1]  为一张2 * 4 列表, 表示CNC携带的刀具
    其中0表示携带第一类刀具      1 表示携带第二类刀具
'''
State_RGV = 0

'''
State_RGV表示RGV的位置
    其中State_RGV = 0,1,2,3分别代表位于1#、2#,3#、4#,5#、6#,7#、8#之间

'''
State_CNC_Break = []    # 存放故障结束时间  0 表示无故障
T_RGV = 0
T_G = []
T_H = []
counts_CSV = []
Count_break = 0
T_down = []
Answer_CSV = []
Answer_CSV_Break =[]
NUM_CNC = []            # 存放CNC上物品编号
counts_CNC = []          # 记录CNC处理产品数量
T_change = [[31,28],[35,30],[32,27]]
T_clean = [25,30,25]
T_move = [[0,20,33,46],[0,23,41,59],[0,18,32,46]]
T_process = [560,580,545]
T_process_1 = [400,280,455]
T_process_2 = [378,500,182]
for i in range (2):
    State_CNC[0].append([])
    State_CNC[1].append([])
    T_CNC_matrix.append([])
    T_G.append([])
    T_down.append([])
    State_CNC_Break.append([])
    NUM_CNC.append([])
    counts_CNC.append([])
    for j in range(4):
        State_CNC[0][i].append(0)
        State_CNC[1][i].append(0)
        T_CNC_matrix[i].append(0)
        T_G[i].append(0)
        T_down[i].append(0)
        State_CNC_Break[i].append(0)
        NUM_CNC[i].append(0)
        counts_CNC[i].append(0)
#print(State_CNC)
        
        

'''穷举刀具各种情况主循环'''

for loop in range (Loop):
    for i in range (2):
        for j in range (4):
            T_CNC_matrix[i][j] = 0
            NUM_CNC[i][j] = 0
            counts_CNC[i][j] = 0
            State_CNC[0][i][j] = 0
            State_CNC[1][i][j] = 0
            T_CNC_matrix[i][j] = 0
            counts_CNC[i][j] = 0
    NUM_1 = 0
    NUM_2 = 0
    Count_break = 0
    NUM = '{:08b}'.format(loop + 1)
    list_NUM = list(str(NUM))
    State_CNC[1][1][0] = int(list_NUM[7])
    State_CNC[1][0][0] = int(list_NUM[6])
    State_CNC[1][1][1] = int(list_NUM[5])
    State_CNC[1][0][1] = int(list_NUM[4])
    State_CNC[1][1][2] = int(list_NUM[3])
    State_CNC[1][0][2] = int(list_NUM[2])
    State_CNC[1][1][3] = int(list_NUM[1])
    State_CNC[1][0][3] = int(list_NUM[0])
#    State_CNC[1][1][0] = 0
#    State_CNC[1][0][0] = 0
#    State_CNC[1][1][1] = 0
#    State_CNC[1][0][1] = 1
#    State_CNC[1][1][2] = 1
#    State_CNC[1][0][2] = 1
#    State_CNC[1][1][3] = 1
#    State_CNC[1][0][3] = 1
#    print(State_CNC[1])
    for i in range (2):
        for j in range (4):
            if State_CNC[1][i][j] == 0:
                NUM_1 = NUM_1 + 1       #1类刀具CNC数目
            elif State_CNC[1][i][j] == 1:
                NUM_2 = NUM_2 + 1       #2类刀具CNC数目
#    print(NUM_1)
            

    
    
    
#    定义时间矩阵表示从目前位置到完成整件预估时间  
#    T_move + T_change + T_process_1 + T_change + T_move + T_change + T_process_2 + T_clean
#    预估时间矩阵T_CNC_matrix求解===============================================
#    2类刀具CNC预估时间矩阵
    for i in range (2):
        for j in range (4):
            if State_CNC[1][i][j] == 1:               # 携带2类刀具CNC
#                T_change
                if i == 0:
                    T_CNC_matrix[i][j] = 2 * T_change[Group][0]
                elif i == 1:
                    T_CNC_matrix[i][j] = 2 * T_change[Group][1]

#                T_process_2
                T_CNC_matrix[i][j] = T_CNC_matrix[i][j] + T_process_2[Group]

#                T_clean
                T_CNC_matrix[i][j] = T_CNC_matrix[i][j] + T_clean[Group]
#    print(T_CNC_matrix)


    Answer_CSV.append([])
    Answer_CSV_Break.append([])
    T_RGV = 0
    counts = 0
    counts_1 = 0            # 计数:1类刀具CNC正在加工零件数目
    counts_2 = 0            # 计数:2类刀具CNC正在加工零件数目
    State_RGV = 0
#循环求解
    for times in range (Times):
#        print(counts+1,'===================================================')
#        for i in range (2):
#            for j in range (4):
#                State_CNC[0][i][j] = 0
#        1类刀具CNC预估时间矩阵
#        State_CNC[1][1][0] = 0
#        State_CNC[1][0][0] = 1
#        State_CNC[1][1][1] = 1
#        State_CNC[1][0][1] = 0
#        State_CNC[1][1][2] = 1
#        State_CNC[1][0][2] = 0
#        State_CNC[1][1][3] = 0
#        State_CNC[1][0][3] = 0
#        NUM_1 = 5
        
        for i in range (2):
            for j in range (4):
                if State_CNC[1][i][j] == 0:               # 携带1类刀具CNC
#                    T_change
                    if i == 0:
                        T_CNC_matrix[i][j] = T_change[Group][0]
                    elif i == 1:
                        T_CNC_matrix[i][j] = T_change[Group][1]
#                    T_process_1
                    T_CNC_matrix[i][j] = T_CNC_matrix[i][j] + T_process_1[Group]
#        print(T_CNC_matrix)
        for i in range (2):
            for j in range (4):
                if State_CNC[1][i][j]== 0:
                    for k in range (2):
                        for l in range (4):
                            if State_CNC[1][k][l] == 1:
                                T_G[k][l] = T_CNC_matrix[i][j] + T_move[Group][abs(l-j)] + T_CNC_matrix[k][l]
                    (a,b) = find_martrix_min_value(T_G,State_CNC,State_CNC_Break,1,1)
                    if (a,b) == (2,2):
                        T_CNC_matrix[i][j] = T_G[0][0] + T_move[Group][abs(State_RGV-j)] + 1200
                    else:
                        T_CNC_matrix[i][j] = T_G[a][b] + T_move[Group][abs(State_RGV-j)]
        (c,d) = find_martrix_min_value(T_CNC_matrix,State_CNC,State_CNC_Break,1,0)
        for i in range (2):
            for j in range(4):
                T_G[i][j] = 0
#        print(T_CNC_matrix)
#    预估时间矩阵T_CNC_matrix求解===============================================





# =============================================================================
# NUM_1 1CNC数
# counts 零件标号
# counts_1 正在加工
# counts_1_free 加工完成空闲数
# counts_2 正在加工
# counts_2_free 加工完成空闲数

# =============================================================================
#

        for i in range (2):
            for j in range (4):
                if T_RGV >= T_down[i][j]:
                    State_CNC[0][i][j] = 0
#        print(State_CNC[0])
#        print(State_CNC_Break)
        (c,d) = find_free_min_add(T_CNC_matrix,State_CNC,State_CNC_Break,0,0,1,0)
#            移动至目标CNC
#        print(c,d)
        for i in range (2):
            for j in range (4):
                if T_RGV >= T_down[i][j]:
                    State_CNC[0][i][j] = 0
        if(c,d) == (2,2):
            (c,d) = find_martrix_min_value(T_down,State_CNC,State_CNC_Break,1,0)
            if (c,d) == (2,2):
                (h,o) = (0,0)
                T_RGV = T_down[0][0]
            else:
                T_RGV = max(T_RGV + T_move[Group][abs(State_RGV-d)],T_down[c][d])
        else:
            T_RGV = T_RGV + T_move[Group][abs(State_RGV-d)]
        
        State_RGV = d
#           上件
        if c == 0:
            T_RGV = T_RGV + T_change[Group][0]
        elif c == 1:
            T_RGV = T_RGV + T_change[Group][1]
        if (c,d) == (2,2):
            (c,d) = (0,0)
            T_RGV = T_down[0][0]
        T_down[c][d] = T_RGV + T_process_1[Group]
#        产生随机故障
        (e,f,g)= Breakdown_random()
        if times > NUM_1 and e != 2:
#            存在故障
            State_CNC[0][e][f] = 1
            T_down[e][f] = g + T_RGV
            State_CNC_Break[e][f] = T_down[e][f]
            Answer_CSV_Break[loop].append([])
            Answer_CSV_Break[loop][Count_break].append(NUM_CNC[e][f])
            if e == 0:
                Num_Break = 2 * (f + 1)
            elif e == 1:
                Num_Break = 2 * (f + 1) - 1
            Answer_CSV_Break[loop][Count_break].append('CNC{}#'.format(Num_Break))
            T_up = T_RGV
            Answer_CSV_Break[loop][Count_break].append(T_up)
            Answer_CSV_Break[loop][Count_break].append(T_down[e][f])
            Count_break = Count_break + 1
        for i in range (2):
            for j in range (4):
                if T_RGV > State_CNC_Break[i][j] and State_CNC_Break[i][j] != 0:
                    State_CNC_Break[i][j] = 0
                    State_CNC[0][i][j] = 0
#        print('T_down',T_down)
        if c == 0:
            Num = 2 * (d + 1)
        elif c == 1:
            Num = 2 * (d + 1) - 1
        State_CNC[0][c][d] = 1
        counts = counts + 1
#        print(NUM_CNC)
        Answer_CSV[loop].append([])
        if counts_CNC[c][d] != 0:
            if find_free_min_add(T_CNC_matrix,State_CNC,State_CNC_Break,0,0,1,1) == (2,2):
                (m,n) = find_martrix_min_value(T_down,State_CNC,State_CNC_Break,1,1)
                if (m,n) == (2,2):
                    (m,n) = (0,0)
                    T_RGV = T_down[0][0] + 1200
                else:
                    T_RGV = max(T_RGV + T_move[Group][abs(State_RGV-n)],T_down[m][n])
            else:
                (m,n) = find_free_min_add(T_CNC_matrix,State_CNC,State_CNC_Break,0,0,1,1)
                T_RGV = T_RGV + T_move[Group][abs(State_RGV-n)]
#           上件
#                print(m,n)
            if m == 0:
                T_RGV = T_RGV + T_change[Group][0]
            elif m == 1:
                T_RGV = T_RGV + T_change[Group][1]
            if (m,n) == (2,2):
                (m,n) == (0,0)
                S_RGV = T_down[0][0]
            State_CNC[0][m][n] = 1
            State_RGV = n
#            print(counts_CNC)
            if counts_CNC[m][n] != 0:
                T_RGV = T_RGV + T_clean[Group]
            counts_CNC[m][n] = counts_CNC[m][n] + 1
            T_down[m][n] = T_process_2[Group] + T_RGV
            
#            print(NUM_CNC)
            NUM_CNC[m][n] = NUM_CNC[c][d]
#            print(NUM_CNC[m][n])
            if m == 0:
                Num = 2 * (n + 1)
            elif m == 1:
                Num = 2 * (n + 1) - 1
#            print(Answer_CSV[loop])
#            print(NUM_CNC[m][n] - 1)
            Answer_CSV[loop][NUM_CNC[m][n] - 1].append('CNC{}#'.format(Num))
            T_up = T_RGV
            Answer_CSV[loop][NUM_CNC[m][n] - 1].append(T_up)
            Answer_CSV[loop][NUM_CNC[m][n] - 1].append(T_down[m][n])
        NUM_CNC[c][d] = counts
#        print(counts)
        counts_CNC[c][d] = counts_CNC[c][d] + 1
        T_down[c][d] = T_process_1[Group] + T_RGV
#            超过8小时即结束循环
        if T_down[c][d] + T_change[Group][c] + T_clean[Group] > T_total:
            break
#            将结果输出至CSV表格
        if c == 0:
            Num = 2 * (d + 1)
        elif c == 1:
            Num = 2 * (d + 1) - 1
#        print(NUM_CNC[c][d])
        Answer_CSV[loop][NUM_CNC[c][d] - 1].append(NUM_CNC[c][d])
        Answer_CSV[loop][NUM_CNC[c][d] - 1].append('CNC{}#'.format(Num))
        T_up = T_RGV
        Answer_CSV[loop][times].append(T_up)
        Answer_CSV[loop][times].append(T_down[c][d])
        for i in range (2):
            for j in range (4):
                if T_RGV >= T_down[i][j]:
                    State_CNC[0][i][j] = 0
    counts_CSV.append(counts)
#    print(Answer_CSV)
MAX_loop = 0
for loop in range (Loop):
    if MAX_OUTPUT < counts_CSV[loop]:
        MAX_OUTPUT = counts_CSV[loop]
        MAX_loop = loop
print(Answer_CSV[MAX_loop])
print(counts_CSV[MAX_loop])
print(Answer_CSV_Break[MAX_loop])

writer = csv.writer(open("Case_3_2_3.csv",'w',newline=''))
for item in Answer_CSV[MAX_loop]:
    writer.writerow(item)

writer_1 = csv.writer(open("Case_3_2_3_Break.csv",'w',newline=''))
for item_1 in Answer_CSV_Break[MAX_loop]:
    writer_1.writerow(item_1)

猜你喜欢

转载自blog.csdn.net/weixin_42733218/article/details/82886310