我在理解遗传算法的过程时遇到了问题。我找到了在一个区间内最大化函数的例子,我想我理解它们,但是如何使用遗传算法来求解例如二次方程?
假设我们想找到一个最多 4 位的解决方案,那么对数字进行编码的正确表示是什么?什么可以用作评估每个数字的适应度函数?
任何帮助表示赞赏
我在理解遗传算法的过程时遇到了问题。我找到了在一个区间内最大化函数的例子,我想我理解它们,但是如何使用遗传算法来求解例如二次方程?
假设我们想找到一个最多 4 位的解决方案,那么对数字进行编码的正确表示是什么?什么可以用作评估每个数字的适应度函数?
任何帮助表示赞赏
如果你想解一个二次方程
a * x^2 + b * x + c = 0
那么您只需要一个变量x
作为表示。您可以使用
f(x) = abs(a * x^2 + b * x + c)
作为适应度函数,与那时的精度相同,因此需要最小化。
但是只有一个变量很难进行交叉,您可以每个人使用 10 个数字,然后取平均值得到 x,或者在进行交叉时只取两个数字的平均值。同样对于突变而不是完全覆盖 x,您可以将其乘以 0.5 到 2 之间的随机数,例如。
第一步是选择解决方案的表示。最广泛使用的是二进制编码。例如,您的 x 可能看起来:
1 0 0 1 1 1 1 0 | 0 0 0 0 0 0 0 0 0 0 1 1 1
前 8 位编码数字的整数部分,剩余的 13 位编码点后数字的一部分。在此示例中,二进制字符串编码一个数字 158.0007。
交叉可能看起来
1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 - 158.0007
1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 - 225.0008
最简单的交叉算子是一个分界点。您从 1 到字符串长度生成一个数字 - 1。到此为止,您从一个字符串中获取一个位,然后从第二个字符串中获取该位。在本例中,我们选择分割点 4 的位置。后代将如下所示:
1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 - 145.0008
突变随着选择的概率而改变一些位。
适应度函数可能是 x 中的二次方程的函数值(如果您尝试找到最大值),并且 x 是作为比特字符串的解码获得的。
最后还有一些理论。你有两套。一组是搜索空间(带有二进制字符串的空间),第二组是带有解决方案的空间。来自搜索空间的个体被解码为解决方案空间中的解决方案(在我们的例子中,x 的值由二进制字符串编码)。搜索空间代表基因型,解码的解决方案是表型。遗传学算子使用解码解决方案处理搜索空间个体(在这种情况下为二进制字符串)和适应度函数。
我有一个可以解方程:
a(x1*x1+x2*x2)+b(x1+x2)+2*c = 0
这是加法:
ax1x1+bx1+c=0
并且ax2x2+bx2+c=0
由于 x1 和 x2 都是方程的解,所以可以进行加法。代码为 aa=1、bb=-1 和 cc=-30 提供以下输出:
best solutions at generation 0 :: fitness = 1
chromosome 13 : x1 = -5 , x2 = 6
chromosome 269 : x1 = 6 , x2 = 6
chromosome 340 : x1 = 6 , x2 = -5
chromosome 440 : x1 = -5 , x2 = 6
chromosome 452 : x1 = 6 , x2 = -5
chromosome 549 : x1 = -5 , x2 = -5
chromosome 550 : x1 = 6 , x2 = -5
chromosome 603 : x1 = -5 , x2 = -5
chromosome 826 : x1 = 6 , x2 = -5
chromosome 827 : x1 = -5 , x2 = 6
chromosome 842 : x1 = -5 , x2 = -5
chromosome 952 : x1 = 6 , x2 = 6
chromosome 986 : x1 = 6 , x2 = -5
也就是说,我相信一个好的开始,我只是还不知道如何从不太好的解决方案中筛选出好的。
这是部分代码:
void objective(Chromosome* c){
// the problem here is when one root is found the fitness
// will be 1 :
// resulting in the second value is a non-root or the same
// value as the first root
//so probably I need to rewrite the fitness function
c->result = aa * ((c->gene[0].geneticcode * c->gene[0].geneticcode) + (c->gene[1].geneticcode * c->gene[1].geneticcode)) /
+ bb * (c->gene[0].geneticcode + c->gene[1].geneticcode) /
+ 2 * cc;
}
void fitness(Chromosome* c){
//rewrite of fitness function for this example
c->fitness = 1.0 / (1.0 + fabs(c->result));
}
如果有人可以改进,我相信有请分享。