1. 程式人生 > >【演算法】電梯排程演算法/磁碟掃描演算法

【演算法】電梯排程演算法/磁碟掃描演算法

1,問題描述

假如有十層樓,每層都有相同數量的人,一共有三部電梯並且沒有樓梯。你將如何分配電梯來實現效能最優,及最小化每一層的等待時間?
設計一個使大樓裡所有人等待時間最短的演算法,同時要考慮每一層的負載量。假定每一層人數相同且每層的人以同樣的方式使用電梯。假設每天有幾個小時是“高峰時段”,演算法需要提供一種最“公平”的方式來將電梯分配到不同的樓層。

2,問題分析

分析問題,問題規定如下:
1)樓層數量任意(0-10,0表示地下一層)
2)電梯數量任意(3,所有電梯通過統一按鈕控制)
3)給定高峰時段
4)必須通過某種關於負載和時間的函式來分配電梯

3,傳統電梯排程演算法

1)先來先服務演算法(FCFS,FCFS-First Come First Serve)

①概念

根據乘客請求乘坐電梯的先後次序進行排程。

②評價

公平、簡單,且每個乘客的請求都能依次地得到處理,不會出現某一乘客的請求長期得不到滿足的情況。
這種方法在載荷較輕鬆的環境下,效能尚可接受,但是在載荷較大的情況下,這種演算法的效能就會嚴重下降,甚至惡化。

2)最短尋找樓層時間優先演算法(SSTF,SSTF-Shortest Seek Time First)

①概念

針對電梯尋找樓層進行了優化:選擇下一個服務物件的原則是最短尋找樓層的時間。這樣請求佇列中距當前能夠最先到達的樓層的請求訊號就是下一個服務物件。

②評價

在過載荷的情況下,最短尋找樓層時間優先演算法的平均響應時間較短,但響應時間的方差較大,原因是佇列中的某些請求可能長時間得不到響應,出現所謂的“餓死”現象。

3)掃描演算法(SCAN)

①概念

針對尋找樓層的優化。
按照樓層順序依次服務請求,讓電梯在最底層和最頂層之間連續往返執行,在執行過程中響應處在於電梯執行方向相同的各樓層上的請求。

②評價

效率比較高,但它是一個非實時演算法。掃描演算法較好地解決了電梯移動的問題,在這個演算法中,每個電梯響應乘客請求使乘客獲得服務的次序是由其發出請求的乘客的位置與當前電梯位置之間的距離來決定的,所有的與電梯執行方向相同的乘客的請求在一次電向上執行或向下執行的過程中完成,免去了電梯頻繁的來回移動。
掃描演算法的平均響應時間比最短尋找樓層時間優先演算法長,但是響應時間方差比最短尋找樓層時間優先演算法小,從統計學角度來講,掃描演算法要比最短尋找樓層時間優先演算法穩定。

③磁碟排程

i>過程

總是從磁臂當前位置開始,沿磁臂的移動方向去選擇當前磁臂近期的 那個煮麵的訪問者。
當沿磁臂方向無請求訪問時,改變磁臂的移動方向。
需要為訪問者設定兩個佇列,依據磁頭的移動方向,能訪問到的訪問者由近及遠排隊。
背離磁頭移動方向的訪問者也由近及遠排隊。
先按磁頭移動方向佇列排程訪問者訪問磁碟,當該方向沒有訪問者時,再改變方向,選擇還有一個訪問者佇列訪問磁碟。

ii>舉例

資料:98 183 37 122 14 124 65 67
讀寫頭起始位置:53
磁頭移動方向:0(0磁軌減少方向、1磁軌增加方向)

計算過程:
①53為基準,向內移動。
②分為兩個佇列,按由近到遠排序:
37 14
65 67 98……183
③先移動到37,再到14,共:53-14 = 39長度
14移動到183,共:183-14 = 169長度;
④則共需移動長度為:39+169 = 208,平均定址長度為:208/8 = 26

iii>程式碼

public class SCAN {

int visitAdd[];
int visitSub[];
int index=0;   //存放下標,已排序序列中找到比它大的最小值的下標
public void scan(int data[],int begin,int direction){
    int temp=0;
    //從小到大排序
    for(int i=0;i<data.length;i++){
        for(int j=i;j<data.length;j++){
            if(data[i]>data[j]){
                temp=data[i];
                data[i]=data[j];
                data[j]=temp;
            }
        }
    }

    for(int i=0;i<data.length;i++){
        if(data[i]>begin){   //在已排序序列中找到比它大的最小值的下標
            index=i;
            break;
        }
    }
    //比起始位置小的
    visitSub=new int[index];   //比他小的共同擁有index個
    for(int i=0;i<index;i++){
        visitSub[i]=data[i];
    }
    //比起始位置大的
    visitAdd=new int[data.length-index];   //比他大的共data.length-index個
    for(int i=0;i<visitAdd.length;i++){
        visitAdd[i]=data[i+index];
    }
    //計算平均時間
    int lengthAdd=0;
    int lengthSub=0;
    int length=0;
    for(int i=0;i<visitAdd.length-1;i++){
        lengthAdd+=Math.abs(visitAdd[i]-visitAdd[i+1]);
    }
    for(int i=visitSub.length-1;i>0;i--){
        lengthSub+=Math.abs(visitSub[i]-visitSub[i-1]);
    }
    length=lengthAdd+lengthSub+Math.abs(begin-visitAdd[0])+Math.abs(begin-visitSub[visitSub.length-1]);

    if(direction==0){   //找小的
        for(int i=visitSub.length-1;i>=0;i--){              
            System.out.print(visitSub[i]+"    ");
        }
        //迴轉
        for(int i=0;i<visitAdd.length;i++){              
            System.out.print(visitAdd[i]+"    ");
        }
        length+=Math.abs(visitSub[0]-begin);
    }else{        //找大的
        for(int i=0;i<visitAdd.length;i++){              
            System.out.print(visitAdd[i]+"    ");
        }
        //迴轉
        for(int i=visitSub.length-1;i>=0;i--){              
            System.out.print(visitSub[i]+"    ");
        }
        length+=Math.abs(visitAdd[visitAdd.length-1]-begin);
    }
    System.out.println("平均尋道長度為"+length/data.length);
}
public static void main(String[] args) {
    SCAN scan=new SCAN();
    Scanner scanner=new Scanner(System.in);
    System.out.println("請輸入資料個數");
    int num=scanner.nextInt();
    System.out.println("請一次輸入資料,空格隔開");
    int data[]=new int[num];
    for(int i=0;i<num;i++){
        data[i]=scanner.nextInt();
    }
    System.out.println("請輸入讀寫頭起始位置");
    int  begin=scanner.nextInt();
    System.out.println("請輸入磁頭移動方向  0:磁軌降低方向   1:磁軌新增方向 ");
    int direction=scanner.nextInt();
    scan.scan(data, begin, direction);

}
//98 183 37 122 14 124 65 67

}

4)LOOK 演算法

是掃描演算法的一種改進。對LOOK演算法而言,電梯同樣在最底層和最頂層之間執行。但當LOOK演算法發現電梯所移動的方向上不再有請求時立即改變執行方向,而掃描演算法則需要移動到最底層或者最頂層時才改變執行方向。

5)SAFT 演算法(Shortest Access Time First)

與SSTF演算法的思想類似,唯一的區別就是SATF演算法將SSTF演算法中的尋找樓層時間改成了訪問時間。這是因為電梯技術發展到今天,尋找樓層的時間已經有了很大地改進,但是電梯的運行當中等待乘客上梯時間卻不是人為可以控制。SATF演算法考慮到了電梯執行過程中乘客上梯時間的影響。

4,實時電梯排程演算法

1)最早截止期優先排程演算法(EDF-Earliest Deadline First)

①概念

是最簡單的實時電梯排程演算法,與FCFS排程演算法類似。它響應請求佇列中時限最早的請求,是其它實時電梯排程演算法效能衡量的基準和特例。

②評價

缺點是造成電梯任意地尋找樓層,導致極低的電梯吞吐率。

2)SCAN-EDF 演算法

是SCAN演算法和EDF演算法相結合的產物。SCAN-EDF演算法先按照EDF演算法選擇請求列隊中哪一個是下一個服務物件,而對於具有相同時限的請求,則按照SCAN演算法服務每一個請求。它的效率取決於有相同deadline 的數目,因而效率是有限的。

3)PI 演算法(Priority Inversion)

將請求佇列中的請求分成兩個優先順序,它首先保證高優先順序佇列中的請求得到及時響應,在高優先順序佇列為空的情況下在相應地優先順序佇列中的請求。

4)FD-SCAN 演算法(Feasible Deadline SCAN)

首先從請求佇列中找出時限最早、從當前位置開始移動又可以買足其時限要求的請求,作為下一次SCAN的方向。並在電梯所在樓層向該請求訊號執行的過程中響應處在與電梯執行方向相同且電梯可以經過的請求訊號。這種演算法忽略了用SCAN演算法相應其它請求的開銷,因此並不能確保服務物件時限最終得到滿足。

5,實現

1)電梯的初始狀態

i>建築共有11層,其中含有地下一層(地下一層為停車場及貨物運送場所)。
ii>建築內部設有三部電梯,編號分別為A梯、B梯、C梯。
iii>電梯內部有11個按鈕,其中包括開門按鈕、關門按鈕和樓層按鈕,編號為-1,1,2,3,4……10。
iv>電梯外部含有兩個按鈕,即向上執行按鈕和向下執行按鈕。建築頂層與地下一層例外,建築頂層只設置有向下執行按鈕,地下一層只設置有向上執行按鈕。
v>電梯開關門完成時間設定為1秒。電梯到達每層後上下人的時間設定為8秒。電梯從靜止開始執行到下一層的時間設定為2秒,而執行中通過一層的時間為1秒。
vi>在凌晨2:00——4:30之間,如若沒有請求訊號,A梯自動停在2層,B梯自動停在5層,C梯自動停在8層。
v>當電梯下到-1層後,如果沒有請求訊號,電梯自動回到1層

2)電梯按鈕功能

i>電梯內部的樓層按鈕
電梯內部對應每一個樓層的按鈕成為樓層按鈕,即本章第一結提到的編號為-1,1,2,3,4……10的按鈕。當乘客進入電梯後按下樓層按鈕,此按鈕顯示灰色,代表不可以用。這樣就表示乘客將要去往此層,電梯將開往相應層。當電梯到達該層後,按鈕恢復可以使用狀態。
ii>電梯內部開門按鈕
當電梯達到乘客想要去往的某樓層後,乘客需要準備離開電梯,當電梯停穩後,乘客可以按下開門按鈕,電梯門將開啟,讓使用者離開。如若電梯到了乘客曾經按下的樓層,但是無乘客按開門按鈕,電梯將自動在停穩後1秒後自動開門。
iii>電梯內部關門按鈕
當所有想要乘坐電梯的乘客都進入電梯以後,準備讓電梯開始執行的時候,乘客需要按下關門按鈕,讓電梯門關閉,使電梯進入執行狀態。設定電梯的自動關門時間為8秒。
iv>電梯外部向上按鈕
此按鈕表示上樓請求,當按下此按鈕時,如果電梯到達按下此按鈕的樓層,且電梯執行方向是向上的,那麼電梯響將停下,並在電梯停穩之後自動開門,此請求被響應後,取消此請求訊號。
v>電梯外部向下按鈕
此按鈕表示下樓請求,當按下此按鈕時,如果電梯到達按下此按鈕的樓層,且電梯執行方向是向下的,那麼電梯響將停下,並在電梯停穩之後自動開門,此請求被響應後,取消此請求訊號。

3)樓層選擇控制器

給定一個控制器儲存需電梯樓層和最大樓層(max)、最小樓層(min)。
電梯根據當前控制器內所要到的樓層資訊判斷是向下執行或向上執行。
最值只有在同向時才更新,如:向下執行時,min=3,max=8,出現樓層10只會存入控制器中,出現樓層1,除了加入控制器中,還要更新min=1。
期間出現的所有樓層資訊都加入到控制器內,每到一樓層就判斷控制器內是否有該樓層,有則在該層停留,並移除控制器內該層資訊,無則繼續執行,執行至最值處,重新從控制器內找出最值,並判斷向上或向下執行,如此迴圈。當控制器內沒有資訊後,電梯停留在原處。

6,應用

1)磁碟尋道的優化