首先介紹什麼是遺傳算法。
由一個問題引入,求某函數f(x)在區間[a,b]上的最大值。
這看似簡單,我們很快會說,求他的導數,然後等於0即可。
但是往往在應用中,f(x)未知,或很難解析,這就讓求導這類方法變得困難。
於是科學家們聯想到了生物裏的進化論,給出了這樣一個很有意思的求解過程。
首先你先隨機出一些數對,x從對應的區間中隨機,y就是他們對應的f(x).
幹嘛呢?把他們看做進化論中的個體。x是基因型,y是表現型,你作爲上帝,目標是選出表現型比較大的值。
於是你根據,y的值,把一些數對搞死了。
然後再讓剩下的進行繁殖——把基因編碼,也就是把float映射成二進制數組,然後把這個數組看成生物上的基因序列,交叉重組,產生下一代,然後這個過程中往往還伴隨着變異。
如此反覆。我們可以發現,最後留在種羣裏的,會集中在f(x)的極大值點附近。
這就描述了遺傳算法的過程。
初始化隨機數據->篩選->編碼->重組->變異->迭代。
然後我們再想想在遊戲裏用這個能幹嘛。
其實遊戲人工智能很大的不同在於,我們致力於研究最有趣的AI,而非最優秀的AI。
所以我們在遊戲裏用遺傳算法去模擬種羣,很大程度是希望看到,玩家對遊戲世界作出的動作,在最終宏觀的影響了整個遊戲世界,體現一種很強的自由度——而並非真正希望AI在進化過程中成長成可以對抗玩家的AI。
那麼如何在遊戲裏運用遺傳算法呢?
要做一個小小的改動——大多的遺傳算法往往是先迭代完成,計算出最優解,然後投入應用。而遊戲裏——我們說了,我們並不關心最優解,我們關心他在變化。所以我們不在遊戲初始化的時候,直接完成遺傳算法的迭代,而是在遊戲中實時的計算這個個體的情況,並每個一段時間進行一次迭代,這次迭代將決定下一代的個體,如此往復,直到遊戲最後結束。
最後講一講我們將用到的優化——可以使用多線程和池化技術。
因爲這個遺傳算法的維護和主邏輯是可分離的,確切的說,遺傳算法的迭代過程中,和主邏輯並不衝突,相反,由於遺傳算法在迭代下一代的過程中,計算非常集中,所以在這個階段會嚴重阻塞主邏輯。
所以我們可以使用多線程,用一個線程去維護一個種羣的遺傳算法。
而至於池化,是因爲在迭代過程中要消亡上一代,生成下一代,也就是生成、銷燬操作非常頻繁,這種情況是可以使用池化,具體請參考上一篇文章。
下一篇,我們講一些具體的代碼實現。