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上,准备好所有后运行场景:
 

遗传算法的简单使用-LMLPHP

可以看到,经过5代繁衍,后面的老鼠体型都是很大一个了,蛇已经吃不了它们,但还是偶尔会有基因突变的小老鼠繁衍出来。

遗传算法的简单使用-LMLPHP

 如有错误,欢迎指正!

01-14 21:10