[FreedomAI]第六周——遗传算法与种群代码实现

本文介绍了在Unity游戏开发中应用遗传算法的实现过程。内容包括个体类的设计,使用Bool数组作为基因编码,float表示适应度,以及评价函数的实现。此外,文章还探讨了遗传算法的选择、重组和变异策略,通过委托进行底层实现。最后,展示了种群类和种群管理者的结构,如何将这些策略与SimpleAI结合,以执行遗传算法的核心逻辑。
摘要由CSDN通过智能技术生成

首先是个体类:

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;
	}
种群管理类将种群记录在数组里,并一一和线程关联,在游戏初始化时,把所有的线程打开。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值