Почему моя копия глубокого массива меняет свое значение вне цикла for в 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 функция мутации возвращает популяцию индивидуумов, которые все являются копиями последней особи в популяции, а не всех различных «мутировавших» особей. (Значения пригодности в конце массивов не оценивались).

ПЕРВАЯ ИТЕРАЦИЯ

копировать в цикле популяции:

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

2-я ИТЕРАЦИЯ

копировать в цикле популяции:

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

Я уверен, что делаю глубокую копию, создавая нового индивидуума и присваивая ему значения индивидуума, который я хочу скопировать ему после каждой итерации. Я также пробовал создать функцию clone () в классе Individual.

public Individual clone(){
    Individual individual = new Individual(gene, fitness);
    individual.gene = gene;
    individual.fitness = fitness;
    return individual;
}

Оба метода создают популяцию идентичных особей (или массивов), которые являются копией последней особи в мутировавшей популяции, независимо от того, используются ли они внутри цикла или вне его. В этом примере два последних массива для копирования одинаковы, но я уверяю вас, что все полученные массивы потомков / мутировавших потомков являются копией последнего.

Я хочу сохранить популяцию измененных массивов для работы GA.


person Billy Martin    schedule 17.11.2016    source источник
comment
Я должен отметить, что когда я запускал этот метод 100 раз сам по себе в тесте, он работает отлично ...   -  person Billy Martin    schedule 17.11.2016


Ответы (1)


Прежде всего. Я думаю, что вы неправильно интерпретируете основы GA. Вы берете всю совокупность, а затем «мутируете» каждый элемент массива с вероятностью 10%? Если это так, вы мутируете почти каждый элемент популяции. Это не кажется правильным. Вы должны применить этот процент, чтобы выбрать ТОЛЬКО 10% населения, которое будет участвовать в мутации в каждом поколении.

Кроме того, я думаю, ваша проблема в том, что вы не делаете распечатку генома.

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

Когда вы делаете personal.gene = gene; вы фактически указываете этому новому человеку на геном «родителя». Проблема похожа на этот вопрос.

person Enrique Arriaga    schedule 17.11.2016
comment
Спасибо, вот и все, мой клон не создавал каждый геном. Кроме того, да, я думал, что каждый человек в популяции является кандидатом на мутацию в каждом поколении? И да, я изменяю вероятность мутации, и каждый геном потенциально мутирует? Я прочитаю это, еще раз спасибо. - person Billy Martin; 18.11.2016