人口变得陈旧 - 遗传算法

Population becomes stale - Genetic Algorithm

我正在构建一个简单的 "Hello, World!" 遗传算法用于学习目的。我的人口是一组随机字符串。通过突变和交叉,字符串演化为 "Hello, World!"。出于某种原因,我的人口将处于一个健康分数并且似乎永远不会进化。其他时候,我的人口将达到目标基因,"Hello, World"。我正在使用随机选择和一点交叉。虽然,当我使用锦标赛和轮盘选择时也会发生这种情况。

问题:
为什么我的种群变得陈旧并且没有达到目标基因,即使我通过突变使种群多样化?是因为遗传算法的随机性还是我的代码有误?

例如
种群中的每条染色体最终都会有基因"HellV, Wor`dL"。即使在 10,000 代之后,基因也是相同的。其他时候,基因在 ~33 代后到达目标基因 "Hello, World!"。

人口规模:333
精英主义:正确
精英主义百分比:25%
突变概率:20%
交叉概率:95%
选择类型:随机
交叉类型:一点

编辑: 我已经从这个 post 中删除了代码,而是在我的 github 中添加了一个 link,因为它有几百行代码。

Genetic Algorithm - C++

感谢@molbdnilo 的评论,我得以解决我的问题。

事实证明这是因为 C++ 复制对象的方式,这解释了为什么这段代码在 Java 而不是 C++ 中有效。

如@molbdnilo所述:

One of the most common problems when moving from Java to C++ is how C++ copies objects in places where Java passes around a reference.

为了解决我的问题,我更改了以下方法声明:

1. int calculateFitness(GAChromosome chromosome); ---> int calculateFitness(GAChromosome const &chromosome);
在这个方法声明中,我告诉编译器我想通过引用而不是通过值传递染色体,使用 &,并使用 const 使它成为常量。这样做可以防止染色体被复制和改变。

2. void mutate(GAChromosome chromosome); ---> void mutate(GAChromosome &chromosome);
在这个方法声明中,我告诉编译器我想通过引用而不是通过值来传递染色体,使用&。这样做可以防止染色体被复制。由于前面的方法声明没有指定染色体是通过引用传递的,因此正在制作、更改副本,然后在方法到达范围末尾后将其丢弃。最终,从未进行过更改。

3. std::pair<GAChromosome, GAChromosome> onePointCrossover(GAChromosome chromosomeA, GAChromosome chromosomeB); ---> std::pair<GAChromosome, GAChromosome> onePointCrossover(GAChromosome const &chromosomeA, GAChromosome const &chromosomeB);
在这个方法声明中,我告诉编译器我想通过引用而不是通过值传递染色体,使用 &,并使用 const 使它成为常量。这样做可以防止染色体被复制和改变。

总之,问题出在将染色体传递给 mutate 方法的方式上。染色体是按值传递而不是按引用传递,导致复制染色体并在 mutate 方法到达范围末尾时丢弃更改。