输入:乘客请求事件,所有电梯状态
输出:电梯命令
其中,
电梯状态 |
电梯命令 |
乘客请求事件 |
最高层数 |
添加电梯停时响应事件 |
X楼上行请求 |
剩余负载 |
取消电梯停时响应事件 |
X楼下行请求 |
运行方向(上、下、静止) |
E电梯内有乘客请求去Y楼 |
|
能否到达X楼 |
开往X楼 |
|
开往(静止时:上、下) |
设置开往方向(上、下) |
算法思想
一、统计每层楼的“剩余负载”变化情况
如果0、1层“剩余负载”的平均增量大于其它楼层,则是下班
如果0、1层“剩余负载”的平均增量小于其它楼层,则是上班
二、流程:
a. 电梯按环形路线运行,向上至顶,再向下至底,再向上至顶,。。。
b. 电梯停时,按a从近向远扫描,如果在某一站,有必要停的话(参考c,d),就开往那一站。
c. 如果有乘客请求在E电梯的X层停,则标志E电梯需要在X层停。
d. 如果有乘客请求上/下行,
下班时,标志一个电梯需要在那停。
上班时,标志所有电梯都需在那停。
e. 如果c、d发生,执行b
算法很简单,但模式识别思想很赞。
算法很粗糙,可以有很多优化。比如,
上班时,环形路线并不是最佳的,我们已经证明内线、外线的模式更佳。即是说,适当的时候可以拒绝去高层的请求。
下班时,如何选择电梯 来响应乘客上/下行的请求。我们的方案很粗糙: 电梯ID==楼层*电梯总数/(楼层高度+1)。 更精细的方案是考虑电梯的“剩余负载”,或者更精细地根据楼层远近绑定电梯和楼层。
但因为时间关系没有实现他们。有兴趣的读者可以尝试。
相关工作
按钮
为了过滤重复请求,我们引入了“Button”(这更应该在电梯中实现)
IButton
-Press(ID)
-UnPress(ID)
-IsPressed(ID)
-NotPressed(ID)
每个电梯有个Button,记录需要停的楼层
四个电梯共享一个Button,记录上行、下行的情况。
最佳算法
在没有新的外部请求的情况下,我们找得到了最佳调度算法
(动态规划法)
目标:让电梯里的人为零
转移:电梯在任何状态下,只有两种选择,上行一层,或下行一层。这两个新的状态是当前状态的子问题。新状态下,电梯里的人可能减少。
合并:如果当前在同一个楼层,并且电梯递里的乘客一样,则可以合并状态,取离开乘客平均等待时间最少的那个状态。
可以证明,每一层,只有N种状态,于是,总共只有N*N种状态。算法有效
但是电梯外部请求是不确定的,所以不存在最佳调度算法。于是,我们转向模式识别。
模式识别
实际上,电梯的外部请求有两种极端情况,
上班时,大量乘客从一楼和地下一层进电梯
下班时,大量乘客从一楼或地下一层出电梯
这两种情况下最佳调度方式不太可能一样,所以上/下班的信息对调度会有很大帮助
我们可以从 每一层的“剩余负载”变化,即每一层多少重量的人进出, 提取出上/下班信息。
“剩余负载”更新是离散的,而且有毛刺。为了让上/下班信息稳定,我们增加了移动平均滤波器。
移动平均滤器如此有用,以至于我一定要把代码贴出来。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class RateMeasurer
2 {
3 private float[] m_Samples = null;
4 private int m_LastUpdated = -1;
5
6 public RateMeasurer(int n_samples = 4)
7 {
8 m_Samples = new float[n_samples];
9 for (int i = 0; i < n_samples; i++)
10 m_Samples[i] = 0;
11 }
12
13 public void Update(float rate)
14 {
15 if (m_LastUpdated < 0)
16 {
17 m_LastUpdated = 0;
18 }
19 m_Samples[m_LastUpdated] = rate;
20 m_LastUpdated = (m_LastUpdated + 1) % m_Samples.Length;
21 }
22
23 public float GetAverageRate()
24 {
25 float avg = 0.0F;
26 int pos = 0;
27 for (int i = 0; i < m_Samples.Length; i++)
28 {
29 avg += m_Samples[i];
30 pos++;
31 }
32 if (pos > 0)
33 return avg / pos;
34 else
35 return 0;
36 }
37
38 }
39
如果一楼和地下一层进的人很多,无疑是上班模式;
如果一楼和地下一层出的人很多,无疑是下班模式。
测试框架
电梯系统还包括 电梯、乘客和楼。这部分工作由Sen Xiang完成。简单介绍下
楼是顶层对象,包括一些电梯、一个调度器和一个计时器。
初始化后,计时器开始计时,
乘客:
如果时间和乘客到达时间一致,乘客状态变为等待,并发送上/下行请求。
如果电梯停在乘客所在楼层,并且开往方向与乘客的去向一致,则乘客进入电梯,乘客状态变为正在电梯中,并发送目的地请求。
如果乘客所乘电梯停在目的,乘客状态变为到达。
电梯:
根据高度器的命令运行,并更新状态。
电梯停时,发送电梯停信号。
楼:
只需要要提供楼层高度的信息。
MicroTeam Hui
CodingCrazy Hao