圖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輸送生料(未加工的物料);左邊爲下料傳送帶,負責將成料(加工並清洗完成的物料)送出系統。其他爲保證系統正常運行的輔助設備。
附圖1:RGV—CNC車間佈局圖
附圖2:帶機械手臂和清洗槽的RGV實物圖
附圖2是RGV的實物圖,包括車體、機械臂、機械手爪和物料清洗槽等。
附圖3:RGV機械手臂前端的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條下料傳送帶等附屬設備構成。
(1)CNC:在上料傳送帶和下料傳送帶的兩側各安裝4臺CNC,等距排列,每臺CNC同一時間只能安裝1種刀具加工1個物料。
如果物料的加工過程需要兩道工序,則需要有不同的CNC安裝不同的刀具分別加工完成,在加工過程中不能更換刀具。第一和第二道工序需要在不同的CNC上依次加工完成,完成時間也不同,每臺CNC只能完成其中的一道工序。
(2)RGV:RGV帶有智能控制功能,能夠接收和發送指令信號。根據指令能在直線軌道上移動和停止等待,可連續移動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)