文章作者:环球物流咨询首席咨询顾问——*尧笛
记录下物流系统运行的数据是物流仿真系统最为重要的环节。我们在构建仿真系统时要全面、充分的考虑到系统运行中需要输出哪些数据,并在MATLAB中建立数据表,将系统运行的数据记录到表里,以供下一环节的数据统计与分析调用。本文将简要介绍笔者在构建物流仿真系统时的数据记录方式。
数据表产生的逻辑
1、流程活动
“卸货”、“检验”、“理货”、“上架”、“分拣”等流程为主要仓储流程活动(二级流程可根据实际需求在流程库里导出)。流程中的活动规则决定了仿真系统中服务台的运行机制。
仓储运作参考流程(示例)
2、资源调用
流程活动中需要调用的“人、设施、设备”资源,资源的状态分为“占用、空闲”两种状态,如果资源被占用,则需要等待,反之运行。
逻辑举例
3、数据记录
各个服务台在进行活动时需要记录活动数据,活动数据的结构如前文中所说,可根据系统输出的需要进行构造,本文中举例说明数据记录中的几个重要的数据输出。活动时间记录时分为:开始时间与结束时间,上一活动结束到下一活动开始的时间空闲为等待时间。
1)时间:所有活动的运行都是在某个时间点上运行,大部分的数据统计都需要使用到时间数据。时间可以按需求的精准程度制定时间刻度;
2)队列数:队列数是等待需要处理的货物(托盘/箱/盒)的数量,队列数的多少体现了系统的繁忙程度;
3)服务台数量:一个服务台的构成由“人、设施、设备”组成,服务台数量影响了服务台同时处理队列的能力。
数据记录表(示例)
4、数据记录结果
5、MATLAB源码:
系统运行过程的数据记录(示例)
[M,N]=size(worksheet_raw);%定义worksheet_raw行列数
forI=1:M-1
%到货
ifany(arrivaltable(:,1)==worksheet_data(I,raw_wtime))%到货表列名称写入
ifworksheet_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;
ifI1
forn=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);%查看服务台数量
ifdeskNo1%如果是多服务台
ifany(rescall_data(:,raw_unload_per)==0)
deskNo0=length(find(rescall_data(:,raw_unload_per)==0));%找到资源表中被占用资源坐标
fordesk_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
elseifdeskNo=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
%%%调整检验资源
ifany(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);%查看服务台数量
ifdeskNo1%如果是多服务台
ifany(rescall_data(:,raw_inspect_per)==0)
deskNo0=length(find(rescall_data(:,raw_inspect_per)==0));%找到资源表中被占用资源坐标
fordesk_No=1:deskNo
rescall_data(desk_No,raw_inspect_per)=1;%调整资源表中的卸货人员资源状态
end
end
elseifdeskNo=1%如果是单个服务台
rescall_data(min(find(rescall_data(:,raw_inspect_per)==0,1)),raw_inspect_per)=1;%调整资源表中的卸货人员资源状态
end
end
%%%调整检验资源完成
%%%调整上架资源
ifany(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);%查看服务台数量
ifdeskNo1%如果是多服务台
ifany(rescall_data(:,raw_store_per)==0)
deskNo0=length(find(rescall_data(:,raw_store_per)==0));%找到资源表中被占用资源坐标
fordesk_No=1:deskNo
rescall_data(desk_No,raw_store_per)=1;%调整资源表中的卸货人员资源状态
end
end
elseifdeskNo=1%如果是单个服务台
rescall_data(min(find(rescall_data(:,raw_store_per)==0,1)),raw_store_per)=1;%调整资源表中的卸货人员资源状态
end
end
%%%调整上架资源完成
worksheet_n=length(worksheet_txt);
ifsum(pallet_data0)%判断是否有新到货数据
worksheet_data(I,raw_unload_queue)=sum(pallet_data);%新到货数据进入队列
pallet_data(:)=0;%到货表清零
end
%%%卸货流程
%%%%查看队列
ifworksheet_data(I,raw_unload_queue)0%判断pallet_data是否有到货
%%%%构建服务台
iflength(find(rescall_data(:,raw_unload_per)0))=1length(find(rescall_data(:,raw_eforklift)0))=1length(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;%队列减少
%%%%资源占用
forunload_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
%%%卸货流程完成
ifI1
%%%检验流程
%%%%查看并形成队列
ifany(worksheet_data(I-1,raw_inspect_queue))%上一时间指针队列是否有剩余
ifany(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
ifany(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);
ifworksheet_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;%队列减少
forinspect_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
%%%检验流程完成
……