簡單蟻羣算法的實現

 

一引言

蟻羣算法(ant colony optimization,ACO),又稱螞蟻算法,是一種用來在圖中尋找優化路徑的機率型技術。它由Marco Dorigo於1992年在他的博士論文中引入,其靈感來源於螞蟻在尋找食物過程中發現路徑的行爲。蟻羣算法是一種模擬進化算法。初步的研究表明該算法具有許多優良的性質。針對PID控制器參數優化設計問題,將蟻羣算法設計的結果與遺傳算法設計的結果進行了比較,數值仿真結果表明,蟻羣算法具有一種新的模擬進化優化方法的有效性和應用價值。蟻羣算法是一種求解組合最優化問題的新型通用啓發式方法,該方法具有正反饋、分佈式計算和富於建設性的貪婪啓發式搜索的特點。正因爲蟻羣算法有這些優點,很多研究者都在致力研究和改過它,本文的目的正是爲了介紹蟻羣算法,學習如何編寫蟻羣算法。

 

二蟻羣算法的介紹

昆蟲世界中,螞蟻的組成是一種羣居的世襲大家庭,我們稱之爲蟻羣。螞蟻分爲世襲制的蟻王(後)和工蟻兩種,它們具有高度組織的社會性,彼此溝通不僅可以藉助觸覺和視覺的聯繫,在大規模的協調行動中還可以藉助外激素(有些書稱信息素)之類的信息介質。

首先我們要理解螞蟻是如何覓食的,螞蟻平時在巢穴附近作無規則行走,一量發現食物並不立即進食而是將之搬回蟻穴與其它螞蟻分享,在食物小時則獨自搬回蟻穴,否則就回蟻穴搬兵,一路上會留下外激素,食物越大外激素的濃度就越大,越能吸引其它的螞蟻過去一起搬去食物,這樣最終就能將食物全部搬回蟻穴。這個過程用程序實現看似非常複雜,要編寫一個“智能”的螞蟻也看似不太可能,事實上每個螞蟻只做了非常簡單的工作:檢查某個範圍內有無食物,並逐漸向外激素濃的方向運動。簡而言之,蟻羣運動無非是同時反覆執行多個簡單規則而已。下面詳細說明蟻羣中的這些簡單規則:

1、範圍:螞蟻觀察到的範圍是一個方格世界,螞蟻有一個參數爲速度半徑(一般是3),那麼它能觀察到的範圍就是3*3個方格世界,並且能移動的距離也在這個範圍之內。

2、環境:螞蟻所在的環境是一個虛擬的世界,其中有障礙物,有別的螞蟻,還有外激素,外激素有兩種,一種是找到食物的螞蟻灑下的食物外激素,一種是找到窩的螞蟻灑下的窩的外激素。每個螞蟻都僅僅能感知它範圍內的環境信息。環境以一定的速率讓外激素消失。

3、覓食規則:在每隻螞蟻能感知的範圍內尋找是否有食物,如果有就直接過去。否則看是否有外激素,並且比較在能感知的範圍內哪一點的外激素最多,這樣,它就朝外激素多的地方走,並且每隻螞蟻多會以小概率犯錯誤,從而並不是往外激素最多的點移動。螞蟻找窩的規則和上面一樣,只不過它對窩的外激素做出反應,而對食物外激素沒反應。

4、移動規則: 每隻螞蟻都朝向外激素最多的方向移,並且,當週圍沒有外激素指引的時候,螞蟻會按照自己原來運動的方向慣性的運動下去,並且,在運動的方向有一個隨機的小的擾動。爲了防止螞蟻原地轉圈,它會記住最近剛走過了哪些點,如果發現要走的下一點已經在最近走過了,它就會盡量避開。

5、避障規則:如果螞蟻要移動的方向有障礙物擋住,它會隨機的選擇另一個方向,並且有外激素指引的話,它會按照覓食的規則行爲。

7、播撒外激素規則:每隻螞蟻在剛找到食物或者窩的時候撒發的外激素最多,並隨着它走遠的距離,播撒的外激素越來越少。

根據這幾條規則,螞蟻之間並沒有直接的關係,但是每隻螞蟻都和環境發生交互,而通過外激素這個紐帶,實際上把各個螞蟻之間關聯起來了。比如,當一隻螞蟻找到了食物,它並沒有直接告訴其它螞蟻這兒有食物,而是向環境播撒外激素,當其它的螞蟻經過它附近的時候,就會感覺到外激素的存在,進而根據外激素的指引找到了食物。成功的覓食算法正是最小化搜索食物的時間。

 

三蟻羣算法的實現

理解蟻羣算法的實質之後寫出一個簡單蟻羣算法也不是太困難,關鍵是實現以上介紹的幾個規則,下面用JAVA簡單講述一下以上規則的實現。

1、螞蟻:螞蟻是蟻羣中最小的單位,是所以簡單規則應用的最小個體。

 

public class Ant
{
    public Square SQUARE;        //螞蟻所在方格
    public Food CARRYING = null;    //所搬的食物數
    public int ID;            //螞蟻的編號
    public boolean HELPING = false;        //是否幫忙搬運食物

public void move(int turn)
{
    //螞蟻移動到下一個方格
}
}

2、範圍:螞蟻所在的方格應該包含附近的方格編號,所含食物數量,螞蟻數量,外激素的濃度,以及座標等信息。

 

public class Square
{ public Square NE;            //附近的8個方向的方格

     public Square N;
     public Square NW;
     public Square W;
     public Square SW;
     public Square S;
     public Square SE;
     public Square E;
     public LinkedList ANTS;        //本方格中包含的螞蟻
     public Food FOOD;            //本方格中包含的食物數
     public Nest NEST;                //方格爲蟻穴
     public Pheromone_1 PHEROMONE_1;            //本方格中的外激素含量
     public int X;            //本方格的座標
     public int Y;
     private World WORLD;            //所屬的環境
     public boolean WALL;            //是否有障礙物

    public Square(int x, int y, World world)
    {
        FOOD = null;
        NEST = null;
        PHEROMONE_1 = null;
        X = x;
        Y = y;
        WORLD = world;
        WALL = false;
        ANTS = new LinkedList();
    }

3、環境:環境是由多個方格組成的,是一個平面的,因此用一個方格的二維數組來表示是最合適不過的。

public class World
{
    private Square[][] WORLD;        //定義環境二維數組
    private int WIDTH;                //環境的長寬
    private int HEIGHT;
    private Pheromone_1List P1LIST;        //保存所有外激素的列表
  
    public World(Pheromone_1List p1list)
    {
        this.WIDTH = Settings.WIDTH;
        this.HEIGHT = Settings.HEIGHT;
        this.P1LIST = p1list;
        WORLD = new Square[WIDTH][HEIGHT];
    }

     4、覓食規則,移動規則和避障規則:這三種規則全都跟螞蟻的移動方向有關,並在移動前都要先計算周圍方格的外激素濃度,選擇外激素濃度最高的方格方向移動。

private Square chooseBestSquare()
{
     Square[] square_list = {SQUARE.E, SQUARE.NE, SQUARE.N, SQUARE.NW, SQUARE.W, SQUARE.SW, SQUARE.S, SQUARE.SE};
        double current_best_value = 0;
        double value = 0;
        Square square = SQUARE;
        // 選擇最好的方格

        for(int i=0;i<square_list.length;i++)
        {
            value = calculateSquareValue(square_list[i]);//計算方格值
            if(value > current_best_value)
            {
                current_best_value = value;
                square = square_list[i];
            }
        }
        if(square.ANTS.size() >= Settings.MAXIMUM_NUMBER_OF_ANTS)
        {
          return SQUARE;
        }
        return square;
    }

private double calculateSquareValue(Square s)
{
    double[] thresholds = Settings.THRESHOLDS;
    if(s==null || s.WALL) // 方格有障礙物
    {
        return -100000;
    }

    // 計算方格中各項參數的值
    return s.getFood()*thresholds[0]        // 食物
    + s.getPheromone_1() * thresholds[1]    // 外激素
}

5、播撒外激素規則:每隻螞蟻找到食物後會根據食物的數量播撒相應量的外激素,以便其它螞蟻能夠更快得找到這堆食物。

private void putPheromone_1(double amount)
{
    if(SQUARE.getPheromone_1() < Settings.PHEROMONE_LIMIT)
     SQUARE.addPheromone_1(amount);
}

從以上蟻羣算法中各個要素的代碼來看,實現蟻羣算法並不難。每隻螞蟻並不是像我們想象的需要知道整個環境的信息,它們只關心很小範圍內的眼前信息,而且根據這些局部信息利用幾條簡單的規則進行決策,這樣,在蟻羣這個集體裏,複雜性的行爲就會凸現出來。這就是人工生命、複雜性科學解釋的規律。

 

四蟻羣算法的不足

    本文實現的蟻羣算法只是簡單的大致模擬蟻羣的覓食過程,真正的螞蟻覓食過程遠比這個複雜,比如增加螞蟻搬運食物的距離和數量,螞蟻在搬運食物發現更大的食物可能會丟棄原有食物,還可以增加螞蟻搬運食物回蟻穴的最短路徑的求解。同時需要注意的是,由於蟻羣算法覓食的過程,蟻羣算法可能會過早的收斂並陷入局部最優解。

原文鏈接:http://blog.chinaunix.net/space.php?uid=763534&do=blog&id=2047753

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章