物流模擬可以這樣實現:資料記錄

文章作者:環球物流諮詢首席諮詢顧問——黃堯笛

記錄下物流系統執行的資料是物流模擬系統最為重要的環節。我們在構建模擬系統時要全面、充分的考慮到系統執行中需要輸出哪些資料,並在MATLAB中建立資料表,將系統執行的資料記錄到表裡,以供下一環節的資料統計與分析呼叫。本文將簡要介紹筆者在構建物流模擬系統時的資料記錄方式。

資料表產生的邏輯

物流模擬可以這樣實現:資料記錄

1、流程活動

“卸貨”、“檢驗”、“理貨”、“上架”、“分揀”等流程為主要倉儲流程活動(二級流程可根據實際需求在流程庫裡匯出)。流程中的活動規則決定了模擬系統中服務檯的執行機制。

倉儲運作參考流程(示例)

物流模擬可以這樣實現:資料記錄

2、資源呼叫

流程活動中需要呼叫的“人、設施、裝置”資源,資源的狀態分為“佔用、空閒”兩種狀態,如果資源被佔用,則需要等待,反之執行。

邏輯舉例

物流模擬可以這樣實現:資料記錄

3、資料記錄

各個服務檯在進行活動時需要記錄活動資料,活動資料的結構如前文中所說,可根據系統輸出的需要進行構造,本文中舉例說明資料記錄中的幾個重要的資料輸出。活動時間記錄時分為:開始時間與結束時間,上一活動結束到下一活動開始的時間空閒為等待時間。

1)時間:

所有活動的執行都是在某個時間點上執行,大部分的資料統計都需要使用到時間資料。時間可以按需求的精準程度制定時間刻度;

2)佇列數:

佇列數是等待需要處理的貨物(托盤/箱/盒)的數量,佇列數的多少體現了系統的繁忙程度;

3)服務檯數量:

一個服務檯的構成由“人、設施、裝置”組成,服務檯數量影響了服務檯同時處理佇列的能力。

資料記錄表(示例)

物流模擬可以這樣實現:資料記錄

4、資料記錄結果

物流模擬可以這樣實現:資料記錄

5、MATLAB原始碼:

系統執行過程的資料記錄(示例)

[M,N] =size(worksheet_raw); %定義worksheet_raw行列數

for I = 1:M-1

%到貨

if any(arrivaltable(:,1) ==worksheet_data(I,raw_wtime)) %到貨表列名稱寫入

if worksheet_data(I,raw_unload_queue)> 0

pallet_data =arrivaltable(find(arrivaltable(:,1) == worksheet_data(I,raw_wtime)),2) +worksheet_data(I,raw_unload_queue);

else

pallet_data =arrivaltable(find(arrivaltable(:,1) == worksheet_data(I,raw_wtime)),2);

end

end

pallet_data_0 = pallet_data;

if I > 1

for n = 1:worksheet_n

%%%調整卸貨資源

ifany(worksheet_data(:,raw_e_unload) == I) %假設上一行有資源釋放

deskNo =worksheet_data(find(worksheet_data(:,raw_e_unload) == I),raw_desk_unload);

% deskNo =sum(worksheet_data(:,raw_e_unload) == I - 1); %檢視服務檯數量

if deskNo > 1 %如果是多服務檯

ifany(rescall_data(:,raw_unload_per) == 0)

deskNo0 =length(find(rescall_data(:,raw_unload_per) == 0)); %找到資源表中被佔用資源座標

for desk_No = 1:deskNo

rescall_data(desk_No,raw_unload_per) = 1; %調整資源表中的卸貨人員資源狀態

rescall_data(desk_No,raw_eforklift) = 1; %調整資源表中的電叉車資源狀態

rescall_data(desk_No,raw_unloadar) = 1; %調整資源表中的卸貨埠資源狀態

end

end

elseif deskNo <= 1 %如果是單個服務檯

rescall_data(min(find(rescall_data(:,raw_unload_per) == 0,1)),raw_unload_per) = 1; %調整資源表中的卸貨人員資源狀態

rescall_data(min(find(rescall_data(:,raw_eforklift) == 0,1)),raw_eforklift) = 1; %調整資源表中的電叉車資源狀態

rescall_data(min(find(rescall_data(:,raw_unloadar) == 0,1)),raw_unloadar) = 1; %調整資源表中的卸貨埠資源狀態

end

end

end

end

%%%調整檢驗資源

if any(worksheet_data(:,raw_e_inspect) ==I) %假設本行有資源釋放

deskNo =worksheet_data(find(worksheet_data(:,raw_e_inspect) == I),raw_desk_inspect);

% deskNo =sum(worksheet_data(:,raw_e_inspect) == I); %檢視服務檯數量

if deskNo > 1 %如果是多服務檯

ifany(rescall_data(:,raw_inspect_per) == 0)

deskNo0 =length(find(rescall_data(:,raw_inspect_per) == 0)); %找到資源表中被佔用資源座標

for desk_No = 1:deskNo

rescall_data(desk_No,raw_inspect_per) = 1; %調整資源表中的卸貨人員資源狀態

end

end

elseif deskNo <= 1 %如果是單個服務檯

rescall_data(min(find(rescall_data(:,raw_inspect_per) == 0,1)),raw_inspect_per) = 1; %調整資源表中的卸貨人員資源狀態

end

end

%%%調整檢驗資源完成

%%%調整上架資源

if any(worksheet_data(:,raw_e_store) ==I) %假設本行有資源釋放

deskNo = worksheet_data(find(worksheet_data(:,raw_e_store) == I),raw_desk_store);

% deskNo =sum(worksheet_data(:,raw_e_inspect) == I); %檢視服務檯數量

if deskNo > 1 %如果是多服務檯

ifany(rescall_data(:,raw_store_per) == 0)

deskNo0 =length(find(rescall_data(:,raw_store_per) == 0)); %找到資源表中被佔用資源座標

for desk_No = 1:deskNo

rescall_data(desk_No,raw_store_per) = 1; %調整資源表中的卸貨人員資源狀態

end

end

elseif deskNo <= 1 %如果是單個服務檯

rescall_data(min(find(rescall_data(:,raw_store_per) == 0,1)),raw_store_per) = 1; %調整資源表中的卸貨人員資源狀態

end

end

%%%調整上架資源完成

worksheet_n = length(worksheet_txt);

if sum(pallet_data > 0) %判斷是否有新到貨資料 【到貨資料】

worksheet_data(I,raw_unload_queue) =sum(pallet_data); %新到貨資料進入佇列 【到貨佇列】

pallet_data(:) = 0; %到貨表清零

end

%%%卸貨流程

%%%%檢視佇列

if worksheet_data(I,raw_unload_queue) >0 %判斷pallet_data是否有到貨 【判斷到貨佇列】

%%%%構建服務檯

if length(find(rescall_data(:,raw_unload_per)> 0)) >= 1 && length(find(rescall_data(:,raw_eforklift) > 0))>= 1 && length(find(rescall_data(:,raw_unloadar) > 0)) >=1 %服務檯是否空閒 【判斷卸貨資源服務檯】

deskNo_unload =min([length(find(rescall_data(:,raw_unload_per) > 0)),length(find(rescall_data(:,raw_eforklift)> 0)),length(find(rescall_data(:,raw_unloadar) >0)),worksheet_data(I,raw_unload_queue)]); %確定服務檯數量【構建多服務檯】

worksheet_data(I,raw_desk_unload) =deskNo_unload; %記錄服務檯數量【卸貨服務檯數量】

%%%%服務

worksheet_data(I,raw_b_unload) =I; %開始卸貨時間【開始卸貨】

worksheet_data(I,raw_e_unload) = I+ res_data(raw_serviceability,raw_unload_per); %按服務能力確定結束時間【卸貨結束】

%%%%形成佇列

worksheet_data(I +1,raw_unload_queue) = worksheet_data(I,raw_unload_queue) - deskNo_unload; %佇列減少【進入服務檯】

%%%%資源佔用

for unload_i = 1:deskNo_unload %迴圈建立服務檯

rescall_data(min(find(rescall_data(:,raw_unload_per) ~= 0, 1)),raw_unload_per) = 0;

unloadper_sheet(size(unloadper_sheet,1)+ 1,1) = unload_i; %記錄卸貨人員資源監控表

unloadper_sheet(size(unloadper_sheet,1),3) = I;

unloadper_sheet(size(unloadper_sheet,1),4) = I +res_data(raw_serviceability,raw_unload_per);

rescall_data(min(find(rescall_data(:,raw_eforklift)~= 0, 1 )),raw_eforklift) = 0; %資源服務物件減一 【佔用一個卸貨服務檯資源】

eforklift_sheet(size(eforklift_sheet,1) + 1,1) = unload_i; %記錄電叉車資源監控表

eforklift_sheet(size(eforklift_sheet,1),3) = I;

eforklift_sheet(size(eforklift_sheet,1),4) = I + res_data(raw_serviceability,raw_unload_per);

rescall_data(min(find(rescall_data(:,raw_unloadar) ~= 0, 1 )),raw_unloadar)= 0; %資源服務物件減一 【佔用一個卸貨服務檯資源】

unloadar_sheet(size(unloadar_sheet,1) + 1,1) = unload_i; %記錄卸貨臺監控表

unloadar_sheet(size(unloadar_sheet,1),3) = I;

unloadar_sheet(size(unloadar_sheet,1),4) = I + res_data(raw_serviceability,raw_unload_per);

end

else

worksheet_data(I +1,raw_unload_queue) = worksheet_data(I,raw_unload_queue);

end

end

%%%卸貨流程完成

if I > 1

%%%檢驗流程

%%%%檢視並形成佇列

if any(worksheet_data(I -1,raw_inspect_queue)) %上一時間指標佇列是否有剩餘

if any(worksheet_data(I -1,raw_desk_inspect)) %如果上一行有服務檯

queue_surplus = worksheet_data(I -1,raw_inspect_queue) - worksheet_data(I - 1,raw_desk_inspect); %佇列扣除

else

queue_surplus = worksheet_data(I -1,raw_inspect_queue); %判斷佇列是否有剩餘

end

else

queue_surplus = 0;

end

if any(sum(worksheet_data(:,raw_e_unload)== I))

serviceNo_i = find((worksheet_data(:,raw_e_unload)) ==I); %檢視卸貨結束服務數量

queue_new =sum(worksheet_data(:,raw_e_unload) == I) *worksheet_data(serviceNo_i,raw_desk_unload); %貨物檢驗佇列生成

else

queue_new = 0;

end

worksheet_data(I,raw_inspect_queue) =queue_surplus + queue_new; %剩餘佇列順延

% worksheet_data(I,raw_inspect_queue) = sum(worksheet_data(:,raw_e_unload)== I);

if worksheet_data(I,raw_inspect_queue) >0 %判斷是否有佇列等待 【判斷檢驗佇列】

%%%%構建服務檯

iflength(find(rescall_data(:,raw_inspect_per) > 0)) >= 1 %服務檯是否空閒 【判斷卸貨資源服務檯】

deskNo_inspect =min([length(find(rescall_data(:,raw_inspect_per) >0)),worksheet_data(I,raw_inspect_queue)]); %確定服務檯數量【構建多服務檯】

worksheet_data(I,raw_desk_inspect)= deskNo_inspect; %記錄服務檯數量【檢驗服務檯數量】

%%%%服務

worksheet_data(I,raw_b_inspect) =I; %開始卸貨時間【開始卸貨】

worksheet_data(I,raw_e_inspect) = I+ res_data(raw_serviceability,raw_inspect_per); %按服務能力確定結束時間【卸貨結束】

worksheet_data(I +1,raw_inspect_queue) = worksheet_data(I,raw_inspect_queue) -deskNo_inspect; %佇列減少【進入服務檯】

for inspect_i =1:deskNo_inspect %迴圈建立服務檯

rescall_data(min(find(rescall_data(:,raw_inspect_per) ~= 0, 1)),raw_inspect_per) = 0; %資源服務物件減一 【佔用一個卸貨服務檯資源】

inspectper_sheet(size(inspectper_sheet,1) + 1,1) = inspect_i; %記錄卸貨人員資源監控表

inspectper_sheet(size(inspectper_sheet,1),3) = I;

inspectper_sheet(size(inspectper_sheet,1),4)= I + res_data(raw_serviceability,raw_inspect_per);

end

end

end

%%%檢驗流程完成

……