using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 遗传算法
/// </summary>
public class GeneticAlgorithm
{
private List<Attr> curAttrList=new List<Attr>();
private List<Attr> childAttrList = new List<Attr>();
//传入种群|繁殖进化后再返回出去
public List<Attr> Pushout(List<Attr> Attrs)
{
curAttrList = Attrs;
tempcount = curAttrList.Count;
childAttrList.Clear();
SortAttr();
return ChooseBest();
}
//排序
private void SortAttr()
{
//从小到大排序
curAttrList.Sort((left, right) =>
{
return left.fitness.CompareTo(right.fitness);
});
}
int tempcount;//初始的长度
int splitBest = 0;
//对个体选择
private Attr Choose(List<Attr> attrs)
{
float totalfitness = 0;//总适应度
foreach (var Attr in curAttrList)
{
totalfitness += Attr.fitness;
}
float totalpercent = 0;
float rand = UnityEngine.Random.Range(0f, totalfitness);
foreach (var attr in curAttrList)
{
totalpercent += attr.fitness;
if (totalpercent >= rand)
return attr.Clone();
}
return null;
}
//赌轮盘选择[(优秀基因保留)1/4效果比较好]
private List<Attr> ChooseBest()//
{
while (true)
{
Attr attr1 = Choose(curAttrList);
Attr attr2 = null;
bool boo = true;//是否一样
while (true)
{
attr2 = Choose(curAttrList);
for (int i = 0; i < attr2.neuralNetwork.WeightList.Count; i++)
{
if(attr2.neuralNetwork.WeightList[i]!= attr1.neuralNetwork.WeightList[i])
{
boo = false;
break;
}
}
if (!boo)
break;
}
Attr child1;
Attr child2;
CrossAttr(attr1, attr2, out child1, out child2);
childAttrList.Add(child1);
childAttrList.Add(child2);
if (childAttrList.Count == (int)tempcount*3/4)
break;
if (childAttrList.Count > (int)tempcount * 3 / 4)
{
childAttrList.Remove(child2);
break;
}
}
VariationAttr(childAttrList);//变异
//新生的交叉变异|优秀的保存不动
/************ 交叉变异 *************/
int temp = childAttrList.Count;
for (int i = tempcount-1; i >temp-1 ; i--)//特殊挑选的best也加入新群体
{
childAttrList.Add(curAttrList[i].Clone());
}
return childAttrList;
}
public void Foresh(double[] d)
{
string str = "";
foreach (var item in d)
{
str += item.ToString() + ",";
}
Debug.LogError("权重s:" + str);
}
private List<Attr> crossAttrList;
//交叉
private void CrossAttr(Attr Attr1,Attr Attr2,out Attr child1,out Attr child2)
{
int count = Attr1.neuralNetwork.WeightList.Count;//基因的长度
int index1 = UnityEngine.Random.Range(0, count - 1);
int index2 = UnityEngine.Random.Range(index1, count);
child1 = Attr1.Clone();
child2 = Attr1.Clone();
for (int j = index1; j < index2; j++)
{
double temp = child1.neuralNetwork.WeightList[j];
child1.neuralNetwork.WeightList[j] = child2.neuralNetwork.WeightList[j];//基因片段交换
child2.neuralNetwork.WeightList[j] = temp;//这里已经交叉了
if (child1.neuralNetwork.WeightList.Count == 0)
child1.neuralNetwork.LoadWeight(child1.neuralNetwork.WeightList);
if (child2.neuralNetwork.WeightList.Count == 0)
child2.neuralNetwork.LoadWeight(child2.neuralNetwork.WeightList);
}
}
float variation = 0.2f;//1/50 0.02的概率突变
//变异[突变]
private void VariationAttr(List<Attr> list)//ok
{
for (int i = 0; i < list.Count; i++)
{
float ran = UnityEngine.Random.Range(0, 1f);
if (ran <= variation) //1/50的概率突变基因随一个片段[一部分]位置
{
int count = list[i].neuralNetwork.WeightList.Count;//基因的长度
int index = UnityEngine.Random.Range(0, count);//变异一个片段
list[i].neuralNetwork.WeightList[index] = UnityEngine.Random.Range(-1f, 1f);
if (list[i].neuralNetwork.WeightList.Count == 0)
list[i].neuralNetwork.LoadWeight(list[i].neuralNetwork.WeightList);
}
}
}
}