我目前正试图让我的遗传算法“生成”或“演化”到一个给定的单词 . 问题是,它永远不会完全达到这个词,它会停留在一个太高的 Health 分数,即使它应该继续变异 .
下面是一个例子:
用户输入=“HelloWorld”500代后=“XelgoWorfd”
我不知道为什么它不会继续变异 . 通常它应该随着字符串中的一些字符随机改变而恢复 .
所以我会很乐意提供一些帮助 .
这是一个基本的逐步说明:
-
使用完全随机化的字符串创建20个染色体
-
计算与目标词相比的 Health 分数 . (计算Ascii ID差异)
-
将两个染色体配对得分最高 .
-
随机改变一些染色体(改变随机字符串字符)
-
杀死90%的弱人群并用精英染色体取代它(具有当前最佳 Health 评分的染色体) .
-
重复一切 .
所以这里是我算法中最重要的方法:
public Chromoson[] mate(string gene) {
Console.WriteLine("[MATING] In Progress : "+gens+" "+gene);
int pivot = (int)Math.Round((double)gens.Length / 2) - 1;
string child1 = this.gens.Substring(0, pivot) + gene.Substring(pivot);
string child2 = gene.Substring(0, pivot) + this.gens.Substring(pivot);
Chromoson[] list = new Chromoson[2];
list[0] = new Chromoson(child1);
list[1] = new Chromoson(child2);
Console.WriteLine("[MATING] Pivot : "+pivot);
Console.WriteLine("[MATING] Children : "+child1+" "+child2);
return list;
}
public void mutate(float chance, int possiblyChanges) {
if (random.Next(0,101) <= chance) return;
int changes = random.Next(0, possiblyChanges + 1);
//int index = (int) Math.Floor((double)random.Next() * this.gens.Length);
for (int i = 0; i < changes; i++) {
int index = random.Next(0, 13);
StringBuilder builder = new StringBuilder(gens);
int upOrDown = random.Next(0, 101);
if (upOrDown <= 50 && (int)builder[index] > 0 && chars.Contains(Convert.ToChar(builder[index] - 1)))
builder[index] = Convert.ToChar(builder[index] - 1);
else if (upOrDown >= 50 && (int)builder[index] < 127 && chars.Contains(Convert.ToChar(builder[index] + 1)))
builder[index] = Convert.ToChar(builder[index] + 1);
else
mutate(chance, possiblyChanges);
gens = builder.ToString();
}
Console.WriteLine("[MUTATING] In Progress");
}
public void calculateCost(string otherGens)
{
int total = 0;
for (int i = 0; i < gens.Length; i++)
{
total += (((int)gens[i] - (int)otherGens[i]) * ((int)gens[i] - (int)otherGens[i])) * (i*i);
}
Console.WriteLine("[CALCULATING] Costs : " + total);
this.cost = total;
}
2 回答
在你的时间步骤中完全没有东西:
所以改变你的步骤:
不要每轮都创造随机个体 . 这会将您的算法转换为随机搜索 .
你的mutate和calculateCost函数很奇怪 . 特别是,mutate()看起来被设计为陷入局部最小值 . 任何突变上升或下降将比精英更糟糕(它们可能相同,因此交叉不会改变) . 使用不同的mutate:选择一个随机索引并完全更改它 . 同时从cost()中删除i * i .