为什么我的深层数组副本会在 Java 中的 for 循环外更改它的值?

Why does my deep array copy change it's value outside for loop in Java?

我正在创建一个用 Java 编写的遗传算法。变异函数以指定的概率翻转数组中的位。 变异函数不保留数组的变异种群(个体)。

public static void mutation(Individual[] population, Individual[] mutatedOffspring, double mutationRate) {

    // Iterate through gene, randomly select whether
    // or not to change the value of the genome
    //
    System.out.println("\nMUTATION\n");
    Random mutant = new Random();
    Individual[] offspring = new Individual[POPULATION_SIZE];

    System.out.println("mutated offspring array");
    for (int i = 0; i < (population.length); i++) {
        for (int j = 0; j < population[i].gene.length; j++) {
            // flip bits in array at preset probability (0.1)
            if (mutationRate > mutant.nextDouble()) {
                if (population[i].gene[j] == 0) {
                    population[i].gene[j] = 1;
                } else if (population[i].gene[j] == 1) {
                    population[i].gene[j] = 0;
                }
            }
        }
        // Deep copy contents of mutated array into new object array index (Individual)
        fitness(population);
        offspring[i] = new Individual(population[i].gene, population[i].fitness);
        // Print both mutated array and copied array to show successful copy
        System.out.println("offspring " + i + Arrays.toString(population[i].gene) + (population[i].fitness));
        System.out.println("copy:     " + i + Arrays.toString(offspring[i].gene) + (offspring[i].fitness));
    }
    //print same array outside loop of population
    System.out.println("\n");
    for (int i = 0; i < offspring.length; i++) {
        System.out.println("copy:     " + i + Arrays.toString(offspring[i].gene) + (offspring[i].fitness));
    }
    // deep copy outside p of population using .clone
    for (int i = 0; i < offspring.length; i++) {
        mutatedOffspring[i] = offspring[i].clone();
    }

    fitness(mutatedOffspring);
    System.out.println("\n");
    System.out.println("deep copied array using .clone() outside loop");

    for (int i = 0; i < mutatedOffspring.length; i++) {
        System.out.println("offspring " + i + Arrays.toString(mutatedOffspring[i].gene) + (mutatedOffspring[i].fitness));
    }
}

GA第一次迭代后,变异函数returns一个个体的种群,都是种群中最后一个个体的副本,而不是所有不同的 'mutated' 个人。 (数组末尾的适应度值尚未计算)。

第一次迭代

在人口循环内复制:

offspring 0[0, 0, 1, 0, 1, 1, 0, 0, 0, 1]4
copy:     0[0, 0, 1, 0, 1, 1, 0, 0, 0, 1]4
offspring 1[1, 0, 1, 0, 0, 0, 0, 0, 0, 1]3
copy:     1[1, 0, 1, 0, 0, 0, 0, 0, 0, 1]3
offspring 2[1, 1, 1, 1, 0, 0, 1, 1, 0, 0]6
copy:     2[1, 1, 1, 1, 0, 0, 1, 1, 0, 0]6
offspring 3[1, 1, 1, 1, 1, 0, 1, 1, 1, 0]8
copy:     3[1, 1, 1, 1, 1, 0, 1, 1, 1, 0]8
offspring 4[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]7
copy:     4[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]7
offspring 5[0, 0, 1, 0, 1, 1, 0, 1, 0, 1]5
copy:     5[0, 0, 1, 0, 1, 1, 0, 1, 0, 1]5

人口循环外的相同复制数组:

copy:     0[0, 0, 1, 0, 1, 1, 0, 1, 0, 1]4
copy:     1[1, 0, 1, 0, 0, 0, 0, 0, 0, 1]3
copy:     2[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]6
copy:     3[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]8
copy:     4[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]7
copy:     5[0, 0, 1, 0, 1, 1, 0, 1, 0, 1]5

在循环外使用 .clone() 进行深度复制

offspring 0[0, 0, 1, 0, 1, 1, 0, 1, 0, 1]5
offspring 1[1, 0, 1, 0, 0, 0, 0, 0, 0, 1]3
offspring 2[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]7
offspring 3[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]7
offspring 4[0, 1, 1, 0, 0, 1, 1, 1, 1, 1]7
offspring 5[0, 0, 1, 0, 1, 1, 0, 1, 0, 1]5

第二次迭代

在人口循环内复制:

offspring 0[0, 1, 0, 0, 1, 1, 0, 0, 0, 1]4
copy:     0[0, 1, 0, 0, 1, 1, 0, 0, 0, 1]4
offspring 1[0, 1, 0, 0, 1, 1, 1, 1, 0, 0]5
copy:     1[0, 1, 0, 0, 1, 1, 1, 1, 0, 0]5
offspring 2[0, 0, 0, 0, 1, 1, 0, 1, 0, 0]3
copy:     2[0, 0, 0, 0, 1, 1, 0, 1, 0, 0]3
offspring 3[1, 1, 0, 1, 0, 0, 0, 1, 1, 0]5
copy:     3[1, 1, 0, 1, 0, 0, 0, 1, 1, 0]5
offspring 4[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
copy:     4[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
offspring 5[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
copy:     5[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4

人口循环外的相同复制数组:

copy:     0[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
copy:     1[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]5
copy:     2[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]3
copy:     3[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]5
copy:     4[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
copy:     5[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4

在循环外使用 .clone() 进行深度复制

offspring 0[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
offspring 1[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
offspring 2[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
offspring 3[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
offspring 4[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4
offspring 5[0, 1, 0, 1, 0, 0, 0, 1, 1, 0]4

我确定我正在通过创建一个新个体并为其分配我希望在每次迭代后复制到它的个体的值来进行深度复制。 我还尝试在 Individual class.

中创建一个 clone() 函数
public Individual clone(){
    Individual individual = new Individual(gene, fitness);
    individual.gene = gene;
    individual.fitness = fitness;
    return individual;
}

这两种方法都会产生相同个体(或数组)的群体,无论是在循环内还是在循环外,它们都是突变群体中最后一个个体的副本。 在示例中,要复制的最后两个数组是相同的,但我向您保证生成的后代/变异后代数组都是最后一个数组的副本。

我想为 GA 工作保留变异数组的数量。

首先。我认为您没有正确解释 GA 基础知识。你是在整个人口中,然后 "mutating" 数组的每个元素都有 10% 的概率吗? 如果是这样的话,你几乎是人口中的每一个元素都发生了突变。这似乎不正确。您应该将此百分比应用于 select 只有 10% 的人口参与每一代的突变。

除此之外,我认为你的问题是你没有制作基因组的硬拷贝。

Individual individual = new Individual(gene, fitness);
individual.gene = gene;

当你做 individual.gene = 基因;你实际上是在将这个新个体指向 "parent" 的基因组。是一个类似于问题的问题。