遗传算法健身分数问题
Genetic Algorithm Fitness Score Issue
我正在尝试编写一个 java 程序,该程序生成大量随机字符并最终落在输入的字符串上以模拟类似于无限猴子定理 (https://en.wikipedia.org/wiki/Infinite_monkey_theorem) 的东西。我遇到的问题是,在我测试它时,所有初始种群的健康水平都为 0,因此在自然选择过程中没有任何东西被添加到交配池中。这是项目的内容。
目标:字符串"Hello"
变异率:0.01
人口最大值: 100 个 DNA 对象,每个对象包含一个 char[] 基因数组。
这是我计算适应度的函数:
public void calcFitness(String target){
double score = 0.0;
for(int i = 0; i < this.genes.length; i++){
if(this.genes[i] == target.charAt(i)){
score++;
}
}
this.fitness = score/this.genes.length;
}
我是遗传编程的新手,不确定我做错了什么,任何帮助将不胜感激,任何有关遗传编程的提示或见解也将不胜感激。
编辑
这里是选择过程的代码:
public void naturalSelection(){
ArrayList<DNA> selection = new ArrayList<>();
Random rand = new Random();
String child = "";
DNA[] newPop = new DNA[popMax];
for(int i = 0; i < population.length; i++){
for(int j = 0; j < population[i].getFitness(); j++){
selection.add(population[i]);
}
}
for(int i = 0; i < selection.size(); i++){
int parentSelect = rand.nextInt(selection.size());
DNA parent1 = selection.get(parentSelect);
child = parent1.split(true);
parentSelect = rand.nextInt(selection.size());
DNA parent2 = selection.get(parentSelect);
child += parent2.split(false);
newPop[i] = new DNA(child);
}
double mutation = rand.nextDouble();
if(mutation < this.mutationRate){
this.population = swapMutation(newPop);
calcFittest();
}
else{
this.population = newPop;
calcFittest();
}
}
如果发生突变,swap mutation 会交换两个随机字符。
我建议使用适应度函数来测量从候选字符串到目标字符串的距离。然后,您将最小化整体适应度而不是最大化。
为此:
public void calcFitness(String target){
double score = 0.0;
for(int i = 0; i < this.genes.length; i++){
score += Math.abs((int)this.genes[i] - (int)target.charAt(i));
}
this.fitness = score / this.genes.length;
}
这应该会更好,因为它会更好地区分每个候选人。在没有看到您正在使用的随机字符串生成器的情况下很难说,但可能的候选者数量很可能是天文数字,而且他们中的任何一个通过您的适应度函数获得单点的可能性很小。
可能还值得指出的是,您的代码可能是遗传算法的一部分,而不是遗传编程。
如果您想改进 selection,我建议您将锦标赛选择作为一种易于编程的技术 - 从人群中随机选择 n 个个体,然后 select 从 n 个中选择最适合的个体个人。这让更好的候选人比其他人更有机会 selected 并且有额外的好处,你不需要计算人口中每个人的适应度。
我刚刚完成了无限猴子定理的 GA。您可以在 https://github.com/Willtl/infinite_monkey_theorem
找到
它是在 C++ 中,但在 Java 中做同样的事情并不困难。您可以使用 Eclipse CPP 打开项目。
void Individual::calculateFitness(vector<char> chromosomePlate) {
fitness = 0;
for (int i = 0; i < chromosome.size(); i++) {
int gene = (int) chromosome[i];
int genePlate = (int) chromosomePlate[i];
if (gene == genePlate && gene != 32) {
fitness++;
}
}
首先,当我读取输入时,我将其设为小写。然后为了便于随机化和比较,我使用了 ASCII。因此,由于我只考虑小写字母,我的字符范围从 97 到 122。我还在染色体上保留了空格,但是在适应度函数中我忽略了它 (32)。
任何你需要的 post 在这里,我将非常乐意提供帮助。
我正在尝试编写一个 java 程序,该程序生成大量随机字符并最终落在输入的字符串上以模拟类似于无限猴子定理 (https://en.wikipedia.org/wiki/Infinite_monkey_theorem) 的东西。我遇到的问题是,在我测试它时,所有初始种群的健康水平都为 0,因此在自然选择过程中没有任何东西被添加到交配池中。这是项目的内容。
目标:字符串"Hello"
变异率:0.01
人口最大值: 100 个 DNA 对象,每个对象包含一个 char[] 基因数组。
这是我计算适应度的函数:
public void calcFitness(String target){
double score = 0.0;
for(int i = 0; i < this.genes.length; i++){
if(this.genes[i] == target.charAt(i)){
score++;
}
}
this.fitness = score/this.genes.length;
}
我是遗传编程的新手,不确定我做错了什么,任何帮助将不胜感激,任何有关遗传编程的提示或见解也将不胜感激。
编辑
这里是选择过程的代码:
public void naturalSelection(){
ArrayList<DNA> selection = new ArrayList<>();
Random rand = new Random();
String child = "";
DNA[] newPop = new DNA[popMax];
for(int i = 0; i < population.length; i++){
for(int j = 0; j < population[i].getFitness(); j++){
selection.add(population[i]);
}
}
for(int i = 0; i < selection.size(); i++){
int parentSelect = rand.nextInt(selection.size());
DNA parent1 = selection.get(parentSelect);
child = parent1.split(true);
parentSelect = rand.nextInt(selection.size());
DNA parent2 = selection.get(parentSelect);
child += parent2.split(false);
newPop[i] = new DNA(child);
}
double mutation = rand.nextDouble();
if(mutation < this.mutationRate){
this.population = swapMutation(newPop);
calcFittest();
}
else{
this.population = newPop;
calcFittest();
}
}
如果发生突变,swap mutation 会交换两个随机字符。
我建议使用适应度函数来测量从候选字符串到目标字符串的距离。然后,您将最小化整体适应度而不是最大化。
为此:
public void calcFitness(String target){
double score = 0.0;
for(int i = 0; i < this.genes.length; i++){
score += Math.abs((int)this.genes[i] - (int)target.charAt(i));
}
this.fitness = score / this.genes.length;
}
这应该会更好,因为它会更好地区分每个候选人。在没有看到您正在使用的随机字符串生成器的情况下很难说,但可能的候选者数量很可能是天文数字,而且他们中的任何一个通过您的适应度函数获得单点的可能性很小。
可能还值得指出的是,您的代码可能是遗传算法的一部分,而不是遗传编程。
如果您想改进 selection,我建议您将锦标赛选择作为一种易于编程的技术 - 从人群中随机选择 n 个个体,然后 select 从 n 个中选择最适合的个体个人。这让更好的候选人比其他人更有机会 selected 并且有额外的好处,你不需要计算人口中每个人的适应度。
我刚刚完成了无限猴子定理的 GA。您可以在 https://github.com/Willtl/infinite_monkey_theorem
找到它是在 C++ 中,但在 Java 中做同样的事情并不困难。您可以使用 Eclipse CPP 打开项目。
void Individual::calculateFitness(vector<char> chromosomePlate) {
fitness = 0;
for (int i = 0; i < chromosome.size(); i++) {
int gene = (int) chromosome[i];
int genePlate = (int) chromosomePlate[i];
if (gene == genePlate && gene != 32) {
fitness++;
}
}
首先,当我读取输入时,我将其设为小写。然后为了便于随机化和比较,我使用了 ASCII。因此,由于我只考虑小写字母,我的字符范围从 97 到 122。我还在染色体上保留了空格,但是在适应度函数中我忽略了它 (32)。
任何你需要的 post 在这里,我将非常乐意提供帮助。