gpt4 book ai didi

java - 需要帮助查明 Java 遗传算法单点交叉机制中的问题

转载 作者:行者123 更新时间:2023-12-01 14:29:01 25 4
gpt4 key购买 nike

我一直在使用 Java 实现一个简单的遗传算法 (GA)。我的 GA 的步骤基本上是二进制编码、锦标赛选择、单点交叉和逐位变异。种群中的每个个体都由一个由二进制基因和适应度值组成的类表示。

public class Individual {
int gene[];
int fitness;

public Individual(int n){
this.gene = new int[n];
}
}

下面的代码不包括按位变异部分,因为我在 GA 的单点交叉部分一直面临问题。我实现单点交叉算法的方法是随机为两个连续的单个数组元素找到一个点,然后交换它们的尾部。然后对每对个体重复尾部交换。我还创建了 printGenome() 方法来打印出所有要比较的数组,交叉过程后的结果数组没有正确交换。我单独测试了我的单点交叉算法,它有效。但是,当我尝试在下面的代码中运行它时,交叉根本不起作用。我可以知道这是因为锦标赛选择算法有问题吗?还是其他原因(愚蠢的错误)?我一直在对其进行修改,但仍然无法查明错误。

如能提供任何帮助和信息,我将不胜感激! :)

public class GeneticAlgorithm {

public static void main(String[] args) {
int p = 10;
int n = 10;
Individual population[];

//create new population
population = new Individual[p];

for (int i = 0; i < p; i++) {
population[i] = new Individual(n);
}

//fills individual's gene with binary randomly
for (int i = 0; i < p; i++) {
for (int j = 0; j < n; j++) {
population[i].gene[j] = (Math.random() < 0.5) ? 0 : 1;
}
population[i].fitness = 0;
}

//evaluate each individual
for (int i = 0; i < p; i++) {
for (int j = 0; j < n; j++) {
if (population[i].gene[j] == 1) {
population[i].fitness++;
}
}
}

//total fitness check
System.out.println("Total fitness check #1 before tournament selection: " + getTotalFitness(population, p));
System.out.println("Mean fitness check #1 before tournament selection: " + getMeanFitness(population, p));
System.out.println("");

//tournament selection
Individual offspring[] = new Individual[p];

for (int i = 0; i < p; i++) {
offspring[i] = new Individual(n);
}

int parent1, parent2;
Random rand = new Random();
for (int i = 0; i < p; i++) {
parent1 = rand.nextInt(p); //randomly choose parent
parent2 = rand.nextInt(p); //randomly choose parent

if (population[parent1].fitness >= population[parent2].fitness) {
offspring[i] = population[parent1];
} else {
offspring[i] = population[parent2];
}
}

//total fitness check
System.out.println("Total fitness check #2 after tournament selection: " + getTotalFitness(offspring, p));
System.out.println("Mean fitness check #2 after tournament selection: " + getMeanFitness(offspring, p));
System.out.println("");

//genome check
System.out.println("Before Crossover: ");
printGenome(offspring, p, n);

//crossover
for (int i = 0; i < p; i = i + 2) {
int splitPoint = rand.nextInt(n);
for (int j = splitPoint; j < n; j++) {
int temp = offspring[i].gene[j];
offspring[i].gene[j] = offspring[i + 1].gene[j];
offspring[i + 1].gene[j] = temp;
}
}

//genome check
System.out.println("After Crossover:");
printGenome(offspring, p, n);

//evaluate each individual by counting the number of 1s after crossover
for (int i = 0; i < p; i++) {
offspring[i].fitness = 0;
for (int j = 0; j < n; j++) {
if (offspring[i].gene[j] == 1) {
offspring[i].fitness++;
}
}
}

//total fitness check
System.out.println("Total fitness check #3 after crossover: " + getTotalFitness(offspring, p));
System.out.println("Mean fitness check #3 after crossover: " + getMeanFitness(offspring, p));
}

public static void printGenome(Individual pop[], int p, int n) {
for (int i = 0; i < p; i++) {
for (int j = 0; j < n; j++) {
System.out.print(pop[i].gene[j]);
}
System.out.println("");
}
}

public static int getTotalFitness(Individual pop[], int p) {
int totalFitness = 0;
for (int i = 0; i < p; i++) {
totalFitness = totalFitness + pop[i].fitness;
}
return totalFitness;
}

public static double getMeanFitness(Individual pop[], int p) {
double meanFitness = getTotalFitness(pop, p) / (double) p;
return meanFitness;
}

}

最佳答案

问题是,在您的选择中,当您说:

offspring[i] = population[parent1]

您实际上是在 offspring[i] 中存储对 population[parent1] 的引用。因此,您的后代数组可以多次包含相同的引用,因此同一个对象将与多个合作伙伴多次参与交叉。

作为解决方案,您可以存储一个克隆而不是对同一对象的引用。在个人中添加:

    public Individual clone(){
Individual clone = new Individual(gene.length);
clone.gene = gene.clone();
return clone;
}

在您的选择中(注意添加的 .clone()):

    for (int i = 0; i < p; i++) {
parent1 = rand.nextInt(p); //randomly choose parent
parent2 = rand.nextInt(p); //randomly choose parent

if (population[parent1].fitness >= population[parent2].fitness) {
offspring[i] = population[parent1].clone();
} else {
offspring[i] = population[parent2].clone();
}
}

这样后代中的每个元素都是不同的对象,即使基因组相同也是如此。

这解决了 Java 部分。关于 GA 理论,我希望有些东西,例如你的健身指标只是占位符,对吧?

关于java - 需要帮助查明 Java 遗传算法单点交叉机制中的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39906861/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com