電梯調度有很多種模式,參見http://www.cnblogs.com/jianyungsun/archive/2011/03/16/1986439.html
1.1先來先服務算法(FCFS)
先來先服務(FCFS-First Come First Serve)算法,是一種隨即服務算法,它不僅僅沒有對尋找樓層進行優化,也沒有實時性的特征,它是一種最簡單的電梯調度算法。它根據乘客請求乘坐電梯的先后次序進行調度。此算法的優點是公平、簡單,且每個乘客的請求都能依次地得到處理,不會出現某一乘客的請求長期得不到滿足的情況[12]。這種方法在載荷較輕松的環境下,性能尚可接受,但是在載荷較大的情況下,這種算法的性能就會嚴重下降,甚至惡化。人們之所以研究這種在載荷較大的情況下幾乎不可用的算法,有兩個原因:
(1)任何調度算法在請求隊列長度為1時,請求速率極低或相鄰請求的間隔為無窮大時使用先來先服務算法既對調度效率不會產生影響,而且實現這種算法極其簡單。
(2)先來先服務算法可以作為衡量其他算法的標准。
1.2最短尋找樓層時間優先算法(SSTF)
最短尋找樓層時間優先(SSTF-Shortest Seek Time First) [14]算法,它注重電梯尋找樓層的優化。最短尋找樓層時間優先算法選擇下一個服務對象的原則是最短尋找樓層的時間。這樣請求隊列中距當前能夠最先到達的樓層的請求信號就是下一個服務對象。在重載荷的情況下,最短尋找樓層時間優先算法的平均響應時間較短,但響應時間的方差較大,原因是隊列中的某些請求可能長時間得不到響應,出現所謂的“餓死”現象。
1.3掃描算法(SCAN)
掃描算法(SCAN)是一種按照樓層順序依次服務請求,它讓電梯在最底層和最頂層之間連續往返運行,在運行過程中響應處在於電梯運行方向相同的各樓層上的請求。它進行尋找樓層的優化,效率比較高,但它是一個非實時算法。掃描算法較好地解決了電梯移動的問題,在這個算法中,每個電梯響應乘客請求使乘客獲得服務的次序是由其發出請求的乘客的位置與當前電梯位置之間的距離來決定的,所有的與電梯運行方向相同的乘客的請求在一次電向上運行或向下運行的過程中完成,免去了電梯頻繁的來回移動[2]。
掃描算法的平均響應時間比最短尋找樓層時間優先算法長,但是響應時間方差比最短尋找樓層時間優先算法小,從統計學角度來講,掃描算法要比最短尋找樓層時間優先算法穩定。
1.4 LOOK 算法
LOOK算法[18]是掃描算法的一種改進。對LOOK算法而言,電梯同樣在最底層和最頂層之間運行。但當LOOK算法發現電梯所移動的方向上不再有請求時立即改變運行方向,而掃描算法則需要移動到最底層或者最頂層時才改變運行方向。
1.5 SAFT 算法
SATF(Shortest Access Time First)[15,19]算法與SSTF算法的思想類似,唯一的區別就是SATF算法將SSTF算法中的尋找樓層時間改成了訪問時間。這是因為電梯技術發展到今天,尋找樓層的時間已經有了很大地改進,但是電梯的運行當中等待乘客上梯時間卻不是人為可以控制。SATF算法考慮到了電梯運行過程中乘客上梯時間的影響。
上面是常見的電梯調度模式,這里我們寫的是第二種模式,這是一個簡化的版本。
運行原理:電梯會將目前所有的請求中最高的樓層請求查出來,通過與電梯所在樓層進行對比,確定電梯的運行方向,是向上運行(方法getRequest1)或者是向下運行(方法getRequest),同時每到一層都會執行下面的操作:
1.這層是否有人請求,如果有,那么要求設置目的層。
2.確定這層是某個請求的目的層,如果是,就將相應的請求歸零。
缺陷:將請求單純簡化為層數,其實實際中還會出現請求的方向,這個下次再解決,還有其他的一些。
代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 電梯調度算法 { struct elevatorRequest { public int start; public int end; public int rFlag; } class elevator { public static int count = 0; public static int now = 0; elevatorRequest[] sRequest = new elevatorRequest[12]; public static int runNow = 0; public void run() { while (count > 0) { getRequest(); getRequest1(); } } public void setDirect() { int max = 0; int ns = count; if (ns != 0) { max = sRequest[0].start; int i = 0; while (ns > 0) { if (max < sRequest[i].end || max < sRequest[i].start) { max = sRequest[i].end > sRequest[i].start ? sRequest[i].end : sRequest[i].start; } } if(max>runNow) { getRequest(); } else { getRequest1(); } } } public void getRequest1() { if (count > 0) { Console.WriteLine("電梯開始方向運行"); for (int i = 11; i >= 0; i--) { Console.WriteLine("-----" + i + "----"); int j = isEnd(i); if (j != 0) { Console.WriteLine("完成了從" + sRequest[j].start + "層到" + sRequest[j].end + "的請求"); runNow = i; count--; sRequest[j].start = 0; sRequest[j].end = 0; } } if (count == 0) { Console.WriteLine("請求執行完畢,電梯停止運行"); Console.WriteLine("電梯停留在" + runNow + "層"); } } else { Console.WriteLine("請求執行完畢,電梯停止運行"); Console.WriteLine("電梯停留在" + runNow + "層"); } } public void getRequest() { if (count > 0) { //int next = getNextFloor(); for (int i = 0; i < 12; i++) { Console.WriteLine("-----" + i + "----"); if (sRequest[i].start != 0) { Console.WriteLine("響應了" + i + "層的請求"); Console.WriteLine("請輸入要去的樓層"); int e; string str = Console.ReadLine(); e = Convert.ToInt32(str); setRequest(i, e); } int j = isEnd(i); if (j != 0) { Console.WriteLine("完成了從" + sRequest[j].start + "層到" + sRequest[j].end + "的請求"); runNow = i; count--; sRequest[j].start = 0; sRequest[j].end = 0; } } if (count == 0) { Console.WriteLine("請求執行完畢,電梯停止運行"); Console.WriteLine("電梯停留在" + runNow + "層"); } } else { Console.WriteLine("請求執行完畢,電梯停止運行"); Console.WriteLine("電梯停留在" + runNow + "層"); } } public int isEnd(int i) { for (int j = 0; j < 12; j++) { if (i == sRequest[j].end) { return j; } } return 0; } public int getNextFloor() { int min = sRequest[0].start - runNow > 0 ? (sRequest[0].start - runNow) : (runNow - sRequest[0].start); for (int i = 0; i < now; i++) { if (min > sRequest[i].start - runNow) { min = sRequest[i].start - runNow; } } return min + runNow; } public void setRequest(int i, int e) { sRequest[i].end = e; if (i > e) { sRequest[i].rFlag = 0; } else { sRequest[i].rFlag = 1; } } public void setRequest(int s) { count++; sRequest[s].start = s; } public void show() { for (int i = 0; i < 12; i++) { if (sRequest[i].end != 0) { string s = ""; if (sRequest[i].rFlag > 0) { s = "上"; } else { s = "下"; } Console.WriteLine("我要從" + sRequest[i].start + "層到" + sRequest[i].end + "層,方向向" + s); } } } } class Program { static void Main(string[] args) { elevator es = new elevator(); es.setRequest(1); es.setRequest(10); es.setRequest(7); es.run(); es.show(); es.setRequest(9); es.setRequest(4); es.run(); Console.ReadKey(); } } }
運行結果: