13

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

我在论文A mutation operator based on a Pareto ranking for multi-objective evolutionary algorithms (PM Mateo, I. Alberto) 第 6 页和第 7 页中找到了有关高斯变异算子 (GMO) 的一些信息。

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

我使用的random.nextGaussian()是random Java util的函数,但是这个方法只返回一个0到1之间的随机数。

所以,

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

b)以及如何指定musigma用于此功能,因为我想在本地搜索我的基因组的值,而不是在 -1 和 1 之间。我如何才能围绕我的基因组值调整本地研究?

经过研究,我找到了 b) 问题的答案。看来我可以像这样置换高斯随机数:

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

其中mean= 我的基因组值。

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

4

4 回答 4

5

要回答问题 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
}
于 2011-06-25T18:03:34.183 回答
3

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

如果需要更高质量的随机数,并且有足够的内存可用(约 2 KB),则 Mersenne twister 算法提供更长的周期 (219937-1) 和变化的均匀性。 [9] Mersenne twister 产生的偏差几乎比任何 LCG 都高。[需要引用] 有趣的是,一个常见的 Mersenne twister 实现使用 LCG 来生成种子数据。*(来自 Wikipedia)

因此,我建议您考虑使用 Mersenne twister 实现。特别是,我正在使用 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 接口。

于 2011-06-17T07:53:12.063 回答
-1

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

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

如果您需要一个整数,请将其强制转换为int但在 n 上加一,即(int)random(n + 1)

于 2011-06-13T09:44:13.893 回答
-1

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

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

这会将变量四舍五入rand到小数点后 2 位。当然,你必须小心小的浮点舍入误差,所以它不一定是准确的。

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

于 2011-06-23T17:37:12.347 回答