1. 程式人生 > >遺傳演算法的簡單使用

遺傳演算法的簡單使用

1、示例說明

       前幾天記了一下遺傳演算法的基本概念,我們知道,遺傳演算法就是模擬達爾文生物進化論而提出來的演算法。這裡提供一個遺傳演算法使用的簡單示例,在這個示例中,有一條吃老鼠的蛇,這條蛇只吃體型較小的老鼠,老鼠種群經過N代繁殖,經歷了物競天擇、適者生存的自然法則,最後基本都進化成了體型很大的老鼠,蛇吃不了它們,當然也有少數基因突變的老鼠體型還是很小,依然躲不過被蛇吃的命運。下面在unity中簡單實現一下它:  

2、定義老鼠個體類

////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               
// // o8888888o // // 88" . "88 // // (| ^_^ |) // // O\ = /O // // ____/`---'\____
// // .' \\| |// `. // // / \\||| : |||// \ // // / _||||| -:- |||||- \ // // | | \\\ - /// | | // // | \_| ''\---/'' | |
// // \ .-\__ `-` ___/-. / // // ___`. .' /--.--\ `. . ___ // // ."" '< `.___\_<|>_/___.' >'"". // // | | : `- \`.;`\ _ /`;.`/ - ` : | | // // \ \ `-. \_ __\ /__ _/ .-` / / // // ========`-.____`-.___\_____/___.-`____.-'======== // // `=---=' // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // 佛祖保佑 永無BUG // //////////////////////////////////////////////////////////////////// using System.Collections; using System.Collections.Generic; using UnityEngine; public class RatItem : MonoBehaviour { public float size = 1;//大小 public float survivalTime = 8;//存活時間 //被蛇吃 public void Dead() { survivalTime = Population.timeCount; gameObject.SetActive(false); } }

3、定義老鼠種群管理類

////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O\  =  /O                              //
//                      ____/`---'\____                           //
//                    .'  \\|     |//  `.                         //
//                   /  \\|||  :  |||//  \                        //
//                  /  _||||| -:- |||||-  \                       //
//                  |   | \\\  -  /// |   |                       //
//                  | \_|  ''\---/''  |   |                       //
//                  \  .-\__  `-`  ___/-. /                       //
//                ___`. .'  /--.--\  `. . ___                     //
//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
//      ========`-.____`-.___\_____/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//            佛祖保佑                    永無BUG                   //
////////////////////////////////////////////////////////////////////



using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;

public class Population : MonoBehaviour {
    public GameObject ratPrefab;//老鼠prefab
    public int populationSize = 10;//種群大小
    public List<GameObject> population = new List<GameObject>();//老鼠種群
    static List<GameObject> ratSize;
    public static float timeCount = 0;//計時
    private int trailInterval = 10;//每一代訓練間隔
    private int count = 1;//第幾代老鼠
    public float mutation = 0.1f;//基因突變概率
    public Text countText;//第幾代顯示
    public Text timeCountText;//時間顯示

    void Start () {
        //初始化第一代種群
        for (int i = 0; i < populationSize; i++)
        {
            Vector3 pos = new Vector3(Random.Range(-3, 3), 0, Random.Range(-3, 3));
            GameObject go = Instantiate(ratPrefab, pos, Quaternion.identity);
            float randomSize= Random.Range(1, 4);
            go.GetComponent<RatItem>().size = randomSize;
            go.transform.localScale = new Vector3(randomSize, randomSize, randomSize);
            population.Add(go);
        }
        ratSize = population.OrderByDescending(go => go.GetComponent<RatItem>().size).ToList();
    }
    
    void Update () {
        //定時繁衍新一代
        timeCount += Time.deltaTime;
        if (timeCount > trailInterval)
        {
            BreedNewPopulation();
            timeCount = 0;
        }

        countText.text ="繁衍代數:"+ count.ToString();
        timeCountText.text = "計時:" + timeCount.ToString();
    }

    //繁衍一代
    void BreedNewPopulation()
    {
        List<GameObject> newPopulation = new List<GameObject>();
        //給上一代個體列表按存活時間降序排序
        List<GameObject> sortedList = population.OrderByDescending(go => go.GetComponent<RatItem>().survivalTime).ToList();
        //清空上一代列表
        population.Clear();
        ratSize.Clear();
        //選擇優良的兩個父代(存活時間長)去繁殖新一代
        for (int i =0; i < (int)(sortedList.Count / 2); i++)
        {
            population.Add(Breed(sortedList[i].GetComponent<RatItem>(), sortedList[i + 1].GetComponent<RatItem>()));
            population.Add(Breed(sortedList[i + 1].GetComponent<RatItem>(), sortedList[i].GetComponent<RatItem>()));
        }
        ratSize = population.OrderByDescending(go => go.GetComponent<RatItem>().size).ToList();
        //銷燬先前所有的種群
        for (int i = 0; i < sortedList.Count; i++)
        {
            Destroy(sortedList[i]);
        }
        count++;
    }

    //兩個父代繁殖出新個體 (交叉)
    GameObject Breed(RatItem item1,RatItem item2)
    {
        Vector3 pos = new Vector3(Random.Range(-3, 3), 0, Random.Range(-3, 3));
        GameObject go = Instantiate(ratPrefab, pos, Quaternion.identity);
        RatItem item = go.GetComponent<RatItem>();
        //新個體隨機繼承父親或母親的基因
        if (Random.Range(0, 100) > mutation * 100)
        {
            float random= Random.Range(0, 1) > 0.5f ? item1.size : item2.size;
            item.size = random;
            go.transform.localScale = new Vector3(random, random, random);
        }
        //基因突變
        else
        {
            float random = Random.Range(0, 2);
            item.size = random;
            go.transform.localScale = new Vector3(random, random, random);
        }
        return go;
    }


    //得到體型最小的個體
     public static GameObject GetSmallRat()
    {
        if (ratSize.Count > 0)
        {
            GameObject go = ratSize[ratSize.Count - 1];
            go.GetComponent<RatItem>().Dead();
            ratSize.Remove(go);
            return go;
        }
        else
            return null;
    }


}

 

4、定義蛇類

////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O\  =  /O                              //
//                      ____/`---'\____                           //
//                    .'  \\|     |//  `.                         //
//                   /  \\|||  :  |||//  \                        //
//                  /  _||||| -:- |||||-  \                       //
//                  |   | \\\  -  /// |   |                       //
//                  | \_|  ''\---/''  |   |                       //
//                  \  .-\__  `-`  ___/-. /                       //
//                ___`. .'  /--.--\  `. . ___                     //
//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
//      ========`-.____`-.___\_____/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//            佛祖保佑                    永無BUG                   //
////////////////////////////////////////////////////////////////////



using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Snake : MonoBehaviour {
    public float interval = 2;//每三秒吃一隻老鼠
    private float timeCount = 0;//計時

    
    // Update is called once per frame
    void Update () {
        timeCount += Time.deltaTime;
        if (timeCount > interval)
        {
            EatRat();
            timeCount = 0;
        }
    }

    //吃老鼠
    void EatRat()
    {
        GameObject go = Population.GetSmallRat();
        if (go != null)
        {
            if (go.GetComponent<RatItem>().size < 2.5f)
            {
                Debug.Log("吃只小老鼠!");
                go.GetComponent<RatItem>().Dead();
            }
            else
                Debug.Log("老鼠都太大了,我吃不下了!");
        }
    }
}
5、操作步驟與執行測試         在上述程式碼中,首先初始化第一代老鼠種群,蛇會吃了淘汰掉體型較小的老鼠,老鼠種群會挑選基因優良(存活時間長)的老鼠父代去繁衍下一代。 在unity中,建好一個場景,並製作老鼠prefab,將RatItem類掛到該prefab上,準備好所有後執行場景:  

可以看到,經過5代繁衍,後面的老鼠體型都是很大一個了,蛇已經吃不了它們,但還是偶爾會有基因突變的小老鼠繁衍出來。

 如有錯誤,歡迎指正!