【发布时间】:2017-04-24 03:41:16
【问题描述】:
我在理解遗传算法的过程时遇到了问题。我找到了在一个区间内最大化函数的例子,我想我理解它们,但是如何使用遗传算法来求解例如二次方程?
假设我们要找到最多 4 位数字的解决方案,那么对数字进行编码的正确表示形式是什么?什么可以作为适应度函数来评估每个数字?
感谢任何帮助
【问题讨论】:
标签: algorithm genetic-algorithm quadratic fitness
我在理解遗传算法的过程时遇到了问题。我找到了在一个区间内最大化函数的例子,我想我理解它们,但是如何使用遗传算法来求解例如二次方程?
假设我们要找到最多 4 位数字的解决方案,那么对数字进行编码的正确表示形式是什么?什么可以作为适应度函数来评估每个数字?
感谢任何帮助
【问题讨论】:
标签: algorithm genetic-algorithm quadratic fitness
如果你想解一个二次方程
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));
}
如果有人可以改进,我相信有请分享。
【讨论】: