系统仿真(四):电梯系统的仿真实现

一、 实验背景

 根据第一次作业时间分布,实现电梯仿真系统,检验不同场景下学生到达一楼的时间开销性能。电梯系统是离散系统,由事件驱动,状态在离散时间点上变化,使用先叫先服务方式运行。

二、 已知条件
  1. 到达电梯时间即开始时间 = 起床时间分布+洗漱时间分布。起床时间分布为 N ( 7.633 , 0.7822 ) N(7.633,0.7822) N(7.633,0.7822) ,洗漱时间分布为 N ( 0.17689 , 0.00235 ) N(0.17689,0.00235) N(0.17689,0.00235)
  2. 电梯运行速度1.58s/每层。
  3. 每层停留时间服从 U ( 10 , 60 ) U(10,60) U(10,60)秒。
  4. 电梯运行策略:先呼叫先服务+运行方向楼层排序策略
三、 实现过程

 电梯共存在三种状态空闲、运行未满载(人数<10)、运行且满载(人数=10)。设Event_queue为事件序列,第一行为开始时间及消耗时间,第二行为当前状态,1为到达,0为在电梯中,-1判断是否到达1层或出电梯状态。设queue为等待序列,每一行代表漏乘第一位为人数,第二位及以后为ID号
设queue_in_elevator记录在电梯中的ID。
电梯运行分三种情况:

  1. 学生到达呼叫电梯①有且正开着门③是否满员②是否在一层。
  2. 电梯正在运行中,到达呼叫楼层,依次判断低于呼叫层是否有人排队, 若有并在电梯未满情况下在向下运行的时候同时加入到电梯队列。
  3. 电梯关门等待呼叫。

情况1 type=1

在这里插入图片描述

图1 情况1学生到达流程图

情况2 type=0

在这里插入图片描述

图2 情况2电梯移动过程流程图

情况3 type = -1

在这里插入图片描述

图3 情况3电梯关门等待过程流程图
四、 效果检验

运行过程:

在这里插入图片描述
……

在这里插入图片描述

图4 运行过程

在这里插入图片描述

图5 消耗时间折线图

场景组对比
①设每层20个学生

表1 (5,9)层下平均消耗时间表
楼层数56789
总人数100120140160180
平均消耗时间143.511s41.36567.58952.90865.652
244.179s48.70253.10261.90486.502
341.51553.73160.28959.37464.415
441.05649.85860.92953.57571.541
538.55267.70240.73964.39374.349
总平均41.76252.27156.529658.430872.4918

在这里插入图片描述
图5 不同楼层平均消耗时间对比图
② 根据作者宿舍楼实际情况数据9层,每层64人可得平均使用时间是261.192s.
表2 9层64人下平均消耗时间表

12345平均
376.576196.350267.617266.110199.309261.192s
五、结论

对比平均时间性能可知,随着楼层数的增加,总人数的增加,平均时间开销也相应增加。

附录:

Main.m

clc;clear;
close all;
%***********************
Event_queue= [];%事件队列
N=6;%楼层数
student_num = 20*N;
queue = zeros(N,20);
elevator_loc = 1;%电梯所在楼层
elevator_num_threshold = 10;%电梯人数上限
num_in_elevator = 0;%在电梯中的人数
time_every_floor = 0.0004388; %2.1361/3600s
elevator_dst = 0;
queue_in_elevator = [];
elevator_door = 0;%电梯门的状态

wakeup_time=normrnd(7.633,0.7822,1,student_num);
wash_time=normrnd(0.17689,0.00235,1,student_num);
t=wakeup_time+wash_time;
time=sort(t);

for t=1:student_num
    s(t)=student;
    s(t).id = t;
    s(t).StartTime = time(t);
    s(t).floor = unidrnd(N); %floor=1 2 3 4 5 6 7 8 9
    s(t).left_elevator = 0;%离开电梯时间
    if s(t).floor == 1
        s(t).left_elevator = s(t).StartTime;
    else
        Event_queue = insert_Event_queue(Event_queue, s(t).StartTime, 1,s(t).id);
    end
end
t_floor = []; %打印生成同学对应的楼层
for i = 1:student_num
    t_floor = [t_floor s(i).floor];
end
t_floor;
t_start=[]; %打印生成同学进入电梯系统对应的开始时间
for i =1:student_num
    t_start = [t_start s(i).StartTime];
end
t_start;

t=0;
mid = 0;
while(~isempty(Event_queue))

        
    [t,type,id,Event_queue]=pop_Event_queue(Event_queue);
%**********************************************************************************************
    if type == -1 %电梯关门
        elevator_door = 0;
        if elevator_loc == 1 
            for i = N:-1:1
                if queue(i,1) ~= 0
                    elevator_dst = i;
                    break;
                end
            end
            if i == 1
                elevator_dst = 0;
            else
                Event_queue = insert_Event_queue(Event_queue,t+time_every_floor*(elevator_dst-1), 0, elevator_dst);
            end
        else
            time_arrive_next_floor = t + time_every_floor;%去下一层
            Event_queue = insert_Event_queue(Event_queue,time_arrive_next_floor, 0, elevator_loc-1);%insert change event
        end
%**********************************************************************************************         
    elseif type == 0 %电梯运行
       elevator_loc = id;%电梯楼层
       elevator_door = 1;
       if elevator_loc == 1%出电梯
           while(num_in_elevator ~= 0)
               temp_id = queue_in_elevator(1);
               s(temp_id).left_elevator = t;%记录下时间
               queue_in_elevator = queue_in_elevator(2:length(queue_in_elevator));
               num_in_elevator = num_in_elevator - 1;
           end
%            queue_in_elevator = [];
           elevator_dst = 0;
           time_elevator_close = t + (10 + 50 * rand())/3600;
           Event_queue = insert_Event_queue(Event_queue,time_elevator_close, -1, elevator_loc);%insert close event
       elseif elevator_loc == elevator_dst
           elevator_dst = 1;
           time_elevator_close = t + (10 + 50 * rand())/3600;
           Event_queue = insert_Event_queue(Event_queue,time_elevator_close, -1, elevator_loc);%insert close event
           if queue(elevator_loc,1) ~= 0
               [queue, pop_id] = pop_queue(queue,elevator_loc,elevator_num_threshold-num_in_elevator);
                while(~isempty(pop_id))
                    temp_id = pop_id(1);
                    queue_in_elevator = [queue_in_elevator temp_id];%ID放入电梯里
                    num_in_elevator = num_in_elevator + 1;
                    pop_id = pop_id(2:length(pop_id));
                end
           end
       elseif elevator_dst == 1 
           if queue(elevator_loc,1) ~= 0 && num_in_elevator < elevator_num_threshold%判断是否有人
               [queue, pop_id] = pop_queue(queue,elevator_loc,elevator_num_threshold-num_in_elevator);
                while(~isempty(pop_id))%挨层判断
                    temp_id = pop_id(1);
                    queue_in_elevator = [queue_in_elevator temp_id];
                    num_in_elevator = num_in_elevator + 1;
                    pop_id = pop_id(2:length(pop_id));
                end
                time_elevator_close = t + (10 + 50 * rand())/3600;
                Event_queue = insert_Event_queue(Event_queue,time_elevator_close, -1, elevator_loc);%insert close event
           else
                Event_queue = insert_Event_queue(Event_queue,t+time_every_floor, 0, elevator_loc-1);%insert change event
           end
      end
 %**********************************************************************************************   
    elseif type == 1% 电梯
        if elevator_loc == s(id).floor && elevator_door == 1%刚好电梯在并且门开
                queue_in_elevator = [queue_in_elevator id];
                num_in_elevator = num_in_elevator + 1;
        elseif queue(s(id).floor,1) == 0 %判断当前楼层队列是否为空
            temp_num_in_queue = queue(s(id).floor,1);%这一楼层的人数
            queue(s(id).floor,temp_num_in_queue+2) = id;
            queue(s(id).floor,1) = queue(s(id).floor,1) + 1;
            if elevator_loc == 1 && elevator_dst == 0 %刚开始的时候,电梯在一层
                for i = N:-1:1
                    if queue(i,1) ~= 0
                        elevator_dst = i;
                        break;
                    end
                end
                Event_queue = insert_Event_queue(Event_queue,t+time_every_floor*(elevator_dst-1), 0, elevator_dst);%把id换成了楼层
            end
        else %else, join the queue
            temp_num_in_queue = queue(s(id).floor,1);
            queue(s(id).floor,temp_num_in_queue+2) = id;
            queue(s(id).floor,1) = queue(s(id).floor,1) + 1;
        end
    end

end
% 结果图形可视化
t_cost=[];
t_left=[];
for i =1:student_num
        t_cost = [t_cost (s(i).left_elevator-s(i).StartTime)*3600];
end
for i =1:student_num
    t_left = [t_left s(i).left_elevator];
end

x=(1:student_num);
figure
plot(x,t_cost,'LineWidth',1.5);
xlabel('ID');
ylabel('耗费时长(单位:秒)');
grid on;

%结果值输出
fprintf('楼层数: %d  学生总数:%d\n',N,student_num);
fprintf('-----------------------------------------------------------\n')
t_start_hour=floor(t_start);
t_start_middle = (t_start-floor(t_start))*60;
t_start_min=floor(t_start_middle);
t_start_second=(t_start_middle-floor(t_start_middle))*60;

t_left_hour=floor(t_left);
t_left_middle = (t_left-floor(t_left))*60;
t_left_min=floor(t_left_middle);
t_left_second=(t_left_middle-floor(t_left_middle))*60;

for k=1:student_num
       fprintf('ID号为 %d 的学生在第 %d 层出发的时间为 %d:%d:%0.1f,离开时间为 %d:%d:%0.1f,耗时%0.1fs\n',s(k).id,s(k).floor,t_start_hour(k),t_start_min(k),t_start_second(k),t_left_hour(k),t_left_min(k),t_left_second(k),t_cost(k));
end
fprintf('-----------------------------------------------------------\n')
fprintf('学生乘坐电梯平均消耗时长= %f 秒\n',mean(t_cost));

pop_queuw.m

function [ queue, pop_id ] = pop_queue( queue, index ,num_to_pop )
    pop_id = [];
    num_pop = 0;
    if queue(index,1) <= num_to_pop %想取出的学生数少于当前层排队人数
        num_pop = queue(index,1); %排队的人都取出
        for i = 2:(num_pop+1)
            pop_id = [pop_id queue(index,i)];
            if queue(index,i) == 0
                bb = 1;
            end
        end
        queue(index,:) = 0;
    else %想取出的学生数多于当前层排队人数
        num_pop = num_to_pop;
        queue(index,1) = queue(index,1) - num_pop;
        for i = 2:(num_pop +1)
            pop_id = [pop_id queue(index,i)];
            if queue(index,i) == 0
                bb = 1;
            end
            queue(index,i) = 0; %将被取出的学生 位置处 置0
        end
        for i = 2:(queue(index,1)+1)
            queue(index,i) = queue(index,i+num_pop); %将后面没被取出的同学 排队前移
            queue(index,i+num_pop) = 0; %被前移的学生位置处 置0
        end
        
    end
end

insert_Event_queue.m

function event_queue=insert_Event_queue(event_queue,time, type,id)

if isempty(event_queue)
    event_queue = [time type id]';
else
    s = size(event_queue);
    %check the start and end 
    if event_queue(1,1) >= time
        %add to the start
        event_queue = [[time type id]' event_queue(:,1:s(2))];
    elseif event_queue(1,s(2)) <= time
        %add to the end
        event_queue = [event_queue(:,1:s(2)) [time type id]'];
    else
        for n = 1:s(2) %go through the event queue and find the right place to insert
            if event_queue(1,n)<time
                %insert the time and type
                event_queue = [event_queue(:,1:n) [time type id]' event_queue(:,n+1:s(2))];
                break;
            end
        end
    end
end

pop_Event_queue.m

function [time, type, id, event_queue]=pop_Event_queue(event_queue)
time= event_queue(1,1);% move the timer
type = event_queue(2,1);
id = event_queue(3,1);
s = size(event_queue);
if s == [3 1]% only one event existed
    event_queue = [];
else %more than one event existed
     %push the fisrt event out.
    event_queue=event_queue(:,2:s(2));%取出前一个            
end

参考
[1]. Liuss 升升小屋

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值