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

遗传算法中高斯变异算子的Java实现,java,random,artificial-intelligence,genetic-algorithm,gaussian,Java,Random,Artificial Intelligence,Genetic Algorithm,Gaussian,我试图为我的项目学习并实现一个简单的遗传算法库。现在,进化,种群选择已经准备好了,我正试图在Java和Scala中为我的遗传进化引擎实现一个简单好的变异算子,比如(GMO) 我在论文(p.M.Mateo,I.Alberto)第6页和第7页找到了一些关于高斯变异算子(GMO)的信息 但是我有一些问题需要找到关于如何在Java中实现这个高斯变异算子和这个算子的其他有用变体的其他信息。我该怎么办 我正在使用random Java util的random.nextGaussian()函数,但是这个方法只

我试图为我的项目学习并实现一个简单的遗传算法库。现在,进化,种群选择已经准备好了,我正试图在Java和Scala中为我的遗传进化引擎实现一个简单好的变异算子,比如(GMO)

我在论文(p.M.Mateo,I.Alberto)第6页和第7页找到了一些关于高斯变异算子(GMO)的信息

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

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

所以

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

b) 我如何为这个函数指定
mu
sigma
,因为我想在局部搜索我基因组的值,而不是-1和1之间的值。我怎样才能让当地的研究围绕我的基因组价值进行呢

经过研究,我找到了这个问题的答案。我似乎可以这样替换高斯随机数:

 newGenomeValue = oldGenomeValue + (( gaussiandRndNumber * sigma ) + mean )
其中
表示
=我的基因组值


(请参阅中的底页方法。)

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

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

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

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

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

因此,我建议你考虑一个梅森扭曲器的实现。特别是,我正在使用ECJ的实现,它还能够生成高斯数

如果您需要与Java的随机接口兼容,请使用

速度更快,但不实现随机接口。

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

((int)(100*rand))/100.0
这将把变量
rand
四舍五入到小数点后2位。当然,您必须小心小的浮点舍入错误,这样它就不一定是精确的


至于实施转基因,本文非常精确地描述了如何做到这一点。我不知道怎样才能解释得更清楚。我假设你的代码中有一个
x
和一个
sigma
,你只需使用所描述的数学运算对它进行变换。

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

  step = 0.00001;
  quantized_x = step * Math.rint(x / step);
现在,对于第二部分,您有了正确的想法,并且您提供的代码应该可以工作。您所需要做的就是将变量重新缩放到所需的范围。我唯一能补充的是,这项工作的根本原因是微积分的变量变化定理:

如果你在高斯分布的情况下计算出这个公式,平均值为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
}

你所说的“返回数字的精度”到底是什么意思?逗号后的数字:你想以什么方式“修改”逗号后的数字
nextGaussian
为您提供了一个
double
。你是说这还不足以满足你的需要吗?我在模拟中用这个数字来校准概率定律。我需要一个介于0,01和0.00000001之间的数字,所以如果我在coma之后添加一个只有一个数字精度的double(例如0.11111 0.255525 0.114182等),这是有问题的,因为我需要添加这样的随机数:0.001、0.001252、0000352等。您的注释实际上包含了您需要的所有内容。那篇论文中的z,z_k,z_k'都是0-均值,stddev 1随机变量(就像你从nextGaussian()中得到的那样),你只需要用与论文中相同的方式对它们进行缩放(即x_k的均值,x_k和exp(tau'z+tauz_k)的sigma_k的stddev)对于sigma的乘法更新。我忘了说…nextGaussian从正态分布返回一个样本。因为你想改变均值和方差,你应该应用你在评论中提到的标准变换。有关更多信息,请参阅Thx以获得帮助,我使用的是SSJ中lecuyer的随机生成器library和math.commons(apache基金会)一样。关于在随机双精度中生成更多的小变化,我没有答案:/实际上,我正在使用1和1E6之间的随机(int)来除以随机(double)。。。