如何在Java中实现遗传算法的高斯变异算子

我尝试为我的项目学习并实现一个简单的遗传算法库。 此时,人口的进化,选择已经准备就绪,我正在尝试为Java和Scala中的遗传进化引擎实现一个简单的好变异算子,如高斯变异算子 (GMO)。

我在基于多目标进化算法的Pareto排名 (PM Mateo,I。Alberto),第6页和第7页的论文A变异算子中找到了关于高斯变异算子(GMO)的一些信息。

但我有一些问题需要找到有关如何在Java中实现此高斯变异算子和此运算符的其他有用变体的其他信息。 我该怎么办?

我正在使用随机Java util的random.nextGaussian()函数,但此方法仅返回0到1之间的随机数。

所以,

a)在这种情况下,如何修改返回编号的精度? (例如,我想获得一个介于0和1之间的随机双数,步长等于0.00001。)

b)我如何为这个函数指定musigma ,因为我想在本地搜索我的基因组的值,而不是在-1和1之间。我怎样才能调整我的基因组价值的本地研究?

经过研究,我找到了b)问题的答案。 似乎我可以取代高斯随机数,如下所示:

  newGenomeValue = oldGenomeValue + (( gaussiandRndNumber * sigma ) + mean ) 

其中mean =我的基因组值。

(参见底部的方法如何生成具有正态或高斯分布的随机数? )

要回答问题a,您所要做的就是四舍五入到最接近的0.00001以获得这些单位的答案。 例如:

  step = 0.00001; quantized_x = step * Math.rint(x / step); 

现在对于b部分,你有正确的想法,你提出的代码应该工作。 您需要做的就是将变量重新调整到所需范围。 我唯一可以补充的是,它起作用的根本原因是微积分变量定理的变化: http : //en.wikipedia.org/wiki/Integration_by_substitution

如果你在高斯分布的情况下计算出这个公式,其中0均值和标准偏差1通过线性移位和重新缩放进行转换,那么你会看到你写出的内容确实是正确的。

总而言之,这里有一些代码可以解决这个问题:

 double next_gaussian() { double x = rng.nextGaussian(); //Use whichever method you like //here to generate an initial [-1,1] gaussian distribution y = (x * 0.5) + 0.5; //Rescale to [0,1] return Math.rint(y * 100000.0) * 0.00001; //Quantize to step size 0.00001 } 

我强烈建议不要使用Java的随机数生成器。 它使用线性同余生成器 ,它具有已知的局限性:

如果需要更高质量的随机数,并且有足够的存储空间(~2千字节),那么梅森捻线机算法可以提供更长的周期(219937-1)和变化均匀性。[9] Mersenne twister比几乎任何LCG产生更高质量的偏差。[引证需要]一个常见的Mersenne扭转器实现,有趣的是,使用LCG生成种子数据。*(来自维基百科)

因此,我建议你考虑梅森捻线机的实施。 特别是,我正在使用ECJ的实现,它也具有生成高斯数的能力。

如果您需要与Java的Random接口兼容,请使用http://code.google.com/p/ecj/source/browse/trunk/ecj/ec/util/MersenneTwister.java 。

http://code.google.com/p/ecj/source/browse/trunk/ecj/ec/util/MersenneTwisterFast.java更快,但它没有实现Random接口。

要更改数字的“精确度”,请执行以下操作:

 ((int)(100*rand))/100.0 

这会将变量rand四舍五入到小数点后两位。 当然,您必须小心小浮点舍入错误,因此它不一定是准确的。

至于实施转基因生物,该论文描述了如何非常精确地做到这一点。 我不确定如何更清楚地解释它。 我假设你的代码中有一个x和一个sigma ,你只需使用所描述的数学运算对其进行转换。

以下是如何生成0到n之间的随机数:

 public static double random(int n) { return Math.random() * n; } 

如果你需要一个整数,把它intint但是加一个到n,即(int)random(n + 1)