首先是个体类:
public class GAObject { public Vector3 mPosition; public float mfitness { get { return Evaluate (); } } public bool[] mbitbunch { set { mbitbunch = new bool[value.Length]; for (int i = 0; i < mbitbunch.Length; i++) mbitbunch [i] = value [i]; } get { return mbitbunch; } } public List<int> mBreakPoint = new List<int>(); public virtual void Encode () { } public virtual void Decode () { } public virtual void RandomData() { } public virtual float Evaluate() { return 1.0f; } };
用Bool[]来保存基因的编码,用float来确定一个适应度,并用重载后的评价函数来计算他。
同时还要提供编码函数、解码函数的虚函数,在派生类里,可以申明性状的属性,并在解码、编码函数中对应起来。
接着,出于选择策略、重组策略、变异策略多为底层实现,我们把遗传算法的这三个过程申明成了委托。
public delegate GAObject[] GASelector(GAObject[] pObjects,float pDyingRate); public delegate GAObject[] GABreedor(GAObject[] pObjects,float pIncreaseRate); public delegate GAObject[] GAMutator(GAObject[] pObjects,float pMutatorRate);
底层中几个简单实现:
public static GAObject[] RouletteSelector(GAObject[] pGAObject,float pDyingRate) { int nowLength = (int)(pGAObject.Length * pDyingRate); GAObject[] nowObject = new GAObject[nowLength]; int index = 0; int RSIndex = 0; float maxfitness = -1.0f; for (int i = 0; i < pGAObject.Length; i++) { if (pGAObject [i].mfitness > maxfitness) { maxfitness = pGAObject [i].mfitness; } } List<int> succeedIndex = new List<int> (); while (index < nowLength) { if (succeedIndex.Contains (RSIndex)) { RSIndex++; RSIndex = RSIndex % pGAObject.Length; continue; } float trate = pGAObject [RSIndex].mfitness / maxfitness; if (UnityEngine.Random.Range (0.0f, 1.0f) < trate) { nowObject [index++] = pGAObject [RSIndex]; succeedIndex.Add (RSIndex); RSIndex++; RSIndex = RSIndex % pGAObject.Length; } else { RSIndex++; RSIndex = RSIndex % pGAObject.Length; } } return nowObject; } public static GAObject[] SinglePointInsertBreedor(GAObject[] pGAObject,float pIncreseseRate) { int nowLength = (int)(pGAObject.Length * pIncreseseRate); if (nowLength % 2 == 1) nowLength++; GAObject[] nowObject = new GAObject[nowLength]; int index = 0; while (index < nowLength) { GAObject mother = pGAObject[UnityEngine.Random.Range(0,pGAObject.Length)]; GAObject father = pGAObject[UnityEngine.Random.Range(0,pGAObject.Length)]; bool[] bitbunch1 = new bool[mother.mbitbunch.Length]; bool[] bitbunch2 = new bool[mother.mbitbunch.Length]; for (int i = 0; i < bitbunch1.Length; i++) { if (i < bitbunch1.Length / 2) { bitbunch1 [i] = mother.mbitbunch [i]; bitbunch2 [i] = father.mbitbunch [i]; } else { bitbunch1 [i] = father.mbitbunch [i]; bitbunch2 [i] = mother.mbitbunch [i]; } } nowObject [index].mbitbunch = bitbunch1; nowObject [index + 1].mbitbunch = bitbunch2; index = index + 2; } return nowObject; } public static GAObject[] SimpleMutator(GAObject[] pGAObject,float pMutatoRate) { for (int i = 0; i < pGAObject.Length; i++) { if (UnityEngine.Random.Range (0.0f, 1.0f) < Mathf.Pow(pMutatoRate,0.5f)) { for (int j = 0; j < pGAObject[i].mbitbunch.Length; j++) { if (UnityEngine.Random.Range (0.0f, 1.0f) < Mathf.Pow (pMutatoRate, 0.5f)) { pGAObject [i].mbitbunch [j] = !pGAObject [i].mbitbunch [j]; } } } } return pGAObject; }
最后还有种群和种群管理者的类:
public class GAPopulation { public Type mObjectType; public string mRTType; public SimpleAIRunner mRTObjectRunner; public SimpleAIStateJudger mRTObjectJudger; public GameObject mPrefab; public GameObject mPlayer; public int mMaxCount; public float mBreedCycle; public float mBreedTimer = 0.0f; public float mMutatorRate; public float mIncreaseRate; public float mDyingRate; public GASelector mSelector; public GABreedor mBreedor; public GAMutator mMutator; private GAObject[] mGAObjectSet; private SimpleAI[] mRTObjectSet; public float lifeRate { get { return (float)mGAObjectSet.Length / (float)mMaxCount; } } public static Dictionary<string,GAPopulation> allDic; public static void GlobalInit() { allDic = new Dictionary<string, GAPopulation> (); } public GAPopulation() { GAPopulationManager.getInstance ().Add (this); } public void Init() { mGAObjectSet = new GAObject[mMaxCount]; allDic.Add (mRTType,this); for (int i = 0; i < mGAObjectSet.Length; i++) { mGAObjectSet [i].RandomData (); mGAObjectSet [i].Encode (); } RePairRTObject (); } public void Generate() { mGAObjectSet = mSelector (mGAObjectSet,mDyingRate); mGAObjectSet = mBreedor (mGAObjectSet,mIncreaseRate); mGAObjectSet = mMutator (mGAObjectSet,mMutatorRate); for (int i = 0; i < mGAObjectSet.Length; i++) { mGAObjectSet [i].Decode (); } RePairRTObject (); } public void RePairRTObject() { for (int i = 0; i < mRTObjectSet.Length; i++) { GameObject.Destroy (mRTObjectSet[i].mAIRT); SimpleAISetSingleton.getInstance ().GetComponent<SimpleAISet> ().Delete (mRTObjectSet[i]); } mRTObjectSet = new SimpleAI[mGAObjectSet.Length]; for (int i = 0; i < mRTObjectSet.Length; i++) { mRTObjectSet [i] = new SimpleAI (); mRTObjectSet [i].Init (mRTObjectRunner,mRTObjectJudger,mPrefab,mPlayer,mGAObjectSet[i].mPosition); mRTObjectSet [i].mType = mRTType; mRTObjectSet [i].mCharacter = mGAObjectSet [i]; } } public void Delete(SimpleAI pSimpleAI) { GAObject[] tGAObjects = new GAObject[mGAObjectSet.Length-1]; SimpleAI[] tSimpleAIs = new SimpleAI[mRTObjectSet.Length-1]; int index = 0; for (int i = 0; i < mGAObjectSet.Length; i++) { if (mRTObjectSet [i] == pSimpleAI) continue; tGAObjects [index] = mGAObjectSet [i]; tSimpleAIs [index] = mRTObjectSet [i]; index++; } mGAObjectSet = tGAObjects; mRTObjectSet = tSimpleAIs; } };
种群类主要是为了将选择策略、重组策略、变异策略、基因遗传因子、和具体的SimpleAI统一的联系起来,并组织出遗传算法的核心代码。
public class GAPopulationManager { private static GAPopulationManager mGAPoputionManager; public static GAPopulationManager getInstance() { if (mGAPoputionManager == null) mGAPoputionManager = new GAPopulationManager (); return mGAPoputionManager; } public void Add(GAPopulation pGAPopulation) { mGAPopulationSet [mCount] = pGAPopulation; mGAPopulationThreadSet [mCount] = new Thread (ThreadDo); mCount++; } public void Init() { mGAPopulationSet = new GAPopulation[100]; mGAPopulationThreadSet = new Thread[100]; } public void Start() { for (int i = 0; i < mCount; i++) { mGAPopulationThreadSet [i].Start (mGAPopulationSet[i]); } } private void ThreadDo(object pGAPopulation) { GAPopulation tGAPopulation = (GAPopulation)pGAPopulation; while (true) { Thread.Sleep (50); tGAPopulation.mBreedTimer += 0.05f; if (tGAPopulation.mBreedTimer >= tGAPopulation.mBreedCycle) { tGAPopulation.Generate (); tGAPopulation.mBreedTimer = 0.0f; } } } private GAPopulation[] mGAPopulationSet; private Thread[] mGAPopulationThreadSet; public int mCount = 0; }种群管理类将种群记录在数组里,并一一和线程关联,在游戏初始化时,把所有的线程打开。